Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 11 additions & 13 deletions lib/compiler_rt.zig
Original file line number Diff line number Diff line change
Expand Up @@ -198,19 +198,17 @@ comptime {
const __trunctfxf2 = @import("compiler_rt/trunc_f80.zig").__trunctfxf2;
@export(__trunctfxf2, .{ .name = "__trunctfxf2", .linkage = linkage });

if (builtin.zig_backend == .stage1) { // TODO
switch (arch) {
.i386,
.x86_64,
=> {
const zig_probe_stack = @import("compiler_rt/stack_probe.zig").zig_probe_stack;
@export(zig_probe_stack, .{
.name = "__zig_probe_stack",
.linkage = linkage,
});
},
else => {},
}
switch (arch) {
.i386,
.x86_64,
=> {
const zig_probe_stack = @import("compiler_rt/stack_probe.zig").zig_probe_stack;
@export(zig_probe_stack, .{
.name = "__zig_probe_stack",
.linkage = linkage,
});
},
else => {},
}

const __unordsf2 = @import("compiler_rt/compareXf2.zig").__unordsf2;
Expand Down
21 changes: 21 additions & 0 deletions lib/std/builtin.zig
Original file line number Diff line number Diff line change
Expand Up @@ -846,5 +846,26 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace) noreturn
}
}

pub fn panicUnwrapError(st: ?*StackTrace, err: anyerror) noreturn {
@setCold(true);
std.debug.panicExtra(st, "attempt to unwrap error: {s}", .{@errorName(err)});
}

pub fn panicOutOfBounds(index: usize, len: usize) noreturn {
@setCold(true);
std.debug.panic("attempt to index out of bound: index {d}, len {d}", .{ index, len });
}

pub noinline fn returnError(maybe_st: ?*StackTrace) void {
@setCold(true);
const st = maybe_st orelse return;
addErrRetTraceAddr(st, @returnAddress());
}

pub inline fn addErrRetTraceAddr(st: *StackTrace, addr: usize) void {
st.instruction_addresses[st.index & (st.instruction_addresses.len - 1)] = addr;
st.index +%= 1;
}

const std = @import("std.zig");
const root = @import("root");
4 changes: 2 additions & 2 deletions lib/test_runner.zig
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ pub fn main() void {
fail_count += 1;
progress.log("FAIL ({s})\n", .{@errorName(err)});
if (!have_tty) std.debug.print("FAIL ({s})\n", .{@errorName(err)});
if (builtin.zig_backend != .stage2_llvm) if (@errorReturnTrace()) |trace| {
if (@errorReturnTrace()) |trace| {
std.debug.dumpStackTrace(trace.*);
};
}
test_node.end();
},
}
Expand Down
8 changes: 8 additions & 0 deletions src/Air.zig
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,12 @@ pub const Inst = struct {
/// flush().
cmp_lt_errors_len,

/// Returns pointer to current error return trace.
err_return_trace,

/// Sets the operand as the current error return trace,
set_err_return_trace,

pub fn fromCmpOp(op: std.math.CompareOperator) Tag {
return switch (op) {
.lt => .cmp_lt,
Expand Down Expand Up @@ -961,6 +967,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
.alloc,
.ret_ptr,
.arg,
.err_return_trace,
=> return datas[inst].ty,

.assembly,
Expand Down Expand Up @@ -1048,6 +1055,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
.memcpy,
.set_union_tag,
.prefetch,
.set_err_return_trace,
=> return Type.void,

.ptrtoint,
Expand Down
27 changes: 27 additions & 0 deletions src/AstGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,33 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
catch_token + 2
else
null;

var rhs = node_datas[node].rhs;
while (true) switch (node_tags[rhs]) {
.grouped_expression => rhs = node_datas[rhs].lhs,
.unreachable_literal => {
if (payload_token != null and mem.eql(u8, tree.tokenSlice(payload_token.?), "_")) {
return astgen.failTok(payload_token.?, "discard of error capture; omit it instead", .{});
} else if (payload_token != null) {
return astgen.failTok(payload_token.?, "unused capture", .{});
}
const lhs = node_datas[node].lhs;

const operand = try reachableExpr(gz, scope, switch (rl) {
.ref => .ref,
else => .none,
}, lhs, lhs);
const result = try gz.addUnNode(switch (rl) {
.ref => .err_union_payload_safe_ptr,
else => .err_union_payload_safe,
}, operand, node);
switch (rl) {
.none, .coerced_ty, .discard, .ref => return result,
else => return rvalue(gz, rl, result, lhs),
}
},
else => break,
};
switch (rl) {
.ref => return orelseCatchExpr(
gz,
Expand Down
3 changes: 2 additions & 1 deletion src/Compilation.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1457,7 +1457,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
errdefer if (module) |zm| zm.deinit();

const error_return_tracing = !strip and switch (options.optimize_mode) {
.Debug, .ReleaseSafe => true,
.Debug, .ReleaseSafe => (!options.target.isWasm() or options.target.os.tag == .emscripten) and
!options.target.cpu.arch.isBpf(),
.ReleaseFast, .ReleaseSmall => false,
};

Expand Down
2 changes: 2 additions & 0 deletions src/Liveness.zig
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ fn analyzeInst(
.ret_addr,
.frame_addr,
.wasm_memory_size,
.err_return_trace,
=> return trackOperands(a, new_set, inst, main_tomb, .{ .none, .none, .none }),

.not,
Expand Down Expand Up @@ -434,6 +435,7 @@ fn analyzeInst(
.round,
.trunc_float,
.cmp_lt_errors_len,
.set_err_return_trace,
=> {
const operand = inst_datas[inst].un_op;
return trackOperands(a, new_set, inst, main_tomb, .{ operand, .none, .none });
Expand Down
21 changes: 21 additions & 0 deletions src/Module.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1427,6 +1427,7 @@ pub const Fn = struct {
state: Analysis,
is_cold: bool = false,
is_noinline: bool = false,
calls_or_awaits_errorable_fn: bool = false,

/// Any inferred error sets that this function owns, both its own inferred error set and
/// inferred error sets of any inline/comptime functions called. Not to be confused
Expand Down Expand Up @@ -4838,6 +4839,9 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
};
defer sema.deinit();

// reset in case calls to errorable functions are removed.
func.calls_or_awaits_errorable_fn = false;

// First few indexes of extra are reserved and set at the end.
const reserved_count = @typeInfo(Air.ExtraIndex).Enum.fields.len;
try sema.air_extra.ensureTotalCapacity(gpa, reserved_count);
Expand Down Expand Up @@ -4936,6 +4940,8 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
func.state = .in_progress;
log.debug("set {s} to in_progress", .{decl.name});

const last_arg_index = inner_block.instructions.items.len;

sema.analyzeBody(&inner_block, fn_info.body) catch |err| switch (err) {
// TODO make these unreachable instead of @panic
error.NeededSourceLocation => @panic("zig compiler bug: NeededSourceLocation"),
Expand All @@ -4944,6 +4950,21 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
else => |e| return e,
};

// If we don't get an error return trace from a caller, create our own.
if (func.calls_or_awaits_errorable_fn and
mod.comp.bin_file.options.error_return_tracing and
!sema.fn_ret_ty.isError())
{
sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) {
// TODO make these unreachable instead of @panic
error.NeededSourceLocation => @panic("zig compiler bug: NeededSourceLocation"),
error.GenericPoison => @panic("zig compiler bug: GenericPoison"),
error.ComptimeReturn => @panic("zig compiler bug: ComptimeReturn"),
error.ComptimeBreak => @panic("zig compiler bug: ComptimeBreak"),
else => |e| return e,
};
}

try wip_captures.finalize();

// Copy the block into place and mark that as the main block.
Expand Down
Loading