No public description

PiperOrigin-RevId: 869737255
Change-Id: I936f44db323f8d67ed19f993aca414f8712c9aff
diff --git a/mpact/sim/decoder/BUILD b/mpact/sim/decoder/BUILD
index 00eaa42..f214fa9 100644
--- a/mpact/sim/decoder/BUILD
+++ b/mpact/sim/decoder/BUILD
@@ -128,6 +128,7 @@
         "@com_google_absl//absl/status",
         "@com_google_absl//absl/status:statusor",
         "@com_google_absl//absl/strings",
+        "@com_google_absl//absl/strings:str_format",
         "@com_googlesource_code_re2//:re2",
     ],
 )
diff --git a/mpact/sim/decoder/slot.cc b/mpact/sim/decoder/slot.cc
index d967ec5..0c786ef 100644
--- a/mpact/sim/decoder/slot.cc
+++ b/mpact/sim/decoder/slot.cc
@@ -34,6 +34,7 @@
 #include "absl/status/statusor.h"
 #include "absl/strings/numbers.h"
 #include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
 #include "absl/strings/string_view.h"
 #include "mpact/sim/decoder/format_name.h"
 #include "mpact/sim/decoder/instruction.h"
@@ -1101,6 +1102,10 @@
   return output;
 }
 
+std::string Slot::GetInstructionArrayName() const {
+  return absl::StrCat("k", pascal_name(), "SlotInstructionArray");
+}
+
 // Generates a string that is a unique identifier from the operands to
 // determine which instructions can share operand getter functions.
 std::string Slot::CreateOperandLookupKey(const Opcode* opcode) const {
@@ -1251,25 +1256,22 @@
   return output;
 }
 
-std::string Slot::ListFuncGetterInitializations(
-    absl::string_view encoding_type) {
-  std::string output;
-  if (instruction_map_.empty()) return output;
-  std::string class_name = pascal_name() + "Slot";
-  // For each instruction create two lambda functions. One that is used to
-  // obtain the semantic function object for the instruction, the other a
-  // lambda that sets the predicate, source and target operands. Both lambdas
-  // use calls to virtual functions declared in the current class or a base
-  // class thereof.
-  std::string signature =
-      absl::StrCat("(Instruction *inst, ", encoding_type,
-                   " *enc, OpcodeEnum opcode, SlotEnum slot, int entry)");
+std::string Slot::CreateFuncGetterGlobalArray(absl::string_view encoding_type) {
+  const std::string class_name = pascal_name() + "Slot";
+  std::string output = absl::StrFormat(
+      "const std::array<std::pair<OpcodeEnum, InstructionInfo>, %d>\n"
+      "%s {\n",
+      instruction_map_.size() + 1, GetInstructionArrayName());
+
   absl::StrAppend(&setter_functions_,
                   GenerateOperandSetterFcn(
                       absl::StrCat(pascal_name(), "SlotSetOperandsNull"),
                       encoding_type, default_instruction_->opcode()));
+
   absl::StrAppend(
-      &output, "    {static_cast<int>(OpcodeEnum::kNone), {OperandSetter{",
+      &output,
+      "    std::make_pair(OpcodeEnum::kNone, "
+      "InstructionInfo{OperandSetter{",
       pascal_name(),
       "SlotSetOperandsNull},\n"
       "    ",
@@ -1277,7 +1279,7 @@
       GenerateResourceSetter(default_instruction_, encoding_type), ",\n",
       "    ", GenerateAttributeSetter(default_instruction_), ",\n",
       "    SemFuncSetter{", default_instruction_->semfunc_code_string(), "}, ",
-      default_instruction_->opcode()->instruction_size(), "}},\n");
+      default_instruction_->opcode()->instruction_size(), "}),\n");
   for (auto const& [unused, inst_ptr] : instruction_map_) {
     auto* instruction = inst_ptr;
     std::string opcode_name = instruction->opcode()->pascal_name();
@@ -1316,14 +1318,16 @@
       }
       sep = ", ";
     }
-    absl::StrAppend(&output, "    {static_cast<int>(OpcodeEnum::k", opcode_name,
-                    "), {OperandSetter{", operands_str, "},\n", "    ",
-                    GenerateDisassemblySetter(instruction), ",\n", "    ",
-                    GenerateResourceSetter(instruction, encoding_type), ",\n",
-                    "    ", GenerateAttributeSetter(instruction), ",\n",
+    absl::StrAppend(&output, "    std::make_pair(OpcodeEnum::k", opcode_name,
+                    ", InstructionInfo{OperandSetter{", operands_str, "},\n",
+                    "    ", GenerateDisassemblySetter(instruction), ",\n",
+                    "    ", GenerateResourceSetter(instruction, encoding_type),
+                    ",\n", "    ", GenerateAttributeSetter(instruction), ",\n",
                     "    SemFuncSetter{", code_str, "}, ",
-                    instruction->opcode()->instruction_size(), "}},\n");
+                    instruction->opcode()->instruction_size(), "}),\n");
   }
+  absl::StrAppend(&output, "};\n\n");
+
   return output;
 }
 
@@ -1346,10 +1350,8 @@
       "* isa_encoding, SlotEnum, int entry);\n",
       "\n"
       " private:\n"
-      "  ArchState *arch_state_;\n"
+      "  ArchState *arch_state_;\n",
       "  absl::flat_hash_map<int, InstructionInfo> instruction_info_;\n",
-      //"  std::array<InstructionInfo, ",
-      // instruction_map_.size() + 1, "> instruction_info_", ";\n",
       "  static constexpr SlotEnum slot_ = SlotEnum::k", pascal_name(),
       ";\n"
       "};\n"
@@ -1367,9 +1369,14 @@
   absl::StrAppend(
       &output, class_name, "::", class_name,
       "(ArchState *arch_state) :\n"
-      "  arch_state_(arch_state),\n",
-      "  instruction_info_{{\n", ListFuncGetterInitializations(encoding_type),
-      "}} {}\n",
+      "  arch_state_(arch_state) {\n"
+      "  for (const auto& inst_info : ",
+      GetInstructionArrayName(),
+      ") {\n"
+      "    instruction_info_[static_cast<int>(inst_info.first)] =\n"
+      "        inst_info.second;\n"
+      "  }\n"
+      "}\n"
       "\n"
       "Instruction *",
       class_name, "::Decode(uint64_t address, ", encoding_type,
@@ -1398,9 +1405,12 @@
       "  inst_info.attribute_setter(inst);\n"
       "  return inst;\n"
       "}\n");
-  // Prepend the setter functions.
-  std::string combined_output = absl::StrCat(
-      "namespace {\n\n", setter_functions_, "}  // namespace\n\n", output);
+  // Prepend the setter functions and global instruction map.
+  const std::string instruction_map_string =
+      CreateFuncGetterGlobalArray(encoding_type);
+  std::string combined_output =
+      absl::StrCat("namespace {\n\n", setter_functions_, instruction_map_string,
+                   "}  // namespace\n\n", output);
   return combined_output;
 }
 
diff --git a/mpact/sim/decoder/slot.h b/mpact/sim/decoder/slot.h
index fbdae67..640ff0c 100644
--- a/mpact/sim/decoder/slot.h
+++ b/mpact/sim/decoder/slot.h
@@ -168,6 +168,11 @@
   }
 
  private:
+  // Returns the name of the instruction array used for this slot. The
+  // instruction array is a constexpr global array of instruction information,
+  // keyed by the opcode.
+  std::string GetInstructionArrayName() const;
+
   // These functions generate the functions that are called by the decoder to
   // set the instruction operands.
   std::string CreateOperandLookupKey(const Opcode* opcode) const;
@@ -194,13 +199,10 @@
   std::string GenerateAttributeSetterFcn(absl::string_view name,
                                          const Instruction* inst) const;
   std::string CreateAttributeLookupKey(const Instruction* inst) const;
-  // Generates a string that is a unique key for the operands to determine which
-  // instructions can share operand getter functions.
-  // Build up a string containing the function getter initializers that are
-  // stored in two flat hash maps with the opcode as the key. These functions
-  // are lambda's that call the getters for the semantic functions as well as
-  // operand getters for each instruction opcode.
-  std::string ListFuncGetterInitializations(absl::string_view encoding_type);
+  // Generates a string that defines a global constexpr array of instruction
+  // opcodes and instruction info structs. Also populates the setter function
+  // string 'setter_functions_' with the setters.
+  std::string CreateFuncGetterGlobalArray(absl::string_view encoding_type);
   // Transitively check if base slot is in the predecessor set of the current
   // slot or any of its inheritance predecessors. Returns AlreadyExistsError
   // if the current slot or its predecessors already inherit from base or its
@@ -242,6 +244,10 @@
       resource_setter_name_map_;
   static absl::NoDestructor<absl::flat_hash_map<std::string, std::string>>
       attribute_setter_name_map_;
+
+  // Stores a string representation of the instruction array for this slot. This
+  // is an array that is used to initialize the map within the decoder.
+  std::string instruction_array_str_;
   std::string setter_functions_;
   // Used to list the unique getters for the operands.
   absl::flat_hash_set<std::string> pred_operand_getters_;