implement coroutine resume
This commit is contained in:
parent
78e03c466c
commit
11bd50f2b2
|
@ -2322,6 +2322,7 @@ enum IrInstructionId {
|
|||
IrInstructionIdUnionInitNamedField,
|
||||
IrInstructionIdSuspendBegin,
|
||||
IrInstructionIdSuspendBr,
|
||||
IrInstructionIdCoroResume,
|
||||
};
|
||||
|
||||
struct IrInstruction {
|
||||
|
@ -3548,6 +3549,12 @@ struct IrInstructionSuspendBr {
|
|||
IrBasicBlock *resume_block;
|
||||
};
|
||||
|
||||
struct IrInstructionCoroResume {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *frame;
|
||||
};
|
||||
|
||||
enum ResultLocId {
|
||||
ResultLocIdInvalid,
|
||||
ResultLocIdNone,
|
||||
|
|
|
@ -4969,6 +4969,18 @@ static LLVMValueRef ir_render_suspend_br(CodeGen *g, IrExecutable *executable,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable,
|
||||
IrInstructionCoroResume *instruction)
|
||||
{
|
||||
LLVMValueRef frame = ir_llvm_value(g, instruction->frame);
|
||||
ZigType *frame_type = instruction->frame->value.type;
|
||||
assert(frame_type->id == ZigTypeIdCoroFrame);
|
||||
ZigFn *fn = frame_type->data.frame.fn;
|
||||
LLVMValueRef fn_val = fn_llvm_value(g, fn);
|
||||
LLVMBuildCall(g->builder, fn_val, &frame, 1, "");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
|
||||
AstNode *source_node = instruction->source_node;
|
||||
Scope *scope = instruction->scope;
|
||||
|
@ -5213,6 +5225,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
|
|||
return ir_render_suspend_begin(g, executable, (IrInstructionSuspendBegin *)instruction);
|
||||
case IrInstructionIdSuspendBr:
|
||||
return ir_render_suspend_br(g, executable, (IrInstructionSuspendBr *)instruction);
|
||||
case IrInstructionIdCoroResume:
|
||||
return ir_render_coro_resume(g, executable, (IrInstructionCoroResume *)instruction);
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
|
35
src/ir.cpp
35
src/ir.cpp
|
@ -1035,6 +1035,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSuspendBr *) {
|
|||
return IrInstructionIdSuspendBr;
|
||||
}
|
||||
|
||||
static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroResume *) {
|
||||
return IrInstructionIdCoroResume;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
|
||||
T *special_instruction = allocate<T>(1);
|
||||
|
@ -3216,6 +3220,18 @@ static IrInstruction *ir_build_suspend_br(IrBuilder *irb, Scope *scope, AstNode
|
|||
return &instruction->base;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_coro_resume(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||
IrInstruction *frame)
|
||||
{
|
||||
IrInstructionCoroResume *instruction = ir_build_instruction<IrInstructionCoroResume>(irb, scope, source_node);
|
||||
instruction->base.value.type = irb->codegen->builtin_types.entry_void;
|
||||
instruction->frame = frame;
|
||||
|
||||
ir_ref_instruction(frame, irb->current_basic_block);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
|
||||
static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
|
||||
results[ReturnKindUnconditional] = 0;
|
||||
results[ReturnKindError] = 0;
|
||||
|
@ -7675,7 +7691,7 @@ static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node)
|
|||
if (target_inst == irb->codegen->invalid_instruction)
|
||||
return irb->codegen->invalid_instruction;
|
||||
|
||||
zig_panic("TODO ir_gen_resume");
|
||||
return ir_build_coro_resume(irb, scope, node, target_inst);
|
||||
}
|
||||
|
||||
static 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
|
|||
return ir_finish_anal(ira, result);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_analyze_instruction_coro_resume(IrAnalyze *ira, IrInstructionCoroResume *instruction) {
|
||||
IrInstruction *frame = instruction->frame->child;
|
||||
if (type_is_invalid(frame->value.type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
if (frame->value.type->id != ZigTypeIdCoroFrame) {
|
||||
ir_add_error(ira, instruction->frame,
|
||||
buf_sprintf("expected frame, found '%s'", buf_ptr(&frame->value.type->name)));
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
|
||||
return ir_build_coro_resume(&ira->new_irb, instruction->base.scope, instruction->base.source_node, frame);
|
||||
}
|
||||
|
||||
static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction *instruction) {
|
||||
switch (instruction->id) {
|
||||
case IrInstructionIdInvalid:
|
||||
|
@ -24421,6 +24451,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
|
|||
return ir_analyze_instruction_suspend_begin(ira, (IrInstructionSuspendBegin *)instruction);
|
||||
case IrInstructionIdSuspendBr:
|
||||
return ir_analyze_instruction_suspend_br(ira, (IrInstructionSuspendBr *)instruction);
|
||||
case IrInstructionIdCoroResume:
|
||||
return ir_analyze_instruction_coro_resume(ira, (IrInstructionCoroResume *)instruction);
|
||||
}
|
||||
zig_unreachable();
|
||||
}
|
||||
|
@ -24555,6 +24587,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
|
|||
case IrInstructionIdResetResult:
|
||||
case IrInstructionIdSuspendBegin:
|
||||
case IrInstructionIdSuspendBr:
|
||||
case IrInstructionIdCoroResume:
|
||||
return true;
|
||||
|
||||
case IrInstructionIdPhi:
|
||||
|
|
|
@ -1513,6 +1513,12 @@ static void ir_print_suspend_br(IrPrint *irp, IrInstructionSuspendBr *instructio
|
|||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_coro_resume(IrPrint *irp, IrInstructionCoroResume *instruction) {
|
||||
fprintf(irp->f, "@coroResume(");
|
||||
ir_print_other_instruction(irp, instruction->frame);
|
||||
fprintf(irp->f, ")");
|
||||
}
|
||||
|
||||
static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
||||
ir_print_prefix(irp, instruction);
|
||||
switch (instruction->id) {
|
||||
|
@ -1977,6 +1983,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
|
|||
case IrInstructionIdSuspendBr:
|
||||
ir_print_suspend_br(irp, (IrInstructionSuspendBr *)instruction);
|
||||
break;
|
||||
case IrInstructionIdCoroResume:
|
||||
ir_print_coro_resume(irp, (IrInstructionCoroResume *)instruction);
|
||||
break;
|
||||
}
|
||||
fprintf(irp->f, "\n");
|
||||
}
|
||||
|
|
|
@ -4,9 +4,11 @@ const expect = std.testing.expect;
|
|||
|
||||
var x: i32 = 1;
|
||||
|
||||
test "simple coroutine suspend" {
|
||||
test "simple coroutine suspend and resume" {
|
||||
const p = async simpleAsyncFn();
|
||||
expect(x == 2);
|
||||
resume p;
|
||||
expect(x == 3);
|
||||
}
|
||||
fn simpleAsyncFn() void {
|
||||
x += 1;
|
||||
|
|
Loading…
Reference in New Issue
Block a user