Commit 125d3324d9

Robin Voetter <robin@voetter.nl>
2024-04-06 12:40:49
spirv: add link progression
1 parent 3e388fa
src/link/SpirV/deduplicate.zig
@@ -363,7 +363,11 @@ const EntityHashContext = struct {
     }
 };
 
-pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule) !void {
+pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule, progress: *std.Progress.Node) !void {
+    var sub_node = progress.start("deduplicate", 0);
+    sub_node.activate();
+    defer sub_node.end();
+
     var arena = std.heap.ArenaAllocator.init(parser.a);
     defer arena.deinit();
     const a = arena.allocator();
@@ -376,6 +380,7 @@ pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule) !void {
         .info = &info,
         .binary = binary,
     };
+
     for (info.entities.keys()) |id| {
         _ = try ctx.hash(id);
     }
@@ -395,6 +400,8 @@ pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule) !void {
         }
     }
 
+    sub_node.setEstimatedTotalItems(binary.instructions.len);
+
     // Now process the module, and replace instructions where needed.
     var section = Section{};
     var it = binary.iterateInstructions();
@@ -402,6 +409,8 @@ pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule) !void {
     var new_operands = std.ArrayList(u32).init(a);
     var emitted_ptrs = std.AutoHashMap(ResultId, void).init(a);
     while (it.next()) |inst| {
+        defer sub_node.setCompletedItems(inst.offset);
+
         // Result-id can only be the first or second operand
         const inst_spec = parser.getInstSpec(inst.opcode).?;
 
src/link/SpirV/lower_invocation_globals.zig
@@ -682,7 +682,11 @@ const ModuleBuilder = struct {
     }
 };
 
-pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule) !void {
+pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule, progress: *std.Progress.Node) !void {
+    var sub_node = progress.start("Lower invocation globals", 6);
+    sub_node.activate();
+    defer sub_node.end();
+
     var arena = std.heap.ArenaAllocator.init(parser.a);
     defer arena.deinit();
     const a = arena.allocator();
@@ -691,10 +695,16 @@ pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule) !void {
     try info.resolve(a);
 
     var builder = try ModuleBuilder.init(a, binary.*, info);
+    sub_node.completeOne();
     try builder.deriveNewFnInfo(info);
+    sub_node.completeOne();
     try builder.processPreamble(binary.*, info);
+    sub_node.completeOne();
     try builder.emitFunctionTypes(info);
+    sub_node.completeOne();
     try builder.rewriteFunctions(parser, binary.*, info);
+    sub_node.completeOne();
     try builder.emitNewEntryPoints(info);
+    sub_node.completeOne();
     try builder.finalize(parser.a, binary);
 }
src/link/SpirV/prune_unused.zig
@@ -255,7 +255,11 @@ fn removeIdsFromMap(a: Allocator, map: anytype, info: ModuleInfo, alive_marker:
     }
 }
 
-pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule) !void {
+pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule, progress: *std.Progress.Node) !void {
+    var sub_node = progress.start("Prune unused IDs", 0);
+    sub_node.activate();
+    defer sub_node.end();
+
     var arena = std.heap.ArenaAllocator.init(parser.a);
     defer arena.deinit();
     const a = arena.allocator();
@@ -285,9 +289,13 @@ pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule) !void {
 
     var section = Section{};
 
+    sub_node.setEstimatedTotalItems(binary.instructions.len);
+
     var new_functions_section: ?usize = null;
     var it = binary.iterateInstructions();
     skip: while (it.next()) |inst| {
+        defer sub_node.setCompletedItems(inst.offset);
+
         const inst_spec = parser.getInstSpec(inst.opcode).?;
 
         reemit: {
src/link/SpirV.zig
@@ -245,7 +245,7 @@ pub fn flushModule(self: *SpirV, arena: Allocator, prog_node: *std.Progress.Node
     const module = try spv.finalize(arena, target);
     errdefer arena.free(module);
 
-    const linked_module = self.linkModule(arena, module) catch |err| switch (err) {
+    const linked_module = self.linkModule(arena, module, &sub_prog_node) catch |err| switch (err) {
         error.OutOfMemory => return error.OutOfMemory,
         else => |other| {
             log.err("error while linking: {s}\n", .{@errorName(other)});
@@ -256,7 +256,7 @@ pub fn flushModule(self: *SpirV, arena: Allocator, prog_node: *std.Progress.Node
     try self.base.file.?.writeAll(std.mem.sliceAsBytes(linked_module));
 }
 
-fn linkModule(self: *SpirV, a: Allocator, module: []Word) ![]Word {
+fn linkModule(self: *SpirV, a: Allocator, module: []Word, progress: *std.Progress.Node) ![]Word {
     _ = self;
 
     const lower_invocation_globals = @import("SpirV/lower_invocation_globals.zig");
@@ -267,9 +267,9 @@ fn linkModule(self: *SpirV, a: Allocator, module: []Word) ![]Word {
     defer parser.deinit();
     var binary = try parser.parse(module);
 
-    try lower_invocation_globals.run(&parser, &binary);
-    try prune_unused.run(&parser, &binary);
-    try dedup.run(&parser, &binary);
+    try lower_invocation_globals.run(&parser, &binary, progress);
+    try prune_unused.run(&parser, &binary, progress);
+    try dedup.run(&parser, &binary, progress);
 
     return binary.finalize(a);
 }