authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-08 12:55:24-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-09 15:37:16-07:00
logaf909f6c93f06e409e98cb90a9896aa5216f1563
treed52ba626cc23257b4d619abfaa0e1a33869e2c36
parent83f300218f1a35a32d80e92179011db44ac83d05

std.debug.Trace: improve API

Now `std.debug.Trace` is a concrete type with pre-chosen defaults. `std.debug.ConfigurableTrace` can be used for more advanced cases.

2 files changed, 33 insertions(+), 10 deletions(-)

lib/std/debug.zig+31-6
......@@ -1944,19 +1944,42 @@ noinline fn showMyTrace() usize {
19441944 return @returnAddress();
19451945}
19461946
1947pub fn Trace(comptime size: usize, comptime stack_frame_count: usize) type {
1947/// This API helps you track where a value originated and where it was mutated,
1948/// or any other points of interest.
1949/// In debug mode, it adds a small size penalty (104 bytes on 64-bit architectures)
1950/// to the aggregate that you add it to.
1951/// In release mode, it is size 0 and all methods are no-ops.
1952/// This is a pre-made type with default settings.
1953/// For more advanced usage, see `ConfigurableTrace`.
1954pub const Trace = ConfigurableTrace(2, 4, builtin.mode == .Debug);
1955
1956pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize, comptime enabled: bool) type {
19481957 return struct {
1949 addrs: [size][stack_frame_count]usize = undefined,
1950 notes: [size][]const u8 = undefined,
1951 index: usize = 0,
1958 addrs: [actual_size][stack_frame_count]usize = undefined,
1959 notes: [actual_size][]const u8 = undefined,
1960 index: Index = 0,
19521961
1953 const frames_init = [1]usize{0} ** stack_frame_count;
1962 const actual_size = if (enabled) size else 0;
1963 const Index = if (enabled) usize else u0;
19541964
1955 pub noinline fn add(t: *@This(), note: []const u8) void {
1965 pub const enabled = enabled;
1966
1967 pub const add = if (enabled) addNoInline else addNoOp;
1968
1969 pub noinline fn addNoInline(t: *@This(), note: []const u8) void {
1970 comptime assert(enabled);
19561971 return addAddr(t, @returnAddress(), note);
19571972 }
19581973
1974 pub inline fn addNoOp(t: *@This(), note: []const u8) void {
1975 _ = t;
1976 _ = note;
1977 comptime assert(!enabled);
1978 }
1979
19591980 pub fn addAddr(t: *@This(), addr: usize, note: []const u8) void {
1981 if (!enabled) return;
1982
19601983 if (t.index < size) {
19611984 t.notes[t.index] = note;
19621985 t.addrs[t.index] = [1]usize{0} ** stack_frame_count;
......@@ -1972,6 +1995,8 @@ pub fn Trace(comptime size: usize, comptime stack_frame_count: usize) type {
19721995 }
19731996
19741997 pub fn dump(t: @This()) void {
1998 if (!enabled) return;
1999
19752000 const tty_config = detectTTYConfig();
19762001 const stderr = io.getStdErr().writer();
19772002 const end = @maximum(t.index, size);
src/Module.zig+2-4
......@@ -2529,11 +2529,9 @@ pub const SrcLoc = struct {
25292529/// where in semantic analysis the value got set.
25302530const TracedOffset = struct {
25312531 x: i32,
2532 trace: Trace = trace_init,
2532 trace: std.debug.Trace = .{},
25332533
2534 const want_tracing = builtin.mode == .Debug;
2535 const trace_init = if (want_tracing) std.debug.Trace(1, 3){} else {};
2536 const Trace = @TypeOf(trace_init);
2534 const want_tracing = std.debug.Trace.enabled;
25372535};
25382536
25392537/// Resolving a source location into a byte offset may require doing work