mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
stage2: properly reset error return trace index
This commit is contained in:
parent
28054d96f0
commit
5316a00a18
4 changed files with 111 additions and 5 deletions
|
|
@ -2471,6 +2471,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
|
|||
.try_ptr,
|
||||
//.try_inline,
|
||||
//.try_ptr_inline,
|
||||
.save_err_ret_index,
|
||||
=> break :b false,
|
||||
|
||||
.extended => switch (gz.astgen.instructions.items(.data)[inst].extended.opcode) {
|
||||
|
|
@ -2533,6 +2534,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
|
|||
.validate_array_init_ty,
|
||||
.validate_struct_init_ty,
|
||||
.validate_deref,
|
||||
.restore_err_ret_index,
|
||||
=> break :b true,
|
||||
|
||||
.@"defer" => unreachable,
|
||||
|
|
@ -5152,10 +5154,16 @@ fn orelseCatchExpr(
|
|||
const astgen = parent_gz.astgen;
|
||||
const tree = astgen.tree;
|
||||
|
||||
const do_err_trace = astgen.fn_block != null and (cond_op == .is_non_err or cond_op == .is_non_err_ptr);
|
||||
|
||||
var block_scope = parent_gz.makeSubBlock(scope);
|
||||
block_scope.setBreakResultLoc(rl);
|
||||
defer block_scope.unstack();
|
||||
|
||||
if (do_err_trace) {
|
||||
block_scope.saved_err_trace_index = try parent_gz.addNode(.save_err_ret_index, node);
|
||||
}
|
||||
|
||||
const operand_rl: ResultLoc = switch (block_scope.break_result_loc) {
|
||||
.ref => .ref,
|
||||
else => .none,
|
||||
|
|
@ -5220,7 +5228,7 @@ fn orelseCatchExpr(
|
|||
// instructions or not.
|
||||
|
||||
const break_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .break_inline else .@"break";
|
||||
return finishThenElseBlock(
|
||||
const result = try finishThenElseBlock(
|
||||
parent_gz,
|
||||
rl,
|
||||
node,
|
||||
|
|
@ -5235,6 +5243,16 @@ fn orelseCatchExpr(
|
|||
block,
|
||||
break_tag,
|
||||
);
|
||||
if (do_err_trace) {
|
||||
_ = try parent_gz.add(.{
|
||||
.tag = .restore_err_ret_index,
|
||||
.data = .{ .un_node = .{
|
||||
.operand = parent_gz.saved_err_trace_index,
|
||||
.src_node = parent_gz.nodeIndexToRelative(node),
|
||||
} },
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Supports `else_scope` stacked on `then_scope` stacked on `block_scope`. Unstacks `else_scope` then `then_scope`.
|
||||
|
|
@ -5430,10 +5448,16 @@ fn ifExpr(
|
|||
const tree = astgen.tree;
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
|
||||
const do_err_trace = astgen.fn_block != null and if_full.error_token != null;
|
||||
|
||||
var block_scope = parent_gz.makeSubBlock(scope);
|
||||
block_scope.setBreakResultLoc(rl);
|
||||
defer block_scope.unstack();
|
||||
|
||||
if (do_err_trace) {
|
||||
block_scope.saved_err_trace_index = try parent_gz.addNode(.save_err_ret_index, node);
|
||||
}
|
||||
|
||||
const payload_is_ref = if (if_full.payload_token) |payload_token|
|
||||
token_tags[payload_token] == .asterisk
|
||||
else
|
||||
|
|
@ -5602,7 +5626,7 @@ fn ifExpr(
|
|||
};
|
||||
|
||||
const break_tag: Zir.Inst.Tag = if (parent_gz.force_comptime) .break_inline else .@"break";
|
||||
return finishThenElseBlock(
|
||||
const result = try finishThenElseBlock(
|
||||
parent_gz,
|
||||
rl,
|
||||
node,
|
||||
|
|
@ -5617,6 +5641,16 @@ fn ifExpr(
|
|||
block,
|
||||
break_tag,
|
||||
);
|
||||
if (do_err_trace) {
|
||||
_ = try parent_gz.add(.{
|
||||
.tag = .restore_err_ret_index,
|
||||
.data = .{ .un_node = .{
|
||||
.operand = parent_gz.saved_err_trace_index,
|
||||
.src_node = parent_gz.nodeIndexToRelative(node),
|
||||
} },
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Supports `else_scope` stacked on `then_scope`. Unstacks `else_scope` then `then_scope`.
|
||||
|
|
@ -10300,6 +10334,8 @@ const GenZir = struct {
|
|||
/// Keys are the raw instruction index, values are the closure_capture instruction.
|
||||
captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{},
|
||||
|
||||
saved_err_trace_index: Zir.Inst.Ref = .none,
|
||||
|
||||
const unstacked_top = std.math.maxInt(usize);
|
||||
/// Call unstack before adding any new instructions to containing GenZir.
|
||||
fn unstack(self: *GenZir) void {
|
||||
|
|
@ -10344,6 +10380,7 @@ const GenZir = struct {
|
|||
.any_defer_node = gz.any_defer_node,
|
||||
.instructions = gz.instructions,
|
||||
.instructions_top = gz.instructions.items.len,
|
||||
.saved_err_trace_index = gz.saved_err_trace_index,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
55
src/Sema.zig
55
src/Sema.zig
|
|
@ -926,6 +926,8 @@ fn analyzeBodyInner(
|
|||
.ret_ptr => try sema.zirRetPtr(block, inst),
|
||||
.ret_type => try sema.addType(sema.fn_ret_ty),
|
||||
|
||||
.save_err_ret_index => try sema.zirSaveErrRetIndex(block, inst),
|
||||
|
||||
// Instructions that we know to *always* be noreturn based solely on their tag.
|
||||
// These functions match the return type of analyzeBody so that we can
|
||||
// tail call them here.
|
||||
|
|
@ -1208,6 +1210,11 @@ fn analyzeBodyInner(
|
|||
i += 1;
|
||||
continue;
|
||||
},
|
||||
.restore_err_ret_index => {
|
||||
try sema.zirRestoreErrRetIndex(block, inst);
|
||||
i += 1;
|
||||
continue;
|
||||
},
|
||||
|
||||
// Special case instructions to handle comptime control flow.
|
||||
.@"break" => {
|
||||
|
|
@ -16176,6 +16183,52 @@ fn wantErrorReturnTracing(sema: *Sema, fn_ret_ty: Type) bool {
|
|||
backend_supports_error_return_tracing;
|
||||
}
|
||||
|
||||
fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].node;
|
||||
const src = LazySrcLoc.nodeOffset(inst_data);
|
||||
|
||||
// This is only relevant at runtime.
|
||||
if (block.is_comptime) return Air.Inst.Ref.zero_usize;
|
||||
|
||||
const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm;
|
||||
const ok = sema.owner_func.?.calls_or_awaits_errorable_fn and
|
||||
sema.mod.comp.bin_file.options.error_return_tracing and
|
||||
backend_supports_error_return_tracing;
|
||||
if (!ok) return Air.Inst.Ref.zero_usize;
|
||||
|
||||
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.single_mut_pointer.create(sema.arena, stack_trace_ty);
|
||||
const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
|
||||
return sema.fieldVal(block, src, err_return_trace, "index", src);
|
||||
}
|
||||
|
||||
fn zirRestoreErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
|
||||
const src = inst_data.src();
|
||||
|
||||
// This is only relevant at runtime.
|
||||
if (block.is_comptime) return;
|
||||
|
||||
const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm;
|
||||
const ok = sema.owner_func.?.calls_or_awaits_errorable_fn and
|
||||
sema.mod.comp.bin_file.options.error_return_tracing and
|
||||
backend_supports_error_return_tracing;
|
||||
if (!ok) return;
|
||||
|
||||
const operand = if (inst_data.operand != .none)
|
||||
try sema.resolveInst(inst_data.operand)
|
||||
else
|
||||
.zero_usize;
|
||||
|
||||
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.single_mut_pointer.create(sema.arena, stack_trace_ty);
|
||||
const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
|
||||
const field_ptr = try sema.structFieldPtr(block, src, err_return_trace, "index", src, stack_trace_ty, true);
|
||||
try sema.storePtr2(block, src, field_ptr, src, operand, src, .store);
|
||||
}
|
||||
|
||||
fn addToInferredErrorSet(sema: *Sema, uncasted_operand: Air.Inst.Ref) !void {
|
||||
assert(sema.fn_ret_ty.zigTypeTag() == .ErrorUnion);
|
||||
|
||||
|
|
@ -17181,8 +17234,6 @@ fn zirBoolToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
|
|||
|
||||
fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
|
||||
const src = inst_data.src();
|
||||
_ = src;
|
||||
const operand = try sema.resolveInst(inst_data.operand);
|
||||
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
|
||||
|
||||
|
|
|
|||
16
src/Zir.zig
16
src/Zir.zig
|
|
@ -988,6 +988,15 @@ pub const Inst = struct {
|
|||
/// Uses the `err_defer_code` union field.
|
||||
defer_err_code,
|
||||
|
||||
/// Saves the current error return case if it exists,
|
||||
/// otherwise just returns zero.
|
||||
/// Uses the `node` union field.
|
||||
save_err_ret_index,
|
||||
/// Sets error return trace to zero if no operand is given,
|
||||
/// otherwise sets the value to the given amount.
|
||||
/// Uses the `un_node` union field.
|
||||
restore_err_ret_index,
|
||||
|
||||
/// The ZIR instruction tag is one of the `Extended` ones.
|
||||
/// Uses the `extended` union field.
|
||||
extended,
|
||||
|
|
@ -1236,6 +1245,8 @@ pub const Inst = struct {
|
|||
//.try_ptr_inline,
|
||||
.@"defer",
|
||||
.defer_err_code,
|
||||
.save_err_ret_index,
|
||||
.restore_err_ret_index,
|
||||
=> false,
|
||||
|
||||
.@"break",
|
||||
|
|
@ -1305,6 +1316,7 @@ pub const Inst = struct {
|
|||
.check_comptime_control_flow,
|
||||
.@"defer",
|
||||
.defer_err_code,
|
||||
.restore_err_ret_index,
|
||||
=> true,
|
||||
|
||||
.param,
|
||||
|
|
@ -1530,6 +1542,7 @@ pub const Inst = struct {
|
|||
.try_ptr,
|
||||
//.try_inline,
|
||||
//.try_ptr_inline,
|
||||
.save_err_ret_index,
|
||||
=> false,
|
||||
|
||||
.extended => switch (data.extended.opcode) {
|
||||
|
|
@ -1810,6 +1823,9 @@ pub const Inst = struct {
|
|||
.@"defer" = .@"defer",
|
||||
.defer_err_code = .defer_err_code,
|
||||
|
||||
.save_err_ret_index = .node,
|
||||
.restore_err_ret_index = .un_node,
|
||||
|
||||
.extended = .extended,
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -232,6 +232,7 @@ const Writer = struct {
|
|||
.validate_deref,
|
||||
.overflow_arithmetic_ptr,
|
||||
.check_comptime_control_flow,
|
||||
.restore_err_ret_index,
|
||||
=> try self.writeUnNode(stream, inst),
|
||||
|
||||
.ref,
|
||||
|
|
@ -405,6 +406,7 @@ const Writer = struct {
|
|||
.alloc_inferred_comptime_mut,
|
||||
.ret_ptr,
|
||||
.ret_type,
|
||||
.save_err_ret_index,
|
||||
=> try self.writeNode(stream, inst),
|
||||
|
||||
.error_value,
|
||||
|
|
@ -440,7 +442,7 @@ const Writer = struct {
|
|||
|
||||
.dbg_block_begin,
|
||||
.dbg_block_end,
|
||||
=> try stream.writeAll("))"),
|
||||
=> try stream.writeAll(")"),
|
||||
|
||||
.closure_get => try self.writeInstNode(stream, inst),
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue