SPIR-V: DeclGen constructor/destructor

This commit is contained in:
Robin Voetter 2021-05-20 20:35:52 +02:00
parent 46184ab85e
commit e3be1a1e88
2 changed files with 46 additions and 35 deletions

View File

@ -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;

View File

@ -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?
}
}
}