authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-07-21 20:54:08-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-07-21 20:54:08-04:00
log11bd50f2b2a74ce25d841a15ba67d042d41b71c2
tree8221af0a57e853be09b7dea942ba2f44261f8270
parent78e03c466c6641571adef4bb3931d6cc6f425eb4
signaturelock-open Commit is signed but in an unrecognized format.

implement coroutine resume


5 files changed, 67 insertions(+), 2 deletions(-)

src/all_types.hpp+7
......@@ -2322,6 +2322,7 @@ enum IrInstructionId {
23222322 IrInstructionIdUnionInitNamedField,
23232323 IrInstructionIdSuspendBegin,
23242324 IrInstructionIdSuspendBr,
2325 IrInstructionIdCoroResume,
23252326};
23262327
23272328struct IrInstruction {
......@@ -3548,6 +3549,12 @@ struct IrInstructionSuspendBr {
35483549 IrBasicBlock *resume_block;
35493550};
35503551
3552struct IrInstructionCoroResume {
3553 IrInstruction base;
3554
3555 IrInstruction *frame;
3556};
3557
35513558enum ResultLocId {
35523559 ResultLocIdInvalid,
35533560 ResultLocIdNone,
src/codegen.cpp+14
......@@ -4969,6 +4969,18 @@ static LLVMValueRef ir_render_suspend_br(CodeGen *g, IrExecutable *executable,
49694969 return nullptr;
49704970}
49714971
4972static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable,
4973 IrInstructionCoroResume *instruction)
4974{
4975 LLVMValueRef frame = ir_llvm_value(g, instruction->frame);
4976 ZigType *frame_type = instruction->frame->value.type;
4977 assert(frame_type->id == ZigTypeIdCoroFrame);
4978 ZigFn *fn = frame_type->data.frame.fn;
4979 LLVMValueRef fn_val = fn_llvm_value(g, fn);
4980 LLVMBuildCall(g->builder, fn_val, &frame, 1, "");
4981 return nullptr;
4982}
4983
49724984static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
49734985 AstNode *source_node = instruction->source_node;
49744986 Scope *scope = instruction->scope;
......@@ -5213,6 +5225,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
52135225 return ir_render_suspend_begin(g, executable, (IrInstructionSuspendBegin *)instruction);
52145226 case IrInstructionIdSuspendBr:
52155227 return ir_render_suspend_br(g, executable, (IrInstructionSuspendBr *)instruction);
5228 case IrInstructionIdCoroResume:
5229 return ir_render_coro_resume(g, executable, (IrInstructionCoroResume *)instruction);
52165230 }
52175231 zig_unreachable();
52185232}
src/ir.cpp+34-1
......@@ -1035,6 +1035,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSuspendBr *) {
10351035 return IrInstructionIdSuspendBr;
10361036}
10371037
1038static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroResume *) {
1039 return IrInstructionIdCoroResume;
1040}
1041
10381042template<typename T>
10391043static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
10401044 T *special_instruction = allocate<T>(1);
......@@ -3216,6 +3220,18 @@ static IrInstruction *ir_build_suspend_br(IrBuilder *irb, Scope *scope, AstNode
32163220 return &instruction->base;
32173221}
32183222
3223static IrInstruction *ir_build_coro_resume(IrBuilder *irb, Scope *scope, AstNode *source_node,
3224 IrInstruction *frame)
3225{
3226 IrInstructionCoroResume *instruction = ir_build_instruction<IrInstructionCoroResume>(irb, scope, source_node);
3227 instruction->base.value.type = irb->codegen->builtin_types.entry_void;
3228 instruction->frame = frame;
3229
3230 ir_ref_instruction(frame, irb->current_basic_block);
3231
3232 return &instruction->base;
3233}
3234
32193235static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
32203236 results[ReturnKindUnconditional] = 0;
32213237 results[ReturnKindError] = 0;
......@@ -7675,7 +7691,7 @@ static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node)
76757691 if (target_inst == irb->codegen->invalid_instruction)
76767692 return irb->codegen->invalid_instruction;
76777693
7678 zig_panic("TODO ir_gen_resume");
7694 return ir_build_coro_resume(irb, scope, node, target_inst);
76797695}
76807696
76817697static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
......@@ -24134,6 +24150,20 @@ static IrInstruction *ir_analyze_instruction_suspend_br(IrAnalyze *ira, IrInstru
2413424150 return ir_finish_anal(ira, result);
2413524151}
2413624152
24153static IrInstruction *ir_analyze_instruction_coro_resume(IrAnalyze *ira, IrInstructionCoroResume *instruction) {
24154 IrInstruction *frame = instruction->frame->child;
24155 if (type_is_invalid(frame->value.type))
24156 return ira->codegen->invalid_instruction;
24157
24158 if (frame->value.type->id != ZigTypeIdCoroFrame) {
24159 ir_add_error(ira, instruction->frame,
24160 buf_sprintf("expected frame, found '%s'", buf_ptr(&frame->value.type->name)));
24161 return ira->codegen->invalid_instruction;
24162 }
24163
24164 return ir_build_coro_resume(&ira->new_irb, instruction->base.scope, instruction->base.source_node, frame);
24165}
24166
2413724167static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction *instruction) {
2413824168 switch (instruction->id) {
2413924169 case IrInstructionIdInvalid:
......@@ -24421,6 +24451,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
2442124451 return ir_analyze_instruction_suspend_begin(ira, (IrInstructionSuspendBegin *)instruction);
2442224452 case IrInstructionIdSuspendBr:
2442324453 return ir_analyze_instruction_suspend_br(ira, (IrInstructionSuspendBr *)instruction);
24454 case IrInstructionIdCoroResume:
24455 return ir_analyze_instruction_coro_resume(ira, (IrInstructionCoroResume *)instruction);
2442424456 }
2442524457 zig_unreachable();
2442624458}
......@@ -24555,6 +24587,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2455524587 case IrInstructionIdResetResult:
2455624588 case IrInstructionIdSuspendBegin:
2455724589 case IrInstructionIdSuspendBr:
24590 case IrInstructionIdCoroResume:
2455824591 return true;
2455924592
2456024593 case IrInstructionIdPhi:
src/ir_print.cpp+9
......@@ -1513,6 +1513,12 @@ static void ir_print_suspend_br(IrPrint *irp, IrInstructionSuspendBr *instructio
15131513 fprintf(irp->f, ")");
15141514}
15151515
1516static void ir_print_coro_resume(IrPrint *irp, IrInstructionCoroResume *instruction) {
1517 fprintf(irp->f, "@coroResume(");
1518 ir_print_other_instruction(irp, instruction->frame);
1519 fprintf(irp->f, ")");
1520}
1521
15161522static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
15171523 ir_print_prefix(irp, instruction);
15181524 switch (instruction->id) {
......@@ -1977,6 +1983,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
19771983 case IrInstructionIdSuspendBr:
19781984 ir_print_suspend_br(irp, (IrInstructionSuspendBr *)instruction);
19791985 break;
1986 case IrInstructionIdCoroResume:
1987 ir_print_coro_resume(irp, (IrInstructionCoroResume *)instruction);
1988 break;
19801989 }
19811990 fprintf(irp->f, "\n");
19821991}
test/stage1/behavior/coroutines.zig+3-1
......@@ -4,9 +4,11 @@ const expect = std.testing.expect;
44
55var x: i32 = 1;
66
7test "simple coroutine suspend" {
7test "simple coroutine suspend and resume" {
88 const p = async simpleAsyncFn();
99 expect(x == 2);
10 resume p;
11 expect(x == 3);
1012}
1113fn simpleAsyncFn() void {
1214 x += 1;