authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2022-01-21 15:43:25+01:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2022-01-28 14:38:57+01:00
log462d8fd3ac643c48f61dd58a6d42ef60593cce13
treef759203616c9d732b874bddcfa866a6f1eca75a0
parent94dd7639363bd48ba50655ddf1e94d488a0bc75c

spirv: keep track of air & liveness so that it can be used in flush()


2 files changed, 75 insertions(+), 10 deletions(-)

src/codegen/spirv.zig+9-5
...@@ -190,12 +190,12 @@ pub const DeclGen = struct {...@@ -190,12 +190,12 @@ pub const DeclGen = struct {
190 /// The decl we are currently generating code for.190 /// The decl we are currently generating code for.
191 decl: *Decl,191 decl: *Decl,
192192
193 /// If `gen` returned `Error.AnalysisFail`, this contains an explanatory message.193 /// If `gen` returned `Error.CodegenFail`, this contains an explanatory message.
194 /// Memory is owned by `module.gpa`.194 /// Memory is owned by `module.gpa`.
195 error_msg: ?*Module.ErrorMsg,195 error_msg: ?*Module.ErrorMsg,
196196
197 /// Possible errors the `gen` function may return.197 /// Possible errors the `gen` function may return.
198 const Error = error{ AnalysisFail, OutOfMemory };198 const Error = error{ CodegenFail, OutOfMemory };
199199
200 /// This structure is used to return information about a type typically used for200 /// This structure is used to return information about a type typically used for
201 /// arithmetic operations. These types may either be integers, floats, or a vector201 /// arithmetic operations. These types may either be integers, floats, or a vector
...@@ -276,8 +276,12 @@ pub const DeclGen = struct {...@@ -276,8 +276,12 @@ pub const DeclGen = struct {
276 self.decl = decl;276 self.decl = decl;
277 self.error_msg = null;277 self.error_msg = null;
278278
279 try self.genDecl();279 self.genDecl() catch |err| switch (err) {
280 return self.error_msg;280 error.CodegenFail => return self.error_msg,
281 else => |others| return others,
282 };
283
284 return null;
281 }285 }
282286
283 /// Free resources owned by the DeclGen.287 /// Free resources owned by the DeclGen.
...@@ -297,7 +301,7 @@ pub const DeclGen = struct {...@@ -297,7 +301,7 @@ pub const DeclGen = struct {
297 const src: LazySrcLoc = .{ .node_offset = 0 };301 const src: LazySrcLoc = .{ .node_offset = 0 };
298 const src_loc = src.toSrcLoc(self.decl);302 const src_loc = src.toSrcLoc(self.decl);
299 self.error_msg = try Module.ErrorMsg.create(self.spv.module.gpa, src_loc, format, args);303 self.error_msg = try Module.ErrorMsg.create(self.spv.module.gpa, src_loc, format, args);
300 return error.AnalysisFail;304 return error.CodegenFail;
301 }305 }
302306
303 fn resolve(self: *DeclGen, inst: Air.Inst.Ref) !ResultId {307 fn resolve(self: *DeclGen, inst: Air.Inst.Ref) !ResultId {
src/link/SpirV.zig+66-5
...@@ -24,6 +24,7 @@ const SpirV = @This();...@@ -24,6 +24,7 @@ const SpirV = @This();
2424
25const std = @import("std");25const std = @import("std");
26const Allocator = std.mem.Allocator;26const Allocator = std.mem.Allocator;
27const ArenaAllocator = std.heap.ArenaAllocator;
27const assert = std.debug.assert;28const assert = std.debug.assert;
28const log = std.log.scoped(.link);29const log = std.log.scoped(.link);
2930
...@@ -38,6 +39,7 @@ const build_options = @import("build_options");...@@ -38,6 +39,7 @@ const build_options = @import("build_options");
38const spec = @import("../codegen/spirv/spec.zig");39const spec = @import("../codegen/spirv/spec.zig");
39const Air = @import("../Air.zig");40const Air = @import("../Air.zig");
40const Liveness = @import("../Liveness.zig");41const Liveness = @import("../Liveness.zig");
42const Value = @import("../value.zig").Value;
4143
42// TODO: Should this struct be used at all rather than just a hashmap of aux data for every decl?44// TODO: Should this struct be used at all rather than just a hashmap of aux data for every decl?
43pub const FnData = struct {45pub const FnData = struct {
...@@ -55,7 +57,15 @@ decl_table: std.AutoArrayHashMapUnmanaged(*Module.Decl, DeclGenContext) = .{},...@@ -55,7 +57,15 @@ decl_table: std.AutoArrayHashMapUnmanaged(*Module.Decl, DeclGenContext) = .{},
5557
56const DeclGenContext = struct {58const DeclGenContext = struct {
57 air: Air,59 air: Air,
60 air_value_arena: ArenaAllocator.State,
58 liveness: Liveness,61 liveness: Liveness,
62
63 fn deinit(self: *DeclGenContext, gpa: Allocator) void {
64 self.air.deinit(gpa);
65 self.liveness.deinit(gpa);
66 self.air_value_arena.promote(gpa).deinit();
67 self.* = undefined;
68 }
59};69};
6070
61pub fn createEmpty(gpa: Allocator, options: link.Options) !*SpirV {71pub fn createEmpty(gpa: Allocator, options: link.Options) !*SpirV {
...@@ -113,12 +123,27 @@ pub fn updateFunc(self: *SpirV, module: *Module, func: *Module.Fn, air: Air, liv...@@ -113,12 +123,27 @@ pub fn updateFunc(self: *SpirV, module: *Module, func: *Module.Fn, air: Air, liv
113 @panic("Attempted to compile for architecture that was disabled by build configuration");123 @panic("Attempted to compile for architecture that was disabled by build configuration");
114 }124 }
115 _ = module;125 _ = module;
126
116 // Keep track of all decls so we can iterate over them on flush().127 // Keep track of all decls so we can iterate over them on flush().
117 _ = try self.decl_table.getOrPut(self.base.allocator, func.owner_decl);128 const result = try self.decl_table.getOrPut(self.base.allocator, func.owner_decl);
129 if (result.found_existing) {
130 result.value_ptr.deinit(self.base.allocator);
131 }
132
133 var arena = ArenaAllocator.init(self.base.allocator);
134 errdefer arena.deinit();
135
136 var new_air = try cloneAir(air, self.base.allocator, arena.allocator());
137 errdefer new_air.deinit(self.base.allocator);
118138
119 _ = air;139 var new_liveness = try cloneLiveness(liveness, self.base.allocator);
120 _ = liveness;140 errdefer new_liveness.deinit(self.base.allocator);
121 @panic("TODO SPIR-V needs to keep track of Air and Liveness so it can use them later");141
142 result.value_ptr.* = .{
143 .air = new_air,
144 .air_value_arena = arena.state,
145 .liveness = new_liveness,
146 };
122}147}
123148
124pub fn updateDecl(self: *SpirV, module: *Module, decl: *Module.Decl) !void {149pub fn updateDecl(self: *SpirV, module: *Module, decl: *Module.Decl) !void {
...@@ -143,7 +168,11 @@ pub fn updateDeclExports(...@@ -143,7 +168,11 @@ pub fn updateDeclExports(
143}168}
144169
145pub fn freeDecl(self: *SpirV, decl: *Module.Decl) void {170pub fn freeDecl(self: *SpirV, decl: *Module.Decl) void {
146 assert(self.decl_table.swapRemove(decl));171 const index = self.decl_table.getIndex(decl).?;
172 if (decl.val.tag() == .function) {
173 self.decl_table.values()[index].deinit(self.base.allocator);
174 }
175 self.decl_table.swapRemoveAt(index);
147}176}
148177
149pub fn flush(self: *SpirV, comp: *Compilation) !void {178pub fn flush(self: *SpirV, comp: *Compilation) !void {
...@@ -273,3 +302,35 @@ fn writeMemoryModel(binary: *std.ArrayList(Word), target: std.Target) !void {...@@ -273,3 +302,35 @@ fn writeMemoryModel(binary: *std.ArrayList(Word), target: std.Target) !void {
273 @enumToInt(addressing_model), @enumToInt(memory_model),302 @enumToInt(addressing_model), @enumToInt(memory_model),
274 });303 });
275}304}
305
306fn cloneLiveness(l: Liveness, gpa: Allocator) !Liveness {
307 const tomb_bits = try gpa.dupe(usize, l.tomb_bits);
308 errdefer gpa.free(tomb_bits);
309
310 const extra = try gpa.dupe(u32, l.extra);
311 errdefer gpa.free(extra);
312
313 return Liveness{
314 .tomb_bits = tomb_bits,
315 .extra = extra,
316 .special = try l.special.clone(gpa),
317 };
318}
319
320fn cloneAir(air: Air, gpa: Allocator, value_arena: Allocator) !Air {
321 const values = try gpa.alloc(Value, air.values.len);
322 errdefer gpa.free(values);
323
324 for (values) |*value, i| {
325 value.* = try air.values[i].copy(value_arena);
326 }
327
328 var instructions = try air.instructions.toMultiArrayList().clone(gpa);
329 errdefer instructions.deinit(gpa);
330
331 return Air{
332 .instructions = instructions.slice(),
333 .extra = try gpa.dupe(u32, air.extra),
334 .values = values,
335 };
336}