authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-05 00:41:49-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-05 00:41:49-04:00
log0d8c9fcb18b399bd2afedbcbcc7736326ef92297
tree8a5191a67c15148bbf0dbb50bdaef14c15794256
parentf27e5d439c121e620b2c0d9d7a6a8f4154826aa8
signature Commit is signed but in an unrecognized format.

support async functions with inferred error sets


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 tests2 * go over the commented out tests
2 * error return tracing3 * 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 - resume33 - resume
33 - anyframe, anyframe->T34 - anyframe, anyframe->T
34 * safety for double await35 * 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;
3705static const size_t coro_fn_ptr_index = 0;3705static const size_t coro_fn_ptr_index = 0;
3706static const size_t coro_resume_index = 1;3706static const size_t coro_resume_index = 1;
3707static const size_t coro_awaiter_index = 2;3707static const size_t coro_awaiter_index = 2;
3708static const size_t coro_arg_start = 3;3708static const size_t coro_ret_start = 3;
37093709
3710// TODO call graph analysis to find out what this number needs to be for every function3710// 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 @@
77
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 = {};
52145215
5215 field_names.append("fn_ptr");5216 field_names.append("@fn_ptr");
5216 field_types.append(fn_type);5217 field_types.append(fn_type);
52175218
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);
52205221
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);
52235224
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);
52285229
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);
52315232
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 }
52665284
...@@ -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;
73717389
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);
75287546
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);
75427553
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, "");
75737556
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);
75867561
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 };
76317644
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}
76357655
7636static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {7656static 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}
299299
300// label (grep this): [coro_frame_struct_layout]
301static 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]
309static 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
300static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) {318static 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 }
445459
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,
20182031
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}
33583371
3359static 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
3365static LLVMValueRef get_new_stack_addr(CodeGen *g, LLVMValueRef new_stack) {3372static 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) {
3402static void render_async_spills(CodeGen *g) {3409static 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);
34083415
...@@ -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;
35193526
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
35343541
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);
35863628
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);
35933631
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;
36293666
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;
36333669
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 args3672 // 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}
52615297
5262static 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
5279static LLVMValueRef ir_render_coro_resume(CodeGen *g, IrExecutable *executable,5298static 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 }
66376656
6638 // error return tracing setup6657 // 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
96919716
9692 return g;9717 return g;
9693}9718}
9719
9720bool 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);
61TargetSubsystem detect_subsystem(CodeGen *g);61TargetSubsystem detect_subsystem(CodeGen *g);
6262
63void codegen_release_caches(CodeGen *codegen);63void codegen_release_caches(CodeGen *codegen);
64bool codegen_fn_has_err_ret_tracing(CodeGen *g, ZigType *return_type);
6465
65#endif66#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 @asyncCall14863 // this is an @asyncCall
1486814864
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 }
1488514884
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 {
161161
162test "coroutine suspend with block" {162test "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}
168168
169var a_promise: anyframe = undefined;169var a_promise: anyframe = undefined;
170var result = false;170var global_result = false;
171async fn testSuspendBlock() void {171async 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()));
180180
181 result = true;181 global_result = true;
182}182}
183183
184var await_a_promise: anyframe = undefined;184var 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,
285285
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}
299306
300//test "async fn with inferred error set" {307test "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}
309336
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" {
422449
423test "suspension points inside branching control flow" {450test "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;
426453
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 }
438465
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 };