zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit f3ad12b5f1e2d76d157928d9bd4b5926b1bd015f (tree)
parent c5a61e8998742ee0627afd80f35008b5d2703e61
Author: mlugg <mlugg@noreply.codeberg.org>
Date:   Fri, 29 May 2026 14:55:11 +0200

Merge pull request 'Elf2: yet more enhancements' (#35516) from elf2 into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/35516

Diffstat:
Mbuild.zig | 51+++++++++++++++++++++++++--------------------------
Msrc/Air/Liveness.zig | 4++--
Msrc/Compilation.zig | 24++++++++++++++++++------
Msrc/Sema.zig | 287-------------------------------------------------------------------------------
Msrc/Sema/type_resolution.zig | 21+++++++++++++++++++++
Msrc/Zcu.zig | 55++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/Zcu/PerThread.zig | 88+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Msrc/codegen.zig | 7+++++++
Msrc/link.zig | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Msrc/link/Elf2.zig | 66+++++++++++++++++++++++++++++++++++++++++-------------------------
Msrc/main.zig | 6++----
Msrc/tracy.zig | 309++++++++++++++++++++++++++++++++++---------------------------------------------
12 files changed, 424 insertions(+), 580 deletions(-)

diff --git a/build.zig b/build.zig @@ -181,10 +181,10 @@ pub fn build(b: *std.Build) !void { return; const entitlements = b.option([]const u8, "entitlements", "Path to entitlements file for hot-code swapping without sudo on macOS"); - const tracy = b.option([]const u8, "tracy", "Enable Tracy integration. Supply path to Tracy source"); - const tracy_callstack = b.option(bool, "tracy-callstack", "Include callstack information with Tracy data. Does nothing if -Dtracy is not provided") orelse (tracy != null); - const tracy_allocation = b.option(bool, "tracy-allocation", "Include allocation information with Tracy data. Does nothing if -Dtracy is not provided") orelse (tracy != null); - const tracy_callstack_depth: u32 = b.option(u32, "tracy-callstack-depth", "Declare callstack depth for Tracy data. Does nothing if -Dtracy_callstack is not provided") orelse 10; + const tracy = b.option(std.Build.LazyPath, "tracy", "Enable Tracy integration. Supply path to Tracy source"); + const tracy_callstack = b.option(bool, "tracy-callstack", "Include callstack information with Tracy data. Does nothing if -Dtracy is not provided. Has a significant performance impact in some cases. Default: false") orelse false; + const tracy_allocation = b.option(bool, "tracy-allocation", "Include allocation information with Tracy data. Does nothing if -Dtracy is not provided. Default: true") orelse (tracy != null); + const tracy_callstack_depth: u32 = b.option(u32, "tracy-callstack-depth", "Declare callstack depth for Tracy data. Does nothing if -Dtracy-callstack is not provided") orelse 6; const debug_gpa = b.option(bool, "debug-allocator", "Force the compiler to use SafeAllocator") orelse false; const link_libc = b.option(bool, "force-link-libc", "Force self-hosted compiler to link libc") orelse (enable_llvm or only_c); const sanitize_thread = b.option(bool, "sanitize-thread", "Enable thread-sanitization") orelse false; @@ -373,32 +373,31 @@ pub fn build(b: *std.Build) !void { exe_options.addOption(bool, "enable_tracy_allocation", tracy_allocation); exe_options.addOption(u32, "tracy_callstack_depth", tracy_callstack_depth); exe_options.addOption(bool, "value_tracing", value_tracing); - if (tracy) |tracy_path| { - const client_cpp = b.pathJoin( - &[_][]const u8{ tracy_path, "public", "TracyClient.cpp" }, - ); - - const tracy_c_flags: []const []const u8 = &.{ - "-DTRACY_ENABLE=1", - "-fno-sanitize=undefined", - "-DTRACY_FIBERS", - }; - - exe.root_module.addIncludePath(.{ .cwd_relative = tracy_path }); - exe.root_module.addCSourceFile(.{ - .file = .{ .cwd_relative = client_cpp }, - .flags = tracy_c_flags[0..switch (io_mode) { - .threaded => 2, - .evented => 3, - }], + if (tracy) |tracy_dir| { + const tracy_mod = b.createModule(.{ + .target = target, + // Always build Tracy in ReleaseFast so that it doesn't make Debug compiler builds unusable. + .optimize = .ReleaseFast, + .root_source_file = null, + .link_libc = true, + .link_libcpp = true, }); - exe.root_module.link_libc = true; - exe.root_module.link_libcpp = true; + + tracy_mod.addCMacro("TRACY_ENABLE", "1"); + + if (!tracy_callstack) { + tracy_mod.addCMacro("TRACY_NO_CALLSTACK", "1"); + } + + tracy_mod.addIncludePath(tracy_dir); + tracy_mod.addCSourceFile(.{ .file = tracy_dir.path(b, "public/TracyClient.cpp") }); if (target.result.os.tag == .windows) { - exe.root_module.linkSystemLibrary("dbghelp", .{}); - exe.root_module.linkSystemLibrary("ws2_32", .{}); + tracy_mod.linkSystemLibrary("dbghelp", .{}); + tracy_mod.linkSystemLibrary("ws2_32", .{}); } + + exe.root_module.addImport("tracy", tracy_mod); } const test_filters = b.option([]const []const u8, "test-filter", "Skip tests that do not match any filter") orelse &[0][]const u8{}; diff --git a/src/Air/Liveness.zig b/src/Air/Liveness.zig @@ -13,7 +13,7 @@ const Log2Int = std.math.Log2Int; const Writer = std.Io.Writer; const Liveness = @This(); -const trace = @import("../tracy.zig").trace; +const traceNamed = @import("../tracy.zig").traceNamed; const Air = @import("../Air.zig"); const InternPool = @import("../InternPool.zig"); const Zcu = @import("../Zcu.zig"); @@ -140,7 +140,7 @@ fn LivenessPassData(comptime pass: LivenessPass) type { } pub fn analyze(zcu: *Zcu, air: Air, intern_pool: *InternPool) Allocator.Error!Liveness { - const tracy = trace(@src()); + const tracy = traceNamed(@src(), "analyze_liveness"); defer tracy.end(); const gpa = zcu.gpa; diff --git a/src/Compilation.zig b/src/Compilation.zig @@ -2870,8 +2870,8 @@ pub const UpdateError = error{ /// Detect changes to source files, perform semantic analysis, and update the output files. pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateError!void { - const tracy_trace = trace(@src()); - defer tracy_trace.end(); + const tracy_frame = tracy.namedFrame(comp.root_name); + defer tracy_frame.end(); const gpa = comp.gpa; const io = comp.io; @@ -3008,10 +3008,19 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) UpdateE // For compiling C objects, we rely on the cache hash system to avoid duplicating work. // Add a Job for each C object. - try comp.c_object_work_queue.ensureUnusedCapacity(gpa, comp.c_object_table.count()); - for (comp.c_object_table.keys()) |c_object| { - comp.c_object_work_queue.pushBackAssumeCapacity(c_object); - try comp.appendFileSystemInput(try .fromUnresolved(arena, comp.dirs, &.{c_object.src.src_path})); + if (comp.bin_file != null and comp.bin_file.?.post_prelink) { + assert(comp.config.incremental); + // TODO: this indicates that we are using incremental compilation and this is not the first + // incremental update. The incremental linkers do not (currently?) support updating C inputs + // incrementally. The frontend needs to learn to trigger a full rebuild if a C link input + // changes. For now, to avoid crashing the linker in this case, don't kick off C object + // updates if we've done prelink already. https://codeberg.org/ziglang/zig/issues/32081 + } else { + try comp.c_object_work_queue.ensureUnusedCapacity(gpa, comp.c_object_table.count()); + for (comp.c_object_table.keys()) |c_object| { + comp.c_object_work_queue.pushBackAssumeCapacity(c_object); + try comp.appendFileSystemInput(try .fromUnresolved(arena, comp.dirs, &.{c_object.src.src_path})); + } } for (comp.link_inputs) |input| if (input.path()) |path| { @@ -7595,6 +7604,9 @@ pub fn queuePrelinkTaskMode(comp: *Compilation, path: Cache.Path, must_link: boo /// Only valid to call during `update`. pub fn queuePrelinkTasks(comp: *Compilation, tasks: []const link.PrelinkTask) Io.Cancelable!void { + if (tasks.len > 0) { + if (comp.bin_file) |lf| assert(!lf.post_prelink); + } comp.link_prog_node.increaseEstimatedTotalItems(tasks.len); try comp.link_queue.enqueuePrelink(comp, tasks); } diff --git a/src/Sema.zig b/src/Sema.zig @@ -19,7 +19,6 @@ const Type = @import("Type.zig"); const Air = @import("Air.zig"); const Zir = std.zig.Zir; const Zcu = @import("Zcu.zig"); -const trace = @import("tracy.zig").trace; const Namespace = Zcu.Namespace; const CompileError = Zcu.CompileError; const SemaError = Zcu.SemaError; @@ -1127,8 +1126,6 @@ fn analyzeBodyInner( block: *Block, body: []const Zir.Inst.Index, ) CompileError!void { - // No tracy calls here, to avoid interfering with the tail call mechanism. - try sema.inst_map.ensureSpaceForInstructions(sema.gpa, body); const pt = sema.pt; @@ -3002,9 +2999,6 @@ fn zirErrorSetDecl( sema: *Sema, inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; @@ -3032,9 +3026,6 @@ fn zirErrorSetDecl( } fn zirRetPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; @@ -3061,18 +3052,12 @@ fn zirRetPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. } fn zirRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_tok; const operand = sema.resolveInst(inst_data.operand); return sema.analyzeRef(block, block.tokenOffset(inst_data.src_tok), operand, .none); } fn zirEnsureResultUsed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const operand = sema.resolveInst(inst_data.operand); const src = block.nodeOffset(inst_data.src_node); @@ -3114,9 +3099,6 @@ fn ensureResultUsed( } fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; @@ -3139,9 +3121,6 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com } fn zirEnsureErrUnionPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; @@ -3166,9 +3145,6 @@ fn zirEnsureErrUnionPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index } fn zirIndexablePtrLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); const object = sema.resolveInst(inst_data.operand); @@ -3302,9 +3278,6 @@ fn zirAllocExtended( } fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node }); const var_src = block.nodeOffset(inst_data.src_node); @@ -3732,9 +3705,6 @@ fn zirAllocInferredComptime( } fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; @@ -3764,9 +3734,6 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I } fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; @@ -3797,9 +3764,6 @@ fn zirAllocInferred( block: *Block, is_const: bool, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const gpa = sema.gpa; if (block.isComptime()) { @@ -3830,9 +3794,6 @@ fn zirAllocInferred( } fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const gpa = sema.gpa; @@ -4391,9 +4352,6 @@ fn zirValidatePtrStructInit( block: *Block, inst: Zir.Inst.Index, ) CompileError!void { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const validate_inst = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; @@ -4776,9 +4734,6 @@ pub fn addDeclaredHereNote(sema: *Sema, parent: *Zcu.ErrorMsg, decl_ty: Type) !v } fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { - const tracy = trace(@src()); - defer tracy.end(); - const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(pl_node.src_node); const bin = sema.code.extraData(Zir.Inst.Bin, pl_node.payload_index).data; @@ -4870,9 +4825,6 @@ fn zirSetEvalBranchQuota(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi } fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { - const tracy = trace(@src()); - defer tracy.end(); - const zir_tags = sema.code.instructions.items(.tag); const zir_datas = sema.code.instructions.items(.data); const inst_data = zir_datas[@intFromEnum(inst)].pl_node; @@ -4935,8 +4887,6 @@ fn uavRef(sema: *Sema, val: Value) CompileError!Air.Inst.Ref { fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { _ = block; - const tracy = trace(@src()); - defer tracy.end(); const int = sema.code.instructions.items(.data)[@intFromEnum(inst)].int; return sema.pt.intRef(.comptime_int, int); @@ -4944,8 +4894,6 @@ fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins fn zirIntBig(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { _ = block; - const tracy = trace(@src()); - defer tracy.end(); const int = sema.code.instructions.items(.data)[@intFromEnum(inst)].str; const byte_count = int.len * @sizeOf(std.math.big.Limb); @@ -4981,9 +4929,6 @@ fn zirFloat128(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai } fn zirCompileError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); @@ -5111,9 +5056,6 @@ fn zirTrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { } fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; @@ -5202,9 +5144,6 @@ fn zirSuspendBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) Comp } fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pl_node = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = parent_block.nodeOffset(pl_node.src_node); const extra = sema.code.extraData(Zir.Inst.Block, pl_node.payload_index); @@ -5326,9 +5265,6 @@ fn resolveAnalyzedBlock( merges: *Block.Merges, need_debug_scope: bool, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const gpa = sema.gpa; const pt = sema.pt; const zcu = pt.zcu; @@ -5540,9 +5476,6 @@ fn resolveAnalyzedBlock( } fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; @@ -5713,9 +5646,6 @@ fn zirSetRuntimeSafety(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compile } fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError!void { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"break"; const extra = sema.code.extraData(Zir.Inst.Break, inst_data.payload_index).data; const operand = sema.resolveInst(inst_data.operand); @@ -5746,9 +5676,6 @@ fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError } fn zirSwitchContinue(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError!void { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].@"break"; const extra = sema.code.extraData(Zir.Inst.Break, inst_data.payload_index).data; const operand_src = start_block.nodeOffset(extra.operand_src_node.unwrap().?); @@ -6139,9 +6066,6 @@ fn zirCall( inst: Zir.Inst.Index, comptime kind: enum { direct, field }, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; @@ -7376,9 +7300,6 @@ fn zirIntType(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { } fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; @@ -7469,9 +7390,6 @@ fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! } fn zirArrayType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const len_src = block.src(.{ .node_offset_array_type_len = inst_data.src_node }); @@ -7488,9 +7406,6 @@ fn zirArrayType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A } fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; @@ -7534,9 +7449,6 @@ fn validateArrayElemType(sema: *Sema, block: *Block, elem_type: Type, elem_src: } fn zirAnyframeType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; if (true) { return sema.failWithUseOfAsync(block, block.nodeOffset(inst_data.src_node)); @@ -7550,9 +7462,6 @@ fn zirAnyframeType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro } fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; @@ -7613,9 +7522,6 @@ fn zirErrorValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! } fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; @@ -7655,9 +7561,6 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD } fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const io = zcu.comp.io; @@ -7702,9 +7605,6 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD } fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const ip = &zcu.intern_pool; @@ -7759,8 +7659,6 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { _ = block; - const tracy = trace(@src()); - defer tracy.end(); const pt = sema.pt; const zcu = pt.zcu; @@ -7776,9 +7674,6 @@ fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError } fn zirDeclLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index, do_coerce: bool) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; @@ -7960,9 +7855,6 @@ fn zirOptionalPayloadPtr( inst: Zir.Inst.Index, safety_check: bool, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const optional_ptr = sema.resolveInst(inst_data.operand); const src = block.nodeOffset(inst_data.src_node); @@ -8051,9 +7943,6 @@ fn zirOptionalPayload( inst: Zir.Inst.Index, safety_check: bool, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; @@ -8105,9 +7994,6 @@ fn zirErrUnionPayload( block: *Block, inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; @@ -8164,9 +8050,6 @@ fn zirErrUnionPayloadPtr( block: *Block, inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const operand = sema.resolveInst(inst_data.operand); const src = block.nodeOffset(inst_data.src_node); @@ -8256,9 +8139,6 @@ fn analyzeErrUnionPayloadPtr( /// Value in, value out fn zirErrUnionCode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); const operand = sema.resolveInst(inst_data.operand); @@ -8292,9 +8172,6 @@ fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air /// Pointer in, value out fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); const operand = sema.resolveInst(inst_data.operand); @@ -9088,9 +8965,6 @@ fn zirParamAnytype( } fn zirAsNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.As, inst_data.payload_index).data; @@ -9098,9 +8972,6 @@ fn zirAsNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. } fn zirAsShiftOperand(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.As, inst_data.payload_index).data; @@ -9136,9 +9007,6 @@ fn analyzeAs( } fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; @@ -9193,9 +9061,6 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! } fn zirFieldPtrLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; @@ -9218,9 +9083,6 @@ fn zirFieldPtrLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro } fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; @@ -9243,9 +9105,6 @@ fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai } fn zirStructInitFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; @@ -9276,9 +9135,6 @@ fn zirStructInitFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi } fn zirFieldPtrNamedLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const field_name_src = block.builtinCallArgSrc(inst_data.src_node, 1); @@ -9289,9 +9145,6 @@ fn zirFieldPtrNamedLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil } fn zirFieldPtrNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const field_name_src = block.builtinCallArgSrc(inst_data.src_node, 1); @@ -9302,9 +9155,6 @@ fn zirFieldPtrNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr } fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); @@ -9375,9 +9225,6 @@ fn intCast( } fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; @@ -9541,9 +9388,6 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air } fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; @@ -9609,9 +9453,6 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A } fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; @@ -9621,9 +9462,6 @@ fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air } fn zirElemPtrLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const elem_index_src = block.src(.{ .node_offset_array_access_index = inst_data.src_node }); @@ -9643,9 +9481,6 @@ fn zirElemPtrLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError } fn zirElemValImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].elem_val_imm; const array = sema.resolveInst(inst_data.operand); const elem_index = try sema.pt.intRef(.usize, inst_data.idx); @@ -9653,9 +9488,6 @@ fn zirElemValImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! } fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; @@ -9684,9 +9516,6 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air } fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const elem_index_src = block.src(.{ .node_offset_array_access_index = inst_data.src_node }); @@ -9698,9 +9527,6 @@ fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError } fn zirArrayInitElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; @@ -9719,9 +9545,6 @@ fn zirArrayInitElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compile } fn zirSliceStart(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.SliceStart, inst_data.payload_index).data; @@ -9735,9 +9558,6 @@ fn zirSliceStart(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! } fn zirSliceEnd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.SliceEnd, inst_data.payload_index).data; @@ -9752,9 +9572,6 @@ fn zirSliceEnd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai } fn zirSliceSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const sentinel_src = block.src(.{ .node_offset_slice_sentinel = inst_data.src_node }); @@ -9771,9 +9588,6 @@ fn zirSliceSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr } fn zirSliceLength(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.nodeOffset(inst_data.src_node); const extra = sema.code.extraData(Zir.Inst.SliceLength, inst_data.payload_index).data; @@ -9793,9 +9607,6 @@ fn zirSliceLength(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError } fn zirSliceSentinelTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; @@ -9833,9 +9644,6 @@ fn zirSliceSentinelTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE } fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const gpa = sema.gpa; @@ -9999,8 +9807,6 @@ fn zirSwitchBlock( inst: Zir.Inst.Index, operand_is_ref: bool, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); const zir_switch = sema.code.getSwitchBlock(inst); const block_inst: Air.Inst.Index = @enumFromInt(sema.air_instructions.len); @@ -12847,9 +12653,6 @@ fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air } fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_tok; @@ -12898,9 +12701,6 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. } fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; @@ -12935,9 +12735,6 @@ fn zirShl( inst: Zir.Inst.Index, air_tag: Air.Inst.Tag, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; @@ -13125,9 +12922,6 @@ fn zirShr( inst: Zir.Inst.Index, air_tag: Air.Inst.Tag, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; @@ -13255,9 +13049,6 @@ fn zirBitwise( inst: Zir.Inst.Index, air_tag: Air.Inst.Tag, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; @@ -13438,9 +13229,6 @@ fn analyzeTupleCat( } fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; @@ -13933,9 +13721,6 @@ fn zirArithmetic( zir_tag: Zir.Inst.Tag, safety: bool, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const src = block.src(.{ .node_offset_bin_op = inst_data.src_node }); const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); @@ -14663,9 +14448,6 @@ fn zirOverflowArithmetic( extended: Zir.Inst.Extended.InstData, zir_tag: Zir.Inst.Extended, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; const src = block.nodeOffset(extra.node); @@ -15183,9 +14965,6 @@ fn analyzePtrArithmetic( } fn zirLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); const ptr_src = src; // TODO better source location @@ -15199,9 +14978,6 @@ fn zirAsm( extended: Zir.Inst.Extended.InstData, tmpl_is_expr: bool, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; @@ -15393,9 +15169,6 @@ fn zirCmpEq( op: std.math.CompareOperator, air_tag: Air.Inst.Tag, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; @@ -15509,9 +15282,6 @@ fn zirCmp( inst: Zir.Inst.Index, op: std.math.CompareOperator, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const src: LazySrcLoc = block.nodeOffset(inst_data.src_node); @@ -15852,9 +15622,6 @@ fn zirBuiltinSrc( block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; @@ -17181,9 +16948,6 @@ fn zirTypeofPeer( extended: Zir.Inst.Extended.InstData, inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const extra = sema.code.extraData(Zir.Inst.TypeOfPeer, extended.operand); const src = block.nodeOffset(extra.data.src_node); const body = sema.code.bodySlice(extra.data.body_index, extra.data.body_len); @@ -17249,9 +17013,6 @@ fn zirBoolBr( inst: Zir.Inst.Index, is_bool_or: bool, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const gpa = sema.gpa; @@ -17418,9 +17179,6 @@ fn zirIsNonNull( block: *Block, inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); const operand = sema.resolveInst(inst_data.operand); @@ -17433,9 +17191,6 @@ fn zirIsNonNullPtr( block: *Block, inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; @@ -17472,9 +17227,6 @@ fn checkErrorType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { } fn zirIsNonErr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); const operand = sema.resolveInst(inst_data.operand); @@ -17483,9 +17235,6 @@ fn zirIsNonErr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai } fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; @@ -17500,9 +17249,6 @@ fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError } fn zirRetIsNonErr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); const operand = sema.resolveInst(inst_data.operand); @@ -17514,9 +17260,6 @@ fn zirCondbr( parent_block: *Block, inst: Zir.Inst.Index, ) CompileError!void { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; @@ -17866,9 +17609,6 @@ fn zirRetImplicit( block: *Block, inst: Zir.Inst.Index, ) CompileError!void { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_tok; @@ -17913,9 +17653,6 @@ fn zirRetImplicit( } fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const operand = sema.resolveInst(inst_data.operand); const src = block.nodeOffset(inst_data.src_node); @@ -17924,9 +17661,6 @@ fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi } fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); const ret_ptr = sema.resolveInst(inst_data.operand); @@ -18071,9 +17805,6 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, extended: Zir.Inst.Ex /// its state at the point `block` was reached (or, if `block` is `none`, the /// point this function began execution). fn restoreErrRetIndex(sema: *Sema, start_block: *Block, src: LazySrcLoc, target_block: Zir.Inst.Ref, operand_zir: Zir.Inst.Ref) CompileError!void { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; @@ -18229,9 +17960,6 @@ fn floatOpAllowed(tag: Zir.Inst.Tag) bool { } fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; @@ -18361,9 +18089,6 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air } fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const src = block.nodeOffset(inst_data.src_node); const ty_src = block.src(.{ .node_offset_init_ty = inst_data.src_node }); @@ -18382,9 +18107,6 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE } fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_byref: bool) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; @@ -19622,9 +19344,6 @@ fn zirUnaryMath( air_tag: Air.Inst.Tag, comptime eval: fn (Value, Type, Allocator, Zcu.PerThread) Allocator.Error!Value, ) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; const operand = sema.resolveInst(inst_data.operand); const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); @@ -23441,9 +23160,6 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. } fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].pl_node; @@ -24489,9 +24205,6 @@ fn zirResume(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. } fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const tracy = trace(@src()); - defer tracy.end(); - const pt = sema.pt; const zcu = pt.zcu; const comp = zcu.comp; diff --git a/src/Sema/type_resolution.zig b/src/Sema/type_resolution.zig @@ -13,6 +13,7 @@ const LazySrcLoc = Zcu.LazySrcLoc; const InternPool = @import("../InternPool.zig"); const Alignment = InternPool.Alignment; const arith = @import("arith.zig"); +const trace = @import("../tracy.zig").trace; pub const LayoutResolveReason = enum { variable, @@ -174,6 +175,11 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { const gpa = comp.gpa; const ip = &zcu.intern_pool; + const tracy = trace(@src()); + defer tracy.end(); + tracy.addText(struct_ty.containerTypeName(ip).toSlice(ip)); + tracy.addTextFmt("ip_index={d}", .{struct_ty.toIntern()}); + assert(sema.owner.unwrap().type_layout == struct_ty.toIntern()); const struct_obj = ip.loadStructType(struct_ty.toIntern()); @@ -548,6 +554,11 @@ pub fn resolveStructDefaults(sema: *Sema, struct_ty: Type) CompileError!void { const gpa = comp.gpa; const ip = &zcu.intern_pool; + const tracy = trace(@src()); + defer tracy.end(); + tracy.addText(struct_ty.containerTypeName(ip).toSlice(ip)); + tracy.addTextFmt("ip_index={d}", .{struct_ty.toIntern()}); + assert(sema.owner.unwrap().struct_defaults == struct_ty.toIntern()); // We always depend on the layout of `struct_ty`. However, we don't actually need to resolve it @@ -655,6 +666,11 @@ pub fn resolveUnionLayout(sema: *Sema, union_ty: Type) CompileError!void { const gpa = comp.gpa; const ip = &zcu.intern_pool; + const tracy = trace(@src()); + defer tracy.end(); + tracy.addText(union_ty.containerTypeName(ip).toSlice(ip)); + tracy.addTextFmt("ip_index={d}", .{union_ty.toIntern()}); + assert(sema.owner.unwrap().type_layout == union_ty.toIntern()); const union_obj = ip.loadUnionType(union_ty.toIntern()); @@ -1134,6 +1150,11 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void { const gpa = comp.gpa; const ip = &zcu.intern_pool; + const tracy = trace(@src()); + defer tracy.end(); + tracy.addText(enum_ty.containerTypeName(ip).toSlice(ip)); + tracy.addTextFmt("ip_index={d}", .{enum_ty.toIntern()}); + assert(sema.owner.unwrap().type_layout == enum_ty.toIntern()); const enum_obj = ip.loadEnumType(enum_ty.toIntern()); diff --git a/src/Zcu.zig b/src/Zcu.zig @@ -29,7 +29,7 @@ const Package = @import("Package.zig"); const link = @import("link.zig"); const Air = @import("Air.zig"); const Zir = std.zig.Zir; -const trace = @import("tracy.zig").trace; +const tracy = @import("tracy.zig"); const AstGen = std.zig.AstGen; const Sema = @import("Sema.zig"); const target_util = @import("target.zig"); @@ -2811,6 +2811,7 @@ pub const CompileError = error{ pub fn init(zcu: *Zcu, gpa: Allocator, io: Io, thread_count: usize) !void { try zcu.intern_pool.init(gpa, io, thread_count); + zcu.initTracyPlots(); } pub fn deinit(zcu: *Zcu) void { @@ -3161,12 +3162,15 @@ pub fn markDependeeOutdated( try zcu.markTransitiveDependersPotentiallyOutdated(depender); } } + + zcu.updateTracyOutdatedPlots(); } pub fn markPoDependeeUpToDate(zcu: *Zcu, dependee: InternPool.Dependee) !void { if (std.debug.runtime_safety) zcu.outdated_lock.lockUncancelable(zcu.comp.io); defer if (std.debug.runtime_safety) zcu.outdated_lock.unlock(zcu.comp.io); - return markPoDependeeUpToDateInner(zcu, dependee); + try markPoDependeeUpToDateInner(zcu, dependee); + zcu.updateTracyOutdatedPlots(); } /// Assumes that `zcu.outdated_lock` is already held exclusively. fn markPoDependeeUpToDateInner(zcu: *Zcu, dependee: InternPool.Dependee) !void { @@ -3304,6 +3308,7 @@ pub fn findOutdatedToAnalyze(zcu: *Zcu) Allocator.Error!?AnalUnit { // Everything is up-to-date. There could be lingering entries in `zcu.potentially_outdated` // from a dependency loop on a previous update. zcu.potentially_outdated.clearRetainingCapacity(); + zcu.updateTracyOutdatedPlots(); log.debug("findOutdatedToAnalyze: all up-to-date", .{}); return null; } @@ -3337,6 +3342,7 @@ pub fn flushRetryableFailures(zcu: *Zcu) !void { try zcu.markTransitiveDependersPotentiallyOutdated(depender); } zcu.retryable_failures.clearRetainingCapacity(); + zcu.updateTracyOutdatedPlots(); } pub fn mapOldZirToNew( @@ -3580,6 +3586,7 @@ pub fn ensureFuncBodyAnalysisQueued(zcu: *Zcu, func: InternPool.Index) !void { try zcu.outdated_ready.funcs.ensureUnusedCapacity(gpa, 1); zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .func = func }), 0); zcu.outdated_ready.funcs.putAssumeCapacityNoClobber(func, {}); + zcu.updateTracyOutdatedPlots(); } } @@ -3598,6 +3605,7 @@ pub fn ensureNavValAnalysisQueued(zcu: *Zcu, nav: InternPool.Nav.Index) !void { zcu.outdated.putAssumeCapacityNoClobber(.wrap(.{ .nav_ty = nav }), 0); zcu.outdated_ready.other.putAssumeCapacityNoClobber(.wrap(.{ .nav_val = nav }), {}); zcu.outdated_ready.other.putAssumeCapacityNoClobber(.wrap(.{ .nav_ty = nav }), {}); + zcu.updateTracyOutdatedPlots(); } } @@ -3614,6 +3622,7 @@ pub fn queueComptimeUnitAnalysis(zcu: *Zcu, cu: InternPool.ComptimeUnit.Id) Allo try zcu.outdated_ready.other.ensureUnusedCapacity(gpa, 1); zcu.outdated.putAssumeCapacityNoClobber(unit, 0); zcu.outdated_ready.other.putAssumeCapacityNoClobber(unit, {}); + zcu.updateTracyOutdatedPlots(); } /// If `unit` was marked as outdated or porentially outdated, clears that status and returns `true`. @@ -3632,8 +3641,10 @@ pub fn clearOutdatedState(zcu: *Zcu, unit: AnalUnit) bool { } else { assert(!was_ready); } + zcu.updateTracyOutdatedPlots(); return true; } else if (zcu.potentially_outdated.swapRemove(unit)) { + zcu.updateTracyOutdatedPlots(); return true; } else { return false; @@ -4164,6 +4175,9 @@ pub fn resolveReferences(zcu: *Zcu) Allocator.Error!*const std.AutoArrayHashMapU return &zcu.resolved_references.?; } fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.AutoArrayHashMapUnmanaged(AnalUnit, ?ResolvedReference) { + const trace = tracy.trace(@src()); + defer trace.end(); + const gpa = zcu.gpa; const comp = zcu.comp; const ip = &zcu.intern_pool; @@ -5265,6 +5279,7 @@ pub const CodegenTaskPool = struct { mir.deinit(zcu); } assert(pool.available_air_bytes == max_air_bytes_in_flight); + zcu.updateTracyPlot("air_bytes_in_flight", 0); } pub fn start( @@ -5298,6 +5313,12 @@ pub const CodegenTaskPool = struct { } pool.available_air_bytes -= effective_air_bytes; + + zcu.updateTracyPlot("air_bytes_in_flight", @max( + max_air_bytes_in_flight - pool.available_air_bytes, + actual_air_bytes, + )); + break :index pool.free.pop().?; }; @@ -5326,8 +5347,9 @@ pub const CodegenTaskPool = struct { pub fn wait( index: Index, pool: *CodegenTaskPool, - io: Io, + zcu: *const Zcu, ) PerThread.RunCodegenError!struct { InternPool.Index, codegen.AnyMir } { + const io = zcu.comp.io; const func = pool.task_funcs[@intFromEnum(index)]; assert(func != .none); const effective_air_bytes = pool.task_air_bytes[@intFromEnum(index)]; @@ -5343,6 +5365,7 @@ pub const CodegenTaskPool = struct { pool.available_air_bytes += effective_air_bytes; pool.free.appendAssumeCapacity(index); pool.free_cond.signal(io); + zcu.updateTracyPlot("air_bytes_in_flight", max_air_bytes_in_flight - pool.available_air_bytes); } return .{ func, try result }; @@ -5376,3 +5399,29 @@ pub const CodegenTaskPool = struct { return pt.runCodegen(func_index, air); } }; + +fn initTracyPlots(zcu: *const Zcu) void { + if (zcu.comp.skip_linker_dependencies) return; + + tracy.plotConfig("air_bytes_in_flight", .{ .format = .memory, .mode = .step }); + + tracy.plotConfig("outdated + potentially_outdated", .{ .format = .number, .mode = .step, .color = 0xFFFF00 }); + tracy.plotConfig("outdated", .{ .format = .number, .mode = .step, .color = 0xFF0000 }); + tracy.plotConfig("potentially_outdated", .{ .format = .number, .mode = .step, .color = 0xFF7700 }); + tracy.plotConfig("outdated_ready", .{ .format = .number, .mode = .step, .color = 0x00FF00 }); +} + +/// Marked `inline` to prevent binary bloat from trivial generic instances, and to ensure there is +/// minimal overhead to this call when Tracy is disabled, even in Debug builds. +inline fn updateTracyPlot(zcu: *const Zcu, comptime name: [*:0]const u8, val: u64) void { + if (zcu.comp.skip_linker_dependencies) return; + tracy.plotInt(name, @intCast(val)); +} + +/// Assumes that `zcu.outdated_lock` is already held. +fn updateTracyOutdatedPlots(zcu: *const Zcu) void { + zcu.updateTracyPlot("outdated + potentially_outdated", zcu.outdated.count() + zcu.potentially_outdated.count()); + zcu.updateTracyPlot("outdated", zcu.outdated.count()); + zcu.updateTracyPlot("potentially_outdated", zcu.potentially_outdated.count()); + zcu.updateTracyPlot("outdated_ready", zcu.outdated_ready.funcs.count() + zcu.outdated_ready.other.count()); +} diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig @@ -313,18 +313,22 @@ pub fn update( // `comptime` declarations, any declarations marked `export`, and `test` declarations in the // main module if this is a test compilation---become referenced, and so will be picked up // up by the main semantic analysis loop below. - for (zcu.analysisRoots()) |analysis_root_mod| { - const analysis_root_file = zcu.module_roots.get(analysis_root_mod).?.unwrap().?; - try pt.ensureFilePopulated(analysis_root_file); + { + const tracy_trace = traceNamed(@src(), "populate_sema_roots"); + defer tracy_trace.end(); + for (zcu.analysisRoots()) |analysis_root_mod| { + const analysis_root_file = zcu.module_roots.get(analysis_root_mod).?.unwrap().?; + try pt.ensureFilePopulated(analysis_root_file); + } } + const tracy_trace = traceNamed(@src(), "sema_loop"); + defer tracy_trace.end(); + // This is the main semantic analysis loop, which is essentially the main loop of the whole // Zig compilation pipeline. It selects some `AnalUnit` which we know needs to be analyzed, // and analyzes it, which may in turn discover more `AnalUnit`s which we need to analyze. while (try zcu.findOutdatedToAnalyze()) |unit| { - const tracy_trace = traceNamed(@src(), "analyze_outdated"); - defer tracy_trace.end(); - const maybe_err: Zcu.SemaError!void = switch (unit.unwrap()) { .@"comptime" => |cu| pt.ensureComptimeUnitUpToDate(cu), .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav, null), @@ -823,6 +827,9 @@ fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void { const gpa = comp.gpa; const io = comp.io; + const tracy_trace = trace(@src()); + defer tracy_trace.end(); + // We need to visit every updated File for every TrackedInst in InternPool. // This only includes Zig files; ZON files are omitted. var updated_files: std.AutoArrayHashMapUnmanaged(Zcu.File.Index, UpdatedFile) = .empty; @@ -1008,9 +1015,6 @@ fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void { pub fn ensureFilePopulated(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Allocator.Error || Io.Cancelable)!void { dev.check(.sema); - const tracy_trace = trace(@src()); - defer tracy_trace.end(); - const zcu = pt.zcu; const comp = zcu.comp; const io = comp.io; @@ -1019,6 +1023,9 @@ pub fn ensureFilePopulated(pt: Zcu.PerThread, file_index: Zcu.File.Index) (Alloc if (zcu.fileRootType(file_index) != .none) return; // already good + const tracy_trace = traceNamed(@src(), "create_file_struct"); + defer tracy_trace.end(); + if (zcu.comp.time_report) |*tr| tr.stats.n_imported_files += 1; const file = zcu.fileByIndex(file_index); @@ -1065,9 +1072,6 @@ pub fn ensureMemoizedStateUpToDate( /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. reason: ?*const Zcu.DependencyReason, ) Zcu.SemaError!void { - const tracy_trace = trace(@src()); - defer tracy_trace.end(); - const zcu = pt.zcu; const gpa = zcu.gpa; @@ -1142,6 +1146,10 @@ fn analyzeMemoizedState( log.debug("analyzeMemoizedState({t})", .{stage}); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); + tracy_trace.addText(@tagName(stage)); + const unit: AnalUnit = .wrap(.{ .memoized_state = stage }); try zcu.analysis_in_progress.putNoClobber(gpa, unit, reason); @@ -1174,9 +1182,6 @@ fn analyzeMemoizedState( /// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is /// free to ignore this, since the error is already registered. pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.SemaError!void { - const tracy_trace = trace(@src()); - defer tracy_trace.end(); - const zcu = pt.zcu; const gpa = zcu.gpa; @@ -1257,6 +1262,10 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu log.debug("analyzeComptimeUnit {f}", .{zcu.fmtAnalUnit(anal_unit)}); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); + tracy_trace.addTextFmt("cu_id={d}", .{cu_id}); + const inst_resolved = comptime_unit.zir_index.resolveFull(ip) orelse return error.AnalysisFail; const file = zcu.fileByIndex(inst_resolved.file); const zir = file.zir.?; @@ -1333,9 +1342,6 @@ pub fn ensureTypeLayoutUpToDate( /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. reason: ?*const Zcu.DependencyReason, ) Zcu.SemaError!void { - const tracy_trace = trace(@src()); - defer tracy_trace.end(); - const zcu = pt.zcu; const ip = &zcu.intern_pool; const comp = zcu.comp; @@ -1464,9 +1470,6 @@ pub fn ensureStructDefaultsUpToDate( /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. reason: ?*const Zcu.DependencyReason, ) Zcu.SemaError!void { - const tracy_trace = trace(@src()); - defer tracy_trace.end(); - const zcu = pt.zcu; const ip = &zcu.intern_pool; const comp = zcu.comp; @@ -1572,9 +1575,6 @@ pub fn ensureNavValUpToDate( /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. reason: ?*const Zcu.DependencyReason, ) Zcu.SemaError!void { - const tracy_trace = trace(@src()); - defer tracy_trace.end(); - const zcu = pt.zcu; const gpa = zcu.gpa; const ip = &zcu.intern_pool; @@ -1677,6 +1677,11 @@ fn analyzeNavVal( log.debug("analyzeNavVal {f}", .{zcu.fmtAnalUnit(anal_unit)}); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); + tracy_trace.addText(old_nav.fqn.toSlice(ip)); + tracy_trace.addTextFmt("nav_id={d}", .{nav_id}); + const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail; const file = zcu.fileByIndex(inst_resolved.file); const zir = file.zir.?; @@ -1939,9 +1944,6 @@ pub fn ensureNavTypeUpToDate( /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. reason: ?*const Zcu.DependencyReason, ) Zcu.SemaError!void { - const tracy_trace = trace(@src()); - defer tracy_trace.end(); - const zcu = pt.zcu; const gpa = zcu.gpa; const ip = &zcu.intern_pool; @@ -2044,6 +2046,11 @@ fn analyzeNavType( log.debug("analyzeNavType {f}", .{zcu.fmtAnalUnit(anal_unit)}); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); + tracy_trace.addText(old_nav.fqn.toSlice(ip)); + tracy_trace.addTextFmt("nav_id={d}", .{nav_id}); + const inst_resolved = old_nav.analysis.?.zir_index.resolveFull(ip) orelse return error.AnalysisFail; const file = zcu.fileByIndex(inst_resolved.file); const zir = file.zir.?; @@ -2183,9 +2190,6 @@ pub fn ensureFuncBodyUpToDate( ) Zcu.SemaError!void { dev.check(.sema); - const tracy_trace = trace(@src()); - defer tracy_trace.end(); - const zcu = pt.zcu; const gpa = zcu.gpa; const ip = &zcu.intern_pool; @@ -2283,6 +2287,11 @@ fn analyzeFuncBody( log.debug("analyzeFuncBody {f}", .{zcu.fmtAnalUnit(anal_unit)}); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); + tracy_trace.addText(ip.getNav(func.owner_nav).fqn.toSlice(ip)); + tracy_trace.addTextFmt("func_ip_index={d}", .{func_index}); + var air = try pt.analyzeFuncBodyInner(func_index, reason); var air_owned = true; defer if (air_owned) air.deinit(gpa); @@ -2592,6 +2601,9 @@ fn computeAliveFiles(pt: Zcu.PerThread) Allocator.Error!bool { const comp = zcu.comp; const gpa = zcu.gpa; + const tracy_trace = trace(@src()); + defer tracy_trace.end(); + var any_fatal_files = false; zcu.multi_module_err = null; zcu.failed_imports.clearRetainingCapacity(); @@ -3028,14 +3040,16 @@ pub fn scanNamespace( namespace_index: Zcu.Namespace.Index, decls: []const Zir.Inst.Index, ) Allocator.Error!void { - const tracy_trace = trace(@src()); - defer tracy_trace.end(); - const zcu = pt.zcu; const ip = &zcu.intern_pool; const gpa = zcu.gpa; const namespace = zcu.namespacePtr(namespace_index); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); + tracy_trace.addText(Type.fromInterned(namespace.owner_type).containerTypeName(ip).toSlice(ip)); + tracy_trace.addTextFmt("type_ip_index={d}", .{namespace.owner_type}); + const tracked_unit = zcu.trackUnitSema( Type.fromInterned(namespace.owner_type).containerTypeName(ip).toSlice(ip), null, @@ -3247,9 +3261,6 @@ fn analyzeFuncBodyInner( func_index: InternPool.Index, reason: ?*const Zcu.DependencyReason, ) Zcu.SemaError!Air { - const tracy_trace = trace(@src()); - defer tracy_trace.end(); - const zcu = pt.zcu; const comp = zcu.comp; const gpa = comp.gpa; @@ -4556,6 +4567,11 @@ fn runCodegenInner(pt: Zcu.PerThread, func_index: InternPool.Index, air: *Air) e const codegen_prog_node = zcu.codegen_prog_node.start(fqn.toSlice(ip), 0); defer codegen_prog_node.end(); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); + tracy_trace.addText(fqn.toSlice(ip)); + tracy_trace.addTextFmt("func_ip_index={d}", .{func_index}); + if (codegen.legalizeFeatures(pt, nav)) |features| { try air.legalize(pt, features); } diff --git a/src/codegen.zig b/src/codegen.zig @@ -186,6 +186,12 @@ pub fn emitFunction( const zcu = pt.zcu; const func = zcu.funcInfo(func_index); const target = &zcu.navFileScope(func.owner_nav).mod.?.resolved_target.result; + + const tracy_trace = trace(@src()); + defer tracy_trace.end(); + tracy_trace.addText(zcu.intern_pool.getNav(func.owner_nav).fqn.toSlice(&zcu.intern_pool)); + tracy_trace.addTextFmt("func_ip_index={d}", .{func_index}); + switch (target_util.zigBackend(target, zcu.comp.config.use_llvm)) { else => unreachable, inline .stage2_aarch64, @@ -236,6 +242,7 @@ pub fn generateLazySymbol( ) (CodeGenError || std.Io.Writer.Error)!void { const tracy = trace(@src()); defer tracy.end(); + tracy.addTextFmt("{t}, {f}", .{ lazy_sym.kind, Type.fromInterned(lazy_sym.ty).fmt(pt) }); const comp = bin_file.comp; const zcu = pt.zcu; diff --git a/src/link.zig b/src/link.zig @@ -1205,6 +1205,7 @@ pub const File = struct { pub fn loadInput(base: *File, input: Input) anyerror!void { if (base.tag == .lld) return; + assert(!base.post_prelink); switch (base.tag) { inline .elf, .elf2, .wasm => |tag| { dev.check(tag.devFeature()); @@ -1424,6 +1425,8 @@ pub fn doPrelinkTask(comp: *Compilation, task: PrelinkTask) void { return; }; + assert(!base.post_prelink); + var timer = comp.startTimer(); defer if (timer.finish(io)) |ns| { comp.mutex.lockUncancelable(io); @@ -1573,7 +1576,7 @@ pub fn doZcuTask(comp: *Compilation, tid: Zcu.PerThread.Id, task: ZcuTask) void }, .link_func => |codegen_task| nav: { timer.pause(io); - const func, var mir = codegen_task.wait(&zcu.codegen_task_pool, io) catch |err| switch (err) { + const func, var mir = codegen_task.wait(&zcu.codegen_task_pool, zcu) catch |err| switch (err) { error.Canceled, error.AlreadyReported => { comp.link_prog_node.completeOne(); return; @@ -1850,6 +1853,9 @@ pub fn resolveInputs( var ld_script_bytes: std.ArrayList(u8) = .empty; defer ld_script_bytes.deinit(gpa); + var archive_dedup: ArchiveDedupMap = .empty; + defer archive_dedup.deinit(gpa); + var failed_libs: std.ArrayList(struct { name: []const u8, strategy: UnresolvedInput.SearchStrategy, @@ -1889,6 +1895,7 @@ pub fn resolveInputs( resolved_inputs, &checked_paths, &ld_script_bytes, + &archive_dedup, lib_directory, name_query, target, @@ -1916,6 +1923,7 @@ pub fn resolveInputs( resolved_inputs, &checked_paths, &ld_script_bytes, + &archive_dedup, lib_directory, name_query, target, @@ -1944,6 +1952,7 @@ pub fn resolveInputs( resolved_inputs, &checked_paths, &ld_script_bytes, + &archive_dedup, lib_directory, name_query, target, @@ -1963,6 +1972,7 @@ pub fn resolveInputs( resolved_inputs, &checked_paths, &ld_script_bytes, + &archive_dedup, lib_directory, name_query, target, @@ -1994,6 +2004,7 @@ pub fn resolveInputs( unresolved_inputs, resolved_inputs, &ld_script_bytes, + &archive_dedup, target, .{ .path = Path.initCwd(an.name), @@ -2012,6 +2023,7 @@ pub fn resolveInputs( unresolved_inputs, resolved_inputs, &ld_script_bytes, + &archive_dedup, target, .{ .path = .{ @@ -2040,6 +2052,7 @@ pub fn resolveInputs( unresolved_inputs, resolved_inputs, &ld_script_bytes, + &archive_dedup, target, pq, color, @@ -2085,6 +2098,8 @@ fn resolveLibInput( checked_paths: *std.ArrayList(u8), /// Allocated via `gpa`. ld_script_bytes: *std.ArrayList(u8), + /// Allocated via `gpa`. + archive_dedup: *ArchiveDedupMap, lib_directory: Directory, name_query: UnresolvedInput.NameQuery, target: *const std.Target, @@ -2092,6 +2107,7 @@ fn resolveLibInput( color: std.zig.Color, ) Allocator.Error!ResolveLibInputResult { try resolved_inputs.ensureUnusedCapacity(gpa, 1); + try archive_dedup.ensureUnusedCapacity(gpa, 1); const lib_name = name_query.name; @@ -2107,7 +2123,7 @@ fn resolveLibInput( else => |e| fatal("unable to search for tbd library '{f}': {s}", .{ test_path, @errorName(e) }), }; errdefer file.close(io); - return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query); + return finishResolveLibInput(io, resolved_inputs, archive_dedup, test_path, file, link_mode, name_query.query); } { @@ -2122,7 +2138,7 @@ fn resolveLibInput( }), }; try checked_paths.print(gpa, "\n {f}", .{test_path}); - switch (try resolvePathInputLib(gpa, arena, io, unresolved_inputs, resolved_inputs, ld_script_bytes, target, .{ + switch (try resolvePathInputLib(gpa, arena, io, unresolved_inputs, resolved_inputs, ld_script_bytes, archive_dedup, target, .{ .path = test_path, .query = name_query.query, }, link_mode, color)) { @@ -2146,7 +2162,7 @@ fn resolveLibInput( }), }; errdefer file.close(io); - return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query); + return finishResolveLibInput(io, resolved_inputs, archive_dedup, test_path, file, link_mode, name_query.query); } // In the case of MinGW, the main check will be .lib but we also need to @@ -2162,26 +2178,61 @@ fn resolveLibInput( else => |e| fatal("unable to search for static library '{f}': {s}", .{ test_path, @errorName(e) }), }; errdefer file.close(io); - return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, name_query.query); + return finishResolveLibInput(io, resolved_inputs, archive_dedup, test_path, file, link_mode, name_query.query); } return .no_match; } +/// Deduplicates static archive link inputs based on their path. This is done for efficiency, so +/// that linker implementations do not need to open and scan the archive just to determine that they +/// need not extract any objects. At the time of writing, it also helps avoid "multiple definitions +/// of symbol" errors in incomplete linker implementations. +/// +/// Key is index into `resolved_inputs` of an `Input.archive`. +/// +/// Accessed through `ArchiveDedupAdapter`. +/// +const ArchiveDedupMap = std.array_hash_map.Custom(u32, void, void, true); +/// Adapter for accessing `ArchiveDedupMap` with an effective key type of `Path`. +const ArchiveDedupAdapter = struct { + resolved_inputs: []const Input, + pub fn hash(ctx: ArchiveDedupAdapter, path: Path) u32 { + _ = ctx; + return Path.TableAdapter.hash(.{}, path); + } + pub fn eql(ctx: ArchiveDedupAdapter, a_path: Path, b_input_index: u32, _: usize) bool { + const b_path = ctx.resolved_inputs[b_input_index].archive.path; + return a_path.eql(b_path); + } +}; + fn finishResolveLibInput( + io: Io, resolved_inputs: *std.ArrayList(Input), + archive_dedup: *ArchiveDedupMap, path: Path, file: Io.File, link_mode: std.lang.LinkMode, query: UnresolvedInput.Query, ) ResolveLibInputResult { switch (link_mode) { - .static => resolved_inputs.appendAssumeCapacity(.{ .archive = .{ - .path = path, - .file = file, - .must_link = query.must_link, - .hidden = query.hidden, - } }), + .static => { + const ctx: ArchiveDedupAdapter = .{ .resolved_inputs = resolved_inputs.items }; + const gop = archive_dedup.getOrPutAssumeCapacityAdapted(path, ctx); + if (gop.found_existing) { + // Ignore duplicate archive input + file.close(io); + return .ok; + } + gop.key_ptr.* = @intCast(resolved_inputs.items.len); + resolved_inputs.appendAssumeCapacity(.{ .archive = .{ + .path = path, + .file = file, + .must_link = query.must_link, + .hidden = query.hidden, + } }); + }, .dynamic => resolved_inputs.appendAssumeCapacity(.{ .dso = .{ .path = path, .file = file, @@ -2203,13 +2254,15 @@ fn resolvePathInput( resolved_inputs: *std.ArrayList(Input), /// Allocated via `gpa`. ld_script_bytes: *std.ArrayList(u8), + /// Allocated via `gpa`. + archive_dedup: *ArchiveDedupMap, target: *const std.Target, pq: UnresolvedInput.PathQuery, color: std.zig.Color, ) Allocator.Error!?ResolveLibInputResult { switch (Compilation.classifyFileExt(pq.path.sub_path)) { - .static_library => return try resolvePathInputLib(gpa, arena, io, unresolved_inputs, resolved_inputs, ld_script_bytes, target, pq, .static, color), - .shared_library => return try resolvePathInputLib(gpa, arena, io, unresolved_inputs, resolved_inputs, ld_script_bytes, target, pq, .dynamic, color), + .static_library => return try resolvePathInputLib(gpa, arena, io, unresolved_inputs, resolved_inputs, ld_script_bytes, archive_dedup, target, pq, .static, color), + .shared_library => return try resolvePathInputLib(gpa, arena, io, unresolved_inputs, resolved_inputs, ld_script_bytes, archive_dedup, target, pq, .dynamic, color), .object => { var file = pq.path.root_dir.handle.openFile(io, pq.path.sub_path, .{}) catch |err| fatal("failed to open object {f}: {s}", .{ pq.path, @errorName(err) }); @@ -2246,12 +2299,15 @@ fn resolvePathInputLib( resolved_inputs: *std.ArrayList(Input), /// Allocated via `gpa`. ld_script_bytes: *std.ArrayList(u8), + /// Allocated via `gpa`. + archive_dedup: *ArchiveDedupMap, target: *const std.Target, pq: UnresolvedInput.PathQuery, link_mode: std.lang.LinkMode, color: std.zig.Color, ) Allocator.Error!ResolveLibInputResult { try resolved_inputs.ensureUnusedCapacity(gpa, 1); + try archive_dedup.ensureUnusedCapacity(gpa, 1); const test_path: Path = pq.path; // In the case of shared libraries, they might actually be "linker scripts" @@ -2276,7 +2332,7 @@ fn resolvePathInputLib( mem.startsWith(u8, buf, std.elf.ARMAG_THIN)) { // Appears to be an ELF or archive file. - return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query); + return finishResolveLibInput(io, resolved_inputs, archive_dedup, test_path, file, link_mode, pq.query); } const stat = file.stat(io) catch |err| fatal("failed to stat {f}: {t}", .{ test_path, err }); @@ -2346,7 +2402,7 @@ fn resolvePathInputLib( }), }; errdefer file.close(io); - return finishResolveLibInput(resolved_inputs, test_path, file, link_mode, pq.query); + return finishResolveLibInput(io, resolved_inputs, archive_dedup, test_path, file, link_mode, pq.query); } pub fn openObject(io: Io, path: Path, must_link: bool, hidden: bool) !Input.Object { diff --git a/src/link/Elf2.zig b/src/link/Elf2.zig @@ -14,6 +14,7 @@ const InternPool = @import("../InternPool.zig"); const link = @import("../link.zig"); const MappedFile = @import("MappedFile.zig"); const target_util = @import("../target.zig"); +const tracy = @import("../tracy.zig"); const Type = @import("../Type.zig"); const Value = @import("../Value.zig"); const Zcu = @import("../Zcu.zig"); @@ -127,7 +128,7 @@ section_by_name: std.array_hash_map.Auto(String(.shstrtab), void), changed_symtab_index: std.array_hash_map.Auto(String(.strtab), void), /// Counts how many relocations are currently in `.rela.dyn` which would require a `DT_TEXTREL` /// entry in the `.dynamic` section. This allows adding `DT_TEXTREL` to the output `.dynamic` -/// section in `flush` only when it is actually necessary. See also `nodeRequiresTextrel`. +/// section in `flush` only when it is actually necessary. See also `nodeWantsDsoRelocation`. textrel_count: u32, const_prog_node: std.Progress.Node, @@ -1127,8 +1128,10 @@ const SymbolReloc = struct { } if (reloc.rela_index.unwrap()) |rela_index| { reloc.relaSection(elf).relaDeleteOne(elf, rela_index); - if (elf.nodeRequiresTextrel(reloc.node)) { - elf.textrel_count -= 1; + switch (elf.nodeWantsDsoRelocation(reloc.node)) { + .no => unreachable, // there *was* a dynamic relocation! + .yes => {}, + .yes_textrel => elf.textrel_count -= 1, } } if (reloc.type.dependsOnTlsSize()) { @@ -1671,8 +1674,10 @@ fn setGlobalSymbolValue( assert(reloc.target == Symbol.Id.global(global_name)); if (reloc.rela_index.unwrap()) |rela_index| { reloc.relaSection(elf).relaDeleteOne(elf, rela_index); - if (elf.nodeRequiresTextrel(reloc.node)) { - elf.textrel_count -= 1; + switch (elf.nodeWantsDsoRelocation(reloc.node)) { + .no => unreachable, // there *was* a dynamic relocation! + .yes => {}, + .yes_textrel => elf.textrel_count -= 1, } reloc.rela_index = .none; } @@ -1966,17 +1971,6 @@ const Symbol = struct { fn ptr(si: Symbol.Index, elf: *Elf) *Symbol { return &elf.symtab.items[@intFromEnum(si)]; } - - fn applyTargetRelocs(si: Symbol.Index, elf: *Elf) void { - assert(elf.ehdrField(.type) != .REL); - var ri = si.ptr(elf).first_target_reloc; - while (ri != .none) { - const reloc = ri.get(elf); - assert(reloc.target.index(elf) == si); - reloc.apply(elf); - ri = reloc.next; - } - } }; /// A `LocalIndex` is a raw index into the symtab like `Index`, but it guarantees that the @@ -2063,7 +2057,7 @@ const Symbol = struct { // Re-apply relocations targeting this symbol if (elf.ehdrField(.type) != .REL) { - sym_index.applyTargetRelocs(elf); + sym_id.applyTargetRelocs(elf); } // Update GOT entries targeting this symbol @@ -2079,6 +2073,17 @@ const Symbol = struct { } } + fn applyTargetRelocs(sym_id: Symbol.Id, elf: *Elf) void { + assert(elf.ehdrField(.type) != .REL); + var ri = sym_id.index(elf).ptr(elf).first_target_reloc; + while (ri != .none) { + const reloc = ri.get(elf); + assert(reloc.target == sym_id); + reloc.apply(elf); + ri = reloc.next; + } + } + /// Returns `true` if the target of `s` has moved, meaning the symbol's value will change at /// some point due to a call to `flushMoved`. fn hasMoved(s: Symbol.Id, elf: *Elf) bool { @@ -4441,7 +4446,7 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) !void { elf.addPltEntry(name, global_ptr.dynsym_index); // ...and therefore, we need to re-apply that symbol's relocations, as // some might be targeting its PLT entry. - global_ptr.symtab_index.applyTargetRelocs(elf); + Symbol.Id.global(name).applyTargetRelocs(elf); } } } @@ -5107,8 +5112,10 @@ fn addSymbolRelocAssumeCapacity( } else elf.globalByName(name).?.dynsym_index, }; - if (elf.nodeRequiresTextrel(node)) { - elf.textrel_count += 1; + switch (elf.nodeWantsDsoRelocation(node)) { + .no => break :r .none, + .yes => {}, + .yes_textrel => elf.textrel_count += 1, } // It currently looks like we need a runtime relocation for this. @@ -5382,13 +5389,18 @@ fn updateGotEntry(elf: *Elf, got_index: usize) void { }; } -/// Returns whether a `DT_TEXTREL` dynamic entry is needed to have a runtime relocation in `node`. -fn nodeRequiresTextrel(elf: *Elf, node: MappedFile.Node.Index) bool { +/// If `node` cannot contain runtime relocations, returns `.no`. +/// +/// If `node` can contain runtime relocations, `returns `.yes_textrel` if such a relocation requires +/// the presence of a `DT_TEXTREL` dynamic entry, or `.yes` otherwise. +fn nodeWantsDsoRelocation(elf: *Elf, node: MappedFile.Node.Index) enum { yes, yes_textrel, no } { const shndx = elf.getNodeShndx(node); const shf: std.elf.SHF = switch (elf.shdrPtr(shndx)) { inline else => |shdr| elf.targetLoad(&shdr.flags).shf, }; - return shf.ALLOC and !shf.WRITE; + if (!shf.ALLOC) return .no; + if (!shf.WRITE) return .yes_textrel; + return .yes; } pub fn updateNav(elf: *Elf, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) !void { @@ -5668,7 +5680,7 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) !bool { }; break :task; } - if (elf.changed_symtab_index.pop()) |kv| { + while (elf.changed_symtab_index.pop()) |kv| { // We only need to do work in relocatables, because in ELF modules (non-relocatables) // our `ElfN.Rela` entries use `.dynsym` indices rather than `.symtab` indices, and // `.dynsym` indices are (at the time of writing) always immutable. @@ -5865,6 +5877,8 @@ fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) !void { } fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void { + const trace = tracy.trace(@src()); + defer trace.end(); switch (elf.getNode(ni)) { .file => unreachable, .ehdr, .shdr => try elf.flushFileOffset(ni), @@ -6019,6 +6033,8 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) !void { } fn flushResized(elf: *Elf, ni: MappedFile.Node.Index) !void { + const trace = tracy.trace(@src()); + defer trace.end(); _, const size = ni.location(&elf.mf).resolve(&elf.mf); switch (elf.getNode(ni)) { .file => {}, @@ -6152,7 +6168,7 @@ fn flushMovedPltSection(elf: *Elf, which: enum { plt, plt_sec, got_plt }, old_ad // specific tracking for PLT relocations---instead just re-apply all relocations // targeting symbols with PLT entries. for (elf.plt.keys()) |sym| { - sym.index(elf).applyTargetRelocs(elf); + sym.applyTargetRelocs(elf); } // We also need to update all of the references from `.plt.sec` to `.got.plt`. // However, if there's also a flush pending for `.got.plt`, don't bother doing diff --git a/src/main.zig b/src/main.zig @@ -218,8 +218,8 @@ pub fn main(init: std.process.Init.Minimal) anyerror!void { var environ_map = init.environ.createMap(arena) catch |err| fatal("failed to parse environment: {t}", .{err}); if (tracy.enable_allocation) { - var gpa_tracy = tracy.tracyAllocator(gpa); - return mainArgs(gpa_tracy.allocator(), arena, io, args, &environ_map); + var tracy_allocator: tracy.Allocator = .{ .parent_allocator = gpa }; + return mainArgs(tracy_allocator.interface(), arena, io, args, &environ_map); } if (native_os == .wasi) { @@ -4239,7 +4239,6 @@ fn serve( switch (hdr.tag) { .exit => return cleanExit(io), .update => { - tracy.frameMark(); file_system_inputs.clearRetainingCapacity(); if (arg_mode == .translate_c) { @@ -4296,7 +4295,6 @@ fn serve( //); }, .hot_update => { - tracy.frameMark(); file_system_inputs.clearRetainingCapacity(); if (child_pid) |pid| { try comp.hotCodeSwap(main_progress_node, pid); diff --git a/src/tracy.zig b/src/tracy.zig @@ -1,11 +1,13 @@ const std = @import("std"); +const assert = std.debug.assert; + const builtin = @import("builtin"); const build_options = @import("build_options"); pub const enable = if (builtin.is_test) false else build_options.enable_tracy; pub const enable_allocation = enable and build_options.enable_tracy_allocation; pub const enable_callstack = enable and build_options.enable_tracy_callstack; -pub const callstack_depth = if (enable_callstack and build_options.tracy_callstack_depth > 0) build_options.tracy_callstack_depth else 10; +pub const callstack_depth = if (enable_callstack) build_options.tracy_callstack_depth else 0; const ___tracy_c_zone_context = extern struct { id: u32, @@ -19,6 +21,12 @@ const ___tracy_c_zone_context = extern struct { ___tracy_emit_zone_text(self, text.ptr, text.len); } + pub inline fn addTextFmt(self: @This(), comptime fmt: []const u8, args: anytype) void { + var buf: [512]u8 = undefined; + const slice = std.fmt.bufPrint(&buf, fmt, args) catch &buf; + self.addText(slice); + } + pub inline fn setName(self: @This(), name: []const u8) void { ___tracy_emit_zone_name(self, name.ptr, name.len); } @@ -42,6 +50,12 @@ pub const Ctx = if (enable) ___tracy_c_zone_context else struct { _ = text; } + pub inline fn addTextFmt(self: @This(), comptime fmt: []const u8, args: anytype) void { + _ = self; + _ = fmt; + _ = args; + } + pub inline fn setName(self: @This(), name: []const u8) void { _ = self; _ = name; @@ -71,11 +85,7 @@ pub inline fn trace(comptime src: std.lang.SourceLocation) Ctx { }; }; - if (enable_callstack) { - return ___tracy_emit_zone_begin_callstack(&global.loc, callstack_depth, 1); - } else { - return ___tracy_emit_zone_begin(&global.loc, 1); - } + return ___tracy_emit_zone_begin_callstack(&global.loc, callstack_depth, 1); } pub inline fn traceNamed(comptime src: std.lang.SourceLocation, comptime name: [:0]const u8) Ctx { @@ -91,11 +101,7 @@ pub inline fn traceNamed(comptime src: std.lang.SourceLocation, comptime name: [ }; }; - if (enable_callstack) { - return ___tracy_emit_zone_begin_callstack(&global.loc, callstack_depth, 1); - } else { - return ___tracy_emit_zone_begin(&global.loc, 1); - } + return ___tracy_emit_zone_begin_callstack(&global.loc, callstack_depth, 1); } pub inline fn fiberEnter(fiber: [*:0]const u8) void { @@ -108,102 +114,93 @@ pub inline fn fiberLeave() void { ___tracy_fiber_leave(); } -pub fn tracyAllocator(allocator: std.mem.Allocator) TracyAllocator(null) { - return TracyAllocator(null).init(allocator); +pub inline fn plotConfig(comptime name: [*:0]const u8, config: PlotConfig) void { + if (!enable) return; + ___tracy_emit_plot_config( + name, + config.format, + config.mode, + @intFromBool(config.fill), + // https://github.com/wolfpld/tracy/issues/1232 + @byteSwap(config.color), + ); } -pub fn TracyAllocator(comptime name: ?[:0]const u8) type { - return struct { - parent_allocator: std.mem.Allocator, +pub inline fn plotInt(comptime name: [*:0]const u8, val: i64) void { + if (!enable) return; + ___tracy_emit_plot_int(name, val); +} - const Self = @This(); +pub const Allocator = struct { + parent_allocator: std.mem.Allocator, - pub fn init(parent_allocator: std.mem.Allocator) Self { - return .{ - .parent_allocator = parent_allocator, - }; - } + comptime { + assert(enable); // used `tracy.Allocator` with Tracy disabled + } - pub fn allocator(self: *Self) std.mem.Allocator { - return .{ - .ptr = self, - .vtable = &.{ - .alloc = allocFn, - .resize = resizeFn, - .remap = remapFn, - .free = freeFn, - }, - }; - } + pub fn interface(self: *Allocator) std.mem.Allocator { + return .{ + .ptr = self, + .vtable = &.{ + .alloc = allocFn, + .resize = resizeFn, + .remap = remapFn, + .free = freeFn, + }, + }; + } - fn allocFn(ptr: *anyopaque, len: usize, alignment: std.mem.Alignment, ret_addr: usize) ?[*]u8 { - const self: *Self = @ptrCast(@alignCast(ptr)); - const result = self.parent_allocator.rawAlloc(len, alignment, ret_addr); - if (result) |memory| { - if (len != 0) { - if (name) |n| { - allocNamed(memory, len, n); - } else { - alloc(memory, len); - } - } - } else { - messageColor("allocation failed", 0xFF0000); - } - return result; + fn allocFn(ptr: *anyopaque, len: usize, alignment: std.mem.Alignment, ret_addr: usize) ?[*]u8 { + const self: *Allocator = @ptrCast(@alignCast(ptr)); + assert(len > 0); + if (self.parent_allocator.rawAlloc(len, alignment, ret_addr)) |memory| { + ___tracy_emit_memory_alloc_callstack(memory, len, callstack_depth, 0); + return memory; + } else { + messageColor("allocation failed", 0xFF0000); + return null; } + } - fn resizeFn(ptr: *anyopaque, memory: []u8, alignment: std.mem.Alignment, new_len: usize, ret_addr: usize) bool { - const self: *Self = @ptrCast(@alignCast(ptr)); - if (self.parent_allocator.rawResize(memory, alignment, new_len, ret_addr)) { - if (name) |n| { - freeNamed(memory.ptr, n); - allocNamed(memory.ptr, new_len, n); - } else { - free(memory.ptr); - alloc(memory.ptr, new_len); - } - - return true; - } - - // during normal operation the compiler hits this case thousands of times due to this - // emitting messages for it is both slow and causes clutter + fn resizeFn(ptr: *anyopaque, memory: []u8, alignment: std.mem.Alignment, new_len: usize, ret_addr: usize) bool { + const self: *Allocator = @ptrCast(@alignCast(ptr)); + assert(memory.len > 0); + assert(new_len > 0); + // We need to mark the free before calling the implementation to avoid a race. + ___tracy_emit_memory_free_callstack(memory.ptr, callstack_depth, 0); + if (self.parent_allocator.rawResize(memory, alignment, new_len, ret_addr)) { + ___tracy_emit_memory_alloc_callstack(memory.ptr, new_len, callstack_depth, 0); + return true; + } else { + // No `messageColor` call here because this case is hit frequently in normal operation. + ___tracy_emit_memory_alloc_callstack(memory.ptr, memory.len, callstack_depth, 0); return false; } + } - fn remapFn(ptr: *anyopaque, memory: []u8, alignment: std.mem.Alignment, new_len: usize, ret_addr: usize) ?[*]u8 { - const self: *Self = @ptrCast(@alignCast(ptr)); - if (self.parent_allocator.rawRemap(memory, alignment, new_len, ret_addr)) |new_memory| { - if (name) |n| { - freeNamed(memory.ptr, n); - allocNamed(new_memory, new_len, n); - } else { - free(memory.ptr); - alloc(new_memory, new_len); - } - return new_memory; - } else { - messageColor("reallocation failed", 0xFF0000); - return null; - } + fn remapFn(ptr: *anyopaque, memory: []u8, alignment: std.mem.Alignment, new_len: usize, ret_addr: usize) ?[*]u8 { + const self: *Allocator = @ptrCast(@alignCast(ptr)); + assert(memory.len > 0); + assert(new_len > 0); + // We need to mark the free before calling the implementation to avoid a race. + ___tracy_emit_memory_free_callstack(memory.ptr, callstack_depth, 0); + if (self.parent_allocator.rawRemap(memory, alignment, new_len, ret_addr)) |new_memory| { + ___tracy_emit_memory_alloc_callstack(new_memory, new_len, callstack_depth, 0); + return new_memory; + } else { + // No `messageColor` call here because this case is hit frequently in normal operation. + ___tracy_emit_memory_alloc_callstack(memory.ptr, memory.len, callstack_depth, 0); + return null; } + } - fn freeFn(ptr: *anyopaque, memory: []u8, alignment: std.mem.Alignment, ret_addr: usize) void { - const self: *Self = @ptrCast(@alignCast(ptr)); - self.parent_allocator.rawFree(memory, alignment, ret_addr); - // this condition is to handle free being called on an empty slice that was never even allocated - // example case: `std.process.getSelfExeSharedLibPaths` can return `&[_][:0]u8{}` - if (memory.len != 0) { - if (name) |n| { - freeNamed(memory.ptr, n); - } else { - free(memory.ptr); - } - } - } - }; -} + fn freeFn(ptr: *anyopaque, memory: []u8, alignment: std.mem.Alignment, ret_addr: usize) void { + const self: *Allocator = @ptrCast(@alignCast(ptr)); + assert(memory.len > 0); + ___tracy_emit_memory_free_callstack(memory.ptr, callstack_depth, 0); + self.parent_allocator.rawFree(memory, alignment, ret_addr); + } +}; // This function only accepts comptime-known strings, see `messageCopy` for runtime strings pub inline fn message(comptime msg: [:0]const u8) void { @@ -213,7 +210,7 @@ pub inline fn message(comptime msg: [:0]const u8) void { // This function only accepts comptime-known strings, see `messageColorCopy` for runtime strings pub inline fn messageColor(comptime msg: [:0]const u8, color: u24) void { if (!enable) return; - ___tracy_emit_logStringL(.Info, color, if (enable_callstack) callstack_depth else 0, msg.ptr); + ___tracy_emit_logStringL(.Info, color, callstack_depth, msg.ptr); } pub inline fn messageCopy(msg: []const u8) void { @@ -222,84 +219,29 @@ pub inline fn messageCopy(msg: []const u8) void { pub inline fn messageColorCopy(msg: []const u8, color: u24) void { if (!enable) return; - ___tracy_emit_logString(.Info, color, if (enable_callstack) callstack_depth else 0, msg.len, msg.ptr); + ___tracy_emit_logString(.Info, color, callstack_depth, msg.len, msg.ptr); } -pub inline fn frameMark() void { - if (!enable) return; - ___tracy_emit_frame_mark(null); +/// Used to store strings which Tracy requires to have stable pointers for the program's entire +/// lifetime. All such strings will be leaked. +/// +/// The `enable` check ensures that this is not referenced if Tracy is disabled. +var tracy_arena: std.heap.ArenaAllocator = if (enable) .init(std.heap.page_allocator); + +pub inline fn namedFrame(name: []const u8) Frame { + if (!enable) return .{ .name = {} }; + const stable_name = tracy_arena.allocator().dupeSentinel(u8, name, 0) catch @panic("tracy arena OOM"); + ___tracy_emit_frame_mark_start(stable_name.ptr); + return .{ .name = stable_name.ptr }; } -pub inline fn frameMarkNamed(comptime name: [:0]const u8) void { - if (!enable) return; - ___tracy_emit_frame_mark(name.ptr); -} - -pub inline fn namedFrame(comptime name: [:0]const u8) Frame(name) { - frameMarkStart(name); - return .{}; -} - -pub fn Frame(comptime name: [:0]const u8) type { - return struct { - pub fn end(_: @This()) void { - frameMarkEnd(name); - } - }; -} - -inline fn frameMarkStart(comptime name: [:0]const u8) void { - if (!enable) return; - ___tracy_emit_frame_mark_start(name.ptr); -} - -inline fn frameMarkEnd(comptime name: [:0]const u8) void { - if (!enable) return; - ___tracy_emit_frame_mark_end(name.ptr); -} - -extern fn ___tracy_emit_frame_mark_start(name: [*:0]const u8) void; -extern fn ___tracy_emit_frame_mark_end(name: [*:0]const u8) void; - -inline fn alloc(ptr: [*]u8, len: usize) void { - if (!enable) return; - - if (enable_callstack) { - ___tracy_emit_memory_alloc_callstack(ptr, len, callstack_depth, 0); - } else { - ___tracy_emit_memory_alloc(ptr, len, 0); - } -} - -inline fn allocNamed(ptr: [*]u8, len: usize, comptime name: [:0]const u8) void { - if (!enable) return; - - if (enable_callstack) { - ___tracy_emit_memory_alloc_callstack_named(ptr, len, callstack_depth, 0, name.ptr); - } else { - ___tracy_emit_memory_alloc_named(ptr, len, 0, name.ptr); - } -} - -inline fn free(ptr: [*]u8) void { - if (!enable) return; - - if (enable_callstack) { - ___tracy_emit_memory_free_callstack(ptr, callstack_depth, 0); - } else { - ___tracy_emit_memory_free(ptr, 0); +pub const Frame = struct { + name: if (enable) [*:0]const u8 else void, + pub inline fn end(frame: Frame) void { + if (!enable) return; + ___tracy_emit_frame_mark_end(frame.name); } -} - -inline fn freeNamed(ptr: [*]u8, comptime name: [:0]const u8) void { - if (!enable) return; - - if (enable_callstack) { - ___tracy_emit_memory_free_callstack_named(ptr, callstack_depth, 0, name.ptr); - } else { - ___tracy_emit_memory_free_named(ptr, 0, name.ptr); - } -} +}; pub const MessageSeverity = enum(i8) { Trace, // Broadly track variable states and events in the software program. @@ -310,24 +252,39 @@ pub const MessageSeverity = enum(i8) { Fatal, // Describes a critical event that will lead to a software failure/crash. }; -extern fn ___tracy_emit_zone_begin(srcloc: *const ___tracy_source_location_data, active: i32) ___tracy_c_zone_context; +pub const PlotConfig = struct { + format: Format, + mode: Mode, + fill: bool = true, + color: u24 = 0, + + pub const Format = enum(i32) { + number = 0, + memory = 1, + percentage = 2, + watt = 3, + }; + + pub const Mode = enum(i32) { + line = 0, + step = 1, + }; +}; + +extern fn ___tracy_emit_frame_mark_start(name: [*:0]const u8) void; +extern fn ___tracy_emit_frame_mark_end(name: [*:0]const u8) void; extern fn ___tracy_emit_zone_begin_callstack(srcloc: *const ___tracy_source_location_data, depth: i32, active: i32) ___tracy_c_zone_context; extern fn ___tracy_emit_zone_text(ctx: ___tracy_c_zone_context, txt: [*]const u8, size: usize) void; extern fn ___tracy_emit_zone_name(ctx: ___tracy_c_zone_context, txt: [*]const u8, size: usize) void; extern fn ___tracy_emit_zone_color(ctx: ___tracy_c_zone_context, color: u32) void; extern fn ___tracy_emit_zone_value(ctx: ___tracy_c_zone_context, value: u64) void; extern fn ___tracy_emit_zone_end(ctx: ___tracy_c_zone_context) void; -extern fn ___tracy_emit_memory_alloc(ptr: *const anyopaque, size: usize, secure: i32) void; extern fn ___tracy_emit_memory_alloc_callstack(ptr: *const anyopaque, size: usize, depth: i32, secure: i32) void; -extern fn ___tracy_emit_memory_free(ptr: *const anyopaque, secure: i32) void; extern fn ___tracy_emit_memory_free_callstack(ptr: *const anyopaque, depth: i32, secure: i32) void; -extern fn ___tracy_emit_memory_alloc_named(ptr: *const anyopaque, size: usize, secure: i32, name: [*:0]const u8) void; -extern fn ___tracy_emit_memory_alloc_callstack_named(ptr: *const anyopaque, size: usize, depth: i32, secure: i32, name: [*:0]const u8) void; -extern fn ___tracy_emit_memory_free_named(ptr: *const anyopaque, secure: i32, name: [*:0]const u8) void; -extern fn ___tracy_emit_memory_free_callstack_named(ptr: *const anyopaque, depth: i32, secure: i32, name: [*:0]const u8) void; extern fn ___tracy_emit_logString(severity: MessageSeverity, color: i32, callstack_depth: i32, size: usize, txt: [*]const u8) void; extern fn ___tracy_emit_logStringL(severity: MessageSeverity, color: i32, callstack_depth: i32, txt: [*:0]const u8) void; -extern fn ___tracy_emit_frame_mark(name: ?[*:0]const u8) void; +extern fn ___tracy_emit_plot_int(name: [*:0]const u8, val: i64) void; +extern fn ___tracy_emit_plot_config(name: [*:0]const u8, format: PlotConfig.Format, mode: PlotConfig.Mode, fill: i32, color: u32) void; extern fn ___tracy_fiber_enter(fiber: [*:0]const u8) void; extern fn ___tracy_fiber_leave() void;