aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorJosh Wolfe <thejoshwolfe@gmail.com>2018-04-10 21:46:13 -0400
committerJosh Wolfe <thejoshwolfe@gmail.com>2018-04-10 21:46:13 -0400
commitb553b7ab83894447d53bcdc1b5a10c7cbcd2281f (patch)
treea2614c600dfbf57d7c92cfa8268767b60eb75b91 /src/ir.cpp
parent0ba85ea6ff910c7a49ae036625b945c475c0f58c (diff)
parentee3e2790aa85c624fc952bc8326b82d72843bb17 (diff)
downloadzig-b553b7ab83894447d53bcdc1b5a10c7cbcd2281f.tar.gz
zig-b553b7ab83894447d53bcdc1b5a10c7cbcd2281f.zip
Merge branch 'master' into self-hosted-parser
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp274
1 files changed, 190 insertions, 84 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index 18fd02c297..0b072cc696 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -725,6 +725,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAddImplicitRetur
return IrInstructionIdAddImplicitReturnType;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionMergeErrRetTraces *) {
+ return IrInstructionIdMergeErrRetTraces;
+}
+
+static constexpr IrInstructionId ir_instruction_id(IrInstructionMarkErrRetTracePtr *) {
+ return IrInstructionIdMarkErrRetTracePtr;
+}
+
template<typename T>
static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
T *special_instruction = allocate<T>(1);
@@ -956,25 +964,6 @@ static IrInstruction *ir_build_const_c_str_lit(IrBuilder *irb, Scope *scope, Ast
return &const_instruction->base;
}
-static IrInstruction *ir_build_const_promise_init(IrBuilder *irb, Scope *scope, AstNode *source_node,
- TypeTableEntry *return_type)
-{
- TypeTableEntry *struct_type = get_promise_frame_type(irb->codegen, return_type);
-
- IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
- const_instruction->base.value.type = struct_type;
- const_instruction->base.value.special = ConstValSpecialStatic;
- const_instruction->base.value.data.x_struct.fields = allocate<ConstExprValue>(struct_type->data.structure.src_field_count);
- const_instruction->base.value.data.x_struct.fields[0].type = struct_type->data.structure.fields[0].type_entry;
- const_instruction->base.value.data.x_struct.fields[0].special = ConstValSpecialStatic;
- const_instruction->base.value.data.x_struct.fields[0].data.x_maybe = nullptr;
- const_instruction->base.value.data.x_struct.fields[1].type = return_type;
- const_instruction->base.value.data.x_struct.fields[1].special = ConstValSpecialUndef;
- const_instruction->base.value.data.x_struct.fields[2].type = struct_type->data.structure.fields[2].type_entry;
- const_instruction->base.value.data.x_struct.fields[2].special = ConstValSpecialUndef;
- return &const_instruction->base;
-}
-
static IrInstruction *ir_build_bin_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrBinOp op_id,
IrInstruction *op1, IrInstruction *op2, bool safety_check_on)
{
@@ -2495,8 +2484,9 @@ static IrInstruction *ir_build_arg_type(IrBuilder *irb, Scope *scope, AstNode *s
return &instruction->base;
}
-static IrInstruction *ir_build_error_return_trace(IrBuilder *irb, Scope *scope, AstNode *source_node) {
+static IrInstruction *ir_build_error_return_trace(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstructionErrorReturnTrace::Nullable nullable) {
IrInstructionErrorReturnTrace *instruction = ir_build_instruction<IrInstructionErrorReturnTrace>(irb, scope, source_node);
+ instruction->nullable = nullable;
return &instruction->base;
}
@@ -2717,6 +2707,30 @@ static IrInstruction *ir_build_add_implicit_return_type(IrBuilder *irb, Scope *s
return &instruction->base;
}
+static IrInstruction *ir_build_merge_err_ret_traces(IrBuilder *irb, Scope *scope, AstNode *source_node,
+ IrInstruction *coro_promise_ptr, IrInstruction *src_err_ret_trace_ptr, IrInstruction *dest_err_ret_trace_ptr)
+{
+ IrInstructionMergeErrRetTraces *instruction = ir_build_instruction<IrInstructionMergeErrRetTraces>(irb, scope, source_node);
+ instruction->coro_promise_ptr = coro_promise_ptr;
+ instruction->src_err_ret_trace_ptr = src_err_ret_trace_ptr;
+ instruction->dest_err_ret_trace_ptr = dest_err_ret_trace_ptr;
+
+ ir_ref_instruction(coro_promise_ptr, irb->current_basic_block);
+ ir_ref_instruction(src_err_ret_trace_ptr, irb->current_basic_block);
+ ir_ref_instruction(dest_err_ret_trace_ptr, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_mark_err_ret_trace_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *err_ret_trace_ptr) {
+ IrInstructionMarkErrRetTracePtr *instruction = ir_build_instruction<IrInstructionMarkErrRetTracePtr>(irb, scope, source_node);
+ instruction->err_ret_trace_ptr = err_ret_trace_ptr;
+
+ ir_ref_instruction(err_ret_trace_ptr, irb->current_basic_block);
+
+ return &instruction->base;
+}
+
static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
results[ReturnKindUnconditional] = 0;
results[ReturnKindError] = 0;
@@ -2741,9 +2755,10 @@ static IrInstruction *ir_mark_gen(IrInstruction *instruction) {
static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, bool gen_error_defers) {
Scope *scope = inner_scope;
+ bool is_noreturn = false;
while (scope != outer_scope) {
if (!scope)
- return false;
+ return is_noreturn;
if (scope->id == ScopeIdDefer) {
AstNode *defer_node = scope->source_node;
@@ -2756,14 +2771,18 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o
Scope *defer_expr_scope = defer_node->data.defer.expr_scope;
IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);
if (defer_expr_value != irb->codegen->invalid_instruction) {
- ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, defer_expr_value));
+ if (defer_expr_value->value.type != nullptr && defer_expr_value->value.type->id == TypeTableEntryIdUnreachable) {
+ is_noreturn = true;
+ } else {
+ ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, defer_expr_value));
+ }
}
}
}
scope = scope->parent;
}
- return true;
+ return is_noreturn;
}
static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) {
@@ -2822,34 +2841,6 @@ static IrInstruction *ir_gen_async_return(IrBuilder *irb, Scope *scope, AstNode
// the above blocks are rendered by ir_gen after the rest of codegen
}
-static bool exec_have_err_ret_trace(CodeGen *g, IrExecutable *exec) {
- if (!g->have_err_ret_tracing)
- return false;
- FnTableEntry *fn_entry = exec_fn_entry(exec);
- if (fn_entry == nullptr)
- return false;
- if (exec->is_inline)
- return false;
- return type_can_fail(fn_entry->type_entry->data.fn.fn_type_id.return_type);
-}
-
-static void ir_gen_save_err_ret_addr(IrBuilder *irb, Scope *scope, AstNode *node) {
- if (!exec_have_err_ret_trace(irb->codegen, irb->exec))
- return;
-
- bool is_async = exec_is_async(irb->exec);
-
- if (is_async) {
- //IrInstruction *err_ret_addr_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_err_ret_addr_ptr);
- //IrInstruction *return_address_ptr = ir_build_instr_addr(irb, scope, node);
- //IrInstruction *return_address_usize = ir_build_ptr_to_int(irb, scope, node, return_address_ptr);
- //ir_build_store_ptr(irb, scope, node, err_ret_addr_ptr, return_address_usize);
- return;
- }
-
- ir_build_save_err_ret_addr(irb, scope, node);
-}
-
static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
assert(node->type == NodeTypeReturnExpr);
@@ -2895,8 +2886,9 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
IrInstruction *is_err = ir_build_test_err(irb, scope, node, return_value);
+ bool should_inline = ir_should_inline(irb->exec, scope);
IrInstruction *is_comptime;
- if (ir_should_inline(irb->exec, scope)) {
+ if (should_inline) {
is_comptime = ir_build_const_bool(irb, scope, node, true);
} else {
is_comptime = ir_build_test_comptime(irb, scope, node, is_err);
@@ -2909,7 +2901,9 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
if (have_err_defers) {
ir_gen_defers_for_block(irb, scope, outer_scope, true);
}
- ir_gen_save_err_ret_addr(irb, scope, node);
+ if (irb->codegen->have_err_ret_tracing && !should_inline) {
+ ir_build_save_err_ret_addr(irb, scope, node);
+ }
ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, ok_block);
@@ -2938,7 +2932,8 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
IrBasicBlock *return_block = ir_create_basic_block(irb, scope, "ErrRetReturn");
IrBasicBlock *continue_block = ir_create_basic_block(irb, scope, "ErrRetContinue");
IrInstruction *is_comptime;
- if (ir_should_inline(irb->exec, scope)) {
+ bool should_inline = ir_should_inline(irb->exec, scope);
+ if (should_inline) {
is_comptime = ir_build_const_bool(irb, scope, node, true);
} else {
is_comptime = ir_build_test_comptime(irb, scope, node, is_err_val);
@@ -2946,10 +2941,13 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
ir_mark_gen(ir_build_cond_br(irb, scope, node, is_err_val, return_block, continue_block, is_comptime));
ir_set_cursor_at_end_and_append_block(irb, return_block);
- ir_gen_defers_for_block(irb, scope, outer_scope, true);
- IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr);
- ir_gen_save_err_ret_addr(irb, scope, node);
- ir_gen_async_return(irb, scope, node, err_val, false);
+ if (!ir_gen_defers_for_block(irb, scope, outer_scope, true)) {
+ IrInstruction *err_val = ir_build_unwrap_err_code(irb, scope, node, err_union_ptr);
+ if (irb->codegen->have_err_ret_tracing && !should_inline) {
+ ir_build_save_err_ret_addr(irb, scope, node);
+ }
+ ir_gen_async_return(irb, scope, node, err_val, false);
+ }
ir_set_cursor_at_end_and_append_block(irb, continue_block);
IrInstruction *unwrapped_ptr = ir_build_unwrap_err_payload(irb, scope, node, err_union_ptr, false);
@@ -4242,7 +4240,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
}
case BuiltinFnIdErrorReturnTrace:
{
- return ir_build_error_return_trace(irb, scope, node);
+ return ir_build_error_return_trace(irb, scope, node, IrInstructionErrorReturnTrace::Null);
}
case BuiltinFnIdAtomicRmw:
{
@@ -5703,7 +5701,7 @@ static IrInstruction *ir_gen_continue(IrBuilder *irb, Scope *continue_scope, Ast
IrBasicBlock *dest_block = loop_scope->continue_block;
ir_gen_defers_for_block(irb, continue_scope, dest_block->scope, false);
- return ir_build_br(irb, continue_scope, node, dest_block, is_comptime);
+ return ir_mark_gen(ir_build_br(irb, continue_scope, node, dest_block, is_comptime));
}
static IrInstruction *ir_gen_error_type(IrBuilder *irb, Scope *scope, AstNode *node) {
@@ -6125,6 +6123,13 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast
Buf *result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);
IrInstruction *result_ptr_field_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr, result_ptr_field_name);
+ if (irb->codegen->have_err_ret_tracing) {
+ IrInstruction *err_ret_trace_ptr = ir_build_error_return_trace(irb, parent_scope, node, IrInstructionErrorReturnTrace::NonNull);
+ Buf *err_ret_trace_ptr_field_name = buf_create_from_str(ERR_RET_TRACE_PTR_FIELD_NAME);
+ IrInstruction *err_ret_trace_ptr_field_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr, err_ret_trace_ptr_field_name);
+ ir_build_store_ptr(irb, parent_scope, node, err_ret_trace_ptr_field_ptr, err_ret_trace_ptr);
+ }
+
Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME);
IrInstruction *awaiter_field_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr,
awaiter_handle_field_name);
@@ -6148,10 +6153,16 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast
IrInstruction *is_non_null = ir_build_test_nonnull(irb, parent_scope, node, maybe_await_handle);
IrBasicBlock *yes_suspend_block = ir_create_basic_block(irb, parent_scope, "YesSuspend");
IrBasicBlock *no_suspend_block = ir_create_basic_block(irb, parent_scope, "NoSuspend");
- IrBasicBlock *merge_block = ir_create_basic_block(irb, parent_scope, "Merge");
+ IrBasicBlock *merge_block = ir_create_basic_block(irb, parent_scope, "MergeSuspend");
ir_build_cond_br(irb, parent_scope, node, is_non_null, no_suspend_block, yes_suspend_block, const_bool_false);
ir_set_cursor_at_end_and_append_block(irb, no_suspend_block);
+ if (irb->codegen->have_err_ret_tracing) {
+ Buf *err_ret_trace_field_name = buf_create_from_str(ERR_RET_TRACE_FIELD_NAME);
+ IrInstruction *src_err_ret_trace_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr, err_ret_trace_field_name);
+ IrInstruction *dest_err_ret_trace_ptr = ir_build_error_return_trace(irb, parent_scope, node, IrInstructionErrorReturnTrace::NonNull);
+ ir_build_merge_err_ret_traces(irb, parent_scope, node, coro_promise_ptr, src_err_ret_trace_ptr, dest_err_ret_trace_ptr);
+ }
Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);
IrInstruction *promise_result_ptr = ir_build_field_ptr(irb, parent_scope, node, coro_promise_ptr, result_field_name);
IrInstruction *no_suspend_result = ir_build_load_ptr(irb, parent_scope, node, promise_result_ptr);
@@ -6173,7 +6184,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *parent_scope, Ast
ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
ir_gen_defers_for_block(irb, parent_scope, outer_scope, true);
- ir_build_br(irb, parent_scope, node, irb->exec->coro_final_cleanup_block, const_bool_false);
+ ir_mark_gen(ir_build_br(irb, parent_scope, node, irb->exec->coro_final_cleanup_block, const_bool_false));
ir_set_cursor_at_end_and_append_block(irb, resume_block);
IrInstruction *yes_suspend_result = ir_build_load_ptr(irb, parent_scope, node, my_result_var_ptr);
@@ -6249,7 +6260,7 @@ static IrInstruction *ir_gen_suspend(IrBuilder *irb, Scope *parent_scope, AstNod
ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
ir_gen_defers_for_block(irb, parent_scope, outer_scope, true);
- ir_build_br(irb, parent_scope, node, irb->exec->coro_final_cleanup_block, const_bool_false);
+ ir_mark_gen(ir_build_br(irb, parent_scope, node, irb->exec->coro_final_cleanup_block, const_bool_false));
ir_set_cursor_at_end_and_append_block(irb, resume_block);
return ir_build_const_void(irb, parent_scope, node);
@@ -6268,7 +6279,6 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
case NodeTypeSwitchRange:
case NodeTypeStructField:
case NodeTypeFnDef:
- case NodeTypeFnDecl:
case NodeTypeTestDecl:
zig_unreachable();
case NodeTypeBlock:
@@ -6407,6 +6417,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
IrInstruction *coro_id;
IrInstruction *u8_ptr_type;
IrInstruction *const_bool_false;
+ IrInstruction *coro_promise_ptr;
+ IrInstruction *err_ret_trace_ptr;
TypeTableEntry *return_type;
Buf *result_ptr_field_name;
VariableTableEntry *coro_size_var;
@@ -6417,9 +6429,12 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
VariableTableEntry *promise_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
return_type = fn_entry->type_entry->data.fn.fn_type_id.return_type;
- IrInstruction *promise_init = ir_build_const_promise_init(irb, coro_scope, node, return_type);
- ir_build_var_decl(irb, coro_scope, node, promise_var, nullptr, nullptr, promise_init);
- IrInstruction *coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var, false, false);
+ IrInstruction *undef = ir_build_const_undefined(irb, coro_scope, node);
+ TypeTableEntry *coro_frame_type = get_promise_frame_type(irb->codegen, return_type);
+ IrInstruction *coro_frame_type_value = ir_build_const_type(irb, coro_scope, node, coro_frame_type);
+ // TODO mark this var decl as "no safety" e.g. disable initializing the undef value to 0xaa
+ ir_build_var_decl(irb, coro_scope, node, promise_var, coro_frame_type_value, nullptr, undef);
+ coro_promise_ptr = ir_build_var_ptr(irb, coro_scope, node, promise_var, false, false);
VariableTableEntry *await_handle_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
IrInstruction *null_value = ir_build_const_null(irb, coro_scope, node);
@@ -6452,7 +6467,6 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
ir_set_cursor_at_end_and_append_block(irb, alloc_err_block);
// we can return undefined here, because the caller passes a pointer to the error struct field
// in the error union result, and we populate it in case of allocation failure.
- IrInstruction *undef = ir_build_const_undefined(irb, coro_scope, node);
ir_build_return(irb, coro_scope, node, undef);
ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);
@@ -6460,13 +6474,35 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);
Buf *awaiter_handle_field_name = buf_create_from_str(AWAITER_HANDLE_FIELD_NAME);
- irb->exec->coro_awaiter_field_ptr = ir_build_field_ptr(irb, coro_scope, node, coro_promise_ptr,
+ irb->exec->coro_awaiter_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
awaiter_handle_field_name);
+ ir_build_store_ptr(irb, scope, node, irb->exec->coro_awaiter_field_ptr, null_value);
Buf *result_field_name = buf_create_from_str(RESULT_FIELD_NAME);
- irb->exec->coro_result_field_ptr = ir_build_field_ptr(irb, coro_scope, node, coro_promise_ptr, result_field_name);
+ irb->exec->coro_result_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_field_name);
result_ptr_field_name = buf_create_from_str(RESULT_PTR_FIELD_NAME);
- irb->exec->coro_result_ptr_field_ptr = ir_build_field_ptr(irb, coro_scope, node, coro_promise_ptr, result_ptr_field_name);
- ir_build_store_ptr(irb, coro_scope, node, irb->exec->coro_result_ptr_field_ptr, irb->exec->coro_result_field_ptr);
+ irb->exec->coro_result_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, result_ptr_field_name);
+ ir_build_store_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr, irb->exec->coro_result_field_ptr);
+ if (irb->codegen->have_err_ret_tracing) {
+ // initialize the error return trace
+ Buf *return_addresses_field_name = buf_create_from_str(RETURN_ADDRESSES_FIELD_NAME);
+ IrInstruction *return_addresses_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, return_addresses_field_name);
+
+ Buf *err_ret_trace_field_name = buf_create_from_str(ERR_RET_TRACE_FIELD_NAME);
+ err_ret_trace_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_field_name);
+ ir_build_mark_err_ret_trace_ptr(irb, scope, node, err_ret_trace_ptr);
+
+ // coordinate with builtin.zig
+ Buf *index_name = buf_create_from_str("index");
+ IrInstruction *index_ptr = ir_build_field_ptr(irb, scope, node, err_ret_trace_ptr, index_name);
+ IrInstruction *zero = ir_build_const_usize(irb, scope, node, 0);
+ ir_build_store_ptr(irb, scope, node, index_ptr, zero);
+
+ Buf *instruction_addresses_name = buf_create_from_str("instruction_addresses");
+ IrInstruction *addrs_slice_ptr = ir_build_field_ptr(irb, scope, node, err_ret_trace_ptr, instruction_addresses_name);
+
+ IrInstruction *slice_value = ir_build_slice(irb, scope, node, return_addresses_ptr, zero, nullptr, false);
+ ir_build_store_ptr(irb, scope, node, addrs_slice_ptr, slice_value);
+ }
irb->exec->coro_early_final = ir_create_basic_block(irb, scope, "CoroEarlyFinal");
@@ -6517,6 +6553,12 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
IrInstruction *size_of_ret_val = ir_build_size_of(irb, scope, node, return_type_inst);
ir_build_memcpy(irb, scope, node, result_ptr_as_u8_ptr, return_value_ptr_as_u8_ptr, size_of_ret_val);
}
+ if (irb->codegen->have_err_ret_tracing) {
+ Buf *err_ret_trace_ptr_field_name = buf_create_from_str(ERR_RET_TRACE_PTR_FIELD_NAME);
+ IrInstruction *err_ret_trace_ptr_field_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr_field_name);
+ IrInstruction *dest_err_ret_trace_ptr = ir_build_load_ptr(irb, scope, node, err_ret_trace_ptr_field_ptr);
+ ir_build_merge_err_ret_traces(irb, scope, node, coro_promise_ptr, err_ret_trace_ptr, dest_err_ret_trace_ptr);
+ }
ir_build_br(irb, scope, node, check_free_block, const_bool_false);
ir_set_cursor_at_end_and_append_block(irb, irb->exec->coro_final_cleanup_block);
@@ -11579,18 +11621,25 @@ static bool exec_has_err_ret_trace(CodeGen *g, IrExecutable *exec) {
static TypeTableEntry *ir_analyze_instruction_error_return_trace(IrAnalyze *ira,
IrInstructionErrorReturnTrace *instruction)
{
- TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(ira->codegen);
- TypeTableEntry *nullable_type = get_maybe_type(ira->codegen, ptr_to_stack_trace_type);
- if (!exec_has_err_ret_trace(ira->codegen, ira->new_irb.exec)) {
- ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
- out_val->data.x_maybe = nullptr;
+ if (instruction->nullable == IrInstructionErrorReturnTrace::Null) {
+ TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(ira->codegen);
+ TypeTableEntry *nullable_type = get_maybe_type(ira->codegen, ptr_to_stack_trace_type);
+ if (!exec_has_err_ret_trace(ira->codegen, ira->new_irb.exec)) {
+ ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
+ out_val->data.x_maybe = nullptr;
+ return nullable_type;
+ }
+ IrInstruction *new_instruction = ir_build_error_return_trace(&ira->new_irb, instruction->base.scope,
+ instruction->base.source_node, instruction->nullable);
+ ir_link_new_instruction(new_instruction, &instruction->base);
return nullable_type;
+ } else {
+ assert(ira->codegen->have_err_ret_tracing);
+ IrInstruction *new_instruction = ir_build_error_return_trace(&ira->new_irb, instruction->base.scope,
+ instruction->base.source_node, instruction->nullable);
+ ir_link_new_instruction(new_instruction, &instruction->base);
+ return get_ptr_to_stack_trace_type(ira->codegen);
}
-
- IrInstruction *new_instruction = ir_build_error_return_trace(&ira->new_irb, instruction->base.scope,
- instruction->base.source_node);
- ir_link_new_instruction(new_instruction, &instruction->base);
- return nullable_type;
}
static TypeTableEntry *ir_analyze_instruction_error_union(IrAnalyze *ira,
@@ -13072,6 +13121,7 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
{
if (!is_slice(bare_struct_type)) {
ScopeDecls *container_scope = get_container_scope(bare_struct_type);
+ assert(container_scope != nullptr);
auto entry = container_scope->decl_table.maybe_get(field_name);
Tld *tld = entry ? entry->value : nullptr;
if (tld && tld->id == TldIdFn) {
@@ -14709,7 +14759,7 @@ static TypeTableEntry *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructi
return ira->codegen->builtin_types.entry_namespace;
}
- if ((err = os_fetch_file_path(abs_full_path, import_code))) {
+ if ((err = os_fetch_file_path(abs_full_path, import_code, true))) {
if (err == ErrorFileNotFound) {
ir_add_error_node(ira, source_node,
buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
@@ -15570,7 +15620,7 @@ static TypeTableEntry *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstr
// load from file system into const expr
Buf *file_contents = buf_alloc();
int err;
- if ((err = os_fetch_file_path(&file_path, file_contents))) {
+ if ((err = os_fetch_file_path(&file_path, file_contents, false))) {
if (err == ErrorFileNotFound) {
ir_add_error(ira, instruction->name, buf_sprintf("unable to find '%s'", buf_ptr(&file_path)));
return ira->codegen->builtin_types.entry_invalid;
@@ -16702,6 +16752,11 @@ static TypeTableEntry *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruc
return ira->codegen->builtin_types.entry_invalid;
if (fn_type_id.cc == CallingConventionAsync) {
+ if (instruction->async_allocator_type_value == nullptr) {
+ ir_add_error(ira, &instruction->base,
+ buf_sprintf("async fn proto missing allocator type"));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
IrInstruction *async_allocator_type_value = instruction->async_allocator_type_value->other;
fn_type_id.async_allocator_type = ir_resolve_type(ira, async_allocator_type_value);
if (type_is_invalid(fn_type_id.async_allocator_type))
@@ -17904,6 +17959,39 @@ static TypeTableEntry *ir_analyze_instruction_await_bookkeeping(IrAnalyze *ira,
return out_val->type;
}
+static TypeTableEntry *ir_analyze_instruction_merge_err_ret_traces(IrAnalyze *ira,
+ IrInstructionMergeErrRetTraces *instruction)
+{
+ IrInstruction *coro_promise_ptr = instruction->coro_promise_ptr->other;
+ if (type_is_invalid(coro_promise_ptr->value.type))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ assert(coro_promise_ptr->value.type->id == TypeTableEntryIdPointer);
+ TypeTableEntry *promise_frame_type = coro_promise_ptr->value.type->data.pointer.child_type;
+ assert(promise_frame_type->id == TypeTableEntryIdStruct);
+ TypeTableEntry *promise_result_type = promise_frame_type->data.structure.fields[1].type_entry;
+
+ if (!type_can_fail(promise_result_type)) {
+ ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base);
+ out_val->type = ira->codegen->builtin_types.entry_void;
+ return out_val->type;
+ }
+
+ IrInstruction *src_err_ret_trace_ptr = instruction->src_err_ret_trace_ptr->other;
+ if (type_is_invalid(src_err_ret_trace_ptr->value.type))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ IrInstruction *dest_err_ret_trace_ptr = instruction->dest_err_ret_trace_ptr->other;
+ if (type_is_invalid(dest_err_ret_trace_ptr->value.type))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ IrInstruction *result = ir_build_merge_err_ret_traces(&ira->new_irb, instruction->base.scope,
+ instruction->base.source_node, coro_promise_ptr, src_err_ret_trace_ptr, dest_err_ret_trace_ptr);
+ ir_link_new_instruction(result, &instruction->base);
+ result->value.type = ira->codegen->builtin_types.entry_void;
+ return result->value.type;
+}
+
static TypeTableEntry *ir_analyze_instruction_save_err_ret_addr(IrAnalyze *ira, IrInstructionSaveErrRetAddr *instruction) {
IrInstruction *result = ir_build_save_err_ret_addr(&ira->new_irb, instruction->base.scope,
instruction->base.source_node);
@@ -17912,6 +18000,18 @@ static TypeTableEntry *ir_analyze_instruction_save_err_ret_addr(IrAnalyze *ira,
return result->value.type;
}
+static TypeTableEntry *ir_analyze_instruction_mark_err_ret_trace_ptr(IrAnalyze *ira, IrInstructionMarkErrRetTracePtr *instruction) {
+ IrInstruction *err_ret_trace_ptr = instruction->err_ret_trace_ptr->other;
+ if (type_is_invalid(err_ret_trace_ptr->value.type))
+ return ira->codegen->builtin_types.entry_invalid;
+
+ IrInstruction *result = ir_build_mark_err_ret_trace_ptr(&ira->new_irb, instruction->base.scope,
+ instruction->base.source_node, err_ret_trace_ptr);
+ ir_link_new_instruction(result, &instruction->base);
+ result->value.type = ira->codegen->builtin_types.entry_void;
+ return result->value.type;
+}
+
static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
switch (instruction->id) {
case IrInstructionIdInvalid:
@@ -18155,6 +18255,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
return ir_analyze_instruction_save_err_ret_addr(ira, (IrInstructionSaveErrRetAddr *)instruction);
case IrInstructionIdAddImplicitReturnType:
return ir_analyze_instruction_add_implicit_return_type(ira, (IrInstructionAddImplicitReturnType *)instruction);
+ case IrInstructionIdMergeErrRetTraces:
+ return ir_analyze_instruction_merge_err_ret_traces(ira, (IrInstructionMergeErrRetTraces *)instruction);
+ case IrInstructionIdMarkErrRetTracePtr:
+ return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction);
}
zig_unreachable();
}
@@ -18282,6 +18386,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdAwaitBookkeeping:
case IrInstructionIdSaveErrRetAddr:
case IrInstructionIdAddImplicitReturnType:
+ case IrInstructionIdMergeErrRetTraces:
+ case IrInstructionIdMarkErrRetTracePtr:
return true;
case IrInstructionIdPhi: