authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-28 04:01:22-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-02-28 04:01:22-05:00
log026aebf2ea567c15eebf9ddb9180f7d0e2ec7a9d
treee01512d7d9883706d207fd701c0b89165f431880
parentd24345386274e3abcbcc676fe65bda127c06ce8e

another workaround for llvm coroutines

this one doesn't work either

6 files changed, 222 insertions(+), 51 deletions(-)

src/all_types.hpp+9
...@@ -1634,6 +1634,7 @@ struct CodeGen {...@@ -1634,6 +1634,7 @@ struct CodeGen {
1634 LLVMValueRef coro_free_fn_val;1634 LLVMValueRef coro_free_fn_val;
1635 LLVMValueRef coro_resume_fn_val;1635 LLVMValueRef coro_resume_fn_val;
1636 LLVMValueRef coro_save_fn_val;1636 LLVMValueRef coro_save_fn_val;
1637 LLVMValueRef coro_alloc_helper_fn_val;
1637 bool error_during_imports;1638 bool error_during_imports;
16381639
1639 const char **clang_argv;1640 const char **clang_argv;
...@@ -2004,6 +2005,7 @@ enum IrInstructionId {...@@ -2004,6 +2005,7 @@ enum IrInstructionId {
2004 IrInstructionIdCoroFree,2005 IrInstructionIdCoroFree,
2005 IrInstructionIdCoroResume,2006 IrInstructionIdCoroResume,
2006 IrInstructionIdCoroSave,2007 IrInstructionIdCoroSave,
2008 IrInstructionIdCoroAllocHelper,
2007};2009};
20082010
2009struct IrInstruction {2011struct IrInstruction {
...@@ -2913,6 +2915,13 @@ struct IrInstructionCoroSave {...@@ -2913,6 +2915,13 @@ struct IrInstructionCoroSave {
2913 IrInstruction *coro_handle;2915 IrInstruction *coro_handle;
2914};2916};
29152917
2918struct IrInstructionCoroAllocHelper {
2919 IrInstruction base;
2920
2921 IrInstruction *alloc_fn;
2922 IrInstruction *coro_size;
2923};
2924
2916static const size_t slice_ptr_index = 0;2925static const size_t slice_ptr_index = 0;
2917static const size_t slice_len_index = 1;2926static const size_t slice_len_index = 1;
29182927
src/analyze.cpp+7-3
...@@ -1001,9 +1001,7 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {...@@ -1001,9 +1001,7 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
1001 bool first_arg_return = calling_convention_does_first_arg_return(fn_type_id->cc) &&1001 bool first_arg_return = calling_convention_does_first_arg_return(fn_type_id->cc) &&
1002 handle_is_ptr(fn_type_id->return_type);1002 handle_is_ptr(fn_type_id->return_type);
1003 bool is_async = fn_type_id->cc == CallingConventionAsync;1003 bool is_async = fn_type_id->cc == CallingConventionAsync;
1004 bool prefix_arg_error_return_trace = g->have_err_ret_tracing &&1004 bool prefix_arg_error_return_trace = g->have_err_ret_tracing && fn_type_can_fail(fn_type_id);
1005 (fn_type_id->return_type->id == TypeTableEntryIdErrorUnion ||
1006 fn_type_id->return_type->id == TypeTableEntryIdErrorSet);
1007 // +1 for maybe making the first argument the return value1005 // +1 for maybe making the first argument the return value
1008 // +1 for maybe first argument the error return trace1006 // +1 for maybe first argument the error return trace
1009 // +2 for maybe arguments async allocator and error code pointer1007 // +2 for maybe arguments async allocator and error code pointer
...@@ -5795,3 +5793,9 @@ bool type_is_global_error_set(TypeTableEntry *err_set_type) {...@@ -5795,3 +5793,9 @@ bool type_is_global_error_set(TypeTableEntry *err_set_type) {
5795uint32_t get_coro_frame_align_bytes(CodeGen *g) {5793uint32_t get_coro_frame_align_bytes(CodeGen *g) {
5796 return g->pointer_size_bytes * 2;5794 return g->pointer_size_bytes * 2;
5797}5795}
5796
5797bool fn_type_can_fail(FnTypeId *fn_type_id) {
5798 TypeTableEntry *return_type = fn_type_id->return_type;
5799 return return_type->id == TypeTableEntryIdErrorUnion || return_type->id == TypeTableEntryIdErrorSet ||
5800 fn_type_id->cc == CallingConventionAsync;
5801}
src/analyze.hpp+1
...@@ -192,5 +192,6 @@ void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry);...@@ -192,5 +192,6 @@ void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry);
192TypeTableEntry *get_auto_err_set_type(CodeGen *g, FnTableEntry *fn_entry);192TypeTableEntry *get_auto_err_set_type(CodeGen *g, FnTableEntry *fn_entry);
193193
194uint32_t get_coro_frame_align_bytes(CodeGen *g);194uint32_t get_coro_frame_align_bytes(CodeGen *g);
195bool fn_type_can_fail(FnTypeId *fn_type_id);
195196
196#endif197#endif
src/codegen.cpp+141-14
...@@ -412,10 +412,10 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, FnTableEntry *fn_table_e...@@ -412,10 +412,10 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, FnTableEntry *fn_table_e
412 return UINT32_MAX;412 return UINT32_MAX;
413 }413 }
414 TypeTableEntry *fn_type = fn_table_entry->type_entry;414 TypeTableEntry *fn_type = fn_table_entry->type_entry;
415 TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;415 if (!fn_type_can_fail(&fn_type->data.fn.fn_type_id)) {
416 if (return_type->id != TypeTableEntryIdErrorUnion && return_type->id != TypeTableEntryIdErrorSet) {
417 return UINT32_MAX;416 return UINT32_MAX;
418 }417 }
418 TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;
419 bool first_arg_ret = type_has_bits(return_type) && handle_is_ptr(return_type);419 bool first_arg_ret = type_has_bits(return_type) && handle_is_ptr(return_type);
420 return first_arg_ret ? 1 : 0;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,21 +2662,23 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
2662 }2662 }
2663}2663}
26642664
2665static bool get_prefix_arg_err_ret_stack(CodeGen *g, TypeTableEntry *src_return_type) {2665static bool get_prefix_arg_err_ret_stack(CodeGen *g, FnTypeId *fn_type_id) {
2666 return g->have_err_ret_tracing &&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}
26692671
2670static size_t get_async_allocator_arg_index(CodeGen *g, TypeTableEntry *src_return_type) {2672static size_t get_async_allocator_arg_index(CodeGen *g, FnTypeId *fn_type_id) {
2671 // 0 1 2 32673 // 0 1 2 3
2672 // err_ret_stack allocator_ptr err_code other_args...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}
26752677
2676static size_t get_async_err_code_arg_index(CodeGen *g, TypeTableEntry *src_return_type) {2678static size_t get_async_err_code_arg_index(CodeGen *g, FnTypeId *fn_type_id) {
2677 // 0 1 2 32679 // 0 1 2 3
2678 // err_ret_stack allocator_ptr err_code other_args...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}
26812683
2682static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) {2684static 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,7 +2700,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
26982700
2699 bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type) &&2701 bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type) &&
2700 calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc);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 // +2 for the async args2704 // +2 for the async args
2703 size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0) + 2;2705 size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0) + 2;
2704 bool is_var_args = fn_type_id->is_var_args;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,7 +2719,6 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
2717 gen_param_index += 1;2719 gen_param_index += 1;
27182720
2719 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, err_union_err_index, "");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 gen_param_values[gen_param_index] = err_val_ptr;2722 gen_param_values[gen_param_index] = err_val_ptr;
2722 gen_param_index += 1;2723 gen_param_index += 1;
2723 }2724 }
...@@ -3293,8 +3294,7 @@ static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrIns...@@ -3293,8 +3294,7 @@ static LLVMValueRef ir_render_cancel(CodeGen *g, IrExecutable *executable, IrIns
3293static LLVMValueRef ir_render_get_implicit_allocator(CodeGen *g, IrExecutable *executable,3294static LLVMValueRef ir_render_get_implicit_allocator(CodeGen *g, IrExecutable *executable,
3294 IrInstructionGetImplicitAllocator *instruction)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, &g->cur_fn->type_entry->data.fn.fn_type_id);
3297 size_t allocator_arg_index = get_async_allocator_arg_index(g, src_return_type);
3298 return LLVMGetParam(g->cur_fn_val, allocator_arg_index);3298 return LLVMGetParam(g->cur_fn_val, allocator_arg_index);
3299}3299}
33003300
...@@ -3926,8 +3926,7 @@ static LLVMValueRef ir_render_coro_begin(CodeGen *g, IrExecutable *executable, I...@@ -3926,8 +3926,7 @@ static LLVMValueRef ir_render_coro_begin(CodeGen *g, IrExecutable *executable, I
3926static LLVMValueRef ir_render_coro_alloc_fail(CodeGen *g, IrExecutable *executable,3926static LLVMValueRef ir_render_coro_alloc_fail(CodeGen *g, IrExecutable *executable,
3927 IrInstructionCoroAllocFail *instruction)3927 IrInstructionCoroAllocFail *instruction)
3928{3928{
3929 TypeTableEntry *src_return_type = g->cur_fn->type_entry->data.fn.fn_type_id.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);
3930 size_t err_code_ptr_arg_index = get_async_err_code_arg_index(g, src_return_type);
3931 LLVMValueRef err_code_ptr_val = LLVMGetParam(g->cur_fn_val, err_code_ptr_arg_index);3930 LLVMValueRef err_code_ptr_val = LLVMGetParam(g->cur_fn_val, err_code_ptr_arg_index);
3932 LLVMValueRef err_code = ir_llvm_value(g, instruction->err_val);3931 LLVMValueRef err_code = ir_llvm_value(g, instruction->err_val);
3933 LLVMBuildStore(g->builder, err_code, err_code_ptr_val);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,6 +3984,132 @@ static LLVMValueRef ir_render_coro_save(CodeGen *g, IrExecutable *executable, Ir
3985 return LLVMBuildCall(g->builder, get_coro_save_fn_val(g), &coro_handle, 1, "");3984 return LLVMBuildCall(g->builder, get_coro_save_fn_val(g), &coro_handle, 1, "");
3986}3985}
39873986
3987static 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
4090static 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
3988static void set_debug_location(CodeGen *g, IrInstruction *instruction) {4113static void set_debug_location(CodeGen *g, IrInstruction *instruction) {
3989 AstNode *source_node = instruction->source_node;4114 AstNode *source_node = instruction->source_node;
3990 Scope *scope = instruction->scope;4115 Scope *scope = instruction->scope;
...@@ -4190,6 +4315,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -4190,6 +4315,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
4190 return ir_render_coro_resume(g, executable, (IrInstructionCoroResume *)instruction);4315 return ir_render_coro_resume(g, executable, (IrInstructionCoroResume *)instruction);
4191 case IrInstructionIdCoroSave:4316 case IrInstructionIdCoroSave:
4192 return ir_render_coro_save(g, executable, (IrInstructionCoroSave *)instruction);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 zig_unreachable();4321 zig_unreachable();
4195}4322}
src/ir.cpp+53-34
...@@ -695,6 +695,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroSave *) {...@@ -695,6 +695,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroSave *) {
695 return IrInstructionIdCoroSave;695 return IrInstructionIdCoroSave;
696}696}
697697
698static constexpr IrInstructionId ir_instruction_id(IrInstructionCoroAllocHelper *) {
699 return IrInstructionIdCoroAllocHelper;
700}
701
698template<typename T>702template<typename T>
699static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {703static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
700 T *special_instruction = allocate<T>(1);704 T *special_instruction = allocate<T>(1);
...@@ -829,14 +833,6 @@ static IrInstruction *ir_build_const_usize(IrBuilder *irb, Scope *scope, AstNode...@@ -829,14 +833,6 @@ static IrInstruction *ir_build_const_usize(IrBuilder *irb, Scope *scope, AstNode
829 return &const_instruction->base;833 return &const_instruction->base;
830}834}
831835
832static IrInstruction *ir_build_const_u29(IrBuilder *irb, Scope *scope, AstNode *source_node, uint32_t value) {
833 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
834 const_instruction->base.value.type = irb->codegen->builtin_types.entry_u29;
835 const_instruction->base.value.special = ConstValSpecialStatic;
836 bigint_init_unsigned(&const_instruction->base.value.data.x_bigint, value);
837 return &const_instruction->base;
838}
839
840static IrInstruction *ir_build_const_u8(IrBuilder *irb, Scope *scope, AstNode *source_node, uint8_t value) {836static IrInstruction *ir_build_const_u8(IrBuilder *irb, Scope *scope, AstNode *source_node, uint8_t value) {
841 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);837 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
842 const_instruction->base.value.type = irb->codegen->builtin_types.entry_u8;838 const_instruction->base.value.type = irb->codegen->builtin_types.entry_u8;
...@@ -2600,6 +2596,19 @@ static IrInstruction *ir_build_coro_save(IrBuilder *irb, Scope *scope, AstNode *...@@ -2600,6 +2596,19 @@ static IrInstruction *ir_build_coro_save(IrBuilder *irb, Scope *scope, AstNode *
2600 return &instruction->base;2596 return &instruction->base;
2601}2597}
26022598
2599static IrInstruction *ir_build_coro_alloc_helper(IrBuilder *irb, Scope *scope, AstNode *source_node,
2600 IrInstruction *alloc_fn, IrInstruction *coro_size)
2601{
2602 IrInstructionCoroAllocHelper *instruction = ir_build_instruction<IrInstructionCoroAllocHelper>(irb, scope, source_node);
2603 instruction->alloc_fn = alloc_fn;
2604 instruction->coro_size = coro_size;
2605
2606 ir_ref_instruction(alloc_fn, irb->current_basic_block);
2607 ir_ref_instruction(coro_size, irb->current_basic_block);
2608
2609 return &instruction->base;
2610}
2611
2603static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {2612static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
2604 results[ReturnKindUnconditional] = 0;2613 results[ReturnKindUnconditional] = 0;
2605 results[ReturnKindError] = 0;2614 results[ReturnKindError] = 0;
...@@ -6074,10 +6083,11 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -6074,10 +6083,11 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
6074 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;6083 bool is_async = fn_entry != nullptr && fn_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync;
6075 IrInstruction *u8_ptr_type;6084 IrInstruction *u8_ptr_type;
6076 IrInstruction *const_bool_false;6085 IrInstruction *const_bool_false;
6077 IrInstruction *coro_unwrapped_mem_ptr;6086 IrInstruction *coro_size;
6078 IrInstruction *coro_id;6087 IrInstruction *coro_id;
6079 IrInstruction *coro_promise_ptr;6088 IrInstruction *coro_promise_ptr;
6080 IrInstruction *coro_result_field_ptr;6089 IrInstruction *coro_result_field_ptr;
6090 IrInstruction *coro_mem_ptr;
6081 TypeTableEntry *return_type;6091 TypeTableEntry *return_type;
6082 Buf *result_ptr_field_name;6092 Buf *result_ptr_field_name;
6083 if (is_async) {6093 if (is_async) {
...@@ -6095,39 +6105,25 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -6095,39 +6105,25 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
6095 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));6105 get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));
6096 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, coro_promise_ptr);6106 IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, coro_promise_ptr);
6097 coro_id = ir_build_coro_id(irb, scope, node, promise_as_u8_ptr);6107 coro_id = ir_build_coro_id(irb, scope, node, promise_as_u8_ptr);
6098 IrInstruction *coro_size = ir_build_coro_size(irb, scope, node);6108 coro_size = ir_build_coro_size(irb, scope, node);
6099 irb->exec->implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node);6109 irb->exec->implicit_allocator_ptr = ir_build_get_implicit_allocator(irb, scope, node);
6100 Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);6110 Buf *alloc_field_name = buf_create_from_str(ASYNC_ALLOC_FIELD_NAME);
6101 IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, scope, node, irb->exec->implicit_allocator_ptr,6111 IrInstruction *alloc_fn_ptr = ir_build_field_ptr(irb, scope, node, irb->exec->implicit_allocator_ptr,
6102 alloc_field_name);6112 alloc_field_name);
6103 IrInstruction *alloc_fn = ir_build_load_ptr(irb, scope, node, alloc_fn_ptr);6113 IrInstruction *alloc_fn = ir_build_load_ptr(irb, scope, node, alloc_fn_ptr);
6104 IrInstruction *alignment = ir_build_const_u29(irb, scope, node,6114 IrInstruction *maybe_coro_mem_ptr = ir_build_coro_alloc_helper(irb, scope, node, alloc_fn, coro_size);
6105 get_coro_frame_align_bytes(irb->codegen));6115 IrInstruction *alloc_result_is_ok = ir_build_test_nonnull(irb, scope, node, maybe_coro_mem_ptr);
6106 size_t arg_count = 3;
6107 IrInstruction **args = allocate<IrInstruction *>(arg_count);
6108 args[0] = irb->exec->implicit_allocator_ptr; // self
6109 args[1] = coro_size; // byte_count
6110 args[2] = alignment; // alignment
6111 IrInstruction *alloc_result = ir_build_call(irb, scope, node, nullptr, alloc_fn, arg_count, args, false,
6112 FnInlineAuto, false, nullptr);
6113 IrInstruction *alloc_result_ptr = ir_build_ref(irb, scope, node, alloc_result, true, false);
6114 IrInstruction *alloc_result_is_err = ir_build_test_err(irb, scope, node, alloc_result);
6115 IrBasicBlock *alloc_err_block = ir_create_basic_block(irb, scope, "AllocError");6116 IrBasicBlock *alloc_err_block = ir_create_basic_block(irb, scope, "AllocError");
6116 IrBasicBlock *alloc_ok_block = ir_create_basic_block(irb, scope, "AllocOk");6117 IrBasicBlock *alloc_ok_block = ir_create_basic_block(irb, scope, "AllocOk");
6117 ir_build_cond_br(irb, scope, node, alloc_result_is_err, alloc_err_block, alloc_ok_block, const_bool_false);6118 ir_build_cond_br(irb, scope, node, alloc_result_is_ok, alloc_ok_block, alloc_err_block, const_bool_false);
61186119
6119 ir_set_cursor_at_end_and_append_block(irb, alloc_err_block);6120 ir_set_cursor_at_end_and_append_block(irb, alloc_err_block);
6120 IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, alloc_result_ptr);6121 IrInstruction *undef = ir_build_const_undefined(irb, scope, node);
6121 ir_build_coro_alloc_fail(irb, scope, node, err_val);6122 ir_build_return(irb, scope, node, undef);
61226123
6123 ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);6124 ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);
6124 coro_unwrapped_mem_ptr = ir_build_unwrap_err_payload(irb, scope, node, alloc_result_ptr, false);6125 coro_mem_ptr = ir_build_ptr_cast(irb, scope, node, u8_ptr_type, maybe_coro_mem_ptr);
6125 Buf *ptr_field_name = buf_create_from_str("ptr");6126 irb->exec->coro_handle = ir_build_coro_begin(irb, scope, node, coro_id, coro_mem_ptr);
6126 IrInstruction *coro_mem_ptr_field = ir_build_field_ptr(irb, scope, node, coro_unwrapped_mem_ptr,
6127 ptr_field_name);
6128 IrInstruction *coro_mem = ir_build_load_ptr(irb, scope, node, coro_mem_ptr_field);
6129
6130 irb->exec->coro_handle = ir_build_coro_begin(irb, scope, node, coro_id, coro_mem);
61316127
6132 Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME);6128 Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME);
6133 irb->exec->coro_awaiter_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,6129 irb->exec->coro_awaiter_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
...@@ -6207,10 +6203,13 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec...@@ -6207,10 +6203,13 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
6207 IrInstruction *free_fn_ptr = ir_build_field_ptr(irb, scope, node, irb->exec->implicit_allocator_ptr,6203 IrInstruction *free_fn_ptr = ir_build_field_ptr(irb, scope, node, irb->exec->implicit_allocator_ptr,
6208 free_field_name);6204 free_field_name);
6209 IrInstruction *free_fn = ir_build_load_ptr(irb, scope, node, free_fn_ptr);6205 IrInstruction *free_fn = ir_build_load_ptr(irb, scope, node, free_fn_ptr);
6206 IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);
6207 IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
6208 IrInstruction *mem_slice = ir_build_slice(irb, scope, node, coro_mem_ptr_ref, zero, coro_size, false);
6210 size_t arg_count = 2;6209 size_t arg_count = 2;
6211 IrInstruction **args = allocate<IrInstruction *>(arg_count);6210 IrInstruction **args = allocate<IrInstruction *>(arg_count);
6212 args[0] = irb->exec->implicit_allocator_ptr; // self6211 args[0] = irb->exec->implicit_allocator_ptr; // self
6213 args[1] = ir_build_load_ptr(irb, scope, node, coro_unwrapped_mem_ptr); // old_mem6212 args[1] = mem_slice; // old_mem
6214 ir_build_call(irb, scope, node, nullptr, free_fn, arg_count, args, false, FnInlineAuto, false, nullptr);6213 ir_build_call(irb, scope, node, nullptr, free_fn, arg_count, args, false, FnInlineAuto, false, nullptr);
62156214
6216 IrBasicBlock *resume_block = ir_create_basic_block(irb, scope, "Resume");6215 IrBasicBlock *resume_block = ir_create_basic_block(irb, scope, "Resume");
...@@ -11844,7 +11843,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal...@@ -11844,7 +11843,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
11844 }11843 }
1184511844
11846 TypeTableEntry *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type;11845 TypeTableEntry *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type;
11847 if (return_type->id == TypeTableEntryIdErrorSet || return_type->id == TypeTableEntryIdErrorUnion) {11846 if (fn_type_can_fail(&impl_fn->type_entry->data.fn.fn_type_id)) {
11848 parent_fn_entry->calls_errorable_function = true;11847 parent_fn_entry->calls_errorable_function = true;
11849 }11848 }
1185011849
...@@ -11870,7 +11869,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal...@@ -11870,7 +11869,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
11870 FnTableEntry *parent_fn_entry = exec_fn_entry(ira->new_irb.exec);11869 FnTableEntry *parent_fn_entry = exec_fn_entry(ira->new_irb.exec);
11871 assert(fn_type_id->return_type != nullptr);11870 assert(fn_type_id->return_type != nullptr);
11872 assert(parent_fn_entry != nullptr);11871 assert(parent_fn_entry != nullptr);
11873 if (fn_type_id->return_type->id == TypeTableEntryIdErrorSet || fn_type_id->return_type->id == TypeTableEntryIdErrorUnion) {11872 if (fn_type_can_fail(fn_type_id)) {
11874 parent_fn_entry->calls_errorable_function = true;11873 parent_fn_entry->calls_errorable_function = true;
11875 }11874 }
1187611875
...@@ -17274,6 +17273,23 @@ static TypeTableEntry *ir_analyze_instruction_coro_save(IrAnalyze *ira, IrInstru...@@ -17274,6 +17273,23 @@ static TypeTableEntry *ir_analyze_instruction_coro_save(IrAnalyze *ira, IrInstru
17274 return result->value.type;17273 return result->value.type;
17275}17274}
1727617275
17276static TypeTableEntry *ir_analyze_instruction_coro_alloc_helper(IrAnalyze *ira, IrInstructionCoroAllocHelper *instruction) {
17277 IrInstruction *alloc_fn = instruction->alloc_fn->other;
17278 if (type_is_invalid(alloc_fn->value.type))
17279 return ira->codegen->builtin_types.entry_invalid;
17280
17281 IrInstruction *coro_size = instruction->coro_size->other;
17282 if (type_is_invalid(coro_size->value.type))
17283 return ira->codegen->builtin_types.entry_invalid;
17284
17285 IrInstruction *result = ir_build_coro_alloc_helper(&ira->new_irb, instruction->base.scope,
17286 instruction->base.source_node, alloc_fn, coro_size);
17287 ir_link_new_instruction(result, &instruction->base);
17288 TypeTableEntry *u8_ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_u8, false);
17289 result->value.type = get_maybe_type(ira->codegen, u8_ptr_type);
17290 return result->value.type;
17291}
17292
1727717293
17278static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {17294static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
17279 switch (instruction->id) {17295 switch (instruction->id) {
...@@ -17501,6 +17517,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -17501,6 +17517,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
17501 return ir_analyze_instruction_coro_resume(ira, (IrInstructionCoroResume *)instruction);17517 return ir_analyze_instruction_coro_resume(ira, (IrInstructionCoroResume *)instruction);
17502 case IrInstructionIdCoroSave:17518 case IrInstructionIdCoroSave:
17503 return ir_analyze_instruction_coro_save(ira, (IrInstructionCoroSave *)instruction);17519 return ir_analyze_instruction_coro_save(ira, (IrInstructionCoroSave *)instruction);
17520 case IrInstructionIdCoroAllocHelper:
17521 return ir_analyze_instruction_coro_alloc_helper(ira, (IrInstructionCoroAllocHelper *)instruction);
17504 }17522 }
17505 zig_unreachable();17523 zig_unreachable();
17506}17524}
...@@ -17624,6 +17642,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -17624,6 +17642,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
17624 case IrInstructionIdCoroEnd:17642 case IrInstructionIdCoroEnd:
17625 case IrInstructionIdCoroResume:17643 case IrInstructionIdCoroResume:
17626 case IrInstructionIdCoroSave:17644 case IrInstructionIdCoroSave:
17645 case IrInstructionIdCoroAllocHelper:
17627 return true;17646 return true;
1762817647
17629 case IrInstructionIdPhi:17648 case IrInstructionIdPhi:
src/ir_print.cpp+11
...@@ -1096,6 +1096,14 @@ static void ir_print_coro_save(IrPrint *irp, IrInstructionCoroSave *instruction)...@@ -1096,6 +1096,14 @@ static void ir_print_coro_save(IrPrint *irp, IrInstructionCoroSave *instruction)
1096 fprintf(irp->f, ")");1096 fprintf(irp->f, ")");
1097}1097}
10981098
1099static void ir_print_coro_alloc_helper(IrPrint *irp, IrInstructionCoroAllocHelper *instruction) {
1100 fprintf(irp->f, "@coroAllocHelper(");
1101 ir_print_other_instruction(irp, instruction->alloc_fn);
1102 fprintf(irp->f, ",");
1103 ir_print_other_instruction(irp, instruction->coro_size);
1104 fprintf(irp->f, ")");
1105}
1106
1099static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {1107static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1100 ir_print_prefix(irp, instruction);1108 ir_print_prefix(irp, instruction);
1101 switch (instruction->id) {1109 switch (instruction->id) {
...@@ -1452,6 +1460,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1452,6 +1460,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1452 case IrInstructionIdCoroSave:1460 case IrInstructionIdCoroSave:
1453 ir_print_coro_save(irp, (IrInstructionCoroSave *)instruction);1461 ir_print_coro_save(irp, (IrInstructionCoroSave *)instruction);
1454 break;1462 break;
1463 case IrInstructionIdCoroAllocHelper:
1464 ir_print_coro_alloc_helper(irp, (IrInstructionCoroAllocHelper *)instruction);
1465 break;
1455 }1466 }
1456 fprintf(irp->f, "\n");1467 fprintf(irp->f, "\n");
1457}1468}