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
51835183 decl.zir_decl_index = @intCast(u32, decl_sub_index);
51845184 if (decl.getFunction()) |_| {
51855185 switch (comp.bin_file.tag) {
5186 .coff => {
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 => {
5186 .coff, .elf, .macho, .plan9 => {
52005187 // TODO Look into detecting when this would be unnecessary by storing enough state
52015188 // in `Decl` to notice that the line number did not change.
52025189 comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index });
......@@ -5290,7 +5277,7 @@ pub fn clearDecl(
52905277 .plan9 => .{ .plan9 = {} },
52915278 .c => .{ .c = {} },
52925279 .wasm => .{ .wasm = link.File.Wasm.FnData.empty },
5293 .spirv => .{ .spirv = .{} },
5280 .spirv => .{ .spirv = {} },
52945281 .nvptx => .{ .nvptx = {} },
52955282 };
52965283 }
......@@ -5710,7 +5697,7 @@ pub fn allocateNewDecl(
57105697 .plan9 => .{ .plan9 = {} },
57115698 .c => .{ .c = {} },
57125699 .wasm => .{ .wasm = link.File.Wasm.FnData.empty },
5713 .spirv => .{ .spirv = .{} },
5700 .spirv => .{ .spirv = {} },
57145701 .nvptx => .{ .nvptx = {} },
57155702 },
57165703 .generation = 0,
src/codegen/spirv.zig+19-11
......@@ -49,7 +49,7 @@ pub const DeclGen = struct {
4949 spv: *SpvModule,
5050
5151 /// The decl we are currently generating code for.
52 decl: *Decl,
52 decl_index: Decl.Index,
5353
5454 /// The intermediate code of the declaration we are currently generating. Note: If
5555 /// the declaration is not a function, this value will be undefined!
......@@ -59,6 +59,8 @@ pub const DeclGen = struct {
5959 /// Note: If the declaration is not a function, this value will be undefined!
6060 liveness: Liveness,
6161
62 ids: *const std.AutoHashMap(Decl.Index, IdResult),
63
6264 /// An array of function argument result-ids. Each index corresponds with the
6365 /// function argument of the same index.
6466 args: std.ArrayListUnmanaged(IdRef) = .{},
......@@ -133,14 +135,20 @@ pub const DeclGen = struct {
133135
134136 /// Initialize the common resources of a DeclGen. Some fields are left uninitialized,
135137 /// 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 {
137144 return .{
138145 .gpa = allocator,
139146 .module = module,
140147 .spv = spv,
141 .decl = undefined,
148 .decl_index = undefined,
142149 .air = undefined,
143150 .liveness = undefined,
151 .ids = ids,
144152 .next_arg_index = undefined,
145153 .current_block_label_id = undefined,
146154 .error_msg = undefined,
......@@ -150,9 +158,9 @@ pub const DeclGen = struct {
150158 /// Generate the code for `decl`. If a reportable error occurred during code generation,
151159 /// a message is returned by this function. Callee owns the memory. If this function
152160 /// 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 {
154162 // Reset internal resources, we don't want to re-allocate these.
155 self.decl = decl;
163 self.decl_index = decl_index;
156164 self.air = air;
157165 self.liveness = liveness;
158166 self.args.items.len = 0;
......@@ -194,7 +202,7 @@ pub const DeclGen = struct {
194202 pub fn fail(self: *DeclGen, comptime format: []const u8, args: anytype) Error {
195203 @setCold(true);
196204 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));
198206 assert(self.error_msg == null);
199207 self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, format, args);
200208 return error.CodegenFail;
......@@ -332,7 +340,7 @@ pub const DeclGen = struct {
332340 };
333341 const decl = self.module.declPtr(fn_decl_index);
334342 self.module.markDeclAlive(decl);
335 return decl.fn_link.spirv.id.toRef();
343 return self.ids.get(fn_decl_index).?.toRef();
336344 }
337345
338346 const target = self.getTarget();
......@@ -553,8 +561,8 @@ pub const DeclGen = struct {
553561 }
554562
555563 fn genDecl(self: *DeclGen) !void {
556 const decl = self.decl;
557 const result_id = decl.fn_link.spirv.id;
564 const result_id = self.ids.get(self.decl_index).?;
565 const decl = self.module.declPtr(self.decl_index);
558566
559567 if (decl.val.castTag(.function)) |_| {
560568 assert(decl.ty.zigTypeTag() == .Fn);
......@@ -945,7 +953,7 @@ pub const DeclGen = struct {
945953
946954 fn airDbgStmt(self: *DeclGen, inst: Air.Inst.Index) !void {
947955 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));
949957 try self.func.body.emit(self.spv.gpa, .OpLine, .{
950958 .file = src_fname_id,
951959 .line = dbg_stmt.line,
......@@ -1106,7 +1114,7 @@ pub const DeclGen = struct {
11061114 assert(as.errors.items.len != 0);
11071115 assert(self.error_msg == null);
11081116 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));
11101118 self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, "failed to assemble SPIR-V inline assembly", .{});
11111119 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 {
279279 plan9: void,
280280 c: void,
281281 wasm: Wasm.FnData,
282 spirv: SpirV.FnData,
282 spirv: void,
283283 nvptx: void,
284284 };
285285
src/link/SpirV.zig+7-11
......@@ -42,13 +42,6 @@ const SpvModule = @import("../codegen/spirv/Module.zig");
4242const spec = @import("../codegen/spirv/spec.zig");
4343const 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
5245base: link.File,
5346
5447/// 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
209202 // so that we can access them before processing them.
210203 // TODO: We're allocating an ID unconditionally now, are there
211204 // 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
213209 for (self.decl_table.keys()) |decl_index| {
214210 const decl = module.declPtr(decl_index);
215211 if (decl.has_tv) {
216 decl.fn_link.spirv.id = spv.allocId();
212 ids.putAssumeCapacityNoClobber(decl_index, spv.allocId());
217213 }
218214 }
219215
220216 // 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);
222218 defer decl_gen.deinit();
223219
224220 var it = self.decl_table.iterator();
......@@ -231,7 +227,7 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No
231227 const liveness = entry.value_ptr.liveness;
232228
233229 // 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| {
235231 try module.failed_decls.put(module.gpa, decl_index, msg);
236232 return; // TODO: Attempt to generate more decls?
237233 }