Allow sharing of initialization functions across slots to limit code size growth.

PiperOrigin-RevId: 734615591
Change-Id: I7b7d73c0e38e2b9f55013f79a33fce7bf71edb72
diff --git a/mpact/sim/decoder/BUILD b/mpact/sim/decoder/BUILD
index 75511a5..536ba70 100644
--- a/mpact/sim/decoder/BUILD
+++ b/mpact/sim/decoder/BUILD
@@ -117,6 +117,7 @@
         ":antlr_parser_wrapper",
         ":decoder_error_listener",
         ":format_name",
+        "@com_google_absl//absl/base:no_destructor",
         "@com_google_absl//absl/container:btree",
         "@com_google_absl//absl/container:flat_hash_map",
         "@com_google_absl//absl/container:flat_hash_set",
diff --git a/mpact/sim/decoder/slot.cc b/mpact/sim/decoder/slot.cc
index 63372ff..135539f 100644
--- a/mpact/sim/decoder/slot.cc
+++ b/mpact/sim/decoder/slot.cc
@@ -26,7 +26,9 @@
 #include <variant>
 #include <vector>
 
+#include "absl/base/no_destructor.h"
 #include "absl/container/btree_set.h"
+#include "absl/container/flat_hash_map.h"
 #include "absl/container/flat_hash_set.h"
 #include "absl/status/status.h"
 #include "absl/status/statusor.h"
@@ -46,6 +48,15 @@
 namespace machine_description {
 namespace instruction_set {
 
+absl::NoDestructor<absl::flat_hash_map<std::string, std::string>>
+    Slot::operand_setter_name_map_;
+absl::NoDestructor<absl::flat_hash_map<std::string, std::string>>
+    Slot::disasm_setter_name_map_;
+absl::NoDestructor<absl::flat_hash_map<std::string, std::string>>
+    Slot::resource_setter_name_map_;
+absl::NoDestructor<absl::flat_hash_map<std::string, std::string>>
+    Slot::attribute_setter_name_map_;
+
 // This function translates the location specification into a set of '->'
 // references starting with 'inst->' to get to the operand that is implied.
 static absl::StatusOr<std::string> TranslateLocator(
@@ -274,12 +285,12 @@
 // instruction. If no such appropriate function exists, create one.
 std::string Slot::GenerateAttributeSetter(const Instruction *inst) {
   auto key = CreateAttributeLookupKey(inst);
-  auto iter = attribute_setter_name_map_.find(key);
-  if (iter == attribute_setter_name_map_.end()) {
-    auto index = attribute_setter_name_map_.size();
+  auto iter = attribute_setter_name_map_->find(key);
+  if (iter == attribute_setter_name_map_->end()) {
+    auto index = attribute_setter_name_map_->size();
     std::string func_name =
         absl::StrCat(pascal_name(), "Slot", "SetAttributes", index);
-    iter = attribute_setter_name_map_.emplace(key, func_name).first;
+    iter = attribute_setter_name_map_->emplace(key, func_name).first;
     absl::StrAppend(&setter_functions_,
                     GenerateAttributeSetterFcn(func_name, inst));
   }
@@ -719,9 +730,9 @@
   absl::StrAppend(&key, ":", CreateOperandLookupKey(inst->opcode()));
   std::string func_name = absl::StrCat(
       pascal_name(), "Slot", inst->opcode()->pascal_name(), "SetDisasm");
-  auto iter = disasm_setter_name_map_.find(key);
-  if (iter == disasm_setter_name_map_.end()) {
-    iter = disasm_setter_name_map_.emplace(key, func_name).first;
+  auto iter = disasm_setter_name_map_->find(key);
+  if (iter == disasm_setter_name_map_->end()) {
+    iter = disasm_setter_name_map_->emplace(key, func_name).first;
     absl::StrAppend(&setter_functions_,
                     GenerateDisasmSetterFcn(func_name, inst));
   }
@@ -849,12 +860,12 @@
                                          absl::string_view encoding_type) {
   std::string key = CreateResourceKey(inst->resource_use_vec());
   absl::StrAppend(&key, ":", CreateResourceKey(inst->resource_acquire_vec()));
-  auto iter = resource_setter_name_map_.find(key);
-  if (iter == resource_setter_name_map_.end()) {
-    auto index = resource_setter_name_map_.size();
+  auto iter = resource_setter_name_map_->find(key);
+  if (iter == resource_setter_name_map_->end()) {
+    auto index = resource_setter_name_map_->size();
     std::string func_name =
         absl::StrCat(pascal_name(), "Slot", "SetResources", index);
-    iter = resource_setter_name_map_.emplace(key, func_name).first;
+    iter = resource_setter_name_map_->emplace(key, func_name).first;
     absl::StrAppend(&setter_functions_,
                     GenerateResourceSetterFcn(func_name, inst, encoding_type));
   }
@@ -1246,18 +1257,19 @@
          inst = inst->child()) {
       // Construct operand getter lookup key.
       std::string key = CreateOperandLookupKey(inst->opcode());
-      auto iter = operand_setter_name_map_.find(key);
+      auto iter = operand_setter_name_map_->find(key);
       // If the key is not found, create a new getter function, otherwise
       // reuse the existing one.
-      if (iter == operand_setter_name_map_.end()) {
-        auto index = operand_setter_name_map_.size();
+      if (iter == operand_setter_name_map_->end()) {
+        auto index = operand_setter_name_map_->size();
         std::string setter_name =
             absl::StrCat(class_name, "SetOperands", index);
         absl::StrAppend(&setter_functions_,
                         GenerateOperandSetterFcn(setter_name, encoding_type,
                                                  inst->opcode()));
-        iter = operand_setter_name_map_.insert(std::make_pair(key, setter_name))
-                   .first;
+        iter =
+            operand_setter_name_map_->insert(std::make_pair(key, setter_name))
+                .first;
       }
       absl::StrAppend(&operands_str, sep, iter->second);
       if (inst->semfunc_code_string().empty()) {
diff --git a/mpact/sim/decoder/slot.h b/mpact/sim/decoder/slot.h
index cc1df51..1f074d0 100644
--- a/mpact/sim/decoder/slot.h
+++ b/mpact/sim/decoder/slot.h
@@ -20,6 +20,7 @@
 #include <tuple>
 #include <vector>
 
+#include "absl/base/no_destructor.h"
 #include "absl/container/btree_map.h"
 #include "absl/container/flat_hash_map.h"
 #include "absl/container/flat_hash_set.h"
@@ -219,11 +220,16 @@
   // Pointer to slot it inherits from.
   std::vector<BaseSlot> base_slots_;
   absl::flat_hash_set<const Slot *> predecessor_set_;
-  // Map from operand getter key to operand getter function name.
-  absl::flat_hash_map<std::string, std::string> operand_setter_name_map_;
-  absl::flat_hash_map<std::string, std::string> disasm_setter_name_map_;
-  absl::flat_hash_map<std::string, std::string> resource_setter_name_map_;
-  absl::flat_hash_map<std::string, std::string> attribute_setter_name_map_;
+  // Map from operand getter key to operand getter function name. These are
+  // static so that they can be shared across different slots.
+  static absl::NoDestructor<absl::flat_hash_map<std::string, std::string>>
+      operand_setter_name_map_;
+  static absl::NoDestructor<absl::flat_hash_map<std::string, std::string>>
+      disasm_setter_name_map_;
+  static absl::NoDestructor<absl::flat_hash_map<std::string, std::string>>
+      resource_setter_name_map_;
+  static absl::NoDestructor<absl::flat_hash_map<std::string, std::string>>
+      attribute_setter_name_map_;
   std::string setter_functions_;
   // Used to list the unique getters for the operands.
   absl::flat_hash_set<std::string> pred_operand_getters_;