Index: include/llvm/MC/MCTargetAsmParser.h =================================================================== --- include/llvm/MC/MCTargetAsmParser.h +++ include/llvm/MC/MCTargetAsmParser.h @@ -13,6 +13,7 @@ #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCParser/MCAsmParserExtension.h" #include "llvm/MC/MCTargetOptions.h" +#include "llvm/MC/SubtargetFeature.h" #include namespace llvm { @@ -95,7 +96,7 @@ MCTargetAsmParser(); /// AvailableFeatures - The current set of available features. - uint64_t AvailableFeatures; + FeatureBitset AvailableFeatures; /// ParsingInlineAsm - Are we parsing ms-style inline assembly? bool ParsingInlineAsm; @@ -110,8 +111,8 @@ public: ~MCTargetAsmParser() override; - uint64_t getAvailableFeatures() const { return AvailableFeatures; } - void setAvailableFeatures(uint64_t Value) { AvailableFeatures = Value; } + FeatureBitset getAvailableFeatures() const { return AvailableFeatures; } + void setAvailableFeatures(FeatureBitset Value) { AvailableFeatures = Value; } bool isParsingInlineAsm () { return ParsingInlineAsm; } void setParsingInlineAsm (bool Value) { ParsingInlineAsm = Value; } @@ -169,6 +170,7 @@ virtual bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset &ErrorMissingFeature, bool MatchingInlineAsm) = 0; /// Allows targets to let registers opt out of clobber lists. Index: lib/MC/MCParser/AsmParser.cpp =================================================================== --- lib/MC/MCParser/AsmParser.cpp +++ lib/MC/MCParser/AsmParser.cpp @@ -1681,9 +1681,11 @@ // If parsing succeeded, match the instruction. if (!HadError) { uint64_t ErrorInfo; + FeatureBitset ErrorMissingFeature; getTargetParser().MatchAndEmitInstruction(IDLoc, Info.Opcode, Info.ParsedOperands, Out, - ErrorInfo, ParsingInlineAsm); + ErrorInfo, ErrorMissingFeature, + ParsingInlineAsm); } // Don't skip the rest of the line, the instruction parser is responsible for Index: lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp =================================================================== --- lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -33,6 +33,7 @@ #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/MC/SubtargetFeature.h" #include using namespace llvm; @@ -86,6 +87,7 @@ bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset &ErrorMissingFeature, bool MatchingInlineAsm) override; /// @name Auto-generated Match Functions /// { @@ -3613,12 +3615,13 @@ } } -static const char *getSubtargetFeatureName(uint64_t Val); +static const char *getSubtargetFeatureName(uint64_t Feature); bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset &ErrorMissingFeature, bool MatchingInlineAsm) { assert(!Operands.empty() && "Unexpect empty operand list!"); AArch64Operand &Op = static_cast(*Operands[0]); @@ -3894,13 +3897,13 @@ // First try to match against the secondary set of tables containing the // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2"). unsigned MatchResult = - MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1); + MatchInstructionImpl(Operands, Inst, ErrorInfo, ErrorMissingFeature, MatchingInlineAsm, 1); // If that fails, try against the alternate table containing long-form NEON: // "fadd v0.2s, v1.2s, v2.2s" if (MatchResult != Match_Success) MatchResult = - MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0); + MatchInstructionImpl(Operands, Inst, ErrorInfo, ErrorMissingFeature, MatchingInlineAsm, 0); switch (MatchResult) { case Match_Success: { @@ -3917,17 +3920,15 @@ return false; } case Match_MissingFeature: { - assert(ErrorInfo && "Unknown missing feature!"); + assert(ErrorMissingFeature.any() && "Unknown missing feature!"); // Special case the error message for the very common case where only // a single subtarget feature is missing (neon, e.g.). std::string Msg = "instruction requires:"; - uint64_t Mask = 1; - for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) { - if (ErrorInfo & Mask) { + for (unsigned i = 0; i < ErrorMissingFeature.size()-1; ++i) { + if (ErrorMissingFeature[i]) { Msg += " "; - Msg += getSubtargetFeatureName(ErrorInfo & Mask); + Msg += getSubtargetFeatureName(i); } - Mask <<= 1; } return Error(IDLoc, Msg); } Index: lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp =================================================================== --- lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -346,6 +346,7 @@ bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset &ErrorMissingFeature, bool MatchingInlineAsm) override; bool ParseDirective(AsmToken DirectiveID) override; OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic); @@ -527,10 +528,11 @@ OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset &ErrorMissingFeature, bool MatchingInlineAsm) { MCInst Inst; - switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) { + switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, ErrorMissingFeature, MatchingInlineAsm)) { default: break; case Match_Success: Inst.setLoc(IDLoc); @@ -562,6 +564,7 @@ AMDGPUOperand::ImmTyOMod)); bool Res = MatchAndEmitInstruction(IDLoc, Opcode, Operands, Out, ErrorInfo, + ErrorMissingFeature, MatchingInlineAsm); if (!Res) return Res; Index: lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -281,7 +281,7 @@ } void SwitchMode() { - uint64_t FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb)); + FeatureBitset FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb)); setAvailableFeatures(FB); } bool isMClass() const { @@ -375,6 +375,7 @@ bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset &ErrorMissingFeature, bool MatchingInlineAsm) override; void onLabelParsed(MCSymbol *Symbol) override; }; @@ -5623,7 +5624,7 @@ static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) { return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm"); } -static void applyMnemonicAliases(StringRef &Mnemonic, uint64_t Features, +static void applyMnemonicAliases(StringRef &Mnemonic, FeatureBitset Features, unsigned VariantID); static bool RequiresVFPRegListValidation(StringRef Inst, @@ -5662,7 +5663,7 @@ // The generic tblgen'erated code does this later, at the start of // MatchInstructionImpl(), but that's too late for aliases that include // any sort of suffix. - uint64_t AvailableFeatures = getAvailableFeatures(); + FeatureBitset AvailableFeatures = getAvailableFeatures(); unsigned AssemblerDialect = getParser().getAssemblerDialect(); applyMnemonicAliases(Name, AvailableFeatures, AssemblerDialect); @@ -8573,16 +8574,17 @@ } } -static const char *getSubtargetFeatureName(uint64_t Val); +static const char *getSubtargetFeatureName(uint64_t Feature); bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset &ErrorMissingFeature, bool MatchingInlineAsm) { MCInst Inst; unsigned MatchResult; MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, - MatchingInlineAsm); + ErrorMissingFeature, MatchingInlineAsm); switch (MatchResult) { case Match_Success: // Context sensitive operand constraints aren't handled by the matcher, @@ -8625,17 +8627,15 @@ Out.EmitInstruction(Inst, STI); return false; case Match_MissingFeature: { - assert(ErrorInfo && "Unknown missing feature!"); + assert(ErrorMissingFeature.any() && "Unknown missing feature!"); // Special case the error message for the very common case where only // a single subtarget feature is missing (Thumb vs. ARM, e.g.). std::string Msg = "instruction requires:"; - uint64_t Mask = 1; - for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) { - if (ErrorInfo & Mask) { + for (unsigned i = 0; i < ErrorMissingFeature.size()-1; ++i) { + if (ErrorMissingFeature[i]) { Msg += " "; - Msg += getSubtargetFeatureName(ErrorInfo & Mask); + Msg += getSubtargetFeatureName(i); } - Mask <<= 1; } return Error(IDLoc, Msg); } @@ -9916,27 +9916,27 @@ // flags below, that were generated by table-gen. static const struct { const ARM::ArchExtKind Kind; - const unsigned ArchCheck; + const FeatureBitset ArchCheck; const FeatureBitset Features; } Extensions[] = { - { ARM::AEK_CRC, Feature_HasV8, {ARM::FeatureCRC} }, - { ARM::AEK_CRYPTO, Feature_HasV8, + { ARM::AEK_CRC, {Feature_HasV8}, {ARM::FeatureCRC} }, + { ARM::AEK_CRYPTO, {Feature_HasV8}, {ARM::FeatureCrypto, ARM::FeatureNEON, ARM::FeatureFPARMv8} }, - { ARM::AEK_FP, Feature_HasV8, {ARM::FeatureFPARMv8} }, - { ARM::AEK_HWDIV, Feature_HasV7 | Feature_IsNotMClass, + { ARM::AEK_FP, {Feature_HasV8}, {ARM::FeatureFPARMv8} }, + { ARM::AEK_HWDIV, {Feature_HasV7, Feature_IsNotMClass}, {ARM::FeatureHWDiv, ARM::FeatureHWDivARM} }, - { ARM::AEK_MP, Feature_HasV7 | Feature_IsNotMClass, {ARM::FeatureMP} }, - { ARM::AEK_SIMD, Feature_HasV8, {ARM::FeatureNEON, ARM::FeatureFPARMv8} }, + { ARM::AEK_MP, {Feature_HasV7 , Feature_IsNotMClass}, {ARM::FeatureMP} }, + { ARM::AEK_SIMD, {Feature_HasV8}, {ARM::FeatureNEON, ARM::FeatureFPARMv8} }, // FIXME: Also available in ARMv6-K - { ARM::AEK_SEC, Feature_HasV7, {ARM::FeatureTrustZone} }, + { ARM::AEK_SEC, {Feature_HasV7}, {ARM::FeatureTrustZone} }, // FIXME: Only available in A-class, isel not predicated - { ARM::AEK_VIRT, Feature_HasV7, {ARM::FeatureVirtualization} }, + { ARM::AEK_VIRT, {Feature_HasV7}, {ARM::FeatureVirtualization} }, // FIXME: Unsupported extensions. - { ARM::AEK_OS, Feature_None, {} }, - { ARM::AEK_IWMMXT, Feature_None, {} }, - { ARM::AEK_IWMMXT2, Feature_None, {} }, - { ARM::AEK_MAVERICK, Feature_None, {} }, - { ARM::AEK_XSCALE, Feature_None, {} }, + { ARM::AEK_OS, {Feature_None}, {} }, + { ARM::AEK_IWMMXT, {Feature_None}, {} }, + { ARM::AEK_IWMMXT2, {Feature_None}, {} }, + { ARM::AEK_MAVERICK, {Feature_None}, {} }, + { ARM::AEK_XSCALE, {Feature_None}, {} }, }; /// parseDirectiveArchExtension @@ -9980,7 +9980,7 @@ ? (~STI.getFeatureBits() & Extension.Features) : ( STI.getFeatureBits() & Extension.Features); - uint64_t Features = + FeatureBitset Features = ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures)); setAvailableFeatures(Features); return false; Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -127,6 +127,7 @@ bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset &ErrorMissingFeature, bool MatchingInlineAsm) override; /// Parse a register as used in CFI directives @@ -2625,12 +2626,13 @@ OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset &ErrorMissingFeature, bool MatchingInlineAsm) { MCInst Inst; SmallVector Instructions; unsigned MatchResult = - MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); + MatchInstructionImpl(Operands, Inst, ErrorInfo, ErrorMissingFeature, MatchingInlineAsm); switch (MatchResult) { case Match_Success: { Index: lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp =================================================================== --- lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -277,6 +277,7 @@ bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset &ErrorMissingFeature, bool MatchingInlineAsm) override; void ProcessInstruction(MCInst &Inst, const OperandVector &Ops); @@ -1197,10 +1198,11 @@ bool PPCAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset &ErrorMissingFeature, bool MatchingInlineAsm) { MCInst Inst; - switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) { + switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, ErrorMissingFeature, MatchingInlineAsm)) { case Match_Success: // Post-process instructions (typically extended mnemonics) ProcessInstruction(Inst, Operands); Index: lib/Target/Sparc/AsmParser/SparcAsmParser.cpp =================================================================== --- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp +++ lib/Target/Sparc/AsmParser/SparcAsmParser.cpp @@ -49,6 +49,7 @@ bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset &ErrorMissingFeature, bool MatchingInlineAsm) override; bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, @@ -445,10 +446,12 @@ OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset &ErrorMissingFeature, bool MatchingInlineAsm) { MCInst Inst; SmallVector Instructions; unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, + ErrorMissingFeature, MatchingInlineAsm); switch (MatchResult) { case Match_Success: { @@ -510,7 +513,7 @@ return Error(StartLoc, "invalid register name"); } -static void applyMnemonicAliases(StringRef &Mnemonic, uint64_t Features, +static void applyMnemonicAliases(StringRef &Mnemonic, FeatureBitset Features, unsigned VariantID); bool SparcAsmParser::ParseInstruction(ParseInstructionInfo &Info, Index: lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp =================================================================== --- lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp +++ lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp @@ -404,6 +404,7 @@ bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset &ErrorMissingFeature, bool MatchingInlineAsm) override; // Used by the TableGen code to parse particular operand types. @@ -782,12 +783,13 @@ OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset &ErrorMissingFeature, bool MatchingInlineAsm) { MCInst Inst; unsigned MatchResult; MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, - MatchingInlineAsm); + ErrorMissingFeature, MatchingInlineAsm); switch (MatchResult) { case Match_Success: Inst.setLoc(IDLoc); @@ -795,17 +797,15 @@ return false; case Match_MissingFeature: { - assert(ErrorInfo && "Unknown missing feature!"); + assert(ErrorMissingFeature.any() && "Unknown missing feature!"); // Special case the error message for the very common case where only // a single subtarget feature is missing std::string Msg = "instruction requires:"; - uint64_t Mask = 1; - for (unsigned I = 0; I < sizeof(ErrorInfo) * 8 - 1; ++I) { - if (ErrorInfo & Mask) { + for (unsigned I = 0; I < ErrorMissingFeature.size()-1; ++I) { + if (ErrorMissingFeature[I]) { Msg += " "; - Msg += getSubtargetFeatureName(ErrorInfo & Mask); + Msg += getSubtargetFeatureName(I); } - Mask <<= 1; } return Error(IDLoc, Msg); } Index: lib/Target/X86/AsmParser/X86AsmParser.cpp =================================================================== --- lib/Target/X86/AsmParser/X86AsmParser.cpp +++ lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -722,22 +722,25 @@ bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset &ErrorMissingFeature, bool MatchingInlineAsm) override; void MatchFPUWaitAlias(SMLoc IDLoc, X86Operand &Op, OperandVector &Operands, MCStreamer &Out, bool MatchingInlineAsm); - bool ErrorMissingFeature(SMLoc IDLoc, uint64_t ErrorInfo, + bool ErrorMissingFeature(SMLoc IDLoc, FeatureBitset MissingFeature, bool MatchingInlineAsm); bool MatchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset &ErrorMissingFeature, bool MatchingInlineAsm); bool MatchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset &ErrorMissingFeature, bool MatchingInlineAsm); bool OmitRegisterFromClobberLists(unsigned RegNo) override; @@ -768,7 +771,7 @@ void SwitchMode(unsigned mode) { FeatureBitset AllModes({X86::Mode64Bit, X86::Mode32Bit, X86::Mode16Bit}); FeatureBitset OldMode = STI.getFeatureBits() & AllModes; - unsigned FB = ComputeAvailableFeatures( + FeatureBitset FB = ComputeAvailableFeatures( STI.ToggleFeature(OldMode.flip(mode))); setAvailableFeatures(FB); @@ -2490,7 +2493,7 @@ } } -static const char *getSubtargetFeatureName(uint64_t Val); +static const char *getSubtargetFeatureName(uint64_t Feature); void X86AsmParser::EmitInstruction(MCInst &Inst, OperandVector &Operands, MCStreamer &Out) { @@ -2501,12 +2504,13 @@ bool X86AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset &ErrorMissingFeature, bool MatchingInlineAsm) { if (isParsingIntelSyntax()) return MatchAndEmitIntelInstruction(IDLoc, Opcode, Operands, Out, ErrorInfo, - MatchingInlineAsm); + ErrorMissingFeature, MatchingInlineAsm); return MatchAndEmitATTInstruction(IDLoc, Opcode, Operands, Out, ErrorInfo, - MatchingInlineAsm); + ErrorMissingFeature, MatchingInlineAsm); } void X86AsmParser::MatchFPUWaitAlias(SMLoc IDLoc, X86Operand &Op, @@ -2535,18 +2539,16 @@ } } -bool X86AsmParser::ErrorMissingFeature(SMLoc IDLoc, uint64_t ErrorInfo, +bool X86AsmParser::ErrorMissingFeature(SMLoc IDLoc, FeatureBitset MissingFeature, bool MatchingInlineAsm) { - assert(ErrorInfo && "Unknown missing feature!"); + assert(MissingFeature.any() && "Unknown missing feature!"); ArrayRef EmptyRanges = None; SmallString<126> Msg; raw_svector_ostream OS(Msg); OS << "instruction requires:"; - uint64_t Mask = 1; - for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) { - if (ErrorInfo & Mask) - OS << ' ' << getSubtargetFeatureName(ErrorInfo & Mask); - Mask <<= 1; + for (unsigned i = 0; i < MissingFeature.size()-1; ++i) { + if (MissingFeature[i]) + OS << ' ' << getSubtargetFeatureName(i); } return Error(IDLoc, OS.str(), EmptyRanges, MatchingInlineAsm); } @@ -2555,6 +2557,7 @@ OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset &ErrMissingFeature, bool MatchingInlineAsm) { assert(!Operands.empty() && "Unexpect empty operand list!"); X86Operand &Op = static_cast(*Operands[0]); @@ -2569,7 +2572,8 @@ // First, try a direct match. switch (MatchInstructionImpl(Operands, Inst, - ErrorInfo, MatchingInlineAsm, + ErrorInfo, ErrMissingFeature, + MatchingInlineAsm, isParsingIntelSyntax())) { default: llvm_unreachable("Unexpected match result!"); case Match_Success: @@ -2589,7 +2593,7 @@ Opcode = Inst.getOpcode(); return false; case Match_MissingFeature: - return ErrorMissingFeature(IDLoc, ErrorInfo, MatchingInlineAsm); + return ErrorMissingFeature(IDLoc, ErrMissingFeature, MatchingInlineAsm); case Match_InvalidOperand: WasOriginallyInvalidOperand = true; break; @@ -2619,16 +2623,16 @@ // Check for the various suffix matches. uint64_t ErrorInfoIgnore; - uint64_t ErrorInfoMissingFeature = 0; // Init suppresses compiler warnings. + FeatureBitset ErrorInfoMissingFeature; unsigned Match[4]; for (unsigned I = 0, E = array_lengthof(Match); I != E; ++I) { Tmp.back() = Suffixes[I]; - Match[I] = MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore, - MatchingInlineAsm, isParsingIntelSyntax()); + Match[I] = MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore, ErrMissingFeature, + MatchingInlineAsm, isParsingIntelSyntax()); // If this returned as a missing feature failure, remember that. if (Match[I] == Match_MissingFeature) - ErrorInfoMissingFeature = ErrorInfoIgnore; + ErrorInfoMissingFeature = ErrMissingFeature; } // Restore the old token. @@ -2707,8 +2711,8 @@ // missing feature. if (std::count(std::begin(Match), std::end(Match), Match_MissingFeature) == 1) { - ErrorInfo = ErrorInfoMissingFeature; - return ErrorMissingFeature(IDLoc, ErrorInfoMissingFeature, + ErrMissingFeature = ErrorInfoMissingFeature; + return ErrorMissingFeature(IDLoc, ErrMissingFeature, MatchingInlineAsm); } @@ -2730,6 +2734,7 @@ OperandVector &Operands, MCStreamer &Out, uint64_t &ErrorInfo, + FeatureBitset& ErrMissingFeature, bool MatchingInlineAsm) { assert(!Operands.empty() && "Unexpect empty operand list!"); X86Operand &Op = static_cast(*Operands[0]); @@ -2766,22 +2771,23 @@ // operand size. In Intel assembly, the size is not part of the instruction // mnemonic. SmallVector Match; - uint64_t ErrorInfoMissingFeature = 0; + FeatureBitset ErrorInfoMissingFeature; if (UnsizedMemOp && UnsizedMemOp->isMemUnsized()) { static const unsigned MopSizes[] = {8, 16, 32, 64, 80, 128, 256, 512}; for (unsigned Size : MopSizes) { UnsizedMemOp->Mem.Size = Size; uint64_t ErrorInfoIgnore; + FeatureBitset MissingFeature; unsigned LastOpcode = Inst.getOpcode(); unsigned M = - MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore, + MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore, MissingFeature, MatchingInlineAsm, isParsingIntelSyntax()); if (Match.empty() || LastOpcode != Inst.getOpcode()) Match.push_back(M); // If this returned as a missing feature failure, remember that. if (Match.back() == Match_MissingFeature) - ErrorInfoMissingFeature = ErrorInfoIgnore; + ErrorInfoMissingFeature = MissingFeature; } // Restore the size of the unsized memory operand if we modified it. @@ -2794,11 +2800,12 @@ // matching with the unsized operand. if (Match.empty()) { Match.push_back(MatchInstructionImpl(Operands, Inst, ErrorInfo, + ErrMissingFeature, MatchingInlineAsm, isParsingIntelSyntax())); // If this returned as a missing feature failure, remember that. if (Match.back() == Match_MissingFeature) - ErrorInfoMissingFeature = ErrorInfo; + ErrorInfoMissingFeature = ErrMissingFeature; } // Restore the size of the unsized memory operand if we modified it. @@ -2847,7 +2854,7 @@ // missing feature. if (std::count(std::begin(Match), std::end(Match), Match_MissingFeature) == 1) { - ErrorInfo = ErrorInfoMissingFeature; + ErrMissingFeature = ErrorInfoMissingFeature; return ErrorMissingFeature(IDLoc, ErrorInfoMissingFeature, MatchingInlineAsm); } Index: utils/TableGen/AsmMatcherEmitter.cpp =================================================================== --- utils/TableGen/AsmMatcherEmitter.cpp +++ utils/TableGen/AsmMatcherEmitter.cpp @@ -2223,7 +2223,7 @@ << " {\n"; for (const auto &SF : Info.SubtargetFeatures) { const SubtargetFeatureInfo &SFI = SF.second; - OS << " " << SFI.getEnumName() << " = (1ULL << " << SFI.Index << "),\n"; + OS << " " << SFI.getEnumName() << " = " << SFI.Index << ",\n"; } OS << " Feature_None = 0\n"; OS << "};\n\n"; @@ -2254,9 +2254,9 @@ static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) { OS << "// User-level names for subtarget features that participate in\n" << "// instruction matching.\n" - << "static const char *getSubtargetFeatureName(uint64_t Val) {\n"; + << "static const char *getSubtargetFeatureName(uint64_t Feature) {\n"; if (!Info.SubtargetFeatures.empty()) { - OS << " switch(Val) {\n"; + OS << " switch(Feature) {\n"; for (const auto &SF : Info.SubtargetFeatures) { const SubtargetFeatureInfo &SFI = SF.second; // FIXME: Totally just a placeholder name to get the algorithm working. @@ -2279,9 +2279,9 @@ std::string ClassName = Info.AsmParser->getValueAsString("AsmParserClassName"); - OS << "uint64_t " << Info.Target.getName() << ClassName << "::\n" + OS << "FeatureBitset " << Info.Target.getName() << ClassName << "::\n" << "ComputeAvailableFeatures(const FeatureBitset& FB) const {\n"; - OS << " uint64_t Features = 0;\n"; + OS << " FeatureBitset Features;\n"; for (const auto &SF : Info.SubtargetFeatures) { const SubtargetFeatureInfo &SFI = SF.second; @@ -2315,7 +2315,7 @@ } while (true); OS << ")\n"; - OS << " Features |= " << SFI.getEnumName() << ";\n"; + OS << " Features.set(" << SFI.getEnumName() << ", 1);\n"; } OS << " return Features;\n"; OS << "}\n\n"; @@ -2400,7 +2400,7 @@ if (!MatchCode.empty()) MatchCode += "else "; - MatchCode += "if ((Features & " + FeatureMask + ") == "+FeatureMask+")\n"; + MatchCode += "if ((Features & FeatureBitset({"+FeatureMask+"})) == FeatureBitset({"+FeatureMask+"}))\n"; MatchCode += " Mnemonic = \"" +R->getValueAsString("ToMnemonic")+"\";\n"; } @@ -2431,7 +2431,7 @@ if (Aliases.empty()) return false; OS << "static void applyMnemonicAliases(StringRef &Mnemonic, " - "uint64_t Features, unsigned VariantID) {\n"; + "FeatureBitset Features, unsigned VariantID) {\n"; OS << " switch (VariantID) {\n"; unsigned VariantCount = Target.getAsmParserVariantCount(); for (unsigned VC = 0; VC != VariantCount; ++VC) { @@ -2467,8 +2467,7 @@ // Emit the static custom operand parsing table; OS << "namespace {\n"; OS << " struct OperandMatchEntry {\n"; - OS << " " << getMinimalRequiredFeaturesType(Info) - << " RequiredFeatures;\n"; + OS << " FeatureBitset RequiredFeatures;\n"; OS << " " << getMinimalTypeForRange(MaxMnemonicIndex) << " Mnemonic;\n"; OS << " " << getMinimalTypeForRange(std::distance( @@ -2511,12 +2510,14 @@ // Write the required features mask. if (!II.RequiredFeatures.empty()) { + OS << "{"; for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) { - if (i) OS << "|"; + if (i) OS << ","; OS << II.RequiredFeatures[i]->getEnumName(); } + OS << "}"; } else - OS << "0"; + OS << "{}"; // Store a pascal-style length byte in the mnemonic. std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str(); @@ -2572,7 +2573,7 @@ // Emit code to get the available features. OS << " // Get the current feature set.\n"; - OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n"; + OS << " FeatureBitset AvailableFeatures = getAvailableFeatures();\n\n"; OS << " // Get the next operand index.\n"; OS << " unsigned NextOpNum = Operands.size()-1;\n"; @@ -2675,7 +2676,7 @@ OS << "#undef GET_ASSEMBLER_HEADER\n"; OS << " // This should be included into the middle of the declaration of\n"; OS << " // your subclasses implementation of MCTargetAsmParser.\n"; - OS << " uint64_t ComputeAvailableFeatures(const FeatureBitset& FB) const;\n"; + OS << " FeatureBitset ComputeAvailableFeatures(const FeatureBitset& FB) const;\n"; OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, " << "unsigned Opcode,\n" << " const OperandVector " @@ -2685,8 +2686,9 @@ OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) override;\n"; OS << " unsigned MatchInstructionImpl(const OperandVector &Operands,\n" << " MCInst &Inst,\n" - << " uint64_t &ErrorInfo," - << " bool matchingInlineAsm,\n" + << " uint64_t &ErrorInfo,\n" + << " FeatureBitset &ErrorMissingFeature,\n" + << " bool matchingInlineAsm,\n" << " unsigned VariantID = 0);\n"; if (!Info.OperandMatchInfo.empty()) { @@ -2797,8 +2799,7 @@ OS << " uint16_t Opcode;\n"; OS << " " << getMinimalTypeForRange(Info.Matchables.size()) << " ConvertFn;\n"; - OS << " " << getMinimalRequiredFeaturesType(Info) - << " RequiredFeatures;\n"; + OS << " FeatureBitset RequiredFeatures;\n"; OS << " " << getMinimalTypeForRange( std::distance(Info.Classes.begin(), Info.Classes.end())) << " Classes[" << MaxNumOperands << "];\n"; @@ -2844,12 +2845,14 @@ // Write the required features mask. if (!MI->RequiredFeatures.empty()) { + OS << "{"; for (unsigned i = 0, e = MI->RequiredFeatures.size(); i != e; ++i) { - if (i) OS << "|"; + if (i) OS << ","; OS << MI->RequiredFeatures[i]->getEnumName(); } + OS << "}"; } else - OS << "0"; + OS << "{}"; OS << ", { "; for (unsigned i = 0, e = MI->AsmOperands.size(); i != e; ++i) { @@ -2888,6 +2891,7 @@ OS << "unsigned " << Target.getName() << ClassName << "::\n" << "MatchInstructionImpl(const OperandVector &Operands,\n"; OS << " MCInst &Inst, uint64_t &ErrorInfo,\n" + << " FeatureBitset &ErrorMissingFeature,\n" << " bool matchingInlineAsm, unsigned VariantID) {\n"; OS << " // Eliminate obvious mismatches.\n"; @@ -2898,7 +2902,7 @@ // Emit code to get the available features. OS << " // Get the current feature set.\n"; - OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n"; + OS << " FeatureBitset AvailableFeatures = getAvailableFeatures();\n\n"; OS << " // Get the instruction mnemonic, which is the first token.\n"; OS << " StringRef Mnemonic = ((" << Target.getName() @@ -2914,7 +2918,7 @@ OS << " bool HadMatchOtherThanFeatures = false;\n"; OS << " bool HadMatchOtherThanPredicate = false;\n"; OS << " unsigned RetCode = Match_InvalidOperand;\n"; - OS << " uint64_t MissingFeatures = ~0ULL;\n"; + OS << " FeatureBitset MissingFeatures(~0ULL);\n"; OS << " // Set ErrorInfo to the operand that mismatches if it is\n"; OS << " // wrong for all instances of the instruction.\n"; OS << " ErrorInfo = ~0ULL;\n"; @@ -2990,10 +2994,10 @@ OS << " if ((AvailableFeatures & it->RequiredFeatures) " << "!= it->RequiredFeatures) {\n"; OS << " HadMatchOtherThanFeatures = true;\n"; - OS << " uint64_t NewMissingFeatures = it->RequiredFeatures & " + OS << " FeatureBitset NewMissingFeatures = it->RequiredFeatures & " "~AvailableFeatures;\n"; - OS << " if (countPopulation(NewMissingFeatures) <=\n" - " countPopulation(MissingFeatures))\n"; + OS << " if (NewMissingFeatures.count() <=\n" + " MissingFeatures.count())\n"; OS << " MissingFeatures = NewMissingFeatures;\n"; OS << " continue;\n"; OS << " }\n"; @@ -3043,7 +3047,7 @@ OS << " if (HadMatchOtherThanPredicate || !HadMatchOtherThanFeatures)\n"; OS << " return RetCode;\n\n"; OS << " // Missing feature matches return which features were missing\n"; - OS << " ErrorInfo = MissingFeatures;\n"; + OS << " ErrorMissingFeature = MissingFeatures;\n"; OS << " return Match_MissingFeature;\n"; OS << "}\n\n";