Index: llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp +++ llvm/trunk/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp @@ -35,11 +35,13 @@ class AArch64MCCodeEmitter : public MCCodeEmitter { MCContext &Ctx; + const MCInstrInfo &MCII; AArch64MCCodeEmitter(const AArch64MCCodeEmitter &); // DO NOT IMPLEMENT void operator=(const AArch64MCCodeEmitter &); // DO NOT IMPLEMENT public: - AArch64MCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) : Ctx(ctx) {} + AArch64MCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) + : Ctx(ctx), MCII(mcii) {} ~AArch64MCCodeEmitter() override {} @@ -170,6 +172,11 @@ unsigned fixOneOperandFPComparison(const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const; + +private: + uint64_t computeAvailableFeatures(const FeatureBitset &FB) const; + void verifyInstructionPredicates(const MCInst &MI, + uint64_t AvailableFeatures) const; }; } // end anonymous namespace @@ -547,6 +554,9 @@ void AArch64MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { + verifyInstructionPredicates(MI, + computeAvailableFeatures(STI.getFeatureBits())); + if (MI.getOpcode() == AArch64::TLSDESCCALL) { // This is a directive which applies an R_AARCH64_TLSDESC_CALL to the // following (BLR) instruction. It doesn't emit any code itself so it @@ -589,4 +599,5 @@ return EncodedValue; } +#define ENABLE_INSTR_PREDICATE_VERIFIER #include "AArch64GenMCCodeEmitter.inc" Index: llvm/trunk/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.h =================================================================== --- llvm/trunk/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.h +++ llvm/trunk/lib/Target/AMDGPU/MCTargetDesc/AMDGPUMCCodeEmitter.h @@ -21,11 +21,19 @@ namespace llvm { class MCInst; +class MCInstrInfo; class MCOperand; class MCSubtargetInfo; +class FeatureBitset; class AMDGPUMCCodeEmitter : public MCCodeEmitter { virtual void anchor(); + +protected: + const MCInstrInfo &MCII; + + AMDGPUMCCodeEmitter(const MCInstrInfo &mcii) : MCII(mcii) {} + public: uint64_t getBinaryCodeForInstr(const MCInst &MI, @@ -43,6 +51,11 @@ const MCSubtargetInfo &STI) const { return 0; } + +protected: + uint64_t computeAvailableFeatures(const FeatureBitset &FB) const; + void verifyInstructionPredicates(const MCInst &MI, + uint64_t AvailableFeatures) const; }; } // End namespace llvm Index: llvm/trunk/lib/Target/AMDGPU/MCTargetDesc/R600MCCodeEmitter.cpp =================================================================== --- llvm/trunk/lib/Target/AMDGPU/MCTargetDesc/R600MCCodeEmitter.cpp +++ llvm/trunk/lib/Target/AMDGPU/MCTargetDesc/R600MCCodeEmitter.cpp @@ -34,12 +34,11 @@ class R600MCCodeEmitter : public AMDGPUMCCodeEmitter { R600MCCodeEmitter(const R600MCCodeEmitter &) = delete; void operator=(const R600MCCodeEmitter &) = delete; - const MCInstrInfo &MCII; const MCRegisterInfo &MRI; public: R600MCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri) - : MCII(mcii), MRI(mri) { } + : AMDGPUMCCodeEmitter(mcii), MRI(mri) { } /// \brief Encode the instruction and write it to the OS. void encodeInstruction(const MCInst &MI, raw_ostream &OS, @@ -86,6 +85,9 @@ void R600MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { + verifyInstructionPredicates(MI, + computeAvailableFeatures(STI.getFeatureBits())); + const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); if (MI.getOpcode() == AMDGPU::RETURN || MI.getOpcode() == AMDGPU::FETCH_CLAUSE || @@ -178,4 +180,5 @@ return MO.getImm(); } +#define ENABLE_INSTR_PREDICATE_VERIFIER #include "AMDGPUGenMCCodeEmitter.inc" Index: llvm/trunk/lib/Target/AMDGPU/MCTargetDesc/SIMCCodeEmitter.cpp =================================================================== --- llvm/trunk/lib/Target/AMDGPU/MCTargetDesc/SIMCCodeEmitter.cpp +++ llvm/trunk/lib/Target/AMDGPU/MCTargetDesc/SIMCCodeEmitter.cpp @@ -36,7 +36,6 @@ class SIMCCodeEmitter : public AMDGPUMCCodeEmitter { SIMCCodeEmitter(const SIMCCodeEmitter &) = delete; void operator=(const SIMCCodeEmitter &) = delete; - const MCInstrInfo &MCII; const MCRegisterInfo &MRI; /// \brief Encode an fp or int literal @@ -46,7 +45,7 @@ public: SIMCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri, MCContext &ctx) - : MCII(mcii), MRI(mri) { } + : AMDGPUMCCodeEmitter(mcii), MRI(mri) {} ~SIMCCodeEmitter() override {} @@ -192,6 +191,8 @@ void SIMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { + verifyInstructionPredicates(MI, + computeAvailableFeatures(STI.getFeatureBits())); uint64_t Encoding = getBinaryCodeForInstr(MI, Fixups, STI); const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); Index: llvm/trunk/lib/Target/AMDGPU/VOP1Instructions.td =================================================================== --- llvm/trunk/lib/Target/AMDGPU/VOP1Instructions.td +++ llvm/trunk/lib/Target/AMDGPU/VOP1Instructions.td @@ -550,6 +550,7 @@ PseudoInstExpansion<(V_MOV_B32_e32_vi getVALUDstForVT.ret:$vdst, getVOPSrc0ForVT.ret:$src0)> { let VOP1 = 1; + let SubtargetPredicate = isVI; } // This is a pseudo variant of the v_movreld_b32 instruction in which the Index: llvm/trunk/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp =================================================================== --- llvm/trunk/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp +++ llvm/trunk/lib/Target/BPF/MCTargetDesc/BPFMCCodeEmitter.cpp @@ -30,12 +30,14 @@ class BPFMCCodeEmitter : public MCCodeEmitter { BPFMCCodeEmitter(const BPFMCCodeEmitter &) = delete; void operator=(const BPFMCCodeEmitter &) = delete; + const MCInstrInfo &MCII; const MCRegisterInfo &MRI; bool IsLittleEndian; public: - BPFMCCodeEmitter(const MCRegisterInfo &mri, bool IsLittleEndian) - : MRI(mri), IsLittleEndian(IsLittleEndian) {} + BPFMCCodeEmitter(const MCInstrInfo &mcii, const MCRegisterInfo &mri, + bool IsLittleEndian) + : MCII(mcii), MRI(mri), IsLittleEndian(IsLittleEndian) {} ~BPFMCCodeEmitter() {} @@ -58,19 +60,24 @@ void encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const override; + +private: + uint64_t computeAvailableFeatures(const FeatureBitset &FB) const; + void verifyInstructionPredicates(const MCInst &MI, + uint64_t AvailableFeatures) const; }; } MCCodeEmitter *llvm::createBPFMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, MCContext &Ctx) { - return new BPFMCCodeEmitter(MRI, true); + return new BPFMCCodeEmitter(MCII, MRI, true); } MCCodeEmitter *llvm::createBPFbeMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, MCContext &Ctx) { - return new BPFMCCodeEmitter(MRI, false); + return new BPFMCCodeEmitter(MCII, MRI, false); } unsigned BPFMCCodeEmitter::getMachineOpValue(const MCInst &MI, @@ -108,6 +115,9 @@ void BPFMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { + verifyInstructionPredicates(MI, + computeAvailableFeatures(STI.getFeatureBits())); + unsigned Opcode = MI.getOpcode(); support::endian::Writer LE(OS); support::endian::Writer BE(OS); @@ -165,4 +175,5 @@ return Encoding; } +#define ENABLE_INSTR_PREDICATE_VERIFIER #include "BPFGenMCCodeEmitter.inc" Index: llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.h =================================================================== --- llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.h +++ llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.h @@ -63,6 +63,11 @@ unsigned getMachineOpValue(MCInst const &MI, MCOperand const &MO, SmallVectorImpl &Fixups, MCSubtargetInfo const &STI) const; + +private: + uint64_t computeAvailableFeatures(const FeatureBitset &FB) const; + void verifyInstructionPredicates(const MCInst &MI, + uint64_t AvailableFeatures) const; }; // class HexagonMCCodeEmitter } // namespace llvm Index: llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp =================================================================== --- llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp +++ llvm/trunk/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp @@ -78,6 +78,9 @@ size_t Last = HexagonMCInstrInfo::bundleSize(HMB) - 1; for (auto &I : HexagonMCInstrInfo::bundleInstructions(HMB)) { MCInst &HMI = const_cast(*I.getInst()); + verifyInstructionPredicates(HMI, + computeAvailableFeatures(STI.getFeatureBits())); + EncodeSingleInstruction(HMI, OS, Fixups, STI, parseBits(Instruction, Last, HMB, HMI), Instruction); @@ -817,4 +820,5 @@ return new HexagonMCCodeEmitter(MII, MCT); } +#define ENABLE_INSTR_PREDICATE_VERIFIER #include "HexagonGenMCCodeEmitter.inc" Index: llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp =================================================================== --- llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp +++ llvm/trunk/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp @@ -106,6 +106,9 @@ void encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const override { + verifyInstructionPredicates(MI, + computeAvailableFeatures(STI.getFeatureBits())); + unsigned Opcode = MI.getOpcode(); const MCInstrDesc &Desc = MCII.get(Opcode); @@ -139,7 +142,11 @@ ++MCNumEmitted; // Keep track of the # of mi's emitted. } - + +private: + uint64_t computeAvailableFeatures(const FeatureBitset &FB) const; + void verifyInstructionPredicates(const MCInst &MI, + uint64_t AvailableFeatures) const; }; } // end anonymous namespace @@ -377,4 +384,6 @@ } + +#define ENABLE_INSTR_PREDICATE_VERIFIER #include "PPCGenMCCodeEmitter.inc" Index: llvm/trunk/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp =================================================================== --- llvm/trunk/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp +++ llvm/trunk/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp @@ -19,6 +19,7 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCAsmInfo.h" @@ -35,10 +36,12 @@ class SparcMCCodeEmitter : public MCCodeEmitter { SparcMCCodeEmitter(const SparcMCCodeEmitter &) = delete; void operator=(const SparcMCCodeEmitter &) = delete; + const MCInstrInfo &MCII; MCContext &Ctx; public: - SparcMCCodeEmitter(MCContext &ctx): Ctx(ctx) {} + SparcMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) + : MCII(mcii), Ctx(ctx) {} ~SparcMCCodeEmitter() override {} @@ -71,18 +74,25 @@ SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; +private: + uint64_t computeAvailableFeatures(const FeatureBitset &FB) const; + void verifyInstructionPredicates(const MCInst &MI, + uint64_t AvailableFeatures) const; }; } // end anonymous namespace MCCodeEmitter *llvm::createSparcMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, MCContext &Ctx) { - return new SparcMCCodeEmitter(Ctx); + return new SparcMCCodeEmitter(MCII, Ctx); } void SparcMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { + verifyInstructionPredicates(MI, + computeAvailableFeatures(STI.getFeatureBits())); + unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI); if (Ctx.getAsmInfo()->isLittleEndian()) { @@ -215,6 +225,5 @@ return 0; } - - +#define ENABLE_INSTR_PREDICATE_VERIFIER #include "SparcGenMCCodeEmitter.inc" Index: llvm/trunk/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp =================================================================== --- llvm/trunk/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp +++ llvm/trunk/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp @@ -113,6 +113,11 @@ return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC32DBL, 2, true); } + +private: + uint64_t computeAvailableFeatures(const FeatureBitset &FB) const; + void verifyInstructionPredicates(const MCInst &MI, + uint64_t AvailableFeatures) const; }; } // end anonymous namespace @@ -126,6 +131,9 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { + verifyInstructionPredicates(MI, + computeAvailableFeatures(STI.getFeatureBits())); + uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); unsigned Size = MCII.get(MI.getOpcode()).getSize(); // Big-endian insertion of Size bytes. @@ -254,4 +262,5 @@ return 0; } +#define ENABLE_INSTR_PREDICATE_VERIFIER #include "SystemZGenMCCodeEmitter.inc" Index: llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp =================================================================== --- llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp +++ llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp @@ -2364,29 +2364,6 @@ OS << "}\n\n"; } -static const char *getMinimalRequiredFeaturesType(const AsmMatcherInfo &Info) { - uint64_t MaxIndex = Info.SubtargetFeatures.size(); - if (MaxIndex > 0) - MaxIndex--; - return getMinimalTypeForRange(1ULL << MaxIndex); -} - -/// emitSubtargetFeatureFlagEnumeration - Emit the subtarget feature flag -/// definitions. -static void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info, - raw_ostream &OS) { - OS << "// Flags for subtarget features that participate in " - << "instruction matching.\n"; - OS << "enum SubtargetFeatureFlag : " << getMinimalRequiredFeaturesType(Info) - << " {\n"; - for (const auto &SF : Info.SubtargetFeatures) { - const SubtargetFeatureInfo &SFI = SF.second; - OS << " " << SFI.getEnumName() << " = (1ULL << " << SFI.Index << "),\n"; - } - OS << " Feature_None = 0\n"; - OS << "};\n\n"; -} - /// emitOperandDiagnosticTypes - Emit the operand matching diagnostic types. static void emitOperandDiagnosticTypes(AsmMatcherInfo &Info, raw_ostream &OS) { // Get the set of diagnostic types from all of the operand classes. @@ -2568,7 +2545,7 @@ // Emit the static custom operand parsing table; OS << "namespace {\n"; OS << " struct OperandMatchEntry {\n"; - OS << " " << getMinimalRequiredFeaturesType(Info) + OS << " " << getMinimalTypeForEnumBitfield(Info.SubtargetFeatures.size()) << " RequiredFeatures;\n"; OS << " " << getMinimalTypeForRange(MaxMnemonicIndex) << " Mnemonic;\n"; @@ -2837,7 +2814,8 @@ OS << "#undef GET_REGISTER_MATCHER\n\n"; // Emit the subtarget feature enumeration. - emitSubtargetFeatureFlagEnumeration(Info, OS); + SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration( + Info.SubtargetFeatures, OS); // Emit the function to match a register name to number. // This should be omitted for Mips target @@ -2883,7 +2861,8 @@ // Emit the available features compute function. SubtargetFeatureInfo::emitComputeAvailableFeatures( - Info.Target.getName(), ClassName, Info.SubtargetFeatures, OS); + Info.Target.getName(), ClassName, "ComputeAvailableFeatures", + Info.SubtargetFeatures, OS); StringToOffsetTable StringTable; @@ -2921,7 +2900,7 @@ OS << " uint16_t Opcode;\n"; OS << " " << getMinimalTypeForRange(Info.Matchables.size()) << " ConvertFn;\n"; - OS << " " << getMinimalRequiredFeaturesType(Info) + OS << " " << getMinimalTypeForEnumBitfield(Info.SubtargetFeatures.size()) << " RequiredFeatures;\n"; OS << " " << getMinimalTypeForRange( std::distance(Info.Classes.begin(), Info.Classes.end())) Index: llvm/trunk/utils/TableGen/CodeEmitterGen.cpp =================================================================== --- llvm/trunk/utils/TableGen/CodeEmitterGen.cpp +++ llvm/trunk/utils/TableGen/CodeEmitterGen.cpp @@ -14,6 +14,8 @@ //===----------------------------------------------------------------------===// #include "CodeGenTarget.h" +#include "SubtargetFeatureInfo.h" +#include "Types.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Debug.h" #include "llvm/TableGen/Record.h" @@ -307,6 +309,64 @@ << " }\n" << " return Value;\n" << "}\n\n"; + + const auto &All = SubtargetFeatureInfo::getAll(Records); + std::map SubtargetFeatures; + SubtargetFeatures.insert(All.begin(), All.end()); + + o << "#ifdef ENABLE_INSTR_PREDICATE_VERIFIER\n" + << "#undef ENABLE_INSTR_PREDICATE_VERIFIER\n" + << "#include \n\n"; + + // Emit the subtarget feature enumeration. + SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(SubtargetFeatures, + o); + + // Emit the name table for error messages. + o << "#ifndef NDEBUG\n"; + SubtargetFeatureInfo::emitNameTable(SubtargetFeatures, o); + o << "#endif // NDEBUG\n"; + + // Emit the available features compute function. + SubtargetFeatureInfo::emitComputeAvailableFeatures( + Target.getName(), "MCCodeEmitter", "computeAvailableFeatures", + SubtargetFeatures, o); + + // Emit the predicate verifier. + o << "void " << Target.getName() + << "MCCodeEmitter::verifyInstructionPredicates(\n" + << " const MCInst &Inst, uint64_t AvailableFeatures) const {\n" + << "#ifndef NDEBUG\n" + << " static uint64_t RequiredFeatures[] = {\n"; + unsigned InstIdx = 0; + for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) { + o << " "; + for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs("Predicates")) { + const auto &I = SubtargetFeatures.find(Predicate); + if (I != SubtargetFeatures.end()) + o << I->second.getEnumName() << " | "; + } + o << "0, // " << Inst->TheDef->getName() << " = " << InstIdx << "\n"; + InstIdx++; + } + o << " };\n\n"; + o << " assert(Inst.getOpcode() < " << InstIdx << ");\n"; + o << " uint64_t MissingFeatures =\n" + << " (AvailableFeatures & RequiredFeatures[Inst.getOpcode()]) ^\n" + << " RequiredFeatures[Inst.getOpcode()];\n" + << " if (MissingFeatures) {\n" + << " std::ostringstream Msg;\n" + << " Msg << \"Attempting to emit \" << MCII.getName(Inst.getOpcode()).str()\n" + << " << \" instruction but the \";\n" + << " for (unsigned i = 0; i < 8 * sizeof(MissingFeatures); ++i)\n" + << " if (MissingFeatures & (1ULL << i))\n" + << " Msg << SubtargetFeatureNames[i] << \" \";\n" + << " Msg << \"predicate(s) are not met\";\n" + << " report_fatal_error(Msg.str());\n" + << " }\n" + << "#endif // NDEBUG\n"; + o << "}\n"; + o << "#endif\n"; } } // End anonymous namespace Index: llvm/trunk/utils/TableGen/SubtargetFeatureInfo.h =================================================================== --- llvm/trunk/utils/TableGen/SubtargetFeatureInfo.h +++ llvm/trunk/utils/TableGen/SubtargetFeatureInfo.h @@ -14,6 +14,8 @@ #include "llvm/TableGen/Record.h" #include +#include +#include namespace llvm { class Record; @@ -37,6 +39,16 @@ static std::vector> getAll(const RecordKeeper &Records); + /// Emit the subtarget feature flag definitions. + static void emitSubtargetFeatureFlagEnumeration( + std::map + &SubtargetFeatures, + raw_ostream &OS); + + static void emitNameTable(std::map &SubtargetFeatures, + raw_ostream &OS); + /// Emit the function to compute the list of available features given a /// subtarget. /// @@ -44,10 +56,11 @@ /// Subtarget) /// \param ClassName The name of the class (without the prefix) /// that will contain the generated functions. + /// \param FuncName The name of the function to emit. /// \param SubtargetFeatures A map of TableGen records to the /// SubtargetFeatureInfo equivalent. static void emitComputeAvailableFeatures( - StringRef TargetName, StringRef ClassName, + StringRef TargetName, StringRef ClassName, StringRef FuncName, std::map &SubtargetFeatures, raw_ostream &OS); Index: llvm/trunk/utils/TableGen/SubtargetFeatureInfo.cpp =================================================================== --- llvm/trunk/utils/TableGen/SubtargetFeatureInfo.cpp +++ llvm/trunk/utils/TableGen/SubtargetFeatureInfo.cpp @@ -9,6 +9,7 @@ #include "SubtargetFeatureInfo.h" +#include "Types.h" #include "llvm/TableGen/Record.h" #include @@ -42,12 +43,41 @@ return SubtargetFeatures; } +void SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration( + std::map &SubtargetFeatures, + raw_ostream &OS) { + OS << "// Flags for subtarget features that participate in " + << "instruction matching.\n"; + OS << "enum SubtargetFeatureFlag : " + << getMinimalTypeForEnumBitfield(SubtargetFeatures.size()) << " {\n"; + for (const auto &SF : SubtargetFeatures) { + const SubtargetFeatureInfo &SFI = SF.second; + OS << " " << SFI.getEnumName() << " = (1ULL << " << SFI.Index << "),\n"; + } + OS << " Feature_None = 0\n"; + OS << "};\n\n"; +} + +void SubtargetFeatureInfo::emitNameTable( + std::map &SubtargetFeatures, + raw_ostream &OS) { + OS << "static const char *SubtargetFeatureNames[] = {\n"; + for (const auto &SF : SubtargetFeatures) { + const SubtargetFeatureInfo &SFI = SF.second; + OS << " \"" << SFI.getEnumName() << "\",\n"; + } + // A small number of targets have no predicates. Null terminate the array to + // avoid a zero-length array. + OS << " nullptr\n" + << "};\n\n"; +} + void SubtargetFeatureInfo::emitComputeAvailableFeatures( - StringRef TargetName, StringRef ClassName, + StringRef TargetName, StringRef ClassName, StringRef FuncName, std::map &SubtargetFeatures, raw_ostream &OS) { OS << "uint64_t " << TargetName << ClassName << "::\n" - << "ComputeAvailableFeatures(const FeatureBitset& FB) const {\n"; + << FuncName << "(const FeatureBitset& FB) const {\n"; OS << " uint64_t Features = 0;\n"; for (const auto &SF : SubtargetFeatures) { const SubtargetFeatureInfo &SFI = SF.second; Index: llvm/trunk/utils/TableGen/Types.h =================================================================== --- llvm/trunk/utils/TableGen/Types.h +++ llvm/trunk/utils/TableGen/Types.h @@ -17,6 +17,9 @@ /// MaxSize indicates the largest size of integer to consider (in bits) and only /// supports values of at least 32. const char *getMinimalTypeForRange(uint64_t Range, unsigned MaxSize = 64); + +/// Returns the smallest unsigned integer type that can hold the given bitfield. +const char *getMinimalTypeForEnumBitfield(uint64_t Size); } #endif Index: llvm/trunk/utils/TableGen/Types.cpp =================================================================== --- llvm/trunk/utils/TableGen/Types.cpp +++ llvm/trunk/utils/TableGen/Types.cpp @@ -35,3 +35,10 @@ return "uint16_t"; return "uint8_t"; } + +const char *llvm::getMinimalTypeForEnumBitfield(uint64_t Size) { + uint64_t MaxIndex = Size; + if (MaxIndex > 0) + MaxIndex--; + return getMinimalTypeForRange(1ULL << MaxIndex); +}