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(...@@ -5051,6 +5051,16 @@ fn tryExpr(
50515051
5052 if (parent_gz.in_defer) return astgen.failNode(node, "'try' not allowed inside defer expression", .{});5052 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
5054 const operand_rl: ResultLoc = switch (rl) {5064 const operand_rl: ResultLoc = switch (rl) {
5055 .ref => .ref,5065 .ref => .ref,
5056 else => .none,5066 else => .none,
...@@ -5080,6 +5090,7 @@ fn tryExpr(...@@ -5080,6 +5090,7 @@ fn tryExpr(
5080 };5090 };
5081 const err_code = try else_scope.addUnNode(err_tag, operand, node);5091 const err_code = try else_scope.addUnNode(err_tag, operand, node);
5082 try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code });5092 try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code });
5093 try emitDbgStmt(&else_scope, try_line, try_column);
5083 _ = try else_scope.addUnNode(.ret_node, err_code, node);5094 _ = try else_scope.addUnNode(.ret_node, err_code, node);
50845095
5085 try else_scope.setTryBody(try_inst, operand);5096 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...@@ -6614,13 +6625,13 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
6614 const defer_counts = countDefers(astgen, defer_outer, scope);6625 const defer_counts = countDefers(astgen, defer_outer, scope);
6615 if (!defer_counts.need_err_code) {6626 if (!defer_counts.need_err_code) {
6616 try genDefers(gz, defer_outer, scope, .both_sans_err);6627 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);
6618 _ = try gz.addStrTok(.ret_err_value, err_name_str_index, ident_token);6629 _ = try gz.addStrTok(.ret_err_value, err_name_str_index, ident_token);
6619 return Zir.Inst.Ref.unreachable_value;6630 return Zir.Inst.Ref.unreachable_value;
6620 }6631 }
6621 const err_code = try gz.addStrTok(.ret_err_value_code, err_name_str_index, ident_token);6632 const err_code = try gz.addStrTok(.ret_err_value_code, err_name_str_index, ident_token);
6622 try genDefers(gz, defer_outer, scope, .{ .both = err_code });6633 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);
6624 _ = try gz.addUnNode(.ret_node, err_code, node);6635 _ = try gz.addUnNode(.ret_node, err_code, node);
6625 return Zir.Inst.Ref.unreachable_value;6636 return Zir.Inst.Ref.unreachable_value;
6626 }6637 }
...@@ -6639,7 +6650,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -6639,7 +6650,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
6639 .never => {6650 .never => {
6640 // Returning a value that cannot be an error; skip error defers.6651 // Returning a value that cannot be an error; skip error defers.
6641 try genDefers(gz, defer_outer, scope, .normal_only);6652 try genDefers(gz, defer_outer, scope, .normal_only);
6642 try emitRetDbgStmt(gz, ret_line, ret_column);6653 try emitDbgStmt(gz, ret_line, ret_column);
6643 try gz.addRet(rl, operand, node);6654 try gz.addRet(rl, operand, node);
6644 return Zir.Inst.Ref.unreachable_value;6655 return Zir.Inst.Ref.unreachable_value;
6645 },6656 },
...@@ -6647,7 +6658,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -6647,7 +6658,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
6647 // Value is always an error. Emit both error defers and regular defers.6658 // Value is always an error. Emit both error defers and regular defers.
6648 const err_code = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr, node) else operand;6659 const err_code = if (rl == .ptr) try gz.addUnNode(.load, rl.ptr, node) else operand;
6649 try genDefers(gz, defer_outer, scope, .{ .both = err_code });6660 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);
6651 try gz.addRet(rl, operand, node);6662 try gz.addRet(rl, operand, node);
6652 return Zir.Inst.Ref.unreachable_value;6663 return Zir.Inst.Ref.unreachable_value;
6653 },6664 },
...@@ -6656,7 +6667,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -6656,7 +6667,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
6656 if (!defer_counts.have_err) {6667 if (!defer_counts.have_err) {
6657 // Only regular defers; no branch needed.6668 // Only regular defers; no branch needed.
6658 try genDefers(gz, defer_outer, scope, .normal_only);6669 try genDefers(gz, defer_outer, scope, .normal_only);
6659 try emitRetDbgStmt(gz, ret_line, ret_column);6670 try emitDbgStmt(gz, ret_line, ret_column);
6660 try gz.addRet(rl, operand, node);6671 try gz.addRet(rl, operand, node);
6661 return Zir.Inst.Ref.unreachable_value;6672 return Zir.Inst.Ref.unreachable_value;
6662 }6673 }
...@@ -6670,7 +6681,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -6670,7 +6681,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
6670 defer then_scope.unstack();6681 defer then_scope.unstack();
66716682
6672 try genDefers(&then_scope, defer_outer, scope, .normal_only);6683 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);
6674 try then_scope.addRet(rl, operand, node);6685 try then_scope.addRet(rl, operand, node);
66756686
6676 var else_scope = gz.makeSubBlock(scope);6687 var else_scope = gz.makeSubBlock(scope);
...@@ -6680,7 +6691,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -6680,7 +6691,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
6680 .both = try else_scope.addUnNode(.err_union_code, result, node),6691 .both = try else_scope.addUnNode(.err_union_code, result, node),
6681 };6692 };
6682 try genDefers(&else_scope, defer_outer, scope, which_ones);6693 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);
6684 try else_scope.addRet(rl, operand, node);6695 try else_scope.addRet(rl, operand, node);
66856696
6686 try setCondBrPayload(condbr, is_non_err, &then_scope, 0, &else_scope, 0);6697 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 {...@@ -11698,7 +11709,7 @@ fn countBodyLenAfterFixups(astgen: *AstGen, body: []const Zir.Inst.Index) u32 {
11698 return @intCast(u32, count);11709 return @intCast(u32, count);
11699}11710}
1170011711
11701fn emitRetDbgStmt(gz: *GenZir, line: u32, column: u32) !void {11712fn emitDbgStmt(gz: *GenZir, line: u32, column: u32) !void {
11702 if (gz.force_comptime) return;11713 if (gz.force_comptime) return;
1170311714
11704 _ = try gz.add(.{ .tag = .dbg_stmt, .data = .{11715 _ = try gz.add(.{ .tag = .dbg_stmt, .data = .{
test/stack_traces.zig+1
...@@ -22,6 +22,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void {...@@ -22,6 +22,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
22 .ReleaseSafe = .{22 .ReleaseSafe = .{
23 .exclude_os = .{23 .exclude_os = .{
24 .windows, // segfault24 .windows, // segfault
25 .linux, // defeated by aggressive inlining
25 },26 },
26 .expect = 27 .expect =
27 \\error: TheSkyIsFalling28 \\error: TheSkyIsFalling