aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-04-22 21:30:54 +0300
committerAndrew Kelley <andrew@ziglang.org>2022-05-16 17:42:51 -0700
commiteee8fffec70b1d3e2900970dbe836e346e499231 (patch)
treeba6418a557532cbe2aee2be1045f84ff0f3ee0ce /src/Sema.zig
parent5888446c03b1f77a031f5a8093488a6a2f6decb6 (diff)
downloadzig-eee8fffec70b1d3e2900970dbe836e346e499231.tar.gz
zig-eee8fffec70b1d3e2900970dbe836e346e499231.zip
stage2: implement error return traces
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig75
1 files changed, 67 insertions, 8 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 471639ba96..ab2a59f44a 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -1411,6 +1411,38 @@ fn analyzeAsType(
return ty.copy(sema.arena);
}
+pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) !void {
+ var err_trace_block = block.makeSubBlock();
+ err_trace_block.is_comptime = false;
+ defer err_trace_block.instructions.deinit(sema.gpa);
+
+ const src: LazySrcLoc = .unneeded;
+
+ // var addrs: [err_return_trace_addr_count]usize = undefined;
+ const err_return_trace_addr_count = 32;
+ const addr_arr_ty = try Type.array(sema.arena, err_return_trace_addr_count, null, Type.usize, sema.mod);
+ const addrs_ptr = try err_trace_block.addTy(.alloc, try Type.Tag.single_mut_pointer.create(sema.arena, addr_arr_ty));
+
+ // var st: StackTrace = undefined;
+ const unresolved_stack_trace_ty = try sema.getBuiltinType(&err_trace_block, src, "StackTrace");
+ const stack_trace_ty = try sema.resolveTypeFields(&err_trace_block, src, unresolved_stack_trace_ty);
+ const st_ptr = try err_trace_block.addTy(.alloc, try Type.Tag.single_mut_pointer.create(sema.arena, stack_trace_ty));
+
+ // st.instruction_addresses = &addrs;
+ const addr_field_ptr = try sema.fieldPtr(&err_trace_block, src, st_ptr, "instruction_addresses", src);
+ try sema.storePtr2(&err_trace_block, src, addr_field_ptr, src, addrs_ptr, src, .store);
+
+ // st.index = 0;
+ const index_field_ptr = try sema.fieldPtr(&err_trace_block, src, st_ptr, "index", src);
+ const zero = try sema.addConstant(Type.usize, Value.zero);
+ try sema.storePtr2(&err_trace_block, src, index_field_ptr, src, zero, src, .store);
+
+ // @errorReturnTrace() = &st;
+ _ = try err_trace_block.addUnOp(.set_err_return_trace, st_ptr);
+
+ try block.instructions.insertSlice(sema.gpa, last_arg_index, err_trace_block.instructions.items);
+}
+
/// May return Value Tags: `variable`, `undef`.
/// See `resolveConstValue` for an alternative.
/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.
@@ -5236,6 +5268,13 @@ fn analyzeCall(
}
try sema.queueFullTypeResolution(func_ty_info.return_type);
+ if (sema.owner_func != null and func_ty_info.return_type.isError()) {
+ if (!sema.owner_func.?.calls_or_awaits_errorable_fn) {
+ // Ensure the type exists so that backends can assume that.
+ _ = try sema.getBuiltinType(block, call_src, "StackTrace");
+ }
+ sema.owner_func.?.calls_or_awaits_errorable_fn = true;
+ }
try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).Struct.fields.len +
args.len);
@@ -5645,6 +5684,15 @@ fn instantiateGenericCall(
try sema.queueFullTypeResolution(new_fn_info.return_type);
}
+
+ if (sema.owner_func != null and new_fn_info.return_type.isError()) {
+ if (!sema.owner_func.?.calls_or_awaits_errorable_fn) {
+ // Ensure the type exists so that backends can assume that.
+ _ = try sema.getBuiltinType(block, call_src, "StackTrace");
+ }
+ sema.owner_func.?.calls_or_awaits_errorable_fn = true;
+ }
+
try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len +
runtime_args_len);
const func_inst = try block.addInst(.{
@@ -12607,6 +12655,16 @@ fn analyzeRet(
return always_noreturn;
}
+ if (sema.fn_ret_ty.isError() and sema.mod.comp.bin_file.options.error_return_tracing) {
+ const return_err_fn = try sema.getBuiltin(block, src, "returnError");
+ const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace");
+ const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty);
+ const ptr_stack_trace_ty = try Type.Tag.optional_single_mut_pointer.create(sema.arena, stack_trace_ty);
+ const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
+ const args: [1]Air.Inst.Ref = .{err_return_trace};
+ _ = try sema.analyzeCall(block, return_err_fn, src, src, .never_inline, false, &args);
+ }
+
try sema.resolveTypeLayout(block, src, sema.fn_ret_ty);
_ = try block.addUnOp(.ret, operand);
return always_noreturn;
@@ -13338,9 +13396,14 @@ fn zirErrorReturnTrace(
const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace");
const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty);
- const opt_stack_trace_ty = try Type.optional(sema.arena, stack_trace_ty);
- // https://github.com/ziglang/zig/issues/11259
- return sema.addConstant(opt_stack_trace_ty, Value.@"null");
+ const opt_ptr_stack_trace_ty = try Type.Tag.optional_single_mut_pointer.create(sema.arena, stack_trace_ty);
+ if (sema.owner_func != null and
+ sema.owner_func.?.calls_or_awaits_errorable_fn and
+ sema.mod.comp.bin_file.options.error_return_tracing)
+ {
+ return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);
+ }
+ return sema.addConstant(opt_ptr_stack_trace_ty, Value.@"null");
}
fn zirFrame(
@@ -21817,11 +21880,7 @@ fn resolvePeerTypes(
info.data.sentinel = chosen_child_ty.sentinel();
info.data.size = .Slice;
info.data.mutable = !(seen_const or chosen_child_ty.isConstPtr());
- info.data.pointee_type = switch (chosen_child_ty.tag()) {
- .array => chosen_child_ty.elemType2(),
- .array_u8, .array_u8_sentinel_0 => Type.initTag(.u8),
- else => unreachable,
- };
+ info.data.pointee_type = chosen_child_ty.elemType2();
const new_ptr_ty = try Type.ptr(sema.arena, sema.mod, info.data);
const opt_ptr_ty = if (any_are_null)