Skip to content

Commit 05bf666

Browse files
committed
codegen for calling an async function
See #727
1 parent 40dbcd0 commit 05bf666

File tree

3 files changed

+49
-9
lines changed

3 files changed

+49
-9
lines changed

src/analyze.cpp

+29-5
Original file line numberDiff line numberDiff line change
@@ -986,20 +986,25 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
986986
if (!skip_debug_info) {
987987
bool first_arg_return = calling_convention_does_first_arg_return(fn_type_id->cc) &&
988988
handle_is_ptr(fn_type_id->return_type);
989+
bool is_async = fn_type_id->cc == CallingConventionAsync;
989990
bool prefix_arg_error_return_trace = g->have_err_ret_tracing &&
990991
(fn_type_id->return_type->id == TypeTableEntryIdErrorUnion ||
991992
fn_type_id->return_type->id == TypeTableEntryIdErrorSet);
992993
// +1 for maybe making the first argument the return value
993-
// +1 for maybe last argument the error return trace
994-
LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(2 + fn_type_id->param_count);
994+
// +1 for maybe first argument the error return trace
995+
// +2 for maybe arguments async allocator and error code pointer
996+
LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(4 + fn_type_id->param_count);
995997
// +1 because 0 is the return type and
996998
// +1 for maybe making first arg ret val and
997-
// +1 for maybe last argument the error return trace
998-
ZigLLVMDIType **param_di_types = allocate<ZigLLVMDIType*>(3 + fn_type_id->param_count);
999+
// +1 for maybe first argument the error return trace
1000+
// +2 for maybe arguments async allocator and error code pointer
1001+
ZigLLVMDIType **param_di_types = allocate<ZigLLVMDIType*>(5 + fn_type_id->param_count);
9991002
param_di_types[0] = fn_type_id->return_type->di_type;
10001003
size_t gen_param_index = 0;
10011004
TypeTableEntry *gen_return_type;
1002-
if (!type_has_bits(fn_type_id->return_type)) {
1005+
if (is_async) {
1006+
gen_return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, false);
1007+
} else if (!type_has_bits(fn_type_id->return_type)) {
10031008
gen_return_type = g->builtin_types.entry_void;
10041009
} else if (first_arg_return) {
10051010
TypeTableEntry *gen_type = get_pointer_to_type(g, fn_type_id->return_type, false);
@@ -1020,6 +1025,25 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
10201025
// after the gen_param_index += 1 because 0 is the return type
10211026
param_di_types[gen_param_index] = gen_type->di_type;
10221027
}
1028+
if (is_async) {
1029+
{
1030+
// async allocator param
1031+
TypeTableEntry *gen_type = fn_type_id->async_allocator_type;
1032+
gen_param_types[gen_param_index] = gen_type->type_ref;
1033+
gen_param_index += 1;
1034+
// after the gen_param_index += 1 because 0 is the return type
1035+
param_di_types[gen_param_index] = gen_type->di_type;
1036+
}
1037+
1038+
{
1039+
// error code pointer
1040+
TypeTableEntry *gen_type = get_pointer_to_type(g, g->builtin_types.entry_global_error_set, false);
1041+
gen_param_types[gen_param_index] = gen_type->type_ref;
1042+
gen_param_index += 1;
1043+
// after the gen_param_index += 1 because 0 is the return type
1044+
param_di_types[gen_param_index] = gen_type->di_type;
1045+
}
1046+
}
10231047

10241048
fn_type->data.fn.gen_param_info = allocate<FnGenParamInfo>(fn_type_id->param_count);
10251049
for (size_t i = 0; i < fn_type_id->param_count; i += 1) {

src/codegen.cpp

+18-4
Original file line numberDiff line numberDiff line change
@@ -2521,13 +2521,12 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
25212521
}
25222522

25232523
FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
2524-
if (fn_type_id->cc == CallingConventionAsync) {
2525-
zig_panic("TODO codegen async function call");
2526-
}
25272524

25282525
TypeTableEntry *src_return_type = fn_type_id->return_type;
25292526
bool ret_has_bits = type_has_bits(src_return_type);
2530-
bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type);
2527+
2528+
bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type) &&
2529+
calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc);
25312530
bool prefix_arg_err_ret_stack = g->have_err_ret_tracing && (src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdErrorSet);
25322531
size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0);
25332532
bool is_var_args = fn_type_id->is_var_args;
@@ -2541,6 +2540,15 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
25412540
gen_param_values[gen_param_index] = g->cur_err_ret_trace_val;
25422541
gen_param_index += 1;
25432542
}
2543+
if (instruction->is_async) {
2544+
gen_param_values[gen_param_index] = ir_llvm_value(g, instruction->async_allocator);
2545+
gen_param_index += 1;
2546+
2547+
LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, "");
2548+
LLVMBuildStore(g->builder, LLVMConstNull(g->builtin_types.entry_global_error_set->type_ref), err_val_ptr);
2549+
gen_param_values[gen_param_index] = err_val_ptr;
2550+
gen_param_index += 1;
2551+
}
25442552
for (size_t call_i = 0; call_i < instruction->arg_count; call_i += 1) {
25452553
IrInstruction *param_instruction = instruction->args[call_i];
25462554
TypeTableEntry *param_type = param_instruction->value.type;
@@ -2578,6 +2586,12 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
25782586
}
25792587
}
25802588

2589+
if (instruction->is_async) {
2590+
LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_payload_index, "");
2591+
LLVMBuildStore(g->builder, result, payload_ptr);
2592+
return instruction->tmp_ptr;
2593+
}
2594+
25812595
if (src_return_type->id == TypeTableEntryIdUnreachable) {
25822596
return LLVMBuildUnreachable(g->builder);
25832597
} else if (!ret_has_bits) {

src/ir.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -11775,6 +11775,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1177511775
if (call_instruction->is_async) {
1177611776
IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry, fn_ref, casted_args, impl_param_count, async_allocator_inst);
1177711777
ir_link_new_instruction(result, &call_instruction->base);
11778+
ir_add_alloca(ira, result, result->value.type);
1177811779
return ir_finish_anal(ira, result->value.type);
1177911780
}
1178011781

@@ -11862,6 +11863,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1186211863

1186311864
IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref, casted_args, call_param_count, async_allocator_inst);
1186411865
ir_link_new_instruction(result, &call_instruction->base);
11866+
ir_add_alloca(ira, result, result->value.type);
1186511867
return ir_finish_anal(ira, result->value.type);
1186611868
}
1186711869

0 commit comments

Comments
 (0)