Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 28 additions & 19 deletions llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -198,21 +192,36 @@ enum class DiagnosticPredicateTy {
// 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).
struct DiagnosticPredicate {
DiagnosticPredicateTy Type;

explicit DiagnosticPredicate(bool Match)
: Type(Match ? DiagnosticPredicateTy::Match
: DiagnosticPredicateTy::NearMatch) {}
DiagnosticPredicate(DiagnosticPredicateTy T) : Type(T) {}
DiagnosticPredicate(const DiagnosticPredicate &) = default;
// PredicateMethods that return a 'bool' (match or near match).
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) {}

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
Expand Down
126 changes: 64 additions & 62 deletions llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -833,15 +833,15 @@ 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())
Val = getFirstImmVal();
else {
const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
if (!MCE)
return DiagnosticPredicateTy::NoMatch;
return DiagnosticPredicate::NoMatch;
Val = MCE->getValue();
}

Expand All @@ -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 {
Expand Down Expand Up @@ -1057,41 +1057,41 @@ 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;
if (auto ShiftedImm = getShiftedVal<8>())
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
// 16 bits or higher it may also be a signed multiple of 256 in the
// 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;
if (auto ShiftedImm = getShiftedVal<8>())
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; }
Expand Down Expand Up @@ -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,
Expand All @@ -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
Expand All @@ -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 {
Expand Down Expand Up @@ -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 {
Expand All @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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; }
Expand All @@ -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.
Expand All @@ -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;
}

Expand Down Expand Up @@ -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 {
Expand Down