authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-08-08 20:53:06-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-08-08 21:12:04-07:00
logfeb90f6ed4f64eb0faef8fbbcf8c51fad5392b39
tree39e5fc83c905256d24a903ed8b6f56c26b5102b6
parent0648177ed7a1ad5364c478b63ec28a6de15e4ad9

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.

2 files changed, 20 insertions(+), 8 deletions(-)

src/AstGen.zig+19-8
......@@ -5051,6 +5051,16 @@ fn tryExpr(
50515051
50525052 if (parent_gz.in_defer) return astgen.failNode(node, "'try' not allowed inside defer expression", .{});
50535053
5054 // Ensure debug line/column information is emitted for this try expression.
5055 // Then we will save the line/column so that we can emit another one that goes
5056 // "backwards" because we want to evaluate the operand, but then put the debug
5057 // info back at the try keyword for error return tracing.
5058 if (!parent_gz.force_comptime) {
5059 try emitDbgNode(parent_gz, node);
5060 }
5061 const try_line = astgen.source_line - parent_gz.decl_line;
5062 const try_column = astgen.source_column;
5063
50545064 const operand_rl: ResultLoc = switch (rl) {
50555065 .ref => .ref,
50565066 else => .none,
......@@ -5080,6 +5090,7 @@ fn tryExpr(
50805090 };
50815091 const err_code = try else_scope.addUnNode(err_tag, operand, node);
50825092 try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code });
5093 try emitDbgStmt(&else_scope, try_line, try_column);
50835094 _ = try else_scope.addUnNode(.ret_node, err_code, node);
50845095
50855096 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
66146625 const defer_counts = countDefers(astgen, defer_outer, scope);
66156626 if (!defer_counts.need_err_code) {
66166627 try genDefers(gz, defer_outer, scope, .both_sans_err);
6617 try emitRetDbgStmt(gz, ret_line, ret_column);
6628 try emitDbgStmt(gz, ret_line, ret_column);
66186629 _ = try gz.addStrTok(.ret_err_value, err_name_str_index, ident_token);
66196630 return Zir.Inst.Ref.unreachable_value;
66206631 }
66216632 const err_code = try gz.addStrTok(.ret_err_value_code, err_name_str_index, ident_token);
66226633 try genDefers(gz, defer_outer, scope, .{ .both = err_code });
6623 try emitRetDbgStmt(gz, ret_line, ret_column);
6634 try emitDbgStmt(gz, ret_line, ret_column);
66246635 _ = try gz.addUnNode(.ret_node, err_code, node);
66256636 return Zir.Inst.Ref.unreachable_value;
66266637 }
......@@ -6639,7 +6650,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
66396650 .never => {
66406651 // Returning a value that cannot be an error; skip error defers.
66416652 try genDefers(gz, defer_outer, scope, .normal_only);
6642 try emitRetDbgStmt(gz, ret_line, ret_column);
6653 try emitDbgStmt(gz, ret_line, ret_column);
66436654 try gz.addRet(rl, operand, node);
66446655 return Zir.Inst.Ref.unreachable_value;
66456656 },
......@@ -6647,7 +6658,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
66476658 // Value is always an error. Emit both error defers and regular defers.
66486659 const err_code = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr, node) else operand;
66496660 try genDefers(gz, defer_outer, scope, .{ .both = err_code });
6650 try emitRetDbgStmt(gz, ret_line, ret_column);
6661 try emitDbgStmt(gz, ret_line, ret_column);
66516662 try gz.addRet(rl, operand, node);
66526663 return Zir.Inst.Ref.unreachable_value;
66536664 },
......@@ -6656,7 +6667,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
66566667 if (!defer_counts.have_err) {
66576668 // Only regular defers; no branch needed.
66586669 try genDefers(gz, defer_outer, scope, .normal_only);
6659 try emitRetDbgStmt(gz, ret_line, ret_column);
6670 try emitDbgStmt(gz, ret_line, ret_column);
66606671 try gz.addRet(rl, operand, node);
66616672 return Zir.Inst.Ref.unreachable_value;
66626673 }
......@@ -6670,7 +6681,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
66706681 defer then_scope.unstack();
66716682
66726683 try genDefers(&then_scope, defer_outer, scope, .normal_only);
6673 try emitRetDbgStmt(gz, ret_line, ret_column);
6684 try emitDbgStmt(&then_scope, ret_line, ret_column);
66746685 try then_scope.addRet(rl, operand, node);
66756686
66766687 var else_scope = gz.makeSubBlock(scope);
......@@ -6680,7 +6691,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
66806691 .both = try else_scope.addUnNode(.err_union_code, result, node),
66816692 };
66826693 try genDefers(&else_scope, defer_outer, scope, which_ones);
6683 try emitRetDbgStmt(gz, ret_line, ret_column);
6694 try emitDbgStmt(&else_scope, ret_line, ret_column);
66846695 try else_scope.addRet(rl, operand, node);
66856696
66866697 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 {
1169811709 return @intCast(u32, count);
1169911710}
1170011711
11701fn emitRetDbgStmt(gz: *GenZir, line: u32, column: u32) !void {
11712fn emitDbgStmt(gz: *GenZir, line: u32, column: u32) !void {
1170211713 if (gz.force_comptime) return;
1170311714
1170411715 _ = try gz.add(.{ .tag = .dbg_stmt, .data = .{
test/stack_traces.zig+1
......@@ -22,6 +22,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
2222 .ReleaseSafe = .{
2323 .exclude_os = .{
2424 .windows, // segfault
25 .linux, // defeated by aggressive inlining
2526 },
2627 .expect =
2728 \\error: TheSkyIsFalling