This fixes two issues:

In the .isa parser, backslashes in disasm formats are filtered out as intended.

In the .bin_fmt parser, warnings are given if binary constants in constraints
are of different width than the field it is compared to.

PiperOrigin-RevId: 671858831
Change-Id: Icf660504726eb02b64c54ad0111756d653122246
diff --git a/mpact/sim/decoder/bin_format_visitor.cc b/mpact/sim/decoder/bin_format_visitor.cc
index dbaef12..605b0f5 100644
--- a/mpact/sim/decoder/bin_format_visitor.cc
+++ b/mpact/sim/decoder/bin_format_visitor.cc
@@ -763,7 +763,7 @@
   if (format == nullptr) return;
   // Add constraints to the instruction encoding.
   for (auto *constraint : ctx->field_constraint_list()->field_constraint()) {
-    VisitConstraint(constraint, inst_encoding);
+    VisitConstraint(format, constraint, inst_encoding);
   }
 }
 
@@ -921,7 +921,7 @@
   return generated;
 }
 
-void BinFormatVisitor::VisitConstraint(FieldConstraintCtx *ctx,
+void BinFormatVisitor::VisitConstraint(Format *format, FieldConstraintCtx *ctx,
                                        InstructionEncoding *inst_encoding) {
   if (ctx == nullptr) return;
   if (inst_encoding == nullptr) return;
@@ -929,6 +929,29 @@
   // Constraints are based on field names ==/!=/>/>=/</<= to a value.
   std::string field_name = ctx->field_name->getText();
   std::string op = ctx->constraint_op()->getText();
+  // If the number is binary, let's get its length too and check against the
+  // field width.
+  if (ctx->number()->BIN_NUMBER() != nullptr) {
+    int length = ParseBinaryNum(ctx->number()->BIN_NUMBER()).width;
+    auto *field = format->GetField(field_name);
+    auto *overlay = format->GetOverlay(field_name);
+    if (field != nullptr) {
+      if (field->width != length) {
+        error_listener_->semanticWarning(
+            ctx->start,
+            absl::StrCat("Field '", field_name, "' has width ", field->width,
+                         " but constraint value is ", length, " bits"));
+      }
+    } else if (overlay != nullptr) {
+      if (overlay->computed_width() != length) {
+        error_listener_->semanticWarning(
+            ctx->start,
+            absl::StrCat("Overlay '", field_name, "' has width ",
+                         overlay->computed_width(), " but constraint value is ",
+                         length, " bits"));
+      }
+    }
+  }
   int value = ConvertToInt(ctx->number());
   absl::Status status;
   if (op == "==") {
diff --git a/mpact/sim/decoder/bin_format_visitor.h b/mpact/sim/decoder/bin_format_visitor.h
index fb41348..68ac713 100644
--- a/mpact/sim/decoder/bin_format_visitor.h
+++ b/mpact/sim/decoder/bin_format_visitor.h
@@ -124,7 +124,7 @@
   std::string GenerateInstructionDefList(
       const std::vector<RangeAssignmentInfo *> &range_info_vec, int index,
       const std::string &template_str_in) const;
-  void VisitConstraint(FieldConstraintCtx *ctx,
+  void VisitConstraint(Format *format, FieldConstraintCtx *ctx,
                        InstructionEncoding *inst_encoding);
 
   // Accessors.
diff --git a/mpact/sim/decoder/instruction_set_visitor.cc b/mpact/sim/decoder/instruction_set_visitor.cc
index c8acd80..31f9792 100644
--- a/mpact/sim/decoder/instruction_set_visitor.cc
+++ b/mpact/sim/decoder/instruction_set_visitor.cc
@@ -16,11 +16,12 @@
 
 #include <cctype>
 #include <cstddef>
-#include <filesystem>
+#include <filesystem>  // NOLINT: third party.
 #include <fstream>
 #include <iostream>
 #include <istream>
 #include <memory>
+#include <new>
 #include <optional>
 #include <string>
 #include <utility>
@@ -214,7 +215,7 @@
     PerformBundleReferenceChecks(instruction_set, bundle_ref);
   }
   // Verify that all the slot uses were declared.
-  for (auto [slot_name, instance_vec] : bundle->slot_uses()) {
+  for (auto &[slot_name, instance_vec] : bundle->slot_uses()) {
     Slot *slot = instruction_set->GetSlot(slot_name);
     // Verify that the instance number of the slot falls within valid range.
     for (auto &instance_number : instance_vec) {
@@ -1701,8 +1702,13 @@
   DisasmFormat *disasm_fmt = new DisasmFormat();
   while ((pos != std::string::npos) &&
          ((pos = format.find_first_of('%', pos)) != std::string::npos)) {
-    disasm_fmt->format_fragment_vec.push_back(format.substr(prev, pos - prev));
     std::string text = format.substr(prev, pos - prev);
+    std::string new_text;
+    for (auto &c : text) {
+      if (c == '\\') continue;
+      new_text.push_back(c);
+    }
+    disasm_fmt->format_fragment_vec.push_back(new_text);
     pos++;
     if (pos >= length) break;
 
@@ -1790,7 +1796,17 @@
         absl::StrCat("Unexpected end of format string in '", format, "'"));
   }
   if (prev != std::string::npos) {
-    disasm_fmt->format_fragment_vec.push_back(format.substr(prev));
+    std::string text = format.substr(prev);
+    std::string new_text;
+    for (auto &c : text) {
+      if (c == '\\') continue;
+      new_text.push_back(c);
+    }
+    disasm_fmt->format_fragment_vec.push_back(new_text);
+  }
+  std::string str;
+  for (auto &s : disasm_fmt->format_fragment_vec) {
+    absl::StrAppend(&str, s, ":");
   }
   int width = 0;
   auto count = inst->disasm_format_vec().size();