authorgravatar for leecannon@leecannon.xyzLee Cannon <leecannon@leecannon.xyz> 2021-10-31 14:12:36+00:00
committergravatar for leecannon@leecannon.xyzLee Cannon <leecannon@leecannon.xyz> 2021-10-31 14:12:36+00:00
log10c9fa0e080763faa1d952f635deb8e4cc1a23e2
tree37cf97be9f369a06ca10bfe60da4bc866f97ecf5
parent969bcb6a59eadb2ef46a9784286728a25d275c24

make tracy.zig more feature complete


2 files changed, 288 insertions(+), 25 deletions(-)

build.zig+2
......@@ -110,6 +110,7 @@ pub fn build(b: *Builder) !void {
110110 return;
111111
112112 const tracy = b.option([]const u8, "tracy", "Enable Tracy integration. Supply path to Tracy source");
113 const tracy_callstack = b.option(bool, "tracy-callstack", "Include callstack information with Tracy data. Does nothing if -Dtracy is not provided") orelse false;
113114 const link_libc = b.option(bool, "force-link-libc", "Force self-hosted compiler to link libc") orelse enable_llvm;
114115 const strip = b.option(bool, "strip", "Omit debug information") orelse false;
115116
......@@ -264,6 +265,7 @@ pub fn build(b: *Builder) !void {
264265 exe_options.addOption(bool, "enable_logging", enable_logging);
265266 exe_options.addOption(bool, "enable_link_snapshots", enable_link_snapshots);
266267 exe_options.addOption(bool, "enable_tracy", tracy != null);
268 exe_options.addOption(bool, "enable_tracy_callstack", tracy_callstack);
267269 exe_options.addOption(bool, "is_stage1", is_stage1);
268270 exe_options.addOption(bool, "omit_stage2", omit_stage2);
269271 if (tracy) |tracy_path| {
src/tracy.zig+286-25
......@@ -2,47 +2,308 @@ const std = @import("std");
22const builtin = @import("builtin");
33
44pub const enable = if (builtin.is_test) false else @import("build_options").enable_tracy;
5const enable_callstack = @import("build_options").enable_tracy_callstack;
56
6extern fn ___tracy_emit_zone_begin_callstack(
7 srcloc: *const ___tracy_source_location_data,
8 depth: c_int,
9 active: c_int,
10) ___tracy_c_zone_context;
11
12extern fn ___tracy_emit_zone_end(ctx: ___tracy_c_zone_context) void;
13
14pub const ___tracy_source_location_data = extern struct {
15 name: ?[*:0]const u8,
16 function: [*:0]const u8,
17 file: [*:0]const u8,
18 line: u32,
19 color: u32,
20};
7// TODO: make this configurable
8const callstack_depth = 10;
219
22pub const ___tracy_c_zone_context = extern struct {
10const ___tracy_c_zone_context = extern struct {
2311 id: u32,
2412 active: c_int,
2513
26 pub fn end(self: ___tracy_c_zone_context) void {
14 pub inline fn end(self: @This()) void {
2715 ___tracy_emit_zone_end(self);
2816 }
17
18 pub inline fn addText(self: @This(), text: []const u8) void {
19 ___tracy_emit_zone_text(self, text.ptr, text.len);
20 }
21
22 pub inline fn setName(self: @This(), name: []const u8) void {
23 ___tracy_emit_zone_name(self, name.ptr, name.len);
24 }
25
26 pub inline fn setColor(self: @This(), color: u32) void {
27 ___tracy_emit_zone_color(self, color);
28 }
29
30 pub inline fn setValue(self: @This(), value: u64) void {
31 ___tracy_emit_zone_value(self, value);
32 }
2933};
3034
3135pub const Ctx = if (enable) ___tracy_c_zone_context else struct {
32 pub fn end(self: Ctx) void {
36 pub inline fn end(self: @This()) void {
37 _ = self;
38 }
39
40 pub inline fn addText(self: @This(), text: []const u8) void {
3341 _ = self;
42 _ = text;
43 }
44
45 pub inline fn setName(self: @This(), name: []const u8) void {
46 _ = self;
47 _ = name;
48 }
49
50 pub inline fn setColor(self: @This(), color: u32) void {
51 _ = self;
52 _ = color;
53 }
54
55 pub inline fn setValue(self: @This(), value: u64) void {
56 _ = self;
57 _ = value;
3458 }
3559};
3660
3761pub inline fn trace(comptime src: std.builtin.SourceLocation) Ctx {
3862 if (!enable) return .{};
3963
40 const loc: ___tracy_source_location_data = .{
41 .name = null,
42 .function = src.fn_name.ptr,
43 .file = src.file.ptr,
44 .line = src.line,
45 .color = 0,
64 if (enable_callstack) {
65 return ___tracy_emit_zone_begin_callstack(&.{
66 .name = null,
67 .function = src.fn_name.ptr,
68 .file = src.file.ptr,
69 .line = src.line,
70 .color = 0,
71 }, callstack_depth, 1);
72 } else {
73 return ___tracy_emit_zone_begin(&.{
74 .name = null,
75 .function = src.fn_name.ptr,
76 .file = src.file.ptr,
77 .line = src.line,
78 .color = 0,
79 }, 1);
80 }
81}
82
83pub inline fn traceNamed(comptime src: std.builtin.SourceLocation, comptime name: [:0]const u8) Ctx {
84 if (!enable) return .{};
85
86 if (enable_callstack) {
87 return ___tracy_emit_zone_begin_callstack(&.{
88 .name = name.ptr,
89 .function = src.fn_name.ptr,
90 .file = src.file.ptr,
91 .line = src.line,
92 .color = 0,
93 }, callstack_depth, 1);
94 } else {
95 return ___tracy_emit_zone_begin(&.{
96 .name = name.ptr,
97 .function = src.fn_name.ptr,
98 .file = src.file.ptr,
99 .line = src.line,
100 .color = 0,
101 }, 1);
102 }
103}
104
105pub fn tracyAllocator(allocator: *std.mem.Allocator) TracyAllocator(null) {
106 return TracyAllocator(null).init(allocator);
107}
108
109pub fn TracyAllocator(comptime name: ?[:0]const u8) type {
110 return struct {
111 allocator: std.mem.Allocator,
112 parent_allocator: *std.mem.Allocator,
113
114 const Self = @This();
115
116 pub fn init(allocator: *std.mem.Allocator) Self {
117 return .{
118 .parent_allocator = allocator,
119 .allocator = .{
120 .allocFn = allocFn,
121 .resizeFn = resizeFn,
122 },
123 };
124 }
125
126 fn allocFn(allocator: *std.mem.Allocator, len: usize, ptr_align: u29, len_align: u29, ret_addr: usize) std.mem.Allocator.Error![]u8 {
127 const self = @fieldParentPtr(Self, "allocator", allocator);
128 const result = self.parent_allocator.allocFn(self.parent_allocator, len, ptr_align, len_align, ret_addr);
129 if (result) |data| {
130 if (data.len != 0) {
131 if (name) |n| {
132 allocNamed(data.ptr, data.len, n);
133 } else {
134 alloc(data.ptr, data.len);
135 }
136 }
137 } else |_| {
138 messageColor("allocation failed", 0xFF0000);
139 }
140 return result;
141 }
142
143 fn resizeFn(allocator: *std.mem.Allocator, buf: []u8, buf_align: u29, new_len: usize, len_align: u29, ret_addr: usize) std.mem.Allocator.Error!usize {
144 const self = @fieldParentPtr(Self, "allocator", allocator);
145
146 if (self.parent_allocator.resizeFn(self.parent_allocator, buf, buf_align, new_len, len_align, ret_addr)) |resized_len| {
147 // this condition is to handle free being called on an empty slice that was never even allocated
148 // example case: `std.process.getSelfExeSharedLibPaths` can return `&[_][:0]u8{}`
149 if (buf.len != 0) {
150 if (name) |n| {
151 freeNamed(buf.ptr, n);
152 } else {
153 free(buf.ptr);
154 }
155 }
156
157 if (resized_len != 0) {
158 // this was a shrink or a resize
159 if (name) |n| {
160 allocNamed(buf.ptr, resized_len, n);
161 } else {
162 alloc(buf.ptr, resized_len);
163 }
164 }
165
166 return resized_len;
167 } else |err| {
168 // this is not really an error condition, during normal operation the compiler hits this case thousands of times
169 // due to this emitting messages for it is both slow and causes clutter
170 // messageColor("allocation resize failed", 0xFF0000);
171 return err;
172 }
173 }
174 };
175}
176
177// This function only accepts comptime known strings, see `messageCopy` for runtime strings
178pub inline fn message(comptime msg: [:0]const u8) void {
179 if (!enable) return;
180 ___tracy_emit_messageL(msg.ptr, if (enable_callstack) callstack_depth else 0);
181}
182
183// This function only accepts comptime known strings, see `messageColorCopy` for runtime strings
184pub inline fn messageColor(comptime msg: [:0]const u8, color: u32) void {
185 if (!enable) return;
186 ___tracy_emit_messageLC(msg.ptr, color, if (enable_callstack) callstack_depth else 0);
187}
188
189pub inline fn messageCopy(msg: []const u8) void {
190 if (!enable) return;
191 ___tracy_emit_message(msg.ptr, msg.len, if (enable_callstack) callstack_depth else 0);
192}
193
194pub inline fn messageColorCopy(msg: [:0]const u8, color: u32) void {
195 if (!enable) return;
196 ___tracy_emit_messageC(msg.ptr, msg.len, color, if (enable_callstack) callstack_depth else 0);
197}
198
199pub inline fn frameMark() void {
200 if (!enable) return;
201 ___tracy_emit_frame_mark(null);
202}
203
204pub inline fn frameMarkNamed(comptime name: [:0]const u8) void {
205 if (!enable) return;
206 ___tracy_emit_frame_mark(name.ptr);
207}
208
209pub inline fn namedFrame(comptime name: [:0]const u8) Frame(name) {
210 frameMarkStart(name);
211 return .{};
212}
213
214pub fn Frame(comptime name: [:0]const u8) type {
215 return struct {
216 pub fn end(_: @This()) void {
217 frameMarkEnd(name);
218 }
46219 };
47 return ___tracy_emit_zone_begin_callstack(&loc, 1, 1);
48220}
221
222inline fn frameMarkStart(comptime name: [:0]const u8) void {
223 if (!enable) return;
224 ___tracy_emit_frame_mark_start(name.ptr);
225}
226
227inline fn frameMarkEnd(comptime name: [:0]const u8) void {
228 if (!enable) return;
229 ___tracy_emit_frame_mark_end(name.ptr);
230}
231
232extern fn ___tracy_emit_frame_mark_start(name: [*:0]const u8) void;
233extern fn ___tracy_emit_frame_mark_end(name: [*:0]const u8) void;
234
235inline fn alloc(ptr: [*]u8, len: usize) void {
236 if (!enable) return;
237
238 if (enable_callstack) {
239 ___tracy_emit_memory_alloc_callstack(ptr, len, callstack_depth, 0);
240 } else {
241 ___tracy_emit_memory_alloc(ptr, len, 0);
242 }
243}
244
245inline fn allocNamed(ptr: [*]u8, len: usize, comptime name: [:0]const u8) void {
246 if (!enable) return;
247
248 if (enable_callstack) {
249 ___tracy_emit_memory_alloc_callstack_named(ptr, len, callstack_depth, 0, name.ptr);
250 } else {
251 ___tracy_emit_memory_alloc_named(ptr, len, 0, name.ptr);
252 }
253}
254
255inline fn free(ptr: [*]u8) void {
256 if (!enable) return;
257
258 if (enable_callstack) {
259 ___tracy_emit_memory_free_callstack(ptr, callstack_depth, 0);
260 } else {
261 ___tracy_emit_memory_free(ptr, 0);
262 }
263}
264
265inline fn freeNamed(ptr: [*]u8, comptime name: [:0]const u8) void {
266 if (!enable) return;
267
268 if (enable_callstack) {
269 ___tracy_emit_memory_free_callstack_named(ptr, callstack_depth, 0, name.ptr);
270 } else {
271 ___tracy_emit_memory_free_named(ptr, 0, name.ptr);
272 }
273}
274
275extern fn ___tracy_emit_zone_begin(
276 srcloc: *const ___tracy_source_location_data,
277 active: c_int,
278) ___tracy_c_zone_context;
279extern fn ___tracy_emit_zone_begin_callstack(
280 srcloc: *const ___tracy_source_location_data,
281 depth: c_int,
282 active: c_int,
283) ___tracy_c_zone_context;
284extern fn ___tracy_emit_zone_text(ctx: ___tracy_c_zone_context, txt: [*]const u8, size: usize) void;
285extern fn ___tracy_emit_zone_name(ctx: ___tracy_c_zone_context, txt: [*]const u8, size: usize) void;
286extern fn ___tracy_emit_zone_color(ctx: ___tracy_c_zone_context, color: u32) void;
287extern fn ___tracy_emit_zone_value(ctx: ___tracy_c_zone_context, value: u64) void;
288extern fn ___tracy_emit_zone_end(ctx: ___tracy_c_zone_context) void;
289extern fn ___tracy_emit_memory_alloc(ptr: *const c_void, size: usize, secure: c_int) void;
290extern fn ___tracy_emit_memory_alloc_callstack(ptr: *const c_void, size: usize, depth: c_int, secure: c_int) void;
291extern fn ___tracy_emit_memory_free(ptr: *const c_void, secure: c_int) void;
292extern fn ___tracy_emit_memory_free_callstack(ptr: *const c_void, depth: c_int, secure: c_int) void;
293extern fn ___tracy_emit_memory_alloc_named(ptr: *const c_void, size: usize, secure: c_int, name: [*:0]const u8) void;
294extern fn ___tracy_emit_memory_alloc_callstack_named(ptr: *const c_void, size: usize, depth: c_int, secure: c_int, name: [*:0]const u8) void;
295extern fn ___tracy_emit_memory_free_named(ptr: *const c_void, secure: c_int, name: [*:0]const u8) void;
296extern fn ___tracy_emit_memory_free_callstack_named(ptr: *const c_void, depth: c_int, secure: c_int, name: [*:0]const u8) void;
297extern fn ___tracy_emit_message(txt: [*]const u8, size: usize, callstack: c_int) void;
298extern fn ___tracy_emit_messageL(txt: [*:0]const u8, callstack: c_int) void;
299extern fn ___tracy_emit_messageC(txt: [*]const u8, size: usize, color: u32, callstack: c_int) void;
300extern fn ___tracy_emit_messageLC(txt: [*:0]const u8, color: u32, callstack: c_int) void;
301extern fn ___tracy_emit_frame_mark(name: ?[*:0]const u8) void;
302
303const ___tracy_source_location_data = extern struct {
304 name: ?[*:0]const u8,
305 function: [*:0]const u8,
306 file: [*:0]const u8,
307 line: u32,
308 color: u32,
309};