[llvm] [AsmParser][NFCI] Restructure DiagnosticPredicate (PR #126653)
Sam Elliott via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 11 22:55:28 PST 2025
https://github.com/lenary updated https://github.com/llvm/llvm-project/pull/126653
>From 45ce215f07c702e26fb3e8a3c419c2b5dbaed8d6 Mon Sep 17 00:00:00 2001
From: Sam Elliott <quic_aelliott at quicinc.com>
Date: Mon, 10 Feb 2025 18:03:26 -0800
Subject: [PATCH 1/4] [AsmParser][NFCI] Restructure DiagnosticPredicate
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.
---
.../llvm/MC/MCParser/MCTargetAsmParser.h | 43 +++---
.../AArch64/AsmParser/AArch64AsmParser.cpp | 126 +++++++++---------
2 files changed, 90 insertions(+), 79 deletions(-)
diff --git a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
index 4c88448e6a128..c856d9f68b482 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 335b46b76688f..38963810e28d6 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 {
>From ae057a523991f1b22a33355d4317f01b6b9d6d9b Mon Sep 17 00:00:00 2001
From: Sam Elliott <quic_aelliott at quicinc.com>
Date: Mon, 10 Feb 2025 18:23:21 -0800
Subject: [PATCH 2/4] fixup! [AsmParser][NFCI] Restructure DiagnosticPredicate
---
llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
index c856d9f68b482..65d255fe13145 100644
--- a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
+++ b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
@@ -192,7 +192,7 @@ class ParseStatus {
// This is a light-weight alternative to the 'NearMissInfo' approach
// 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).
+// PredicateMethods that return a 'bool' (match or near match).
class DiagnosticPredicate {
enum class PredicateTy {
Match, // Matches
>From 718623d28c82e69277d36ce5d0875efe95c89415 Mon Sep 17 00:00:00 2001
From: Sam Elliott <quic_aelliott at quicinc.com>
Date: Tue, 11 Feb 2025 22:54:21 -0800
Subject: [PATCH 3/4] fixup! [AsmParser][NFCI] Restructure DiagnosticPredicate
---
llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h | 3 ---
1 file changed, 3 deletions(-)
diff --git a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
index 65d255fe13145..2f7abc85bb59d 100644
--- a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
+++ b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
@@ -211,9 +211,6 @@ class DiagnosticPredicate {
constexpr DiagnosticPredicate(PredicateTy T) : Predicate(T) {}
- DiagnosticPredicate& operator=(const DiagnosticPredicate &) = default;
- DiagnosticPredicate(const DiagnosticPredicate &) = default;
-
explicit constexpr DiagnosticPredicate(bool Matches)
: Predicate(Matches ? Match : NearMatch) {}
>From a2d9088b9bb5cebbc4b96f74232f12432ae4e67a Mon Sep 17 00:00:00 2001
From: Sam Elliott <quic_aelliott at quicinc.com>
Date: Tue, 11 Feb 2025 22:55:13 -0800
Subject: [PATCH 4/4] Make operator bool() explicit
---
llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h | 3 +--
llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp | 4 +++-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
index 2f7abc85bb59d..2e3705d24f94e 100644
--- a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
+++ b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
@@ -213,8 +213,7 @@ class DiagnosticPredicate {
explicit constexpr DiagnosticPredicate(bool Matches)
: Predicate(Matches ? Match : NearMatch) {}
-
- operator bool() const { return Predicate == Match; }
+ explicit operator bool() const { return Predicate == Match; }
constexpr bool isMatch() const { return Predicate == Match; }
constexpr bool isNearMatch() const { return Predicate == NearMatch; }
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index 38963810e28d6..f2d206b864f35 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -814,7 +814,9 @@ class AArch64Operand : public MCParsedAsmOperand {
return (Val >= 0 && Val < 64);
}
- template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
+ template <int Width> DiagnosticPredicate isSImm() const {
+ return isSImmScaled<Width, 1>();
+ }
template <int Bits, int Scale> DiagnosticPredicate isSImmScaled() const {
return isImmScaled<Bits, Scale>(true);
More information about the llvm-commits
mailing list