mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
AstGen: emit debug stmt for try
This improves the following test case:
```zig
pub fn main() !void {
try foo();
}
fn foo() !void {
return error.Bad;
}
```
The error return trace now points to the `try` token instead of pointing
to the foo() function call, matching stage1.
Closes #12308.
This commit is contained in:
parent
0648177ed7
commit
feb90f6ed4
2 changed files with 20 additions and 8 deletions
|
|
@ -5051,6 +5051,16 @@ fn tryExpr(
|
||||||
|
|
||||||
if (parent_gz.in_defer) return astgen.failNode(node, "'try' not allowed inside defer expression", .{});
|
if (parent_gz.in_defer) return astgen.failNode(node, "'try' not allowed inside defer expression", .{});
|
||||||
|
|
||||||
|
// Ensure debug line/column information is emitted for this try expression.
|
||||||
|
// Then we will save the line/column so that we can emit another one that goes
|
||||||
|
// "backwards" because we want to evaluate the operand, but then put the debug
|
||||||
|
// info back at the try keyword for error return tracing.
|
||||||
|
if (!parent_gz.force_comptime) {
|
||||||
|
try emitDbgNode(parent_gz, node);
|
||||||
|
}
|
||||||
|
const try_line = astgen.source_line - parent_gz.decl_line;
|
||||||
|
const try_column = astgen.source_column;
|
||||||
|
|
||||||
const operand_rl: ResultLoc = switch (rl) {
|
const operand_rl: ResultLoc = switch (rl) {
|
||||||
.ref => .ref,
|
.ref => .ref,
|
||||||
else => .none,
|
else => .none,
|
||||||
|
|
@ -5080,6 +5090,7 @@ fn tryExpr(
|
||||||
};
|
};
|
||||||
const err_code = try else_scope.addUnNode(err_tag, operand, node);
|
const err_code = try else_scope.addUnNode(err_tag, operand, node);
|
||||||
try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code });
|
try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code });
|
||||||
|
try emitDbgStmt(&else_scope, try_line, try_column);
|
||||||
_ = try else_scope.addUnNode(.ret_node, err_code, node);
|
_ = try else_scope.addUnNode(.ret_node, err_code, node);
|
||||||
|
|
||||||
try else_scope.setTryBody(try_inst, operand);
|
try else_scope.setTryBody(try_inst, operand);
|
||||||
|
|
@ -6614,13 +6625,13 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
|
||||||
const defer_counts = countDefers(astgen, defer_outer, scope);
|
const defer_counts = countDefers(astgen, defer_outer, scope);
|
||||||
if (!defer_counts.need_err_code) {
|
if (!defer_counts.need_err_code) {
|
||||||
try genDefers(gz, defer_outer, scope, .both_sans_err);
|
try genDefers(gz, defer_outer, scope, .both_sans_err);
|
||||||
try emitRetDbgStmt(gz, ret_line, ret_column);
|
try emitDbgStmt(gz, ret_line, ret_column);
|
||||||
_ = try gz.addStrTok(.ret_err_value, err_name_str_index, ident_token);
|
_ = try gz.addStrTok(.ret_err_value, err_name_str_index, ident_token);
|
||||||
return Zir.Inst.Ref.unreachable_value;
|
return Zir.Inst.Ref.unreachable_value;
|
||||||
}
|
}
|
||||||
const err_code = try gz.addStrTok(.ret_err_value_code, err_name_str_index, ident_token);
|
const err_code = try gz.addStrTok(.ret_err_value_code, err_name_str_index, ident_token);
|
||||||
try genDefers(gz, defer_outer, scope, .{ .both = err_code });
|
try genDefers(gz, defer_outer, scope, .{ .both = err_code });
|
||||||
try emitRetDbgStmt(gz, ret_line, ret_column);
|
try emitDbgStmt(gz, ret_line, ret_column);
|
||||||
_ = try gz.addUnNode(.ret_node, err_code, node);
|
_ = try gz.addUnNode(.ret_node, err_code, node);
|
||||||
return Zir.Inst.Ref.unreachable_value;
|
return Zir.Inst.Ref.unreachable_value;
|
||||||
}
|
}
|
||||||
|
|
@ -6639,7 +6650,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
|
||||||
.never => {
|
.never => {
|
||||||
// Returning a value that cannot be an error; skip error defers.
|
// Returning a value that cannot be an error; skip error defers.
|
||||||
try genDefers(gz, defer_outer, scope, .normal_only);
|
try genDefers(gz, defer_outer, scope, .normal_only);
|
||||||
try emitRetDbgStmt(gz, ret_line, ret_column);
|
try emitDbgStmt(gz, ret_line, ret_column);
|
||||||
try gz.addRet(rl, operand, node);
|
try gz.addRet(rl, operand, node);
|
||||||
return Zir.Inst.Ref.unreachable_value;
|
return Zir.Inst.Ref.unreachable_value;
|
||||||
},
|
},
|
||||||
|
|
@ -6647,7 +6658,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
|
||||||
// Value is always an error. Emit both error defers and regular defers.
|
// Value is always an error. Emit both error defers and regular defers.
|
||||||
const err_code = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr, node) else operand;
|
const err_code = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr, node) else operand;
|
||||||
try genDefers(gz, defer_outer, scope, .{ .both = err_code });
|
try genDefers(gz, defer_outer, scope, .{ .both = err_code });
|
||||||
try emitRetDbgStmt(gz, ret_line, ret_column);
|
try emitDbgStmt(gz, ret_line, ret_column);
|
||||||
try gz.addRet(rl, operand, node);
|
try gz.addRet(rl, operand, node);
|
||||||
return Zir.Inst.Ref.unreachable_value;
|
return Zir.Inst.Ref.unreachable_value;
|
||||||
},
|
},
|
||||||
|
|
@ -6656,7 +6667,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
|
||||||
if (!defer_counts.have_err) {
|
if (!defer_counts.have_err) {
|
||||||
// Only regular defers; no branch needed.
|
// Only regular defers; no branch needed.
|
||||||
try genDefers(gz, defer_outer, scope, .normal_only);
|
try genDefers(gz, defer_outer, scope, .normal_only);
|
||||||
try emitRetDbgStmt(gz, ret_line, ret_column);
|
try emitDbgStmt(gz, ret_line, ret_column);
|
||||||
try gz.addRet(rl, operand, node);
|
try gz.addRet(rl, operand, node);
|
||||||
return Zir.Inst.Ref.unreachable_value;
|
return Zir.Inst.Ref.unreachable_value;
|
||||||
}
|
}
|
||||||
|
|
@ -6670,7 +6681,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
|
||||||
defer then_scope.unstack();
|
defer then_scope.unstack();
|
||||||
|
|
||||||
try genDefers(&then_scope, defer_outer, scope, .normal_only);
|
try genDefers(&then_scope, defer_outer, scope, .normal_only);
|
||||||
try emitRetDbgStmt(gz, ret_line, ret_column);
|
try emitDbgStmt(&then_scope, ret_line, ret_column);
|
||||||
try then_scope.addRet(rl, operand, node);
|
try then_scope.addRet(rl, operand, node);
|
||||||
|
|
||||||
var else_scope = gz.makeSubBlock(scope);
|
var else_scope = gz.makeSubBlock(scope);
|
||||||
|
|
@ -6680,7 +6691,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
|
||||||
.both = try else_scope.addUnNode(.err_union_code, result, node),
|
.both = try else_scope.addUnNode(.err_union_code, result, node),
|
||||||
};
|
};
|
||||||
try genDefers(&else_scope, defer_outer, scope, which_ones);
|
try genDefers(&else_scope, defer_outer, scope, which_ones);
|
||||||
try emitRetDbgStmt(gz, ret_line, ret_column);
|
try emitDbgStmt(&else_scope, ret_line, ret_column);
|
||||||
try else_scope.addRet(rl, operand, node);
|
try else_scope.addRet(rl, operand, node);
|
||||||
|
|
||||||
try setCondBrPayload(condbr, is_non_err, &then_scope, 0, &else_scope, 0);
|
try setCondBrPayload(condbr, is_non_err, &then_scope, 0, &else_scope, 0);
|
||||||
|
|
@ -11698,7 +11709,7 @@ fn countBodyLenAfterFixups(astgen: *AstGen, body: []const Zir.Inst.Index) u32 {
|
||||||
return @intCast(u32, count);
|
return @intCast(u32, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emitRetDbgStmt(gz: *GenZir, line: u32, column: u32) !void {
|
fn emitDbgStmt(gz: *GenZir, line: u32, column: u32) !void {
|
||||||
if (gz.force_comptime) return;
|
if (gz.force_comptime) return;
|
||||||
|
|
||||||
_ = try gz.add(.{ .tag = .dbg_stmt, .data = .{
|
_ = try gz.add(.{ .tag = .dbg_stmt, .data = .{
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
|
||||||
.ReleaseSafe = .{
|
.ReleaseSafe = .{
|
||||||
.exclude_os = .{
|
.exclude_os = .{
|
||||||
.windows, // segfault
|
.windows, // segfault
|
||||||
|
.linux, // defeated by aggressive inlining
|
||||||
},
|
},
|
||||||
.expect =
|
.expect =
|
||||||
\\error: TheSkyIsFalling
|
\\error: TheSkyIsFalling
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue