@@ -45,6 +45,9 @@ static LVal make_lval_addr(bool is_const, bool is_volatile) {
45
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
51
enum ConstCastResultId {
49
52
ConstCastResultIdOk,
50
53
ConstCastResultIdErrSet,
@@ -649,6 +652,22 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionGetImplicitAlloc
649
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
671
template<typename T>
653
672
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
654
673
T *special_instruction = allocate<T>(1);
@@ -2420,6 +2439,38 @@ static IrInstruction *ir_build_get_implicit_allocator(IrBuilder *irb, Scope *sco
2420
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
2474
static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
2424
2475
results[ReturnKindUnconditional] = 0;
2425
2476
results[ReturnKindError] = 0;
@@ -5782,6 +5833,63 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
5782
5833
// Entry block gets a reference because we enter it to begin.
5783
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
5893
IrInstruction *result = ir_gen_node_extra(irb, node, scope, LVAL_NONE);
5786
5894
assert(result);
5787
5895
if (irb->exec->invalid)
@@ -10805,7 +10913,7 @@ IrInstruction *ir_get_implicit_allocator(IrAnalyze *ira, IrInstruction *source_i
10805
10913
static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCall *call_instruction, FnTableEntry *fn_entry, TypeTableEntry *fn_type,
10806
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
10917
//Buf *free_field_name = buf_create_from_str("freeFn");
10810
10918
assert(async_allocator_inst->value.type->id == TypeTableEntryIdPointer);
10811
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
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
16819
static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
16696
16820
switch (instruction->id) {
16697
16821
case IrInstructionIdInvalid:
@@ -16897,6 +17021,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
16897
17021
return ir_analyze_instruction_error_union(ira, (IrInstructionErrorUnion *)instruction);
16898
17022
case IrInstructionIdCancel:
16899
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
17033
zig_unreachable();
16902
17034
}
@@ -17011,6 +17143,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
17011
17143
case IrInstructionIdSetAlignStack:
17012
17144
case IrInstructionIdExport:
17013
17145
case IrInstructionIdCancel:
17146
+ case IrInstructionIdCoroId:
17147
+ case IrInstructionIdCoroBegin:
17014
17148
return true;
17015
17149
17016
17150
case IrInstructionIdPhi:
@@ -17086,6 +17220,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
17086
17220
case IrInstructionIdErrorReturnTrace:
17087
17221
case IrInstructionIdErrorUnion:
17088
17222
case IrInstructionIdGetImplicitAllocator:
17223
+ case IrInstructionIdCoroAlloc:
17224
+ case IrInstructionIdCoroSize:
17089
17225
return false;
17090
17226
17091
17227
case IrInstructionIdAsm:
0 commit comments