authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-23 03:03:06-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-23 03:03:06-05:00
log99985ad6fc0ff4ff09c0284c40023a9c826f8108
treec2aaeaf3626e7cc4d02eb81273c49974034ee4ca
parentca1b77b2d51408589659f652b1b1dbe2a25e149f

implement Zig IR for async functions

See #727

6 files changed, 467 insertions(+), 54 deletions(-)

src/all_types.hpp+36
......@@ -56,7 +56,13 @@ struct IrExecutable {
5656 IrAnalyze *analysis;
5757 Scope *begin_scope;
5858 ZigList<Tld *> tld_list;
59
5960 IrInstruction *coro_handle;
61 IrInstruction *coro_awaiter_field_ptr;
62 IrInstruction *coro_result_ptr_field_ptr;
63 IrInstruction *implicit_allocator_ptr;
64 IrBasicBlock *coro_early_final;
65 IrBasicBlock *coro_normal_final;
6066};
6167
6268enum OutType {
......@@ -1968,6 +1974,10 @@ enum IrInstructionId {
19681974 IrInstructionIdCoroSize,
19691975 IrInstructionIdCoroBegin,
19701976 IrInstructionIdCoroAllocFail,
1977 IrInstructionIdCoroSuspend,
1978 IrInstructionIdCoroEnd,
1979 IrInstructionIdCoroFree,
1980 IrInstructionIdCoroResume,
19711981};
19721982
19731983struct IrInstruction {
......@@ -2819,6 +2829,8 @@ struct IrInstructionGetImplicitAllocator {
28192829
28202830struct IrInstructionCoroId {
28212831 IrInstruction base;
2832
2833 IrInstruction *promise_ptr;
28222834};
28232835
28242836struct IrInstructionCoroAlloc {
......@@ -2844,6 +2856,30 @@ struct IrInstructionCoroAllocFail {
28442856 IrInstruction *err_val;
28452857};
28462858
2859struct IrInstructionCoroSuspend {
2860 IrInstruction base;
2861
2862 IrInstruction *save_point;
2863 IrInstruction *is_final;
2864};
2865
2866struct IrInstructionCoroEnd {
2867 IrInstruction base;
2868};
2869
2870struct IrInstructionCoroFree {
2871 IrInstruction base;
2872
2873 IrInstruction *coro_id;
2874 IrInstruction *coro_handle;
2875};
2876
2877struct IrInstructionCoroResume {
2878 IrInstruction base;
2879
2880 IrInstruction *awaiter_handle;
2881};
2882
28472883static const size_t slice_ptr_index = 0;
28482884static const size_t slice_len_index = 1;
28492885
src/analyze.cpp+6-4
......@@ -475,9 +475,7 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
475475 if (child_type->zero_bits) {
476476 entry->type_ref = LLVMInt1Type();
477477 entry->di_type = g->builtin_types.entry_bool->di_type;
478 } else if (child_type->id == TypeTableEntryIdPointer ||
479 child_type->id == TypeTableEntryIdFn)
480 {
478 } else if (type_is_codegen_pointer(child_type)) {
481479 // this is an optimization but also is necessary for calling C
482480 // functions where all pointers are maybe pointers
483481 // function types are technically pointers
......@@ -1262,7 +1260,7 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) {
12621260 case TypeTableEntryIdMaybe:
12631261 {
12641262 TypeTableEntry *child_type = type_entry->data.maybe.child_type;
1265 return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn;
1263 return type_is_codegen_pointer(child_type);
12661264 }
12671265 case TypeTableEntryIdEnum:
12681266 return type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr;
......@@ -1673,6 +1671,8 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f
16731671 field->src_index = i;
16741672 field->gen_index = i;
16751673
1674 assert(type_has_bits(field->type_entry));
1675
16761676 auto prev_entry = struct_type->data.structure.fields_by_name.put_unique(field->name, field);
16771677 assert(prev_entry == nullptr);
16781678 }
......@@ -3669,9 +3669,11 @@ void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
36693669TypeTableEntry *get_codegen_ptr_type(TypeTableEntry *type) {
36703670 if (type->id == TypeTableEntryIdPointer) return type;
36713671 if (type->id == TypeTableEntryIdFn) return type;
3672 if (type->id == TypeTableEntryIdPromise) return type;
36723673 if (type->id == TypeTableEntryIdMaybe) {
36733674 if (type->data.maybe.child_type->id == TypeTableEntryIdPointer) return type->data.maybe.child_type;
36743675 if (type->data.maybe.child_type->id == TypeTableEntryIdFn) return type->data.maybe.child_type;
3676 if (type->data.maybe.child_type->id == TypeTableEntryIdPromise) return type->data.maybe.child_type;
36753677 }
36763678 return nullptr;
36773679}
src/analyze.hpp+1
......@@ -51,6 +51,7 @@ VariableTableEntry *find_variable(CodeGen *g, Scope *orig_context, Buf *name);
5151Tld *find_decl(CodeGen *g, Scope *scope, Buf *name);
5252void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only, AstNode *source_node);
5353bool type_is_codegen_pointer(TypeTableEntry *type);
54
5455TypeTableEntry *get_codegen_ptr_type(TypeTableEntry *type);
5556uint32_t get_ptr_align(TypeTableEntry *type);
5657TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry);
src/codegen.cpp+34-12
......@@ -542,7 +542,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
542542
543543 if (!type_has_bits(return_type)) {
544544 // nothing to do
545 } else if (return_type->id == TypeTableEntryIdPointer || return_type->id == TypeTableEntryIdFn) {
545 } else if (type_is_codegen_pointer(return_type)) {
546546 addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
547547 } else if (handle_is_ptr(return_type) &&
548548 calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc))
......@@ -2789,7 +2789,7 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, TypeTableEntry *maybe_type, LLV
27892789 if (child_type->zero_bits) {
27902790 return maybe_handle;
27912791 } else {
2792 bool maybe_is_ptr = (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn);
2792 bool maybe_is_ptr = type_is_codegen_pointer(child_type);
27932793 if (maybe_is_ptr) {
27942794 return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), "");
27952795 } else {
......@@ -2829,7 +2829,7 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
28292829 if (child_type->zero_bits) {
28302830 return nullptr;
28312831 } else {
2832 bool maybe_is_ptr = (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn);
2832 bool maybe_is_ptr = type_is_codegen_pointer(child_type);
28332833 if (maybe_is_ptr) {
28342834 return maybe_ptr;
28352835 } else {
......@@ -3052,6 +3052,10 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
30523052 {
30533053 align_bytes = target_type->data.maybe.child_type->data.fn.fn_type_id.alignment;
30543054 ptr_val = target_val;
3055 } else if (target_type->id == TypeTableEntryIdMaybe &&
3056 target_type->data.maybe.child_type->id == TypeTableEntryIdPromise)
3057 {
3058 zig_panic("TODO audit this function");
30553059 } else if (target_type->id == TypeTableEntryIdStruct && target_type->data.structure.is_slice) {
30563060 TypeTableEntry *slice_ptr_type = target_type->data.structure.fields[slice_ptr_index].type_entry;
30573061 align_bytes = slice_ptr_type->data.pointer.alignment;
......@@ -3522,9 +3526,7 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I
35223526 }
35233527
35243528 LLVMValueRef payload_val = ir_llvm_value(g, instruction->value);
3525 if (child_type->id == TypeTableEntryIdPointer ||
3526 child_type->id == TypeTableEntryIdFn)
3527 {
3529 if (type_is_codegen_pointer(child_type)) {
35283530 return payload_val;
35293531 }
35303532
......@@ -3716,6 +3718,22 @@ static LLVMValueRef ir_render_coro_alloc_fail(CodeGen *g, IrExecutable *executab
37163718 zig_panic("TODO ir_render_coro_alloc_fail");
37173719}
37183720
3721static LLVMValueRef ir_render_coro_suspend(CodeGen *g, IrExecutable *executable, IrInstructionCoroSuspend *instruction) {
3722 zig_panic("TODO ir_render_coro_suspend");
3723}
3724
3725static LLVMValueRef ir_render_coro_end(CodeGen *g, IrExecutable *executable, IrInstructionCoroEnd *instruction) {
3726 zig_panic("TODO ir_render_coro_end");
3727}
3728
3729static LLVMValueRef ir_render_coro_free(CodeGen *g, IrExecutable *executable, IrInstructionCoroFree *instruction) {
3730 zig_panic("TODO ir_render_coro_free");
3731}
3732
3733static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable, IrInstructionCoroResume *instruction) {
3734 zig_panic("TODO ir_render_coro_resume");
3735}
3736
37193737static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
37203738 AstNode *source_node = instruction->source_node;
37213739 Scope *scope = instruction->scope;
......@@ -3911,6 +3929,14 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
39113929 return ir_render_coro_begin(g, executable, (IrInstructionCoroBegin *)instruction);
39123930 case IrInstructionIdCoroAllocFail:
39133931 return ir_render_coro_alloc_fail(g, executable, (IrInstructionCoroAllocFail *)instruction);
3932 case IrInstructionIdCoroSuspend:
3933 return ir_render_coro_suspend(g, executable, (IrInstructionCoroSuspend *)instruction);
3934 case IrInstructionIdCoroEnd:
3935 return ir_render_coro_end(g, executable, (IrInstructionCoroEnd *)instruction);
3936 case IrInstructionIdCoroFree:
3937 return ir_render_coro_free(g, executable, (IrInstructionCoroFree *)instruction);
3938 case IrInstructionIdCoroResume:
3939 return ir_render_coro_resume(g, executable, (IrInstructionCoroResume *)instruction);
39143940 }
39153941 zig_unreachable();
39163942}
......@@ -4155,9 +4181,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
41554181 TypeTableEntry *child_type = type_entry->data.maybe.child_type;
41564182 if (child_type->zero_bits) {
41574183 return LLVMConstInt(LLVMInt1Type(), const_val->data.x_maybe ? 1 : 0, false);
4158 } else if (child_type->id == TypeTableEntryIdPointer ||
4159 child_type->id == TypeTableEntryIdFn)
4160 {
4184 } else if (type_is_codegen_pointer(child_type)) {
41614185 if (const_val->data.x_maybe) {
41624186 return gen_const_val(g, const_val->data.x_maybe, "");
41634187 } else {
......@@ -6085,9 +6109,7 @@ static void get_c_type(CodeGen *g, GenH *gen_h, TypeTableEntry *type_entry, Buf
60856109 if (child_type->zero_bits) {
60866110 buf_init_from_str(out_buf, "bool");
60876111 return;
6088 } else if (child_type->id == TypeTableEntryIdPointer ||
6089 child_type->id == TypeTableEntryIdFn)
6090 {
6112 } else if (type_is_codegen_pointer(child_type)) {
60916113 return get_c_type(g, gen_h, child_type, out_buf);
60926114 } else {
60936115 zig_unreachable();
src/ir.cpp+345-37
......@@ -46,7 +46,10 @@ static LVal make_lval_addr(bool is_const, bool is_volatile) {
4646}
4747
4848static const char * ASYNC_ALLOC_FIELD_NAME = "allocFn";
49//static const char * ASYNC_FREE_FIELD_NAME = "freeFn";
49static const char * ASYNC_FREE_FIELD_NAME = "freeFn";
50static const char * AWAITER_HANDLE_FIELD_NAME = "awaiter_handle";
51static const char * RESULT_FIELD_NAME = "result";
52static const char * RESULT_PTR_FIELD_NAME = "result_ptr";
5053
5154enum ConstCastResultId {
5255 ConstCastResultIdOk,
......@@ -672,6 +675,22 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroAllocFail *)
672675 return IrInstructionIdCoroAllocFail;
673676}
674677
678static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroSuspend *) {
679 return IrInstructionIdCoroSuspend;
680}
681
682static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroEnd *) {
683 return IrInstructionIdCoroEnd;
684}
685
686static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroFree *) {
687 return IrInstructionIdCoroFree;
688}
689
690static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroResume *) {
691 return IrInstructionIdCoroResume;
692}
693
675694template<typename T>
676695static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
677696 T *special_instruction = allocate<T>(1);
......@@ -743,14 +762,6 @@ static IrInstruction *ir_build_return(IrBuilder *irb, Scope *scope, AstNode *sou
743762 return &return_instruction->base;
744763}
745764
746static IrInstruction *ir_build_return_from(IrBuilder *irb, IrInstruction *old_instruction,
747 IrInstruction *return_value)
748{
749 IrInstruction *new_instruction = ir_build_return(irb, old_instruction->scope, old_instruction->source_node, return_value);
750 ir_link_new_instruction(new_instruction, old_instruction);
751 return new_instruction;
752}
753
754765static IrInstruction *ir_create_const(IrBuilder *irb, Scope *scope, AstNode *source_node,
755766 TypeTableEntry *type_entry)
756767{
......@@ -822,6 +833,14 @@ static IrInstruction *ir_build_const_u29(IrBuilder *irb, Scope *scope, AstNode *
822833 return &const_instruction->base;
823834}
824835
836static IrInstruction *ir_build_const_u8(IrBuilder *irb, Scope *scope, AstNode *source_node, uint8_t value) {
837 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
838 const_instruction->base.value.type = irb->codegen->builtin_types.entry_u8;
839 const_instruction->base.value.special = ConstValSpecialStatic;
840 bigint_init_unsigned(&const_instruction->base.value.data.x_bigint, value);
841 return &const_instruction->base;
842}
843
825844static IrInstruction *ir_create_const_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
826845 TypeTableEntry *type_entry)
827846{
......@@ -909,6 +928,33 @@ static IrInstruction *ir_build_const_c_str_lit(IrBuilder *irb, Scope *scope, Ast
909928 return &const_instruction->base;
910929}
911930
931static IrInstruction *ir_build_const_promise_init(IrBuilder *irb, Scope *scope, AstNode *source_node,
932 TypeTableEntry *return_type)
933{
934 TypeTableEntry *awaiter_handle_type = get_maybe_type(irb->codegen, irb->codegen->builtin_types.entry_promise);
935 TypeTableEntry *result_ptr_type = get_pointer_to_type(irb->codegen, return_type, false);
936 const char *field_names[] = {AWAITER_HANDLE_FIELD_NAME, RESULT_FIELD_NAME, RESULT_PTR_FIELD_NAME};
937 TypeTableEntry *field_types[] = {awaiter_handle_type, return_type, result_ptr_type};
938 size_t field_count = type_has_bits(result_ptr_type) ? 3 : 1;
939 TypeTableEntry *struct_type = get_struct_type(irb->codegen, "AsyncFramePromise", field_names, field_types,
940 field_count);
941
942 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
943 const_instruction->base.value.type = struct_type;
944 const_instruction->base.value.special = ConstValSpecialStatic;
945 const_instruction->base.value.data.x_struct.fields = allocate<ConstExprValue>(2);
946 const_instruction->base.value.data.x_struct.fields[0].type = awaiter_handle_type;
947 const_instruction->base.value.data.x_struct.fields[0].special = ConstValSpecialStatic;
948 const_instruction->base.value.data.x_struct.fields[0].data.x_maybe = nullptr;
949 if (field_count == 3) {
950 const_instruction->base.value.data.x_struct.fields[1].type = return_type;
951 const_instruction->base.value.data.x_struct.fields[1].special = ConstValSpecialUndef;
952 const_instruction->base.value.data.x_struct.fields[2].type = result_ptr_type;
953 const_instruction->base.value.data.x_struct.fields[2].special = ConstValSpecialUndef;
954 }
955 return &const_instruction->base;
956}
957
912958static IrInstruction *ir_build_bin_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrBinOp op_id,
913959 IrInstruction *op1, IrInstruction *op2, bool safety_check_on)
914960{
......@@ -2451,8 +2497,11 @@ static IrInstruction *ir_build_get_implicit_allocator(IrBuilder *irb, Scope *sco
24512497 return &instruction->base;
24522498}
24532499
2454static IrInstruction *ir_build_coro_id(IrBuilder *irb, Scope *scope, AstNode *source_node) {
2500static IrInstruction *ir_build_coro_id(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *promise_ptr) {
24552501 IrInstructionCoroId *instruction = ir_build_instruction<IrInstructionCoroId>(irb, scope, source_node);
2502 instruction->promise_ptr = promise_ptr;
2503
2504 ir_ref_instruction(promise_ptr, irb->current_basic_block);
24562505
24572506 return &instruction->base;
24582507}
......@@ -2494,6 +2543,48 @@ static IrInstruction *ir_build_coro_alloc_fail(IrBuilder *irb, Scope *scope, Ast
24942543 return &instruction->base;
24952544}
24962545
2546static IrInstruction *ir_build_coro_suspend(IrBuilder *irb, Scope *scope, AstNode *source_node,
2547 IrInstruction *save_point, IrInstruction *is_final)
2548{
2549 IrInstructionCoroSuspend *instruction = ir_build_instruction<IrInstructionCoroSuspend>(irb, scope, source_node);
2550 instruction->save_point = save_point;
2551 instruction->is_final = is_final;
2552
2553 if (save_point != nullptr) ir_ref_instruction(save_point, irb->current_basic_block);
2554 ir_ref_instruction(is_final, irb->current_basic_block);
2555
2556 return &instruction->base;
2557}
2558
2559static IrInstruction *ir_build_coro_end(IrBuilder *irb, Scope *scope, AstNode *source_node) {
2560 IrInstructionCoroEnd *instruction = ir_build_instruction<IrInstructionCoroEnd>(irb, scope, source_node);
2561 return &instruction->base;
2562}
2563
2564static IrInstruction *ir_build_coro_free(IrBuilder *irb, Scope *scope, AstNode *source_node,
2565 IrInstruction *coro_id, IrInstruction *coro_handle)
2566{
2567 IrInstructionCoroFree *instruction = ir_build_instruction<IrInstructionCoroFree>(irb, scope, source_node);
2568 instruction->coro_id = coro_id;
2569 instruction->coro_handle = coro_handle;
2570
2571 ir_ref_instruction(coro_id, irb->current_basic_block);
2572 ir_ref_instruction(coro_handle, irb->current_basic_block);
2573
2574 return &instruction->base;
2575}
2576
2577static IrInstruction *ir_build_coro_resume(IrBuilder *irb, Scope *scope, AstNode *source_node,
2578 IrInstruction *awaiter_handle)
2579{
2580 IrInstructionCoroResume *instruction = ir_build_instruction<IrInstructionCoroResume>(irb, scope, source_node);
2581 instruction->awaiter_handle = awaiter_handle;
2582
2583 ir_ref_instruction(awaiter_handle, irb->current_basic_block);
2584
2585 return &instruction->base;
2586}
2587
24972588static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
24982589 results[ReturnKindUnconditional] = 0;
24992590 results[ReturnKindError] = 0;
......@@ -2566,6 +2657,29 @@ static ScopeDeferExpr *get_scope_defer_expr(Scope *scope) {
25662657 return nullptr;
25672658}
25682659
2660static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode *node, IrInstruction *return_value,
2661 bool is_generated_code)
2662{
2663 FnTableEntry *fn_entry = exec_fn_entry(irb->exec);
2664 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
2665 if (!is_async) {
2666 IrInstruction *return_inst = ir_build_return(irb, scope, node, return_value);
2667 return_inst->is_gen = is_generated_code;
2668 return return_inst;
2669 }
2670
2671 if (irb->exec->coro_result_ptr_field_ptr) {
2672 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);
2673 ir_build_store_ptr(irb, scope, node, result_ptr, return_value);
2674 }
2675 IrInstruction *maybe_await_handle = ir_build_load_ptr(irb, scope, node, irb->exec->coro_awaiter_field_ptr);
2676 IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, maybe_await_handle);
2677 IrInstruction *is_comptime = ir_build_const_bool(irb, scope, node, false);
2678 return ir_build_cond_br(irb, scope, node, is_non_null, irb->exec->coro_normal_final, irb->exec->coro_early_final,
2679 is_comptime);
2680 // the above blocks are rendered by ir_gen after the rest of codegen
2681}
2682
25692683static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
25702684 assert(node->type == NodeTypeReturnExpr);
25712685
......@@ -2615,18 +2729,22 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
26152729 }
26162730
26172731 ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err, err_block, ok_block, is_comptime));
2732 IrBasicBlock *ret_stmt_block = ir_create_basic_block(irb, scope, "RetStmt");
26182733
26192734 ir_set_cursor_at_end_and_append_block(irb, err_block);
26202735 ir_gen_defers_for_block(irb, scope, outer_scope, true);
2621 ir_build_return(irb, scope, node, return_value);
2736 ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);
26222737
26232738 ir_set_cursor_at_end_and_append_block(irb, ok_block);
26242739 ir_gen_defers_for_block(irb, scope, outer_scope, false);
2625 return ir_build_return(irb, scope, node, return_value);
2740 ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);
2741
2742 ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block);
2743 return ir_gen_async_return(irb, scope, node, return_value, false);
26262744 } else {
26272745 // generate unconditional defers
26282746 ir_gen_defers_for_block(irb, scope, outer_scope, false);
2629 return ir_build_return(irb, scope, node, return_value);
2747 return ir_gen_async_return(irb, scope, node, return_value, false);
26302748 }
26312749 }
26322750 case ReturnKindError:
......@@ -2646,7 +2764,7 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
26462764 ir_set_cursor_at_end_and_append_block(irb, return_block);
26472765 ir_gen_defers_for_block(irb, scope, outer_scope, true);
26482766 IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr);
2649 ir_build_return(irb, scope, node, err_val);
2767 ir_gen_async_return(irb, scope, node, err_val, false);
26502768
26512769 ir_set_cursor_at_end_and_append_block(irb, continue_block);
26522770 IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, false);
......@@ -5842,6 +5960,7 @@ static void invalidate_exec(IrExecutable *exec) {
58425960 invalidate_exec(exec->source_exec);
58435961}
58445962
5963
58455964bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_executable) {
58465965 assert(node->owner);
58475966
......@@ -5858,48 +5977,81 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
58585977
58595978 FnTableEntry *fn_entry = exec_fn_entry(irb->exec);
58605979 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
5980 IrInstruction *u8_ptr_type;
5981 IrInstruction *const_bool_false;
5982 IrInstruction *coro_unwrapped_mem_ptr;
5983 IrInstruction *coro_id;
5984 IrInstruction *coro_promise_ptr;
5985 IrInstruction *coro_result_field_ptr;
5986 TypeTableEntry *return_type;
5987 Buf *result_ptr_field_name;
58615988 if (is_async) {
5862 IrInstruction *is_comptime_false = ir_build_const_bool(irb, scope, node, false);
5863 IrInstruction *coro_id = ir_build_coro_id(irb, scope, node);
5989 // create the coro promise
5990 const_bool_false = ir_build_const_bool(irb, scope, node, false);
5991 VariableTableEntry *promise_var = ir_create_var(irb, node, scope, nullptr, false, false, true, const_bool_false);
5992 //scope = promise_var->child_scope;
5993
5994 return_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
5995 IrInstruction *promise_init = ir_build_const_promise_init(irb, scope, node, return_type);
5996 ir_build_var_decl(irb, scope, node, promise_var, nullptr, nullptr, promise_init);
5997
5998 coro_promise_ptr = ir_build_var_ptr(irb, scope, node, promise_var, false, false);
5999 Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME);
6000 irb->exec->coro_awaiter_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
6001 awaiter_handle_field_name);
6002 if (type_has_bits(return_type)) {
6003 Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);
6004 coro_result_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name);
6005 result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);
6006 irb->exec->coro_result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
6007 result_ptr_field_name);
6008 ir_build_store_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr, coro_result_field_ptr);
6009 }
6010
6011 u8_ptr_type = ir_build_const_type(irb, scope, node,
6012 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));
6013 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, coro_promise_ptr);
6014 coro_id = ir_build_coro_id(irb, scope, node, promise_as_u8_ptr);
58646015 IrInstruction *need_dyn_alloc = ir_build_coro_alloc(irb, scope, node, coro_id);
58656016 IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);
5866 IrInstruction *u8_ptr_type = ir_build_const_type(irb, scope, node,
5867 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));
58686017 IrInstruction *null_ptr = ir_build_int_to_ptr(irb, scope, node, u8_ptr_type, zero);
58696018
58706019 IrBasicBlock *dyn_alloc_block = ir_create_basic_block(irb, scope, "DynAlloc");
58716020 IrBasicBlock *coro_begin_block = ir_create_basic_block(irb, scope, "CoroBegin");
5872 ir_build_cond_br(irb, scope, node, need_dyn_alloc, dyn_alloc_block, coro_begin_block, is_comptime_false);
6021 ir_build_cond_br(irb, scope, node, need_dyn_alloc, dyn_alloc_block, coro_begin_block, const_bool_false);
58736022
58746023 ir_set_cursor_at_end_and_append_block(irb, dyn_alloc_block);
58756024 IrInstruction *coro_size = ir_build_coro_size(irb, scope, node);
5876 IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node);
6025 irb->exec->implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node);
58776026 Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);
5878 IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, alloc_field_name);
6027 IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, scope, node, irb->exec->implicit_allocator_ptr,
6028 alloc_field_name);
58796029 IrInstruction *alloc_fn = ir_build_load_ptr(irb, scope, node, alloc_fn_ptr);
58806030 IrInstruction *alignment = ir_build_const_u29(irb, scope, node, irb->codegen->pointer_size_bytes * 2);
58816031 size_t arg_count = 3;
58826032 IrInstruction **args = allocate<IrInstruction *>(arg_count);
5883 args[0] = implicit_allocator_ptr; // self
6033 args[0] = irb->exec->implicit_allocator_ptr; // self
58846034 args[1] = coro_size; // byte_count
58856035 args[2] = alignment; // alignment
5886 IrInstruction *alloc_result = ir_build_call(irb, scope, node, nullptr, alloc_fn, arg_count, args, false, FnInlineAuto, false, nullptr);
6036 IrInstruction *alloc_result = ir_build_call(irb, scope, node, nullptr, alloc_fn, arg_count, args, false,
6037 FnInlineAuto, false, nullptr);
58876038 IrInstruction *alloc_result_ptr = ir_build_ref(irb, scope, node, alloc_result, true, false);
58886039 IrInstruction *alloc_result_is_err = ir_build_test_err(irb, scope, node, alloc_result);
58896040 IrBasicBlock *alloc_err_block = ir_create_basic_block(irb, scope, "AllocError");
58906041 IrBasicBlock *alloc_ok_block = ir_create_basic_block(irb, scope, "AllocOk");
5891 ir_build_cond_br(irb, scope, node, alloc_result_is_err, alloc_err_block, alloc_ok_block, is_comptime_false);
6042 ir_build_cond_br(irb, scope, node, alloc_result_is_err, alloc_err_block, alloc_ok_block, const_bool_false);
58926043
58936044 ir_set_cursor_at_end_and_append_block(irb, alloc_err_block);
58946045 IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, alloc_result_ptr);
58956046 ir_build_coro_alloc_fail(irb, scope, node, err_val);
58966047
58976048 ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);
5898 IrInstruction *unwrapped_mem_ptr = ir_build_unwrap_err_payload(irb, scope, node, alloc_result_ptr, false);
6049 coro_unwrapped_mem_ptr = ir_build_unwrap_err_payload(irb, scope, node, alloc_result_ptr, false);
58996050 Buf *ptr_field_name = buf_create_from_str("ptr");
5900 IrInstruction *coro_mem_ptr_field = ir_build_field_ptr(irb, scope, node, unwrapped_mem_ptr, ptr_field_name);
6051 IrInstruction *coro_mem_ptr_field = ir_build_field_ptr(irb, scope, node, coro_unwrapped_mem_ptr,
6052 ptr_field_name);
59016053 IrInstruction *coro_mem_ptr = ir_build_load_ptr(irb, scope, node, coro_mem_ptr_field);
5902 ir_build_br(irb, scope, node, coro_begin_block, is_comptime_false);
6054 ir_build_br(irb, scope, node, coro_begin_block, const_bool_false);
59036055
59046056 ir_set_cursor_at_end_and_append_block(irb, coro_begin_block);
59056057 IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);
......@@ -5910,6 +6062,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
59106062 incoming_values[1] = coro_mem_ptr;
59116063 IrInstruction *coro_mem = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
59126064 irb->exec->coro_handle = ir_build_coro_begin(irb, scope, node, coro_id, coro_mem);
6065 irb->exec->coro_early_final = ir_create_basic_block(irb, scope, "CoroEarlyFinal");
6066 irb->exec->coro_normal_final = ir_create_basic_block(irb, scope, "CoroNormalFinal");
59136067 }
59146068
59156069 IrInstruction *result = ir_gen_node_extra(irb, node, scope, LVAL_NONE);
......@@ -5918,7 +6072,84 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
59186072 return false;
59196073
59206074 if (!instr_is_unreachable(result)) {
5921 ir_mark_gen(ir_build_return(irb, scope, result->source_node, result));
6075 ir_gen_async_return(irb, scope, result->source_node, result, true);
6076 }
6077
6078 if (is_async) {
6079 IrBasicBlock *invalid_resume_block = ir_create_basic_block(irb, scope, "InvalidResume");
6080 IrBasicBlock *final_cleanup_block = ir_create_basic_block(irb, scope, "FinalCleanup");
6081 IrBasicBlock *suspend_block = ir_create_basic_block(irb, scope, "Suspend");
6082 IrBasicBlock *check_free_block = ir_create_basic_block(irb, scope, "CheckFree");
6083
6084 ir_set_cursor_at_end_and_append_block(irb, irb->exec->coro_early_final);
6085 IrInstruction *const_bool_true = ir_build_const_bool(irb, scope, node, true);
6086 IrInstruction *suspend_code = ir_build_coro_suspend(irb, scope, node, nullptr, const_bool_true);
6087 IrInstructionSwitchBrCase *cases = allocate<IrInstructionSwitchBrCase>(2);
6088 cases[0].value = ir_build_const_u8(irb, scope, node, 0);
6089 cases[0].block = invalid_resume_block;
6090 cases[1].value = ir_build_const_u8(irb, scope, node, 1);
6091 cases[1].block = final_cleanup_block;
6092 ir_build_switch_br(irb, scope, node, suspend_code, suspend_block, 2, cases, const_bool_false);
6093
6094 ir_set_cursor_at_end_and_append_block(irb, suspend_block);
6095 ir_build_coro_end(irb, scope, node);
6096 ir_build_return(irb, scope, node, irb->exec->coro_handle);
6097
6098 ir_set_cursor_at_end_and_append_block(irb, invalid_resume_block);
6099 ir_build_unreachable(irb, scope, node);
6100
6101 ir_set_cursor_at_end_and_append_block(irb, irb->exec->coro_normal_final);
6102 ir_build_br(irb, scope, node, check_free_block, const_bool_false);
6103
6104 ir_set_cursor_at_end_and_append_block(irb, final_cleanup_block);
6105 if (type_has_bits(return_type)) {
6106 IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);
6107 IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, result_ptr);
6108 IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type,
6109 coro_result_field_ptr);
6110 IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,
6111 fn_entry->type_entry->data.fn.fn_type_id.return_type);
6112 IrInstruction *size_of_ret_val = ir_build_size_of(irb, scope, node, return_type_inst);
6113 ir_build_memcpy(irb, scope, node, result_ptr_as_u8_ptr, return_value_ptr_as_u8_ptr, size_of_ret_val);
6114 }
6115 ir_build_br(irb, scope, node, check_free_block, const_bool_false);
6116
6117 ir_set_cursor_at_end_and_append_block(irb, check_free_block);
6118 IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2);
6119 IrInstruction **incoming_values = allocate<IrInstruction *>(2);
6120 incoming_blocks[0] = final_cleanup_block;
6121 incoming_values[0] = const_bool_false;
6122 incoming_blocks[1] = irb->exec->coro_normal_final;
6123 incoming_values[1] = const_bool_true;
6124 IrInstruction *resume_awaiter = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values);
6125 IrInstruction *mem_to_free = ir_build_coro_free(irb, scope, node, coro_id, irb->exec->coro_handle);
6126 IrInstruction *is_non_null = ir_build_test_nonnull(irb, scope, node, mem_to_free);
6127 IrBasicBlock *dyn_free_block = ir_create_basic_block(irb, scope, "DynFree");
6128 IrBasicBlock *end_free_block = ir_create_basic_block(irb, scope, "EndFree");
6129 ir_build_cond_br(irb, scope, node, is_non_null, dyn_free_block, end_free_block, const_bool_false);
6130
6131 ir_set_cursor_at_end_and_append_block(irb, dyn_free_block);
6132 Buf *free_field_name = buf_create_from_str(ASYNC_FREE_FIELD_NAME);
6133 IrInstruction *free_fn_ptr = ir_build_field_ptr(irb, scope, node, irb->exec->implicit_allocator_ptr,
6134 free_field_name);
6135 IrInstruction *free_fn = ir_build_load_ptr(irb, scope, node, free_fn_ptr);
6136 size_t arg_count = 2;
6137 IrInstruction **args = allocate<IrInstruction *>(arg_count);
6138 args[0] = irb->exec->implicit_allocator_ptr; // self
6139 args[1] = ir_build_load_ptr(irb, scope, node, coro_unwrapped_mem_ptr); // old_mem
6140 ir_build_call(irb, scope, node, nullptr, free_fn, arg_count, args, false, FnInlineAuto, false, nullptr);
6141 ir_build_br(irb, scope, node, end_free_block, const_bool_false);
6142
6143 ir_set_cursor_at_end_and_append_block(irb, end_free_block);
6144 IrBasicBlock *resume_block = ir_create_basic_block(irb, scope, "Resume");
6145 ir_build_cond_br(irb, scope, node, resume_awaiter, resume_block, suspend_block, const_bool_false);
6146
6147 ir_set_cursor_at_end_and_append_block(irb, resume_block);
6148 IrInstruction *unwrapped_await_handle_ptr = ir_build_unwrap_maybe(irb, scope, node,
6149 irb->exec->coro_awaiter_field_ptr, false);
6150 IrInstruction *awaiter_handle = ir_build_load_ptr(irb, scope, node, unwrapped_await_handle_ptr);
6151 ir_build_coro_resume(irb, scope, node, awaiter_handle);
6152 ir_build_br(irb, scope, node, suspend_block, const_bool_false);
59226153 }
59236154
59246155 return true;
......@@ -9514,8 +9745,11 @@ static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira,
95149745 ir_add_error(ira, casted_value, buf_sprintf("function returns address of local variable"));
95159746 return ir_unreach_error(ira);
95169747 }
9517 ir_build_return_from(&ira->new_irb, &return_instruction->base, casted_value);
9518 return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable);
9748 IrInstruction *result = ir_build_return(&ira->new_irb, return_instruction->base.scope,
9749 return_instruction->base.source_node, casted_value);
9750 result->value.type = ira->codegen->builtin_types.entry_unreachable;
9751 ir_link_new_instruction(result, &return_instruction->base);
9752 return ir_finish_anal(ira, result->value.type);
95199753}
95209754
95219755static TypeTableEntry *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *const_instruction) {
......@@ -16624,11 +16858,8 @@ static TypeTableEntry *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstr
1662416858
1662516859 TypeTableEntry *usize = ira->codegen->builtin_types.entry_usize;
1662616860
16627 if (!(target->value.type->id == TypeTableEntryIdPointer ||
16628 target->value.type->id == TypeTableEntryIdFn ||
16629 (target->value.type->id == TypeTableEntryIdMaybe &&
16630 (target->value.type->data.maybe.child_type->id == TypeTableEntryIdPointer ||
16631 target->value.type->data.maybe.child_type->id == TypeTableEntryIdFn))))
16861 if (!(type_is_codegen_pointer(target->value.type) || (target->value.type->id == TypeTableEntryIdMaybe &&
16862 type_is_codegen_pointer(target->value.type->data.maybe.child_type))))
1663216863 {
1663316864 ir_add_error(ira, target,
1663416865 buf_sprintf("expected pointer, found '%s'", buf_ptr(&target->value.type->name)));
......@@ -16829,7 +17060,12 @@ static TypeTableEntry *ir_analyze_instruction_cancel(IrAnalyze *ira, IrInstructi
1682917060}
1683017061
1683117062static TypeTableEntry *ir_analyze_instruction_coro_id(IrAnalyze *ira, IrInstructionCoroId *instruction) {
16832 IrInstruction *result = ir_build_coro_id(&ira->new_irb, instruction->base.scope, instruction->base.source_node);
17063 IrInstruction *promise_ptr = instruction->promise_ptr->other;
17064 if (type_is_invalid(promise_ptr->value.type))
17065 return ira->codegen->builtin_types.entry_invalid;
17066
17067 IrInstruction *result = ir_build_coro_id(&ira->new_irb, instruction->base.scope, instruction->base.source_node,
17068 promise_ptr);
1683317069 ir_link_new_instruction(result, &instruction->base);
1683417070 result->value.type = ira->codegen->builtin_types.entry_usize;
1683517071 return result->value.type;
......@@ -16889,6 +17125,63 @@ static TypeTableEntry *ir_analyze_instruction_coro_alloc_fail(IrAnalyze *ira, Ir
1688917125 return ir_finish_anal(ira, result->value.type);
1689017126}
1689117127
17128static TypeTableEntry *ir_analyze_instruction_coro_suspend(IrAnalyze *ira, IrInstructionCoroSuspend *instruction) {
17129 IrInstruction *save_point = nullptr;
17130 if (instruction->save_point != nullptr) {
17131 save_point = instruction->save_point->other;
17132 if (type_is_invalid(save_point->value.type))
17133 return ira->codegen->builtin_types.entry_invalid;
17134 }
17135
17136 IrInstruction *is_final = instruction->is_final->other;
17137 if (type_is_invalid(is_final->value.type))
17138 return ira->codegen->builtin_types.entry_invalid;
17139
17140 IrInstruction *result = ir_build_coro_suspend(&ira->new_irb, instruction->base.scope,
17141 instruction->base.source_node, save_point, is_final);
17142 ir_link_new_instruction(result, &instruction->base);
17143 result->value.type = ira->codegen->builtin_types.entry_u8;
17144 return result->value.type;
17145}
17146
17147static TypeTableEntry *ir_analyze_instruction_coro_end(IrAnalyze *ira, IrInstructionCoroEnd *instruction) {
17148 IrInstruction *result = ir_build_coro_end(&ira->new_irb, instruction->base.scope,
17149 instruction->base.source_node);
17150 ir_link_new_instruction(result, &instruction->base);
17151 result->value.type = ira->codegen->builtin_types.entry_void;
17152 return result->value.type;
17153}
17154
17155static TypeTableEntry *ir_analyze_instruction_coro_free(IrAnalyze *ira, IrInstructionCoroFree *instruction) {
17156 IrInstruction *coro_id = instruction->coro_id->other;
17157 if (type_is_invalid(coro_id->value.type))
17158 return ira->codegen->builtin_types.entry_invalid;
17159
17160 IrInstruction *coro_handle = instruction->coro_handle->other;
17161 if (type_is_invalid(coro_handle->value.type))
17162 return ira->codegen->builtin_types.entry_invalid;
17163
17164 IrInstruction *result = ir_build_coro_free(&ira->new_irb, instruction->base.scope,
17165 instruction->base.source_node, coro_id, coro_handle);
17166 ir_link_new_instruction(result, &instruction->base);
17167 TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, false);
17168 result->value.type = get_maybe_type(ira->codegen, ptr_type);
17169 return result->value.type;
17170}
17171
17172static TypeTableEntry *ir_analyze_instruction_coro_resume(IrAnalyze *ira, IrInstructionCoroResume *instruction) {
17173 IrInstruction *awaiter_handle = instruction->awaiter_handle->other;
17174 if (type_is_invalid(awaiter_handle->value.type))
17175 return ira->codegen->builtin_types.entry_invalid;
17176
17177 IrInstruction *result = ir_build_coro_resume(&ira->new_irb, instruction->base.scope,
17178 instruction->base.source_node, awaiter_handle);
17179 ir_link_new_instruction(result, &instruction->base);
17180 result->value.type = ira->codegen->builtin_types.entry_void;
17181 return result->value.type;
17182}
17183
17184
1689217185static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
1689317186 switch (instruction->id) {
1689417187 case IrInstructionIdInvalid:
......@@ -17105,6 +17398,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
1710517398 return ir_analyze_instruction_get_implicit_allocator(ira, (IrInstructionGetImplicitAllocator *)instruction);
1710617399 case IrInstructionIdCoroAllocFail:
1710717400 return ir_analyze_instruction_coro_alloc_fail(ira, (IrInstructionCoroAllocFail *)instruction);
17401 case IrInstructionIdCoroSuspend:
17402 return ir_analyze_instruction_coro_suspend(ira, (IrInstructionCoroSuspend *)instruction);
17403 case IrInstructionIdCoroEnd:
17404 return ir_analyze_instruction_coro_end(ira, (IrInstructionCoroEnd *)instruction);
17405 case IrInstructionIdCoroFree:
17406 return ir_analyze_instruction_coro_free(ira, (IrInstructionCoroFree *)instruction);
17407 case IrInstructionIdCoroResume:
17408 return ir_analyze_instruction_coro_resume(ira, (IrInstructionCoroResume *)instruction);
1710817409 }
1710917410 zig_unreachable();
1711017411}
......@@ -17134,7 +17435,10 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
1713417435 IrAnalyze *ira = allocate<IrAnalyze>(1);
1713517436 old_exec->analysis = ira;
1713617437 ira->codegen = codegen;
17137 ira->explicit_return_type = expected_type;
17438
17439 FnTableEntry *fn_entry = exec_fn_entry(old_exec);
17440 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
17441 ira->explicit_return_type = is_async ? get_promise_type(codegen, expected_type) : expected_type;
1713817442
1713917443 ira->old_irb.codegen = codegen;
1714017444 ira->old_irb.exec = old_exec;
......@@ -17222,6 +17526,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
1722217526 case IrInstructionIdCoroId:
1722317527 case IrInstructionIdCoroBegin:
1722417528 case IrInstructionIdCoroAllocFail:
17529 case IrInstructionIdCoroEnd:
17530 case IrInstructionIdCoroResume:
1722517531 return true;
1722617532
1722717533 case IrInstructionIdPhi:
......@@ -17299,6 +17605,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
1729917605 case IrInstructionIdGetImplicitAllocator:
1730017606 case IrInstructionIdCoroAlloc:
1730117607 case IrInstructionIdCoroSize:
17608 case IrInstructionIdCoroSuspend:
17609 case IrInstructionIdCoroFree:
1730217610 return false;
1730317611
1730417612 case IrInstructionIdAsm:
src/ir_print.cpp+45-1
......@@ -1031,7 +1031,9 @@ static void ir_print_get_implicit_allocator(IrPrint *irp, IrInstructionGetImplic
10311031}
10321032
10331033static void ir_print_coro_id(IrPrint *irp, IrInstructionCoroId *instruction) {
1034 fprintf(irp->f, "@coroId()");
1034 fprintf(irp->f, "@coroId(");
1035 ir_print_other_instruction(irp, instruction->promise_ptr);
1036 fprintf(irp->f, ")");
10351037}
10361038
10371039static void ir_print_coro_alloc(IrPrint *irp, IrInstructionCoroAlloc *instruction) {
......@@ -1058,6 +1060,36 @@ static void ir_print_coro_alloc_fail(IrPrint *irp, IrInstructionCoroAllocFail *i
10581060 fprintf(irp->f, ")");
10591061}
10601062
1063static void ir_print_coro_suspend(IrPrint *irp, IrInstructionCoroSuspend *instruction) {
1064 fprintf(irp->f, "@coroSuspend(");
1065 if (instruction->save_point != nullptr) {
1066 ir_print_other_instruction(irp, instruction->save_point);
1067 } else {
1068 fprintf(irp->f, "null");
1069 }
1070 fprintf(irp->f, ",");
1071 ir_print_other_instruction(irp, instruction->is_final);
1072 fprintf(irp->f, ")");
1073}
1074
1075static void ir_print_coro_end(IrPrint *irp, IrInstructionCoroEnd *instruction) {
1076 fprintf(irp->f, "@coroEnd()");
1077}
1078
1079static void ir_print_coro_free(IrPrint *irp, IrInstructionCoroFree *instruction) {
1080 fprintf(irp->f, "@coroFree(");
1081 ir_print_other_instruction(irp, instruction->coro_id);
1082 fprintf(irp->f, ",");
1083 ir_print_other_instruction(irp, instruction->coro_handle);
1084 fprintf(irp->f, ")");
1085}
1086
1087static void ir_print_coro_resume(IrPrint *irp, IrInstructionCoroResume *instruction) {
1088 fprintf(irp->f, "@coroResume(");
1089 ir_print_other_instruction(irp, instruction->awaiter_handle);
1090 fprintf(irp->f, ")");
1091}
1092
10611093static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
10621094 ir_print_prefix(irp, instruction);
10631095 switch (instruction->id) {
......@@ -1399,6 +1431,18 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
13991431 case IrInstructionIdCoroAllocFail:
14001432 ir_print_coro_alloc_fail(irp, (IrInstructionCoroAllocFail *)instruction);
14011433 break;
1434 case IrInstructionIdCoroSuspend:
1435 ir_print_coro_suspend(irp, (IrInstructionCoroSuspend *)instruction);
1436 break;
1437 case IrInstructionIdCoroEnd:
1438 ir_print_coro_end(irp, (IrInstructionCoroEnd *)instruction);
1439 break;
1440 case IrInstructionIdCoroFree:
1441 ir_print_coro_free(irp, (IrInstructionCoroFree *)instruction);
1442 break;
1443 case IrInstructionIdCoroResume:
1444 ir_print_coro_resume(irp, (IrInstructionCoroResume *)instruction);
1445 break;
14021446 }
14031447 fprintf(irp->f, "\n");
14041448}