@@ -194,6 +194,11 @@ inst: struct {
194194/// This map maps results to their tracked values.
195195value_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()`.
200+ instruction_map : std .StringArrayHashMapUnmanaged (void ) = .{},
201+
197202/// Free the resources owned by this assembler.
198203pub fn deinit (self : * Assembler ) void {
199204 for (self .errors .items ) | err | {
@@ -204,9 +209,20 @@ pub fn deinit(self: *Assembler) void {
204209 self .inst .operands .deinit (self .gpa );
205210 self .inst .string_bytes .deinit (self .gpa );
206211 self .value_map .deinit (self .gpa );
212+ self .instruction_map .deinit (self .gpa );
207213}
208214
209215pub 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+
210226 try self .tokenize ();
211227 while (! self .testToken (.eof )) {
212228 try self .parseInstruction ();
@@ -475,12 +491,14 @@ fn parseInstruction(self: *Assembler) !void {
475491 }
476492
477493 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 {
480495 return self .fail (opcode_tok .start , "invalid opcode '{s}'" , .{opcode_text });
481496 };
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 ;
484502 // This is a loop because the result-id is not always the first operand.
485503 const requires_lhs_result = for (expected_operands ) | op | {
486504 if (op .kind == .IdResult ) break true ;
0 commit comments