Index: utils/TableGen/AsmMatcherEmitter.cpp =================================================================== --- utils/TableGen/AsmMatcherEmitter.cpp +++ utils/TableGen/AsmMatcherEmitter.cpp @@ -97,6 +97,7 @@ //===----------------------------------------------------------------------===// #include "CodeGenTarget.h" +#include "SubtargetFeatureInfo.h" #include "llvm/ADT/CachedHashString.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLExtras.h" @@ -127,7 +128,6 @@ namespace { class AsmMatcherInfo; -struct SubtargetFeatureInfo; // Register sets are used as keys in some second-order sets TableGen creates // when generating its data structures. This means that the order of two @@ -652,28 +652,6 @@ void addAsmOperand(StringRef Token, bool IsIsolatedToken = false); }; -/// SubtargetFeatureInfo - Helper class for storing information on a subtarget -/// feature which participates in instruction matching. -struct SubtargetFeatureInfo { - /// \brief The predicate record for this feature. - Record *TheDef; - - /// \brief An unique index assigned to represent this feature. - uint64_t Index; - - SubtargetFeatureInfo(Record *D, uint64_t Idx) : TheDef(D), Index(Idx) {} - - /// \brief The name of the enumerated constant identifying this feature. - std::string getEnumName() const { - return "Feature_" + TheDef->getName(); - } - - void dump() const { - errs() << getEnumName() << " " << Index << "\n"; - TheDef->dump(); - } -}; - struct OperandMatchEntry { unsigned OperandMask; const MatchableInfo* MI; @@ -753,7 +731,7 @@ CodeGenTarget &Target, RecordKeeper &Records); - /// buildInfo - Construct the various tables used during matching. + /// Construct the various tables used during matching. void buildInfo(); /// buildOperandMatchInfo - Build the necessary information to handle user @@ -1436,21 +1414,13 @@ void AsmMatcherInfo::buildInfo() { // Build information about all of the AssemblerPredicates. - std::vector AllPredicates = - Records.getAllDerivedDefinitions("Predicate"); - for (Record *Pred : AllPredicates) { - // Ignore predicates that are not intended for the assembler. - if (!Pred->getValueAsBit("AssemblerMatcherPredicate")) - continue; - - if (Pred->getName().empty()) - PrintFatalError(Pred->getLoc(), "Predicate has no name!"); - - SubtargetFeatures.insert(std::make_pair( - Pred, SubtargetFeatureInfo(Pred, SubtargetFeatures.size()))); - DEBUG(SubtargetFeatures.find(Pred)->second.dump()); - assert(SubtargetFeatures.size() <= 64 && "Too many subtarget features!"); - } + const std::vector> + &SubtargetFeaturePairs = SubtargetFeatureInfo::getAll(Records); + SubtargetFeatures.insert(SubtargetFeaturePairs.begin(), + SubtargetFeaturePairs.end()); + for (const auto &Pair : SubtargetFeatures) + DEBUG(Pair.second.dump()); + assert(SubtargetFeatures.size() <= 64 && "Too many subtarget features!"); bool HasMnemonicFirst = AsmParser->getValueAsBit("HasMnemonicFirst"); @@ -2465,55 +2435,6 @@ OS << "}\n\n"; } -/// emitComputeAvailableFeatures - Emit the function to compute the list of -/// available features given a subtarget. -static void emitComputeAvailableFeatures(AsmMatcherInfo &Info, - raw_ostream &OS) { - std::string ClassName = - Info.AsmParser->getValueAsString("AsmParserClassName"); - - OS << "uint64_t " << Info.Target.getName() << ClassName << "::\n" - << "ComputeAvailableFeatures(const FeatureBitset& FB) const {\n"; - OS << " uint64_t Features = 0;\n"; - for (const auto &SF : Info.SubtargetFeatures) { - const SubtargetFeatureInfo &SFI = SF.second; - - OS << " if ("; - std::string CondStorage = - SFI.TheDef->getValueAsString("AssemblerCondString"); - StringRef Conds = CondStorage; - std::pair Comma = Conds.split(','); - bool First = true; - do { - if (!First) - OS << " && "; - - bool Neg = false; - StringRef Cond = Comma.first; - if (Cond[0] == '!') { - Neg = true; - Cond = Cond.substr(1); - } - - OS << "("; - if (Neg) - OS << "!"; - OS << "FB[" << Info.Target.getName() << "::" << Cond << "])"; - - if (Comma.second.empty()) - break; - - First = false; - Comma = Comma.second.split(','); - } while (true); - - OS << ")\n"; - OS << " Features |= " << SFI.getEnumName() << ";\n"; - } - OS << " return Features;\n"; - OS << "}\n\n"; -} - static std::string GetAliasRequiredFeatures(Record *R, const AsmMatcherInfo &Info) { std::vector ReqFeatures = R->getValueAsListOfDefs("Predicates"); @@ -2969,7 +2890,8 @@ emitValidateOperandClass(Info, OS); // Emit the available features compute function. - emitComputeAvailableFeatures(Info, OS); + SubtargetFeatureInfo::emitComputeAvailableFeatures( + Info.Target.getName(), ClassName, Info.SubtargetFeatures, OS); StringToOffsetTable StringTable; Index: utils/TableGen/CMakeLists.txt =================================================================== --- utils/TableGen/CMakeLists.txt +++ utils/TableGen/CMakeLists.txt @@ -29,6 +29,7 @@ RegisterInfoEmitter.cpp SearchableTableEmitter.cpp SubtargetEmitter.cpp + SubtargetFeatureInfo.cpp TableGen.cpp X86DisassemblerTables.cpp X86ModRMFilters.cpp Index: utils/TableGen/SubtargetFeatureInfo.h =================================================================== --- /dev/null +++ utils/TableGen/SubtargetFeatureInfo.h @@ -0,0 +1,57 @@ +//===- SubtargetFeatureInfo.h - Helpers for subtarget features ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_UTIL_TABLEGEN_SUBTARGETFEATUREINFO_H +#define LLVM_UTIL_TABLEGEN_SUBTARGETFEATUREINFO_H + +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" + +#include + +namespace llvm { +class Record; +class RecordKeeper; + +/// Helper class for storing information on a subtarget feature which +/// participates in instruction matching. +struct SubtargetFeatureInfo { + /// \brief The predicate record for this feature. + Record *TheDef; + + /// \brief An unique index assigned to represent this feature. + uint64_t Index; + + SubtargetFeatureInfo(Record *D, uint64_t Idx) : TheDef(D), Index(Idx) {} + + /// \brief The name of the enumerated constant identifying this feature. + std::string getEnumName() const { return "Feature_" + TheDef->getName(); } + + void dump() const; + static std::vector> + getAll(const RecordKeeper &Records); + + /// Emit the function to compute the list of available features given a + /// subtarget. + /// + /// \param TargetName The name of the target as used in class prefixes (e.g. + /// Subtarget) + /// \param ClassName The name of the class (without the prefix) + /// that will contain the generated functions. + /// \param SubtargetFeatures A map of TableGen records to the + /// SubtargetFeatureInfo equivalent. + static void emitComputeAvailableFeatures( + StringRef TargetName, StringRef ClassName, + std::map + &SubtargetFeatures, + raw_ostream &OS); +}; +} // end namespace llvm + +#endif // LLVM_UTIL_TABLEGEN_SUBTARGETFEATUREINFO_H Index: utils/TableGen/SubtargetFeatureInfo.cpp =================================================================== --- /dev/null +++ utils/TableGen/SubtargetFeatureInfo.cpp @@ -0,0 +1,89 @@ +//===- SubtargetFeatureInfo.cpp - Helpers for subtarget features ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "SubtargetFeatureInfo.h" + +#include "llvm/TableGen/Record.h" + +#include + +using namespace llvm; + +void SubtargetFeatureInfo::dump() const { + errs() << getEnumName() << " " << Index << "\n"; + TheDef->dump(); +} + +std::vector> +SubtargetFeatureInfo::getAll(const RecordKeeper &Records) { + std::vector> SubtargetFeatures; + std::vector AllPredicates = + Records.getAllDerivedDefinitions("Predicate"); + for (Record *Pred : AllPredicates) { + // Ignore predicates that are not intended for the assembler. + // + // The "AssemblerMatcherPredicate" string should be promoted to an argument + // if we re-use the machinery for non-assembler purposes in future. + if (!Pred->getValueAsBit("AssemblerMatcherPredicate")) + continue; + + if (Pred->getName().empty()) + PrintFatalError(Pred->getLoc(), "Predicate has no name!"); + + SubtargetFeatures.emplace_back( + Pred, SubtargetFeatureInfo(Pred, SubtargetFeatures.size())); + } + return SubtargetFeatures; +} + +void SubtargetFeatureInfo::emitComputeAvailableFeatures( + StringRef TargetName, StringRef ClassName, + std::map &SubtargetFeatures, + raw_ostream &OS) { + OS << "uint64_t " << TargetName << ClassName << "::\n" + << "ComputeAvailableFeatures(const FeatureBitset& FB) const {\n"; + OS << " uint64_t Features = 0;\n"; + for (const auto &SF : SubtargetFeatures) { + const SubtargetFeatureInfo &SFI = SF.second; + + OS << " if ("; + std::string CondStorage = + SFI.TheDef->getValueAsString("AssemblerCondString"); + StringRef Conds = CondStorage; + std::pair Comma = Conds.split(','); + bool First = true; + do { + if (!First) + OS << " && "; + + bool Neg = false; + StringRef Cond = Comma.first; + if (Cond[0] == '!') { + Neg = true; + Cond = Cond.substr(1); + } + + OS << "("; + if (Neg) + OS << "!"; + OS << "FB[" << TargetName << "::" << Cond << "])"; + + if (Comma.second.empty()) + break; + + First = false; + Comma = Comma.second.split(','); + } while (true); + + OS << ")\n"; + OS << " Features |= " << SFI.getEnumName() << ";\n"; + } + OS << " return Features;\n"; + OS << "}\n\n"; +}