Skip to content

Commit

Permalink
stage2: properly reset error return trace index
Browse files Browse the repository at this point in the history
  • Loading branch information
Vexu authored and topolarity committed Oct 20, 2022
1 parent 5b9c8d1 commit 02adf15
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 5 deletions.
41 changes: 39 additions & 2 deletions src/AstGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2466,6 +2466,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) {
Expand Down Expand Up @@ -2528,6 +2529,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,
Expand Down Expand Up @@ -5144,10 +5146,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,
Expand Down Expand Up @@ -5212,7 +5220,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,
Expand All @@ -5227,6 +5235,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`.
Expand Down Expand Up @@ -5422,10 +5440,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
Expand Down Expand Up @@ -5594,7 +5618,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,
Expand All @@ -5609,6 +5633,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`.
Expand Down Expand Up @@ -10289,6 +10323,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 {
Expand Down Expand Up @@ -10333,6 +10369,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,
};
}

Expand Down
55 changes: 53 additions & 2 deletions src/Sema.zig
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,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.
Expand Down Expand Up @@ -1205,6 +1207,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" => {
Expand Down Expand Up @@ -16135,6 +16142,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);

Expand Down Expand Up @@ -17139,8 +17192,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 };

Expand Down
16 changes: 16 additions & 0 deletions src/Zir.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -1305,6 +1316,7 @@ pub const Inst = struct {
.check_comptime_control_flow,
.@"defer",
.defer_err_code,
.restore_err_ret_index,
=> true,

.param,
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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,
});
};
Expand Down
4 changes: 3 additions & 1 deletion src/print_zir.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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),

Expand Down

0 comments on commit 02adf15

Please sign in to comment.