[llvm-branch-commits] [llvm] [SPARC][IAS] Reject unknown/unavailable mnemonics early in ParseInstruction (PR #96021)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Jul 10 09:57:15 PDT 2024
https://github.com/koachan updated https://github.com/llvm/llvm-project/pull/96021
>From dbd8f1f421b397a4907af3811937a7815900876a Mon Sep 17 00:00:00 2001
From: Koakuma <koachan at protonmail.com>
Date: Wed, 10 Jul 2024 23:57:01 +0700
Subject: [PATCH] Don't use ParseForAllFeatures, validate all mnemonics up
front instead
Created using spr 1.3.5
---
.../Target/Sparc/AsmParser/SparcAsmParser.cpp | 78 ++++++++++++++++---
llvm/test/MC/Sparc/sparc-asm-errors.s | 4 +-
llvm/test/MC/Sparc/sparc-cas-instructions.s | 6 +-
llvm/test/MC/Sparc/sparcv9-instructions.s | 26 +++----
4 files changed, 84 insertions(+), 30 deletions(-)
diff --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
index e6728d0aae4e9..37f8a72bd4421 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 differentiate 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)
+ // differ 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,
+ "unknown instruction" +
+ SparcMnemonicSpellCheck(Name, getAvailableFeatures(), 0));
+ default:
+ llvm_unreachable("invalid return status!");
+ }
// First operand in MCInst is instruction mnemonic.
Operands.push_back(SparcOperand::CreateToken(Name, NameLoc));
@@ -1188,8 +1249,7 @@ ParseStatus SparcAsmParser::parseCallTarget(OperandVector &Operands) {
ParseStatus SparcAsmParser::parseOperand(OperandVector &Operands,
StringRef Mnemonic) {
- ParseStatus Res =
- MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
+ ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic);
// If there wasn't a custom match, try the generic matcher below. Otherwise,
// there was a match, but an error occurred, in which case, just return that
@@ -1379,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;
@@ -1629,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 2b3a2eb2bfae6..655fd15e3962f 100644
--- a/llvm/test/MC/Sparc/sparc-asm-errors.s
+++ b/llvm/test/MC/Sparc/sparc-asm-errors.s
@@ -7,11 +7,11 @@
! 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
- ! V8: unexpected token
+ ! V8: instruction requires a CPU feature not currently enabled
! V9: invalid membar mask number
membar -127
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 68ae2ac5c98a4..9c63f8697e7e3 100644
--- a/llvm/test/MC/Sparc/sparcv9-instructions.s
+++ b/llvm/test/MC/Sparc/sparcv9-instructions.s
@@ -1,32 +1,32 @@
! RUN: not llvm-mc %s -triple=sparc -show-encoding 2>&1 | FileCheck %s --check-prefix=V8
! RUN: llvm-mc %s -triple=sparcv9 -show-encoding | FileCheck %s --check-prefix=V9
- ! V8: error: invalid instruction mnemonic
+ ! V8: error: unknown instruction
! V8-NEXT: addc %g2, %g1, %g3
! V9: addx %g2, %g1, %g3 ! encoding: [0x86,0x40,0x80,0x01]
addc %g2, %g1, %g3
- ! V8: error: invalid instruction mnemonic
+ ! V8: error: unknown instruction
! V8-NEXT: addc %g2, 1, %g3
! V9: addx %g2, 1, %g3 ! encoding: [0x86,0x40,0xa0,0x01]
addc %g2, 1, %g3
- ! V8: error: invalid instruction mnemonic
+ ! V8: error: unknown instruction
! V8-NEXT: addc 1, %g2, %g3
! V9: addx %g2, 1, %g3 ! encoding: [0x86,0x40,0xa0,0x01]
addc 1, %g2, %g3
- ! V8: error: invalid instruction mnemonic
+ ! V8: error: unknown instruction
! V8-NEXT: addccc %g1, %g2, %g3
! V9: addxcc %g1, %g2, %g3 ! encoding: [0x86,0xc0,0x40,0x02]
addccc %g1, %g2, %g3
- ! V8: error: invalid instruction mnemonic
+ ! V8: error: unknown instruction
! V8-NEXT: subc %g2, %g1, %g3
! V9: subx %g2, %g1, %g3 ! encoding: [0x86,0x60,0x80,0x01]
subc %g2, %g1, %g3
- ! V8: error: invalid instruction mnemonic
+ ! V8: error: unknown instruction
! V8-NEXT: subccc %g1, %g2, %g3
! V9: subxcc %g1, %g2, %g3 ! encoding: [0x86,0xe0,0x40,0x02]
subccc %g1, %g2, %g3
@@ -46,23 +46,23 @@
! V9: sra %g1, %g0, %g1 ! encoding: [0x83,0x38,0x40,0x00]
signx %g1
- ! V8: error: invalid instruction mnemonic
+ ! V8: error: unknown instruction
! V8-NEXT: lduw [%i0 + %l6], %o2
! V9: ld [%i0+%l6], %o2 ! encoding: [0xd4,0x06,0x00,0x16]
lduw [%i0 + %l6], %o2
- ! V8: error: invalid instruction mnemonic
+ ! V8: error: unknown instruction
! V8-NEXT: lduw [%i0 + 32], %o2
! V9: ld [%i0+32], %o2 ! encoding: [0xd4,0x06,0x20,0x20]
lduw [%i0 + 32], %o2
- ! V8: error: invalid instruction mnemonic
+ ! V8: error: unknown instruction
! V8-NEXT: lduw [%g1], %o2
! V9: ld [%g1], %o2 ! encoding: [0xd4,0x00,0x40,0x00]
lduw [%g1], %o2
- ! V8: error: invalid instruction mnemonic
+ ! V8: error: unknown instruction
! V8-NEXT: lduwa [%i0 + %l6] 131, %o2
! V9: lda [%i0+%l6] #ASI_SNF, %o2 ! encoding: [0xd4,0x86,0x10,0x76]
lduwa [%i0 + %l6] 131, %o2
- ! V8: error: invalid instruction mnemonic
+ ! V8: error: unknown instruction
! V8-NEXT: lduwa [%i0 + %l6] (130+1), %o2
! V9: lda [%i0+%l6] #ASI_SNF, %o2 ! encoding: [0xd4,0x86,0x10,0x76]
lduwa [%i0 + %l6] (130+1), %o2
@@ -647,12 +647,12 @@
! 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
More information about the llvm-branch-commits
mailing list