| 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 | * delete IrInstructionMarkErrRetTracePtr | |
| 1 | 2 | * go over the commented out tests |
| 2 | 3 | * error return tracing |
| 3 | 4 | * compile error for error: expected anyframe->T, found 'anyframe' |
| ... | ... | @@ -32,3 +33,4 @@ |
| 32 | 33 | - resume |
| 33 | 34 | - anyframe, anyframe->T |
| 34 | 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 | 3705 | static const size_t coro_fn_ptr_index = 0; |
| 3706 | 3706 | static const size_t coro_resume_index = 1; |
| 3707 | 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 | 3710 | // TODO call graph analysis to find out what this number needs to be for every function |
| 3711 | 3711 | // MUST BE A POWER OF TWO. |
src/analyze.cpp+123-103| ... | ... | @@ -7,6 +7,7 @@ |
| 7 | 7 | |
| 8 | 8 | #include "analyze.hpp" |
| 9 | 9 | #include "ast_render.hpp" |
| 10 | #include "codegen.hpp" | |
| 10 | 11 | #include "config.h" |
| 11 | 12 | #include "error.hpp" |
| 12 | 13 | #include "ir.hpp" |
| ... | ... | @@ -5212,23 +5213,34 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { |
| 5212 | 5213 | ZigList<ZigType *> field_types = {}; |
| 5213 | 5214 | ZigList<const char *> field_names = {}; |
| 5214 | 5215 | |
| 5215 | field_names.append("fn_ptr"); | |
| 5216 | field_names.append("@fn_ptr"); | |
| 5216 | 5217 | field_types.append(fn_type); |
| 5217 | 5218 | |
| 5218 | field_names.append("resume_index"); | |
| 5219 | field_names.append("@resume_index"); | |
| 5219 | 5220 | field_types.append(g->builtin_types.entry_usize); |
| 5220 | 5221 | |
| 5221 | field_names.append("awaiter"); | |
| 5222 | field_names.append("@awaiter"); | |
| 5222 | 5223 | field_types.append(g->builtin_types.entry_usize); |
| 5223 | 5224 | |
| 5224 | 5225 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; |
| 5225 | 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 | 5228 | field_types.append(ptr_return_type); |
| 5228 | 5229 | |
| 5229 | field_names.append("result"); | |
| 5230 | field_names.append("@result"); | |
| 5230 | 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 | 5244 | for (size_t arg_i = 0; arg_i < fn_type_id->param_count; arg_i += 1) { |
| 5233 | 5245 | FnTypeParamInfo *param_info = &fn_type_id->param_info[arg_i]; |
| 5234 | 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 | 5249 | if (param_decl_node && !is_var_args) { |
| 5238 | 5250 | param_name = param_decl_node->data.param_decl.name; |
| 5239 | 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 | 5254 | ZigType *param_type = param_info->type; |
| 5243 | 5255 | field_names.append(buf_ptr(param_name)); |
| ... | ... | @@ -5260,7 +5272,13 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) { |
| 5260 | 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 | 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 | 7387 | } |
| 7370 | 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 | 7391 | ZigType *gen_type = get_ptr_to_stack_trace_type(g); |
| 7374 | 7392 | gen_param_types.append(get_llvm_type(g, gen_type)); |
| 7375 | 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 | 7545 | ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit); |
| 7528 | 7546 | |
| 7529 | 7547 | ZigType *result_type = any_frame_type->data.any_frame.result_type; |
| 7530 | if (result_type == nullptr || !type_has_bits(result_type)) { | |
| 7531 | LLVMTypeRef ptr_result_type = LLVMPointerType(fn_type, 0); | |
| 7532 | if (result_type == nullptr) { | |
| 7533 | g->anyframe_fn_type = ptr_result_type; | |
| 7534 | } | |
| 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); | |
| 7548 | ZigType *ptr_result_type = (result_type == nullptr) ? nullptr : get_pointer_to_type(g, result_type, false); | |
| 7549 | LLVMTypeRef ptr_fn_llvm_type = LLVMPointerType(fn_type, 0); | |
| 7550 | if (result_type == nullptr) { | |
| 7551 | g->anyframe_fn_type = ptr_fn_llvm_type; | |
| 7552 | } | |
| 7542 | 7553 | |
| 7543 | ZigLLVMDIType *di_element_types[] = { | |
| 7544 | ZigLLVMCreateDebugMemberType(g->dbuilder, | |
| 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, ""); | |
| 7554 | ZigList<LLVMTypeRef> field_types = {}; | |
| 7555 | ZigList<ZigLLVMDIType *> di_element_types = {}; | |
| 7573 | 7556 | |
| 7574 | ZigLLVMReplaceTemporary(g->dbuilder, frame_header_di_type, replacement_di_type); | |
| 7575 | } else { | |
| 7576 | ZigType *ptr_result_type = get_pointer_to_type(g, result_type, false); | |
| 7577 | // label (grep this): [coro_frame_struct_layout] | |
| 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); | |
| 7557 | // label (grep this): [coro_frame_struct_layout] | |
| 7558 | field_types.append(ptr_fn_llvm_type); // fn_ptr | |
| 7559 | field_types.append(usize_type_ref); // resume_index | |
| 7560 | field_types.append(usize_type_ref); // awaiter | |
| 7586 | 7561 | |
| 7587 | ZigLLVMDIType *di_element_types[] = { | |
| 7588 | ZigLLVMCreateDebugMemberType(g->dbuilder, | |
| 7589 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "fn_ptr", | |
| 7590 | di_file, line, | |
| 7591 | 8*LLVMABISizeOfType(g->target_data_ref, field_types[0]), | |
| 7592 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types[0]), | |
| 7593 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, 0), | |
| 7594 | ZigLLVM_DIFlags_Zero, usize_di_type), | |
| 7595 | ZigLLVMCreateDebugMemberType(g->dbuilder, | |
| 7596 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "awaiter", | |
| 7597 | di_file, line, | |
| 7598 | 8*LLVMABISizeOfType(g->target_data_ref, field_types[1]), | |
| 7599 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types[1]), | |
| 7600 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, 1), | |
| 7601 | ZigLLVM_DIFlags_Zero, usize_di_type), | |
| 7602 | ZigLLVMCreateDebugMemberType(g->dbuilder, | |
| 7603 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "awaiter", | |
| 7604 | di_file, line, | |
| 7605 | 8*LLVMABISizeOfType(g->target_data_ref, field_types[2]), | |
| 7606 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types[2]), | |
| 7607 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, 2), | |
| 7608 | ZigLLVM_DIFlags_Zero, usize_di_type), | |
| 7562 | bool have_result_type = result_type != nullptr && type_has_bits(result_type); | |
| 7563 | if (have_result_type) { | |
| 7564 | field_types.append(get_llvm_type(g, ptr_result_type)); // ptr_result | |
| 7565 | field_types.append(get_llvm_type(g, result_type)); // result | |
| 7566 | if (codegen_fn_has_err_ret_tracing(g, result_type)) { | |
| 7567 | field_types.append(get_llvm_type(g, get_ptr_to_stack_trace_type(g))); // ptr_stack_trace | |
| 7568 | field_types.append(get_llvm_type(g, g->stack_trace_type)); // stack_trace | |
| 7569 | field_types.append(get_llvm_type(g, get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count))); // instruction_addresses | |
| 7570 | } | |
| 7571 | } | |
| 7572 | LLVMStructSetBody(frame_header_type, field_types.items, field_types.length, false); | |
| 7573 | ||
| 7574 | di_element_types.append( | |
| 7575 | ZigLLVMCreateDebugMemberType(g->dbuilder, | |
| 7576 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "fn_ptr", | |
| 7577 | di_file, line, | |
| 7578 | 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)), | |
| 7579 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)), | |
| 7580 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length), | |
| 7581 | ZigLLVM_DIFlags_Zero, usize_di_type)); | |
| 7582 | di_element_types.append( | |
| 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 | 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 | 7603 | di_file, line, |
| 7612 | 8*LLVMABISizeOfType(g->target_data_ref, field_types[3]), | |
| 7613 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types[3]), | |
| 7614 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, 3), | |
| 7615 | ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, ptr_result_type)), | |
| 7604 | 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)), | |
| 7605 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)), | |
| 7606 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length), | |
| 7607 | ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, ptr_result_type))); | |
| 7608 | di_element_types.append( | |
| 7616 | 7609 | ZigLLVMCreateDebugMemberType(g->dbuilder, |
| 7617 | 7610 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "result", |
| 7618 | 7611 | di_file, line, |
| 7619 | 8*LLVMABISizeOfType(g->target_data_ref, field_types[4]), | |
| 7620 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types[4]), | |
| 7621 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, 4), | |
| 7622 | ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, result_type)), | |
| 7623 | }; | |
| 7624 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, | |
| 7625 | compile_unit_scope, buf_ptr(name), | |
| 7626 | di_file, line, | |
| 7627 | 8*LLVMABISizeOfType(g->target_data_ref, frame_header_type), | |
| 7628 | 8*LLVMABIAlignmentOfType(g->target_data_ref, frame_header_type), | |
| 7629 | ZigLLVM_DIFlags_Zero, | |
| 7630 | nullptr, di_element_types, 5, 0, nullptr, ""); | |
| 7612 | 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)), | |
| 7613 | 8*LLVMABIAlignmentOfType(g->target_data_ref, field_types.at(di_element_types.length)), | |
| 7614 | 8*LLVMOffsetOfElement(g->target_data_ref, frame_header_type, di_element_types.length), | |
| 7615 | ZigLLVM_DIFlags_Zero, get_llvm_di_type(g, result_type))); | |
| 7616 | ||
| 7617 | if (codegen_fn_has_err_ret_tracing(g, result_type)) { | |
| 7618 | di_element_types.append( | |
| 7619 | ZigLLVMCreateDebugMemberType(g->dbuilder, | |
| 7620 | ZigLLVMTypeToScope(any_frame_type->llvm_di_type), "ptr_stack_trace", | |
| 7621 | di_file, line, | |
| 7622 | 8*LLVMABISizeOfType(g->target_data_ref, field_types.at(di_element_types.length)), | |
| 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); | |
| 7633 | } | |
| 7645 | ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, | |
| 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 | 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 | 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 | 318 | static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) { |
| 301 | 319 | if (!g->have_err_ret_tracing) { |
| 302 | 320 | return UINT32_MAX; |
| 303 | 321 | } |
| 304 | if (fn_table_entry->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync) { | |
| 305 | return 0; | |
| 322 | if (fn_is_async(fn_table_entry)) { | |
| 323 | return UINT32_MAX; | |
| 306 | 324 | } |
| 307 | 325 | ZigType *fn_type = fn_table_entry->type_entry; |
| 308 | 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 | 456 | } else { |
| 439 | 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 | 460 | bool want_cold = fn->is_cold || cc == CallingConventionCold; |
| 447 | 461 | if (want_cold) { |
| ... | ... | @@ -1273,8 +1287,8 @@ static LLVMValueRef get_cur_err_ret_trace_val(CodeGen *g, Scope *scope) { |
| 1273 | 1287 | if (!g->have_err_ret_tracing) { |
| 1274 | 1288 | return nullptr; |
| 1275 | 1289 | } |
| 1276 | if (g->cur_fn->type_entry->data.fn.fn_type_id.cc == CallingConventionAsync) { | |
| 1277 | return g->cur_err_ret_trace_val_stack; | |
| 1290 | if (fn_is_async(g->cur_fn)) { | |
| 1291 | return LLVMBuildLoad(g->builder, g->cur_err_ret_trace_val_arg, ""); | |
| 1278 | 1292 | } |
| 1279 | 1293 | if (g->cur_err_ret_trace_val_stack != nullptr) { |
| 1280 | 1294 | return g->cur_err_ret_trace_val_stack; |
| ... | ... | @@ -2006,7 +2020,6 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, |
| 2006 | 2020 | { |
| 2007 | 2021 | if (fn_is_async(g->cur_fn)) { |
| 2008 | 2022 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; |
| 2009 | LLVMValueRef locals_ptr = g->cur_ret_ptr; | |
| 2010 | 2023 | bool ret_type_has_bits = return_instruction->value != nullptr && |
| 2011 | 2024 | type_has_bits(return_instruction->value->value.type); |
| 2012 | 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 | 2031 | |
| 2019 | 2032 | LLVMValueRef result_ptr_as_usize; |
| 2020 | 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 | 2035 | LLVMValueRef result_ptr = LLVMBuildLoad(g->builder, result_ptr_ptr, ""); |
| 2023 | 2036 | if (!handle_is_ptr(ret_type)) { |
| 2024 | 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 | 3269 | return nullptr; |
| 3257 | 3270 | src_assert(g->cur_ret_ptr != nullptr, instruction->base.source_node); |
| 3258 | 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 | 3273 | return LLVMBuildLoad(g->builder, ptr_ptr, ""); |
| 3261 | 3274 | } |
| 3262 | 3275 | return g->cur_ret_ptr; |
| ... | ... | @@ -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 | 3372 | static LLVMValueRef get_new_stack_addr(CodeGen *g, LLVMValueRef new_stack) { |
| 3366 | 3373 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, new_stack, (unsigned)slice_ptr_index, ""); |
| 3367 | 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 | 3409 | static void render_async_spills(CodeGen *g) { |
| 3403 | 3410 | ZigType *fn_type = g->cur_fn->type_entry; |
| 3404 | 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 | 3413 | for (size_t var_i = 0; var_i < g->cur_fn->variable_list.length; var_i += 1) { |
| 3407 | 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 | 3525 | CallingConvention cc = fn_type->data.fn.fn_type_id.cc; |
| 3519 | 3526 | |
| 3520 | 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 | 3529 | bool is_var_args = fn_type_id->is_var_args; |
| 3523 | 3530 | ZigList<LLVMValueRef> gen_param_values = {}; |
| 3524 | 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 | 3533 | LLVMValueRef frame_result_loc; |
| 3527 | 3534 | LLVMValueRef awaiter_init_val; |
| 3528 | 3535 | LLVMValueRef ret_ptr; |
| ... | ... | @@ -3534,7 +3541,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3534 | 3541 | |
| 3535 | 3542 | if (ret_has_bits) { |
| 3536 | 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 | 3546 | } else { |
| 3540 | 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 | 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 | 3597 | } else if (callee_is_async) { |
| 3568 | 3598 | frame_result_loc = ir_llvm_value(g, instruction->frame_result_loc); |
| 3569 | awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_ret_ptr, | |
| 3570 | g->builtin_types.entry_usize->llvm_type, ""); // caller's own frame pointer | |
| 3599 | awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_ret_ptr, usize_type_ref, ""); // caller's own frame pointer | |
| 3571 | 3600 | if (ret_has_bits) { |
| 3572 | // Use the call instruction's result location. | |
| 3573 | ret_ptr = result_loc; | |
| 3601 | if (result_loc != nullptr) { | |
| 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 | 3618 | if (instruction->is_async || callee_is_async) { |
| 3577 | 3619 | assert(frame_result_loc != nullptr); |
| ... | ... | @@ -3584,19 +3626,14 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3584 | 3626 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_resume_index, ""); |
| 3585 | 3627 | LLVMBuildStore(g->builder, zero, resume_index_ptr); |
| 3586 | 3628 | |
| 3587 | if (prefix_arg_err_ret_stack) { | |
| 3588 | zig_panic("TODO"); | |
| 3589 | } | |
| 3590 | ||
| 3591 | 3629 | LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, coro_awaiter_index, ""); |
| 3592 | 3630 | LLVMBuildStore(g->builder, awaiter_init_val, awaiter_ptr); |
| 3593 | 3631 | |
| 3594 | 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 | 3634 | LLVMBuildStore(g->builder, ret_ptr, ret_ptr_ptr); |
| 3597 | 3635 | } |
| 3598 | } | |
| 3599 | if (!instruction->is_async && !callee_is_async) { | |
| 3636 | } else { | |
| 3600 | 3637 | if (first_arg_ret) { |
| 3601 | 3638 | gen_param_values.append(result_loc); |
| 3602 | 3639 | } |
| ... | ... | @@ -3628,16 +3665,15 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 3628 | 3665 | LLVMValueRef result; |
| 3629 | 3666 | |
| 3630 | 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; | |
| 3632 | size_t arg_start_i = coro_arg_start + ret_2_or_0; | |
| 3668 | uint32_t arg_start_i = frame_index_arg(g, &fn_type->data.fn.fn_type_id); | |
| 3633 | 3669 | |
| 3634 | 3670 | LLVMValueRef casted_frame; |
| 3635 | 3671 | if (instruction->new_stack != nullptr) { |
| 3636 | 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 | 3673 | size_t field_count = arg_start_i + gen_param_values.length; |
| 3639 | 3674 | LLVMTypeRef *field_types = allocate_nonzero<LLVMTypeRef>(field_count); |
| 3640 | 3675 | LLVMGetStructElementTypes(LLVMGetElementType(LLVMTypeOf(frame_result_loc)), field_types); |
| 3676 | assert(LLVMCountStructElementTypes(LLVMGetElementType(LLVMTypeOf(frame_result_loc))) == arg_start_i); | |
| 3641 | 3677 | for (size_t arg_i = 0; arg_i < gen_param_values.length; arg_i += 1) { |
| 3642 | 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 | 5234 | LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, coro_awaiter_index, ""); |
| 5199 | 5235 | LLVMValueRef result_ptr_as_usize; |
| 5200 | 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 | 5238 | LLVMValueRef result_ptr = LLVMBuildLoad(g->builder, result_ptr_ptr, ""); |
| 5203 | 5239 | result_ptr_as_usize = LLVMBuildPtrToInt(g->builder, result_ptr, usize_type_ref, ""); |
| 5204 | 5240 | } else { |
| ... | ... | @@ -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 | 5298 | static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable, |
| 5280 | 5299 | IrInstructionCoroResume *instruction) |
| 5281 | 5300 | { |
| ... | ... | @@ -5285,7 +5304,7 @@ static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable, |
| 5285 | 5304 | assert(frame_type->id == ZigTypeIdAnyFrame); |
| 5286 | 5305 | LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, frame, coro_fn_ptr_index, ""); |
| 5287 | 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 | 5308 | LLVMValueRef arg_val = ir_want_runtime_safety(g, &instruction->base) ? |
| 5290 | 5309 | LLVMConstAllOnes(usize_type_ref) : LLVMGetUndef(usize_type_ref); |
| 5291 | 5310 | LLVMValueRef args[] = {frame, arg_val}; |
| ... | ... | @@ -6636,7 +6655,8 @@ static void do_code_gen(CodeGen *g) { |
| 6636 | 6655 | } |
| 6637 | 6656 | |
| 6638 | 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 | 6660 | LLVMValueRef err_ret_array_val = nullptr; |
| 6641 | 6661 | if (have_err_ret_trace_stack) { |
| 6642 | 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 | 6800 | g->cur_async_awaiter_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_awaiter_index, ""); |
| 6781 | 6801 | LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_ret_ptr, coro_resume_index, ""); |
| 6782 | 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 | 6808 | LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, ""); |
| 6784 | 6809 | LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, resume_index, bad_resume_block, 4); |
| 6785 | 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 | 9716 | |
| 9692 | 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 | 61 | TargetSubsystem detect_subsystem(CodeGen *g); |
| 62 | 62 | |
| 63 | 63 | void codegen_release_caches(CodeGen *codegen); |
| 64 | bool codegen_fn_has_err_ret_tracing(CodeGen *g, ZigType *return_type); | |
| 64 | 65 | |
| 65 | 66 | #endif |
src/ir.cpp+4-5| ... | ... | @@ -14859,11 +14859,7 @@ static IrInstruction *ir_analyze_async_call(IrAnalyze *ira, IrInstructionCallSrc |
| 14859 | 14859 | ZigType *fn_type, IrInstruction *fn_ref, IrInstruction **casted_args, size_t arg_count, |
| 14860 | 14860 | IrInstruction *casted_new_stack) |
| 14861 | 14861 | { |
| 14862 | if (fn_entry == 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 | } | |
| 14862 | if (casted_new_stack != nullptr) { | |
| 14867 | 14863 | // this is an @asyncCall |
| 14868 | 14864 | |
| 14869 | 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 | 14877 | IrInstructionCallGen *call_gen = ir_build_call_gen(ira, &call_instruction->base, nullptr, fn_ref, |
| 14882 | 14878 | arg_count, casted_args, FnInlineAuto, true, casted_new_stack, ret_ptr, anyframe_type); |
| 14883 | 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 | 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 | 161 | |
| 162 | 162 | test "coroutine suspend with block" { |
| 163 | 163 | const p = async testSuspendBlock(); |
| 164 | expect(!result); | |
| 164 | expect(!global_result); | |
| 165 | 165 | resume a_promise; |
| 166 | expect(result); | |
| 166 | expect(global_result); | |
| 167 | 167 | } |
| 168 | 168 | |
| 169 | 169 | var a_promise: anyframe = undefined; |
| 170 | var result = false; | |
| 170 | var global_result = false; | |
| 171 | 171 | async fn testSuspendBlock() void { |
| 172 | 172 | suspend { |
| 173 | 173 | comptime expect(@typeOf(@frame()) == *@Frame(testSuspendBlock)); |
| ... | ... | @@ -178,7 +178,7 @@ async fn testSuspendBlock() void { |
| 178 | 178 | // var our_handle: anyframe = @frame(); |
| 179 | 179 | expect(a_promise == anyframe(@frame())); |
| 180 | 180 | |
| 181 | result = true; | |
| 181 | global_result = true; | |
| 182 | 182 | } |
| 183 | 183 | |
| 184 | 184 | var await_a_promise: anyframe = undefined; |
| ... | ... | @@ -283,29 +283,56 @@ test "@asyncCall with return type" { |
| 283 | 283 | const Foo = struct { |
| 284 | 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 | 294 | suspend; |
| 288 | 295 | return 1234; |
| 289 | 296 | } |
| 290 | 297 | }; |
| 291 | var foo = Foo{ .bar = Foo.afunc }; | |
| 292 | var bytes: [64]u8 = undefined; | |
| 298 | var foo = Foo{ .bar = Foo.middle }; | |
| 299 | var bytes: [100]u8 = undefined; | |
| 293 | 300 | var aresult: i32 = 0; |
| 294 | const frame = @asyncCall(&bytes, &aresult, foo.bar); | |
| 301 | _ = @asyncCall(&bytes, &aresult, foo.bar); | |
| 295 | 302 | expect(aresult == 0); |
| 296 | resume frame; | |
| 303 | resume Foo.global_frame; | |
| 297 | 304 | expect(aresult == 1234); |
| 298 | 305 | } |
| 299 | 306 | |
| 300 | //test "async fn with inferred error set" { | |
| 301 | // const p = async failing(); | |
| 302 | // resume p; | |
| 303 | //} | |
| 304 | // | |
| 305 | //async fn failing() !void { | |
| 306 | // suspend; | |
| 307 | // return error.Fail; | |
| 308 | //} | |
| 307 | test "async fn with inferred error set" { | |
| 308 | const S = struct { | |
| 309 | var global_frame: anyframe = undefined; | |
| 310 | ||
| 311 | fn doTheTest() void { | |
| 312 | var frame: [1]@Frame(middle) = undefined; | |
| 313 | var result: anyerror!void = undefined; | |
| 314 | _ = @asyncCall(@sliceToBytes(frame[0..]), &result, middle); | |
| 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 | 337 | //test "error return trace across suspend points - early return" { |
| 311 | 338 | // const p = nonFailing(); |
| ... | ... | @@ -422,24 +449,24 @@ test "async function call return value" { |
| 422 | 449 | |
| 423 | 450 | test "suspension points inside branching control flow" { |
| 424 | 451 | const S = struct { |
| 425 | var global_result: i32 = 10; | |
| 452 | var result: i32 = 10; | |
| 426 | 453 | |
| 427 | 454 | fn doTheTest() void { |
| 428 | expect(10 == global_result); | |
| 455 | expect(10 == result); | |
| 429 | 456 | var frame = async func(true); |
| 430 | expect(10 == global_result); | |
| 457 | expect(10 == result); | |
| 431 | 458 | resume frame; |
| 432 | expect(11 == global_result); | |
| 459 | expect(11 == result); | |
| 433 | 460 | resume frame; |
| 434 | expect(12 == global_result); | |
| 461 | expect(12 == result); | |
| 435 | 462 | resume frame; |
| 436 | expect(13 == global_result); | |
| 463 | expect(13 == result); | |
| 437 | 464 | } |
| 438 | 465 | |
| 439 | 466 | fn func(b: bool) void { |
| 440 | 467 | while (b) { |
| 441 | 468 | suspend; |
| 442 | global_result += 1; | |
| 469 | result += 1; | |
| 443 | 470 | } |
| 444 | 471 | } |
| 445 | 472 | }; |