| ... | ... | @@ -194,6 +194,11 @@ inst: struct { |
| 194 | 194 | /// This map maps results to their tracked values. |
| 195 | 195 | value_map: AsmValueMap = .{}, |
| 196 | 196 | |
| 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()`. |
| 200 | instruction_map: std.StringArrayHashMapUnmanaged(void) = .{}, |
| 201 | |
| 197 | 202 | /// Free the resources owned by this assembler. |
| 198 | 203 | pub fn deinit(self: *Assembler) void { |
| 199 | 204 | for (self.errors.items) |err| { |
| ... | ... | @@ -204,9 +209,20 @@ pub fn deinit(self: *Assembler) void { |
| 204 | 209 | self.inst.operands.deinit(self.gpa); |
| 205 | 210 | self.inst.string_bytes.deinit(self.gpa); |
| 206 | 211 | self.value_map.deinit(self.gpa); |
| 212 | self.instruction_map.deinit(self.gpa); |
| 207 | 213 | } |
| 208 | 214 | |
| 209 | 215 | pub 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 | 226 | try self.tokenize(); |
| 211 | 227 | while (!self.testToken(.eof)) { |
| 212 | 228 | try self.parseInstruction(); |
| ... | ... | @@ -475,12 +491,14 @@ fn parseInstruction(self: *Assembler) !void { |
| 475 | 491 | } |
| 476 | 492 | |
| 477 | 493 | const opcode_text = self.tokenText(opcode_tok); |
| 478 | | @setEvalBranchQuota(10000); |
| 479 | | self.inst.opcode = std.meta.stringToEnum(Opcode, opcode_text) orelse { |
| 494 | const index = self.instruction_map.getIndex(opcode_text) orelse { |
| 480 | 495 | return self.fail(opcode_tok.start, "invalid opcode '{s}'", .{opcode_text}); |
| 481 | 496 | }; |
| 482 | 497 | |
| 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 | 502 | // This is a loop because the result-id is not always the first operand. |
| 485 | 503 | const requires_lhs_result = for (expected_operands) |op| { |
| 486 | 504 | if (op.kind == .IdResult) break true; |