Fixes issue with attributes for instructions with child instructions.

PiperOrigin-RevId: 895900622
Change-Id: I006face376ecd28d39990449eb5aef2399dca010
diff --git a/mpact/sim/decoder/instruction.cc b/mpact/sim/decoder/instruction.cc
index e784d8a..2d9ed19 100644
--- a/mpact/sim/decoder/instruction.cc
+++ b/mpact/sim/decoder/instruction.cc
@@ -98,7 +98,7 @@
 // Creating a derived instruction involves copying attributes and re-evaluating
 // any expressions that depend on any slot template instantiation values.
 absl::StatusOr<Instruction*> Instruction::CreateDerivedInstruction(
-    TemplateInstantiationArgs* args) const {
+    TemplateInstantiationArgs* args, Slot* new_slot) const {
   // First try to create a derived opcode object. Fail if it fails.
   auto op_result =
       slot_->instruction_set()->opcode_factory()->CreateDerivedOpcode(opcode(),
@@ -139,6 +139,7 @@
   for (auto const& [attr_name, expr_ptr] : attribute_map_) {
     auto result = expr_ptr->Evaluate(args);
     if (result.ok()) {
+      new_slot->AddAttributeName(attr_name);
       new_inst->AddInstructionAttribute(attr_name, result.value());
     } else {
       delete new_inst;
@@ -150,7 +151,7 @@
   // Recursively hande child instructions.
   if (child() == nullptr) return new_inst;
 
-  auto result = child()->CreateDerivedInstruction(args);
+  auto result = child()->CreateDerivedInstruction(args, new_slot);
   if (result.ok()) {
     new_inst->AppendChild(result.value());
     return new_inst;
diff --git a/mpact/sim/decoder/instruction.h b/mpact/sim/decoder/instruction.h
index e2f6563..9f89586 100644
--- a/mpact/sim/decoder/instruction.h
+++ b/mpact/sim/decoder/instruction.h
@@ -51,7 +51,7 @@
   // evaluation of expressions within the instruction/opcode that rely on
   // template instantiation arguments.
   absl::StatusOr<Instruction*> CreateDerivedInstruction(
-      TemplateInstantiationArgs* args) const;
+      TemplateInstantiationArgs* args, Slot* new_slot) const;
   // Resources used and acquired/released.
   void AppendResourceUse(const ResourceReference* resource_ref);
   void AppendResourceAcquire(const ResourceReference* resource_ref);
diff --git a/mpact/sim/decoder/instruction_set_visitor.cc b/mpact/sim/decoder/instruction_set_visitor.cc
index f70c5b3..d6a0b21 100644
--- a/mpact/sim/decoder/instruction_set_visitor.cc
+++ b/mpact/sim/decoder/instruction_set_visitor.cc
@@ -1328,16 +1328,24 @@
   if (inst != nullptr) {
     for (auto* child = inst; child != nullptr; child = child->child()) {
       for (auto& [name, expr] : attributes) {
-        child->AddInstructionAttribute(name, expr);
+        child->AddInstructionAttribute(
+            name, expr == nullptr ? nullptr : expr->DeepCopy());
       }
     }
     // Ownership of expr objects transferred to opcode.
+    for (auto& [unused, expr] : attributes) {
+      delete expr;
+    }
     attributes.clear();
     return;
   }
   // Attributes are default attributes for the current slot.
   for (auto& [name, expr] : attributes) {
-    slot->AddInstructionAttribute(name, expr);
+    slot->AddInstructionAttribute(name,
+                                  expr == nullptr ? nullptr : expr->DeepCopy());
+  }
+  for (auto& [unused, expr] : attributes) {
+    delete expr;
   }
   attributes.clear();
 }
diff --git a/mpact/sim/decoder/slot.cc b/mpact/sim/decoder/slot.cc
index 0c786ef..0a8bd0e 100644
--- a/mpact/sim/decoder/slot.cc
+++ b/mpact/sim/decoder/slot.cc
@@ -200,7 +200,7 @@
                                               TemplateInstantiationArgs* args) {
   std::string name = inst->opcode()->name();
   if (!instruction_map_.contains(name)) {
-    auto derived = inst->CreateDerivedInstruction(args);
+    auto derived = inst->CreateDerivedInstruction(args, this);
 
     if (derived.ok()) {
       if (!is_templated()) {
@@ -256,9 +256,7 @@
   int size = attribute_names_.size();
   if (size > 0) {
     // Allocate the array and initialize to zero.
-    absl::StrAppend(&output, "  int *attrs = new int[", size,
-                    "];\n"
-                    "  *attrs = {");
+    absl::StrAppend(&output, "  int *attrs = new int[", size, "]{");
     for (auto const& attribute_name : attribute_names_) {
       auto it = inst->attribute_map().find(attribute_name);
       if (it == inst->attribute_map().end()) {