authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2024-03-09 12:31:39+01:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2024-03-18 19:13:48+01:00
log9b058117f0f4595d43fbe08a3e659ac865e8b459
treebfb32104ccd2306f00d805b2ab37f15a7f47fcf5
parent028f532dc0ef1d544d6fcb9074cef92a11d6d25b
signaturebadge-check Signed by SSH key SHA256:ZS52FNyUv2WUXvO4njmVaFVO46RHojFuOrxRc4LuKzg

spirv: update assembler with new spec


1 files changed, 21 insertions(+), 3 deletions(-)

src/codegen/spirv/Assembler.zig+21-3
...@@ -194,6 +194,11 @@ inst: struct {...@@ -194,6 +194,11 @@ inst: struct {
194/// This map maps results to their tracked values.194/// This map maps results to their tracked values.
195value_map: AsmValueMap = .{},195value_map: AsmValueMap = .{},
196196
197/// This set is used to quickly transform from an opcode name to the
198/// index in its instruction set. The index of the key is the
199/// index in `spec.InstructionSet.core.instructions()`.
200instruction_map: std.StringArrayHashMapUnmanaged(void) = .{},
201
197/// Free the resources owned by this assembler.202/// Free the resources owned by this assembler.
198pub fn deinit(self: *Assembler) void {203pub fn deinit(self: *Assembler) void {
199 for (self.errors.items) |err| {204 for (self.errors.items) |err| {
...@@ -204,9 +209,20 @@ pub fn deinit(self: *Assembler) void {...@@ -204,9 +209,20 @@ pub fn deinit(self: *Assembler) void {
204 self.inst.operands.deinit(self.gpa);209 self.inst.operands.deinit(self.gpa);
205 self.inst.string_bytes.deinit(self.gpa);210 self.inst.string_bytes.deinit(self.gpa);
206 self.value_map.deinit(self.gpa);211 self.value_map.deinit(self.gpa);
212 self.instruction_map.deinit(self.gpa);
207}213}
208214
209pub fn assemble(self: *Assembler) Error!void {215pub fn assemble(self: *Assembler) Error!void {
216 // Populate the opcode map if it isn't already
217 if (self.instruction_map.count() == 0) {
218 const instructions = spec.InstructionSet.core.instructions();
219 try self.instruction_map.ensureUnusedCapacity(self.gpa, @intCast(instructions.len));
220 for (spec.InstructionSet.core.instructions(), 0..) |inst, i| {
221 const entry = try self.instruction_map.getOrPut(self.gpa, inst.name);
222 assert(entry.index == i);
223 }
224 }
225
210 try self.tokenize();226 try self.tokenize();
211 while (!self.testToken(.eof)) {227 while (!self.testToken(.eof)) {
212 try self.parseInstruction();228 try self.parseInstruction();
...@@ -475,12 +491,14 @@ fn parseInstruction(self: *Assembler) !void {...@@ -475,12 +491,14 @@ fn parseInstruction(self: *Assembler) !void {
475 }491 }
476492
477 const opcode_text = self.tokenText(opcode_tok);493 const opcode_text = self.tokenText(opcode_tok);
478 @setEvalBranchQuota(10000);494 const index = self.instruction_map.getIndex(opcode_text) orelse {
479 self.inst.opcode = std.meta.stringToEnum(Opcode, opcode_text) orelse {
480 return self.fail(opcode_tok.start, "invalid opcode '{s}'", .{opcode_text});495 return self.fail(opcode_tok.start, "invalid opcode '{s}'", .{opcode_text});
481 };496 };
482497
483 const expected_operands = self.inst.opcode.operands();498 const inst = spec.InstructionSet.core.instructions()[index];
499 self.inst.opcode = @enumFromInt(inst.opcode);
500
501 const expected_operands = inst.operands;
484 // This is a loop because the result-id is not always the first operand.502 // This is a loop because the result-id is not always the first operand.
485 const requires_lhs_result = for (expected_operands) |op| {503 const requires_lhs_result = for (expected_operands) |op| {
486 if (op.kind == .IdResult) break true;504 if (op.kind == .IdResult) break true;