summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp')
-rw-r--r--contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp264
1 files changed, 88 insertions, 176 deletions
diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index 76228e0..1272d2b 100644
--- a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -97,6 +97,9 @@
//===----------------------------------------------------------------------===//
#include "CodeGenTarget.h"
+#include "SubtargetFeatureInfo.h"
+#include "Types.h"
+#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -126,7 +129,6 @@ MatchPrefix("match-prefix", cl::init(""),
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
@@ -353,6 +355,7 @@ public:
std::string TokenizingCharacters;
std::string SeparatorCharacters;
std::string BreakCharacters;
+ std::string Name;
int AsmVariantNo;
};
@@ -556,20 +559,17 @@ struct MatchableInfo {
/// findAsmOperand - Find the AsmOperand with the specified name and
/// suboperand index.
int findAsmOperand(StringRef N, int SubOpIdx) const {
- auto I = std::find_if(AsmOperands.begin(), AsmOperands.end(),
- [&](const AsmOperand &Op) {
- return Op.SrcOpName == N && Op.SubOpIdx == SubOpIdx;
- });
+ auto I = find_if(AsmOperands, [&](const AsmOperand &Op) {
+ return Op.SrcOpName == N && Op.SubOpIdx == SubOpIdx;
+ });
return (I != AsmOperands.end()) ? I - AsmOperands.begin() : -1;
}
/// findAsmOperandNamed - Find the first AsmOperand with the specified name.
/// This does not check the suboperand index.
int findAsmOperandNamed(StringRef N) const {
- auto I = std::find_if(AsmOperands.begin(), AsmOperands.end(),
- [&](const AsmOperand &Op) {
- return Op.SrcOpName == N;
- });
+ auto I = find_if(AsmOperands,
+ [&](const AsmOperand &Op) { return Op.SrcOpName == N; });
return (I != AsmOperands.end()) ? I - AsmOperands.begin() : -1;
}
@@ -653,28 +653,6 @@ private:
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;
@@ -754,7 +732,7 @@ public:
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
@@ -774,9 +752,9 @@ public:
}
bool hasOptionalOperands() const {
- return std::find_if(Classes.begin(), Classes.end(),
- [](const ClassInfo& Class){ return Class.IsOptional; })
- != Classes.end();
+ return find_if(Classes, [](const ClassInfo &Class) {
+ return Class.IsOptional;
+ }) != Classes.end();
}
};
@@ -1311,10 +1289,10 @@ buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters) {
if (CI->ValueName.empty()) {
CI->ClassName = Rec->getName();
- CI->Name = "MCK_" + Rec->getName();
+ CI->Name = "MCK_" + Rec->getName().str();
CI->ValueName = Rec->getName();
} else
- CI->ValueName = CI->ValueName + "," + Rec->getName();
+ CI->ValueName = CI->ValueName + "," + Rec->getName().str();
}
}
@@ -1437,21 +1415,15 @@ void AsmMatcherInfo::buildOperandMatchInfo() {
void AsmMatcherInfo::buildInfo() {
// Build information about all of the AssemblerPredicates.
- std::vector<Record*> 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<std::pair<Record *, SubtargetFeatureInfo>>
+ &SubtargetFeaturePairs = SubtargetFeatureInfo::getAll(Records);
+ SubtargetFeatures.insert(SubtargetFeaturePairs.begin(),
+ SubtargetFeaturePairs.end());
+#ifndef NDEBUG
+ for (const auto &Pair : SubtargetFeatures)
+ DEBUG(Pair.second.dump());
+#endif // NDEBUG
+ assert(SubtargetFeatures.size() <= 64 && "Too many subtarget features!");
bool HasMnemonicFirst = AsmParser->getValueAsBit("HasMnemonicFirst");
@@ -1471,6 +1443,7 @@ void AsmMatcherInfo::buildInfo() {
AsmVariant->getValueAsString("SeparatorCharacters");
Variant.BreakCharacters =
AsmVariant->getValueAsString("BreakCharacters");
+ Variant.Name = AsmVariant->getValueAsString("Name");
Variant.AsmVariantNo = AsmVariant->getValueAsInt("Variant");
for (const CodeGenInstruction *CGI : Target.getInstructionsByEnumValue()) {
@@ -1484,6 +1457,11 @@ void AsmMatcherInfo::buildInfo() {
if (CGI->TheDef->getValueAsBit("isCodeGenOnly"))
continue;
+ // Ignore instructions for different instructions
+ const std::string V = CGI->TheDef->getValueAsString("AsmVariantName");
+ if (!V.empty() && V != Variant.Name)
+ continue;
+
auto II = llvm::make_unique<MatchableInfo>(*CGI);
II->initialize(*this, SingletonRegisters, Variant, HasMnemonicFirst);
@@ -1512,6 +1490,10 @@ void AsmMatcherInfo::buildInfo() {
.startswith( MatchPrefix))
continue;
+ const std::string V = Alias->TheDef->getValueAsString("AsmVariantName");
+ if (!V.empty() && V != Variant.Name)
+ continue;
+
auto II = llvm::make_unique<MatchableInfo>(std::move(Alias));
II->initialize(*this, SingletonRegisters, Variant, HasMnemonicFirst);
@@ -1613,15 +1595,15 @@ void AsmMatcherInfo::buildInfo() {
// Reorder classes so that classes precede super classes.
Classes.sort();
-#ifndef NDEBUG
- // Verify that the table is now sorted
+#ifdef EXPENSIVE_CHECKS
+ // Verify that the table is sorted and operator < works transitively.
for (auto I = Classes.begin(), E = Classes.end(); I != E; ++I) {
for (auto J = I; J != E; ++J) {
assert(!(*J < *I));
assert(I == J || !J->isSubsetOf(*I));
}
}
-#endif // NDEBUG
+#endif
}
/// buildInstructionOperandReference - The specified operand is a reference to a
@@ -1814,13 +1796,13 @@ void MatchableInfo::buildAliasResultOperands() {
}
}
-static unsigned getConverterOperandID(const std::string &Name,
- SmallSetVector<std::string, 16> &Table,
- bool &IsNew) {
- IsNew = Table.insert(Name);
+static unsigned
+getConverterOperandID(const std::string &Name,
+ SmallSetVector<CachedHashString, 16> &Table,
+ bool &IsNew) {
+ IsNew = Table.insert(CachedHashString(Name));
- unsigned ID = IsNew ? Table.size() - 1 :
- std::find(Table.begin(), Table.end(), Name) - Table.begin();
+ unsigned ID = IsNew ? Table.size() - 1 : find(Table, Name) - Table.begin();
assert(ID < Table.size());
@@ -1831,13 +1813,13 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
std::vector<std::unique_ptr<MatchableInfo>> &Infos,
bool HasMnemonicFirst, bool HasOptionalOperands,
raw_ostream &OS) {
- SmallSetVector<std::string, 16> OperandConversionKinds;
- SmallSetVector<std::string, 16> InstructionConversionKinds;
+ SmallSetVector<CachedHashString, 16> OperandConversionKinds;
+ SmallSetVector<CachedHashString, 16> InstructionConversionKinds;
std::vector<std::vector<uint8_t> > ConversionTable;
size_t MaxRowLength = 2; // minimum is custom converter plus terminator.
// TargetOperandClass - This is the target's operand class, like X86Operand.
- std::string TargetOperandClass = Target.getName() + "Operand";
+ std::string TargetOperandClass = Target.getName().str() + "Operand";
// Write the convert function to a separate stream, so we can drop it after
// the enum. We'll build up the conversion handlers for the individual
@@ -1904,9 +1886,9 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
// Pre-populate the operand conversion kinds with the standard always
// available entries.
- OperandConversionKinds.insert("CVT_Done");
- OperandConversionKinds.insert("CVT_Reg");
- OperandConversionKinds.insert("CVT_Tied");
+ OperandConversionKinds.insert(CachedHashString("CVT_Done"));
+ OperandConversionKinds.insert(CachedHashString("CVT_Reg"));
+ OperandConversionKinds.insert(CachedHashString("CVT_Tied"));
enum { CVT_Done, CVT_Reg, CVT_Tied };
for (auto &II : Infos) {
@@ -1918,13 +1900,13 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
II->ConversionFnKind = Signature;
// Check if we have already generated this signature.
- if (!InstructionConversionKinds.insert(Signature))
+ if (!InstructionConversionKinds.insert(CachedHashString(Signature)))
continue;
// Remember this converter for the kind enum.
unsigned KindID = OperandConversionKinds.size();
- OperandConversionKinds.insert("CVT_" +
- getEnumNameForToken(AsmMatchConverter));
+ OperandConversionKinds.insert(
+ CachedHashString("CVT_" + getEnumNameForToken(AsmMatchConverter)));
// Add the converter row for this instruction.
ConversionTable.emplace_back();
@@ -2072,7 +2054,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
Reg = "0";
} else {
Reg = getQualifiedName(OpInfo.Register);
- Name = "reg" + OpInfo.Register->getName();
+ Name = "reg" + OpInfo.Register->getName().str();
}
Signature += "__" + Name;
Name = "CVT_" + Name;
@@ -2106,7 +2088,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
// Save the signature. If we already have it, don't add a new row
// to the table.
- if (!InstructionConversionKinds.insert(Signature))
+ if (!InstructionConversionKinds.insert(CachedHashString(Signature)))
continue;
// Add the row to the table.
@@ -2123,14 +2105,14 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
// Output the operand conversion kind enum.
OS << "enum OperatorConversionKind {\n";
- for (const std::string &Converter : OperandConversionKinds)
+ for (const auto &Converter : OperandConversionKinds)
OS << " " << Converter << ",\n";
OS << " CVT_NUM_CONVERTERS\n";
OS << "};\n\n";
// Output the instruction conversion kind enum.
OS << "enum InstructionConversionKind {\n";
- for (const std::string &Signature : InstructionConversionKinds)
+ for (const auto &Signature : InstructionConversionKinds)
OS << " " << Signature << ",\n";
OS << " CVT_NUM_SIGNATURES\n";
OS << "};\n\n";
@@ -2382,40 +2364,6 @@ static void emitMatchRegisterAltName(CodeGenTarget &Target, Record *AsmParser,
OS << "}\n\n";
}
-static const char *getMinimalTypeForRange(uint64_t Range) {
- assert(Range <= 0xFFFFFFFFFFFFFFFFULL && "Enum too large");
- if (Range > 0xFFFFFFFFULL)
- return "uint64_t";
- if (Range > 0xFFFF)
- return "uint32_t";
- if (Range > 0xFF)
- return "uint16_t";
- return "uint8_t";
-}
-
-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.
@@ -2456,55 +2404,6 @@ static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) {
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<StringRef,StringRef> 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<Record*> ReqFeatures = R->getValueAsListOfDefs("Predicates");
@@ -2646,7 +2545,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
// 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";
@@ -2719,8 +2618,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
// Emit the operand class switch to call the correct custom parser for
// the found operand class.
- OS << Target.getName() << ClassName << "::OperandMatchResultTy "
- << Target.getName() << ClassName << "::\n"
+ OS << "OperandMatchResultTy " << Target.getName() << ClassName << "::\n"
<< "tryCustomParseOperand(OperandVector"
<< " &Operands,\n unsigned MCK) {\n\n"
<< " switch(MCK) {\n";
@@ -2741,8 +2639,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
// Emit the static custom operand parser. This code is very similar with
// the other matcher. Also use MatchResultTy here just in case we go for
// a better error handling.
- OS << Target.getName() << ClassName << "::OperandMatchResultTy "
- << Target.getName() << ClassName << "::\n"
+ OS << "OperandMatchResultTy " << Target.getName() << ClassName << "::\n"
<< "MatchOperandParserImpl(OperandVector"
<< " &Operands,\n StringRef Mnemonic) {\n";
@@ -2822,15 +2719,15 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
const std::unique_ptr<MatchableInfo> &b){
return *a < *b;});
-#ifndef NDEBUG
- // Verify that the table is now sorted
+#ifdef EXPENSIVE_CHECKS
+ // Verify that the table is sorted and operator < works transitively.
for (auto I = Info.Matchables.begin(), E = Info.Matchables.end(); I != E;
++I) {
for (auto J = I; J != E; ++J) {
assert(!(**J < **I));
}
}
-#endif // NDEBUG
+#endif
DEBUG_WITH_TYPE("instruction_info", {
for (const auto &MI : Info.Matchables)
@@ -2896,11 +2793,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
<< " unsigned VariantID = 0);\n";
if (!Info.OperandMatchInfo.empty()) {
- OS << "\n enum OperandMatchResultTy {\n";
- OS << " MatchOperand_Success, // operand matched successfully\n";
- OS << " MatchOperand_NoMatch, // operand did not match\n";
- OS << " MatchOperand_ParseFail // operand matched but had errors\n";
- OS << " };\n";
OS << " OperandMatchResultTy MatchOperandParserImpl(\n";
OS << " OperandVector &Operands,\n";
OS << " StringRef Mnemonic);\n";
@@ -2922,7 +2814,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
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
@@ -2967,7 +2860,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
emitValidateOperandClass(Info, OS);
// Emit the available features compute function.
- emitComputeAvailableFeatures(Info, OS);
+ SubtargetFeatureInfo::emitComputeAvailableFeatures(
+ Info.Target.getName(), ClassName, "ComputeAvailableFeatures",
+ Info.SubtargetFeatures, OS);
StringToOffsetTable StringTable;
@@ -3005,7 +2900,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
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()))
@@ -3254,8 +3149,24 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " }\n";
OS << "\n";
OS << " Inst.clear();\n\n";
+ OS << " Inst.setOpcode(it->Opcode);\n";
+ // Verify the instruction with the target-specific match predicate function.
+ OS << " // We have a potential match but have not rendered the operands.\n"
+ << " // Check the target predicate to handle any context sensitive\n"
+ " // constraints.\n"
+ << " // For example, Ties that are referenced multiple times must be\n"
+ " // checked here to ensure the input is the same for each match\n"
+ " // constraints. If we leave it any later the ties will have been\n"
+ " // canonicalized\n"
+ << " unsigned MatchResult;\n"
+ << " if ((MatchResult = checkEarlyTargetMatchPredicate(Inst, "
+ "Operands)) != Match_Success) {\n"
+ << " Inst.clear();\n"
+ << " RetCode = MatchResult;\n"
+ << " HadMatchOtherThanPredicate = true;\n"
+ << " continue;\n"
+ << " }\n\n";
OS << " if (matchingInlineAsm) {\n";
- OS << " Inst.setOpcode(it->Opcode);\n";
OS << " convertToMapAndConstraints(it->ConvertFn, Operands);\n";
OS << " return Match_Success;\n";
OS << " }\n\n";
@@ -3272,7 +3183,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
// Verify the instruction with the target-specific match predicate function.
OS << " // We have a potential match. Check the target predicate to\n"
<< " // handle any context sensitive constraints.\n"
- << " unsigned MatchResult;\n"
<< " if ((MatchResult = checkTargetMatchPredicate(Inst)) !="
<< " Match_Success) {\n"
<< " Inst.clear();\n"
@@ -3289,7 +3199,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
if (HasDeprecation) {
OS << " std::string Info;\n";
- OS << " if (MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, getSTI(), Info)) {\n";
+ OS << " if (!getParser().getTargetParser().\n";
+ OS << " getTargetOptions().MCNoDeprecatedWarn &&\n";
+ OS << " MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, getSTI(), Info)) {\n";
OS << " SMLoc Loc = ((" << Target.getName()
<< "Operand&)*Operands[0]).getStartLoc();\n";
OS << " getParser().Warning(Loc, Info, None);\n";
OpenPOWER on IntegriCloud