@@ -412,10 +412,10 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, FnTableEntry *fn_table_e
412
412
return UINT32_MAX;
413
413
}
414
414
TypeTableEntry *fn_type = fn_table_entry->type_entry ;
415
- TypeTableEntry *return_type = fn_type->data .fn .fn_type_id .return_type ;
416
- if (return_type->id != TypeTableEntryIdErrorUnion && return_type->id != TypeTableEntryIdErrorSet) {
415
+ if (!fn_type_can_fail (&fn_type->data .fn .fn_type_id )) {
417
416
return UINT32_MAX;
418
417
}
418
+ TypeTableEntry *return_type = fn_type->data .fn .fn_type_id .return_type ;
419
419
bool first_arg_ret = type_has_bits (return_type) && handle_is_ptr (return_type);
420
420
return first_arg_ret ? 1 : 0 ;
421
421
}
@@ -2662,21 +2662,23 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
2662
2662
}
2663
2663
}
2664
2664
2665
- static bool get_prefix_arg_err_ret_stack (CodeGen *g, TypeTableEntry *src_return_type ) {
2665
+ static bool get_prefix_arg_err_ret_stack (CodeGen *g, FnTypeId *fn_type_id ) {
2666
2666
return g->have_err_ret_tracing &&
2667
- (src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdErrorSet);
2667
+ (fn_type_id->return_type ->id == TypeTableEntryIdErrorUnion ||
2668
+ fn_type_id->return_type ->id == TypeTableEntryIdErrorSet ||
2669
+ fn_type_id->cc == CallingConventionAsync);
2668
2670
}
2669
2671
2670
- static size_t get_async_allocator_arg_index (CodeGen *g, TypeTableEntry *src_return_type ) {
2672
+ static size_t get_async_allocator_arg_index (CodeGen *g, FnTypeId *fn_type_id ) {
2671
2673
// 0 1 2 3
2672
2674
// err_ret_stack allocator_ptr err_code other_args...
2673
- return get_prefix_arg_err_ret_stack (g, src_return_type ) ? 1 : 0 ;
2675
+ return get_prefix_arg_err_ret_stack (g, fn_type_id ) ? 1 : 0 ;
2674
2676
}
2675
2677
2676
- static size_t get_async_err_code_arg_index (CodeGen *g, TypeTableEntry *src_return_type ) {
2678
+ static size_t get_async_err_code_arg_index (CodeGen *g, FnTypeId *fn_type_id ) {
2677
2679
// 0 1 2 3
2678
2680
// err_ret_stack allocator_ptr err_code other_args...
2679
- return 1 + get_async_allocator_arg_index (g, src_return_type );
2681
+ return 1 + get_async_allocator_arg_index (g, fn_type_id );
2680
2682
}
2681
2683
2682
2684
static LLVMValueRef ir_render_call (CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) {
@@ -2698,7 +2700,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
2698
2700
2699
2701
bool first_arg_ret = ret_has_bits && handle_is_ptr (src_return_type) &&
2700
2702
calling_convention_does_first_arg_return (fn_type->data .fn .fn_type_id .cc );
2701
- bool prefix_arg_err_ret_stack = get_prefix_arg_err_ret_stack (g, src_return_type );
2703
+ bool prefix_arg_err_ret_stack = get_prefix_arg_err_ret_stack (g, fn_type_id );
2702
2704
// +2 for the async args
2703
2705
size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0 ) + (prefix_arg_err_ret_stack ? 1 : 0 ) + 2 ;
2704
2706
bool is_var_args = fn_type_id->is_var_args ;
@@ -2717,7 +2719,6 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
2717
2719
gen_param_index += 1 ;
2718
2720
2719
2721
LLVMValueRef err_val_ptr = LLVMBuildStructGEP (g->builder , instruction->tmp_ptr , err_union_err_index, " " );
2720
- LLVMBuildStore (g->builder , LLVMConstNull (g->builtin_types .entry_global_error_set ->type_ref ), err_val_ptr);
2721
2722
gen_param_values[gen_param_index] = err_val_ptr;
2722
2723
gen_param_index += 1 ;
2723
2724
}
@@ -3293,8 +3294,7 @@ static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrIns
3293
3294
static LLVMValueRef ir_render_get_implicit_allocator (CodeGen *g, IrExecutable *executable,
3294
3295
IrInstructionGetImplicitAllocator *instruction)
3295
3296
{
3296
- TypeTableEntry *src_return_type = g->cur_fn ->type_entry ->data .fn .fn_type_id .return_type ;
3297
- size_t allocator_arg_index = get_async_allocator_arg_index (g, src_return_type);
3297
+ size_t allocator_arg_index = get_async_allocator_arg_index (g, &g->cur_fn ->type_entry ->data .fn .fn_type_id );
3298
3298
return LLVMGetParam (g->cur_fn_val , allocator_arg_index);
3299
3299
}
3300
3300
@@ -3926,8 +3926,7 @@ static LLVMValueRef ir_render_coro_begin(CodeGen *g, IrExecutable *executable, I
3926
3926
static LLVMValueRef ir_render_coro_alloc_fail (CodeGen *g, IrExecutable *executable,
3927
3927
IrInstructionCoroAllocFail *instruction)
3928
3928
{
3929
- TypeTableEntry *src_return_type = g->cur_fn ->type_entry ->data .fn .fn_type_id .return_type ;
3930
- size_t err_code_ptr_arg_index = get_async_err_code_arg_index (g, src_return_type);
3929
+ size_t err_code_ptr_arg_index = get_async_err_code_arg_index (g, &g->cur_fn ->type_entry ->data .fn .fn_type_id );
3931
3930
LLVMValueRef err_code_ptr_val = LLVMGetParam (g->cur_fn_val , err_code_ptr_arg_index);
3932
3931
LLVMValueRef err_code = ir_llvm_value (g, instruction->err_val );
3933
3932
LLVMBuildStore (g->builder , err_code, err_code_ptr_val);
@@ -3985,6 +3984,132 @@ static LLVMValueRef ir_render_coro_save(CodeGen *g, IrExecutable *executable, Ir
3985
3984
return LLVMBuildCall (g->builder , get_coro_save_fn_val (g), &coro_handle, 1 , " " );
3986
3985
}
3987
3986
3987
+ static LLVMValueRef get_coro_alloc_helper_fn_val (CodeGen *g, LLVMTypeRef alloc_fn_type_ref, TypeTableEntry *fn_type) {
3988
+ if (g->coro_alloc_helper_fn_val != nullptr )
3989
+ return g->coro_alloc_fn_val ;
3990
+
3991
+ assert (fn_type->id == TypeTableEntryIdFn);
3992
+
3993
+ TypeTableEntry *ptr_to_err_code_type = get_pointer_to_type (g, g->builtin_types .entry_global_error_set , false );
3994
+
3995
+ LLVMTypeRef alloc_raw_fn_type_ref = LLVMGetElementType (alloc_fn_type_ref);
3996
+ LLVMTypeRef *alloc_fn_arg_types = allocate<LLVMTypeRef>(LLVMCountParamTypes (alloc_raw_fn_type_ref));
3997
+ LLVMGetParamTypes (alloc_raw_fn_type_ref, alloc_fn_arg_types);
3998
+
3999
+ ZigList<LLVMTypeRef> arg_types = {};
4000
+ arg_types.append (alloc_fn_type_ref);
4001
+ if (g->have_err_ret_tracing ) {
4002
+ arg_types.append (alloc_fn_arg_types[1 ]);
4003
+ }
4004
+ arg_types.append (alloc_fn_arg_types[g->have_err_ret_tracing ? 2 : 1 ]);
4005
+ arg_types.append (ptr_to_err_code_type->type_ref );
4006
+ arg_types.append (g->builtin_types .entry_usize ->type_ref );
4007
+
4008
+ LLVMTypeRef fn_type_ref = LLVMFunctionType (LLVMPointerType (LLVMInt8Type (), 0 ),
4009
+ arg_types.items , arg_types.length , false );
4010
+
4011
+ Buf *fn_name = get_mangled_name (g, buf_create_from_str (" __zig_coro_alloc_helper" ), false );
4012
+ LLVMValueRef fn_val = LLVMAddFunction (g->module , buf_ptr (fn_name), fn_type_ref);
4013
+ LLVMSetLinkage (fn_val, LLVMInternalLinkage);
4014
+ LLVMSetFunctionCallConv (fn_val, get_llvm_cc (g, CallingConventionUnspecified));
4015
+ addLLVMFnAttr (fn_val, " nounwind" );
4016
+ addLLVMArgAttr (fn_val, (unsigned )0 , " nonnull" );
4017
+ addLLVMArgAttr (fn_val, (unsigned )1 , " nonnull" );
4018
+
4019
+ LLVMBasicBlockRef prev_block = LLVMGetInsertBlock (g->builder );
4020
+ LLVMValueRef prev_debug_location = LLVMGetCurrentDebugLocation (g->builder );
4021
+ FnTableEntry *prev_cur_fn = g->cur_fn ;
4022
+ LLVMValueRef prev_cur_fn_val = g->cur_fn_val ;
4023
+
4024
+ LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock (fn_val, " Entry" );
4025
+ LLVMPositionBuilderAtEnd (g->builder , entry_block);
4026
+ ZigLLVMClearCurrentDebugLocation (g->builder );
4027
+ g->cur_fn = nullptr ;
4028
+ g->cur_fn_val = fn_val;
4029
+
4030
+ LLVMValueRef sret_ptr = LLVMBuildAlloca (g->builder , LLVMGetElementType (alloc_fn_arg_types[0 ]), " " );
4031
+
4032
+ size_t next_arg = 0 ;
4033
+ LLVMValueRef alloc_fn_val = LLVMGetParam (fn_val, next_arg);
4034
+ next_arg += 1 ;
4035
+
4036
+ LLVMValueRef stack_trace_val;
4037
+ if (g->have_err_ret_tracing ) {
4038
+ stack_trace_val = LLVMGetParam (fn_val, next_arg);
4039
+ next_arg += 1 ;
4040
+ }
4041
+
4042
+ LLVMValueRef allocator_val = LLVMGetParam (fn_val, next_arg);
4043
+ next_arg += 1 ;
4044
+ LLVMValueRef err_code_ptr = LLVMGetParam (fn_val, next_arg);
4045
+ next_arg += 1 ;
4046
+ LLVMValueRef coro_size = LLVMGetParam (fn_val, next_arg);
4047
+ next_arg += 1 ;
4048
+ LLVMValueRef alignment_val = LLVMConstInt (g->builtin_types .entry_u29 ->type_ref ,
4049
+ 2 * g->pointer_size_bytes , false );
4050
+
4051
+ ZigList<LLVMValueRef> args = {};
4052
+ args.append (sret_ptr);
4053
+ if (g->have_err_ret_tracing ) {
4054
+ args.append (stack_trace_val);
4055
+ }
4056
+ args.append (allocator_val);
4057
+ args.append (coro_size);
4058
+ args.append (alignment_val);
4059
+ ZigLLVMBuildCall (g->builder , alloc_fn_val, args.items , args.length ,
4060
+ get_llvm_cc (g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, " " );
4061
+ LLVMValueRef err_val_ptr = LLVMBuildStructGEP (g->builder , sret_ptr, err_union_err_index, " " );
4062
+ LLVMValueRef err_val = LLVMBuildLoad (g->builder , err_val_ptr, " " );
4063
+ LLVMBuildStore (g->builder , err_val, err_code_ptr);
4064
+ LLVMValueRef ok_bit = LLVMBuildICmp (g->builder , LLVMIntEQ, err_val, LLVMConstNull (LLVMTypeOf (err_val)), " " );
4065
+ LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock (fn_val, " AllocOk" );
4066
+ LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock (fn_val, " AllocFail" );
4067
+ LLVMBuildCondBr (g->builder , ok_bit, ok_block, fail_block);
4068
+
4069
+ LLVMPositionBuilderAtEnd (g->builder , ok_block);
4070
+ LLVMValueRef payload_ptr = LLVMBuildStructGEP (g->builder , sret_ptr, err_union_payload_index, " " );
4071
+ TypeTableEntry *u8_ptr_type = get_pointer_to_type (g, g->builtin_types .entry_u8 , false );
4072
+ TypeTableEntry *slice_type = get_slice_type (g, u8_ptr_type);
4073
+ size_t ptr_field_index = slice_type->data .structure .fields [slice_ptr_index].gen_index ;
4074
+ LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP (g->builder , payload_ptr, ptr_field_index, " " );
4075
+ LLVMValueRef ptr_val = LLVMBuildLoad (g->builder , ptr_field_ptr, " " );
4076
+ LLVMBuildRet (g->builder , ptr_val);
4077
+
4078
+ LLVMPositionBuilderAtEnd (g->builder , fail_block);
4079
+ LLVMBuildRet (g->builder , LLVMConstNull (LLVMPointerType (LLVMInt8Type (), 0 )));
4080
+
4081
+ g->cur_fn = prev_cur_fn;
4082
+ g->cur_fn_val = prev_cur_fn_val;
4083
+ LLVMPositionBuilderAtEnd (g->builder , prev_block);
4084
+ LLVMSetCurrentDebugLocation (g->builder , prev_debug_location);
4085
+
4086
+ g->coro_alloc_helper_fn_val = fn_val;
4087
+ return fn_val;
4088
+ }
4089
+
4090
+ static LLVMValueRef ir_render_coro_alloc_helper (CodeGen *g, IrExecutable *executable,
4091
+ IrInstructionCoroAllocHelper *instruction)
4092
+ {
4093
+ LLVMValueRef alloc_fn = ir_llvm_value (g, instruction->alloc_fn );
4094
+ LLVMValueRef coro_size = ir_llvm_value (g, instruction->coro_size );
4095
+ LLVMValueRef fn_val = get_coro_alloc_helper_fn_val (g, LLVMTypeOf (alloc_fn), instruction->alloc_fn ->value .type );
4096
+ size_t err_code_ptr_arg_index = get_async_err_code_arg_index (g, &g->cur_fn ->type_entry ->data .fn .fn_type_id );
4097
+ size_t allocator_arg_index = get_async_allocator_arg_index (g, &g->cur_fn ->type_entry ->data .fn .fn_type_id );
4098
+
4099
+ ZigList<LLVMValueRef> params = {};
4100
+ params.append (alloc_fn);
4101
+ uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index (g, g->cur_fn );
4102
+ if (err_ret_trace_arg_index != UINT32_MAX) {
4103
+ params.append (LLVMGetParam (g->cur_fn_val , err_ret_trace_arg_index));
4104
+ }
4105
+ params.append (LLVMGetParam (g->cur_fn_val , allocator_arg_index));
4106
+ params.append (LLVMGetParam (g->cur_fn_val , err_code_ptr_arg_index));
4107
+ params.append (coro_size);
4108
+
4109
+ return ZigLLVMBuildCall (g->builder , fn_val, params.items , params.length ,
4110
+ get_llvm_cc (g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, " " );
4111
+ }
4112
+
3988
4113
static void set_debug_location (CodeGen *g, IrInstruction *instruction) {
3989
4114
AstNode *source_node = instruction->source_node ;
3990
4115
Scope *scope = instruction->scope ;
@@ -4190,6 +4315,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
4190
4315
return ir_render_coro_resume (g, executable, (IrInstructionCoroResume *)instruction);
4191
4316
case IrInstructionIdCoroSave:
4192
4317
return ir_render_coro_save (g, executable, (IrInstructionCoroSave *)instruction);
4318
+ case IrInstructionIdCoroAllocHelper:
4319
+ return ir_render_coro_alloc_helper (g, executable, (IrInstructionCoroAllocHelper *)instruction);
4193
4320
}
4194
4321
zig_unreachable ();
4195
4322
}
0 commit comments