authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-02-01 16:01:43+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-02-01 16:01:43+01:00
loge0f3975fc8a7afd8a613802321fd46e64d8970d5
tree4dabff13e809b7cdc4f460410762e93d372349a0
parent5de2aae63cd75322e58204a6be8df49754e4851a

link: make SpirV atoms fully owned by the linker


4 files changed, 30 insertions(+), 39 deletions(-)

src/Module.zig+3-16
...@@ -5183,20 +5183,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err...@@ -5183,20 +5183,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
5183 decl.zir_decl_index = @intCast(u32, decl_sub_index);5183 decl.zir_decl_index = @intCast(u32, decl_sub_index);
5184 if (decl.getFunction()) |_| {5184 if (decl.getFunction()) |_| {
5185 switch (comp.bin_file.tag) {5185 switch (comp.bin_file.tag) {
5186 .coff => {5186 .coff, .elf, .macho, .plan9 => {
5187 // TODO Implement for COFF
5188 },
5189 .elf => {
5190 // TODO Look into detecting when this would be unnecessary by storing enough state
5191 // in `Decl` to notice that the line number did not change.
5192 comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index });
5193 },
5194 .macho => {
5195 // TODO Look into detecting when this would be unnecessary by storing enough state
5196 // in `Decl` to notice that the line number did not change.
5197 comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index });
5198 },
5199 .plan9 => {
5200 // TODO Look into detecting when this would be unnecessary by storing enough state5187 // TODO Look into detecting when this would be unnecessary by storing enough state
5201 // in `Decl` to notice that the line number did not change.5188 // in `Decl` to notice that the line number did not change.
5202 comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index });5189 comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index });
...@@ -5290,7 +5277,7 @@ pub fn clearDecl(...@@ -5290,7 +5277,7 @@ pub fn clearDecl(
5290 .plan9 => .{ .plan9 = {} },5277 .plan9 => .{ .plan9 = {} },
5291 .c => .{ .c = {} },5278 .c => .{ .c = {} },
5292 .wasm => .{ .wasm = link.File.Wasm.FnData.empty },5279 .wasm => .{ .wasm = link.File.Wasm.FnData.empty },
5293 .spirv => .{ .spirv = .{} },5280 .spirv => .{ .spirv = {} },
5294 .nvptx => .{ .nvptx = {} },5281 .nvptx => .{ .nvptx = {} },
5295 };5282 };
5296 }5283 }
...@@ -5710,7 +5697,7 @@ pub fn allocateNewDecl(...@@ -5710,7 +5697,7 @@ pub fn allocateNewDecl(
5710 .plan9 => .{ .plan9 = {} },5697 .plan9 => .{ .plan9 = {} },
5711 .c => .{ .c = {} },5698 .c => .{ .c = {} },
5712 .wasm => .{ .wasm = link.File.Wasm.FnData.empty },5699 .wasm => .{ .wasm = link.File.Wasm.FnData.empty },
5713 .spirv => .{ .spirv = .{} },5700 .spirv => .{ .spirv = {} },
5714 .nvptx => .{ .nvptx = {} },5701 .nvptx => .{ .nvptx = {} },
5715 },5702 },
5716 .generation = 0,5703 .generation = 0,
src/codegen/spirv.zig+19-11
...@@ -49,7 +49,7 @@ pub const DeclGen = struct {...@@ -49,7 +49,7 @@ pub const DeclGen = struct {
49 spv: *SpvModule,49 spv: *SpvModule,
5050
51 /// The decl we are currently generating code for.51 /// The decl we are currently generating code for.
52 decl: *Decl,52 decl_index: Decl.Index,
5353
54 /// The intermediate code of the declaration we are currently generating. Note: If54 /// The intermediate code of the declaration we are currently generating. Note: If
55 /// the declaration is not a function, this value will be undefined!55 /// the declaration is not a function, this value will be undefined!
...@@ -59,6 +59,8 @@ pub const DeclGen = struct {...@@ -59,6 +59,8 @@ pub const DeclGen = struct {
59 /// Note: If the declaration is not a function, this value will be undefined!59 /// Note: If the declaration is not a function, this value will be undefined!
60 liveness: Liveness,60 liveness: Liveness,
6161
62 ids: *const std.AutoHashMap(Decl.Index, IdResult),
63
62 /// An array of function argument result-ids. Each index corresponds with the64 /// An array of function argument result-ids. Each index corresponds with the
63 /// function argument of the same index.65 /// function argument of the same index.
64 args: std.ArrayListUnmanaged(IdRef) = .{},66 args: std.ArrayListUnmanaged(IdRef) = .{},
...@@ -133,14 +135,20 @@ pub const DeclGen = struct {...@@ -133,14 +135,20 @@ pub const DeclGen = struct {
133135
134 /// Initialize the common resources of a DeclGen. Some fields are left uninitialized,136 /// Initialize the common resources of a DeclGen. Some fields are left uninitialized,
135 /// only set when `gen` is called.137 /// only set when `gen` is called.
136 pub fn init(allocator: Allocator, module: *Module, spv: *SpvModule) DeclGen {138 pub fn init(
139 allocator: Allocator,
140 module: *Module,
141 spv: *SpvModule,
142 ids: *const std.AutoHashMap(Decl.Index, IdResult),
143 ) DeclGen {
137 return .{144 return .{
138 .gpa = allocator,145 .gpa = allocator,
139 .module = module,146 .module = module,
140 .spv = spv,147 .spv = spv,
141 .decl = undefined,148 .decl_index = undefined,
142 .air = undefined,149 .air = undefined,
143 .liveness = undefined,150 .liveness = undefined,
151 .ids = ids,
144 .next_arg_index = undefined,152 .next_arg_index = undefined,
145 .current_block_label_id = undefined,153 .current_block_label_id = undefined,
146 .error_msg = undefined,154 .error_msg = undefined,
...@@ -150,9 +158,9 @@ pub const DeclGen = struct {...@@ -150,9 +158,9 @@ pub const DeclGen = struct {
150 /// Generate the code for `decl`. If a reportable error occurred during code generation,158 /// Generate the code for `decl`. If a reportable error occurred during code generation,
151 /// a message is returned by this function. Callee owns the memory. If this function159 /// a message is returned by this function. Callee owns the memory. If this function
152 /// returns such a reportable error, it is valid to be called again for a different decl.160 /// returns such a reportable error, it is valid to be called again for a different decl.
153 pub fn gen(self: *DeclGen, decl: *Decl, air: Air, liveness: Liveness) !?*Module.ErrorMsg {161 pub fn gen(self: *DeclGen, decl_index: Decl.Index, air: Air, liveness: Liveness) !?*Module.ErrorMsg {
154 // Reset internal resources, we don't want to re-allocate these.162 // Reset internal resources, we don't want to re-allocate these.
155 self.decl = decl;163 self.decl_index = decl_index;
156 self.air = air;164 self.air = air;
157 self.liveness = liveness;165 self.liveness = liveness;
158 self.args.items.len = 0;166 self.args.items.len = 0;
...@@ -194,7 +202,7 @@ pub const DeclGen = struct {...@@ -194,7 +202,7 @@ pub const DeclGen = struct {
194 pub fn fail(self: *DeclGen, comptime format: []const u8, args: anytype) Error {202 pub fn fail(self: *DeclGen, comptime format: []const u8, args: anytype) Error {
195 @setCold(true);203 @setCold(true);
196 const src = LazySrcLoc.nodeOffset(0);204 const src = LazySrcLoc.nodeOffset(0);
197 const src_loc = src.toSrcLoc(self.decl);205 const src_loc = src.toSrcLoc(self.module.declPtr(self.decl_index));
198 assert(self.error_msg == null);206 assert(self.error_msg == null);
199 self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, format, args);207 self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, format, args);
200 return error.CodegenFail;208 return error.CodegenFail;
...@@ -332,7 +340,7 @@ pub const DeclGen = struct {...@@ -332,7 +340,7 @@ pub const DeclGen = struct {
332 };340 };
333 const decl = self.module.declPtr(fn_decl_index);341 const decl = self.module.declPtr(fn_decl_index);
334 self.module.markDeclAlive(decl);342 self.module.markDeclAlive(decl);
335 return decl.fn_link.spirv.id.toRef();343 return self.ids.get(fn_decl_index).?.toRef();
336 }344 }
337345
338 const target = self.getTarget();346 const target = self.getTarget();
...@@ -553,8 +561,8 @@ pub const DeclGen = struct {...@@ -553,8 +561,8 @@ pub const DeclGen = struct {
553 }561 }
554562
555 fn genDecl(self: *DeclGen) !void {563 fn genDecl(self: *DeclGen) !void {
556 const decl = self.decl;564 const result_id = self.ids.get(self.decl_index).?;
557 const result_id = decl.fn_link.spirv.id;565 const decl = self.module.declPtr(self.decl_index);
558566
559 if (decl.val.castTag(.function)) |_| {567 if (decl.val.castTag(.function)) |_| {
560 assert(decl.ty.zigTypeTag() == .Fn);568 assert(decl.ty.zigTypeTag() == .Fn);
...@@ -945,7 +953,7 @@ pub const DeclGen = struct {...@@ -945,7 +953,7 @@ pub const DeclGen = struct {
945953
946 fn airDbgStmt(self: *DeclGen, inst: Air.Inst.Index) !void {954 fn airDbgStmt(self: *DeclGen, inst: Air.Inst.Index) !void {
947 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;955 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
948 const src_fname_id = try self.spv.resolveSourceFileName(self.decl);956 const src_fname_id = try self.spv.resolveSourceFileName(self.module.declPtr(self.decl_index));
949 try self.func.body.emit(self.spv.gpa, .OpLine, .{957 try self.func.body.emit(self.spv.gpa, .OpLine, .{
950 .file = src_fname_id,958 .file = src_fname_id,
951 .line = dbg_stmt.line,959 .line = dbg_stmt.line,
...@@ -1106,7 +1114,7 @@ pub const DeclGen = struct {...@@ -1106,7 +1114,7 @@ pub const DeclGen = struct {
1106 assert(as.errors.items.len != 0);1114 assert(as.errors.items.len != 0);
1107 assert(self.error_msg == null);1115 assert(self.error_msg == null);
1108 const loc = LazySrcLoc.nodeOffset(0);1116 const loc = LazySrcLoc.nodeOffset(0);
1109 const src_loc = loc.toSrcLoc(self.decl);1117 const src_loc = loc.toSrcLoc(self.module.declPtr(self.decl_index));
1110 self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, "failed to assemble SPIR-V inline assembly", .{});1118 self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, "failed to assemble SPIR-V inline assembly", .{});
1111 const notes = try self.module.gpa.alloc(Module.ErrorMsg, as.errors.items.len);1119 const notes = try self.module.gpa.alloc(Module.ErrorMsg, as.errors.items.len);
11121120
src/link.zig+1-1
...@@ -279,7 +279,7 @@ pub const File = struct {...@@ -279,7 +279,7 @@ pub const File = struct {
279 plan9: void,279 plan9: void,
280 c: void,280 c: void,
281 wasm: Wasm.FnData,281 wasm: Wasm.FnData,
282 spirv: SpirV.FnData,282 spirv: void,
283 nvptx: void,283 nvptx: void,
284 };284 };
285285
src/link/SpirV.zig+7-11
...@@ -42,13 +42,6 @@ const SpvModule = @import("../codegen/spirv/Module.zig");...@@ -42,13 +42,6 @@ const SpvModule = @import("../codegen/spirv/Module.zig");
42const spec = @import("../codegen/spirv/spec.zig");42const spec = @import("../codegen/spirv/spec.zig");
43const IdResult = spec.IdResult;43const IdResult = spec.IdResult;
4444
45// TODO: Should this struct be used at all rather than just a hashmap of aux data for every decl?
46pub const FnData = struct {
47 // We're going to fill these in flushModule, and we're going to fill them unconditionally,
48 // so just set it to undefined.
49 id: IdResult = undefined,
50};
51
52base: link.File,45base: link.File,
5346
54/// This linker backend does not try to incrementally link output SPIR-V code.47/// This linker backend does not try to incrementally link output SPIR-V code.
...@@ -209,16 +202,19 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No...@@ -209,16 +202,19 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No
209 // so that we can access them before processing them.202 // so that we can access them before processing them.
210 // TODO: We're allocating an ID unconditionally now, are there203 // TODO: We're allocating an ID unconditionally now, are there
211 // declarations which don't generate a result?204 // declarations which don't generate a result?
212 // TODO: fn_link is used here, but thats probably not the right field. It will work anyway though.205 var ids = std.AutoHashMap(Module.Decl.Index, IdResult).init(self.base.allocator);
206 defer ids.deinit();
207 try ids.ensureTotalCapacity(@intCast(u32, self.decl_table.count()));
208
213 for (self.decl_table.keys()) |decl_index| {209 for (self.decl_table.keys()) |decl_index| {
214 const decl = module.declPtr(decl_index);210 const decl = module.declPtr(decl_index);
215 if (decl.has_tv) {211 if (decl.has_tv) {
216 decl.fn_link.spirv.id = spv.allocId();212 ids.putAssumeCapacityNoClobber(decl_index, spv.allocId());
217 }213 }
218 }214 }
219215
220 // Now, actually generate the code for all declarations.216 // Now, actually generate the code for all declarations.
221 var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &spv);217 var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &spv, &ids);
222 defer decl_gen.deinit();218 defer decl_gen.deinit();
223219
224 var it = self.decl_table.iterator();220 var it = self.decl_table.iterator();
...@@ -231,7 +227,7 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No...@@ -231,7 +227,7 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No
231 const liveness = entry.value_ptr.liveness;227 const liveness = entry.value_ptr.liveness;
232228
233 // Note, if `decl` is not a function, air/liveness may be undefined.229 // Note, if `decl` is not a function, air/liveness may be undefined.
234 if (try decl_gen.gen(decl, air, liveness)) |msg| {230 if (try decl_gen.gen(decl_index, air, liveness)) |msg| {
235 try module.failed_decls.put(module.gpa, decl_index, msg);231 try module.failed_decls.put(module.gpa, decl_index, msg);
236 return; // TODO: Attempt to generate more decls?232 return; // TODO: Attempt to generate more decls?
237 }233 }