| ... | @@ -45,6 +45,9 @@ static LVal make_lval_addr(bool is_const, bool is_volatile) { | ... | @@ -45,6 +45,9 @@ static LVal make_lval_addr(bool is_const, bool is_volatile) { |
| 45 | return { true, is_const, is_volatile }; | 45 | return { true, is_const, is_volatile }; |
| 46 | } | 46 | } |
| 47 | | 47 | |
| | 48 | static const char * ASYNC_ALLOC_FIELD_NAME = "allocFn"; |
| | 49 | //static const char * ASYNC_FREE_FIELD_NAME = "freeFn"; |
| | 50 | |
| 48 | enum ConstCastResultId { | 51 | enum ConstCastResultId { |
| 49 | ConstCastResultIdOk, | 52 | ConstCastResultIdOk, |
| 50 | ConstCastResultIdErrSet, | 53 | ConstCastResultIdErrSet, |
| ... | @@ -649,6 +652,22 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionGetImplicitAlloc | ... | @@ -649,6 +652,22 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionGetImplicitAlloc |
| 649 | return IrInstructionIdGetImplicitAllocator; | 652 | return IrInstructionIdGetImplicitAllocator; |
| 650 | } | 653 | } |
| 651 | | 654 | |
| | 655 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroId *) { |
| | 656 | return IrInstructionIdCoroId; |
| | 657 | } |
| | 658 | |
| | 659 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroAlloc *) { |
| | 660 | return IrInstructionIdCoroAlloc; |
| | 661 | } |
| | 662 | |
| | 663 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroSize *) { |
| | 664 | return IrInstructionIdCoroSize; |
| | 665 | } |
| | 666 | |
| | 667 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroBegin *) { |
| | 668 | return IrInstructionIdCoroBegin; |
| | 669 | } |
| | 670 | |
| 652 | template<typename T> | 671 | template<typename T> |
| 653 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 672 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 654 | T *special_instruction = allocate<T>(1); | 673 | T *special_instruction = allocate<T>(1); |
| ... | @@ -2420,6 +2439,38 @@ static IrInstruction *ir_build_get_implicit_allocator(IrBuilder *irb, Scope *sco | ... | @@ -2420,6 +2439,38 @@ static IrInstruction *ir_build_get_implicit_allocator(IrBuilder *irb, Scope *sco |
| 2420 | return &instruction->base; | 2439 | return &instruction->base; |
| 2421 | } | 2440 | } |
| 2422 | | 2441 | |
| | 2442 | static IrInstruction *ir_build_coro_id(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| | 2443 | IrInstructionCoroId *instruction = ir_build_instruction<IrInstructionCoroId>(irb, scope, source_node); |
| | 2444 | |
| | 2445 | return &instruction->base; |
| | 2446 | } |
| | 2447 | |
| | 2448 | static IrInstruction *ir_build_coro_alloc(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *coro_id) { |
| | 2449 | IrInstructionCoroAlloc *instruction = ir_build_instruction<IrInstructionCoroAlloc>(irb, scope, source_node); |
| | 2450 | instruction->coro_id = coro_id; |
| | 2451 | |
| | 2452 | ir_ref_instruction(coro_id, irb->current_basic_block); |
| | 2453 | |
| | 2454 | return &instruction->base; |
| | 2455 | } |
| | 2456 | |
| | 2457 | static IrInstruction *ir_build_coro_size(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| | 2458 | IrInstructionCoroSize *instruction = ir_build_instruction<IrInstructionCoroSize>(irb, scope, source_node); |
| | 2459 | |
| | 2460 | return &instruction->base; |
| | 2461 | } |
| | 2462 | |
| | 2463 | static IrInstruction *ir_build_coro_begin(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *coro_id, IrInstruction *coro_mem_ptr) { |
| | 2464 | IrInstructionCoroBegin *instruction = ir_build_instruction<IrInstructionCoroBegin>(irb, scope, source_node); |
| | 2465 | instruction->coro_id = coro_id; |
| | 2466 | instruction->coro_mem_ptr = coro_mem_ptr; |
| | 2467 | |
| | 2468 | ir_ref_instruction(coro_id, irb->current_basic_block); |
| | 2469 | ir_ref_instruction(coro_mem_ptr, irb->current_basic_block); |
| | 2470 | |
| | 2471 | return &instruction->base; |
| | 2472 | } |
| | 2473 | |
| 2423 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { | 2474 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 2424 | results[ReturnKindUnconditional] = 0; | 2475 | results[ReturnKindUnconditional] = 0; |
| 2425 | results[ReturnKindError] = 0; | 2476 | results[ReturnKindError] = 0; |
| ... | @@ -5782,6 +5833,63 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec | ... | @@ -5782,6 +5833,63 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec |
| 5782 | // Entry block gets a reference because we enter it to begin. | 5833 | // Entry block gets a reference because we enter it to begin. |
| 5783 | ir_ref_bb(irb->current_basic_block); | 5834 | ir_ref_bb(irb->current_basic_block); |
| 5784 | | 5835 | |
| | 5836 | FnTableEntry *fn_entry = exec_fn_entry(irb->exec); |
| | 5837 | bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync; |
| | 5838 | if (is_async) { |
| | 5839 | IrInstruction *is_comptime_false = ir_build_const_bool(irb, scope, node, false); |
| | 5840 | IrInstruction *coro_id = ir_build_coro_id(irb, scope, node); |
| | 5841 | IrInstruction *need_dyn_alloc = ir_build_coro_alloc(irb, scope, node, coro_id); |
| | 5842 | IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0); |
| | 5843 | IrInstruction *u8_ptr_type = ir_build_const_type(irb, scope, node, |
| | 5844 | get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false)); |
| | 5845 | IrInstruction *null_ptr = ir_build_int_to_ptr(irb, scope, node, u8_ptr_type, zero); |
| | 5846 | |
| | 5847 | IrBasicBlock *dyn_alloc_block = ir_create_basic_block(irb, scope, "DynAlloc"); |
| | 5848 | IrBasicBlock *coro_begin_block = ir_create_basic_block(irb, scope, "CoroBegin"); |
| | 5849 | ir_build_cond_br(irb, scope, node, need_dyn_alloc, dyn_alloc_block, coro_begin_block, is_comptime_false); |
| | 5850 | |
| | 5851 | ir_set_cursor_at_end_and_append_block(irb, dyn_alloc_block); |
| | 5852 | IrInstruction *coro_size = ir_build_coro_size(irb, scope, node); |
| | 5853 | IrInstruction *implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node); |
| | 5854 | Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME); |
| | 5855 | IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, scope, node, implicit_allocator_ptr, alloc_field_name); |
| | 5856 | IrInstruction *alloc_fn = ir_build_load_ptr(irb, scope, node, alloc_fn_ptr); |
| | 5857 | IrInstruction *implicit_allocator = ir_build_load_ptr(irb, scope, node, implicit_allocator_ptr); |
| | 5858 | IrInstruction *alignment = ir_build_const_usize(irb, scope, node, irb->codegen->pointer_size_bytes * 2); |
| | 5859 | size_t arg_count = 3; |
| | 5860 | IrInstruction **args = allocate<IrInstruction *>(arg_count); |
| | 5861 | args[0] = implicit_allocator; // self |
| | 5862 | args[1] = coro_size; // byte_count |
| | 5863 | args[2] = alignment; // alignment |
| | 5864 | IrInstruction *alloc_result = ir_build_call(irb, scope, node, nullptr, alloc_fn, arg_count, args, false, FnInlineAuto, false, nullptr); |
| | 5865 | IrInstruction *alloc_result_ptr = ir_build_ref(irb, scope, node, alloc_result, true, false); |
| | 5866 | IrInstruction *alloc_result_is_err = ir_build_test_err(irb, scope, node, alloc_result_ptr); |
| | 5867 | IrBasicBlock *alloc_err_block = ir_create_basic_block(irb, scope, "AllocError"); |
| | 5868 | IrBasicBlock *alloc_ok_block = ir_create_basic_block(irb, scope, "AllocOk"); |
| | 5869 | ir_build_cond_br(irb, scope, node, alloc_result_is_err, alloc_err_block, alloc_ok_block, is_comptime_false); |
| | 5870 | |
| | 5871 | ir_set_cursor_at_end_and_append_block(irb, alloc_err_block); |
| | 5872 | IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, alloc_result_ptr); |
| | 5873 | ir_build_return(irb, scope, node, err_val); |
| | 5874 | |
| | 5875 | ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block); |
| | 5876 | IrInstruction *unwrapped_mem_ptr = ir_build_unwrap_err_payload(irb, scope, node, alloc_result_ptr, false); |
| | 5877 | Buf *ptr_field_name = buf_create_from_str("ptr"); |
| | 5878 | IrInstruction *coro_mem_ptr_field = ir_build_field_ptr(irb, scope, node, unwrapped_mem_ptr, ptr_field_name); |
| | 5879 | IrInstruction *coro_mem_ptr = ir_build_load_ptr(irb, scope, node, coro_mem_ptr_field); |
| | 5880 | ir_build_br(irb, scope, node, coro_begin_block, is_comptime_false); |
| | 5881 | |
| | 5882 | ir_set_cursor_at_end_and_append_block(irb, coro_begin_block); |
| | 5883 | IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2); |
| | 5884 | IrInstruction **incoming_values = allocate<IrInstruction *>(2); |
| | 5885 | incoming_blocks[0] = entry_block; |
| | 5886 | incoming_values[0] = null_ptr; |
| | 5887 | incoming_blocks[1] = dyn_alloc_block; |
| | 5888 | incoming_values[1] = coro_mem_ptr; |
| | 5889 | IrInstruction *coro_mem = ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values); |
| | 5890 | irb->exec->coro_handle = ir_build_coro_begin(irb, scope, node, coro_id, coro_mem); |
| | 5891 | } |
| | 5892 | |
| 5785 | IrInstruction *result = ir_gen_node_extra(irb, node, scope, LVAL_NONE); | 5893 | IrInstruction *result = ir_gen_node_extra(irb, node, scope, LVAL_NONE); |
| 5786 | assert(result); | 5894 | assert(result); |
| 5787 | if (irb->exec->invalid) | 5895 | if (irb->exec->invalid) |
| ... | @@ -10805,7 +10913,7 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i | ... | @@ -10805,7 +10913,7 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i |
| 10805 | static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, FnTableEntry *fn_entry, TypeTableEntry *fn_type, | 10913 | static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, FnTableEntry *fn_entry, TypeTableEntry *fn_type, |
| 10806 | IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count, IrInstruction *async_allocator_inst) | 10914 | IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count, IrInstruction *async_allocator_inst) |
| 10807 | { | 10915 | { |
| 10808 | Buf *alloc_field_name = buf_create_from_str("allocFn"); | 10916 | Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME); |
| 10809 | //Buf *free_field_name = buf_create_from_str("freeFn"); | 10917 | //Buf *free_field_name = buf_create_from_str("freeFn"); |
| 10810 | assert(async_allocator_inst->value.type->id == TypeTableEntryIdPointer); | 10918 | assert(async_allocator_inst->value.type->id == TypeTableEntryIdPointer); |
| 10811 | TypeTableEntry *container_type = async_allocator_inst->value.type->data.pointer.child_type; | 10919 | TypeTableEntry *container_type = async_allocator_inst->value.type->data.pointer.child_type; |
| ... | @@ -16692,6 +16800,22 @@ static TypeTableEntry *ir_analyze_instruction_cancel(IrAnalyze *ira, IrInstructi | ... | @@ -16692,6 +16800,22 @@ static TypeTableEntry *ir_analyze_instruction_cancel(IrAnalyze *ira, IrInstructi |
| 16692 | return result->value.type; | 16800 | return result->value.type; |
| 16693 | } | 16801 | } |
| 16694 | | 16802 | |
| | 16803 | static TypeTableEntry *ir_analyze_instruction_coro_id(IrAnalyze *ira, IrInstructionCoroId *instruction) { |
| | 16804 | zig_panic("TODO ir_analyze_instruction_coro_id"); |
| | 16805 | } |
| | 16806 | |
| | 16807 | static TypeTableEntry *ir_analyze_instruction_coro_alloc(IrAnalyze *ira, IrInstructionCoroAlloc *instruction) { |
| | 16808 | zig_panic("TODO ir_analyze_instruction_coro_alloc"); |
| | 16809 | } |
| | 16810 | |
| | 16811 | static TypeTableEntry *ir_analyze_instruction_coro_size(IrAnalyze *ira, IrInstructionCoroSize *instruction) { |
| | 16812 | zig_panic("TODO ir_analyze_instruction_coro_size"); |
| | 16813 | } |
| | 16814 | |
| | 16815 | static TypeTableEntry *ir_analyze_instruction_coro_begin(IrAnalyze *ira, IrInstructionCoroBegin *instruction) { |
| | 16816 | zig_panic("TODO ir_analyze_instruction_coro_begin"); |
| | 16817 | } |
| | 16818 | |
| 16695 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { | 16819 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 16696 | switch (instruction->id) { | 16820 | switch (instruction->id) { |
| 16697 | case IrInstructionIdInvalid: | 16821 | case IrInstructionIdInvalid: |
| ... | @@ -16897,6 +17021,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -16897,6 +17021,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 16897 | return ir_analyze_instruction_error_union(ira, (IrInstructionErrorUnion *)instruction); | 17021 | return ir_analyze_instruction_error_union(ira, (IrInstructionErrorUnion *)instruction); |
| 16898 | case IrInstructionIdCancel: | 17022 | case IrInstructionIdCancel: |
| 16899 | return ir_analyze_instruction_cancel(ira, (IrInstructionCancel *)instruction); | 17023 | return ir_analyze_instruction_cancel(ira, (IrInstructionCancel *)instruction); |
| | 17024 | case IrInstructionIdCoroId: |
| | 17025 | return ir_analyze_instruction_coro_id(ira, (IrInstructionCoroId *)instruction); |
| | 17026 | case IrInstructionIdCoroAlloc: |
| | 17027 | return ir_analyze_instruction_coro_alloc(ira, (IrInstructionCoroAlloc *)instruction); |
| | 17028 | case IrInstructionIdCoroSize: |
| | 17029 | return ir_analyze_instruction_coro_size(ira, (IrInstructionCoroSize *)instruction); |
| | 17030 | case IrInstructionIdCoroBegin: |
| | 17031 | return ir_analyze_instruction_coro_begin(ira, (IrInstructionCoroBegin *)instruction); |
| 16900 | } | 17032 | } |
| 16901 | zig_unreachable(); | 17033 | zig_unreachable(); |
| 16902 | } | 17034 | } |
| ... | @@ -17011,6 +17143,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -17011,6 +17143,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 17011 | case IrInstructionIdSetAlignStack: | 17143 | case IrInstructionIdSetAlignStack: |
| 17012 | case IrInstructionIdExport: | 17144 | case IrInstructionIdExport: |
| 17013 | case IrInstructionIdCancel: | 17145 | case IrInstructionIdCancel: |
| | 17146 | case IrInstructionIdCoroId: |
| | 17147 | case IrInstructionIdCoroBegin: |
| 17014 | return true; | 17148 | return true; |
| 17015 | | 17149 | |
| 17016 | case IrInstructionIdPhi: | 17150 | case IrInstructionIdPhi: |
| ... | @@ -17086,6 +17220,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -17086,6 +17220,8 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 17086 | case IrInstructionIdErrorReturnTrace: | 17220 | case IrInstructionIdErrorReturnTrace: |
| 17087 | case IrInstructionIdErrorUnion: | 17221 | case IrInstructionIdErrorUnion: |
| 17088 | case IrInstructionIdGetImplicitAllocator: | 17222 | case IrInstructionIdGetImplicitAllocator: |
| | 17223 | case IrInstructionIdCoroAlloc: |
| | 17224 | case IrInstructionIdCoroSize: |
| 17089 | return false; | 17225 | return false; |
| 17090 | | 17226 | |
| 17091 | case IrInstructionIdAsm: | 17227 | case IrInstructionIdAsm: |