authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-25 02:47:31-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-25 02:47:31-05:00
log05bf666eb690d1a1328234cc408960133dba9563
treeebb2780706cb5b84d0502872d321838319bc9d6f
parent40dbcd09da27a271c5d1b0990e712bd2b2bfe68d

codegen for calling an async function

See #727

3 files changed, 49 insertions(+), 9 deletions(-)

src/analyze.cpp+29-5
...@@ -986,20 +986,25 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {...@@ -986,20 +986,25 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
986 if (!skip_debug_info) {986 if (!skip_debug_info) {
987 bool first_arg_return = calling_convention_does_first_arg_return(fn_type_id->cc) &&987 bool first_arg_return = calling_convention_does_first_arg_return(fn_type_id->cc) &&
988 handle_is_ptr(fn_type_id->return_type);988 handle_is_ptr(fn_type_id->return_type);
989 bool is_async = fn_type_id->cc == CallingConventionAsync;
989 bool prefix_arg_error_return_trace = g->have_err_ret_tracing &&990 bool prefix_arg_error_return_trace = g->have_err_ret_tracing &&
990 (fn_type_id->return_type->id == TypeTableEntryIdErrorUnion || 991 (fn_type_id->return_type->id == TypeTableEntryIdErrorUnion ||
991 fn_type_id->return_type->id == TypeTableEntryIdErrorSet);992 fn_type_id->return_type->id == TypeTableEntryIdErrorSet);
992 // +1 for maybe making the first argument the return value993 // +1 for maybe making the first argument the return value
993 // +1 for maybe last argument the error return trace994 // +1 for maybe first argument the error return trace
994 LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(2 + fn_type_id->param_count);995 // +2 for maybe arguments async allocator and error code pointer
996 LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(4 + fn_type_id->param_count);
995 // +1 because 0 is the return type and997 // +1 because 0 is the return type and
996 // +1 for maybe making first arg ret val and998 // +1 for maybe making first arg ret val and
997 // +1 for maybe last argument the error return trace999 // +1 for maybe first argument the error return trace
998 ZigLLVMDIType **param_di_types = allocate<ZigLLVMDIType*>(3 + fn_type_id->param_count);1000 // +2 for maybe arguments async allocator and error code pointer
1001 ZigLLVMDIType **param_di_types = allocate<ZigLLVMDIType*>(5 + fn_type_id->param_count);
999 param_di_types[0] = fn_type_id->return_type->di_type;1002 param_di_types[0] = fn_type_id->return_type->di_type;
1000 size_t gen_param_index = 0;1003 size_t gen_param_index = 0;
1001 TypeTableEntry *gen_return_type;1004 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)) {
1003 gen_return_type = g->builtin_types.entry_void;1008 gen_return_type = g->builtin_types.entry_void;
1004 } else if (first_arg_return) {1009 } else if (first_arg_return) {
1005 TypeTableEntry *gen_type = get_pointer_to_type(g, fn_type_id->return_type, false);1010 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) {...@@ -1020,6 +1025,25 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
1020 // after the gen_param_index += 1 because 0 is the return type1025 // after the gen_param_index += 1 because 0 is the return type
1021 param_di_types[gen_param_index] = gen_type->di_type;1026 param_di_types[gen_param_index] = gen_type->di_type;
1022 }1027 }
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
1024 fn_type->data.fn.gen_param_info = allocate<FnGenParamInfo>(fn_type_id->param_count);1048 fn_type->data.fn.gen_param_info = allocate<FnGenParamInfo>(fn_type_id->param_count);
1025 for (size_t i = 0; i < fn_type_id->param_count; i += 1) {1049 for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
src/codegen.cpp+18-4
...@@ -2521,13 +2521,12 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -2521,13 +2521,12 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
2521 }2521 }
25222522
2523 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;2523 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
2528 TypeTableEntry *src_return_type = fn_type_id->return_type;2525 TypeTableEntry *src_return_type = fn_type_id->return_type;
2529 bool ret_has_bits = type_has_bits(src_return_type);2526 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);
2531 bool prefix_arg_err_ret_stack = g->have_err_ret_tracing && (src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdErrorSet);2530 bool prefix_arg_err_ret_stack = g->have_err_ret_tracing && (src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdErrorSet);
2532 size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0);2531 size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0);
2533 bool is_var_args = fn_type_id->is_var_args;2532 bool is_var_args = fn_type_id->is_var_args;
...@@ -2541,6 +2540,15 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -2541,6 +2540,15 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
2541 gen_param_values[gen_param_index] = g->cur_err_ret_trace_val;2540 gen_param_values[gen_param_index] = g->cur_err_ret_trace_val;
2542 gen_param_index += 1;2541 gen_param_index += 1;
2543 }2542 }
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 }
2544 for (size_t call_i = 0; call_i < instruction->arg_count; call_i += 1) {2552 for (size_t call_i = 0; call_i < instruction->arg_count; call_i += 1) {
2545 IrInstruction *param_instruction = instruction->args[call_i];2553 IrInstruction *param_instruction = instruction->args[call_i];
2546 TypeTableEntry *param_type = param_instruction->value.type;2554 TypeTableEntry *param_type = param_instruction->value.type;
...@@ -2578,6 +2586,12 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -2578,6 +2586,12 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
2578 }2586 }
2579 }2587 }
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
2581 if (src_return_type->id == TypeTableEntryIdUnreachable) {2595 if (src_return_type->id == TypeTableEntryIdUnreachable) {
2582 return LLVMBuildUnreachable(g->builder);2596 return LLVMBuildUnreachable(g->builder);
2583 } else if (!ret_has_bits) {2597 } else if (!ret_has_bits) {
src/ir.cpp+2
...@@ -11775,6 +11775,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal...@@ -11775,6 +11775,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
11775 if (call_instruction->is_async) {11775 if (call_instruction->is_async) {
11776 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);11776 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);
11777 ir_link_new_instruction(result, &call_instruction->base);11777 ir_link_new_instruction(result, &call_instruction->base);
11778 ir_add_alloca(ira, result, result->value.type);
11778 return ir_finish_anal(ira, result->value.type);11779 return ir_finish_anal(ira, result->value.type);
11779 }11780 }
1178011781
...@@ -11862,6 +11863,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal...@@ -11862,6 +11863,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
1186211863
11863 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref, casted_args, call_param_count, async_allocator_inst);11864 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref, casted_args, call_param_count, async_allocator_inst);
11864 ir_link_new_instruction(result, &call_instruction->base);11865 ir_link_new_instruction(result, &call_instruction->base);
11866 ir_add_alloca(ira, result, result->value.type);
11865 return ir_finish_anal(ira, result->value.type);11867 return ir_finish_anal(ira, result->value.type);
11866 }11868 }
1186711869