diff options
| author | Robin Voetter <robin@voetter.nl> | 2022-12-02 00:22:26 +0100 |
|---|---|---|
| committer | Robin Voetter <robin@voetter.nl> | 2023-04-09 01:51:51 +0200 |
| commit | c9db6e43af366215cd8bf494ea54ad14e4b97cc0 (patch) | |
| tree | dbcb84fc48154347f36e108255780ec2506cb433 /src/link | |
| parent | 34b98ee372f8974e21cd34b3ca7588b13d93e31a (diff) | |
| download | zig-c9db6e43af366215cd8bf494ea54ad14e4b97cc0.tar.gz zig-c9db6e43af366215cd8bf494ea54ad14e4b97cc0.zip | |
spirv: generate code directly in updateFunc/updateDecl
This cloneAir/cloneLiveness idea used to ignore Zig's internals
has proven buggy. Instead, just generate the code directly from
updateFunc and updateDecl as the other backends do, but pretend
that Zig is not an incremental compiler. The SPIR-V backend will
for the time being not support this.
Diffstat (limited to 'src/link')
| -rw-r--r-- | src/link/SpirV.zig | 172 |
1 files changed, 31 insertions, 141 deletions
diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index 561775a757..c63e4a20af 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -44,34 +44,25 @@ const IdResult = spec.IdResult; base: link.File, -/// This linker backend does not try to incrementally link output SPIR-V code. -/// Instead, it tracks all declarations in this table, and iterates over it -/// in the flush function. -decl_table: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, DeclGenContext) = .{}, - -const DeclGenContext = struct { - air: Air, - air_arena: ArenaAllocator.State, - liveness: Liveness, - - fn deinit(self: *DeclGenContext, gpa: Allocator) void { - self.air.deinit(gpa); - self.liveness.deinit(gpa); - self.air_arena.promote(gpa).deinit(); - self.* = undefined; - } -}; +spv: SpvModule, +spv_arena: ArenaAllocator, +decl_ids: codegen.DeclMap, pub fn createEmpty(gpa: Allocator, options: link.Options) !*SpirV { - const spirv = try gpa.create(SpirV); - spirv.* = .{ + const self = try gpa.create(SpirV); + self.* = .{ .base = .{ .tag = .spirv, .options = options, .file = null, .allocator = gpa, }, + .spv = undefined, + .spv_arena = ArenaAllocator.init(gpa), + .decl_ids = codegen.DeclMap.init(self.base.allocator), }; + self.spv = SpvModule.init(gpa, self.spv_arena.allocator()); + errdefer self.deinit(); // TODO: Figure out where to put all of these switch (options.target.cpu.arch) { @@ -88,7 +79,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*SpirV { return error.TODOAbiNotSupported; } - return spirv; + return self; } pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*SpirV { @@ -107,44 +98,35 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option } pub fn deinit(self: *SpirV) void { - self.decl_table.deinit(self.base.allocator); + self.spv.deinit(); + self.spv_arena.deinit(); + self.decl_ids.deinit(); } pub fn updateFunc(self: *SpirV, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void { if (build_options.skip_non_native) { @panic("Attempted to compile for architecture that was disabled by build configuration"); } - _ = module; - - // Keep track of all decls so we can iterate over them on flush(). - const result = try self.decl_table.getOrPut(self.base.allocator, func.owner_decl); - if (result.found_existing) { - result.value_ptr.deinit(self.base.allocator); - } - - var arena = ArenaAllocator.init(self.base.allocator); - errdefer arena.deinit(); - var new_air = try cloneAir(air, self.base.allocator, arena.allocator()); - errdefer new_air.deinit(self.base.allocator); - - var new_liveness = try cloneLiveness(liveness, self.base.allocator); - errdefer new_liveness.deinit(self.base.allocator); + var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_ids); + defer decl_gen.deinit(); - result.value_ptr.* = .{ - .air = new_air, - .air_arena = arena.state, - .liveness = new_liveness, - }; + if (try decl_gen.gen(func.owner_decl, air, liveness)) |msg| { + try module.failed_decls.put(module.gpa, func.owner_decl, msg); + } } pub fn updateDecl(self: *SpirV, module: *Module, decl_index: Module.Decl.Index) !void { if (build_options.skip_non_native) { @panic("Attempted to compile for architecture that was disabled by build configuration"); } - _ = module; - // Keep track of all decls so we can iterate over them on flush(). - _ = try self.decl_table.getOrPut(self.base.allocator, decl_index); + + var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_ids); + defer decl_gen.deinit(); + + if (try decl_gen.gen(decl_index, undefined, undefined)) |msg| { + try module.failed_decls.put(module.gpa, decl_index, msg); + } } pub fn updateDeclExports( @@ -160,13 +142,8 @@ pub fn updateDeclExports( } pub fn freeDecl(self: *SpirV, decl_index: Module.Decl.Index) void { - if (self.decl_table.getIndex(decl_index)) |index| { - const module = self.base.options.module.?; - const decl = module.declPtr(decl_index); - if (decl.val.tag() == .function) { - self.decl_table.values()[index].deinit(self.base.allocator); - } - } + _ = self; + _ = decl_index; } pub fn flush(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { @@ -189,56 +166,11 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No sub_prog_node.activate(); defer sub_prog_node.end(); - const module = self.base.options.module.?; const target = comp.getTarget(); + try writeCapabilities(&self.spv, target); + try writeMemoryModel(&self.spv, target); - var arena = std.heap.ArenaAllocator.init(self.base.allocator); - defer arena.deinit(); - - var spv = SpvModule.init(self.base.allocator, arena.allocator()); - defer spv.deinit(); - - // Allocate an ID for every declaration before generating code, - // so that we can access them before processing them. - // TODO: We're allocating an ID unconditionally now, are there - // declarations which don't generate a result? - var ids = std.AutoHashMap(Module.Decl.Index, IdResult).init(self.base.allocator); - defer ids.deinit(); - try ids.ensureTotalCapacity(@intCast(u32, self.decl_table.count())); - - for (self.decl_table.keys()) |decl_index| { - const decl = module.declPtr(decl_index); - if (decl.has_tv) { - ids.putAssumeCapacityNoClobber(decl_index, spv.allocId()); - } - } - - // Now, actually generate the code for all declarations. - var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &spv, &ids); - defer decl_gen.deinit(); - - var it = self.decl_table.iterator(); - while (it.next()) |entry| { - const decl_index = entry.key_ptr.*; - const decl = module.declPtr(decl_index); - if (!decl.has_tv) continue; - - const air = entry.value_ptr.air; - const liveness = entry.value_ptr.liveness; - - log.debug("generating code for {s}", .{decl.name}); - - // Note, if `decl` is not a function, air/liveness may be undefined. - if (try decl_gen.gen(decl_index, air, liveness)) |msg| { - try module.failed_decls.put(module.gpa, decl_index, msg); - return; // TODO: Attempt to generate more decls? - } - } - - try writeCapabilities(&spv, target); - try writeMemoryModel(&spv, target); - - try spv.flush(self.base.file.?); + try self.spv.flush(self.base.file.?); } fn writeCapabilities(spv: *SpvModule, target: std.Target) !void { @@ -281,45 +213,3 @@ fn writeMemoryModel(spv: *SpvModule, target: std.Target) !void { .memory_model = memory_model, }); } - -fn cloneLiveness(l: Liveness, gpa: Allocator) !Liveness { - const tomb_bits = try gpa.dupe(usize, l.tomb_bits); - errdefer gpa.free(tomb_bits); - - const extra = try gpa.dupe(u32, l.extra); - errdefer gpa.free(extra); - - return Liveness{ - .tomb_bits = tomb_bits, - .extra = extra, - .special = try l.special.clone(gpa), - }; -} - -fn cloneAir(air: Air, gpa: Allocator, air_arena: Allocator) !Air { - const values = try gpa.alloc(Value, air.values.len); - errdefer gpa.free(values); - - for (values, 0..) |*value, i| { - value.* = try air.values[i].copy(air_arena); - } - - var instructions = try air.instructions.toMultiArrayList().clone(gpa); - errdefer instructions.deinit(gpa); - - const air_tags = instructions.items(.tag); - const air_datas = instructions.items(.data); - - for (air_tags, 0..) |tag, i| { - switch (tag) { - .alloc, .ret_ptr, .const_ty => air_datas[i].ty = try air_datas[i].ty.copy(air_arena), - else => {}, - } - } - - return Air{ - .instructions = instructions.slice(), - .extra = try gpa.dupe(u32, air.extra), - .values = values, - }; -} |
