| ... | @@ -24,6 +24,7 @@ const SpirV = @This(); | ... | @@ -24,6 +24,7 @@ const SpirV = @This(); |
| 24 | | 24 | |
| 25 | const std = @import("std"); | 25 | const std = @import("std"); |
| 26 | const Allocator = std.mem.Allocator; | 26 | const Allocator = std.mem.Allocator; |
| | 27 | const ArenaAllocator = std.heap.ArenaAllocator; |
| 27 | const assert = std.debug.assert; | 28 | const assert = std.debug.assert; |
| 28 | const log = std.log.scoped(.link); | 29 | const log = std.log.scoped(.link); |
| 29 | | 30 | |
| ... | @@ -38,6 +39,7 @@ const build_options = @import("build_options"); | ... | @@ -38,6 +39,7 @@ const build_options = @import("build_options"); |
| 38 | const spec = @import("../codegen/spirv/spec.zig"); | 39 | const spec = @import("../codegen/spirv/spec.zig"); |
| 39 | const Air = @import("../Air.zig"); | 40 | const Air = @import("../Air.zig"); |
| 40 | const Liveness = @import("../Liveness.zig"); | 41 | const Liveness = @import("../Liveness.zig"); |
| | 42 | const Value = @import("../value.zig").Value; |
| 41 | | 43 | |
| 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? |
| 43 | pub const FnData = struct { | 45 | pub 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) = .{}, |
| 55 | | 57 | |
| 56 | const DeclGenContext = struct { | 58 | const 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 | }; |
| 60 | | 70 | |
| 61 | pub fn createEmpty(gpa: Allocator, options: link.Options) !*SpirV { | 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,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); |
| 118 | | 138 | |
| 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 | } |
| 123 | | 148 | |
| 124 | pub fn updateDecl(self: *SpirV, module: *Module, decl: *Module.Decl) !void { | 149 | pub 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 | } |
| 144 | | 169 | |
| 145 | pub fn freeDecl(self: *SpirV, decl: *Module.Decl) void { | 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 | pub fn flush(self: *SpirV, comp: *Compilation) !void { | 178 | pub 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 | |
| | 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 | } |