Commit a8a2f2b58b

kcbanner <kcbanner@gmail.com>
2023-07-26 05:29:55
Add --verbose-generic-instances to provide visibility on the number of generic function instantiations
1 parent 6cee98e
src/Compilation.zig
@@ -89,6 +89,7 @@ clang_preprocessor_mode: ClangPreprocessorMode,
 verbose_cc: bool,
 verbose_air: bool,
 verbose_intern_pool: bool,
+verbose_generic_instances: bool,
 verbose_llvm_ir: ?[]const u8,
 verbose_llvm_bc: ?[]const u8,
 verbose_cimport: bool,
@@ -596,6 +597,7 @@ pub const InitOptions = struct {
     verbose_link: bool = false,
     verbose_air: bool = false,
     verbose_intern_pool: bool = false,
+    verbose_generic_instances: bool = false,
     verbose_llvm_ir: ?[]const u8 = null,
     verbose_llvm_bc: ?[]const u8 = null,
     verbose_cimport: bool = false,
@@ -1606,6 +1608,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
             .verbose_cc = options.verbose_cc,
             .verbose_air = options.verbose_air,
             .verbose_intern_pool = options.verbose_intern_pool,
+            .verbose_generic_instances = options.verbose_generic_instances,
             .verbose_llvm_ir = options.verbose_llvm_ir,
             .verbose_llvm_bc = options.verbose_llvm_bc,
             .verbose_cimport = options.verbose_cimport,
@@ -2071,6 +2074,14 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
             module.intern_pool.dump();
         }
 
+        if (builtin.mode == .Debug and comp.verbose_generic_instances) {
+            std.debug.print("generic instances for '{s}:0x{x}':\n", .{
+                comp.bin_file.options.root_name,
+                @as(usize, @intFromPtr(module)),
+            });
+            module.intern_pool.dumpGenericInstances(comp.gpa);
+        }
+
         if (comp.bin_file.options.is_test and comp.totalErrorCount() == 0) {
             // The `test_functions` decl has been intentionally postponed until now,
             // at which point we must populate it with the list of test functions that
@@ -5491,6 +5502,7 @@ fn buildOutputFromZig(
         .verbose_link = comp.bin_file.options.verbose_link,
         .verbose_air = comp.verbose_air,
         .verbose_intern_pool = comp.verbose_intern_pool,
+        .verbose_generic_instances = comp.verbose_intern_pool,
         .verbose_llvm_ir = comp.verbose_llvm_ir,
         .verbose_llvm_bc = comp.verbose_llvm_bc,
         .verbose_cimport = comp.verbose_cimport,
@@ -5570,6 +5582,7 @@ pub fn build_crt_file(
         .verbose_link = comp.bin_file.options.verbose_link,
         .verbose_air = comp.verbose_air,
         .verbose_intern_pool = comp.verbose_intern_pool,
+        .verbose_generic_instances = comp.verbose_generic_instances,
         .verbose_llvm_ir = comp.verbose_llvm_ir,
         .verbose_llvm_bc = comp.verbose_llvm_bc,
         .verbose_cimport = comp.verbose_cimport,
src/InternPool.zig
@@ -6266,6 +6266,59 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
     try bw.flush();
 }
 
+pub fn dumpGenericInstances(ip: *const InternPool, allocator: Allocator) void {
+    ip.dumpGenericInstancesFallible(allocator) catch return;
+}
+
+pub fn dumpGenericInstancesFallible(ip: *const InternPool, allocator: Allocator) anyerror!void {
+    var arena_allocator = std.heap.ArenaAllocator.init(allocator);
+    defer arena_allocator.deinit();
+    const arena = arena_allocator.allocator();
+
+    var bw = std.io.bufferedWriter(std.io.getStdErr().writer());
+    const w = bw.writer();
+
+    var instances: std.AutoArrayHashMapUnmanaged(Index, std.ArrayListUnmanaged(Index)) = .{};
+    const datas = ip.items.items(.data);
+    for (ip.items.items(.tag), 0..) |tag, i| {
+        if (tag != .func_instance) continue;
+        const info = ip.extraData(Tag.FuncInstance, datas[i]);
+
+        const gop = try instances.getOrPut(arena, info.generic_owner);
+        if (!gop.found_existing) gop.value_ptr.* = .{};
+
+        try gop.value_ptr.append(arena, @enumFromInt(i));
+    }
+
+    const SortContext = struct {
+        values: []std.ArrayListUnmanaged(Index),
+        pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool {
+            return ctx.values[a_index].items.len > ctx.values[b_index].items.len;
+        }
+    };
+
+    instances.sort(SortContext{ .values = instances.values() });
+    var it = instances.iterator();
+    while (it.next()) |entry| {
+        const generic_fn_owner_decl = ip.declPtrConst(ip.funcDeclOwner(entry.key_ptr.*));
+        try w.print("{} ({}): \n", .{ generic_fn_owner_decl.name.fmt(ip), entry.value_ptr.items.len });
+        for (entry.value_ptr.items) |index| {
+            const func = ip.extraFuncInstance(datas[@intFromEnum(index)]);
+            const owner_decl = ip.declPtrConst(func.owner_decl);
+            try w.print("  {}: (", .{owner_decl.name.fmt(ip)});
+            for (func.comptime_args.get(ip)) |arg| {
+                if (arg != .none) {
+                    const key = ip.indexToKey(arg);
+                    try w.print(" {} ", .{key});
+                }
+            }
+            try w.writeAll(")\n");
+        }
+    }
+
+    try bw.flush();
+}
+
 pub fn structPtr(ip: *InternPool, index: Module.Struct.Index) *Module.Struct {
     return ip.allocated_structs.at(@intFromEnum(index));
 }
@@ -6290,6 +6343,10 @@ pub fn declPtr(ip: *InternPool, index: Module.Decl.Index) *Module.Decl {
     return ip.allocated_decls.at(@intFromEnum(index));
 }
 
+pub fn declPtrConst(ip: *const InternPool, index: Module.Decl.Index) *const Module.Decl {
+    return ip.allocated_decls.at(@intFromEnum(index));
+}
+
 pub fn namespacePtr(ip: *InternPool, index: Module.Namespace.Index) *Module.Namespace {
     return ip.allocated_namespaces.at(@intFromEnum(index));
 }
src/main.zig
@@ -571,6 +571,7 @@ const usage_build_generic =
     \\  --verbose-cc                 Display C compiler invocations
     \\  --verbose-air                Enable compiler debug output for Zig AIR
     \\  --verbose-intern-pool        Enable compiler debug output for InternPool
+    \\  --verbose-generic-instances  Enable compiler debug output for generic instance generation
     \\  --verbose-llvm-ir[=path]     Enable compiler debug output for unoptimized LLVM IR
     \\  --verbose-llvm-bc=[path]     Enable compiler debug output for unoptimized LLVM BC
     \\  --verbose-cimport            Enable compiler debug output for C imports
@@ -741,6 +742,7 @@ fn buildOutputType(
     var verbose_cc = (builtin.os.tag != .wasi or builtin.link_libc) and std.process.hasEnvVarConstant("ZIG_VERBOSE_CC");
     var verbose_air = false;
     var verbose_intern_pool = false;
+    var verbose_generic_instances = false;
     var verbose_llvm_ir: ?[]const u8 = null;
     var verbose_llvm_bc: ?[]const u8 = null;
     var verbose_cimport = false;
@@ -1469,6 +1471,8 @@ fn buildOutputType(
                         verbose_air = true;
                     } else if (mem.eql(u8, arg, "--verbose-intern-pool")) {
                         verbose_intern_pool = true;
+                    } else if (mem.eql(u8, arg, "--verbose-generic-instances")) {
+                        verbose_generic_instances = true;
                     } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) {
                         verbose_llvm_ir = "-";
                     } else if (mem.startsWith(u8, arg, "--verbose-llvm-ir=")) {
@@ -3166,6 +3170,7 @@ fn buildOutputType(
         .verbose_link = verbose_link,
         .verbose_air = verbose_air,
         .verbose_intern_pool = verbose_intern_pool,
+        .verbose_generic_instances = verbose_generic_instances,
         .verbose_llvm_ir = verbose_llvm_ir,
         .verbose_llvm_bc = verbose_llvm_bc,
         .verbose_cimport = verbose_cimport,