Last active
June 7, 2022 22:04
-
-
Save andrewrk/b2ab3699d070ce6af0cb1da5019513d7 to your computer and use it in GitHub Desktop.
a new std.debug.Trace API
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| pub fn Trace(comptime size: usize, comptime stack_frame_count: usize) type { | |
| return struct { | |
| addrs: [size][stack_frame_count]usize = undefined, | |
| notes: [size][]const u8 = undefined, | |
| index: usize = 0, | |
| const frames_init = [1]usize{0} ** stack_frame_count; | |
| pub noinline fn add(t: *@This(), note: []const u8) void { | |
| return addAddr(t, @returnAddress(), note); | |
| } | |
| pub fn addAddr(t: *@This(), addr: usize, note: []const u8) void { | |
| if (t.index < size) { | |
| t.notes[t.index] = note; | |
| t.addrs[t.index] = [1]usize{0} ** stack_frame_count; | |
| var stack_trace: std.builtin.StackTrace = .{ | |
| .index = 0, | |
| .instruction_addresses = &t.addrs[t.index], | |
| }; | |
| captureStackTrace(addr, &stack_trace); | |
| } | |
| // Keep counting even if the end is reached so that the | |
| // user can find out how much more size they need. | |
| t.index += 1; | |
| } | |
| pub fn dump(t: @This()) void { | |
| const tty_config = detectTTYConfig(); | |
| const stderr = io.getStdErr().writer(); | |
| const end = @maximum(t.index, size); | |
| const debug_info = getSelfDebugInfo() catch |err| { | |
| stderr.print( | |
| "Unable to dump stack trace: Unable to open debug info: {s}\n", | |
| .{@errorName(err)}, | |
| ) catch return; | |
| return; | |
| }; | |
| for (t.addrs[0..end]) |frames_array, i| { | |
| stderr.print("{s}:\n", .{t.notes[i]}) catch return; | |
| var frames_array_mutable = frames_array; | |
| const frames = mem.sliceTo(frames_array_mutable[0..], 0); | |
| const stack_trace: std.builtin.StackTrace = .{ | |
| .index = frames.len, | |
| .instruction_addresses = frames, | |
| }; | |
| writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, tty_config) catch continue; | |
| } | |
| } | |
| }; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @@ -2105,7 +2105,18 @@ pub const SrcLoc = struct { | |
| const token_starts = tree.tokens.items(.start); | |
| return token_starts[tok_index]; | |
| }, | |
| - .node_offset, .node_offset_bin_op => |traced_off| { | |
| + .node_offset => |traced_off| { | |
| const node_off = traced_off.x; | |
| const tree = try src_loc.file_scope.getTree(gpa); | |
| const node = src_loc.declRelativeToNodeIndex(node_off); | |
| assert(src_loc.file_scope.tree_loaded); | |
| const main_tokens = tree.nodes.items(.main_token); | |
| + traced_off.trace.dump(); | |
| const tok_index = main_tokens[node]; | |
| const token_starts = tree.tokens.items(.start); | |
| return token_starts[tok_index]; | |
| }, | |
| .node_offset_bin_op => |node_off| { | |
| @@ -2515,6 +2526,17 @@ pub const SrcLoc = struct { | |
| } | |
| }; | |
| +/// This wraps a simple integer in debug builds so that later on we can find out | |
| +/// where in semantic analysis the value got set. | |
| +const TracedOffset = struct { | |
| + x: i32, | |
| + trace: Trace = trace_init, | |
| + | |
| + const want_tracing = builtin.mode == .Debug; | |
| + const trace_init = if (want_tracing) std.debug.Trace(1, 3){} else {}; | |
| + const Trace = @TypeOf(trace_init); | |
| +}; | |
| + | |
| @@ -2555,7 +2577,7 @@ pub const LazySrcLoc = union(enum) { | |
| /// The source location points to an AST node, which is this value offset | |
| /// from its containing Decl node AST index. | |
| /// The Decl is determined contextually. | |
| - node_offset: i32, | |
| + node_offset: TracedOffset, | |
| /// The source location points to two tokens left of the first token of an AST node, | |
| /// which is this value offset from its containing Decl node AST index. | |
| /// The Decl is determined contextually. | |
| @@ -2705,6 +2727,18 @@ pub const LazySrcLoc = union(enum) { | |
| /// The Decl is determined contextually. | |
| node_offset_array_type_elem: i32, | |
| + pub const nodeOffset = if (TracedOffset.want_tracing) nodeOffsetDebug else nodeOffsetRelease; | |
| + | |
| + noinline fn nodeOffsetDebug(node_offset: i32) LazySrcLoc { | |
| + var result: LazySrcLoc = .{ .node_offset = .{ .x = node_offset } }; | |
| + result.node_offset.trace.addAddr(@returnAddress(), "init"); | |
| + return result; | |
| + } | |
| + | |
| + fn nodeOffsetRelease(node_offset: i32) LazySrcLoc { | |
| + return .{ .node_offset = .{ .x = node_offset } }; | |
| + } | |
| + | |
| /// Upgrade to a `SrcLoc` based on the `Decl` provided. | |
| pub fn toSrcLoc(lazy: LazySrcLoc, decl: *Decl) SrcLoc { | |
| return switch (lazy) { | |
| @@ -4014,7 +4048,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | |
| const body = zir.extra[extra.end..][0..extra.data.body_len]; | |
| const result_ref = (try sema.analyzeBodyBreak(&block_scope, body)).?.operand; | |
| try wip_captures.finalize(); | |
| - const src: LazySrcLoc = .{ .node_offset = 0 }; | |
| + const src = LazySrcLoc.nodeOffset(0); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [nix-shell:~/dev/zig/build-release]$ stage2/bin/zig test test3.zig | |
| thread 18654 panic: index out of bounds | |
| /home/andy/dev/zig/src/Module.zig:2115:46: 0x2f76876 in Module.SrcLoc.byteOffset (zig) | |
| const tok_index = main_tokens[node]; | |
| ^ | |
| /home/andy/dev/zig/src/Compilation.zig:451:66: 0x2f705f6 in Compilation.AllErrors.add (zig) | |
| const byte_offset = try module_err_msg.src_loc.byteOffset(module.gpa); | |
| ^ | |
| /home/andy/dev/zig/src/Compilation.zig:2568:38: 0x2dd1aa3 in Compilation.getAllErrorsAlloc (zig) | |
| try AllErrors.add(module, &arena, &errors, entry.value_ptr.*.*); | |
| ^ | |
| /home/andy/dev/zig/src/main.zig:3121:44: 0x2d3bf6a in updateModule (zig) | |
| var errors = try comp.getAllErrorsAlloc(); | |
| ^ | |
| /home/andy/dev/zig/src/main.zig:2808:17: 0x2d04a59 in buildOutputType (zig) | |
| updateModule(gpa, comp, hook) catch |err| switch (err) { | |
| ^ | |
| /home/andy/dev/zig/src/main.zig:225:31: 0x2cea926 in mainArgs (zig) | |
| return buildOutputType(gpa, arena, args, .zig_test); | |
| ^ | |
| /home/andy/dev/zig/src/main.zig:174:20: 0x2ce9974 in main (zig) | |
| return mainArgs(gpa, arena, args); | |
| ^ | |
| /home/andy/dev/zig/lib/std/start.zig:581:37: 0x31d5bf7 in std.start.callMain (zig) | |
| const result = root.main() catch |err| { | |
| ^ | |
| /home/andy/dev/zig/lib/std/start.zig:515:12: 0x2cec3c7 in std.start.callMainWithArgs (zig) | |
| return @call(.{ .modifier = .always_inline }, callMain, .{}); | |
| ^ | |
| /home/andy/dev/zig/lib/std/start.zig:480:12: 0x2cec172 in std.start.main (zig) | |
| return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), c_argv, envp }); | |
| ^ | |
| Aborted (core dumped) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| [nix-shell:~/dev/zig/build-release]$ stage2/bin/zig test test3.zig | |
| init: | |
| /home/andy/dev/zig/src/Zir.zig:2441:45: 0x31b8ba5 in Zir.struct:2432:18.src (zig) | |
| return LazySrcLoc.nodeOffset(self.src_node); | |
| ^ | |
| /home/andy/dev/zig/src/Sema.zig:5030:35: 0x339fde6 in Sema.zirCall (zig) | |
| const call_src = inst_data.src(); | |
| ^ | |
| /home/andy/dev/zig/src/Sema.zig:712:62: 0x322dbe7 in Sema.analyzeBodyInner (zig) | |
| .call => try sema.zirCall(block, inst), | |
| ^ | |
| thread 18654 panic: index out of bounds | |
| /home/andy/dev/zig/src/Module.zig:2115:46: 0x2f76876 in Module.SrcLoc.byteOffset (zig) | |
| const tok_index = main_tokens[node]; | |
| ^ | |
| /home/andy/dev/zig/src/Compilation.zig:451:66: 0x2f705f6 in Compilation.AllErrors.add (zig) | |
| const byte_offset = try module_err_msg.src_loc.byteOffset(module.gpa); | |
| ^ | |
| /home/andy/dev/zig/src/Compilation.zig:2568:38: 0x2dd1aa3 in Compilation.getAllErrorsAlloc (zig) | |
| try AllErrors.add(module, &arena, &errors, entry.value_ptr.*.*); | |
| ^ | |
| /home/andy/dev/zig/src/main.zig:3121:44: 0x2d3bf6a in updateModule (zig) | |
| var errors = try comp.getAllErrorsAlloc(); | |
| ^ | |
| /home/andy/dev/zig/src/main.zig:2808:17: 0x2d04a59 in buildOutputType (zig) | |
| updateModule(gpa, comp, hook) catch |err| switch (err) { | |
| ^ | |
| /home/andy/dev/zig/src/main.zig:225:31: 0x2cea926 in mainArgs (zig) | |
| return buildOutputType(gpa, arena, args, .zig_test); | |
| ^ | |
| /home/andy/dev/zig/src/main.zig:174:20: 0x2ce9974 in main (zig) | |
| return mainArgs(gpa, arena, args); | |
| ^ | |
| /home/andy/dev/zig/lib/std/start.zig:581:37: 0x31d5bf7 in std.start.callMain (zig) | |
| const result = root.main() catch |err| { | |
| ^ | |
| /home/andy/dev/zig/lib/std/start.zig:515:12: 0x2cec3c7 in std.start.callMainWithArgs (zig) | |
| return @call(.{ .modifier = .always_inline }, callMain, .{}); | |
| ^ | |
| /home/andy/dev/zig/lib/std/start.zig:480:12: 0x2cec172 in std.start.main (zig) | |
| return @call(.{ .modifier = .always_inline }, callMainWithArgs, .{ @intCast(usize, c_argc), c_argv, envp }); | |
| ^ | |
| Aborted (core dumped) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment