Skip to content

[AsmParser][NFCI] Restructure DiagnosticPredicate #126653

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Feb 14, 2025

Conversation

lenary
Copy link
Member

@lenary lenary commented Feb 11, 2025

This restructures the DiagnosticPredicate type to more closely match how neatly ParseStatus is defined. The DiagnosticPredicateTy enum is moved inside the class, but is exposed with constexpr/using so that references don't have to be so long.

The main user of this code is AArch64, which I have also updated to use the new structure of the code.

This restructures the DiagnosticPredicate type to more closely match how
neatly ParseStatus is defined. The DiagnosticPredicateTy enum is moved
inside the class, but is exposed with constexpr/using so that references
don't have to be so long.

The main user of this code is AArch64, which I have also updated to use
the new structure of the code.
@llvmbot
Copy link
Member

llvmbot commented Feb 11, 2025

@llvm/pr-subscribers-mc

@llvm/pr-subscribers-backend-aarch64

Author: Sam Elliott (lenary)

Changes

This restructures the DiagnosticPredicate type to more closely match how neatly ParseStatus is defined. The DiagnosticPredicateTy enum is moved inside the class, but is exposed with constexpr/using so that references don't have to be so long.

The main user of this code is AArch64, which I have also updated to use the new structure of the code.


Full diff: https://github.com/llvm/llvm-project/pull/126653.diff

2 Files Affected:

  • (modified) llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h (+26-17)
  • (modified) llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp (+64-62)
diff --git a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
index 4c88448e6a1285a..c856d9f68b4822c 100644
--- a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
+++ b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
@@ -167,12 +167,6 @@ class ParseStatus {
   }
 };
 
-enum class DiagnosticPredicateTy {
-  Match,
-  NearMatch,
-  NoMatch,
-};
-
 // When an operand is parsed, the assembler will try to iterate through a set of
 // possible operand classes that the operand might match and call the
 // corresponding PredicateMethod to determine that.
@@ -199,20 +193,35 @@ enum class DiagnosticPredicateTy {
 // below which collects *all* possible diagnostics. This alternative
 // is optional and fully backward compatible with existing
 // PredicateMethods that return a 'bool' (match or no match).
-struct DiagnosticPredicate {
-  DiagnosticPredicateTy Type;
+class DiagnosticPredicate {
+  enum class PredicateTy {
+    Match,     // Matches
+    NearMatch, // Close Match: use Specific Diagnostic
+    NoMatch,   // No Match: use `InvalidOperand`
+  } Predicate;
+
+public:
+#if __cplusplus >= 202002L
+  using enum PredicateTy;
+#else
+  static constexpr PredicateTy Match = PredicateTy::Match;
+  static constexpr PredicateTy NearMatch = PredicateTy::NearMatch;
+  static constexpr PredicateTy NoMatch = PredicateTy::NoMatch;
+#endif
+
+  constexpr DiagnosticPredicate(PredicateTy T) : Predicate(T) {}
 
-  explicit DiagnosticPredicate(bool Match)
-      : Type(Match ? DiagnosticPredicateTy::Match
-                   : DiagnosticPredicateTy::NearMatch) {}
-  DiagnosticPredicate(DiagnosticPredicateTy T) : Type(T) {}
-  DiagnosticPredicate(const DiagnosticPredicate &) = default;
   DiagnosticPredicate& operator=(const DiagnosticPredicate &) = default;
+  DiagnosticPredicate(const DiagnosticPredicate &) = default;
+
+  explicit constexpr DiagnosticPredicate(bool Matches)
+      : Predicate(Matches ? Match : NearMatch) {}
+
+  operator bool() const { return Predicate == Match; }
 
-  operator bool() const { return Type == DiagnosticPredicateTy::Match; }
-  bool isMatch() const { return Type == DiagnosticPredicateTy::Match; }
-  bool isNearMatch() const { return Type == DiagnosticPredicateTy::NearMatch; }
-  bool isNoMatch() const { return Type == DiagnosticPredicateTy::NoMatch; }
+  constexpr bool isMatch() const { return Predicate == Match; }
+  constexpr bool isNearMatch() const { return Predicate == NearMatch; }
+  constexpr bool isNoMatch() const { return Predicate == NoMatch; }
 };
 
 // When matching of an assembly instruction fails, there may be multiple
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 335b46b76688fa4..38963810e28d637 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -824,7 +824,7 @@ class AArch64Operand : public MCParsedAsmOperand {
   DiagnosticPredicate isUImmScaled() const {
     if (IsRange && isImmRange() &&
         (getLastImmVal() != getFirstImmVal() + Offset))
-      return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::NoMatch;
 
     return isImmScaled<Bits, Scale, IsRange>(false);
   }
@@ -833,7 +833,7 @@ class AArch64Operand : public MCParsedAsmOperand {
   DiagnosticPredicate isImmScaled(bool Signed) const {
     if ((!isImm() && !isImmRange()) || (isImm() && IsRange) ||
         (isImmRange() && !IsRange))
-      return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::NoMatch;
 
     int64_t Val;
     if (isImmRange())
@@ -841,7 +841,7 @@ class AArch64Operand : public MCParsedAsmOperand {
     else {
       const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
       if (!MCE)
-        return DiagnosticPredicateTy::NoMatch;
+        return DiagnosticPredicate::NoMatch;
       Val = MCE->getValue();
     }
 
@@ -856,33 +856,33 @@ class AArch64Operand : public MCParsedAsmOperand {
     }
 
     if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
-      return DiagnosticPredicateTy::Match;
+      return DiagnosticPredicate::Match;
 
-    return DiagnosticPredicateTy::NearMatch;
+    return DiagnosticPredicate::NearMatch;
   }
 
   DiagnosticPredicate isSVEPattern() const {
     if (!isImm())
-      return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::NoMatch;
     auto *MCE = dyn_cast<MCConstantExpr>(getImm());
     if (!MCE)
-      return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::NoMatch;
     int64_t Val = MCE->getValue();
     if (Val >= 0 && Val < 32)
-      return DiagnosticPredicateTy::Match;
-    return DiagnosticPredicateTy::NearMatch;
+      return DiagnosticPredicate::Match;
+    return DiagnosticPredicate::NearMatch;
   }
 
   DiagnosticPredicate isSVEVecLenSpecifier() const {
     if (!isImm())
-      return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::NoMatch;
     auto *MCE = dyn_cast<MCConstantExpr>(getImm());
     if (!MCE)
-      return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::NoMatch;
     int64_t Val = MCE->getValue();
     if (Val >= 0 && Val <= 1)
-      return DiagnosticPredicateTy::Match;
-    return DiagnosticPredicateTy::NearMatch;
+      return DiagnosticPredicate::Match;
+    return DiagnosticPredicate::NearMatch;
   }
 
   bool isSymbolicUImm12Offset(const MCExpr *Expr) const {
@@ -1057,7 +1057,7 @@ class AArch64Operand : public MCParsedAsmOperand {
   template <typename T>
   DiagnosticPredicate isSVECpyImm() const {
     if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
-      return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::NoMatch;
 
     bool IsByte = std::is_same<int8_t, std::make_signed_t<T>>::value ||
                   std::is_same<int8_t, T>::value;
@@ -1065,9 +1065,9 @@ class AArch64Operand : public MCParsedAsmOperand {
       if (!(IsByte && ShiftedImm->second) &&
           AArch64_AM::isSVECpyImm<T>(uint64_t(ShiftedImm->first)
                                      << ShiftedImm->second))
-        return DiagnosticPredicateTy::Match;
+        return DiagnosticPredicate::Match;
 
-    return DiagnosticPredicateTy::NearMatch;
+    return DiagnosticPredicate::NearMatch;
   }
 
   // Unsigned value in the range 0 to 255. For element widths of
@@ -1075,7 +1075,7 @@ class AArch64Operand : public MCParsedAsmOperand {
   // range 0 to 65280.
   template <typename T> DiagnosticPredicate isSVEAddSubImm() const {
     if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
-      return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::NoMatch;
 
     bool IsByte = std::is_same<int8_t, std::make_signed_t<T>>::value ||
                   std::is_same<int8_t, T>::value;
@@ -1083,15 +1083,15 @@ class AArch64Operand : public MCParsedAsmOperand {
       if (!(IsByte && ShiftedImm->second) &&
           AArch64_AM::isSVEAddSubImm<T>(ShiftedImm->first
                                         << ShiftedImm->second))
-        return DiagnosticPredicateTy::Match;
+        return DiagnosticPredicate::Match;
 
-    return DiagnosticPredicateTy::NearMatch;
+    return DiagnosticPredicate::NearMatch;
   }
 
   template <typename T> DiagnosticPredicate isSVEPreferredLogicalImm() const {
     if (isLogicalImm<T>() && !isSVECpyImm<T>())
-      return DiagnosticPredicateTy::Match;
-    return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::Match;
+    return DiagnosticPredicate::NoMatch;
   }
 
   bool isCondCode() const { return Kind == k_CondCode; }
@@ -1319,48 +1319,48 @@ class AArch64Operand : public MCParsedAsmOperand {
   template <int ElementWidth, unsigned Class>
   DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
     if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
-      return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::NoMatch;
 
     if (isSVEVectorReg<Class>() && (Reg.ElementWidth == ElementWidth))
-      return DiagnosticPredicateTy::Match;
+      return DiagnosticPredicate::Match;
 
-    return DiagnosticPredicateTy::NearMatch;
+    return DiagnosticPredicate::NearMatch;
   }
 
   template <int ElementWidth, unsigned Class>
   DiagnosticPredicate isSVEPredicateOrPredicateAsCounterRegOfWidth() const {
     if (Kind != k_Register || (Reg.Kind != RegKind::SVEPredicateAsCounter &&
                                Reg.Kind != RegKind::SVEPredicateVector))
-      return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::NoMatch;
 
     if ((isSVEPredicateAsCounterReg<Class>() ||
          isSVEPredicateVectorRegOfWidth<ElementWidth, Class>()) &&
         Reg.ElementWidth == ElementWidth)
-      return DiagnosticPredicateTy::Match;
+      return DiagnosticPredicate::Match;
 
-    return DiagnosticPredicateTy::NearMatch;
+    return DiagnosticPredicate::NearMatch;
   }
 
   template <int ElementWidth, unsigned Class>
   DiagnosticPredicate isSVEPredicateAsCounterRegOfWidth() const {
     if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateAsCounter)
-      return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::NoMatch;
 
     if (isSVEPredicateAsCounterReg<Class>() && (Reg.ElementWidth == ElementWidth))
-      return DiagnosticPredicateTy::Match;
+      return DiagnosticPredicate::Match;
 
-    return DiagnosticPredicateTy::NearMatch;
+    return DiagnosticPredicate::NearMatch;
   }
 
   template <int ElementWidth, unsigned Class>
   DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
     if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
-      return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::NoMatch;
 
     if (isSVEVectorReg<Class>() && Reg.ElementWidth == ElementWidth)
-      return DiagnosticPredicateTy::Match;
+      return DiagnosticPredicate::Match;
 
-    return DiagnosticPredicateTy::NearMatch;
+    return DiagnosticPredicate::NearMatch;
   }
 
   template <int ElementWidth, unsigned Class,
@@ -1369,7 +1369,7 @@ class AArch64Operand : public MCParsedAsmOperand {
   DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
     auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
     if (!VectorMatch.isMatch())
-      return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::NoMatch;
 
     // Give a more specific diagnostic when the user has explicitly typed in
     // a shift-amount that does not match what is expected, but for which
@@ -1378,12 +1378,12 @@ class AArch64Operand : public MCParsedAsmOperand {
     if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
                         ShiftExtendTy == AArch64_AM::SXTW) &&
         !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
-      return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::NoMatch;
 
     if (MatchShift && ShiftExtendTy == getShiftExtendType())
-      return DiagnosticPredicateTy::Match;
+      return DiagnosticPredicate::Match;
 
-    return DiagnosticPredicateTy::NearMatch;
+    return DiagnosticPredicate::NearMatch;
   }
 
   bool isGPR32as64() const {
@@ -1420,15 +1420,17 @@ class AArch64Operand : public MCParsedAsmOperand {
 
   template<int64_t Angle, int64_t Remainder>
   DiagnosticPredicate isComplexRotation() const {
-    if (!isImm()) return DiagnosticPredicateTy::NoMatch;
+    if (!isImm())
+      return DiagnosticPredicate::NoMatch;
 
     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
-    if (!CE) return DiagnosticPredicateTy::NoMatch;
+    if (!CE)
+      return DiagnosticPredicate::NoMatch;
     uint64_t Value = CE->getValue();
 
     if (Value % Angle == Remainder && Value <= 270)
-      return DiagnosticPredicateTy::Match;
-    return DiagnosticPredicateTy::NearMatch;
+      return DiagnosticPredicate::Match;
+    return DiagnosticPredicate::NearMatch;
   }
 
   template <unsigned RegClassID> bool isGPR64() const {
@@ -1439,12 +1441,12 @@ class AArch64Operand : public MCParsedAsmOperand {
   template <unsigned RegClassID, int ExtWidth>
   DiagnosticPredicate isGPR64WithShiftExtend() const {
     if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
-      return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::NoMatch;
 
     if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
         getShiftExtendAmount() == Log2_32(ExtWidth / 8))
-      return DiagnosticPredicateTy::Match;
-    return DiagnosticPredicateTy::NearMatch;
+      return DiagnosticPredicate::Match;
+    return DiagnosticPredicate::NearMatch;
   }
 
   /// Is this a vector list with the type implicit (presumably attached to the
@@ -1479,10 +1481,10 @@ class AArch64Operand : public MCParsedAsmOperand {
     bool Res =
         isTypedVectorList<VectorKind, NumRegs, NumElements, ElementWidth>();
     if (!Res)
-      return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::NoMatch;
     if (!AArch64MCRegisterClasses[RegClass].contains(VectorList.RegNum))
-      return DiagnosticPredicateTy::NearMatch;
-    return DiagnosticPredicateTy::Match;
+      return DiagnosticPredicate::NearMatch;
+    return DiagnosticPredicate::Match;
   }
 
   template <RegKind VectorKind, unsigned NumRegs, unsigned Stride,
@@ -1491,21 +1493,21 @@ class AArch64Operand : public MCParsedAsmOperand {
     bool Res = isTypedVectorList<VectorKind, NumRegs, /*NumElements*/ 0,
                                  ElementWidth, Stride>();
     if (!Res)
-      return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::NoMatch;
     if ((VectorList.RegNum < (AArch64::Z0 + Stride)) ||
         ((VectorList.RegNum >= AArch64::Z16) &&
          (VectorList.RegNum < (AArch64::Z16 + Stride))))
-      return DiagnosticPredicateTy::Match;
-    return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::Match;
+    return DiagnosticPredicate::NoMatch;
   }
 
   template <int Min, int Max>
   DiagnosticPredicate isVectorIndex() const {
     if (Kind != k_VectorIndex)
-      return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::NoMatch;
     if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
-      return DiagnosticPredicateTy::Match;
-    return DiagnosticPredicateTy::NearMatch;
+      return DiagnosticPredicate::Match;
+    return DiagnosticPredicate::NearMatch;
   }
 
   bool isToken() const override { return Kind == k_Token; }
@@ -1531,7 +1533,7 @@ class AArch64Operand : public MCParsedAsmOperand {
 
   template <unsigned ImmEnum> DiagnosticPredicate isExactFPImm() const {
     if (Kind != k_FPImm)
-      return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::NoMatch;
 
     if (getFPImmIsExact()) {
       // Lookup the immediate from table of supported immediates.
@@ -1546,19 +1548,19 @@ class AArch64Operand : public MCParsedAsmOperand {
         llvm_unreachable("FP immediate is not exact");
 
       if (getFPImm().bitwiseIsEqual(RealVal))
-        return DiagnosticPredicateTy::Match;
+        return DiagnosticPredicate::Match;
     }
 
-    return DiagnosticPredicateTy::NearMatch;
+    return DiagnosticPredicate::NearMatch;
   }
 
   template <unsigned ImmA, unsigned ImmB>
   DiagnosticPredicate isExactFPImm() const {
-    DiagnosticPredicate Res = DiagnosticPredicateTy::NoMatch;
+    DiagnosticPredicate Res = DiagnosticPredicate::NoMatch;
     if ((Res = isExactFPImm<ImmA>()))
-      return DiagnosticPredicateTy::Match;
+      return DiagnosticPredicate::Match;
     if ((Res = isExactFPImm<ImmB>()))
-      return DiagnosticPredicateTy::Match;
+      return DiagnosticPredicate::Match;
     return Res;
   }
 
@@ -1741,12 +1743,12 @@ class AArch64Operand : public MCParsedAsmOperand {
   template <MatrixKind Kind, unsigned EltSize, unsigned RegClass>
   DiagnosticPredicate isMatrixRegOperand() const {
     if (!isMatrix())
-      return DiagnosticPredicateTy::NoMatch;
+      return DiagnosticPredicate::NoMatch;
     if (getMatrixKind() != Kind ||
         !AArch64MCRegisterClasses[RegClass].contains(getMatrixReg()) ||
         EltSize != getMatrixElementWidth())
-      return DiagnosticPredicateTy::NearMatch;
-    return DiagnosticPredicateTy::Match;
+      return DiagnosticPredicate::NearMatch;
+    return DiagnosticPredicate::Match;
   }
 
   bool isPAuthPCRelLabel16Operand() const {

@lenary lenary added the mc Machine (object) code label Feb 11, 2025
@lenary
Copy link
Member Author

lenary commented Feb 11, 2025

The fixup contains a change to a comment to make it accurate with the existing behaviour.

Copy link
Contributor

@s-barannikov s-barannikov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link

github-actions bot commented Feb 12, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@lenary lenary merged commit bedd392 into llvm:main Feb 14, 2025
8 checks passed
@lenary lenary deleted the pr/diagnostic-predicate-ty-refactor branch February 14, 2025 17:30
joaosaffran pushed a commit to joaosaffran/llvm-project that referenced this pull request Feb 14, 2025
This restructures the DiagnosticPredicate type to more closely match how
neatly ParseStatus is defined. The DiagnosticPredicateTy enum is moved
inside the class, and the boolean conversions are made explicit.

The main user of this code is AArch64, which I have also updated to use
the new structure of the code.
sivan-shani pushed a commit to sivan-shani/llvm-project that referenced this pull request Feb 24, 2025
This restructures the DiagnosticPredicate type to more closely match how
neatly ParseStatus is defined. The DiagnosticPredicateTy enum is moved
inside the class, and the boolean conversions are made explicit.

The main user of this code is AArch64, which I have also updated to use
the new structure of the code.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:AArch64 mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants