| ... | ... | @@ -24,6 +24,7 @@ const SpirV = @This(); |
| 24 | 24 | |
| 25 | 25 | const std = @import("std"); |
| 26 | 26 | const Allocator = std.mem.Allocator; |
| 27 | const ArenaAllocator = std.heap.ArenaAllocator; |
| 27 | 28 | const assert = std.debug.assert; |
| 28 | 29 | const log = std.log.scoped(.link); |
| 29 | 30 | |
| ... | ... | @@ -38,6 +39,7 @@ const build_options = @import("build_options"); |
| 38 | 39 | const spec = @import("../codegen/spirv/spec.zig"); |
| 39 | 40 | const Air = @import("../Air.zig"); |
| 40 | 41 | const Liveness = @import("../Liveness.zig"); |
| 42 | const Value = @import("../value.zig").Value; |
| 41 | 43 | |
| 42 | 44 | // TODO: Should this struct be used at all rather than just a hashmap of aux data for every decl? |
| 43 | 45 | pub const FnData = struct { |
| ... | ... | @@ -55,7 +57,15 @@ decl_table: std.AutoArrayHashMapUnmanaged(*Module.Decl, DeclGenContext) = .{}, |
| 55 | 57 | |
| 56 | 58 | const DeclGenContext = struct { |
| 57 | 59 | air: Air, |
| 60 | air_value_arena: ArenaAllocator.State, |
| 58 | 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 | }; |
| 60 | 70 | |
| 61 | 71 | pub 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 | 123 | @panic("Attempted to compile for architecture that was disabled by build configuration"); |
| 114 | 124 | } |
| 115 | 125 | _ = module; |
| 126 | |
| 116 | 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); |
| 118 | 138 | |
| 119 | | _ = air; |
| 120 | | _ = liveness; |
| 121 | | @panic("TODO SPIR-V needs to keep track of Air and Liveness so it can use them later"); |
| 139 | var new_liveness = try cloneLiveness(liveness, self.base.allocator); |
| 140 | errdefer new_liveness.deinit(self.base.allocator); |
| 141 | |
| 142 | result.value_ptr.* = .{ |
| 143 | .air = new_air, |
| 144 | .air_value_arena = arena.state, |
| 145 | .liveness = new_liveness, |
| 146 | }; |
| 122 | 147 | } |
| 123 | 148 | |
| 124 | 149 | pub fn updateDecl(self: *SpirV, module: *Module, decl: *Module.Decl) !void { |
| ... | ... | @@ -143,7 +168,11 @@ pub fn updateDeclExports( |
| 143 | 168 | } |
| 144 | 169 | |
| 145 | 170 | pub 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 | } |
| 148 | 177 | |
| 149 | 178 | pub fn flush(self: *SpirV, comp: *Compilation) !void { |
| ... | ... | @@ -273,3 +302,35 @@ fn writeMemoryModel(binary: *std.ArrayList(Word), target: std.Target) !void { |
| 273 | 302 | @enumToInt(addressing_model), @enumToInt(memory_model), |
| 274 | 303 | }); |
| 275 | 304 | } |
| 305 | |
| 306 | fn 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 | |
| 320 | fn 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 | } |