| author | |
| committer | |
| log | 0d8c9fcb18b399bd2afedbcbcc7736326ef92297 |
| tree | 8a5191a67c15148bbf0dbb50bdaef14c15794256 |
| parent | f27e5d439c121e620b2c0d9d7a6a8f4154826aa8 |
| signature | Commit is signed but in an unrecognized format. |
7 files changed, 269 insertions(+), 189 deletions(-)
BRANCH_TODO+2| ... | @@ -1,3 +1,4 @@ | ... | @@ -1,3 +1,4 @@ |
| 1 | * delete IrInstructionMarkErrRetTracePtr | ||
| 1 | * go over the commented out tests | 2 | * go over the commented out tests |
| 2 | * error return tracing | 3 | * error return tracing |
| 3 | * compile error for error: expected anyframe->T, found 'anyframe' | 4 | * compile error for error: expected anyframe->T, found 'anyframe' |
| ... | @@ -32,3 +33,4 @@ | ... | @@ -32,3 +33,4 @@ |
| 32 | - resume | 33 | - resume |
| 33 | - anyframe, anyframe->T | 34 | - anyframe, anyframe->T |
| 34 | * safety for double await | 35 | * safety for double await |
| 36 | * call graph analysis to have fewer stack trace frames |
src/all_types.hpp+1-1| ... | @@ -3705,7 +3705,7 @@ static const size_t err_union_payload_index = 1; | ... | @@ -3705,7 +3705,7 @@ static const size_t err_union_payload_index = 1; |
| 3705 | static const size_t coro_fn_ptr_index = 0; | 3705 | static const size_t coro_fn_ptr_index = 0; |
| 3706 | static const size_t coro_resume_index = 1; | 3706 | static const size_t coro_resume_index = 1; |
| 3707 | static const size_t coro_awaiter_index = 2; | 3707 | static const size_t coro_awaiter_index = 2; |
| 3708 | static const size_t coro_arg_start = 3; | 3708 | static const size_t coro_ret_start = 3; |
| 3709 | 3709 | ||
| 3710 | // TODO call graph analysis to find out what this number needs to be for every function | 3710 | // TODO call graph analysis to find out what this number needs to be for every function |
| 3711 | // MUST BE A POWER OF TWO. | 3711 | // MUST BE A POWER OF TWO. |
src/analyze.cpp+123-103| ... | @@ -7,6 +7,7 @@ | ... | @@ -7,6 +7,7 @@ |
| 7 | 7 | ||
| 8 | #include "analyze.hpp" | 8 | #include "analyze.hpp" |
| 9 | #include "ast_render.hpp" | 9 | #include "ast_render.hpp" |
| 10 | #include "codegen.hpp" | ||
| 10 | #include "config.h" | 11 | #include "config.h" |
| 11 | #include "error.hpp" | 12 | #include "error.hpp" |
| 12 | #include "ir.hpp" | 13 | #include "ir.hpp" |
| ... | @@ -5212,23 +5213,34 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { | ... | @@ -5212,23 +5213,34 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { |
| 5212 | ZigList<ZigType *> field_types = {}; | 5213 | ZigList<ZigType *> field_types = {}; |
| 5213 | ZigList<const char *> field_names = {}; | 5214 | ZigList<const char *> field_names = {}; |
| 5214 | 5215 | ||
| 5215 | field_names.append("fn_ptr"); | 5216 | field_names.append("@fn_ptr"); |
| 5216 | field_types.append(fn_type); | 5217 | field_types.append(fn_type); |
| 5217 | 5218 | ||
| 5218 | field_names.append("resume_index"); | 5219 | field_names.append("@resume_index"); |
| 5219 | field_types.append(g->builtin_types.entry_usize); | 5220 | field_types.append(g->builtin_types.entry_usize); |
| 5220 | 5221 | ||
| 5221 | field_names.append("awaiter"); | 5222 | field_names.append("@awaiter"); |
| 5222 | field_types.append(g->builtin_types.entry_usize); | 5223 | field_types.append(g->builtin_types.entry_usize); |
| 5223 | 5224 | ||
| 5224 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; | 5225 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; |
| 5225 | ZigType *ptr_return_type = get_pointer_to_type(g, fn_type_id->return_type, false); | 5226 | ZigType *ptr_return_type = get_pointer_to_type(g, fn_type_id->return_type, false); |
| 5226 | field_names.append("result_ptr"); | 5227 | field_names.append("@ptr_result"); |
| 5227 | field_types.append(ptr_return_type); | 5228 | field_types.append(ptr_return_type); |
| 5228 | 5229 | ||
| 5229 | field_names.append("result"); | 5230 | field_names.append("@result"); |
| 5230 | field_types.append(fn_type_id->return_type); | 5231 | field_types.append(fn_type_id->return_type); |
| 5231 | 5232 | ||
| 5233 | if (codegen_fn_has_err_ret_tracing(g, fn_type_id->return_type)) { | ||
| 5234 | field_names.append("@ptr_stack_trace"); | ||
| 5235 | field_types.append(get_ptr_to_stack_trace_type(g)); | ||
| 5236 | |||
| 5237 | field_names.append("@stack_trace"); | ||
| 5238 | field_types.append(g->stack_trace_type); | ||
| 5239 | |||
| 5240 | field_names.append("@instruction_addresses"); | ||
| 5241 | field_types.append(get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count)); | ||
| 5242 | } | ||
| 5243 | |||
| 5232 | for (size_t arg_i = 0; arg_i < fn_type_id->param_count; arg_i += 1) { | 5244 | for (size_t arg_i = 0; arg_i < fn_type_id->param_count; arg_i += 1) { |
| 5233 | FnTypeParamInfo *param_info = &fn_type_id->param_info[arg_i]; | 5245 | FnTypeParamInfo *param_info = &fn_type_id->param_info[arg_i]; |
| 5234 | AstNode *param_decl_node = get_param_decl_node(fn, arg_i); | 5246 | AstNode *param_decl_node = get_param_decl_node(fn, arg_i); |
| ... | @@ -5237,7 +5249,7 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { | ... | @@ -5237,7 +5249,7 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { |
| 5237 | if (param_decl_node && !is_var_args) { | 5249 | if (param_decl_node && !is_var_args) { |
| 5238 | param_name = param_decl_node->data.param_decl.name; | 5250 | param_name = param_decl_node->data.param_decl.name; |
| 5239 | } else { | 5251 | } else { |
| 5240 | param_name = buf_sprintf("arg%" ZIG_PRI_usize "", arg_i); | 5252 | param_name = buf_sprintf("@arg%" ZIG_PRI_usize, arg_i); |
| 5241 | } | 5253 | } |
| 5242 | ZigType *param_type = param_info->type; | 5254 | ZigType *param_type = param_info->type; |
| 5243 | field_names.append(buf_ptr(param_name)); | 5255 | field_names.append(buf_ptr(param_name)); |
| ... | @@ -5260,7 +5272,13 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { | ... | @@ -5260,7 +5272,13 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { |
| 5260 | continue; | 5272 | continue; |
| 5261 | } | 5273 | } |
| 5262 | } | 5274 | } |
| 5263 | field_names.append(instruction->name_hint); | 5275 | const char *name; |
| 5276 | if (*instruction->name_hint == 0) { | ||
| 5277 | name = buf_ptr(buf_sprintf("@local%" ZIG_PRI_usize, alloca_i)); | ||
| 5278 | } else { | ||
| 5279 | name = instruction->name_hint; | ||
| 5280 | } | ||
| 5281 | field_names.append(name); | ||
| 5264 | field_types.append(child_type); | 5282 | field_types.append(child_type); |
| 5265 | } | 5283 | } |
| 5266 | 5284 | ||
| ... | @@ -7369,7 +7387,7 @@ static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) { | ... | @@ -7369,7 +7387,7 @@ static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) { |
| 7369 | } | 7387 | } |
| 7370 | fn_type->data.fn.gen_return_type = gen_return_type; | 7388 | fn_type->data.fn.gen_return_type = gen_return_type; |
| 7371 | 7389 | ||
| 7372 | if (prefix_arg_error_return_trace) { | 7390 | if (prefix_arg_error_return_trace && !is_async) { |
| 7373 | ZigType *gen_type = get_ptr_to_stack_trace_type(g); | 7391 | ZigType *gen_type = get_ptr_to_stack_trace_type(g); |
| 7374 | gen_param_types.append(get_llvm_type(g, gen_type)); | 7392 | gen_param_types.append(get_llvm_type(g, gen_type)); |
| 7375 | param_di_types.append(get_llvm_di_type(g, gen_type)); | 7393 | param_di_types.append(get_llvm_di_type(g, gen_type)); |
| ... | @@ -7527,110 +7545,112 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re | ... | @@ -7527,110 +7545,112 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re |
| 7527 | ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit); | 7545 | ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit); |
| 7528 | 7546 | ||
| 7529 | ZigType *result_type = any_frame_type->data.any_frame.result_type; | 7547 | ZigType *result_type = any_frame_type->data.any_frame.result_type; |
| 7530 | if (result_type == nullptr || !type_has_bits(result_type)) { | 7548 | ZigType *ptr_result_type = (result_type == nullptr) ? nullptr : get_pointer_to_type(g, result_type, false); |
| 7531 | LLVMTypeRef ptr_result_type = LLVMPointerType(fn_type, 0); | 7549 | LLVMTypeRef ptr_fn_llvm_type = LLVMPointerType(fn_type, 0); |
| 7532 | if (result_type == nullptr) { | 7550 | if (result_type == nullptr) { |
| 7533 | g->anyframe_fn_type = ptr_result_type; | 7551 | g->anyframe_fn_type = ptr_fn_llvm_type; |
| 7534 | } | 7552 | } |
| 7535 | // label (grep this): [coro_frame_struct_layout] | ||
| 7536 | LLVMTypeRef field_types[] = { | ||
| 7537 | ptr_result_type, // fn_ptr | ||
| 7538 | usize_type_ref, // resume_index | ||
| 7539 | usize_type_ref, // awaiter | ||
| 7540 | }; | ||
| 7541 | LLVMStructSetBody(frame_header_type, field_types, 3, false); | ||
| 7542 | 7553 | ||
| 7543 | ZigLLVMDIType *di_element_types[] = { | 7554 | ZigList<LLVMTypeRef> field_types = {}; |
| 7544 | ZigLLVMCreateDebugMemberType(g->dbuilder, | 7555 | ZigList<ZigLLVMDIType *> di_element_types = {}; |
| 7545 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "fn_ptr", | ||
| 7546 | di_file, line, | ||
| 7547 | 8*LLVMABISizeOfType(g->target_data_ref, field_types[0]), | ||
| 7548 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types[0]), | ||
| 7549 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, 0), | ||
| 7550 | ZigLLVM_DIFlags_Zero, usize_di_type), | ||
| 7551 | ZigLLVMCreateDebugMemberType(g->dbuilder, | ||
| 7552 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "resume_index", | ||
| 7553 | di_file, line, | ||
| 7554 | 8*LLVMABISizeOfType(g->target_data_ref, field_types[1]), | ||
| 7555 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types[1]), | ||
| 7556 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, 1), | ||
| 7557 | ZigLLVM_DIFlags_Zero, usize_di_type), | ||
| 7558 | ZigLLVMCreateDebugMemberType(g->dbuilder, | ||
| 7559 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "awaiter", | ||
| 7560 | di_file, line, | ||
| 7561 | 8*LLVMABISizeOfType(g->target_data_ref, field_types[2]), | ||
| 7562 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types[2]), | ||
| 7563 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, 2), | ||
| 7564 | ZigLLVM_DIFlags_Zero, usize_di_type), | ||
| 7565 | }; | ||
| 7566 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, | ||
| 7567 | compile_unit_scope, buf_ptr(name), | ||
| 7568 | di_file, line, | ||
| 7569 | 8*LLVMABISizeOfType(g->target_data_ref, frame_header_type), | ||
| 7570 | 8*LLVMABIAlignmentOfType(g->target_data_ref, frame_header_type), | ||
| 7571 | ZigLLVM_DIFlags_Zero, | ||
| 7572 | nullptr, di_element_types, 3, 0, nullptr, ""); | ||
| 7573 | 7556 | ||
| 7574 | ZigLLVMReplaceTemporary(g->dbuilder, frame_header_di_type, replacement_di_type); | 7557 | // label (grep this): [coro_frame_struct_layout] |
| 7575 | } else { | 7558 | field_types.append(ptr_fn_llvm_type); // fn_ptr |
| 7576 | ZigType *ptr_result_type = get_pointer_to_type(g, result_type, false); | 7559 | field_types.append(usize_type_ref); // resume_index |
| 7577 | // label (grep this): [coro_frame_struct_layout] | 7560 | field_types.append(usize_type_ref); // awaiter |
| 7578 | LLVMTypeRef field_types[] = { | ||
| 7579 | LLVMPointerType(fn_type, 0), // fn_ptr | ||
| 7580 | usize_type_ref, // resume_index | ||
| 7581 | usize_type_ref, // awaiter | ||
| 7582 | get_llvm_type(g, ptr_result_type), // result_ptr | ||
| 7583 | get_llvm_type(g, result_type), // result | ||
| 7584 | }; | ||
| 7585 | LLVMStructSetBody(frame_header_type, field_types, 5, false); | ||
| 7586 | 7561 | ||
| 7587 | ZigLLVMDIType *di_element_types[] = { | 7562 | bool have_result_type = result_type != nullptr && type_has_bits(result_type); |
| 7588 | ZigLLVMCreateDebugMemberType(g->dbuilder, | 7563 | if (have_result_type) { |
| 7589 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "fn_ptr", | 7564 | field_types.append(get_llvm_type(g, ptr_result_type)); // ptr_result |
| 7590 | di_file, line, | 7565 | field_types.append(get_llvm_type(g, result_type)); // result |
| 7591 | 8*LLVMABISizeOfType(g->target_data_ref, field_types[0]), | 7566 | if (codegen_fn_has_err_ret_tracing(g, result_type)) { |
| 7592 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types[0]), | 7567 | field_types.append(get_llvm_type(g, get_ptr_to_stack_trace_type(g))); // ptr_stack_trace |
| 7593 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, 0), | 7568 | field_types.append(get_llvm_type(g, g->stack_trace_type)); // stack_trace |
| 7594 | ZigLLVM_DIFlags_Zero, usize_di_type), | 7569 | field_types.append(get_llvm_type(g, get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count))); // instruction_addresses |
| 7595 | ZigLLVMCreateDebugMemberType(g->dbuilder, | 7570 | } |
| 7596 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "awaiter", | 7571 | } |
| 7597 | di_file, line, | 7572 | LLVMStructSetBody(frame_header_type, field_types.items, field_types.length, false); |
| 7598 | 8*LLVMABISizeOfType(g->target_data_ref, field_types[1]), | 7573 | |
| 7599 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types[1]), | 7574 | di_element_types.append( |
| 7600 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, 1), | 7575 | ZigLLVMCreateDebugMemberType(g->dbuilder, |
| 7601 | ZigLLVM_DIFlags_Zero, usize_di_type), | 7576 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "fn_ptr", |
| 7602 | ZigLLVMCreateDebugMemberType(g->dbuilder, | 7577 | di_file, line, |
| 7603 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "awaiter", | 7578 | 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)), |
| 7604 | di_file, line, | 7579 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)), |
| 7605 | 8*LLVMABISizeOfType(g->target_data_ref, field_types[2]), | 7580 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length), |
| 7606 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types[2]), | 7581 | ZigLLVM_DIFlags_Zero, usize_di_type)); |
| 7607 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, 2), | 7582 | di_element_types.append( |
| 7608 | ZigLLVM_DIFlags_Zero, usize_di_type), | 7583 | ZigLLVMCreateDebugMemberType(g->dbuilder, |
| 7584 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "resume_index", | ||
| 7585 | di_file, line, | ||
| 7586 | 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)), | ||
| 7587 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)), | ||
| 7588 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length), | ||
| 7589 | ZigLLVM_DIFlags_Zero, usize_di_type)); | ||
| 7590 | di_element_types.append( | ||
| 7591 | ZigLLVMCreateDebugMemberType(g->dbuilder, | ||
| 7592 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "awaiter", | ||
| 7593 | di_file, line, | ||
| 7594 | 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)), | ||
| 7595 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)), | ||
| 7596 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length), | ||
| 7597 | ZigLLVM_DIFlags_Zero, usize_di_type)); | ||
| 7598 | |||
| 7599 | if (have_result_type) { | ||
| 7600 | di_element_types.append( | ||
| 7609 | ZigLLVMCreateDebugMemberType(g->dbuilder, | 7601 | ZigLLVMCreateDebugMemberType(g->dbuilder, |
| 7610 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "result_ptr", | 7602 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "ptr_result", |
| 7611 | di_file, line, | 7603 | di_file, line, |
| 7612 | 8*LLVMABISizeOfType(g->target_data_ref, field_types[3]), | 7604 | 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)), |
| 7613 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types[3]), | 7605 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)), |
| 7614 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, 3), | 7606 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length), |
| 7615 | ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, ptr_result_type)), | 7607 | ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, ptr_result_type))); |
| 7608 | di_element_types.append( | ||
| 7616 | ZigLLVMCreateDebugMemberType(g->dbuilder, | 7609 | ZigLLVMCreateDebugMemberType(g->dbuilder, |
| 7617 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "result", | 7610 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "result", |
| 7618 | di_file, line, | 7611 | di_file, line, |
| 7619 | 8*LLVMABISizeOfType(g->target_data_ref, field_types[4]), | 7612 | 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)), |
| 7620 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types[4]), | 7613 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)), |
| 7621 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, 4), | 7614 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length), |
| 7622 | ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, result_type)), | 7615 | ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, result_type))); |
| 7623 | }; | 7616 | |
| 7624 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, | 7617 | if (codegen_fn_has_err_ret_tracing(g, result_type)) { |
| 7625 | compile_unit_scope, buf_ptr(name), | 7618 | di_element_types.append( |
| 7626 | di_file, line, | 7619 | ZigLLVMCreateDebugMemberType(g->dbuilder, |
| 7627 | 8*LLVMABISizeOfType(g->target_data_ref, frame_header_type), | 7620 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "ptr_stack_trace", |
| 7628 | 8*LLVMABIAlignmentOfType(g->target_data_ref, frame_header_type), | 7621 | di_file, line, |
| 7629 | ZigLLVM_DIFlags_Zero, | 7622 | 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)), |
| 7630 | nullptr, di_element_types, 5, 0, nullptr, ""); | 7623 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)), |
| 7624 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length), | ||
| 7625 | ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, get_ptr_to_stack_trace_type(g)))); | ||
| 7626 | di_element_types.append( | ||
| 7627 | ZigLLVMCreateDebugMemberType(g->dbuilder, | ||
| 7628 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "stack_trace", | ||
| 7629 | di_file, line, | ||
| 7630 | 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)), | ||
| 7631 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)), | ||
| 7632 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length), | ||
| 7633 | ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, g->stack_trace_type))); | ||
| 7634 | di_element_types.append( | ||
| 7635 | ZigLLVMCreateDebugMemberType(g->dbuilder, | ||
| 7636 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "instruction_addresses", | ||
| 7637 | di_file, line, | ||
| 7638 | 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)), | ||
| 7639 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)), | ||
| 7640 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length), | ||
| 7641 | ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count)))); | ||
| 7642 | } | ||
| 7643 | }; | ||
| 7631 | 7644 | ||
| 7632 | ZigLLVMReplaceTemporary(g->dbuilder, frame_header_di_type, replacement_di_type); | 7645 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, |
| 7633 | } | 7646 | compile_unit_scope, buf_ptr(name), |
| 7647 | di_file, line, | ||
| 7648 | 8*LLVMABISizeOfType(g->target_data_ref, frame_header_type), | ||
| 7649 | 8*LLVMABIAlignmentOfType(g->target_data_ref, frame_header_type), | ||
| 7650 | ZigLLVM_DIFlags_Zero, | ||
| 7651 | nullptr, di_element_types.items, di_element_types.length, 0, nullptr, ""); | ||
| 7652 | |||
| 7653 | ZigLLVMReplaceTemporary(g->dbuilder, frame_header_di_type, replacement_di_type); | ||
| 7634 | } | 7654 | } |
| 7635 | 7655 | ||
| 7636 | static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) { | 7656 | static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) { |
src/codegen.cpp+86-55| ... | @@ -297,12 +297,30 @@ static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) { | ... | @@ -297,12 +297,30 @@ static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) { |
| 297 | zig_unreachable(); | 297 | zig_unreachable(); |
| 298 | } | 298 | } |
| 299 | 299 | ||
| 300 | // label (grep this): [coro_frame_struct_layout] | ||
| 301 | static uint32_t frame_index_trace(CodeGen *g, FnTypeId *fn_type_id) { | ||
| 302 | // [0] *ReturnType | ||
| 303 | // [1] ReturnType | ||
| 304 | uint32_t return_field_count = type_has_bits(fn_type_id->return_type) ? 2 : 0; | ||
| 305 | return coro_ret_start + return_field_count; | ||
| 306 | } | ||
| 307 | |||
| 308 | // label (grep this): [coro_frame_struct_layout] | ||
| 309 | static uint32_t frame_index_arg(CodeGen *g, FnTypeId *fn_type_id) { | ||
| 310 | bool have_stack_trace = g->have_err_ret_tracing && codegen_fn_has_err_ret_tracing(g, fn_type_id->return_type); | ||
| 311 | // [0] *StackTrace | ||
| 312 | // [1] StackTrace | ||
| 313 | // [2] [stack_trace_ptr_count]usize | ||
| 314 | uint32_t trace_field_count = have_stack_trace ? 3 : 0; | ||
| 315 | return frame_index_trace(g, fn_type_id) + trace_field_count; | ||
| 316 | } | ||
| 317 | |||
| 300 | static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) { | 318 | static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) { |
| 301 | if (!g->have_err_ret_tracing) { | 319 | if (!g->have_err_ret_tracing) { |
| 302 | return UINT32_MAX; | 320 | return UINT32_MAX; |
| 303 | } | 321 | } |
| 304 | if (fn_table_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync) { | 322 | if (fn_is_async(fn_table_entry)) { |
| 305 | return 0; | 323 | return UINT32_MAX; |
| 306 | } | 324 | } |
| 307 | ZigType *fn_type = fn_table_entry->type_entry; | 325 | ZigType *fn_type = fn_table_entry->type_entry; |
| 308 | if (!fn_type_can_fail(&fn_type->data.fn.fn_type_id)) { | 326 | if (!fn_type_can_fail(&fn_type->data.fn.fn_type_id)) { |
| ... | @@ -438,10 +456,6 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { | ... | @@ -438,10 +456,6 @@ static LLVMValueRef make_fn_llvm_value(CodeGen *g, ZigFn *fn) { |
| 438 | } else { | 456 | } else { |
| 439 | LLVMSetFunctionCallConv(llvm_fn, get_llvm_cc(g, fn_type->data.fn.fn_type_id.cc)); | 457 | LLVMSetFunctionCallConv(llvm_fn, get_llvm_cc(g, fn_type->data.fn.fn_type_id.cc)); |
| 440 | } | 458 | } |
| 441 | if (cc == CallingConventionAsync) { | ||
| 442 | addLLVMFnAttr(llvm_fn, "optnone"); | ||
| 443 | addLLVMFnAttr(llvm_fn, "noinline"); | ||
| 444 | } | ||
| 445 | 459 | ||
| 446 | bool want_cold = fn->is_cold || cc == CallingConventionCold; | 460 | bool want_cold = fn->is_cold || cc == CallingConventionCold; |
| 447 | if (want_cold) { | 461 | if (want_cold) { |
| ... | @@ -1273,8 +1287,8 @@ static LLVMValueRef get_cur_err_ret_trace_val(CodeGen *g, Scope *scope) { | ... | @@ -1273,8 +1287,8 @@ static LLVMValueRef get_cur_err_ret_trace_val(CodeGen *g, Scope *scope) { |
| 1273 | if (!g->have_err_ret_tracing) { | 1287 | if (!g->have_err_ret_tracing) { |
| 1274 | return nullptr; | 1288 | return nullptr; |
| 1275 | } | 1289 | } |
| 1276 | if (g->cur_fn->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync) { | 1290 | if (fn_is_async(g->cur_fn)) { |
| 1277 | return g->cur_err_ret_trace_val_stack; | 1291 | return LLVMBuildLoad(g->builder, g->cur_err_ret_trace_val_arg, ""); |
| 1278 | } | 1292 | } |
| 1279 | if (g->cur_err_ret_trace_val_stack != nullptr) { | 1293 | if (g->cur_err_ret_trace_val_stack != nullptr) { |
| 1280 | return g->cur_err_ret_trace_val_stack; | 1294 | return g->cur_err_ret_trace_val_stack; |
| ... | @@ -2006,7 +2020,6 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, | ... | @@ -2006,7 +2020,6 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, |
| 2006 | { | 2020 | { |
| 2007 | if (fn_is_async(g->cur_fn)) { | 2021 | if (fn_is_async(g->cur_fn)) { |
| 2008 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; | 2022 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; |
| 2009 | LLVMValueRef locals_ptr = g->cur_ret_ptr; | ||
| 2010 | bool ret_type_has_bits = return_instruction->value != nullptr && | 2023 | bool ret_type_has_bits = return_instruction->value != nullptr && |
| 2011 | type_has_bits(return_instruction->value->value.type); | 2024 | type_has_bits(return_instruction->value->value.type); |
| 2012 | ZigType *ret_type = ret_type_has_bits ? return_instruction->value->value.type : nullptr; | 2025 | ZigType *ret_type = ret_type_has_bits ? return_instruction->value->value.type : nullptr; |
| ... | @@ -2018,7 +2031,7 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, | ... | @@ -2018,7 +2031,7 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, |
| 2018 | 2031 | ||
| 2019 | LLVMValueRef result_ptr_as_usize; | 2032 | LLVMValueRef result_ptr_as_usize; |
| 2020 | if (ret_type_has_bits) { | 2033 | if (ret_type_has_bits) { |
| 2021 | LLVMValueRef result_ptr_ptr = LLVMBuildStructGEP(g->builder, locals_ptr, coro_arg_start, ""); | 2034 | LLVMValueRef result_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_ret_start, ""); |
| 2022 | LLVMValueRef result_ptr = LLVMBuildLoad(g->builder, result_ptr_ptr, ""); | 2035 | LLVMValueRef result_ptr = LLVMBuildLoad(g->builder, result_ptr_ptr, ""); |
| 2023 | if (!handle_is_ptr(ret_type)) { | 2036 | if (!handle_is_ptr(ret_type)) { |
| 2024 | // It's a scalar, so it didn't get written to the result ptr. Do that now. | 2037 | // It's a scalar, so it didn't get written to the result ptr. Do that now. |
| ... | @@ -3256,7 +3269,7 @@ static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutable *executable, | ... | @@ -3256,7 +3269,7 @@ static LLVMValueRef ir_render_return_ptr(CodeGen *g, IrExecutable *executable, |
| 3256 | return nullptr; | 3269 | return nullptr; |
| 3257 | src_assert(g->cur_ret_ptr != nullptr, instruction->base.source_node); | 3270 | src_assert(g->cur_ret_ptr != nullptr, instruction->base.source_node); |
| 3258 | if (fn_is_async(g->cur_fn)) { | 3271 | if (fn_is_async(g->cur_fn)) { |
| 3259 | LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_arg_start, ""); | 3272 | LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_ret_start, ""); |
| 3260 | return LLVMBuildLoad(g->builder, ptr_ptr, ""); | 3273 | return LLVMBuildLoad(g->builder, ptr_ptr, ""); |
| 3261 | } | 3274 | } |
| 3262 | return g->cur_ret_ptr; | 3275 | return g->cur_ret_ptr; |
| ... | @@ -3356,12 +3369,6 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI | ... | @@ -3356,12 +3369,6 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 3356 | } | 3369 | } |
| 3357 | } | 3370 | } |
| 3358 | 3371 | ||
| 3359 | static bool get_prefix_arg_err_ret_stack(CodeGen *g, FnTypeId *fn_type_id) { | ||
| 3360 | return g->have_err_ret_tracing && | ||
| 3361 | (fn_type_id->return_type->id == ZigTypeIdErrorUnion || | ||
| 3362 | fn_type_id->return_type->id == ZigTypeIdErrorSet); | ||
| 3363 | } | ||
| 3364 | |||
| 3365 | static LLVMValueRef get_new_stack_addr(CodeGen *g, LLVMValueRef new_stack) { | 3372 | static LLVMValueRef get_new_stack_addr(CodeGen *g, LLVMValueRef new_stack) { |
| 3366 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, new_stack, (unsigned)slice_ptr_index, ""); | 3373 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, new_stack, (unsigned)slice_ptr_index, ""); |
| 3367 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, new_stack, (unsigned)slice_len_index, ""); | 3374 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, new_stack, (unsigned)slice_len_index, ""); |
| ... | @@ -3402,7 +3409,7 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) { | ... | @@ -3402,7 +3409,7 @@ static void set_call_instr_sret(CodeGen *g, LLVMValueRef call_instr) { |
| 3402 | static void render_async_spills(CodeGen *g) { | 3409 | static void render_async_spills(CodeGen *g) { |
| 3403 | ZigType *fn_type = g->cur_fn->type_entry; | 3410 | ZigType *fn_type = g->cur_fn->type_entry; |
| 3404 | ZigType *import = get_scope_import(&g->cur_fn->fndef_scope->base); | 3411 | ZigType *import = get_scope_import(&g->cur_fn->fndef_scope->base); |
| 3405 | size_t async_var_index = coro_arg_start + (type_has_bits(fn_type->data.fn.fn_type_id.return_type) ? 2 : 0); | 3412 | uint32_t async_var_index = frame_index_arg(g, &fn_type->data.fn.fn_type_id); |
| 3406 | for (size_t var_i = 0; var_i < g->cur_fn->variable_list.length; var_i += 1) { | 3413 | for (size_t var_i = 0; var_i < g->cur_fn->variable_list.length; var_i += 1) { |
| 3407 | ZigVar *var = g->cur_fn->variable_list.at(var_i); | 3414 | ZigVar *var = g->cur_fn->variable_list.at(var_i); |
| 3408 | 3415 | ||
| ... | @@ -3518,11 +3525,11 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -3518,11 +3525,11 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3518 | CallingConvention cc = fn_type->data.fn.fn_type_id.cc; | 3525 | CallingConvention cc = fn_type->data.fn.fn_type_id.cc; |
| 3519 | 3526 | ||
| 3520 | bool first_arg_ret = ret_has_bits && want_first_arg_sret(g, fn_type_id); | 3527 | bool first_arg_ret = ret_has_bits && want_first_arg_sret(g, fn_type_id); |
| 3521 | bool prefix_arg_err_ret_stack = get_prefix_arg_err_ret_stack(g, fn_type_id); | 3528 | bool prefix_arg_err_ret_stack = codegen_fn_has_err_ret_tracing(g, fn_type_id->return_type); |
| 3522 | bool is_var_args = fn_type_id->is_var_args; | 3529 | bool is_var_args = fn_type_id->is_var_args; |
| 3523 | ZigList<LLVMValueRef> gen_param_values = {}; | 3530 | ZigList<LLVMValueRef> gen_param_values = {}; |
| 3524 | LLVMValueRef result_loc = instruction->result_loc ? ir_llvm_value(g, instruction->result_loc) : nullptr; | 3531 | LLVMValueRef result_loc = instruction->result_loc ? ir_llvm_value(g, instruction->result_loc) : nullptr; |
| 3525 | LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->llvm_type); | 3532 | LLVMValueRef zero = LLVMConstNull(usize_type_ref); |
| 3526 | LLVMValueRef frame_result_loc; | 3533 | LLVMValueRef frame_result_loc; |
| 3527 | LLVMValueRef awaiter_init_val; | 3534 | LLVMValueRef awaiter_init_val; |
| 3528 | LLVMValueRef ret_ptr; | 3535 | LLVMValueRef ret_ptr; |
| ... | @@ -3534,7 +3541,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -3534,7 +3541,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3534 | 3541 | ||
| 3535 | if (ret_has_bits) { | 3542 | if (ret_has_bits) { |
| 3536 | // Use the result location which is inside the frame if this is an async call. | 3543 | // Use the result location which is inside the frame if this is an async call. |
| 3537 | ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_arg_start + 1, ""); | 3544 | ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_ret_start + 1, ""); |
| 3538 | } | 3545 | } |
| 3539 | } else { | 3546 | } else { |
| 3540 | LLVMValueRef frame_slice_ptr = ir_llvm_value(g, instruction->new_stack); | 3547 | LLVMValueRef frame_slice_ptr = ir_llvm_value(g, instruction->new_stack); |
| ... | @@ -3564,14 +3571,49 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -3564,14 +3571,49 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3564 | ret_ptr = result_loc; | 3571 | ret_ptr = result_loc; |
| 3565 | } | 3572 | } |
| 3566 | } | 3573 | } |
| 3574 | |||
| 3575 | if (prefix_arg_err_ret_stack) { | ||
| 3576 | uint32_t trace_field_index = frame_index_trace(g, fn_type_id); | ||
| 3577 | LLVMValueRef trace_field_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, | ||
| 3578 | trace_field_index, ""); | ||
| 3579 | LLVMValueRef trace_field_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, | ||
| 3580 | trace_field_index + 1, ""); | ||
| 3581 | LLVMValueRef trace_field_addrs = LLVMBuildStructGEP(g->builder, frame_result_loc, | ||
| 3582 | trace_field_index + 2, ""); | ||
| 3583 | LLVMBuildStore(g->builder, trace_field_ptr, trace_field_ptr_ptr); | ||
| 3584 | |||
| 3585 | LLVMValueRef index_ptr = LLVMBuildStructGEP(g->builder, trace_field_ptr, 0, ""); | ||
| 3586 | LLVMBuildStore(g->builder, zero, index_ptr); | ||
| 3587 | |||
| 3588 | LLVMValueRef addrs_slice_ptr = LLVMBuildStructGEP(g->builder, trace_field_ptr, 1, ""); | ||
| 3589 | LLVMValueRef addrs_ptr_ptr = LLVMBuildStructGEP(g->builder, addrs_slice_ptr, slice_ptr_index, ""); | ||
| 3590 | LLVMValueRef indices[] = { LLVMConstNull(usize_type_ref), LLVMConstNull(usize_type_ref) }; | ||
| 3591 | LLVMValueRef trace_field_addrs_as_ptr = LLVMBuildInBoundsGEP(g->builder, trace_field_addrs, indices, 2, ""); | ||
| 3592 | LLVMBuildStore(g->builder, trace_field_addrs_as_ptr, addrs_ptr_ptr); | ||
| 3593 | |||
| 3594 | LLVMValueRef addrs_len_ptr = LLVMBuildStructGEP(g->builder, addrs_slice_ptr, slice_len_index, ""); | ||
| 3595 | LLVMBuildStore(g->builder, LLVMConstInt(usize_type_ref, stack_trace_ptr_count, false), addrs_len_ptr); | ||
| 3596 | } | ||
| 3567 | } else if (callee_is_async) { | 3597 | } else if (callee_is_async) { |
| 3568 | frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc); | 3598 | frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc); |
| 3569 | awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_ret_ptr, | 3599 | awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_ret_ptr, usize_type_ref, ""); // caller's own frame pointer |
| 3570 | g->builtin_types.entry_usize->llvm_type, ""); // caller's own frame pointer | ||
| 3571 | if (ret_has_bits) { | 3600 | if (ret_has_bits) { |
| 3572 | // Use the call instruction's result location. | 3601 | if (result_loc != nullptr) { |
| 3573 | ret_ptr = result_loc; | 3602 | // Use the call instruction's result location. |
| 3603 | ret_ptr = result_loc; | ||
| 3604 | } else { | ||
| 3605 | // return type is a scalar, but we still need a pointer to it. Use the async fn frame. | ||
| 3606 | ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_ret_start + 1, ""); | ||
| 3607 | } | ||
| 3608 | } | ||
| 3609 | |||
| 3610 | if (prefix_arg_err_ret_stack) { | ||
| 3611 | uint32_t trace_field_index = frame_index_trace(g, fn_type_id); | ||
| 3612 | LLVMValueRef trace_field_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, trace_field_index, ""); | ||
| 3613 | LLVMValueRef err_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope); | ||
| 3614 | LLVMBuildStore(g->builder, err_trace_val, trace_field_ptr); | ||
| 3574 | } | 3615 | } |
| 3616 | |||
| 3575 | } | 3617 | } |
| 3576 | if (instruction->is_async || callee_is_async) { | 3618 | if (instruction->is_async || callee_is_async) { |
| 3577 | assert(frame_result_loc != nullptr); | 3619 | assert(frame_result_loc != nullptr); |
| ... | @@ -3584,19 +3626,14 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -3584,19 +3626,14 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3584 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_resume_index, ""); | 3626 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_resume_index, ""); |
| 3585 | LLVMBuildStore(g->builder, zero, resume_index_ptr); | 3627 | LLVMBuildStore(g->builder, zero, resume_index_ptr); |
| 3586 | 3628 | ||
| 3587 | if (prefix_arg_err_ret_stack) { | ||
| 3588 | zig_panic("TODO"); | ||
| 3589 | } | ||
| 3590 | |||
| 3591 | LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_awaiter_index, ""); | 3629 | LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_awaiter_index, ""); |
| 3592 | LLVMBuildStore(g->builder, awaiter_init_val, awaiter_ptr); | 3630 | LLVMBuildStore(g->builder, awaiter_init_val, awaiter_ptr); |
| 3593 | 3631 | ||
| 3594 | if (ret_has_bits) { | 3632 | if (ret_has_bits) { |
| 3595 | LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_arg_start, ""); | 3633 | LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_ret_start, ""); |
| 3596 | LLVMBuildStore(g->builder, ret_ptr, ret_ptr_ptr); | 3634 | LLVMBuildStore(g->builder, ret_ptr, ret_ptr_ptr); |
| 3597 | } | 3635 | } |
| 3598 | } | 3636 | } else { |
| 3599 | if (!instruction->is_async && !callee_is_async) { | ||
| 3600 | if (first_arg_ret) { | 3637 | if (first_arg_ret) { |
| 3601 | gen_param_values.append(result_loc); | 3638 | gen_param_values.append(result_loc); |
| 3602 | } | 3639 | } |
| ... | @@ -3628,16 +3665,15 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -3628,16 +3665,15 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3628 | LLVMValueRef result; | 3665 | LLVMValueRef result; |
| 3629 | 3666 | ||
| 3630 | if (instruction->is_async || callee_is_async) { | 3667 | if (instruction->is_async || callee_is_async) { |
| 3631 | size_t ret_2_or_0 = type_has_bits(fn_type->data.fn.fn_type_id.return_type) ? 2 : 0; | 3668 | uint32_t arg_start_i = frame_index_arg(g, &fn_type->data.fn.fn_type_id); |
| 3632 | size_t arg_start_i = coro_arg_start + ret_2_or_0; | ||
| 3633 | 3669 | ||
| 3634 | LLVMValueRef casted_frame; | 3670 | LLVMValueRef casted_frame; |
| 3635 | if (instruction->new_stack != nullptr) { | 3671 | if (instruction->new_stack != nullptr) { |
| 3636 | // We need the frame type to be a pointer to a struct that includes the args | 3672 | // We need the frame type to be a pointer to a struct that includes the args |
| 3637 | // label (grep this): [coro_frame_struct_layout] | ||
| 3638 | size_t field_count = arg_start_i + gen_param_values.length; | 3673 | size_t field_count = arg_start_i + gen_param_values.length; |
| 3639 | LLVMTypeRef *field_types = allocate_nonzero<LLVMTypeRef>(field_count); | 3674 | LLVMTypeRef *field_types = allocate_nonzero<LLVMTypeRef>(field_count); |
| 3640 | LLVMGetStructElementTypes(LLVMGetElementType(LLVMTypeOf(frame_result_loc)), field_types); | 3675 | LLVMGetStructElementTypes(LLVMGetElementType(LLVMTypeOf(frame_result_loc)), field_types); |
| 3676 | assert(LLVMCountStructElementTypes(LLVMGetElementType(LLVMTypeOf(frame_result_loc))) == arg_start_i); | ||
| 3641 | for (size_t arg_i = 0; arg_i < gen_param_values.length; arg_i += 1) { | 3677 | for (size_t arg_i = 0; arg_i < gen_param_values.length; arg_i += 1) { |
| 3642 | field_types[arg_start_i + arg_i] = LLVMTypeOf(gen_param_values.at(arg_i)); | 3678 | field_types[arg_start_i + arg_i] = LLVMTypeOf(gen_param_values.at(arg_i)); |
| 3643 | } | 3679 | } |
| ... | @@ -5198,7 +5234,7 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst | ... | @@ -5198,7 +5234,7 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst |
| 5198 | LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_awaiter_index, ""); | 5234 | LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_awaiter_index, ""); |
| 5199 | LLVMValueRef result_ptr_as_usize; | 5235 | LLVMValueRef result_ptr_as_usize; |
| 5200 | if (type_has_bits(result_type)) { | 5236 | if (type_has_bits(result_type)) { |
| 5201 | LLVMValueRef result_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_arg_start, ""); | 5237 | LLVMValueRef result_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_ret_start, ""); |
| 5202 | LLVMValueRef result_ptr = LLVMBuildLoad(g->builder, result_ptr_ptr, ""); | 5238 | LLVMValueRef result_ptr = LLVMBuildLoad(g->builder, result_ptr_ptr, ""); |
| 5203 | result_ptr_as_usize = LLVMBuildPtrToInt(g->builder, result_ptr, usize_type_ref, ""); | 5239 | result_ptr_as_usize = LLVMBuildPtrToInt(g->builder, result_ptr, usize_type_ref, ""); |
| 5204 | } else { | 5240 | } else { |
| ... | @@ -5259,23 +5295,6 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst | ... | @@ -5259,23 +5295,6 @@ static LLVMValueRef ir_render_await(CodeGen *g, IrExecutable *executable, IrInst |
| 5259 | } | 5295 | } |
| 5260 | } | 5296 | } |
| 5261 | 5297 | ||
| 5262 | static LLVMTypeRef anyframe_fn_type(CodeGen *g) { | ||
| 5263 | if (g->anyframe_fn_type != nullptr) | ||
| 5264 | return g->anyframe_fn_type; | ||
| 5265 | |||
| 5266 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; | ||
| 5267 | ZigType *anyframe_type = get_any_frame_type(g, nullptr); | ||
| 5268 | LLVMTypeRef return_type = LLVMVoidType(); | ||
| 5269 | LLVMTypeRef param_types[] = { | ||
| 5270 | get_llvm_type(g, anyframe_type), | ||
| 5271 | usize_type_ref, | ||
| 5272 | }; | ||
| 5273 | LLVMTypeRef fn_type = LLVMFunctionType(return_type, param_types, 2, false); | ||
| 5274 | g->anyframe_fn_type = LLVMPointerType(fn_type, 0); | ||
| 5275 | |||
| 5276 | return g->anyframe_fn_type; | ||
| 5277 | } | ||
| 5278 | |||
| 5279 | static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable, | 5298 | static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable, |
| 5280 | IrInstructionCoroResume *instruction) | 5299 | IrInstructionCoroResume *instruction) |
| 5281 | { | 5300 | { |
| ... | @@ -5285,7 +5304,7 @@ static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable, | ... | @@ -5285,7 +5304,7 @@ static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable, |
| 5285 | assert(frame_type->id == ZigTypeIdAnyFrame); | 5304 | assert(frame_type->id == ZigTypeIdAnyFrame); |
| 5286 | LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, frame, coro_fn_ptr_index, ""); | 5305 | LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, frame, coro_fn_ptr_index, ""); |
| 5287 | LLVMValueRef uncasted_fn_val = LLVMBuildLoad(g->builder, fn_ptr_ptr, ""); | 5306 | LLVMValueRef uncasted_fn_val = LLVMBuildLoad(g->builder, fn_ptr_ptr, ""); |
| 5288 | LLVMValueRef fn_val = LLVMBuildIntToPtr(g->builder, uncasted_fn_val, anyframe_fn_type(g), ""); | 5307 | LLVMValueRef fn_val = LLVMBuildIntToPtr(g->builder, uncasted_fn_val, g->anyframe_fn_type, ""); |
| 5289 | LLVMValueRef arg_val = ir_want_runtime_safety(g, &instruction->base) ? | 5308 | LLVMValueRef arg_val = ir_want_runtime_safety(g, &instruction->base) ? |
| 5290 | LLVMConstAllOnes(usize_type_ref) : LLVMGetUndef(usize_type_ref); | 5309 | LLVMConstAllOnes(usize_type_ref) : LLVMGetUndef(usize_type_ref); |
| 5291 | LLVMValueRef args[] = {frame, arg_val}; | 5310 | LLVMValueRef args[] = {frame, arg_val}; |
| ... | @@ -6636,7 +6655,8 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6636,7 +6655,8 @@ static void do_code_gen(CodeGen *g) { |
| 6636 | } | 6655 | } |
| 6637 | 6656 | ||
| 6638 | // error return tracing setup | 6657 | // error return tracing setup |
| 6639 | bool have_err_ret_trace_stack = g->have_err_ret_tracing && fn_table_entry->calls_or_awaits_errorable_fn && !is_async && !have_err_ret_trace_arg; | 6658 | bool have_err_ret_trace_stack = g->have_err_ret_tracing && fn_table_entry->calls_or_awaits_errorable_fn && |
| 6659 | !is_async && !have_err_ret_trace_arg; | ||
| 6640 | LLVMValueRef err_ret_array_val = nullptr; | 6660 | LLVMValueRef err_ret_array_val = nullptr; |
| 6641 | if (have_err_ret_trace_stack) { | 6661 | if (have_err_ret_trace_stack) { |
| 6642 | ZigType *array_type = get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count); | 6662 | ZigType *array_type = get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count); |
| ... | @@ -6780,6 +6800,11 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -6780,6 +6800,11 @@ static void do_code_gen(CodeGen *g) { |
| 6780 | g->cur_async_awaiter_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_awaiter_index, ""); | 6800 | g->cur_async_awaiter_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_awaiter_index, ""); |
| 6781 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_resume_index, ""); | 6801 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_resume_index, ""); |
| 6782 | g->cur_async_resume_index_ptr = resume_index_ptr; | 6802 | g->cur_async_resume_index_ptr = resume_index_ptr; |
| 6803 | if (codegen_fn_has_err_ret_tracing(g, fn_type_id->return_type)) { | ||
| 6804 | uint32_t field_index = frame_index_trace(g, fn_type_id); | ||
| 6805 | g->cur_err_ret_trace_val_arg = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, field_index, ""); | ||
| 6806 | } | ||
| 6807 | |||
| 6783 | LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, ""); | 6808 | LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, ""); |
| 6784 | LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, resume_index, bad_resume_block, 4); | 6809 | LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, resume_index, bad_resume_block, 4); |
| 6785 | g->cur_async_switch_instr = switch_instr; | 6810 | g->cur_async_switch_instr = switch_instr; |
| ... | @@ -9691,3 +9716,9 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget | ... | @@ -9691,3 +9716,9 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget |
| 9691 | 9716 | ||
| 9692 | return g; | 9717 | return g; |
| 9693 | } | 9718 | } |
| 9719 | |||
| 9720 | bool codegen_fn_has_err_ret_tracing(CodeGen *g, ZigType *return_type) { | ||
| 9721 | return g->have_err_ret_tracing && | ||
| 9722 | (return_type->id == ZigTypeIdErrorUnion || | ||
| 9723 | return_type->id == ZigTypeIdErrorSet); | ||
| 9724 | } |
src/codegen.hpp+1| ... | @@ -61,5 +61,6 @@ Buf *codegen_generate_builtin_source(CodeGen *g); | ... | @@ -61,5 +61,6 @@ Buf *codegen_generate_builtin_source(CodeGen *g); |
| 61 | TargetSubsystem detect_subsystem(CodeGen *g); | 61 | TargetSubsystem detect_subsystem(CodeGen *g); |
| 62 | 62 | ||
| 63 | void codegen_release_caches(CodeGen *codegen); | 63 | void codegen_release_caches(CodeGen *codegen); |
| 64 | bool codegen_fn_has_err_ret_tracing(CodeGen *g, ZigType *return_type); | ||
| 64 | 65 | ||
| 65 | #endif | 66 | #endif |
src/ir.cpp+4-5| ... | @@ -14859,11 +14859,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc | ... | @@ -14859,11 +14859,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc |
| 14859 | ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count, | 14859 | ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count, |
| 14860 | IrInstruction *casted_new_stack) | 14860 | IrInstruction *casted_new_stack) |
| 14861 | { | 14861 | { |
| 14862 | if (fn_entry == nullptr) { | 14862 | if (casted_new_stack != nullptr) { |
| 14863 | if (call_instruction->new_stack == nullptr) { | ||
| 14864 | ir_add_error(ira, fn_ref, buf_sprintf("function is not comptime-known; @asyncCall required")); | ||
| 14865 | return ira->codegen->invalid_instruction; | ||
| 14866 | } | ||
| 14867 | // this is an @asyncCall | 14863 | // this is an @asyncCall |
| 14868 | 14864 | ||
| 14869 | if (fn_type->data.fn.fn_type_id.cc != CallingConventionAsync) { | 14865 | if (fn_type->data.fn.fn_type_id.cc != CallingConventionAsync) { |
| ... | @@ -14881,6 +14877,9 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc | ... | @@ -14881,6 +14877,9 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc |
| 14881 | IrInstructionCallGen *call_gen = ir_build_call_gen(ira, &call_instruction->base, nullptr, fn_ref, | 14877 | IrInstructionCallGen *call_gen = ir_build_call_gen(ira, &call_instruction->base, nullptr, fn_ref, |
| 14882 | arg_count, casted_args, FnInlineAuto, true, casted_new_stack, ret_ptr, anyframe_type); | 14878 | arg_count, casted_args, FnInlineAuto, true, casted_new_stack, ret_ptr, anyframe_type); |
| 14883 | return &call_gen->base; | 14879 | return &call_gen->base; |
| 14880 | } else if (fn_entry == nullptr) { | ||
| 14881 | ir_add_error(ira, fn_ref, buf_sprintf("function is not comptime-known; @asyncCall required")); | ||
| 14882 | return ira->codegen->invalid_instruction; | ||
| 14884 | } | 14883 | } |
| 14885 | 14884 | ||
| 14886 | ZigType *frame_type = get_coro_frame_type(ira->codegen, fn_entry); | 14885 | ZigType *frame_type = get_coro_frame_type(ira->codegen, fn_entry); |
test/stage1/behavior/coroutines.zig+52-25| ... | @@ -161,13 +161,13 @@ fn seq(c: u8) void { | ... | @@ -161,13 +161,13 @@ fn seq(c: u8) void { |
| 161 | 161 | ||
| 162 | test "coroutine suspend with block" { | 162 | test "coroutine suspend with block" { |
| 163 | const p = async testSuspendBlock(); | 163 | const p = async testSuspendBlock(); |
| 164 | expect(!result); | 164 | expect(!global_result); |
| 165 | resume a_promise; | 165 | resume a_promise; |
| 166 | expect(result); | 166 | expect(global_result); |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | var a_promise: anyframe = undefined; | 169 | var a_promise: anyframe = undefined; |
| 170 | var result = false; | 170 | var global_result = false; |
| 171 | async fn testSuspendBlock() void { | 171 | async fn testSuspendBlock() void { |
| 172 | suspend { | 172 | suspend { |
| 173 | comptime expect(@typeOf(@frame()) == *@Frame(testSuspendBlock)); | 173 | comptime expect(@typeOf(@frame()) == *@Frame(testSuspendBlock)); |
| ... | @@ -178,7 +178,7 @@ async fn testSuspendBlock() void { | ... | @@ -178,7 +178,7 @@ async fn testSuspendBlock() void { |
| 178 | // var our_handle: anyframe = @frame(); | 178 | // var our_handle: anyframe = @frame(); |
| 179 | expect(a_promise == anyframe(@frame())); | 179 | expect(a_promise == anyframe(@frame())); |
| 180 | 180 | ||
| 181 | result = true; | 181 | global_result = true; |
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | var await_a_promise: anyframe = undefined; | 184 | var await_a_promise: anyframe = undefined; |
| ... | @@ -283,29 +283,56 @@ test "@asyncCall with return type" { | ... | @@ -283,29 +283,56 @@ test "@asyncCall with return type" { |
| 283 | const Foo = struct { | 283 | const Foo = struct { |
| 284 | bar: async fn () i32, | 284 | bar: async fn () i32, |
| 285 | 285 | ||
| 286 | async fn afunc() i32 { | 286 | var global_frame: anyframe = undefined; |
| 287 | |||
| 288 | async fn middle() i32 { | ||
| 289 | return afunc(); | ||
| 290 | } | ||
| 291 | |||
| 292 | fn afunc() i32 { | ||
| 293 | global_frame = @frame(); | ||
| 287 | suspend; | 294 | suspend; |
| 288 | return 1234; | 295 | return 1234; |
| 289 | } | 296 | } |
| 290 | }; | 297 | }; |
| 291 | var foo = Foo{ .bar = Foo.afunc }; | 298 | var foo = Foo{ .bar = Foo.middle }; |
| 292 | var bytes: [64]u8 = undefined; | 299 | var bytes: [100]u8 = undefined; |
| 293 | var aresult: i32 = 0; | 300 | var aresult: i32 = 0; |
| 294 | const frame = @asyncCall(&bytes, &aresult, foo.bar); | 301 | _ = @asyncCall(&bytes, &aresult, foo.bar); |
| 295 | expect(aresult == 0); | 302 | expect(aresult == 0); |
| 296 | resume frame; | 303 | resume Foo.global_frame; |
| 297 | expect(aresult == 1234); | 304 | expect(aresult == 1234); |
| 298 | } | 305 | } |
| 299 | 306 | ||
| 300 | //test "async fn with inferred error set" { | 307 | test "async fn with inferred error set" { |
| 301 | // const p = async failing(); | 308 | const S = struct { |
| 302 | // resume p; | 309 | var global_frame: anyframe = undefined; |
| 303 | //} | 310 | |
| 304 | // | 311 | fn doTheTest() void { |
| 305 | //async fn failing() !void { | 312 | var frame: [1]@Frame(middle) = undefined; |
| 306 | // suspend; | 313 | var result: anyerror!void = undefined; |
| 307 | // return error.Fail; | 314 | _ = @asyncCall(@sliceToBytes(frame[0..]), &result, middle); |
| 308 | //} | 315 | resume global_frame; |
| 316 | std.testing.expectError(error.Fail, result); | ||
| 317 | } | ||
| 318 | |||
| 319 | async fn middle() !void { | ||
| 320 | var f = async middle2(); | ||
| 321 | return await f; | ||
| 322 | } | ||
| 323 | |||
| 324 | fn middle2() !void { | ||
| 325 | return failing(); | ||
| 326 | } | ||
| 327 | |||
| 328 | fn failing() !void { | ||
| 329 | global_frame = @frame(); | ||
| 330 | suspend; | ||
| 331 | return error.Fail; | ||
| 332 | } | ||
| 333 | }; | ||
| 334 | S.doTheTest(); | ||
| 335 | } | ||
| 309 | 336 | ||
| 310 | //test "error return trace across suspend points - early return" { | 337 | //test "error return trace across suspend points - early return" { |
| 311 | // const p = nonFailing(); | 338 | // const p = nonFailing(); |
| ... | @@ -422,24 +449,24 @@ test "async function call return value" { | ... | @@ -422,24 +449,24 @@ test "async function call return value" { |
| 422 | 449 | ||
| 423 | test "suspension points inside branching control flow" { | 450 | test "suspension points inside branching control flow" { |
| 424 | const S = struct { | 451 | const S = struct { |
| 425 | var global_result: i32 = 10; | 452 | var result: i32 = 10; |
| 426 | 453 | ||
| 427 | fn doTheTest() void { | 454 | fn doTheTest() void { |
| 428 | expect(10 == global_result); | 455 | expect(10 == result); |
| 429 | var frame = async func(true); | 456 | var frame = async func(true); |
| 430 | expect(10 == global_result); | 457 | expect(10 == result); |
| 431 | resume frame; | 458 | resume frame; |
| 432 | expect(11 == global_result); | 459 | expect(11 == result); |
| 433 | resume frame; | 460 | resume frame; |
| 434 | expect(12 == global_result); | 461 | expect(12 == result); |
| 435 | resume frame; | 462 | resume frame; |
| 436 | expect(13 == global_result); | 463 | expect(13 == result); |
| 437 | } | 464 | } |
| 438 | 465 | ||
| 439 | fn func(b: bool) void { | 466 | fn func(b: bool) void { |
| 440 | while (b) { | 467 | while (b) { |
| 441 | suspend; | 468 | suspend; |
| 442 | global_result += 1; | 469 | result += 1; |
| 443 | } | 470 | } |
| 444 | } | 471 | } |
| 445 | }; | 472 | }; |