[llvm] a92bcb2 - [SPARC][IAS] Reject unknown/unavailable mnemonics early in ParseInstruction
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 10 21:33:22 PDT 2024
Author: Koakuma
Date: 2024-07-11T11:33:19+07:00
New Revision: a92bcb20b8cfeb74852ccade1651cdf4d1f296de
URL: https://github.com/llvm/llvm-project/commit/a92bcb20b8cfeb74852ccade1651cdf4d1f296de
DIFF: https://github.com/llvm/llvm-project/commit/a92bcb20b8cfeb74852ccade1651cdf4d1f296de.diff
LOG: [SPARC][IAS] Reject unknown/unavailable mnemonics early in ParseInstruction
Validate and reject any unknown or unavailable instruction mnemonics early
in ParseInstruction, before any operand parsing is performed. Some operands
(mainly memory ones) can be parsed slightly differently in V8 and V9
assembly language, so by rejecting unknown or unavailable instructions early
we can prevent the error message from being shadowed by the one raised during
operand parsing.
As a side effect this also allows us to tell unknown and unavailable
mnemonics apart, and issue a suggestion in appropriate cases.
This is based on the approach taken by the MIPS backend.
Reviewers: brad0, rorth, s-barannikov, jrtc27
Reviewed By: s-barannikov
Pull Request: https://github.com/llvm/llvm-project/pull/96021
Added:
Modified:
llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
llvm/test/MC/Sparc/sparc-asm-errors.s
llvm/test/MC/Sparc/sparc-cas-instructions.s
llvm/test/MC/Sparc/sparcv9-instructions.s
Removed:
################################################################################
diff --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
index af634a7da71c8..c1200df5d44dd 100644
--- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
+++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
@@ -116,6 +116,9 @@ class SparcAsmParser : public MCTargetAsmParser {
// Helper function to see if current token can start an expression.
bool isPossibleExpression(const AsmToken &Token);
+ // Check if mnemonic is valid.
+ MatchResultTy mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);
+
// returns true if Tok is matched to a register and returns register in RegNo.
MCRegister matchRegisterName(const AsmToken &Tok, unsigned &RegKind);
@@ -601,6 +604,45 @@ class SparcOperand : public MCParsedAsmOperand {
} // end anonymous namespace
+#define GET_MATCHER_IMPLEMENTATION
+#define GET_REGISTER_MATCHER
+#define GET_MNEMONIC_SPELL_CHECKER
+#include "SparcGenAsmMatcher.inc"
+
+// Use a custom function instead of the one from SparcGenAsmMatcher
+// so we can
diff erentiate between unavailable and unknown instructions.
+SparcAsmParser::MatchResultTy
+SparcAsmParser::mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) {
+ // Process all MnemonicAliases to remap the mnemonic.
+ applyMnemonicAliases(Mnemonic, getAvailableFeatures(), VariantID);
+
+ // Find the appropriate table for this asm variant.
+ const MatchEntry *Start, *End;
+ switch (VariantID) {
+ default:
+ llvm_unreachable("invalid variant!");
+ case 0:
+ Start = std::begin(MatchTable0);
+ End = std::end(MatchTable0);
+ break;
+ }
+
+ // Search the table.
+ auto MnemonicRange = std::equal_range(Start, End, Mnemonic, LessOpcode());
+
+ if (MnemonicRange.first == MnemonicRange.second)
+ return Match_MnemonicFail;
+
+ for (const MatchEntry *it = MnemonicRange.first, *ie = MnemonicRange.second;
+ it != ie; ++it) {
+ const FeatureBitset &RequiredFeatures =
+ FeatureBitsets[it->RequiredFeaturesIdx];
+ if ((getAvailableFeatures() & RequiredFeatures) == RequiredFeatures)
+ return Match_Success;
+ }
+ return Match_MissingFeature;
+}
+
bool SparcAsmParser::expandSET(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions) {
MCOperand MCRegOp = Inst.getOperand(0);
@@ -829,13 +871,32 @@ ParseStatus SparcAsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
return ParseStatus::NoMatch;
}
-static void applyMnemonicAliases(StringRef &Mnemonic,
- const FeatureBitset &Features,
- unsigned VariantID);
-
bool SparcAsmParser::ParseInstruction(ParseInstructionInfo &Info,
StringRef Name, SMLoc NameLoc,
OperandVector &Operands) {
+ // Validate and reject unavailable mnemonics early before
+ // running any operand parsing.
+ // This is needed because some operands (mainly memory ones)
+ //
diff er between V8 and V9 ISA and so any operand parsing errors
+ // will cause IAS to bail out before it reaches MatchAndEmitInstruction
+ // (where the instruction as a whole, including the mnemonic, is validated
+ // once again just before emission).
+ // As a nice side effect this also allows us to reject unknown
+ // instructions and suggest replacements.
+ MatchResultTy MS = mnemonicIsValid(Name, 0);
+ switch (MS) {
+ case Match_Success:
+ break;
+ case Match_MissingFeature:
+ return Error(NameLoc,
+ "instruction requires a CPU feature not currently enabled");
+ case Match_MnemonicFail:
+ return Error(NameLoc,
+ "invalid instruction mnemonic" +
+ SparcMnemonicSpellCheck(Name, getAvailableFeatures(), 0));
+ default:
+ llvm_unreachable("invalid return status!");
+ }
// First operand in MCInst is instruction mnemonic.
Operands.push_back(SparcOperand::CreateToken(Name, NameLoc));
@@ -1378,9 +1439,6 @@ ParseStatus SparcAsmParser::parseExpression(int64_t &Val) {
return getParser().parseAbsoluteExpression(Val);
}
-#define GET_REGISTER_MATCHER
-#include "SparcGenAsmMatcher.inc"
-
MCRegister SparcAsmParser::matchRegisterName(const AsmToken &Tok,
unsigned &RegKind) {
RegKind = SparcOperand::rk_None;
@@ -1628,9 +1686,6 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSparcAsmParser() {
RegisterMCAsmParser<SparcAsmParser> C(getTheSparcelTarget());
}
-#define GET_MATCHER_IMPLEMENTATION
-#include "SparcGenAsmMatcher.inc"
-
unsigned SparcAsmParser::validateTargetOperandClass(MCParsedAsmOperand &GOp,
unsigned Kind) {
SparcOperand &Op = (SparcOperand &)GOp;
diff --git a/llvm/test/MC/Sparc/sparc-asm-errors.s b/llvm/test/MC/Sparc/sparc-asm-errors.s
index 780f4e7fad787..655fd15e3962f 100644
--- a/llvm/test/MC/Sparc/sparc-asm-errors.s
+++ b/llvm/test/MC/Sparc/sparc-asm-errors.s
@@ -7,7 +7,7 @@
! CHECK: argument must be between
set 4294967296, %o1
- ! V8: unexpected token
+ ! V8: instruction requires a CPU feature not currently enabled
! V9: unknown membar tag
membar #BadTag
diff --git a/llvm/test/MC/Sparc/sparc-cas-instructions.s b/llvm/test/MC/Sparc/sparc-cas-instructions.s
index 30ce3fd0b2d22..fde3a8dd26056 100644
--- a/llvm/test/MC/Sparc/sparc-cas-instructions.s
+++ b/llvm/test/MC/Sparc/sparc-cas-instructions.s
@@ -22,9 +22,9 @@ casx [%i0], %l6, %o2
! LEON: error: instruction requires a CPU feature not currently enabled
casxl [%i0], %l6, %o2
-! V8: error: malformed ASI tag, must be a constant integer expression
+! V8: error: instruction requires a CPU feature not currently enabled
! V9: casxa [%i0] %asi, %l6, %o2 ! encoding: [0xd5,0xf6,0x20,0x16]
-! LEON: error: malformed ASI tag, must be a constant integer expression
+! LEON: error: instruction requires a CPU feature not currently enabled
casxa [%i0] %asi, %l6, %o2
! V8: error: instruction requires a CPU feature not currently enabled
@@ -37,7 +37,7 @@ casxa [%i0] 0x80, %l6, %o2
! LEON: error: instruction requires a CPU feature not currently enabled
casxa [%i0] (0x40+0x40), %l6, %o2
-! V8: error: malformed ASI tag, must be a constant integer expression
+! V8: error: instruction requires a CPU feature not currently enabled
! V9: casa [%i0] %asi, %l6, %o2 ! encoding: [0xd5,0xe6,0x20,0x16]
! LEON: error: malformed ASI tag, must be a constant integer expression
casa [%i0] %asi, %l6, %o2
diff --git a/llvm/test/MC/Sparc/sparcv9-instructions.s b/llvm/test/MC/Sparc/sparcv9-instructions.s
index a7761c10c509b..1c174f399ed34 100644
--- a/llvm/test/MC/Sparc/sparcv9-instructions.s
+++ b/llvm/test/MC/Sparc/sparcv9-instructions.s
@@ -537,142 +537,142 @@
! V9: stxa %g0, [%g2+%i5] #ASI_SNF ! encoding: [0xc0,0xf0,0x90,0x7d]
stxa %g0, [%g2 + %i5] #ASI_SNF
- ! V8: error: invalid operand for instruction
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + 0xf80 ], 1
! V9: prefetch [%i1+3968], #one_read ! encoding: [0xc3,0x6e,0x6f,0x80]
prefetch [ %i1 + 0xf80 ], 1
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + 0xf80 ], #n_reads
! V9: prefetch [%i1+3968], #n_reads ! encoding: [0xc1,0x6e,0x6f,0x80]
prefetch [ %i1 + 0xf80 ], #n_reads
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + 0xf80 ], #one_read
! V9: prefetch [%i1+3968], #one_read ! encoding: [0xc3,0x6e,0x6f,0x80]
prefetch [ %i1 + 0xf80 ], #one_read
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + 0xf80 ], #n_writes
! V9: prefetch [%i1+3968], #n_writes ! encoding: [0xc5,0x6e,0x6f,0x80]
prefetch [ %i1 + 0xf80 ], #n_writes
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + 0xf80 ], #one_write
! V9: prefetch [%i1+3968], #one_write ! encoding: [0xc7,0x6e,0x6f,0x80]
prefetch [ %i1 + 0xf80 ], #one_write
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + 0xf80 ], #page
! V9: prefetch [%i1+3968], #page ! encoding: [0xc9,0x6e,0x6f,0x80]
prefetch [ %i1 + 0xf80 ], #page
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + 0xf80 ], #unified
! V9: prefetch [%i1+3968], #unified ! encoding: [0xe3,0x6e,0x6f,0x80]
prefetch [ %i1 + 0xf80 ], #unified
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + 0xf80 ], #n_reads_strong
! V9: prefetch [%i1+3968], #n_reads_strong ! encoding: [0xe9,0x6e,0x6f,0x80]
prefetch [ %i1 + 0xf80 ], #n_reads_strong
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + 0xf80 ], #one_read_strong
! V9: prefetch [%i1+3968], #one_read_strong ! encoding: [0xeb,0x6e,0x6f,0x80]
prefetch [ %i1 + 0xf80 ], #one_read_strong
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + 0xf80 ], #n_writes_strong
! V9: prefetch [%i1+3968], #n_writes_strong ! encoding: [0xed,0x6e,0x6f,0x80]
prefetch [ %i1 + 0xf80 ], #n_writes_strong
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + 0xf80 ], #one_write_strong
! V9: prefetch [%i1+3968], #one_write_strong ! encoding: [0xef,0x6e,0x6f,0x80]
prefetch [ %i1 + 0xf80 ], #one_write_strong
- ! V8: error: invalid operand for instruction
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + %i2 ], 1
! V9: prefetch [%i1+%i2], #one_read ! encoding: [0xc3,0x6e,0x40,0x1a]
prefetch [ %i1 + %i2 ], 1
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + %i2 ], #n_reads
! V9: prefetch [%i1+%i2], #n_reads ! encoding: [0xc1,0x6e,0x40,0x1a]
prefetch [ %i1 + %i2 ], #n_reads
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + %i2 ], #one_read
! V9: prefetch [%i1+%i2], #one_read ! encoding: [0xc3,0x6e,0x40,0x1a]
prefetch [ %i1 + %i2 ], #one_read
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + %i2 ], #n_writes
! V9: prefetch [%i1+%i2], #n_writes ! encoding: [0xc5,0x6e,0x40,0x1a]
prefetch [ %i1 + %i2 ], #n_writes
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + %i2 ], #one_write
! V9: prefetch [%i1+%i2], #one_write ! encoding: [0xc7,0x6e,0x40,0x1a]
prefetch [ %i1 + %i2 ], #one_write
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + %i2 ], #page
! V9: prefetch [%i1+%i2], #page ! encoding: [0xc9,0x6e,0x40,0x1a]
prefetch [ %i1 + %i2 ], #page
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + %i2 ], #unified
! V9: prefetch [%i1+%i2], #unified ! encoding: [0xe3,0x6e,0x40,0x1a]
prefetch [ %i1 + %i2 ], #unified
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + %i2 ], #n_reads_strong
! V9: prefetch [%i1+%i2], #n_reads_strong ! encoding: [0xe9,0x6e,0x40,0x1a]
prefetch [ %i1 + %i2 ], #n_reads_strong
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + %i2 ], #one_read_strong
! V9: prefetch [%i1+%i2], #one_read_strong ! encoding: [0xeb,0x6e,0x40,0x1a]
prefetch [ %i1 + %i2 ], #one_read_strong
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + %i2 ], #n_writes_strong
! V9: prefetch [%i1+%i2], #n_writes_strong ! encoding: [0xed,0x6e,0x40,0x1a]
prefetch [ %i1 + %i2 ], #n_writes_strong
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetch [ %i1 + %i2 ], #one_write_strong
! V9: prefetch [%i1+%i2], #one_write_strong ! encoding: [0xef,0x6e,0x40,0x1a]
prefetch [ %i1 + %i2 ], #one_write_strong
- ! V8: error: malformed ASI tag, must be a constant integer expression
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetcha [ %i1 + 0xf80 ] %asi, 1
! V9: prefetcha [%i1+3968] %asi, #one_read ! encoding: [0xc3,0xee,0x6f,0x80]
prefetcha [ %i1 + 0xf80 ] %asi, 1
- ! V8: error: malformed ASI tag, must be a constant integer expression
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetcha [ %i1 + 0xf80 ] %asi, #one_read
! V9: prefetcha [%i1+3968] %asi, #one_read ! encoding: [0xc3,0xee,0x6f,0x80]
prefetcha [ %i1 + 0xf80 ] %asi, #one_read
- ! V8: error: invalid operand for instruction
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetcha [ %i1 + %i2 ] #ASI_SNF, 1
! V9: prefetcha [%i1+%i2] #ASI_SNF, #one_read ! encoding: [0xc3,0xee,0x50,0x7a]
prefetcha [ %i1 + %i2 ] #ASI_SNF, 1
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetcha [ %i1 + %i2 ] #ASI_SNF, #one_read
! V9: prefetcha [%i1+%i2] #ASI_SNF, #one_read ! encoding: [0xc3,0xee,0x50,0x7a]
prefetcha [ %i1 + %i2 ] #ASI_SNF, #one_read
- ! V8: error: invalid operand for instruction
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetcha [ %i1 + %i2 ] 131, 1
! V9: prefetcha [%i1+%i2] #ASI_SNF, #one_read ! encoding: [0xc3,0xee,0x50,0x7a]
prefetcha [ %i1 + %i2 ] 131, 1
- ! V8: error: unexpected token
+ ! V8: error: instruction requires a CPU feature not currently enabled
! V8-NEXT: prefetcha [ %i1 + %i2 ] 131, #one_read
! V9: prefetcha [%i1+%i2] #ASI_SNF, #one_read ! encoding: [0xc3,0xee,0x50,0x7a]
prefetcha [ %i1 + %i2 ] 131, #one_read
More information about the llvm-commits
mailing list