aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-08-02 01:05:34 -0400
committerAndrew Kelley <andrew@ziglang.org>2019-08-02 01:06:00 -0400
commit056c4e2c988c0a2ff6f1be8fe18a0a056d848271 (patch)
tree86d830fbc801536ec06d7f5d7e609ff01e32288a /src/ir.cpp
parent0f879d02a4c4b1de0e28c2863c1e5f3760eb5b19 (diff)
downloadzig-056c4e2c988c0a2ff6f1be8fe18a0a056d848271.tar.gz
zig-056c4e2c988c0a2ff6f1be8fe18a0a056d848271.zip
implement async await and return
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp97
1 files changed, 82 insertions, 15 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index 3a6853b034..ecd2cd6f87 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -1052,6 +1052,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSuspendBr *) {
return IrInstructionIdSuspendBr;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionAwait *) {
+ return IrInstructionIdAwait;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroResume *) {
return IrInstructionIdCoroResume;
}
@@ -3274,6 +3278,17 @@ static IrInstruction *ir_build_suspend_br(IrBuilder *irb, Scope *scope, AstNode
return &instruction->base;
}
+static IrInstruction *ir_build_await(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *frame)
+{
+ IrInstructionAwait *instruction = ir_build_instruction<IrInstructionAwait>(irb, scope, source_node);
+ instruction->frame = frame;
+
+ ir_ref_instruction(frame, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_coro_resume(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *frame)
{
@@ -7774,11 +7789,26 @@ static IrInstruction *ir_gen_resume(IrBuilder *irb, Scope *scope, AstNode *node)
static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *node) {
assert(node->type == NodeTypeAwaitExpr);
- IrInstruction *target_inst = ir_gen_node(irb, node->data.await_expr.expr, scope);
+ ZigFn *fn_entry = exec_fn_entry(irb->exec);
+ if (!fn_entry) {
+ add_node_error(irb->codegen, node, buf_sprintf("await outside function definition"));
+ return irb->codegen->invalid_instruction;
+ }
+ ScopeSuspend *existing_suspend_scope = get_scope_suspend(scope);
+ if (existing_suspend_scope) {
+ if (!existing_suspend_scope->reported_err) {
+ ErrorMsg *msg = add_node_error(irb->codegen, node, buf_sprintf("cannot await inside suspend block"));
+ add_error_note(irb->codegen, msg, existing_suspend_scope->base.source_node, buf_sprintf("suspend block here"));
+ existing_suspend_scope->reported_err = true;
+ }
+ return irb->codegen->invalid_instruction;
+ }
+
+ IrInstruction *target_inst = ir_gen_node_extra(irb, node->data.await_expr.expr, scope, LValPtr, nullptr);
if (target_inst == irb->codegen->invalid_instruction)
return irb->codegen->invalid_instruction;
- zig_panic("TODO ir_gen_await_expr");
+ return ir_build_await(irb, scope, node, target_inst);
}
static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
@@ -7789,15 +7819,6 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod
add_node_error(irb->codegen, node, buf_sprintf("suspend outside function definition"));
return irb->codegen->invalid_instruction;
}
- ScopeDeferExpr *scope_defer_expr = get_scope_defer_expr(parent_scope);
- if (scope_defer_expr) {
- if (!scope_defer_expr->reported_err) {
- ErrorMsg *msg = add_node_error(irb->codegen, node, buf_sprintf("cannot suspend inside defer expression"));
- add_error_note(irb->codegen, msg, scope_defer_expr->base.source_node, buf_sprintf("defer here"));
- scope_defer_expr->reported_err = true;
- }
- return irb->codegen->invalid_instruction;
- }
ScopeSuspend *existing_suspend_scope = get_scope_suspend(parent_scope);
if (existing_suspend_scope) {
if (!existing_suspend_scope->reported_err) {
@@ -7808,7 +7829,7 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod
return irb->codegen->invalid_instruction;
}
- IrBasicBlock *resume_block = ir_create_basic_block(irb, parent_scope, "Resume");
+ IrBasicBlock *resume_block = ir_create_basic_block(irb, parent_scope, "SuspendResume");
ir_build_suspend_begin(irb, parent_scope, node, resume_block);
if (node->data.suspend.block != nullptr) {
@@ -24372,19 +24393,62 @@ 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) {
+static IrInstruction *ir_analyze_instruction_await(IrAnalyze *ira, IrInstructionAwait *instruction) {
IrInstruction *frame_ptr = instruction->frame->child;
if (type_is_invalid(frame_ptr->value.type))
return ira->codegen->invalid_instruction;
+ ZigType *result_type;
IrInstruction *frame;
if (frame_ptr->value.type->id == ZigTypeIdPointer &&
frame_ptr->value.type->data.pointer.ptr_len == PtrLenSingle &&
- frame_ptr->value.type->data.pointer.child_type->id == ZigTypeIdAnyFrame)
+ frame_ptr->value.type->data.pointer.child_type->id == ZigTypeIdCoroFrame)
{
- frame = ir_get_deref(ira, &instruction->base, frame_ptr, nullptr);
+ result_type = frame_ptr->value.type->data.pointer.child_type->data.frame.fn->type_entry->data.fn.fn_type_id.return_type;
+ frame = frame_ptr;
} else {
+ frame = ir_get_deref(ira, &instruction->base, frame_ptr, nullptr);
+ if (frame->value.type->id != ZigTypeIdAnyFrame ||
+ frame->value.type->data.any_frame.result_type == nullptr)
+ {
+ ir_add_error(ira, &instruction->base,
+ buf_sprintf("expected anyframe->T, found '%s'", buf_ptr(&frame->value.type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+ result_type = frame->value.type->data.any_frame.result_type;
+ }
+
+ ZigType *any_frame_type = get_any_frame_type(ira->codegen, result_type);
+ IrInstruction *casted_frame = ir_implicit_cast(ira, frame, any_frame_type);
+ if (type_is_invalid(casted_frame->value.type))
+ return ira->codegen->invalid_instruction;
+
+ ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
+ ir_assert(fn_entry != nullptr, &instruction->base);
+
+ if (fn_entry->inferred_async_node == nullptr) {
+ fn_entry->inferred_async_node = instruction->base.source_node;
+ }
+
+ IrInstruction *result = ir_build_await(&ira->new_irb,
+ instruction->base.scope, instruction->base.source_node, frame);
+ result->value.type = result_type;
+ return ir_finish_anal(ira, result);
+}
+
+static IrInstruction *ir_analyze_instruction_coro_resume(IrAnalyze *ira, IrInstructionCoroResume *instruction) {
+ IrInstruction *frame_ptr = instruction->frame->child;
+ if (type_is_invalid(frame_ptr->value.type))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *frame;
+ if (frame_ptr->value.type->id == ZigTypeIdPointer &&
+ frame_ptr->value.type->data.pointer.ptr_len == PtrLenSingle &&
+ frame_ptr->value.type->data.pointer.child_type->id == ZigTypeIdCoroFrame)
+ {
frame = frame_ptr;
+ } else {
+ frame = ir_get_deref(ira, &instruction->base, frame_ptr, nullptr);
}
ZigType *any_frame_type = get_any_frame_type(ira->codegen, nullptr);
@@ -24691,6 +24755,8 @@ static IrInstruction *ir_analyze_instruction_base(IrAnalyze *ira, IrInstruction
return ir_analyze_instruction_suspend_br(ira, (IrInstructionSuspendBr *)instruction);
case IrInstructionIdCoroResume:
return ir_analyze_instruction_coro_resume(ira, (IrInstructionCoroResume *)instruction);
+ case IrInstructionIdAwait:
+ return ir_analyze_instruction_await(ira, (IrInstructionAwait *)instruction);
}
zig_unreachable();
}
@@ -24826,6 +24892,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdSuspendBegin:
case IrInstructionIdSuspendBr:
case IrInstructionIdCoroResume:
+ case IrInstructionIdAwait:
return true;
case IrInstructionIdPhi: