https://github.com/koachan updated https://github.com/llvm/llvm-project/pull/96021
>From dbd8f1f421b397a4907af3811937a7815900876a Mon Sep 17 00:00:00 2001 From: Koakuma <koac...@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 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits