diff options
| author | Robin Voetter <robin@voetter.nl> | 2021-05-20 20:35:52 +0200 |
|---|---|---|
| committer | Robin Voetter <robin@voetter.nl> | 2021-05-22 16:11:56 +0200 |
| commit | e3be1a1e88bc76d5886122048e44673b692e6db6 (patch) | |
| tree | 9025dcd08cb45889353e7905e3d2b0fc83c2aff5 /src | |
| parent | 46184ab85eaf32be6e6fcbaac2202a2d58a37cf7 (diff) | |
| download | zig-e3be1a1e88bc76d5886122048e44673b692e6db6.tar.gz zig-e3be1a1e88bc76d5886122048e44673b692e6db6.zip | |
SPIR-V: DeclGen constructor/destructor
Diffstat (limited to 'src')
| -rw-r--r-- | src/codegen/spirv.zig | 41 | ||||
| -rw-r--r-- | src/link/SpirV.zig | 40 |
2 files changed, 46 insertions, 35 deletions
diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 4cb0068473..6687ffd970 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -157,6 +157,45 @@ pub const DeclGen = struct { class: Class, }; + /// Initialize the common resources of a DeclGen. Some fields are left uninitialized, only set when `gen` is called. + pub fn init(gpa: *Allocator, module: *Module, spv: *SPIRVModule) DeclGen { + return .{ + .module = module, + .spv = spv, + .args = std.ArrayList(ResultId).init(gpa), + .next_arg_index = undefined, + .inst_results = InstMap.init(gpa), + .blocks = BlockMap.init(gpa), + .current_block_label_id = undefined, + .decl = undefined, + .error_msg = undefined, + }; + } + + /// Generate the code for `decl`. If a reportable error occured during code generation, + /// a message is returned by this function. Callee owns the memory. If this function returns such + /// a reportable error, it is valid to be called again for a different decl. + pub fn gen(self: *DeclGen, decl: *Decl) !?*Module.ErrorMsg { + // Reset internal resources, we don't want to re-allocate these. + self.args.items.len = 0; + self.next_arg_index = 0; + self.inst_results.clearRetainingCapacity(); + self.blocks.clearRetainingCapacity(); + self.current_block_label_id = undefined; + self.decl = decl; + self.error_msg = null; + + try self.genDecl(); + return self.error_msg; + } + + /// Free resources owned by the DeclGen. + pub fn deinit(self: *DeclGen) void { + self.args.deinit(); + self.inst_results.deinit(); + self.blocks.deinit(); + } + fn fail(self: *DeclGen, src: LazySrcLoc, comptime format: []const u8, args: anytype) Error { @setCold(true); const src_loc = src.toSrcLocWithDecl(self.decl); @@ -476,7 +515,7 @@ pub const DeclGen = struct { return result_id; } - pub fn gen(self: *DeclGen) !void { + fn genDecl(self: *DeclGen) !void { const decl = self.decl; const result_id = decl.fn_link.spirv.id; diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index daa94f932a..cae29eb2d7 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -152,45 +152,17 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void { // Now, actually generate the code for all declarations. { - // We are just going to re-use this same DeclGen for every Decl, and we are just going to - // change the decl. Otherwise, we would have to keep a separate `args` and `types`, and re-construct this - // structure every time. - var decl_gen = codegen.DeclGen{ - .module = module, - .spv = &spv, - .args = std.ArrayList(codegen.Word).init(self.base.allocator), - .next_arg_index = undefined, - .inst_results = codegen.InstMap.init(self.base.allocator), - .blocks = codegen.BlockMap.init(self.base.allocator), - .current_block_label_id = undefined, - .decl = undefined, - .error_msg = undefined, - }; - - defer decl_gen.inst_results.deinit(); - defer decl_gen.args.deinit(); - defer decl_gen.blocks.deinit(); + var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &spv); + defer decl_gen.deinit(); for (self.decl_table.items()) |entry| { const decl = entry.key; if (!decl.has_tv) continue; - // Reset the decl_gen, but retain allocated resources. - decl_gen.args.items.len = 0; - decl_gen.next_arg_index = 0; - decl_gen.inst_results.clearRetainingCapacity(); - decl_gen.blocks.clearRetainingCapacity(); - decl_gen.current_block_label_id = undefined; - decl_gen.decl = decl; - decl_gen.error_msg = null; - - decl_gen.gen() catch |err| switch (err) { - error.AnalysisFail => { - try module.failed_decls.put(module.gpa, decl, decl_gen.error_msg.?); - return; - }, - else => |e| return e, - }; + if (try decl_gen.gen(decl)) |msg| { + try module.failed_decls.put(module.gpa, decl, msg); + return; // TODO: Attempt to generate more decls? + } } } |
