authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-01 16:08:52-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-01 16:08:52-04:00
loge7ae4e4645a46a216c5913e2f9120cb02c10008c
tree8aa2c2921e067f4515a6dcd1d1bab7363900404e
parentdbdc4d62d08c94a967b36afdfa57b126775a4eee
signature Commit is signed but in an unrecognized format.

reimplement async with function splitting instead of switch


6 files changed, 410 insertions(+), 273 deletions(-)

BRANCH_TODO+2-2
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1 * make the anyframe type and anyframe->T type work with resume1 * fix @frameSize
2 * fix calling an inferred async function
2 * await3 * await
3 * await of a non async function4 * await of a non async function
4 * await in single-threaded mode5 * await in single-threaded mode
...@@ -10,5 +11,4 @@...@@ -10,5 +11,4 @@
10 * implicit cast of normal function to async function should be allowed when it is inferred to be async11 * implicit cast of normal function to async function should be allowed when it is inferred to be async
11 * go over the commented out tests12 * go over the commented out tests
12 * revive std.event.Loop13 * revive std.event.Loop
13 * reimplement with function splitting rather than switch
14 * @typeInfo for @Frame(func)14 * @typeInfo for @Frame(func)
src/all_types.hpp+10-10
...@@ -1726,7 +1726,7 @@ struct CodeGen {...@@ -1726,7 +1726,7 @@ struct CodeGen {
1726 LLVMValueRef err_name_table;1726 LLVMValueRef err_name_table;
1727 LLVMValueRef safety_crash_err_fn;1727 LLVMValueRef safety_crash_err_fn;
1728 LLVMValueRef return_err_fn;1728 LLVMValueRef return_err_fn;
1729 LLVMTypeRef async_fn_llvm_type;1729 LLVMTypeRef anyframe_fn_type;
17301730
1731 // reminder: hash tables must be initialized before use1731 // reminder: hash tables must be initialized before use
1732 HashMap<Buf *, ZigType *, buf_hash, buf_eql_buf> import_table;1732 HashMap<Buf *, ZigType *, buf_hash, buf_eql_buf> import_table;
...@@ -1795,7 +1795,9 @@ struct CodeGen {...@@ -1795,7 +1795,9 @@ struct CodeGen {
1795 ZigType *entry_arg_tuple;1795 ZigType *entry_arg_tuple;
1796 ZigType *entry_enum_literal;1796 ZigType *entry_enum_literal;
1797 ZigType *entry_any_frame;1797 ZigType *entry_any_frame;
1798 ZigType *entry_async_fn;
1798 } builtin_types;1799 } builtin_types;
1800
1799 ZigType *align_amt_type;1801 ZigType *align_amt_type;
1800 ZigType *stack_trace_type;1802 ZigType *stack_trace_type;
1801 ZigType *ptr_to_stack_trace_type;1803 ZigType *ptr_to_stack_trace_type;
...@@ -1934,6 +1936,7 @@ struct ZigVar {...@@ -1934,6 +1936,7 @@ struct ZigVar {
1934 ZigType *var_type;1936 ZigType *var_type;
1935 LLVMValueRef value_ref;1937 LLVMValueRef value_ref;
1936 IrInstruction *is_comptime;1938 IrInstruction *is_comptime;
1939 IrInstruction *ptr_instruction;
1937 // which node is the declaration of the variable1940 // which node is the declaration of the variable
1938 AstNode *decl_node;1941 AstNode *decl_node;
1939 ZigLLVMDILocalVariable *di_loc_var;1942 ZigLLVMDILocalVariable *di_loc_var;
...@@ -2159,8 +2162,8 @@ struct IrBasicBlock {...@@ -2159,8 +2162,8 @@ struct IrBasicBlock {
2159 size_t ref_count;2162 size_t ref_count;
2160 // index into the basic block list2163 // index into the basic block list
2161 size_t index;2164 size_t index;
2162 // for coroutines, the resume_index which corresponds to this block2165 // for async functions, the split function which corresponds to this block
2163 size_t resume_index;2166 LLVMValueRef split_llvm_fn;
2164 LLVMBasicBlockRef llvm_block;2167 LLVMBasicBlockRef llvm_block;
2165 LLVMBasicBlockRef llvm_exit_block;2168 LLVMBasicBlockRef llvm_exit_block;
2166 // The instruction that referenced this basic block and caused us to2169 // The instruction that referenced this basic block and caused us to
...@@ -3686,13 +3689,9 @@ static const size_t maybe_null_index = 1;...@@ -3686,13 +3689,9 @@ static const size_t maybe_null_index = 1;
3686static const size_t err_union_err_index = 0;3689static const size_t err_union_err_index = 0;
3687static const size_t err_union_payload_index = 1;3690static const size_t err_union_payload_index = 1;
36883691
3689static const size_t coro_resume_index_index = 0;3692static const size_t coro_fn_ptr_index = 0;
3690static const size_t coro_fn_ptr_index = 1;3693static const size_t coro_awaiter_index = 1;
3691static const size_t coro_awaiter_index = 2;3694static const size_t coro_arg_start = 2;
3692static const size_t coro_arg_start = 3;
3693
3694// one for the Entry block, resume blocks are indexed after that.
3695static const size_t coro_extra_resume_block_count = 1;
36963695
3697// TODO call graph analysis to find out what this number needs to be for every function3696// TODO call graph analysis to find out what this number needs to be for every function
3698// MUST BE A POWER OF TWO.3697// MUST BE A POWER OF TWO.
...@@ -3719,6 +3718,7 @@ enum FnWalkId {...@@ -3719,6 +3718,7 @@ enum FnWalkId {
37193718
3720struct FnWalkAttrs {3719struct FnWalkAttrs {
3721 ZigFn *fn;3720 ZigFn *fn;
3721 LLVMValueRef llvm_fn;
3722 unsigned gen_i;3722 unsigned gen_i;
3723};3723};
37243724
src/analyze.cpp+129-30
...@@ -5135,6 +5135,19 @@ Error ensure_complete_type(CodeGen *g, ZigType *type_entry) {...@@ -5135,6 +5135,19 @@ Error ensure_complete_type(CodeGen *g, ZigType *type_entry) {
5135 return type_resolve(g, type_entry, ResolveStatusSizeKnown);5135 return type_resolve(g, type_entry, ResolveStatusSizeKnown);
5136}5136}
51375137
5138static ZigType *get_async_fn_type(CodeGen *g, ZigType *orig_fn_type) {
5139 if (orig_fn_type->data.fn.fn_type_id.cc == CallingConventionAsync)
5140 return orig_fn_type;
5141
5142 ZigType *fn_type = allocate_nonzero<ZigType>(1);
5143 *fn_type = *orig_fn_type;
5144 fn_type->data.fn.fn_type_id.cc = CallingConventionAsync;
5145 fn_type->llvm_type = nullptr;
5146 fn_type->llvm_di_type = nullptr;
5147
5148 return fn_type;
5149}
5150
5138static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {5151static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {
5139 if (frame_type->data.frame.locals_struct != nullptr)5152 if (frame_type->data.frame.locals_struct != nullptr)
5140 return ErrorNone;5153 return ErrorNone;
...@@ -5156,6 +5169,7 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {...@@ -5156,6 +5169,7 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {
5156 buf_ptr(&frame_type->name)));5169 buf_ptr(&frame_type->name)));
5157 return ErrorSemanticAnalyzeFail;5170 return ErrorSemanticAnalyzeFail;
5158 }5171 }
5172 ZigType *fn_type = get_async_fn_type(g, fn->type_entry);
51595173
5160 for (size_t i = 0; i < fn->call_list.length; i += 1) {5174 for (size_t i = 0; i < fn->call_list.length; i += 1) {
5161 IrInstructionCallGen *call = fn->call_list.at(i);5175 IrInstructionCallGen *call = fn->call_list.at(i);
...@@ -5173,7 +5187,7 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {...@@ -5173,7 +5187,7 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {
51735187
5174 IrBasicBlock *new_resume_block = allocate<IrBasicBlock>(1);5188 IrBasicBlock *new_resume_block = allocate<IrBasicBlock>(1);
5175 new_resume_block->name_hint = "CallResume";5189 new_resume_block->name_hint = "CallResume";
5176 new_resume_block->resume_index = fn->resume_blocks.length + coro_extra_resume_block_count;5190 new_resume_block->split_llvm_fn = reinterpret_cast<LLVMValueRef>(0x1);
5177 fn->resume_blocks.append(new_resume_block);5191 fn->resume_blocks.append(new_resume_block);
5178 call->resume_block = new_resume_block;5192 call->resume_block = new_resume_block;
5179 fn->analyzed_executable.basic_block_list.append(new_resume_block);5193 fn->analyzed_executable.basic_block_list.append(new_resume_block);
...@@ -5194,16 +5208,13 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {...@@ -5194,16 +5208,13 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {
5194 ZigList<ZigType *> field_types = {};5208 ZigList<ZigType *> field_types = {};
5195 ZigList<const char *> field_names = {};5209 ZigList<const char *> field_names = {};
51965210
5197 field_names.append("resume_index");
5198 field_types.append(g->builtin_types.entry_usize);
5199
5200 field_names.append("fn_ptr");5211 field_names.append("fn_ptr");
5201 field_types.append(fn->type_entry);5212 field_types.append(fn_type);
52025213
5203 field_names.append("awaiter");5214 field_names.append("awaiter");
5204 field_types.append(g->builtin_types.entry_usize);5215 field_types.append(g->builtin_types.entry_usize);
52055216
5206 FnTypeId *fn_type_id = &fn->type_entry->data.fn.fn_type_id;5217 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
5207 ZigType *ptr_return_type = get_pointer_to_type(g, fn_type_id->return_type, false);5218 ZigType *ptr_return_type = get_pointer_to_type(g, fn_type_id->return_type, false);
5208 field_names.append("result_ptr");5219 field_names.append("result_ptr");
5209 field_types.append(ptr_return_type);5220 field_types.append(ptr_return_type);
...@@ -6686,7 +6697,9 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa...@@ -6686,7 +6697,9 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa
6686 type->data.structure.resolve_status = ResolveStatusLLVMFull;6697 type->data.structure.resolve_status = ResolveStatusLLVMFull;
6687}6698}
66886699
6689static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveStatus wanted_resolve_status) {6700static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveStatus wanted_resolve_status,
6701 ZigType *coro_frame_type)
6702{
6690 assert(struct_type->id == ZigTypeIdStruct);6703 assert(struct_type->id == ZigTypeIdStruct);
6691 assert(struct_type->data.structure.resolve_status != ResolveStatusInvalid);6704 assert(struct_type->data.structure.resolve_status != ResolveStatusInvalid);
6692 assert(struct_type->data.structure.resolve_status >= ResolveStatusSizeKnown);6705 assert(struct_type->data.structure.resolve_status >= ResolveStatusSizeKnown);
...@@ -6774,7 +6787,16 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS...@@ -6774,7 +6787,16 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
6774 }6787 }
6775 packed_bits_offset = next_packed_bits_offset;6788 packed_bits_offset = next_packed_bits_offset;
6776 } else {6789 } else {
6777 element_types[gen_field_index] = get_llvm_type(g, field_type);6790 LLVMTypeRef llvm_type;
6791 if (i == 0 && coro_frame_type != nullptr) {
6792 assert(coro_frame_type->id == ZigTypeIdCoroFrame);
6793 assert(field_type->id == ZigTypeIdFn);
6794 resolve_llvm_types_fn(g, coro_frame_type->data.frame.fn);
6795 llvm_type = LLVMPointerType(coro_frame_type->data.frame.fn->raw_type_ref, 0);
6796 } else {
6797 llvm_type = get_llvm_type(g, field_type);
6798 }
6799 element_types[gen_field_index] = llvm_type;
67786800
6779 gen_field_index += 1;6801 gen_field_index += 1;
6780 }6802 }
...@@ -7456,7 +7478,7 @@ static void resolve_llvm_types_anyerror(CodeGen *g) {...@@ -7456,7 +7478,7 @@ static void resolve_llvm_types_anyerror(CodeGen *g) {
7456}7478}
74577479
7458static void resolve_llvm_types_coro_frame(CodeGen *g, ZigType *frame_type, ResolveStatus wanted_resolve_status) {7480static void resolve_llvm_types_coro_frame(CodeGen *g, ZigType *frame_type, ResolveStatus wanted_resolve_status) {
7459 resolve_llvm_types_struct(g, frame_type->data.frame.locals_struct, wanted_resolve_status);7481 resolve_llvm_types_struct(g, frame_type->data.frame.locals_struct, wanted_resolve_status, frame_type);
7460 frame_type->llvm_type = frame_type->data.frame.locals_struct->llvm_type;7482 frame_type->llvm_type = frame_type->data.frame.locals_struct->llvm_type;
7461 frame_type->llvm_di_type = frame_type->data.frame.locals_struct->llvm_di_type;7483 frame_type->llvm_di_type = frame_type->data.frame.locals_struct->llvm_di_type;
7462}7484}
...@@ -7464,35 +7486,112 @@ static void resolve_llvm_types_coro_frame(CodeGen *g, ZigType *frame_type, Resol...@@ -7464,35 +7486,112 @@ static void resolve_llvm_types_coro_frame(CodeGen *g, ZigType *frame_type, Resol
7464static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, ResolveStatus wanted_resolve_status) {7486static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, ResolveStatus wanted_resolve_status) {
7465 if (any_frame_type->llvm_di_type != nullptr) return;7487 if (any_frame_type->llvm_di_type != nullptr) return;
74667488
7467 ZigType *result_type = any_frame_type->data.any_frame.result_type;
7468 Buf *name = buf_sprintf("(%s header)", buf_ptr(&any_frame_type->name));7489 Buf *name = buf_sprintf("(%s header)", buf_ptr(&any_frame_type->name));
7490 LLVMTypeRef frame_header_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(name));
7491 any_frame_type->llvm_type = LLVMPointerType(frame_header_type, 0);
7492
7493 unsigned dwarf_kind = ZigLLVMTag_DW_structure_type();
7494 ZigLLVMDIFile *di_file = nullptr;
7495 ZigLLVMDIScope *di_scope = ZigLLVMCompileUnitToScope(g->compile_unit);
7496 unsigned line = 0;
7497 ZigLLVMDIType *frame_header_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder,
7498 dwarf_kind, buf_ptr(name), di_scope, di_file, line);
7499 any_frame_type->llvm_di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, frame_header_di_type,
7500 8*g->pointer_size_bytes, 8*g->builtin_types.entry_usize->abi_align, buf_ptr(&any_frame_type->name));
7501
7502 LLVMTypeRef llvm_void = LLVMVoidType();
7503 LLVMTypeRef fn_type = LLVMFunctionType(llvm_void, &any_frame_type->llvm_type, 1, false);
7504 LLVMTypeRef usize_type_ref = get_llvm_type(g, g->builtin_types.entry_usize);
7505 ZigLLVMDIType *usize_di_type = get_llvm_di_type(g, g->builtin_types.entry_usize);
7506 ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit);
74697507
7470 ZigType *frame_header_type;7508 ZigType *result_type = any_frame_type->data.any_frame.result_type;
7471 if (result_type == nullptr || !type_has_bits(result_type)) {7509 if (result_type == nullptr || !type_has_bits(result_type)) {
7472 const char *field_names[] = {"resume_index", "fn_ptr", "awaiter"};7510 LLVMTypeRef ptr_result_type = LLVMPointerType(fn_type, 0);
7473 ZigType *field_types[] = {7511 if (result_type == nullptr) {
7474 g->builtin_types.entry_usize,7512 g->anyframe_fn_type = ptr_result_type;
7475 g->builtin_types.entry_usize,7513 }
7476 g->builtin_types.entry_usize,7514 LLVMTypeRef field_types[] = {
7515 ptr_result_type, // fn_ptr
7516 usize_type_ref, // awaiter
7517 };
7518 LLVMStructSetBody(frame_header_type, field_types, 2, false);
7519
7520 ZigLLVMDIType *di_element_types[] = {
7521 ZigLLVMCreateDebugMemberType(g->dbuilder,
7522 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "fn_ptr",
7523 di_file, line,
7524 8*LLVMABISizeOfType(g->target_data_ref, field_types[0]),
7525 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types[0]),
7526 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, 0),
7527 ZigLLVM_DIFlags_Zero, usize_di_type),
7528 ZigLLVMCreateDebugMemberType(g->dbuilder,
7529 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "awaiter",
7530 di_file, line,
7531 8*LLVMABISizeOfType(g->target_data_ref, field_types[1]),
7532 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types[1]),
7533 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, 1),
7534 ZigLLVM_DIFlags_Zero, usize_di_type),
7477 };7535 };
7478 frame_header_type = get_struct_type(g, buf_ptr(name), field_names, field_types, 3);7536 ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
7537 compile_unit_scope, buf_ptr(name),
7538 di_file, line,
7539 8*LLVMABISizeOfType(g->target_data_ref, frame_header_type),
7540 8*LLVMABIAlignmentOfType(g->target_data_ref, frame_header_type),
7541 ZigLLVM_DIFlags_Zero,
7542 nullptr, di_element_types, 2, 0, nullptr, "");
7543
7544 ZigLLVMReplaceTemporary(g->dbuilder, frame_header_di_type, replacement_di_type);
7479 } else {7545 } else {
7480 ZigType *ptr_result_type = get_pointer_to_type(g, result_type, false);7546 ZigType *ptr_result_type = get_pointer_to_type(g, result_type, false);
7547 LLVMTypeRef field_types[] = {
7548 LLVMPointerType(fn_type, 0), // fn_ptr
7549 usize_type_ref, // awaiter
7550 get_llvm_type(g, ptr_result_type), // result_ptr
7551 get_llvm_type(g, result_type), // result
7552 };
7553 LLVMStructSetBody(frame_header_type, field_types, 4, false);
74817554
7482 const char *field_names[] = {"resume_index", "fn_ptr", "awaiter", "result_ptr", "result"};7555 ZigLLVMDIType *di_element_types[] = {
7483 ZigType *field_types[] = {7556 ZigLLVMCreateDebugMemberType(g->dbuilder,
7484 g->builtin_types.entry_usize,7557 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "fn_ptr",
7485 g->builtin_types.entry_usize,7558 di_file, line,
7486 g->builtin_types.entry_usize,7559 8*LLVMABISizeOfType(g->target_data_ref, field_types[0]),
7487 ptr_result_type,7560 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types[0]),
7488 result_type,7561 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, 0),
7562 ZigLLVM_DIFlags_Zero, usize_di_type),
7563 ZigLLVMCreateDebugMemberType(g->dbuilder,
7564 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "awaiter",
7565 di_file, line,
7566 8*LLVMABISizeOfType(g->target_data_ref, field_types[1]),
7567 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types[1]),
7568 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, 1),
7569 ZigLLVM_DIFlags_Zero, usize_di_type),
7570 ZigLLVMCreateDebugMemberType(g->dbuilder,
7571 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "result_ptr",
7572 di_file, line,
7573 8*LLVMABISizeOfType(g->target_data_ref, field_types[2]),
7574 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types[2]),
7575 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, 2),
7576 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, ptr_result_type)),
7577 ZigLLVMCreateDebugMemberType(g->dbuilder,
7578 ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "result",
7579 di_file, line,
7580 8*LLVMABISizeOfType(g->target_data_ref, field_types[3]),
7581 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types[3]),
7582 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, 3),
7583 ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, result_type)),
7489 };7584 };
7490 frame_header_type = get_struct_type(g, buf_ptr(name), field_names, field_types, 5);7585 ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
7491 }7586 compile_unit_scope, buf_ptr(name),
7587 di_file, line,
7588 8*LLVMABISizeOfType(g->target_data_ref, frame_header_type),
7589 8*LLVMABIAlignmentOfType(g->target_data_ref, frame_header_type),
7590 ZigLLVM_DIFlags_Zero,
7591 nullptr, di_element_types, 2, 0, nullptr, "");
74927592
7493 ZigType *ptr_type = get_pointer_to_type(g, frame_header_type, false);7593 ZigLLVMReplaceTemporary(g->dbuilder, frame_header_di_type, replacement_di_type);
7494 any_frame_type->llvm_type = get_llvm_type(g, ptr_type);7594 }
7495 any_frame_type->llvm_di_type = get_llvm_di_type(g, ptr_type);
7496}7595}
74977596
7498static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {7597static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {
...@@ -7520,7 +7619,7 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r...@@ -7520,7 +7619,7 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r
7520 if (type->data.structure.is_slice)7619 if (type->data.structure.is_slice)
7521 return resolve_llvm_types_slice(g, type, wanted_resolve_status);7620 return resolve_llvm_types_slice(g, type, wanted_resolve_status);
7522 else7621 else
7523 return resolve_llvm_types_struct(g, type, wanted_resolve_status);7622 return resolve_llvm_types_struct(g, type, wanted_resolve_status, nullptr);
7524 case ZigTypeIdEnum:7623 case ZigTypeIdEnum:
7525 return resolve_llvm_types_enum(g, type);7624 return resolve_llvm_types_enum(g, type);
7526 case ZigTypeIdUnion:7625 case ZigTypeIdUnion:
src/codegen.cpp+216-178
...@@ -343,27 +343,24 @@ static bool cc_want_sret_attr(CallingConvention cc) {...@@ -343,27 +343,24 @@ static bool cc_want_sret_attr(CallingConvention cc) {
343 zig_unreachable();343 zig_unreachable();
344}344}
345345
346static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {346static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) {
347 if (fn_table_entry->llvm_value)347 Buf *unmangled_name = &fn->symbol_name;
348 return fn_table_entry->llvm_value;
349
350 Buf *unmangled_name = &fn_table_entry->symbol_name;
351 Buf *symbol_name;348 Buf *symbol_name;
352 GlobalLinkageId linkage;349 GlobalLinkageId linkage;
353 if (fn_table_entry->body_node == nullptr) {350 if (fn->body_node == nullptr) {
354 symbol_name = unmangled_name;351 symbol_name = unmangled_name;
355 linkage = GlobalLinkageIdStrong;352 linkage = GlobalLinkageIdStrong;
356 } else if (fn_table_entry->export_list.length == 0) {353 } else if (fn->export_list.length == 0) {
357 symbol_name = get_mangled_name(g, unmangled_name, false);354 symbol_name = get_mangled_name(g, unmangled_name, false);
358 linkage = GlobalLinkageIdInternal;355 linkage = GlobalLinkageIdInternal;
359 } else {356 } else {
360 GlobalExport *fn_export = &fn_table_entry->export_list.items[0];357 GlobalExport *fn_export = &fn->export_list.items[0];
361 symbol_name = &fn_export->name;358 symbol_name = &fn_export->name;
362 linkage = fn_export->linkage;359 linkage = fn_export->linkage;
363 }360 }
364361
365 bool external_linkage = linkage != GlobalLinkageIdInternal;362 bool external_linkage = linkage != GlobalLinkageIdInternal;
366 CallingConvention cc = fn_table_entry->type_entry->data.fn.fn_type_id.cc;363 CallingConvention cc = fn->type_entry->data.fn.fn_type_id.cc;
367 if (cc == CallingConventionStdcall && external_linkage &&364 if (cc == CallingConventionStdcall && external_linkage &&
368 g->zig_target->arch == ZigLLVM_x86)365 g->zig_target->arch == ZigLLVM_x86)
369 {366 {
...@@ -371,28 +368,28 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {...@@ -371,28 +368,28 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
371 symbol_name = buf_sprintf("\x01_%s", buf_ptr(symbol_name));368 symbol_name = buf_sprintf("\x01_%s", buf_ptr(symbol_name));
372 }369 }
373370
374 bool is_async = fn_is_async(fn_table_entry);371 bool is_async = fn_is_async(fn);
375372
376373
377 ZigType *fn_type = fn_table_entry->type_entry;374 ZigType *fn_type = fn->type_entry;
378 // Make the raw_type_ref populated375 // Make the raw_type_ref populated
379 resolve_llvm_types_fn(g, fn_table_entry);376 resolve_llvm_types_fn(g, fn);
380 LLVMTypeRef fn_llvm_type = fn_table_entry->raw_type_ref;377 LLVMTypeRef fn_llvm_type = fn->raw_type_ref;
381 if (fn_table_entry->body_node == nullptr) {378 LLVMValueRef llvm_fn = nullptr;
379 if (fn->body_node == nullptr) {
382 LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name));380 LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name));
383 if (existing_llvm_fn) {381 if (existing_llvm_fn) {
384 fn_table_entry->llvm_value = LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, 0));382 return LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, 0));
385 return fn_table_entry->llvm_value;
386 } else {383 } else {
387 auto entry = g->exported_symbol_names.maybe_get(symbol_name);384 auto entry = g->exported_symbol_names.maybe_get(symbol_name);
388 if (entry == nullptr) {385 if (entry == nullptr) {
389 fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type);386 llvm_fn = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type);
390387
391 if (target_is_wasm(g->zig_target)) {388 if (target_is_wasm(g->zig_target)) {
392 assert(fn_table_entry->proto_node->type == NodeTypeFnProto);389 assert(fn->proto_node->type == NodeTypeFnProto);
393 AstNodeFnProto *fn_proto = &fn_table_entry->proto_node->data.fn_proto;390 AstNodeFnProto *fn_proto = &fn->proto_node->data.fn_proto;
394 if (fn_proto-> is_extern && fn_proto->lib_name != nullptr ) {391 if (fn_proto-> is_extern && fn_proto->lib_name != nullptr ) {
395 addLLVMFnAttrStr(fn_table_entry->llvm_value, "wasm-import-module", buf_ptr(fn_proto->lib_name));392 addLLVMFnAttrStr(llvm_fn, "wasm-import-module", buf_ptr(fn_proto->lib_name));
396 }393 }
397 }394 }
398 } else {395 } else {
...@@ -402,101 +399,98 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {...@@ -402,101 +399,98 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
402 resolve_llvm_types_fn(g, tld_fn->fn_entry);399 resolve_llvm_types_fn(g, tld_fn->fn_entry);
403 tld_fn->fn_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name),400 tld_fn->fn_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name),
404 tld_fn->fn_entry->raw_type_ref);401 tld_fn->fn_entry->raw_type_ref);
405 fn_table_entry->llvm_value = LLVMConstBitCast(tld_fn->fn_entry->llvm_value,402 llvm_fn = LLVMConstBitCast(tld_fn->fn_entry->llvm_value, LLVMPointerType(fn_llvm_type, 0));
406 LLVMPointerType(fn_llvm_type, 0));403 return llvm_fn;
407 return fn_table_entry->llvm_value;
408 }404 }
409 }405 }
410 } else {406 } else {
411 if (fn_table_entry->llvm_value == nullptr) {407 if (llvm_fn == nullptr) {
412 fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type);408 llvm_fn = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type);
413 }409 }
414410
415 for (size_t i = 1; i < fn_table_entry->export_list.length; i += 1) {411 for (size_t i = 1; i < fn->export_list.length; i += 1) {
416 GlobalExport *fn_export = &fn_table_entry->export_list.items[i];412 GlobalExport *fn_export = &fn->export_list.items[i];
417 LLVMAddAlias(g->module, LLVMTypeOf(fn_table_entry->llvm_value),413 LLVMAddAlias(g->module, LLVMTypeOf(llvm_fn), llvm_fn, buf_ptr(&fn_export->name));
418 fn_table_entry->llvm_value, buf_ptr(&fn_export->name));
419 }414 }
420 }415 }
421 fn_table_entry->llvm_name = strdup(LLVMGetValueName(fn_table_entry->llvm_value));
422416
423 switch (fn_table_entry->fn_inline) {417 switch (fn->fn_inline) {
424 case FnInlineAlways:418 case FnInlineAlways:
425 addLLVMFnAttr(fn_table_entry->llvm_value, "alwaysinline");419 addLLVMFnAttr(llvm_fn, "alwaysinline");
426 g->inline_fns.append(fn_table_entry);420 g->inline_fns.append(fn);
427 break;421 break;
428 case FnInlineNever:422 case FnInlineNever:
429 addLLVMFnAttr(fn_table_entry->llvm_value, "noinline");423 addLLVMFnAttr(llvm_fn, "noinline");
430 break;424 break;
431 case FnInlineAuto:425 case FnInlineAuto:
432 if (fn_table_entry->alignstack_value != 0) {426 if (fn->alignstack_value != 0) {
433 addLLVMFnAttr(fn_table_entry->llvm_value, "noinline");427 addLLVMFnAttr(llvm_fn, "noinline");
434 }428 }
435 break;429 break;
436 }430 }
437431
438 if (cc == CallingConventionNaked) {432 if (cc == CallingConventionNaked) {
439 addLLVMFnAttr(fn_table_entry->llvm_value, "naked");433 addLLVMFnAttr(llvm_fn, "naked");
440 } else {434 } else {
441 LLVMSetFunctionCallConv(fn_table_entry->llvm_value, get_llvm_cc(g, fn_type->data.fn.fn_type_id.cc));435 LLVMSetFunctionCallConv(llvm_fn, get_llvm_cc(g, fn_type->data.fn.fn_type_id.cc));
442 }436 }
443 if (cc == CallingConventionAsync) {437 if (cc == CallingConventionAsync) {
444 addLLVMFnAttr(fn_table_entry->llvm_value, "optnone");438 addLLVMFnAttr(llvm_fn, "optnone");
445 addLLVMFnAttr(fn_table_entry->llvm_value, "noinline");439 addLLVMFnAttr(llvm_fn, "noinline");
446 }440 }
447441
448 bool want_cold = fn_table_entry->is_cold || cc == CallingConventionCold;442 bool want_cold = fn->is_cold || cc == CallingConventionCold;
449 if (want_cold) {443 if (want_cold) {
450 ZigLLVMAddFunctionAttrCold(fn_table_entry->llvm_value);444 ZigLLVMAddFunctionAttrCold(llvm_fn);
451 }445 }
452446
453447
454 LLVMSetLinkage(fn_table_entry->llvm_value, to_llvm_linkage(linkage));448 LLVMSetLinkage(llvm_fn, to_llvm_linkage(linkage));
455449
456 if (linkage == GlobalLinkageIdInternal) {450 if (linkage == GlobalLinkageIdInternal) {
457 LLVMSetUnnamedAddr(fn_table_entry->llvm_value, true);451 LLVMSetUnnamedAddr(llvm_fn, true);
458 }452 }
459453
460 ZigType *return_type = fn_type->data.fn.fn_type_id.return_type;454 ZigType *return_type = fn_type->data.fn.fn_type_id.return_type;
461 if (return_type->id == ZigTypeIdUnreachable) {455 if (return_type->id == ZigTypeIdUnreachable) {
462 addLLVMFnAttr(fn_table_entry->llvm_value, "noreturn");456 addLLVMFnAttr(llvm_fn, "noreturn");
463 }457 }
464458
465 if (fn_table_entry->body_node != nullptr) {459 if (fn->body_node != nullptr) {
466 maybe_export_dll(g, fn_table_entry->llvm_value, linkage);460 maybe_export_dll(g, llvm_fn, linkage);
467461
468 bool want_fn_safety = g->build_mode != BuildModeFastRelease &&462 bool want_fn_safety = g->build_mode != BuildModeFastRelease &&
469 g->build_mode != BuildModeSmallRelease &&463 g->build_mode != BuildModeSmallRelease &&
470 !fn_table_entry->def_scope->safety_off;464 !fn->def_scope->safety_off;
471 if (want_fn_safety) {465 if (want_fn_safety) {
472 if (g->libc_link_lib != nullptr) {466 if (g->libc_link_lib != nullptr) {
473 addLLVMFnAttr(fn_table_entry->llvm_value, "sspstrong");467 addLLVMFnAttr(llvm_fn, "sspstrong");
474 addLLVMFnAttrStr(fn_table_entry->llvm_value, "stack-protector-buffer-size", "4");468 addLLVMFnAttrStr(llvm_fn, "stack-protector-buffer-size", "4");
475 }469 }
476 }470 }
477 if (g->have_stack_probing && !fn_table_entry->def_scope->safety_off) {471 if (g->have_stack_probing && !fn->def_scope->safety_off) {
478 addLLVMFnAttrStr(fn_table_entry->llvm_value, "probe-stack", "__zig_probe_stack");472 addLLVMFnAttrStr(llvm_fn, "probe-stack", "__zig_probe_stack");
479 }473 }
480 } else {474 } else {
481 maybe_import_dll(g, fn_table_entry->llvm_value, linkage);475 maybe_import_dll(g, llvm_fn, linkage);
482 }476 }
483477
484 if (fn_table_entry->alignstack_value != 0) {478 if (fn->alignstack_value != 0) {
485 addLLVMFnAttrInt(fn_table_entry->llvm_value, "alignstack", fn_table_entry->alignstack_value);479 addLLVMFnAttrInt(llvm_fn, "alignstack", fn->alignstack_value);
486 }480 }
487481
488 addLLVMFnAttr(fn_table_entry->llvm_value, "nounwind");482 addLLVMFnAttr(llvm_fn, "nounwind");
489 add_uwtable_attr(g, fn_table_entry->llvm_value);483 add_uwtable_attr(g, llvm_fn);
490 addLLVMFnAttr(fn_table_entry->llvm_value, "nobuiltin");484 addLLVMFnAttr(llvm_fn, "nobuiltin");
491 if (g->build_mode == BuildModeDebug && fn_table_entry->fn_inline != FnInlineAlways) {485 if (g->build_mode == BuildModeDebug && fn->fn_inline != FnInlineAlways) {
492 ZigLLVMAddFunctionAttr(fn_table_entry->llvm_value, "no-frame-pointer-elim", "true");486 ZigLLVMAddFunctionAttr(llvm_fn, "no-frame-pointer-elim", "true");
493 ZigLLVMAddFunctionAttr(fn_table_entry->llvm_value, "no-frame-pointer-elim-non-leaf", nullptr);487 ZigLLVMAddFunctionAttr(llvm_fn, "no-frame-pointer-elim-non-leaf", nullptr);
494 }488 }
495 if (fn_table_entry->section_name) {489 if (fn->section_name) {
496 LLVMSetSection(fn_table_entry->llvm_value, buf_ptr(fn_table_entry->section_name));490 LLVMSetSection(llvm_fn, buf_ptr(fn->section_name));
497 }491 }
498 if (fn_table_entry->align_bytes > 0) {492 if (fn->align_bytes > 0) {
499 LLVMSetAlignment(fn_table_entry->llvm_value, (unsigned)fn_table_entry->align_bytes);493 LLVMSetAlignment(llvm_fn, (unsigned)fn->align_bytes);
500 } else {494 } else {
501 // We'd like to set the best alignment for the function here, but on Darwin LLVM gives495 // We'd like to set the best alignment for the function here, but on Darwin LLVM gives
502 // "Cannot getTypeInfo() on a type that is unsized!" assertion failure when calling496 // "Cannot getTypeInfo() on a type that is unsized!" assertion failure when calling
...@@ -508,36 +502,46 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {...@@ -508,36 +502,46 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
508 if (!type_has_bits(return_type)) {502 if (!type_has_bits(return_type)) {
509 // nothing to do503 // nothing to do
510 } else if (type_is_nonnull_ptr(return_type)) {504 } else if (type_is_nonnull_ptr(return_type)) {
511 addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");505 addLLVMAttr(llvm_fn, 0, "nonnull");
512 } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {506 } else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {
513 // Sret pointers must not be address 0507 // Sret pointers must not be address 0
514 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull");508 addLLVMArgAttr(llvm_fn, 0, "nonnull");
515 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");509 addLLVMArgAttr(llvm_fn, 0, "sret");
516 if (cc_want_sret_attr(cc)) {510 if (cc_want_sret_attr(cc)) {
517 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "noalias");511 addLLVMArgAttr(llvm_fn, 0, "noalias");
518 }512 }
519 init_gen_i = 1;513 init_gen_i = 1;
520 }514 }
521515
522 if (is_async) {516 if (is_async) {
523 addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull");517 addLLVMArgAttr(llvm_fn, 0, "nonnull");
524 } else {518 } else {
525 // set parameter attributes519 // set parameter attributes
526 FnWalk fn_walk = {};520 FnWalk fn_walk = {};
527 fn_walk.id = FnWalkIdAttrs;521 fn_walk.id = FnWalkIdAttrs;
528 fn_walk.data.attrs.fn = fn_table_entry;522 fn_walk.data.attrs.fn = fn;
523 fn_walk.data.attrs.llvm_fn = llvm_fn;
529 fn_walk.data.attrs.gen_i = init_gen_i;524 fn_walk.data.attrs.gen_i = init_gen_i;
530 walk_function_params(g, fn_type, &fn_walk);525 walk_function_params(g, fn_type, &fn_walk);
531526
532 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);527 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn);
533 if (err_ret_trace_arg_index != UINT32_MAX) {528 if (err_ret_trace_arg_index != UINT32_MAX) {
534 // Error return trace memory is in the stack, which is impossible to be at address 0529 // Error return trace memory is in the stack, which is impossible to be at address 0
535 // on any architecture.530 // on any architecture.
536 addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull");531 addLLVMArgAttr(llvm_fn, (unsigned)err_ret_trace_arg_index, "nonnull");
537 }532 }
538 }533 }
539534
540 return fn_table_entry->llvm_value;535 return llvm_fn;
536}
537
538static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn) {
539 if (fn->llvm_value)
540 return fn->llvm_value;
541
542 fn->llvm_value = make_fn_llvm_value(g, fn);
543 fn->llvm_name = strdup(LLVMGetValueName(fn->llvm_value));
544 return fn->llvm_value;
541}545}
542546
543static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {547static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
...@@ -1665,7 +1669,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_...@@ -1665,7 +1669,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
1665 param_info = &fn_type->data.fn.fn_type_id.param_info[src_i];1669 param_info = &fn_type->data.fn.fn_type_id.param_info[src_i];
1666 ty = param_info->type;1670 ty = param_info->type;
1667 source_node = fn_walk->data.attrs.fn->proto_node;1671 source_node = fn_walk->data.attrs.fn->proto_node;
1668 llvm_fn = fn_walk->data.attrs.fn->llvm_value;1672 llvm_fn = fn_walk->data.attrs.llvm_fn;
1669 break;1673 break;
1670 case FnWalkIdCall: {1674 case FnWalkIdCall: {
1671 if (src_i >= fn_walk->data.call.inst->arg_count)1675 if (src_i >= fn_walk->data.call.inst->arg_count)
...@@ -1916,7 +1920,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {...@@ -1916,7 +1920,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
19161920
1917 switch (fn_walk->id) {1921 switch (fn_walk->id) {
1918 case FnWalkIdAttrs: {1922 case FnWalkIdAttrs: {
1919 LLVMValueRef llvm_fn = fn_walk->data.attrs.fn->llvm_value;1923 LLVMValueRef llvm_fn = fn_walk->data.attrs.llvm_fn;
1920 bool is_byval = gen_info->is_byval;1924 bool is_byval = gen_info->is_byval;
1921 FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[param_i];1925 FnTypeParamInfo *param_info = &fn_type->data.fn.fn_type_id.param_info[param_i];
19221926
...@@ -1989,10 +1993,9 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns...@@ -1989,10 +1993,9 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns
1989 if (fn_is_async(g->cur_fn)) {1993 if (fn_is_async(g->cur_fn)) {
1990 if (ir_want_runtime_safety(g, &return_instruction->base)) {1994 if (ir_want_runtime_safety(g, &return_instruction->base)) {
1991 LLVMValueRef locals_ptr = g->cur_ret_ptr;1995 LLVMValueRef locals_ptr = g->cur_ret_ptr;
1992 LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, locals_ptr, coro_resume_index_index, "");1996 LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, locals_ptr, coro_fn_ptr_index, "");
1993 LLVMValueRef new_resume_index = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,1997 LLVMValueRef new_resume_fn = g->cur_fn->resume_blocks.last()->split_llvm_fn;
1994 g->cur_fn->resume_blocks.length + 2, false);1998 LLVMBuildStore(g->builder, new_resume_fn, resume_index_ptr);
1995 LLVMBuildStore(g->builder, new_resume_index, resume_index_ptr);
1996 }1999 }
19972000
1998 LLVMBuildRetVoid(g->builder);2001 LLVMBuildRetVoid(g->builder);
...@@ -2954,14 +2957,17 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI...@@ -2954,14 +2957,17 @@ static LLVMValueRef ir_render_bool_not(CodeGen *g, IrExecutable *executable, IrI
2954 return LLVMBuildICmp(g->builder, LLVMIntEQ, value, zero, "");2957 return LLVMBuildICmp(g->builder, LLVMIntEQ, value, zero, "");
2955}2958}
29562959
2957static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, IrInstructionDeclVarGen *instruction) {2960static void render_decl_var(CodeGen *g, ZigVar *var) {
2958 ZigVar *var = instruction->var;
2959
2960 if (!type_has_bits(var->var_type))2961 if (!type_has_bits(var->var_type))
2961 return nullptr;2962 return;
29622963
2963 var->value_ref = ir_llvm_value(g, instruction->var_ptr);2964 var->value_ref = ir_llvm_value(g, var->ptr_instruction);
2964 gen_var_debug_decl(g, var);2965 gen_var_debug_decl(g, var);
2966}
2967
2968static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, IrInstructionDeclVarGen *instruction) {
2969 instruction->var->ptr_instruction = instruction->var_ptr;
2970 render_decl_var(g, instruction->var);
2965 return nullptr;2971 return nullptr;
2966}2972}
29672973
...@@ -3369,12 +3375,6 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3369,12 +3375,6 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3369 if (instruction->is_async || callee_is_async) {3375 if (instruction->is_async || callee_is_async) {
3370 assert(frame_result_loc != nullptr);3376 assert(frame_result_loc != nullptr);
3371 assert(instruction->fn_entry != nullptr);3377 assert(instruction->fn_entry != nullptr);
3372 LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_resume_index_index, "");
3373 LLVMBuildStore(g->builder, zero, resume_index_ptr);
3374 LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_fn_ptr_index, "");
3375 LLVMValueRef bitcasted_fn_val = LLVMBuildBitCast(g->builder, fn_val,
3376 LLVMGetElementType(LLVMTypeOf(fn_ptr_ptr)), "");
3377 LLVMBuildStore(g->builder, bitcasted_fn_val, fn_ptr_ptr);
33783378
3379 if (prefix_arg_err_ret_stack) {3379 if (prefix_arg_err_ret_stack) {
3380 zig_panic("TODO");3380 zig_panic("TODO");
...@@ -3431,10 +3431,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -3431,10 +3431,9 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
3431 ZigLLVMBuildCall(g->builder, fn_val, &frame_result_loc, 1, llvm_cc, fn_inline, "");3431 ZigLLVMBuildCall(g->builder, fn_val, &frame_result_loc, 1, llvm_cc, fn_inline, "");
3432 return nullptr;3432 return nullptr;
3433 } else if (callee_is_async) {3433 } else if (callee_is_async) {
3434 LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_resume_index_index, "");3434 LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_fn_ptr_index, "");
3435 LLVMValueRef new_resume_index = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,3435 LLVMValueRef new_fn_ptr = instruction->resume_block->split_llvm_fn;
3436 instruction->resume_block->resume_index, false);3436 LLVMBuildStore(g->builder, new_fn_ptr, fn_ptr_ptr);
3437 LLVMBuildStore(g->builder, new_resume_index, resume_index_ptr);
34383437
3439 LLVMValueRef call_inst = ZigLLVMBuildCall(g->builder, fn_val, &frame_result_loc, 1, llvm_cc, fn_inline, "");3438 LLVMValueRef call_inst = ZigLLVMBuildCall(g->builder, fn_val, &frame_result_loc, 1, llvm_cc, fn_inline, "");
3440 ZigLLVMSetTailCall(call_inst);3439 ZigLLVMSetTailCall(call_inst);
...@@ -4888,10 +4887,9 @@ static LLVMValueRef ir_render_suspend_begin(CodeGen *g, IrExecutable *executable...@@ -4888,10 +4887,9 @@ static LLVMValueRef ir_render_suspend_begin(CodeGen *g, IrExecutable *executable
4888 IrInstructionSuspendBegin *instruction)4887 IrInstructionSuspendBegin *instruction)
4889{4888{
4890 LLVMValueRef locals_ptr = g->cur_ret_ptr;4889 LLVMValueRef locals_ptr = g->cur_ret_ptr;
4891 LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, locals_ptr, coro_resume_index_index, "");4890 LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, locals_ptr, coro_fn_ptr_index, "");
4892 LLVMValueRef new_resume_index = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,4891 LLVMValueRef new_fn_ptr = instruction->resume_block->split_llvm_fn;
4893 instruction->resume_block->resume_index, false);4892 LLVMBuildStore(g->builder, new_fn_ptr, fn_ptr_ptr);
4894 LLVMBuildStore(g->builder, new_resume_index, resume_index_ptr);
4895 return nullptr;4893 return nullptr;
4896}4894}
48974895
...@@ -4902,17 +4900,17 @@ static LLVMValueRef ir_render_suspend_br(CodeGen *g, IrExecutable *executable,...@@ -4902,17 +4900,17 @@ static LLVMValueRef ir_render_suspend_br(CodeGen *g, IrExecutable *executable,
4902 return nullptr;4900 return nullptr;
4903}4901}
49044902
4905static LLVMTypeRef async_fn_llvm_type(CodeGen *g) {4903static LLVMTypeRef anyframe_fn_type(CodeGen *g) {
4906 if (g->async_fn_llvm_type != nullptr)4904 if (g->anyframe_fn_type != nullptr)
4907 return g->async_fn_llvm_type;4905 return g->anyframe_fn_type;
49084906
4909 ZigType *anyframe_type = get_any_frame_type(g, nullptr);4907 ZigType *anyframe_type = get_any_frame_type(g, nullptr);
4910 LLVMTypeRef param_type = get_llvm_type(g, anyframe_type);4908 LLVMTypeRef param_type = get_llvm_type(g, anyframe_type);
4911 LLVMTypeRef return_type = LLVMVoidType();4909 LLVMTypeRef return_type = LLVMVoidType();
4912 LLVMTypeRef fn_type = LLVMFunctionType(return_type, &param_type, 1, false);4910 LLVMTypeRef fn_type = LLVMFunctionType(return_type, &param_type, 1, false);
4913 g->async_fn_llvm_type = LLVMPointerType(fn_type, 0);4911 g->anyframe_fn_type = LLVMPointerType(fn_type, 0);
49144912
4915 return g->async_fn_llvm_type;4913 return g->anyframe_fn_type;
4916}4914}
49174915
4918static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable,4916static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable,
...@@ -4923,7 +4921,7 @@ static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable,...@@ -4923,7 +4921,7 @@ static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable,
4923 assert(frame_type->id == ZigTypeIdAnyFrame);4921 assert(frame_type->id == ZigTypeIdAnyFrame);
4924 LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, frame, coro_fn_ptr_index, "");4922 LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, frame, coro_fn_ptr_index, "");
4925 LLVMValueRef uncasted_fn_val = LLVMBuildLoad(g->builder, fn_ptr_ptr, "");4923 LLVMValueRef uncasted_fn_val = LLVMBuildLoad(g->builder, fn_ptr_ptr, "");
4926 LLVMValueRef fn_val = LLVMBuildIntToPtr(g->builder, uncasted_fn_val, async_fn_llvm_type(g), "");4924 LLVMValueRef fn_val = LLVMBuildIntToPtr(g->builder, uncasted_fn_val, anyframe_fn_type(g), "");
4927 ZigLLVMBuildCall(g->builder, fn_val, &frame, 1, LLVMFastCallConv, ZigLLVM_FnInlineAuto, "");4925 ZigLLVMBuildCall(g->builder, fn_val, &frame, 1, LLVMFastCallConv, ZigLLVM_FnInlineAuto, "");
4928 return nullptr;4926 return nullptr;
4929}4927}
...@@ -5022,7 +5020,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5022,7 +5020,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5022 case IrInstructionIdCallSrc:5020 case IrInstructionIdCallSrc:
5023 case IrInstructionIdAllocaSrc:5021 case IrInstructionIdAllocaSrc:
5024 case IrInstructionIdEndExpr:5022 case IrInstructionIdEndExpr:
5025 case IrInstructionIdAllocaGen:
5026 case IrInstructionIdImplicitCast:5023 case IrInstructionIdImplicitCast:
5027 case IrInstructionIdResolveResult:5024 case IrInstructionIdResolveResult:
5028 case IrInstructionIdResetResult:5025 case IrInstructionIdResetResult:
...@@ -5035,6 +5032,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5035,6 +5032,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5035 case IrInstructionIdUnionInitNamedField:5032 case IrInstructionIdUnionInitNamedField:
5036 case IrInstructionIdFrameType:5033 case IrInstructionIdFrameType:
5037 case IrInstructionIdFrameSizeSrc:5034 case IrInstructionIdFrameSizeSrc:
5035 case IrInstructionIdAllocaGen:
5038 zig_unreachable();5036 zig_unreachable();
50395037
5040 case IrInstructionIdDeclVarGen:5038 case IrInstructionIdDeclVarGen:
...@@ -5195,6 +5193,92 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -5195,6 +5193,92 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
5195 zig_unreachable();5193 zig_unreachable();
5196}5194}
51975195
5196static void render_async_spills(CodeGen *g) {
5197 ZigType *fn_type = g->cur_fn->type_entry;
5198 ZigType *import = get_scope_import(&g->cur_fn->fndef_scope->base);
5199 size_t async_var_index = coro_arg_start + (type_has_bits(fn_type->data.fn.fn_type_id.return_type) ? 2 : 0);
5200 for (size_t var_i = 0; var_i < g->cur_fn->variable_list.length; var_i += 1) {
5201 ZigVar *var = g->cur_fn->variable_list.at(var_i);
5202
5203 if (!type_has_bits(var->var_type)) {
5204 continue;
5205 }
5206 if (ir_get_var_is_comptime(var))
5207 continue;
5208 switch (type_requires_comptime(g, var->var_type)) {
5209 case ReqCompTimeInvalid:
5210 zig_unreachable();
5211 case ReqCompTimeYes:
5212 continue;
5213 case ReqCompTimeNo:
5214 break;
5215 }
5216 if (var->src_arg_index == SIZE_MAX) {
5217 continue;
5218 }
5219
5220 var->value_ref = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, async_var_index,
5221 buf_ptr(&var->name));
5222 async_var_index += 1;
5223 if (var->decl_node) {
5224 var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
5225 buf_ptr(&var->name), import->data.structure.root_struct->di_file,
5226 (unsigned)(var->decl_node->line + 1),
5227 get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0);
5228 gen_var_debug_decl(g, var);
5229 }
5230 }
5231 for (size_t alloca_i = 0; alloca_i < g->cur_fn->alloca_gen_list.length; alloca_i += 1) {
5232 IrInstructionAllocaGen *instruction = g->cur_fn->alloca_gen_list.at(alloca_i);
5233 ZigType *ptr_type = instruction->base.value.type;
5234 assert(ptr_type->id == ZigTypeIdPointer);
5235 ZigType *child_type = ptr_type->data.pointer.child_type;
5236 if (!type_has_bits(child_type))
5237 continue;
5238 if (instruction->base.ref_count == 0)
5239 continue;
5240 if (instruction->base.value.special != ConstValSpecialRuntime) {
5241 if (const_ptr_pointee(nullptr, g, &instruction->base.value, nullptr)->special !=
5242 ConstValSpecialRuntime)
5243 {
5244 continue;
5245 }
5246 }
5247 instruction->base.llvm_value = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, async_var_index,
5248 instruction->name_hint);
5249 async_var_index += 1;
5250 }
5251}
5252
5253static void render_async_var_decls(CodeGen *g, Scope *scope) {
5254 render_async_spills(g);
5255 for (;;) {
5256 switch (scope->id) {
5257 case ScopeIdCImport:
5258 zig_unreachable();
5259 case ScopeIdFnDef:
5260 return;
5261 case ScopeIdVarDecl: {
5262 ZigVar *var = reinterpret_cast<ScopeVarDecl *>(scope)->var;
5263 if (var->ptr_instruction != nullptr) {
5264 render_decl_var(g, var);
5265 }
5266 // fallthrough
5267 }
5268 case ScopeIdDecls:
5269 case ScopeIdBlock:
5270 case ScopeIdDefer:
5271 case ScopeIdDeferExpr:
5272 case ScopeIdLoop:
5273 case ScopeIdSuspend:
5274 case ScopeIdCompTime:
5275 case ScopeIdRuntime:
5276 scope = scope->parent;
5277 continue;
5278 }
5279 }
5280}
5281
5198static void ir_render(CodeGen *g, ZigFn *fn_entry) {5282static void ir_render(CodeGen *g, ZigFn *fn_entry) {
5199 assert(fn_entry);5283 assert(fn_entry);
52005284
...@@ -5204,6 +5288,11 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {...@@ -5204,6 +5288,11 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) {
5204 IrBasicBlock *current_block = executable->basic_block_list.at(block_i);5288 IrBasicBlock *current_block = executable->basic_block_list.at(block_i);
5205 assert(current_block->llvm_block);5289 assert(current_block->llvm_block);
5206 LLVMPositionBuilderAtEnd(g->builder, current_block->llvm_block);5290 LLVMPositionBuilderAtEnd(g->builder, current_block->llvm_block);
5291 if (current_block->split_llvm_fn != nullptr) {
5292 g->cur_fn_val = current_block->split_llvm_fn;
5293 g->cur_ret_ptr = LLVMGetParam(g->cur_fn_val, 0);
5294 render_async_var_decls(g, current_block->instruction_list.at(0)->scope);
5295 }
5207 for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {5296 for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {
5208 IrInstruction *instruction = current_block->instruction_list.at(instr_i);5297 IrInstruction *instruction = current_block->instruction_list.at(instr_i);
5209 if (instruction->ref_count == 0 && !ir_has_side_effects(instruction))5298 if (instruction->ref_count == 0 && !ir_has_side_effects(instruction))
...@@ -6064,19 +6153,17 @@ static void build_all_basic_blocks(CodeGen *g, ZigFn *fn) {...@@ -6064,19 +6153,17 @@ static void build_all_basic_blocks(CodeGen *g, ZigFn *fn) {
6064 IrExecutable *executable = &fn->analyzed_executable;6153 IrExecutable *executable = &fn->analyzed_executable;
6065 assert(executable->basic_block_list.length > 0);6154 assert(executable->basic_block_list.length > 0);
6066 LLVMValueRef fn_val = fn_llvm_value(g, fn);6155 LLVMValueRef fn_val = fn_llvm_value(g, fn);
6067 LLVMBasicBlockRef first_bb = nullptr;
6068 if (fn_is_async(fn)) {
6069 first_bb = LLVMAppendBasicBlock(fn_val, "AsyncSwitch");
6070 fn->preamble_llvm_block = first_bb;
6071 }
6072 for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {6156 for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {
6073 IrBasicBlock *bb = executable->basic_block_list.at(block_i);6157 IrBasicBlock *bb = executable->basic_block_list.at(block_i);
6158 if (bb->split_llvm_fn != nullptr) {
6159 assert(bb->split_llvm_fn == reinterpret_cast<LLVMValueRef>(0x1));
6160 fn_val = make_fn_llvm_value(g, fn);
6161 bb->split_llvm_fn = fn_val;
6162 }
6074 bb->llvm_block = LLVMAppendBasicBlock(fn_val, bb->name_hint);6163 bb->llvm_block = LLVMAppendBasicBlock(fn_val, bb->name_hint);
6075 }6164 }
6076 if (first_bb == nullptr) {6165 IrBasicBlock *entry_bb = executable->basic_block_list.at(0);
6077 first_bb = executable->basic_block_list.at(0)->llvm_block;6166 LLVMPositionBuilderAtEnd(g->builder, entry_bb->llvm_block);
6078 }
6079 LLVMPositionBuilderAtEnd(g->builder, first_bb);
6080}6167}
60816168
6082static void gen_global_var(CodeGen *g, ZigVar *var, LLVMValueRef init_val,6169static void gen_global_var(CodeGen *g, ZigVar *var, LLVMValueRef init_val,
...@@ -6254,7 +6341,6 @@ static void do_code_gen(CodeGen *g) {...@@ -6254,7 +6341,6 @@ static void do_code_gen(CodeGen *g) {
6254 clear_debug_source_node(g);6341 clear_debug_source_node(g);
62556342
6256 bool is_async = fn_is_async(fn_table_entry);6343 bool is_async = fn_is_async(fn_table_entry);
6257 size_t async_var_index = coro_arg_start + (type_has_bits(fn_type_id->return_type) ? 2 : 0);
62586344
6259 if (want_sret || is_async) {6345 if (want_sret || is_async) {
6260 g->cur_ret_ptr = LLVMGetParam(fn, 0);6346 g->cur_ret_ptr = LLVMGetParam(fn, 0);
...@@ -6287,7 +6373,9 @@ static void do_code_gen(CodeGen *g) {...@@ -6287,7 +6373,9 @@ static void do_code_gen(CodeGen *g) {
6287 g->cur_err_ret_trace_val_stack = nullptr;6373 g->cur_err_ret_trace_val_stack = nullptr;
6288 }6374 }
62896375
6290 if (!is_async) {6376 if (is_async) {
6377 render_async_spills(g);
6378 } else {
6291 // allocate temporary stack data6379 // allocate temporary stack data
6292 for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_gen_list.length; alloca_i += 1) {6380 for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_gen_list.length; alloca_i += 1) {
6293 IrInstructionAllocaGen *instruction = fn_table_entry->alloca_gen_list.at(alloca_i);6381 IrInstructionAllocaGen *instruction = fn_table_entry->alloca_gen_list.at(alloca_i);
...@@ -6345,18 +6433,7 @@ static void do_code_gen(CodeGen *g) {...@@ -6345,18 +6433,7 @@ static void do_code_gen(CodeGen *g) {
6345 } else if (is_c_abi) {6433 } else if (is_c_abi) {
6346 fn_walk_var.data.vars.var = var;6434 fn_walk_var.data.vars.var = var;
6347 iter_function_params_c_abi(g, fn_table_entry->type_entry, &fn_walk_var, var->src_arg_index);6435 iter_function_params_c_abi(g, fn_table_entry->type_entry, &fn_walk_var, var->src_arg_index);
6348 } else if (is_async) {6436 } else if (!is_async) {
6349 var->value_ref = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, async_var_index,
6350 buf_ptr(&var->name));
6351 async_var_index += 1;
6352 if (var->decl_node) {
6353 var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope),
6354 buf_ptr(&var->name), import->data.structure.root_struct->di_file,
6355 (unsigned)(var->decl_node->line + 1),
6356 get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0);
6357 gen_var_debug_decl(g, var);
6358 }
6359 } else {
6360 ZigType *gen_type;6437 ZigType *gen_type;
6361 FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index];6438 FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index];
6362 assert(gen_info->gen_index != SIZE_MAX);6439 assert(gen_info->gen_index != SIZE_MAX);
...@@ -6382,29 +6459,6 @@ static void do_code_gen(CodeGen *g) {...@@ -6382,29 +6459,6 @@ static void do_code_gen(CodeGen *g) {
6382 }6459 }
6383 }6460 }
63846461
6385 if (is_async) {
6386 for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_gen_list.length; alloca_i += 1) {
6387 IrInstructionAllocaGen *instruction = fn_table_entry->alloca_gen_list.at(alloca_i);
6388 ZigType *ptr_type = instruction->base.value.type;
6389 assert(ptr_type->id == ZigTypeIdPointer);
6390 ZigType *child_type = ptr_type->data.pointer.child_type;
6391 if (!type_has_bits(child_type))
6392 continue;
6393 if (instruction->base.ref_count == 0)
6394 continue;
6395 if (instruction->base.value.special != ConstValSpecialRuntime) {
6396 if (const_ptr_pointee(nullptr, g, &instruction->base.value, nullptr)->special !=
6397 ConstValSpecialRuntime)
6398 {
6399 continue;
6400 }
6401 }
6402 instruction->base.llvm_value = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, async_var_index,
6403 instruction->name_hint);
6404 async_var_index += 1;
6405 }
6406 }
6407
6408 // finishing error return trace setup. we have to do this after all the allocas.6462 // finishing error return trace setup. we have to do this after all the allocas.
6409 if (have_err_ret_trace_stack) {6463 if (have_err_ret_trace_stack) {
6410 ZigType *usize = g->builtin_types.entry_usize;6464 ZigType *usize = g->builtin_types.entry_usize;
...@@ -6435,31 +6489,16 @@ static void do_code_gen(CodeGen *g) {...@@ -6435,31 +6489,16 @@ static void do_code_gen(CodeGen *g) {
6435 LLVMValueRef size_val = LLVMConstInt(usize_type_ref, fn_table_entry->frame_type->abi_size, false);6489 LLVMValueRef size_val = LLVMConstInt(usize_type_ref, fn_table_entry->frame_type->abi_size, false);
6436 ZigLLVMFunctionSetPrefixData(fn_table_entry->llvm_value, size_val);6490 ZigLLVMFunctionSetPrefixData(fn_table_entry->llvm_value, size_val);
64376491
6438 if (!g->strip_debug_symbols) {6492 if (ir_want_runtime_safety_scope(g, fn_table_entry->child_scope)) {
6439 AstNode *source_node = fn_table_entry->proto_node;6493 IrBasicBlock *bad_resume_block = allocate<IrBasicBlock>(1);
6440 ZigLLVMSetCurrentDebugLocation(g->builder, (int)source_node->line + 1,6494 bad_resume_block->name_hint = "BadResume";
6441 (int)source_node->column + 1, get_di_scope(g, fn_table_entry->child_scope));6495 bad_resume_block->split_llvm_fn = make_fn_llvm_value(g, fn_table_entry);
6442 }6496
6443 IrExecutable *executable = &fn_table_entry->analyzed_executable;6497 LLVMBasicBlockRef llvm_block = LLVMAppendBasicBlock(bad_resume_block->split_llvm_fn, "BadResume");
6444 LLVMBasicBlockRef bad_resume_block = LLVMAppendBasicBlock(g->cur_fn_val, "BadResume");6498 LLVMPositionBuilderAtEnd(g->builder, llvm_block);
6445 LLVMPositionBuilderAtEnd(g->builder, bad_resume_block);6499 gen_safety_crash(g, PanicMsgIdBadResume);
6446 gen_assertion_scope(g, PanicMsgIdBadResume, fn_table_entry->child_scope);6500
64476501 fn_table_entry->resume_blocks.append(bad_resume_block);
6448 LLVMPositionBuilderAtEnd(g->builder, fn_table_entry->preamble_llvm_block);
6449 LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr,
6450 coro_resume_index_index, "");
6451 LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, "");
6452 // +1 - index 0 is reserved for the entry block
6453 LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, resume_index, bad_resume_block,
6454 fn_table_entry->resume_blocks.length + 1);
6455
6456 LLVMValueRef zero = LLVMConstNull(usize_type_ref);
6457 LLVMAddCase(switch_instr, zero, executable->basic_block_list.at(0)->llvm_block);
6458
6459 for (size_t resume_i = 0; resume_i < fn_table_entry->resume_blocks.length; resume_i += 1) {
6460 IrBasicBlock *resume_block = fn_table_entry->resume_blocks.at(resume_i);
6461 LLVMValueRef case_value = LLVMConstInt(usize_type_ref, resume_block->resume_index, false);
6462 LLVMAddCase(switch_instr, case_value, resume_block->llvm_block);
6463 }6502 }
6464 } else {6503 } else {
6465 // create debug variable declarations for parameters6504 // create debug variable declarations for parameters
...@@ -6472,7 +6511,6 @@ static void do_code_gen(CodeGen *g) {...@@ -6472,7 +6511,6 @@ static void do_code_gen(CodeGen *g) {
6472 walk_function_params(g, fn_table_entry->type_entry, &fn_walk_init);6511 walk_function_params(g, fn_table_entry->type_entry, &fn_walk_init);
6473 }6512 }
64746513
6475
6476 ir_render(g, fn_table_entry);6514 ir_render(g, fn_table_entry);
64776515
6478 }6516 }
src/ir.cpp+4-4
...@@ -3227,7 +3227,7 @@ static IrInstruction *ir_build_alloca_src(IrBuilder *irb, Scope *scope, AstNode...@@ -3227,7 +3227,7 @@ static IrInstruction *ir_build_alloca_src(IrBuilder *irb, Scope *scope, AstNode
3227 return &instruction->base;3227 return &instruction->base;
3228}3228}
32293229
3230static IrInstructionAllocaGen *ir_create_alloca_gen(IrAnalyze *ira, IrInstruction *source_instruction,3230static IrInstructionAllocaGen *ir_build_alloca_gen(IrAnalyze *ira, IrInstruction *source_instruction,
3231 uint32_t align, const char *name_hint)3231 uint32_t align, const char *name_hint)
3232{3232{
3233 IrInstructionAllocaGen *instruction = ir_create_instruction<IrInstructionAllocaGen>(&ira->new_irb,3233 IrInstructionAllocaGen *instruction = ir_create_instruction<IrInstructionAllocaGen>(&ira->new_irb,
...@@ -14351,7 +14351,7 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in...@@ -14351,7 +14351,7 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in
14351 ConstExprValue *pointee = create_const_vals(1);14351 ConstExprValue *pointee = create_const_vals(1);
14352 pointee->special = ConstValSpecialUndef;14352 pointee->special = ConstValSpecialUndef;
1435314353
14354 IrInstructionAllocaGen *result = ir_create_alloca_gen(ira, source_inst, align, name_hint);14354 IrInstructionAllocaGen *result = ir_build_alloca_gen(ira, source_inst, align, name_hint);
14355 result->base.value.special = ConstValSpecialStatic;14355 result->base.value.special = ConstValSpecialStatic;
14356 result->base.value.data.x_ptr.special = ConstPtrSpecialRef;14356 result->base.value.data.x_ptr.special = ConstPtrSpecialRef;
14357 result->base.value.data.x_ptr.mut = force_comptime ? ConstPtrMutComptimeVar : ConstPtrMutInfer;14357 result->base.value.data.x_ptr.mut = force_comptime ? ConstPtrMutComptimeVar : ConstPtrMutInfer;
...@@ -14448,7 +14448,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe...@@ -14448,7 +14448,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
14448 return nullptr;14448 return nullptr;
14449 }14449 }
14450 // need to return a result location and don't have one. use a stack allocation14450 // need to return a result location and don't have one. use a stack allocation
14451 IrInstructionAllocaGen *alloca_gen = ir_create_alloca_gen(ira, suspend_source_instr, 0, "");14451 IrInstructionAllocaGen *alloca_gen = ir_build_alloca_gen(ira, suspend_source_instr, 0, "");
14452 if ((err = type_resolve(ira->codegen, value_type, ResolveStatusZeroBitsKnown)))14452 if ((err = type_resolve(ira->codegen, value_type, ResolveStatusZeroBitsKnown)))
14453 return ira->codegen->invalid_instruction;14453 return ira->codegen->invalid_instruction;
14454 alloca_gen->base.value.type = get_pointer_to_type_extra(ira->codegen, value_type, false, false,14454 alloca_gen->base.value.type = get_pointer_to_type_extra(ira->codegen, value_type, false, false,
...@@ -24357,7 +24357,7 @@ static IrInstruction *ir_analyze_instruction_suspend_br(IrAnalyze *ira, IrInstru...@@ -24357,7 +24357,7 @@ static IrInstruction *ir_analyze_instruction_suspend_br(IrAnalyze *ira, IrInstru
24357 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);24357 ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec);
24358 ir_assert(fn_entry != nullptr, &instruction->base);24358 ir_assert(fn_entry != nullptr, &instruction->base);
2435924359
24360 new_bb->resume_index = fn_entry->resume_blocks.length + coro_extra_resume_block_count;24360 new_bb->split_llvm_fn = reinterpret_cast<LLVMValueRef>(0x1);
2436124361
24362 fn_entry->resume_blocks.append(new_bb);24362 fn_entry->resume_blocks.append(new_bb);
24363 if (fn_entry->inferred_async_node == nullptr) {24363 if (fn_entry->inferred_async_node == nullptr) {
test/stage1/behavior/coroutines.zig+49-49
...@@ -82,55 +82,55 @@ test "local variable in async function" {...@@ -82,55 +82,55 @@ test "local variable in async function" {
82 S.doTheTest();82 S.doTheTest();
83}83}
8484
85test "calling an inferred async function" {85//test "calling an inferred async function" {
86 const S = struct {86// const S = struct {
87 var x: i32 = 1;87// var x: i32 = 1;
88 var other_frame: *@Frame(other) = undefined;88// var other_frame: *@Frame(other) = undefined;
8989//
90 fn doTheTest() void {90// fn doTheTest() void {
91 const p = async first();91// const p = async first();
92 expect(x == 1);92// expect(x == 1);
93 resume other_frame.*;93// resume other_frame.*;
94 expect(x == 2);94// expect(x == 2);
95 }95// }
9696//
97 fn first() void {97// fn first() void {
98 other();98// other();
99 }99// }
100 fn other() void {100// fn other() void {
101 other_frame = @frame();101// other_frame = @frame();
102 suspend;102// suspend;
103 x += 1;103// x += 1;
104 }104// }
105 };105// };
106 S.doTheTest();106// S.doTheTest();
107}107//}
108108//
109test "@frameSize" {109//test "@frameSize" {
110 const S = struct {110// const S = struct {
111 fn doTheTest() void {111// fn doTheTest() void {
112 {112// {
113 var ptr = @ptrCast(async fn(i32) void, other);113// var ptr = @ptrCast(async fn(i32) void, other);
114 const size = @frameSize(ptr);114// const size = @frameSize(ptr);
115 expect(size == @sizeOf(@Frame(other)));115// expect(size == @sizeOf(@Frame(other)));
116 }116// }
117 {117// {
118 var ptr = @ptrCast(async fn() void, first);118// var ptr = @ptrCast(async fn() void, first);
119 const size = @frameSize(ptr);119// const size = @frameSize(ptr);
120 expect(size == @sizeOf(@Frame(first)));120// expect(size == @sizeOf(@Frame(first)));
121 }121// }
122 }122// }
123123//
124 fn first() void {124// fn first() void {
125 other(1);125// other(1);
126 }126// }
127 fn other(param: i32) void {127// fn other(param: i32) void {
128 var local: i32 = undefined;128// var local: i32 = undefined;
129 suspend;129// suspend;
130 }130// }
131 };131// };
132 S.doTheTest();132// S.doTheTest();
133}133//}
134134
135//test "coroutine suspend, resume" {135//test "coroutine suspend, resume" {
136// seq('a');136// seq('a');