diff options
Diffstat (limited to 'utils')
44 files changed, 823 insertions, 545 deletions
diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index a1f4be9..a124377 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -965,7 +965,8 @@ static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr, /// CountNumNewlinesBetween - Count the number of newlines in the specified /// range. -static unsigned CountNumNewlinesBetween(StringRef Range) { +static unsigned CountNumNewlinesBetween(StringRef Range, + const char *&FirstNewLine) { unsigned NumNewLines = 0; while (1) { // Scan for newline. @@ -980,6 +981,9 @@ static unsigned CountNumNewlinesBetween(StringRef Range) { (Range[0] != Range[1])) Range = Range.substr(1); Range = Range.substr(1); + + if (NumNewLines == 1) + FirstNewLine = Range.begin(); } } @@ -1039,7 +1043,8 @@ bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const { SMLoc::getFromPointer(Buffer.data())))->getBufferStart() && "CHECK-NEXT can't be the first check in a file"); - unsigned NumNewLines = CountNumNewlinesBetween(Buffer); + const char *FirstNewLine = 0; + unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine); if (NumNewLines == 0) { SM.PrintMessage(Loc, SourceMgr::DK_Error, Prefix + @@ -1058,6 +1063,8 @@ bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const { SourceMgr::DK_Note, "'next' match was here"); SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, "previous match ended here"); + SM.PrintMessage(SMLoc::getFromPointer(FirstNewLine), SourceMgr::DK_Note, + "non-matching line after previous match is here"); return true; } diff --git a/utils/FileUpdate/FileUpdate.cpp b/utils/FileUpdate/FileUpdate.cpp index 5ccf3f3..1bf1248 100644 --- a/utils/FileUpdate/FileUpdate.cpp +++ b/utils/FileUpdate/FileUpdate.cpp @@ -14,6 +14,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" diff --git a/utils/PerfectShuffle/CMakeLists.txt b/utils/PerfectShuffle/CMakeLists.txt new file mode 100644 index 0000000..ed70760 --- /dev/null +++ b/utils/PerfectShuffle/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_utility(llvm-PerfectShuffle + PerfectShuffle.cpp + ) diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 4169f8d..3d72741 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -117,6 +117,8 @@ #include <sstream> using namespace llvm; +#define DEBUG_TYPE "asm-matcher-emitter" + static cl::opt<std::string> MatchPrefix("match-prefix", cl::init(""), cl::desc("Only match instructions with the given prefix")); @@ -191,10 +193,10 @@ struct ClassInfo { /// parsing on the operand. std::string ParserMethod; - /// For register classes, the records for all the registers in this class. + /// For register classes: the records for all the registers in this class. RegisterSet Registers; - /// For custom match classes, he diagnostic kind for when the predicate fails. + /// For custom match classes: the diagnostic kind for when the predicate fails. std::string DiagnosticType; public: /// isRegisterClass() - Check if this is a register class. @@ -306,8 +308,8 @@ struct MatchableInfo { /// Register record if this token is singleton register. Record *SingletonReg; - explicit AsmOperand(StringRef T) : Token(T), Class(0), SubOpIdx(-1), - SingletonReg(0) {} + explicit AsmOperand(StringRef T) : Token(T), Class(nullptr), SubOpIdx(-1), + SingletonReg(nullptr) {} }; /// ResOperand - This represents a single operand in the result instruction @@ -571,6 +573,11 @@ struct SubtargetFeatureInfo { std::string getEnumName() const { return "Feature_" + TheDef->getName(); } + + void dump() { + errs() << getEnumName() << " " << Index << "\n"; + TheDef->dump(); + } }; struct OperandMatchEntry { @@ -666,7 +673,7 @@ public: assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!"); std::map<Record*, SubtargetFeatureInfo*, LessRecordByID>::const_iterator I = SubtargetFeatures.find(Def); - return I == SubtargetFeatures.end() ? 0 : I->second; + return I == SubtargetFeatures.end() ? nullptr : I->second; } RecordKeeper &getRecords() const { @@ -1018,7 +1025,7 @@ AsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) { // RegisterOperand may have an associated ParserMatchClass. If it does, // use it, else just fall back to the underlying register class. const RecordVal *R = Rec->getValue("ParserMatchClass"); - if (R == 0 || R->getValue() == 0) + if (!R || !R->getValue()) PrintFatalError("Record `" + Rec->getName() + "' does not have a ParserMatchClass!\n"); @@ -1322,6 +1329,7 @@ void AsmMatcherInfo::buildInfo() { unsigned FeatureNo = SubtargetFeatures.size(); SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo); + DEBUG(SubtargetFeatures[Pred]->dump()); assert(FeatureNo < 32 && "Too many subtarget features!"); } @@ -1373,7 +1381,8 @@ void AsmMatcherInfo::buildInfo() { std::vector<Record*> AllInstAliases = Records.getAllDerivedDefinitions("InstAlias"); for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) { - CodeGenInstAlias *Alias = new CodeGenInstAlias(AllInstAliases[i], Target); + CodeGenInstAlias *Alias = + new CodeGenInstAlias(AllInstAliases[i], AsmVariantNo, Target); // If the tblgen -match-prefix option is specified (for tblgen hackers), // filter the set of instruction aliases we consider, based on the target @@ -1897,7 +1906,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, } case MatchableInfo::ResOperand::RegOperand: { std::string Reg, Name; - if (OpInfo.Register == 0) { + if (!OpInfo.Register) { Name = "reg0"; Reg = "0"; } else { @@ -2196,18 +2205,35 @@ static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser, OS << "}\n\n"; } +static const char *getMinimalTypeForRange(uint64_t Range) { + assert(Range <= 0xFFFFFFFFULL && "Enum too large"); + 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 {\n"; + OS << "enum SubtargetFeatureFlag : " << getMinimalRequiredFeaturesType(Info) + << " {\n"; for (std::map<Record*, SubtargetFeatureInfo*, LessRecordByID>::const_iterator it = Info.SubtargetFeatures.begin(), ie = Info.SubtargetFeatures.end(); it != ie; ++it) { SubtargetFeatureInfo &SFI = *it->second; - OS << " " << SFI.getEnumName() << " = (1 << " << SFI.Index << "),\n"; + OS << " " << SFI.getEnumName() << " = (1U << " << SFI.Index << "),\n"; } OS << " Feature_None = 0\n"; OS << "};\n\n"; @@ -2319,7 +2345,7 @@ static std::string GetAliasRequiredFeatures(Record *R, for (unsigned i = 0, e = ReqFeatures.size(); i != e; ++i) { SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]); - if (F == 0) + if (!F) PrintFatalError(R->getLoc(), "Predicate '" + ReqFeatures[i]->getName() + "' is not marked as an AssemblerPredicate!"); @@ -2443,15 +2469,6 @@ static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info, return true; } -static const char *getMinimalTypeForRange(uint64_t Range) { - assert(Range < 0xFFFFFFFFULL && "Enum too large"); - if (Range > 0xFFFF) - return "uint32_t"; - if (Range > 0xFF) - return "uint16_t"; - return "uint8_t"; -} - static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, const AsmMatcherInfo &Info, StringRef ClassName, StringToOffsetTable &StringTable, @@ -2466,7 +2483,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, // Emit the static custom operand parsing table; OS << "namespace {\n"; OS << " struct OperandMatchEntry {\n"; - OS << " " << getMinimalTypeForRange(1ULL << Info.SubtargetFeatures.size()) + OS << " " << getMinimalRequiredFeaturesType(Info) << " RequiredFeatures;\n"; OS << " " << getMinimalTypeForRange(MaxMnemonicIndex) << " Mnemonic;\n"; @@ -2802,7 +2819,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " uint16_t Opcode;\n"; OS << " " << getMinimalTypeForRange(Info.Matchables.size()) << " ConvertFn;\n"; - OS << " " << getMinimalTypeForRange(1ULL << Info.SubtargetFeatures.size()) + OS << " " << getMinimalRequiredFeaturesType(Info) << " RequiredFeatures;\n"; OS << " " << getMinimalTypeForRange(Info.Classes.size()) << " Classes[" << MaxNumOperands << "];\n"; @@ -2881,8 +2898,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { for (unsigned VC = 0; VC != VariantCount; ++VC) { Record *AsmVariant = Target.getAsmParserVariant(VC); int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); - OS << " case " << AsmVariantNo << ": Start = MatchTable" << VC - << "; End = array_endof(MatchTable" << VC << "); break;\n"; + OS << " case " << AsmVariantNo << ": Start = std::begin(MatchTable" << VC + << "); End = std::end(MatchTable" << VC << "); break;\n"; } OS << " }\n"; OS << " // Search the table.\n"; @@ -2936,8 +2953,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { for (unsigned VC = 0; VC != VariantCount; ++VC) { Record *AsmVariant = Target.getAsmParserVariant(VC); int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); - OS << " case " << AsmVariantNo << ": Start = MatchTable" << VC - << "; End = array_endof(MatchTable" << VC << "); break;\n"; + OS << " case " << AsmVariantNo << ": Start = std::begin(MatchTable" << VC + << "); End = std::end(MatchTable" << VC << "); break;\n"; } OS << " }\n"; OS << " // Search the table.\n"; diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index f9e1990..2741d8f 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -15,6 +15,7 @@ #include "AsmWriterInst.h" #include "CodeGenTarget.h" #include "SequenceToOffsetTable.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Debug.h" @@ -29,6 +30,8 @@ #include <vector> using namespace llvm; +#define DEBUG_TYPE "asm-writer-emitter" + namespace { class AsmWriterEmitter { RecordKeeper &Records; @@ -36,6 +39,7 @@ class AsmWriterEmitter { std::map<const CodeGenInstruction*, AsmWriterInst*> CGIAWIMap; const std::vector<const CodeGenInstruction*> *NumberedInstructions; std::vector<AsmWriterInst> Instructions; + std::vector<std::string> PrintMethods; public: AsmWriterEmitter(RecordKeeper &R); @@ -152,7 +156,7 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands, for (unsigned i = 0, e = NumberedInstructions->size(); i != e; ++i) { const AsmWriterInst *Inst = getAsmWriterInstByID(i); - if (Inst == 0) + if (!Inst) continue; // PHI, INLINEASM, CFI_INSTRUCTION, etc. std::string Command; @@ -301,7 +305,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { // representation. for (unsigned i = 0, e = NumberedInstructions->size(); i != e; ++i) { AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions->at(i)]; - if (AWI != 0 && + if (AWI && AWI->Operands[0].OperandType == AsmWriterOperand::isLiteralTextOperand && !AWI->Operands[0].Str.empty()) { @@ -317,7 +321,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { for (unsigned i = 0, e = NumberedInstructions->size(); i != e; ++i) { AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions->at(i)]; unsigned Idx; - if (AWI == 0) { + if (!AWI) { // Something not handled by the asmwriter printer. Idx = ~0U; } else if (AWI->Operands[0].OperandType != @@ -626,22 +630,45 @@ namespace { // alias for that pattern. class IAPrinter { std::vector<std::string> Conds; - std::map<StringRef, unsigned> OpMap; + std::map<StringRef, std::pair<int, int>> OpMap; + SmallVector<Record*, 4> ReqFeatures; + std::string Result; std::string AsmString; - SmallVector<Record*, 4> ReqFeatures; public: - IAPrinter(std::string R, std::string AS) - : Result(R), AsmString(AS) {} + IAPrinter(std::string R, std::string AS) : Result(R), AsmString(AS) {} void addCond(const std::string &C) { Conds.push_back(C); } - void addOperand(StringRef Op, unsigned Idx) { - assert(Idx < 0xFF && "Index too large!"); - OpMap[Op] = Idx; + void addOperand(StringRef Op, int OpIdx, int PrintMethodIdx = -1) { + assert(OpIdx >= 0 && OpIdx < 0xFE && "Idx out of range"); + assert(PrintMethodIdx >= -1 && PrintMethodIdx < 0xFF && + "Idx out of range"); + OpMap[Op] = std::make_pair(OpIdx, PrintMethodIdx); } - unsigned getOpIndex(StringRef Op) { return OpMap[Op]; } + bool isOpMapped(StringRef Op) { return OpMap.find(Op) != OpMap.end(); } + int getOpIndex(StringRef Op) { return OpMap[Op].first; } + std::pair<int, int> &getOpData(StringRef Op) { return OpMap[Op]; } + + std::pair<StringRef, StringRef::iterator> parseName(StringRef::iterator Start, + StringRef::iterator End) { + StringRef::iterator I = Start; + if (*I == '{') { + // ${some_name} + Start = ++I; + while (I != End && *I != '}') + ++I; + } else { + // $name, just eat the usual suspects. + while (I != End && + ((*I >= 'a' && *I <= 'z') || (*I >= 'A' && *I <= 'Z') || + (*I >= '0' && *I <= '9') || *I == '_')) + ++I; + } + + return std::make_pair(StringRef(Start, I - Start), I); + } void print(raw_ostream &O) { if (Conds.empty() && ReqFeatures.empty()) { @@ -667,28 +694,30 @@ public: // Directly mangle mapped operands into the string. Each operand is // identified by a '$' sign followed by a byte identifying the number of the // operand. We add one to the index to avoid zero bytes. - std::pair<StringRef, StringRef> ASM = StringRef(AsmString).split(' '); - SmallString<128> OutString = ASM.first; - if (!ASM.second.empty()) { - raw_svector_ostream OS(OutString); - OS << ' '; - for (StringRef::iterator I = ASM.second.begin(), E = ASM.second.end(); - I != E;) { - OS << *I; - if (*I == '$') { - StringRef::iterator Start = ++I; - while (I != E && - ((*I >= 'a' && *I <= 'z') || (*I >= 'A' && *I <= 'Z') || - (*I >= '0' && *I <= '9') || *I == '_')) - ++I; - StringRef Name(Start, I - Start); - assert(isOpMapped(Name) && "Unmapped operand!"); - OS << format("\\x%02X", (unsigned char)getOpIndex(Name) + 1); - } else { - ++I; - } + StringRef ASM(AsmString); + SmallString<128> OutString; + raw_svector_ostream OS(OutString); + for (StringRef::iterator I = ASM.begin(), E = ASM.end(); I != E;) { + OS << *I; + if (*I == '$') { + StringRef Name; + std::tie(Name, I) = parseName(++I, E); + assert(isOpMapped(Name) && "Unmapped operand!"); + + int OpIndex, PrintIndex; + std::tie(OpIndex, PrintIndex) = getOpData(Name); + if (PrintIndex == -1) { + // Can use the default printOperand route. + OS << format("\\x%02X", (unsigned char)OpIndex + 1); + } else + // 3 bytes if a PrintMethod is needed: 0xFF, the MCInst operand + // number, and which of our pre-detected Methods to call. + OS << format("\\xFF\\x%02X\\x%02X", OpIndex + 1, PrintIndex + 1); + } else { + ++I; } } + OS.flush(); // Emit the string. O.indent(6) << "AsmString = \"" << OutString.str() << "\";\n"; @@ -709,109 +738,99 @@ public: return true; } - - bool operator()(const IAPrinter &RHS) { - if (Conds.size() < RHS.Conds.size()) - return true; - - unsigned Idx = 0; - for (std::vector<std::string>::iterator - I = Conds.begin(), E = Conds.end(); I != E; ++I) - if (*I != RHS.Conds[Idx++]) - return *I < RHS.Conds[Idx++]; - - return false; - } }; } // end anonymous namespace -static unsigned CountNumOperands(StringRef AsmString) { - unsigned NumOps = 0; - std::pair<StringRef, StringRef> ASM = AsmString.split(' '); +static unsigned CountNumOperands(StringRef AsmString, unsigned Variant) { + std::string FlatAsmString = + CodeGenInstruction::FlattenAsmStringVariants(AsmString, Variant); + AsmString = FlatAsmString; - while (!ASM.second.empty()) { - ++NumOps; - ASM = ASM.second.split(' '); - } - - return NumOps; + return AsmString.count(' ') + AsmString.count('\t'); } -static unsigned CountResultNumOperands(StringRef AsmString) { - unsigned NumOps = 0; - std::pair<StringRef, StringRef> ASM = AsmString.split('\t'); - - if (!ASM.second.empty()) { - size_t I = ASM.second.find('{'); - StringRef Str = ASM.second; - if (I != StringRef::npos) - Str = ASM.second.substr(I, ASM.second.find('|', I)); - - ASM = Str.split(' '); +namespace { +struct AliasPriorityComparator { + typedef std::pair<CodeGenInstAlias *, int> ValueType; + bool operator()(const ValueType &LHS, const ValueType &RHS) { + if (LHS.second == RHS.second) { + // We don't actually care about the order, but for consistency it + // shouldn't depend on pointer comparisons. + return LHS.first->TheDef->getName() < RHS.first->TheDef->getName(); + } - do { - ++NumOps; - ASM = ASM.second.split(' '); - } while (!ASM.second.empty()); + // Aliases with larger priorities should be considered first. + return LHS.second > RHS.second; } - - return NumOps; +}; } + void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { Record *AsmWriter = Target.getAsmWriter(); O << "\n#ifdef PRINT_ALIAS_INSTR\n"; O << "#undef PRINT_ALIAS_INSTR\n\n"; + ////////////////////////////// + // Gather information about aliases we need to print + ////////////////////////////// + // Emit the method that prints the alias instruction. std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); + unsigned Variant = AsmWriter->getValueAsInt("Variant"); std::vector<Record*> AllInstAliases = Records.getAllDerivedDefinitions("InstAlias"); // Create a map from the qualified name to a list of potential matches. - std::map<std::string, std::vector<CodeGenInstAlias*> > AliasMap; + typedef std::set<std::pair<CodeGenInstAlias*, int>, AliasPriorityComparator> + AliasWithPriority; + std::map<std::string, AliasWithPriority> AliasMap; for (std::vector<Record*>::iterator I = AllInstAliases.begin(), E = AllInstAliases.end(); I != E; ++I) { - CodeGenInstAlias *Alias = new CodeGenInstAlias(*I, Target); + CodeGenInstAlias *Alias = new CodeGenInstAlias(*I, Variant, Target); const Record *R = *I; - if (!R->getValueAsBit("EmitAlias")) - continue; // We were told not to emit the alias, but to emit the aliasee. + int Priority = R->getValueAsInt("EmitPriority"); + if (Priority < 1) + continue; // Aliases with priority 0 are never emitted. + const DagInit *DI = R->getValueAsDag("ResultInst"); const DefInit *Op = cast<DefInit>(DI->getOperator()); - AliasMap[getQualifiedName(Op->getDef())].push_back(Alias); + AliasMap[getQualifiedName(Op->getDef())].insert(std::make_pair(Alias, + Priority)); } // A map of which conditions need to be met for each instruction operand // before it can be matched to the mnemonic. std::map<std::string, std::vector<IAPrinter*> > IAPrinterMap; - for (std::map<std::string, std::vector<CodeGenInstAlias*> >::iterator - I = AliasMap.begin(), E = AliasMap.end(); I != E; ++I) { - std::vector<CodeGenInstAlias*> &Aliases = I->second; - - for (std::vector<CodeGenInstAlias*>::iterator - II = Aliases.begin(), IE = Aliases.end(); II != IE; ++II) { - const CodeGenInstAlias *CGA = *II; + for (auto &Aliases : AliasMap) { + for (auto &Alias : Aliases.second) { + const CodeGenInstAlias *CGA = Alias.first; unsigned LastOpNo = CGA->ResultInstOperandIndex.size(); unsigned NumResultOps = - CountResultNumOperands(CGA->ResultInst->AsmString); + CountNumOperands(CGA->ResultInst->AsmString, Variant); // Don't emit the alias if it has more operands than what it's aliasing. - if (NumResultOps < CountNumOperands(CGA->AsmString)) + if (NumResultOps < CountNumOperands(CGA->AsmString, Variant)) continue; IAPrinter *IAP = new IAPrinter(CGA->Result->getAsString(), CGA->AsmString); + unsigned NumMIOps = 0; + for (auto &Operand : CGA->ResultOperands) + NumMIOps += Operand.getMINumOperands(); + std::string Cond; - Cond = std::string("MI->getNumOperands() == ") + llvm::utostr(LastOpNo); + Cond = std::string("MI->getNumOperands() == ") + llvm::utostr(NumMIOps); IAP->addCond(Cond); bool CantHandle = false; + unsigned MIOpNum = 0; for (unsigned i = 0, e = LastOpNo; i != e; ++i) { const CodeGenInstAlias::ResultOperand &RO = CGA->ResultOperands[i]; @@ -819,42 +838,56 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { case CodeGenInstAlias::ResultOperand::K_Record: { const Record *Rec = RO.getRecord(); StringRef ROName = RO.getName(); - + int PrintMethodIdx = -1; + + // These two may have a PrintMethod, which we want to record (if it's + // the first time we've seen it) and provide an index for the aliasing + // code to use. + if (Rec->isSubClassOf("RegisterOperand") || + Rec->isSubClassOf("Operand")) { + std::string PrintMethod = Rec->getValueAsString("PrintMethod"); + if (PrintMethod != "" && PrintMethod != "printOperand") { + PrintMethodIdx = std::find(PrintMethods.begin(), + PrintMethods.end(), PrintMethod) - + PrintMethods.begin(); + if (static_cast<unsigned>(PrintMethodIdx) == PrintMethods.size()) + PrintMethods.push_back(PrintMethod); + } + } if (Rec->isSubClassOf("RegisterOperand")) Rec = Rec->getValueAsDef("RegClass"); if (Rec->isSubClassOf("RegisterClass")) { - Cond = std::string("MI->getOperand(")+llvm::utostr(i)+").isReg()"; + Cond = std::string("MI->getOperand(") + llvm::utostr(MIOpNum) + + ").isReg()"; IAP->addCond(Cond); if (!IAP->isOpMapped(ROName)) { - IAP->addOperand(ROName, i); + IAP->addOperand(ROName, MIOpNum, PrintMethodIdx); Record *R = CGA->ResultOperands[i].getRecord(); if (R->isSubClassOf("RegisterOperand")) R = R->getValueAsDef("RegClass"); Cond = std::string("MRI.getRegClass(") + Target.getName() + "::" + - R->getName() + "RegClassID)" - ".contains(MI->getOperand(" + llvm::utostr(i) + ").getReg())"; + R->getName() + "RegClassID)" + ".contains(MI->getOperand(" + + llvm::utostr(MIOpNum) + ").getReg())"; IAP->addCond(Cond); } else { Cond = std::string("MI->getOperand(") + - llvm::utostr(i) + ").getReg() == MI->getOperand(" + + llvm::utostr(MIOpNum) + ").getReg() == MI->getOperand(" + llvm::utostr(IAP->getOpIndex(ROName)) + ").getReg()"; IAP->addCond(Cond); } } else { - assert(Rec->isSubClassOf("Operand") && "Unexpected operand!"); - // FIXME: We may need to handle these situations. - delete IAP; - IAP = 0; - CantHandle = true; - break; + // Assume all printable operands are desired for now. This can be + // overridden in the InstAlias instantiation if necessary. + IAP->addOperand(ROName, MIOpNum, PrintMethodIdx); } break; } case CodeGenInstAlias::ResultOperand::K_Imm: { - std::string Op = "MI->getOperand(" + llvm::utostr(i) + ")"; + std::string Op = "MI->getOperand(" + llvm::utostr(MIOpNum) + ")"; // Just because the alias has an immediate result, doesn't mean the // MCInst will. An MCExpr could be present, for example. @@ -874,20 +907,25 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { } Cond = std::string("MI->getOperand(") + - llvm::utostr(i) + ").getReg() == " + Target.getName() + + llvm::utostr(MIOpNum) + ").getReg() == " + Target.getName() + "::" + CGA->ResultOperands[i].getRegister()->getName(); IAP->addCond(Cond); break; } if (!IAP) break; + MIOpNum += RO.getMINumOperands(); } if (CantHandle) continue; - IAPrinterMap[I->first].push_back(IAP); + IAPrinterMap[Aliases.first].push_back(IAP); } } + ////////////////////////////// + // Write out the printAliasInstr function + ////////////////////////////// + std::string Header; raw_string_ostream HeaderO(Header); @@ -952,7 +990,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { // Code that prints the alias, replacing the operands with the ones from the // MCInst. O << " unsigned I = 0;\n"; - O << " while (AsmString[I] != ' ' && AsmString[I] != '\\0')\n"; + O << " while (AsmString[I] != ' ' && AsmString[I] != '\t' &&\n"; + O << " AsmString[I] != '\\0')\n"; O << " ++I;\n"; O << " OS << '\\t' << StringRef(AsmString, I);\n"; @@ -961,7 +1000,13 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { O << " do {\n"; O << " if (AsmString[I] == '$') {\n"; O << " ++I;\n"; - O << " printOperand(MI, unsigned(AsmString[I++]) - 1, OS);\n"; + O << " if (AsmString[I] == (char)0xff) {\n"; + O << " ++I;\n"; + O << " int OpIdx = AsmString[I++] - 1;\n"; + O << " int PrintMethodIdx = AsmString[I++] - 1;\n"; + O << " printCustomAliasOperand(MI, OpIdx, PrintMethodIdx, OS);\n"; + O << " } else\n"; + O << " printOperand(MI, unsigned(AsmString[I++]) - 1, OS);\n"; O << " } else {\n"; O << " OS << AsmString[I++];\n"; O << " }\n"; @@ -971,6 +1016,31 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { O << " return true;\n"; O << "}\n\n"; + ////////////////////////////// + // Write out the printCustomAliasOperand function + ////////////////////////////// + + O << "void " << Target.getName() << ClassName << "::" + << "printCustomAliasOperand(\n" + << " const MCInst *MI, unsigned OpIdx,\n" + << " unsigned PrintMethodIdx, raw_ostream &OS) {\n"; + if (PrintMethods.empty()) + O << " llvm_unreachable(\"Unknown PrintMethod kind\");\n"; + else { + O << " switch (PrintMethodIdx) {\n" + << " default:\n" + << " llvm_unreachable(\"Unknown PrintMethod kind\");\n" + << " break;\n"; + + for (unsigned i = 0; i < PrintMethods.size(); ++i) { + O << " case " << i << ":\n" + << " " << PrintMethods[i] << "(MI, OpIdx, OS);\n" + << " break;\n"; + } + O << " }\n"; + } + O << "}\n\n"; + O << "#endif // PRINT_ALIAS_INSTR\n"; } diff --git a/utils/TableGen/CTagsEmitter.cpp b/utils/TableGen/CTagsEmitter.cpp index 1d240fa..7108679 100644 --- a/utils/TableGen/CTagsEmitter.cpp +++ b/utils/TableGen/CTagsEmitter.cpp @@ -13,8 +13,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "ctags-emitter" - #include "llvm/Support/SourceMgr.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/TableGen/Error.h" @@ -24,6 +22,8 @@ #include <vector> using namespace llvm; +#define DEBUG_TYPE "ctags-emitter" + namespace llvm { extern SourceMgr SrcMgr; } namespace { diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp index 96bd336..6d43e8e 100644 --- a/utils/TableGen/CallingConvEmitter.cpp +++ b/utils/TableGen/CallingConvEmitter.cpp @@ -112,7 +112,7 @@ void CallingConvEmitter::EmitAction(Record *Action, O << IndentStr << "if (unsigned Reg = State.AllocateReg("; O << getQualifiedName(RegList->getElementAsRecord(0)) << ")) {\n"; } else { - O << IndentStr << "static const uint16_t RegList" << ++Counter + O << IndentStr << "static const MCPhysReg RegList" << ++Counter << "[] = {\n"; O << IndentStr << " "; for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) { @@ -143,7 +143,7 @@ void CallingConvEmitter::EmitAction(Record *Action, unsigned RegListNumber = ++Counter; unsigned ShadowRegListNumber = ++Counter; - O << IndentStr << "static const uint16_t RegList" << RegListNumber + O << IndentStr << "static const MCPhysReg RegList" << RegListNumber << "[] = {\n"; O << IndentStr << " "; for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) { @@ -152,7 +152,7 @@ void CallingConvEmitter::EmitAction(Record *Action, } O << "\n" << IndentStr << "};\n"; - O << IndentStr << "static const uint16_t RegList" + O << IndentStr << "static const MCPhysReg RegList" << ShadowRegListNumber << "[] = {\n"; O << IndentStr << " "; for (unsigned i = 0, e = ShadowRegList->getSize(); i != e; ++i) { @@ -196,7 +196,7 @@ void CallingConvEmitter::EmitAction(Record *Action, unsigned ShadowRegListNumber = ++Counter; - O << IndentStr << "static const uint16_t ShadowRegList" + O << IndentStr << "static const MCPhysReg ShadowRegList" << ShadowRegListNumber << "[] = {\n"; O << IndentStr << " "; for (unsigned i = 0, e = ShadowRegList->getSize(); i != e; ++i) { diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 0af7e3d..00bc9a5 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -25,6 +25,8 @@ #include <set> using namespace llvm; +#define DEBUG_TYPE "dag-patterns" + //===----------------------------------------------------------------------===// // EEVT::TypeSet Implementation //===----------------------------------------------------------------------===// @@ -83,7 +85,7 @@ bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP, return false; for (unsigned i = 0, e = LegalTypes.size(); i != e; ++i) - if (Pred == 0 || Pred(LegalTypes[i])) + if (!Pred || Pred(LegalTypes[i])) TypeVec.push_back(LegalTypes[i]); // If we have nothing that matches the predicate, bail out. @@ -736,9 +738,13 @@ static unsigned getPatternSize(const TreePatternNode *P, // specified. To get best possible pattern match we'll need to dynamically // calculate the complexity of all patterns a dag can potentially map to. const ComplexPattern *AM = P->getComplexPatternInfo(CGP); - if (AM) + if (AM) { Size += AM->getNumOperands() * 3; + // We don't want to count any children twice, so return early. + return Size; + } + // If this node has some predicate function that must match, it adds to the // complexity of this node. if (!P->getPredicateFns().empty()) @@ -976,7 +982,7 @@ bool TreePatternNode::UpdateNodeTypeFromInst(unsigned ResNo, // Both RegisterClass and RegisterOperand operands derive their types from a // register class def. - Record *RC = 0; + Record *RC = nullptr; if (Operand->isSubClassOf("RegisterClass")) RC = Operand; else if (Operand->isSubClassOf("RegisterOperand")) @@ -1094,7 +1100,7 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { // Get the result tree. DagInit *Tree = Operator->getValueAsDag("Fragment"); - Record *Op = 0; + Record *Op = nullptr; if (Tree) if (DefInit *DI = dyn_cast<DefInit>(Tree->getOperator())) Op = DI->getDef(); @@ -1120,6 +1126,9 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { if (Operator->isSubClassOf("ValueType")) return 1; // A type-cast of one result. + if (Operator->isSubClassOf("ComplexPattern")) + return 1; + Operator->dump(); errs() << "Unhandled node in GetNumNodeResults\n"; exit(1); @@ -1256,7 +1265,7 @@ SubstituteFormalArguments(std::map<std::string, TreePatternNode*> &ArgMap) { /// PatFrag references. TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { if (TP.hasError()) - return 0; + return nullptr; if (isLeaf()) return this; // nothing to do. @@ -1285,7 +1294,7 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { if (Frag->getNumArgs() != Children.size()) { TP.error("'" + Op->getName() + "' fragment requires " + utostr(Frag->getNumArgs()) + " operands!"); - return 0; + return nullptr; } TreePatternNode *FragTree = Frag->getOnlyTree()->clone(); @@ -1423,6 +1432,9 @@ static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo, return EEVT::TypeSet(); // Unknown. } + if (R->isSubClassOf("Operand")) + return EEVT::TypeSet(getValueType(R->getValueAsDef("Type"))); + TP.error("Unknown node flavor used in pattern: " + R->getName()); return EEVT::TypeSet(MVT::Other, TP); } @@ -1435,7 +1447,7 @@ getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const { if (getOperator() != CDP.get_intrinsic_void_sdnode() && getOperator() != CDP.get_intrinsic_w_chain_sdnode() && getOperator() != CDP.get_intrinsic_wo_chain_sdnode()) - return 0; + return nullptr; unsigned IID = cast<IntInit>(getChild(0)->getLeafValue())->getValue(); return &CDP.getIntrinsicInfo(IID); @@ -1445,12 +1457,37 @@ getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const { /// return the ComplexPattern information, otherwise return null. const ComplexPattern * TreePatternNode::getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const { - if (!isLeaf()) return 0; + Record *Rec; + if (isLeaf()) { + DefInit *DI = dyn_cast<DefInit>(getLeafValue()); + if (!DI) + return nullptr; + Rec = DI->getDef(); + } else + Rec = getOperator(); - DefInit *DI = dyn_cast<DefInit>(getLeafValue()); - if (DI && DI->getDef()->isSubClassOf("ComplexPattern")) - return &CGP.getComplexPattern(DI->getDef()); - return 0; + if (!Rec->isSubClassOf("ComplexPattern")) + return nullptr; + return &CGP.getComplexPattern(Rec); +} + +unsigned TreePatternNode::getNumMIResults(const CodeGenDAGPatterns &CGP) const { + // A ComplexPattern specifically declares how many results it fills in. + if (const ComplexPattern *CP = getComplexPatternInfo(CGP)) + return CP->getNumOperands(); + + // If MIOperandInfo is specified, that gives the count. + if (isLeaf()) { + DefInit *DI = dyn_cast<DefInit>(getLeafValue()); + if (DI && DI->getDef()->isSubClassOf("Operand")) { + DagInit *MIOps = DI->getDef()->getValueAsDag("MIOperandInfo"); + if (MIOps->getNumArgs()) + return MIOps->getNumArgs(); + } + } + + // Otherwise there is just one result. + return 1; } /// NodeHasProperty - Return true if this node has the specified property. @@ -1681,9 +1718,9 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { DagInit *MIOpInfo = OperandNode->getValueAsDag("MIOperandInfo"); if (unsigned NumArgs = MIOpInfo->getNumArgs()) { // But don't do that if the whole operand is being provided by - // a single ComplexPattern. - const ComplexPattern *AM = Child->getComplexPatternInfo(CDP); - if (!AM || AM->getNumOperands() < NumArgs) { + // a single ComplexPattern-related Operand. + + if (Child->getNumMIResults(CDP) < NumArgs) { // Match first sub-operand against the child we already have. Record *SubRec = cast<DefInit>(MIOpInfo->getArg(0))->getDef(); MadeChange |= @@ -1723,6 +1760,15 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { return MadeChange; } + if (getOperator()->isSubClassOf("ComplexPattern")) { + bool MadeChange = false; + + for (unsigned i = 0; i < getNumChildren(); ++i) + MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters); + + return MadeChange; + } + assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!"); // Node transforms always take one operand. @@ -1779,6 +1825,9 @@ bool TreePatternNode::canPatternMatch(std::string &Reason, return true; } + if (getOperator()->isSubClassOf("ComplexPattern")) + return true; + // If this node is a commutative operator, check that the LHS isn't an // immediate. const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(getOperator()); @@ -1888,7 +1937,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ if (BitsInit *BI = dyn_cast<BitsInit>(TheInit)) { // Turn this into an IntInit. Init *II = BI->convertInitializerTo(IntRecTy::get()); - if (II == 0 || !isa<IntInit>(II)) + if (!II || !isa<IntInit>(II)) error("Bits value must be constants!"); return ParseTreePattern(II, OpName); } @@ -1925,6 +1974,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ !Operator->isSubClassOf("Instruction") && !Operator->isSubClassOf("SDNodeXForm") && !Operator->isSubClassOf("Intrinsic") && + !Operator->isSubClassOf("ComplexPattern") && Operator->getName() != "set" && Operator->getName() != "implicit") error("Unrecognized node '" + Operator->getName() + "'!"); @@ -1980,6 +2030,27 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ Children.insert(Children.begin(), IIDNode); } + if (Operator->isSubClassOf("ComplexPattern")) { + for (unsigned i = 0; i < Children.size(); ++i) { + TreePatternNode *Child = Children[i]; + + if (Child->getName().empty()) + error("All arguments to a ComplexPattern must be named"); + + // Check that the ComplexPattern uses are consistent: "(MY_PAT $a, $b)" + // and "(MY_PAT $b, $a)" should not be allowed in the same pattern; + // neither should "(MY_PAT_1 $a, $b)" and "(MY_PAT_2 $a, $b)". + auto OperandId = std::make_pair(Operator, i); + auto PrevOp = ComplexPatternOperands.find(Child->getName()); + if (PrevOp != ComplexPatternOperands.end()) { + if (PrevOp->getValue() != OperandId) + error("All ComplexPattern operands must appear consistently: " + "in the same order in just one ComplexPattern instance."); + } else + ComplexPatternOperands[Child->getName()] = OperandId; + } + } + unsigned NumResults = GetNumNodeResults(Operator, CDP); TreePatternNode *Result = new TreePatternNode(Operator, Children, NumResults); Result->setName(OpName); @@ -2551,14 +2622,11 @@ public: return; } - // Get information about the SDNode for the operator. - const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N->getOperator()); - // Notice properties of the node. - if (OpInfo.hasProperty(SDNPMayStore)) mayStore = true; - if (OpInfo.hasProperty(SDNPMayLoad)) mayLoad = true; - if (OpInfo.hasProperty(SDNPSideEffect)) hasSideEffects = true; - if (OpInfo.hasProperty(SDNPVariadic)) isVariadic = true; + if (N->NodeHasProperty(SDNPMayStore, CDP)) mayStore = true; + if (N->NodeHasProperty(SDNPMayLoad, CDP)) mayLoad = true; + if (N->NodeHasProperty(SDNPSideEffect, CDP)) hasSideEffects = true; + if (N->NodeHasProperty(SDNPVariadic, CDP)) isVariadic = true; if (const CodeGenIntrinsic *IntInfo = N->getIntrinsicInfo(CDP)) { // If this is an intrinsic, analyze it. @@ -2739,7 +2807,7 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern( // Check that all of the results occur first in the list. std::vector<Record*> Results; - TreePatternNode *Res0Node = 0; + TreePatternNode *Res0Node = nullptr; for (unsigned i = 0; i != NumResults; ++i) { if (i == CGI.Operands.size()) I->error("'" + InstResults.begin()->first + @@ -2748,13 +2816,13 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern( // Check that it exists in InstResults. TreePatternNode *RNode = InstResults[OpName]; - if (RNode == 0) + if (!RNode) I->error("Operand $" + OpName + " does not exist in operand list!"); if (i == 0) Res0Node = RNode; Record *R = cast<DefInit>(RNode->getLeafValue())->getDef(); - if (R == 0) + if (!R) I->error("Operand $" + OpName + " should be a set destination: all " "outputs must occur before inputs in operand list!"); @@ -2811,7 +2879,7 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern( // Promote the xform function to be an explicit node if set. if (Record *Xform = OpNode->getTransformFn()) { - OpNode->setTransformFn(0); + OpNode->setTransformFn(nullptr); std::vector<TreePatternNode*> Children; Children.push_back(OpNode); OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes()); @@ -2855,7 +2923,7 @@ void CodeGenDAGPatterns::ParseInstructions() { std::vector<Record*> Instrs = Records.getAllDerivedDefinitions("Instruction"); for (unsigned i = 0, e = Instrs.size(); i != e; ++i) { - ListInit *LI = 0; + ListInit *LI = nullptr; if (isa<ListInit>(Instrs[i]->getValueInit("Pattern"))) LI = Instrs[i]->getValueAsListInit("Pattern"); @@ -2890,7 +2958,7 @@ void CodeGenDAGPatterns::ParseInstructions() { // Create and insert the instruction. std::vector<Record*> ImpResults; Instructions.insert(std::make_pair(Instrs[i], - DAGInstruction(0, Results, Operands, ImpResults))); + DAGInstruction(nullptr, Results, Operands, ImpResults))); continue; // no pattern. } @@ -2907,7 +2975,7 @@ void CodeGenDAGPatterns::ParseInstructions() { E = Instructions.end(); II != E; ++II) { DAGInstruction &TheInst = II->second; TreePattern *I = TheInst.getPattern(); - if (I == 0) continue; // No pattern. + if (!I) continue; // No pattern. // FIXME: Assume only the first tree is the pattern. The others are clobber // nodes. @@ -2983,7 +3051,7 @@ void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern, // they don't exist in the input pattern. for (std::map<std::string, NameRecord>::iterator I = DstNames.begin(), E = DstNames.end(); I != E; ++I) { - if (SrcNames[I->first].first == 0) + if (SrcNames[I->first].first == nullptr) Pattern->error("Pattern has input without matching name in output: $" + I->first); } @@ -2992,7 +3060,7 @@ void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern, // name isn't used in the dest, and isn't used to tie two values together. for (std::map<std::string, NameRecord>::iterator I = SrcNames.begin(), E = SrcNames.end(); I != E; ++I) - if (DstNames[I->first].first == 0 && SrcNames[I->first].second == 1) + if (DstNames[I->first].first == nullptr && SrcNames[I->first].second == 1) Pattern->error("Pattern has dead named input: $" + I->first); PatternsToMatch.push_back(PTM); @@ -3280,7 +3348,7 @@ void CodeGenDAGPatterns::ParsePatterns() { for (unsigned ii = 0, ee = DstPattern->getNumChildren(); ii != ee; ++ii) { TreePatternNode *OpNode = DstPattern->getChild(ii); if (Record *Xform = OpNode->getTransformFn()) { - OpNode->setTransformFn(0); + OpNode->setTransformFn(nullptr); std::vector<TreePatternNode*> Children; Children.push_back(OpNode); OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes()); @@ -3432,8 +3500,8 @@ static void GenerateVariantsOf(TreePatternNode *N, std::vector<TreePatternNode*> &OutVariants, CodeGenDAGPatterns &CDP, const MultipleUseVarSet &DepVars) { - // We cannot permute leaves. - if (N->isLeaf()) { + // We cannot permute leaves or ComplexPattern uses. + if (N->isLeaf() || N->getOperator()->isSubClassOf("ComplexPattern")) { OutVariants.push_back(N); return; } diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index d995329..fb30cdd 100644 --- a/utils/TableGen/CodeGenDAGPatterns.h +++ b/utils/TableGen/CodeGenDAGPatterns.h @@ -148,8 +148,8 @@ namespace EEVT { /// valid on completely unknown type sets. If Pred is non-null, only MVTs /// that pass the predicate are added. bool FillWithPossibleTypes(TreePattern &TP, - bool (*Pred)(MVT::SimpleValueType) = 0, - const char *PredicateName = 0); + bool (*Pred)(MVT::SimpleValueType) = nullptr, + const char *PredicateName = nullptr); }; } @@ -329,11 +329,11 @@ class TreePatternNode { public: TreePatternNode(Record *Op, const std::vector<TreePatternNode*> &Ch, unsigned NumResults) - : Operator(Op), Val(0), TransformFn(0), Children(Ch) { + : Operator(Op), Val(nullptr), TransformFn(nullptr), Children(Ch) { Types.resize(NumResults); } TreePatternNode(Init *val, unsigned NumResults) // leaf ctor - : Operator(0), Val(val), TransformFn(0) { + : Operator(nullptr), Val(val), TransformFn(nullptr) { Types.resize(NumResults); } ~TreePatternNode(); @@ -342,7 +342,7 @@ public: const std::string &getName() const { return Name; } void setName(StringRef N) { Name.assign(N.begin(), N.end()); } - bool isLeaf() const { return Val != 0; } + bool isLeaf() const { return Val != nullptr; } // Type accessors. unsigned getNumTypes() const { return Types.size(); } @@ -409,6 +409,12 @@ public: const ComplexPattern * getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const; + /// Returns the number of MachineInstr operands that would be produced by this + /// node if it mapped directly to an output Instruction's + /// operand. ComplexPattern specifies this explicitly; MIOperandInfo gives it + /// for Operands; otherwise 1. + unsigned getNumMIResults(const CodeGenDAGPatterns &CGP) const; + /// NodeHasProperty - Return true if this node has the specified property. bool NodeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const; @@ -527,6 +533,13 @@ class TreePattern { /// hasError - True if the currently processed nodes have unresolvable types /// or other non-fatal errors bool HasError; + + /// It's important that the usage of operands in ComplexPatterns is + /// consistent: each named operand can be defined by at most one + /// ComplexPattern. This records the ComplexPattern instance and the operand + /// number for each operand encountered in a ComplexPattern to aid in that + /// check. + StringMap<std::pair<Record *, unsigned>> ComplexPatternOperands; public: /// TreePattern constructor - Parse the specified DagInits into the @@ -580,7 +593,7 @@ public: /// patterns as possible. Return true if all types are inferred, false /// otherwise. Bail out if a type contradiction is found. bool InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > - *NamedTypes=0); + *NamedTypes=nullptr); /// error - If this is the first error in the current resolution step, /// print it and set the error flag. Otherwise, continue silently. @@ -619,7 +632,7 @@ public: const std::vector<Record*> &operands, const std::vector<Record*> &impresults) : Pattern(TP), Results(results), Operands(operands), - ImpResults(impresults), ResultPattern(0) {} + ImpResults(impresults), ResultPattern(nullptr) {} TreePattern *getPattern() const { return Pattern; } unsigned getNumResults() const { return Results.size(); } @@ -768,7 +781,7 @@ public: return PatternFragments.find(R)->second; } TreePattern *getPatternFragmentIfRead(Record *R) const { - if (!PatternFragments.count(R)) return 0; + if (!PatternFragments.count(R)) return nullptr; return PatternFragments.find(R)->second; } diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 5eebb91..2577ad4 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -69,7 +69,7 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { std::string EncoderMethod; std::string OperandType = "OPERAND_UNKNOWN"; unsigned NumOps = 1; - DagInit *MIOpInfo = 0; + DagInit *MIOpInfo = nullptr; if (Rec->isSubClassOf("RegisterOperand")) { PrintMethod = Rec->getValueAsString("PrintMethod"); } else if (Rec->isSubClassOf("Operand")) { @@ -182,7 +182,7 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) { // Find the suboperand number involved. DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo; - if (MIOpInfo == 0) + if (!MIOpInfo) PrintFatalError(TheDef->getName() + ": unknown suboperand name in '" + Op + "'"); // Find the operand with the right name. @@ -290,7 +290,7 @@ void CGIOperandList::ProcessDisableEncoding(std::string DisableEncoding) { //===----------------------------------------------------------------------===// CodeGenInstruction::CodeGenInstruction(Record *R) - : TheDef(R), Operands(R), InferredFrom(0) { + : TheDef(R), Operands(R), InferredFrom(nullptr) { Namespace = R->getValueAsString("Namespace"); AsmString = R->getValueAsString("AsmString"); @@ -436,7 +436,7 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, ResultOperand &ResOp) { Init *Arg = Result->getArg(AliasOpNo); DefInit *ADI = dyn_cast<DefInit>(Arg); - Record *ResultRecord = ADI ? ADI->getDef() : 0; + Record *ResultRecord = ADI ? ADI->getDef() : nullptr; if (ADI && ADI->getDef() == InstOpRec) { // If the operand is a record, it must have a name, and the record type @@ -504,7 +504,7 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, // throw TGError(Loc, "reg0 used for result that is not an " // "OptionalDefOperand!"); - ResOp = ResultOperand(static_cast<Record*>(0)); + ResOp = ResultOperand(static_cast<Record*>(nullptr)); return true; } @@ -536,13 +536,34 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, return false; } -CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) { - AsmString = R->getValueAsString("AsmString"); +unsigned CodeGenInstAlias::ResultOperand::getMINumOperands() const { + if (!isRecord()) + return 1; + + Record *Rec = getRecord(); + if (!Rec->isSubClassOf("Operand")) + return 1; + + DagInit *MIOpInfo = Rec->getValueAsDag("MIOperandInfo"); + if (MIOpInfo->getNumArgs() == 0) { + // Unspecified, so it defaults to 1 + return 1; + } + + return MIOpInfo->getNumArgs(); +} + +CodeGenInstAlias::CodeGenInstAlias(Record *R, unsigned Variant, + CodeGenTarget &T) + : TheDef(R) { Result = R->getValueAsDag("ResultInst"); + AsmString = R->getValueAsString("AsmString"); + AsmString = CodeGenInstruction::FlattenAsmStringVariants(AsmString, Variant); + // Verify that the root of the result is an instruction. DefInit *DI = dyn_cast<DefInit>(Result->getOperator()); - if (DI == 0 || !DI->getDef()->isSubClassOf("Instruction")) + if (!DI || !DI->getDef()->isSubClassOf("Instruction")) PrintFatalError(R->getLoc(), "result of inst alias should be an instruction"); diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index 00d89bf..f143875 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -149,6 +149,12 @@ namespace llvm { OperandInfo &back() { return OperandList.back(); } const OperandInfo &back() const { return OperandList.back(); } + typedef std::vector<OperandInfo>::iterator iterator; + typedef std::vector<OperandInfo>::const_iterator const_iterator; + iterator begin() { return OperandList.begin(); } + const_iterator begin() const { return OperandList.begin(); } + iterator end() { return OperandList.end(); } + const_iterator end() const { return OperandList.end(); } /// getOperandNamed - Return the index of the operand with the specified /// non-empty name. If the instruction does not have an operand with the @@ -318,6 +324,8 @@ namespace llvm { Record *getRecord() const { assert(isRecord()); return R; } int64_t getImm() const { assert(isImm()); return Imm; } Record *getRegister() const { assert(isReg()); return R; } + + unsigned getMINumOperands() const; }; /// ResultOperands - The decoded operands for the result instruction. @@ -330,7 +338,7 @@ namespace llvm { /// of them are matched by the operand, the second value should be -1. std::vector<std::pair<unsigned, int> > ResultInstOperandIndex; - CodeGenInstAlias(Record *R, CodeGenTarget &T); + CodeGenInstAlias(Record *R, unsigned Variant, CodeGenTarget &T); bool tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, Record *InstOpRec, bool hasSubOps, ArrayRef<SMLoc> Loc, diff --git a/utils/TableGen/CodeGenMapTable.cpp b/utils/TableGen/CodeGenMapTable.cpp index b97126b..7e5aa9c 100644 --- a/utils/TableGen/CodeGenMapTable.cpp +++ b/utils/TableGen/CodeGenMapTable.cpp @@ -326,7 +326,7 @@ Record *MapTableEmitter::getInstrForColumn(Record *KeyInstr, const std::vector<Record*> &RelatedInstrVec = RowInstrMap[KeyValue]; ListInit *ColFields = InstrMapDesc.getColFields(); - Record *MatchInstr = NULL; + Record *MatchInstr = nullptr; for (unsigned i = 0, e = RelatedInstrVec.size(); i < e; i++) { bool MatchFound = true; @@ -378,7 +378,7 @@ unsigned MapTableEmitter::emitBinSearchTable(raw_ostream &OS) { unsigned RelExists = 0; if (ColInstrs.size()) { for (unsigned j = 0; j < NumCol; j++) { - if (ColInstrs[j] != NULL) { + if (ColInstrs[j] != nullptr) { RelExists = 1; OutStr += ", "; OutStr += TargetName; diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp index e0e0b62..8099f13 100644 --- a/utils/TableGen/CodeGenRegisters.cpp +++ b/utils/TableGen/CodeGenRegisters.cpp @@ -12,8 +12,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "regalloc-emitter" - #include "CodeGenRegisters.h" #include "CodeGenTarget.h" #include "llvm/ADT/IntEqClasses.h" @@ -26,6 +24,8 @@ using namespace llvm; +#define DEBUG_TYPE "regalloc-emitter" + //===----------------------------------------------------------------------===// // CodeGenSubRegIndex //===----------------------------------------------------------------------===// @@ -41,7 +41,7 @@ CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum) CodeGenSubRegIndex::CodeGenSubRegIndex(StringRef N, StringRef Nspace, unsigned Enum) - : TheDef(0), Name(N), Namespace(Nspace), Size(-1), Offset(-1), + : TheDef(nullptr), Name(N), Namespace(Nspace), Size(-1), Offset(-1), EnumValue(Enum), LaneMask(0), AllSuperRegsCovered(true) { } @@ -725,7 +725,7 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, StringRef Name, Key Props) : Members(*Props.Members), - TheDef(0), + TheDef(nullptr), Name(Name), TopoSigs(RegBank.getNumTopoSigs()), EnumValue(-1), @@ -1312,7 +1312,7 @@ static void computeUberWeights(std::vector<UberRegSet> &UberSets, E = UberSets.end(); I != E; ++I) { // Initialize all unit weights in this set, and remember the max units/reg. - const CodeGenRegister *Reg = 0; + const CodeGenRegister *Reg = nullptr; unsigned MaxWeight = 0, Weight = 0; for (RegUnitIterator UnitI(I->Regs); UnitI.isValid(); ++UnitI) { if (Reg != UnitI.getReg()) { @@ -1923,7 +1923,7 @@ const CodeGenRegisterClass* CodeGenRegBank::getRegClassForRegister(Record *R) { const CodeGenRegister *Reg = getReg(R); ArrayRef<CodeGenRegisterClass*> RCs = getRegClasses(); - const CodeGenRegisterClass *FoundRC = 0; + const CodeGenRegisterClass *FoundRC = nullptr; for (unsigned i = 0, e = RCs.size(); i != e; ++i) { const CodeGenRegisterClass &RC = *RCs[i]; if (!RC.contains(Reg)) @@ -1938,7 +1938,7 @@ CodeGenRegBank::getRegClassForRegister(Record *R) { // If a register's classes have different types, return null. if (RC.getValueTypes() != FoundRC->getValueTypes()) - return 0; + return nullptr; // Check to see if the previously found class that contains // the register is a subclass of the current class. If so, @@ -1956,7 +1956,7 @@ CodeGenRegBank::getRegClassForRegister(Record *R) { // Multiple classes, and neither is a superclass of the other. // Return null. - return 0; + return nullptr; } return FoundRC; } diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h index 03ffb43..30732c8 100644 --- a/utils/TableGen/CodeGenRegisters.h +++ b/utils/TableGen/CodeGenRegisters.h @@ -71,7 +71,7 @@ namespace llvm { // Returns NULL if this and Idx don't compose. CodeGenSubRegIndex *compose(CodeGenSubRegIndex *Idx) const { CompMap::const_iterator I = Composed.find(Idx); - return I == Composed.end() ? 0 : I->second; + return I == Composed.end() ? nullptr : I->second; } // Add a composite subreg index: this+A = B. @@ -90,7 +90,8 @@ namespace llvm { B->Offset = Offset + A->Offset; B->Size = A->Size; } - return (Ins.second || Ins.first->second == B) ? 0 : Ins.first->second; + return (Ins.second || Ins.first->second == B) ? nullptr + : Ins.first->second; } // Update the composite maps of components specified in 'ComposedOf'. @@ -414,7 +415,9 @@ namespace llvm { // contain this unit. unsigned RegClassUnitSetsIdx; - RegUnit() : Weight(0), RegClassUnitSetsIdx(0) { Roots[0] = Roots[1] = 0; } + RegUnit() : Weight(0), RegClassUnitSetsIdx(0) { + Roots[0] = Roots[1] = nullptr; + } ArrayRef<const CodeGenRegister*> getRoots() const { assert(!(Roots[1] && !Roots[0]) && "Invalid roots array"); @@ -572,7 +575,7 @@ namespace llvm { // Create a native register unit that is associated with one or two root // registers. - unsigned newRegUnit(CodeGenRegister *R0, CodeGenRegister *R1 = 0) { + unsigned newRegUnit(CodeGenRegister *R0, CodeGenRegister *R1 = nullptr) { RegUnits.resize(RegUnits.size() + 1); RegUnits.back().Roots[0] = R0; RegUnits.back().Roots[1] = R1; diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp index a07524d..79d60ac 100644 --- a/utils/TableGen/CodeGenSchedule.cpp +++ b/utils/TableGen/CodeGenSchedule.cpp @@ -12,8 +12,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "subtarget-emitter" - #include "CodeGenSchedule.h" #include "CodeGenTarget.h" #include "llvm/ADT/STLExtras.h" @@ -23,6 +21,8 @@ using namespace llvm; +#define DEBUG_TYPE "subtarget-emitter" + #ifndef NDEBUG static void dumpIdxVec(const IdxVec &V) { for (unsigned i = 0, e = V.size(); i < e; ++i) { @@ -59,7 +59,7 @@ struct InstRegexOp : public SetTheory::Operator { void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts, ArrayRef<SMLoc> Loc) override { - SmallVector<Regex*, 4> RegexList; + SmallVector<Regex, 4> RegexList; for (DagInit::const_arg_iterator AI = Expr->arg_begin(), AE = Expr->arg_end(); AI != AE; ++AI) { StringInit *SI = dyn_cast<StringInit>(*AI); @@ -72,17 +72,15 @@ struct InstRegexOp : public SetTheory::Operator { pat.insert(0, "^("); pat.insert(pat.end(), ')'); } - RegexList.push_back(new Regex(pat)); + RegexList.push_back(Regex(pat)); } for (CodeGenTarget::inst_iterator I = Target.inst_begin(), E = Target.inst_end(); I != E; ++I) { - for (SmallVectorImpl<Regex*>::iterator - RI = RegexList.begin(), RE = RegexList.end(); RI != RE; ++RI) { - if ((*RI)->match((*I)->TheDef->getName())) + for (auto &R : RegexList) { + if (R.match((*I)->TheDef->getName())) Elts.insert((*I)->TheDef); } } - DeleteContainerPointers(RegexList); } }; } // end anonymous namespace @@ -429,7 +427,7 @@ void CodeGenSchedModels::expandRWSeqForProc( const CodeGenProcModel &ProcModel) const { const CodeGenSchedRW &SchedWrite = getSchedRW(RWIdx, IsRead); - Record *AliasDef = 0; + Record *AliasDef = nullptr; for (RecIter AI = SchedWrite.Aliases.begin(), AE = SchedWrite.Aliases.end(); AI != AE; ++AI) { const CodeGenSchedRW &AliasRW = getSchedRW((*AI)->getValueAsDef("AliasRW")); @@ -1315,7 +1313,7 @@ static void inferFromTransitions(ArrayRef<PredTransition> LastTransitions, IdxVec ProcIndices(I->ProcIndices.begin(), I->ProcIndices.end()); CodeGenSchedTransition SCTrans; SCTrans.ToClassIdx = - SchedModels.addSchedClass(/*ItinClassDef=*/0, OperWritesVariant, + SchedModels.addSchedClass(/*ItinClassDef=*/nullptr, OperWritesVariant, OperReadsVariant, ProcIndices); SCTrans.ProcIndices = ProcIndices; // The final PredTerm is unique set of predicates guarding the transition. @@ -1621,7 +1619,7 @@ Record *CodeGenSchedModels::findProcResUnits(Record *ProcResKind, if (ProcResKind->isSubClassOf("ProcResourceUnits")) return ProcResKind; - Record *ProcUnitDef = 0; + Record *ProcUnitDef = nullptr; RecVec ProcResourceDefs = Records.getAllDerivedDefinitions("ProcResourceUnits"); diff --git a/utils/TableGen/CodeGenSchedule.h b/utils/TableGen/CodeGenSchedule.h index 5ce679a..65ac602 100644 --- a/utils/TableGen/CodeGenSchedule.h +++ b/utils/TableGen/CodeGenSchedule.h @@ -56,7 +56,7 @@ struct CodeGenSchedRW { RecVec Aliases; CodeGenSchedRW() - : Index(0), TheDef(0), IsRead(false), IsAlias(false), + : Index(0), TheDef(nullptr), IsRead(false), IsAlias(false), HasVariants(false), IsVariadic(false), IsSequence(false) {} CodeGenSchedRW(unsigned Idx, Record *Def) : Index(Idx), TheDef(Def), IsAlias(false), IsVariadic(false) { @@ -74,7 +74,7 @@ struct CodeGenSchedRW { CodeGenSchedRW(unsigned Idx, bool Read, const IdxVec &Seq, const std::string &Name) - : Index(Idx), Name(Name), TheDef(0), IsRead(Read), IsAlias(false), + : Index(Idx), Name(Name), TheDef(nullptr), IsRead(Read), IsAlias(false), HasVariants(false), IsVariadic(false), IsSequence(true), Sequence(Seq) { assert(Sequence.size() > 1 && "implied sequence needs >1 RWs"); } @@ -142,7 +142,7 @@ struct CodeGenSchedClass { // off to join another inferred class. RecVec InstRWs; - CodeGenSchedClass(): Index(0), ItinClassDef(0) {} + CodeGenSchedClass(): Index(0), ItinClassDef(nullptr) {} bool isKeyEqual(Record *IC, const IdxVec &W, const IdxVec &R) { return ItinClassDef == IC && Writes == W && Reads == R; @@ -248,6 +248,28 @@ class CodeGenSchedModels { public: CodeGenSchedModels(RecordKeeper& RK, const CodeGenTarget &TGT); + // iterator access to the scheduling classes. + typedef std::vector<CodeGenSchedClass>::iterator class_iterator; + typedef std::vector<CodeGenSchedClass>::const_iterator const_class_iterator; + class_iterator classes_begin() { return SchedClasses.begin(); } + const_class_iterator classes_begin() const { return SchedClasses.begin(); } + class_iterator classes_end() { return SchedClasses.end(); } + const_class_iterator classes_end() const { return SchedClasses.end(); } + iterator_range<class_iterator> classes() { + return iterator_range<class_iterator>(classes_begin(), classes_end()); + } + iterator_range<const_class_iterator> classes() const { + return iterator_range<const_class_iterator>(classes_begin(), classes_end()); + } + iterator_range<class_iterator> explicit_classes() { + return iterator_range<class_iterator>( + classes_begin(), classes_begin() + NumInstrSchedClasses); + } + iterator_range<const_class_iterator> explicit_classes() const { + return iterator_range<const_class_iterator>( + classes_begin(), classes_begin() + NumInstrSchedClasses); + } + Record *getModelOrItinDef(Record *ProcDef) const { Record *ModelDef = ProcDef->getValueAsDef("SchedModel"); Record *ItinsDef = ProcDef->getValueAsDef("ProcItin"); diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index dd9c23c..de00dc6 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -133,7 +133,7 @@ std::string llvm::getQualifiedName(const Record *R) { /// getTarget - Return the current instance of the Target class. /// CodeGenTarget::CodeGenTarget(RecordKeeper &records) - : Records(records), RegBank(0), SchedModels(0) { + : Records(records), RegBank(nullptr), SchedModels(nullptr) { std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target"); if (Targets.size() == 0) PrintFatalError("ERROR: No 'Target' subclasses defined!"); @@ -226,7 +226,7 @@ const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const { const StringMap<CodeGenRegister*> &Regs = getRegBank().getRegistersByName(); StringMap<CodeGenRegister*>::const_iterator I = Regs.find(Name); if (I == Regs.end()) - return 0; + return nullptr; return I->second; } @@ -287,7 +287,7 @@ GetInstByName(const char *Name, DenseMap<const Record*, CodeGenInstruction*>::const_iterator I = Insts.find(Rec); - if (Rec == 0 || I == Insts.end()) + if (!Rec || I == Insts.end()) PrintFatalError(Twine("Could not find '") + Name + "' instruction!"); return I->second; } @@ -301,7 +301,7 @@ void CodeGenTarget::ComputeInstrsByEnum() const { "GC_LABEL", "KILL", "EXTRACT_SUBREG", "INSERT_SUBREG", "IMPLICIT_DEF", "SUBREG_TO_REG", "COPY_TO_REGCLASS", "DBG_VALUE", "REG_SEQUENCE", "COPY", "BUNDLE", "LIFETIME_START", - "LIFETIME_END", "STACKMAP", "PATCHPOINT", 0}; + "LIFETIME_END", "STACKMAP", "PATCHPOINT", nullptr}; const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions(); for (const char *const *p = FixedInstrs; *p; ++p) { const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records); diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h index d6458f4..5414310 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -171,6 +171,9 @@ public: typedef std::vector<const CodeGenInstruction*>::const_iterator inst_iterator; inst_iterator inst_begin() const{return getInstructionsByEnumValue().begin();} inst_iterator inst_end() const { return getInstructionsByEnumValue().end(); } + iterator_range<inst_iterator> instructions() const { + return iterator_range<inst_iterator>(inst_begin(), inst_end()); + } /// isLittleEndianEncoding - are instruction bit patterns defined as [0..n]? diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index 9294cd5..82682cd 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -18,6 +18,8 @@ #include "llvm/TableGen/TableGenBackend.h" using namespace llvm; +#define DEBUG_TYPE "dag-isel-emitter" + namespace { /// DAGISelEmitter - The top-level class which coordinates construction /// and emission of the instruction selector. diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp index 2557bb6..9c40799 100644 --- a/utils/TableGen/DAGISelMatcher.cpp +++ b/utils/TableGen/DAGISelMatcher.cpp @@ -43,7 +43,7 @@ Matcher *Matcher::unlinkNode(Matcher *Other) { for (; Cur && Cur->getNext() != Other; Cur = Cur->getNext()) /*empty*/; - if (Cur == 0) return 0; + if (!Cur) return nullptr; Cur->takeNext(); Cur->setNext(Other->takeNext()); return this; @@ -108,7 +108,7 @@ TreePredicateFn CheckPredicateMatcher::getPredicate() const { void ScopeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "Scope\n"; for (unsigned i = 0, e = getNumChildren(); i != e; ++i) { - if (getChild(i) == 0) + if (!getChild(i)) OS.indent(indent+1) << "NULL POINTER\n"; else getChild(i)->print(OS, indent+2); diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h index 56a571f..f8f6c54 100644 --- a/utils/TableGen/DAGISelMatcher.h +++ b/utils/TableGen/DAGISelMatcher.h @@ -207,7 +207,7 @@ public: Matcher *takeChild(unsigned i) { Matcher *Res = Children[i]; - Children[i] = 0; + Children[i] = nullptr; return Res; } diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp index 416e8e3..0059570 100644 --- a/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -142,7 +142,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, switch (N->getKind()) { case Matcher::Scope: { const ScopeMatcher *SM = cast<ScopeMatcher>(N); - assert(SM->getNext() == 0 && "Shouldn't have next after scope"); + assert(SM->getNext() == nullptr && "Shouldn't have next after scope"); unsigned StartIdx = CurrentIdx; @@ -725,7 +725,7 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { } static void BuildHistogram(const Matcher *M, std::vector<unsigned> &OpcodeFreq){ - for (; M != 0; M = M->getNext()) { + for (; M != nullptr; M = M->getNext()) { // Count this node. if (unsigned(M->getKind()) >= OpcodeFreq.size()) OpcodeFreq.resize(M->getKind()+1); diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index 8ae7444..97e37ba 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -62,6 +62,13 @@ namespace { /// insertion easier. StringMap<unsigned> VariableMap; + /// This maintains the recorded operand number that OPC_CheckComplexPattern + /// drops each sub-operand into. We don't want to insert these into + /// VariableMap because that leads to identity checking if they are + /// encountered multiple times. Biased by 1 like VariableMap for + /// consistency. + StringMap<unsigned> NamedComplexPatternOperands; + /// NextRecordedOperandNo - As we emit opcodes to record matched values in /// the RecordedNodes array, this keeps track of which slot will be next to /// record into. @@ -76,10 +83,8 @@ namespace { SmallVector<unsigned, 2> MatchedGlueResultNodes; /// MatchedComplexPatterns - This maintains a list of all of the - /// ComplexPatterns that we need to check. The patterns are known to have - /// names which were recorded. The second element of each pair is the first - /// slot number that the OPC_CheckComplexPat opcode drops the matched - /// results into. + /// ComplexPatterns that we need to check. The second element of each pair + /// is the recorded operand number of the input node. SmallVector<std::pair<const TreePatternNode*, unsigned>, 2> MatchedComplexPatterns; @@ -115,6 +120,11 @@ namespace { void EmitOperatorMatchCode(const TreePatternNode *N, TreePatternNode *NodeNoTypes); + /// If this is the first time a node with unique identifier Name has been + /// seen, record it. Otherwise, emit a check to make sure this is the same + /// node. Returns true if this is the first encounter. + bool recordUniqueNode(std::string Name); + // Result Code Generation. unsigned getNamedArgumentSlot(StringRef Name) { unsigned VarMapEntry = VariableMap[Name]; @@ -144,7 +154,7 @@ namespace { MatcherGen::MatcherGen(const PatternToMatch &pattern, const CodeGenDAGPatterns &cgp) : Pattern(pattern), CGP(cgp), NextRecordedOperandNo(0), - TheMatcher(0), CurPredicate(0) { + TheMatcher(nullptr), CurPredicate(nullptr) { // We need to produce the matcher tree for the patterns source pattern. To do // this we need to match the structure as well as the types. To do the type // matching, we want to figure out the fewest number of type checks we need to @@ -182,7 +192,7 @@ void MatcherGen::InferPossibleTypes() { /// AddMatcher - Add a matcher node to the current graph we're building. void MatcherGen::AddMatcher(Matcher *NewNode) { - if (CurPredicate != 0) + if (CurPredicate) CurPredicate->setNext(NewNode); else TheMatcher = NewNode; @@ -218,7 +228,7 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { } DefInit *DI = dyn_cast<DefInit>(N->getLeafValue()); - if (DI == 0) { + if (!DI) { errs() << "Unknown leaf kind: " << *N << "\n"; abort(); } @@ -266,7 +276,8 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { // Remember this ComplexPattern so that we can emit it after all the other // structural matches are done. - MatchedComplexPatterns.push_back(std::make_pair(N, 0)); + unsigned InputOperand = VariableMap[N->getName()] - 1; + MatchedComplexPatterns.push_back(std::make_pair(N, InputOperand)); return; } @@ -277,6 +288,25 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N, TreePatternNode *NodeNoTypes) { assert(!N->isLeaf() && "Not an operator?"); + + if (N->getOperator()->isSubClassOf("ComplexPattern")) { + // The "name" of a non-leaf complex pattern (MY_PAT $op1, $op2) is + // "MY_PAT:op1:op2". We should already have validated that the uses are + // consistent. + std::string PatternName = N->getOperator()->getName(); + for (unsigned i = 0; i < N->getNumChildren(); ++i) { + PatternName += ":"; + PatternName += N->getChild(i)->getName(); + } + + if (recordUniqueNode(PatternName)) { + auto NodeAndOpNum = std::make_pair(N, NextRecordedOperandNo - 1); + MatchedComplexPatterns.push_back(NodeAndOpNum); + } + + return; + } + const SDNodeInfo &CInfo = CGP.getSDNodeInfo(N->getOperator()); // If this is an 'and R, 1234' where the operation is AND/OR and the RHS is @@ -415,6 +445,22 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N, } } +bool MatcherGen::recordUniqueNode(std::string Name) { + unsigned &VarMapEntry = VariableMap[Name]; + if (VarMapEntry == 0) { + // If it is a named node, we must emit a 'Record' opcode. + AddMatcher(new RecordMatcher("$" + Name, NextRecordedOperandNo)); + VarMapEntry = ++NextRecordedOperandNo; + return true; + } + + // If we get here, this is a second reference to a specific name. Since + // we already have checked that the first reference is valid, we don't + // have to recursively match it, just check that it's the same as the + // previously named thing. + AddMatcher(new CheckSameMatcher(VarMapEntry-1)); + return false; +} void MatcherGen::EmitMatchCode(const TreePatternNode *N, TreePatternNode *NodeNoTypes) { @@ -432,21 +478,9 @@ void MatcherGen::EmitMatchCode(const TreePatternNode *N, // If this node has a name associated with it, capture it in VariableMap. If // we already saw this in the pattern, emit code to verify dagness. - if (!N->getName().empty()) { - unsigned &VarMapEntry = VariableMap[N->getName()]; - if (VarMapEntry == 0) { - // If it is a named node, we must emit a 'Record' opcode. - AddMatcher(new RecordMatcher("$" + N->getName(), NextRecordedOperandNo)); - VarMapEntry = ++NextRecordedOperandNo; - } else { - // If we get here, this is a second reference to a specific name. Since - // we already have checked that the first reference is valid, we don't - // have to recursively match it, just check that it's the same as the - // previously named thing. - AddMatcher(new CheckSameMatcher(VarMapEntry-1)); + if (!N->getName().empty()) + if (!recordUniqueNode(N->getName())) return; - } - } if (N->isLeaf()) EmitLeafMatchCode(N); @@ -497,16 +531,20 @@ bool MatcherGen::EmitMatcherCode(unsigned Variant) { const TreePatternNode *N = MatchedComplexPatterns[i].first; // Remember where the results of this match get stuck. - MatchedComplexPatterns[i].second = NextRecordedOperandNo; + if (N->isLeaf()) { + NamedComplexPatternOperands[N->getName()] = NextRecordedOperandNo + 1; + } else { + unsigned CurOp = NextRecordedOperandNo; + for (unsigned i = 0; i < N->getNumChildren(); ++i) { + NamedComplexPatternOperands[N->getChild(i)->getName()] = CurOp + 1; + CurOp += N->getChild(i)->getNumMIResults(CGP); + } + } // Get the slot we recorded the value in from the name on the node. - unsigned RecNodeEntry = VariableMap[N->getName()]; - assert(!N->getName().empty() && RecNodeEntry && - "Complex pattern should have a name and slot"); - --RecNodeEntry; // Entries in VariableMap are biased. + unsigned RecNodeEntry = MatchedComplexPatterns[i].second; - const ComplexPattern &CP = - CGP.getComplexPattern(((DefInit*)N->getLeafValue())->getDef()); + const ComplexPattern &CP = *N->getComplexPatternInfo(CGP); // Emit a CheckComplexPat operation, which does the match (aborting if it // fails) and pushes the matched operands onto the recorded nodes list. @@ -543,21 +581,12 @@ void MatcherGen::EmitResultOfNamedOperand(const TreePatternNode *N, SmallVectorImpl<unsigned> &ResultOps){ assert(!N->getName().empty() && "Operand not named!"); - // A reference to a complex pattern gets all of the results of the complex - // pattern's match. - if (const ComplexPattern *CP = N->getComplexPatternInfo(CGP)) { - unsigned SlotNo = 0; - for (unsigned i = 0, e = MatchedComplexPatterns.size(); i != e; ++i) - if (MatchedComplexPatterns[i].first->getName() == N->getName()) { - SlotNo = MatchedComplexPatterns[i].second; - break; - } - assert(SlotNo != 0 && "Didn't get a slot number assigned?"); + if (unsigned SlotNo = NamedComplexPatternOperands[N->getName()]) { + // Complex operands have already been completely selected, just find the + // right slot ant add the arguments directly. + for (unsigned i = 0; i < N->getNumMIResults(CGP); ++i) + ResultOps.push_back(SlotNo - 1 + i); - // The first slot entry is the node itself, the subsequent entries are the - // matched values. - for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) - ResultOps.push_back(SlotNo+i); return; } @@ -575,7 +604,8 @@ void MatcherGen::EmitResultOfNamedOperand(const TreePatternNode *N, } } - ResultOps.push_back(SlotNo); + for (unsigned i = 0; i < N->getNumMIResults(CGP); ++i) + ResultOps.push_back(SlotNo + i); } void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N, @@ -600,7 +630,7 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N, } if (Def->getName() == "zero_reg") { - AddMatcher(new EmitRegisterMatcher(0, N->getType(0))); + AddMatcher(new EmitRegisterMatcher(nullptr, N->getType(0))); ResultOps.push_back(NextRecordedOperandNo++); return; } @@ -642,7 +672,7 @@ GetInstPatternNode(const DAGInstruction &Inst, const TreePatternNode *N) { else if (/*isRoot*/ N == Pattern.getDstPattern()) InstPatNode = Pattern.getSrcPattern(); else - return 0; + return nullptr; if (InstPatNode && !InstPatNode->isLeaf() && InstPatNode->getOperator()->getName() == "set") @@ -806,7 +836,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, if (isRoot && !Pattern.getDstRegs().empty()) { // If the root came from an implicit def in the instruction handling stuff, // don't re-add it. - Record *HandledReg = 0; + Record *HandledReg = nullptr; if (II.HasOneImplicitDefWithKnownVT(CGT) != MVT::Other) HandledReg = II.ImplicitDefs[0]; @@ -924,7 +954,7 @@ void MatcherGen::EmitResultCode() { if (!Pattern.getDstRegs().empty()) { // If the root came from an implicit def in the instruction handling stuff, // don't re-add it. - Record *HandledReg = 0; + Record *HandledReg = nullptr; const TreePatternNode *DstPat = Pattern.getDstPattern(); if (!DstPat->isLeaf() &&DstPat->getOperator()->isSubClassOf("Instruction")){ const CodeGenTarget &CGT = CGP.getTargetInfo(); @@ -962,7 +992,7 @@ Matcher *llvm::ConvertPatternToMatcher(const PatternToMatch &Pattern, // Generate the code for the matcher. if (Gen.EmitMatcherCode(Variant)) - return 0; + return nullptr; // FIXME2: Kill extra MoveParent commands at the end of the matcher sequence. // FIXME2: Split result code out to another table, and make the matcher end diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp index b7f3b6c..0b117eb 100644 --- a/utils/TableGen/DAGISelMatcherOpt.cpp +++ b/utils/TableGen/DAGISelMatcherOpt.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "isel-opt" #include "DAGISelMatcher.h" #include "CodeGenDAGPatterns.h" #include "llvm/ADT/DenseSet.h" @@ -20,13 +19,15 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; +#define DEBUG_TYPE "isel-opt" + /// ContractNodes - Turn multiple matcher node patterns like 'MoveChild+Record' /// into single compound nodes like RecordChild. static void ContractNodes(std::unique_ptr<Matcher> &MatcherPtr, const CodeGenDAGPatterns &CGP) { // If we reached the end of the chain, we're done. Matcher *N = MatcherPtr.get(); - if (N == 0) return; + if (!N) return; // If we have a scope node, walk down all of the children. if (ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N)) { @@ -41,7 +42,7 @@ static void ContractNodes(std::unique_ptr<Matcher> &MatcherPtr, // If we found a movechild node with a node that comes in a 'foochild' form, // transform it. if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N)) { - Matcher *New = 0; + Matcher *New = nullptr; if (RecordMatcher *RM = dyn_cast<RecordMatcher>(MC->getNext())) if (MC->getChildNo() < 8) // Only have RecordChild0...7 New = new RecordChildMatcher(MC->getChildNo(), RM->getWhatFor(), @@ -191,7 +192,7 @@ static void SinkPatternPredicates(std::unique_ptr<Matcher> &MatcherPtr) { // Recursively scan for a PatternPredicate. // If we reached the end of the chain, we're done. Matcher *N = MatcherPtr.get(); - if (N == 0) return; + if (!N) return; // Walk down all members of a scope node. if (ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N)) { @@ -206,7 +207,7 @@ static void SinkPatternPredicates(std::unique_ptr<Matcher> &MatcherPtr) { // If this node isn't a CheckPatternPredicateMatcher we keep scanning until // we find one. CheckPatternPredicateMatcher *CPPM =dyn_cast<CheckPatternPredicateMatcher>(N); - if (CPPM == 0) + if (!CPPM) return SinkPatternPredicates(N->getNextPtr()); // Ok, we found one, lets try to sink it. Check if we can sink it past the @@ -236,7 +237,7 @@ static Matcher *FindNodeWithKind(Matcher *M, Matcher::KindTy Kind) { for (; M; M = M->getNext()) if (M->getKind() == Kind) return M; - return 0; + return nullptr; } @@ -255,11 +256,11 @@ static Matcher *FindNodeWithKind(Matcher *M, Matcher::KindTy Kind) { static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) { // If we reached the end of the chain, we're done. Matcher *N = MatcherPtr.get(); - if (N == 0) return; + if (!N) return; // If this is not a push node, just scan for one. ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N); - if (Scope == 0) + if (!Scope) return FactorNodes(N->getNextPtr()); // Okay, pull together the children of the scope node into a vector so we can @@ -335,7 +336,7 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) { // or the same as what we're looking for. If so, reorder it. if (Optn->isSimplePredicateOrRecordNode()) { Matcher *M2 = FindNodeWithKind(ScanMatcher, Optn->getKind()); - if (M2 != 0 && M2 != ScanMatcher && + if (M2 && M2 != ScanMatcher && M2->canMoveBefore(ScanMatcher) && (M2->isEqual(Optn) || M2->isContradictory(Optn))) { Matcher *MatcherWithoutM2 = ScanMatcher->unlinkNode(M2); @@ -399,7 +400,7 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) { } if (NewOptionsToMatch.empty()) { - MatcherPtr.reset(0); + MatcherPtr.reset(nullptr); return; } @@ -427,7 +428,7 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) { CheckTypeMatcher *CTM = cast_or_null<CheckTypeMatcher>(FindNodeWithKind(NewOptionsToMatch[i], Matcher::CheckType)); - if (CTM == 0 || + if (!CTM || // iPTR checks could alias any other case without us knowing, don't // bother with them. CTM->getType() == MVT::iPTR || diff --git a/utils/TableGen/DFAPacketizerEmitter.cpp b/utils/TableGen/DFAPacketizerEmitter.cpp index 2549c47..ea14cb9 100644 --- a/utils/TableGen/DFAPacketizerEmitter.cpp +++ b/utils/TableGen/DFAPacketizerEmitter.cpp @@ -82,14 +82,15 @@ namespace { class State { public: static int currentStateNum; - int stateNum; - bool isInitial; - std::set<unsigned> stateInfo; - typedef std::map<unsigned, State *> TransitionMap; - TransitionMap Transitions; + // stateNum is the only member used for equality/ordering, all other members + // can be mutated even in const State objects. + const int stateNum; + mutable bool isInitial; + mutable std::set<unsigned> stateInfo; + typedef std::map<unsigned, const State *> TransitionMap; + mutable TransitionMap Transitions; State(); - State(const State &S); bool operator<(const State &s) const { return stateNum < s.stateNum; @@ -108,16 +109,16 @@ class State { // AddInsnClass - Return all combinations of resource reservation // which are possible from this state (PossibleStates). // - void AddInsnClass(unsigned InsnClass, std::set<unsigned> &PossibleStates); + void AddInsnClass(unsigned InsnClass, std::set<unsigned> &PossibleStates) const; // // addTransition - Add a transition from this state given the input InsnClass // - void addTransition(unsigned InsnClass, State *To); + void addTransition(unsigned InsnClass, const State *To) const; // // hasTransition - Returns true if there is a transition from this state // given the input InsnClass // - bool hasTransition(unsigned InsnClass); + bool hasTransition(unsigned InsnClass) const; }; } // End anonymous namespace. @@ -128,10 +129,9 @@ namespace { class DFA { public: DFA(); - ~DFA(); // Set of states. Need to keep this sorted to emit the transition table. - typedef std::set<State *, less_ptr<State> > StateSet; + typedef std::set<State> StateSet; StateSet states; State *currentState; @@ -139,8 +139,7 @@ public: // // Modify the DFA. // - void initialize(); - void addState(State *); + const State &newState(); // // writeTable: Print out a table representing the DFA. @@ -156,21 +155,12 @@ public: State::State() : stateNum(currentStateNum++), isInitial(false) {} - -State::State(const State &S) : - stateNum(currentStateNum++), isInitial(S.isInitial), - stateInfo(S.stateInfo) {} - -DFA::DFA(): currentState(NULL) {} - -DFA::~DFA() { - DeleteContainerPointers(states); -} +DFA::DFA(): currentState(nullptr) {} // // addTransition - Add a transition from this state given the input InsnClass // -void State::addTransition(unsigned InsnClass, State *To) { +void State::addTransition(unsigned InsnClass, const State *To) const { assert(!Transitions.count(InsnClass) && "Cannot have multiple transitions for the same input"); Transitions[InsnClass] = To; @@ -180,7 +170,7 @@ void State::addTransition(unsigned InsnClass, State *To) { // hasTransition - Returns true if there is a transition from this state // given the input InsnClass // -bool State::hasTransition(unsigned InsnClass) { +bool State::hasTransition(unsigned InsnClass) const { return Transitions.count(InsnClass) > 0; } @@ -189,7 +179,7 @@ bool State::hasTransition(unsigned InsnClass) { // which are possible from this state (PossibleStates). // void State::AddInsnClass(unsigned InsnClass, - std::set<unsigned> &PossibleStates) { + std::set<unsigned> &PossibleStates) const { // // Iterate over all resource states in currentState. // @@ -248,15 +238,10 @@ bool State::canAddInsnClass(unsigned InsnClass) const { } -void DFA::initialize() { - assert(currentState && "Missing current state"); - currentState->isInitial = true; -} - - -void DFA::addState(State *S) { - assert(!states.count(S) && "State already exists"); - states.insert(S); +const State &DFA::newState() { + auto IterPair = states.insert(State()); + assert(IterPair.second && "State already exists"); + return *IterPair.first; } @@ -292,16 +277,16 @@ void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName) { // to construct the StateEntry table. int ValidTransitions = 0; for (unsigned i = 0; i < states.size(); ++i, ++SI) { - assert (((*SI)->stateNum == (int) i) && "Mismatch in state numbers"); + assert ((SI->stateNum == (int) i) && "Mismatch in state numbers"); StateEntry[i] = ValidTransitions; for (State::TransitionMap::iterator - II = (*SI)->Transitions.begin(), IE = (*SI)->Transitions.end(); + II = SI->Transitions.begin(), IE = SI->Transitions.end(); II != IE; ++II) { OS << "{" << II->first << ", " << II->second->stateNum << "}, "; } - ValidTransitions += (*SI)->Transitions.size(); + ValidTransitions += SI->Transitions.size(); // If there are no valid transitions from this stage, we need a sentinel // transition. @@ -447,12 +432,11 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { // Run a worklist algorithm to generate the DFA. // DFA D; - State *Initial = new State; + const State *Initial = &D.newState(); Initial->isInitial = true; Initial->stateInfo.insert(0x0); - D.addState(Initial); - SmallVector<State*, 32> WorkList; - std::map<std::set<unsigned>, State*> Visited; + SmallVector<const State*, 32> WorkList; + std::map<std::set<unsigned>, const State*> Visited; WorkList.push_back(Initial); @@ -474,7 +458,7 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { // Add S' to Visited // while (!WorkList.empty()) { - State *current = WorkList.pop_back_val(); + const State *current = WorkList.pop_back_val(); for (DenseSet<unsigned>::iterator CI = allInsnClasses.begin(), CE = allInsnClasses.end(); CI != CE; ++CI) { unsigned InsnClass = *CI; @@ -486,7 +470,7 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { // if (!current->hasTransition(InsnClass) && current->canAddInsnClass(InsnClass)) { - State *NewState = NULL; + const State *NewState; current->AddInsnClass(InsnClass, NewStateResources); assert(NewStateResources.size() && "New states must be generated"); @@ -494,13 +478,12 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { // If we have seen this state before, then do not create a new state. // // - std::map<std::set<unsigned>, State*>::iterator VI; - if ((VI = Visited.find(NewStateResources)) != Visited.end()) + auto VI = Visited.find(NewStateResources); + if (VI != Visited.end()) NewState = VI->second; else { - NewState = new State; + NewState = &D.newState(); NewState->stateInfo = NewStateResources; - D.addState(NewState); Visited[NewStateResources] = NewState; WorkList.push_back(NewState); } diff --git a/utils/TableGen/DisassemblerEmitter.cpp b/utils/TableGen/DisassemblerEmitter.cpp index 0020de6..f02051a 100644 --- a/utils/TableGen/DisassemblerEmitter.cpp +++ b/utils/TableGen/DisassemblerEmitter.cpp @@ -127,10 +127,13 @@ void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) { } // ARM and Thumb have a CHECK() macro to deal with DecodeStatuses. - if (Target.getName() == "ARM" || - Target.getName() == "Thumb" || - Target.getName() == "AArch64") { - EmitFixedLenDecoder(Records, OS, Target.getName() == "AArch64" ? "AArch64" : "ARM", + if (Target.getName() == "ARM" || Target.getName() == "Thumb" || + Target.getName() == "AArch64" || Target.getName() == "ARM64") { + std::string PredicateNamespace = Target.getName(); + if (PredicateNamespace == "Thumb") + PredicateNamespace = "ARM"; + + EmitFixedLenDecoder(Records, OS, PredicateNamespace, "if (!Check(S, ", ")) return MCDisassembler::Fail;", "S", "MCDisassembler::Fail", " MCDisassembler::DecodeStatus S = " diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp index 3a3f836..154f96d 100644 --- a/utils/TableGen/FastISelEmitter.cpp +++ b/utils/TableGen/FastISelEmitter.cpp @@ -188,7 +188,7 @@ struct OperandsSignature { return true; } - const CodeGenRegisterClass *DstRC = 0; + const CodeGenRegisterClass *DstRC = nullptr; for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) { TreePatternNode *Op = InstPatNode->getChild(i); @@ -252,7 +252,7 @@ struct OperandsSignature { Record *OpLeafRec = OpDI->getDef(); // For now, the only other thing we accept is register operands. - const CodeGenRegisterClass *RC = 0; + const CodeGenRegisterClass *RC = nullptr; if (OpLeafRec->isSubClassOf("RegisterOperand")) OpLeafRec = OpLeafRec->getValueAsDef("RegClass"); if (OpLeafRec->isSubClassOf("RegisterClass")) @@ -459,7 +459,7 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) { // For now, ignore instructions where the first operand is not an // output register. - const CodeGenRegisterClass *DstRC = 0; + const CodeGenRegisterClass *DstRC = nullptr; std::string SubRegNo; if (Op->getName() != "EXTRACT_SUBREG") { Record *Op0Rec = II.Operands[0].Rec; diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp index e249a94..42639cc 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -12,8 +12,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "decoder-emitter" - #include "CodeGenTarget.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/SmallString.h" @@ -34,6 +32,8 @@ using namespace llvm; +#define DEBUG_TYPE "decoder-emitter" + namespace { struct EncodingField { unsigned Base, Width, Offset; @@ -347,7 +347,7 @@ public: unsigned BW, const FixedLenDecoderEmitter *E) : AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(), - Parent(NULL), BestIndex(-1), BitWidth(BW), Emitter(E) { + Parent(nullptr), BestIndex(-1), BitWidth(BW), Emitter(E) { for (unsigned i = 0; i < BitWidth; ++i) FilterBitValues.push_back(BIT_UNFILTERED); @@ -1776,7 +1776,7 @@ static bool populateInstruction(CodeGenTarget &Target, // Determine if Vals[i] actually contributes to the Inst encoding. unsigned bi = 0; for (; bi < Bits.getNumBits(); ++bi) { - VarInit *Var = 0; + VarInit *Var = nullptr; VarBitInit *BI = dyn_cast<VarBitInit>(Bits.getBit(bi)); if (BI) Var = dyn_cast<VarInit>(BI->getBitVar()); @@ -1798,7 +1798,7 @@ static bool populateInstruction(CodeGenTarget &Target, // Get the bit range for this operand: unsigned bitStart = bi++, bitWidth = 1; for (; bi < Bits.getNumBits(); ++bi) { - VarInit *Var = 0; + VarInit *Var = nullptr; VarBitInit *BI = dyn_cast<VarBitInit>(Bits.getBit(bi)); if (BI) Var = dyn_cast<VarInit>(BI->getBitVar()); @@ -1837,7 +1837,7 @@ static bool populateInstruction(CodeGenTarget &Target, RecordVal *DecoderString = TypeRecord->getValue("DecoderMethod"); StringInit *String = DecoderString ? - dyn_cast<StringInit>(DecoderString->getValue()) : 0; + dyn_cast<StringInit>(DecoderString->getValue()) : nullptr; if (String && String->getValue() != "") Decoder = String->getValue(); @@ -1866,7 +1866,7 @@ static bool populateInstruction(CodeGenTarget &Target, DecoderString = TypeRecord->getValue("DecoderMethod"); String = DecoderString ? - dyn_cast<StringInit>(DecoderString->getValue()) : 0; + dyn_cast<StringInit>(DecoderString->getValue()) : nullptr; if (!isReg && String && String->getValue() != "") Decoder = String->getValue(); @@ -1938,7 +1938,7 @@ static bool populateInstruction(CodeGenTarget &Target, RecordVal *DecoderString = TypeRecord->getValue("DecoderMethod"); StringInit *String = DecoderString ? - dyn_cast<StringInit>(DecoderString->getValue()) : 0; + dyn_cast<StringInit>(DecoderString->getValue()) : nullptr; if (!isReg && String && String->getValue() != "") Decoder = String->getValue(); @@ -1948,7 +1948,7 @@ static bool populateInstruction(CodeGenTarget &Target, unsigned Offset = 0; for (unsigned bi = 0; bi < Bits.getNumBits(); ++bi) { - VarInit *Var = 0; + VarInit *Var = nullptr; VarBitInit *BI = dyn_cast<VarBitInit>(Bits.getBit(bi)); if (BI) Var = dyn_cast<VarInit>(BI->getBitVar()); diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 7aa0f40..76f05ce 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -88,7 +88,7 @@ std::vector<std::string> InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { std::vector<std::string> Result; - for (unsigned i = 0, e = Inst.Operands.size(); i != e; ++i) { + for (auto &Op : Inst.Operands) { // Handle aggregate operands and normal operands the same way by expanding // either case into a list of operands for this op. std::vector<CGIOperandList::OperandInfo> OperandList; @@ -97,14 +97,14 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { // registers in their multi-operand operands. It may also be an anonymous // operand, which has a single operand, but no declared class for the // operand. - DagInit *MIOI = Inst.Operands[i].MIOperandInfo; + DagInit *MIOI = Op.MIOperandInfo; if (!MIOI || MIOI->getNumArgs() == 0) { // Single, anonymous, operand. - OperandList.push_back(Inst.Operands[i]); + OperandList.push_back(Op); } else { - for (unsigned j = 0, e = Inst.Operands[i].MINumOperands; j != e; ++j) { - OperandList.push_back(Inst.Operands[i]); + for (unsigned j = 0, e = Op.MINumOperands; j != e; ++j) { + OperandList.push_back(Op); Record *OpR = cast<DefInit>(MIOI->getArg(j))->getDef(); OperandList.back().Rec = OpR; @@ -134,24 +134,24 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { // Predicate operands. Check to see if the original unexpanded operand // was of type PredicateOp. - if (Inst.Operands[i].Rec->isSubClassOf("PredicateOp")) + if (Op.Rec->isSubClassOf("PredicateOp")) Res += "|(1<<MCOI::Predicate)"; // Optional def operands. Check to see if the original unexpanded operand // was of type OptionalDefOperand. - if (Inst.Operands[i].Rec->isSubClassOf("OptionalDefOperand")) + if (Op.Rec->isSubClassOf("OptionalDefOperand")) Res += "|(1<<MCOI::OptionalDef)"; // Fill in operand type. Res += ", MCOI::"; - assert(!Inst.Operands[i].OperandType.empty() && "Invalid operand type."); - Res += Inst.Operands[i].OperandType; + assert(!Op.OperandType.empty() && "Invalid operand type."); + Res += Op.OperandType; // Fill in constraint info. Res += ", "; const CGIOperandList::ConstraintInfo &Constraint = - Inst.Operands[i].Constraints[j]; + Op.Constraints[j]; if (Constraint.isNone()) Res += "0"; else if (Constraint.isEarlyClobber()) @@ -177,16 +177,15 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS, OS << "\n"; const CodeGenTarget &Target = CDP.getTargetInfo(); - for (CodeGenTarget::inst_iterator II = Target.inst_begin(), - E = Target.inst_end(); II != E; ++II) { - std::vector<std::string> OperandInfo = GetOperandInfo(**II); + for (const CodeGenInstruction *Inst : Target.instructions()) { + std::vector<std::string> OperandInfo = GetOperandInfo(*Inst); unsigned &N = OperandInfoIDs[OperandInfo]; if (N != 0) continue; N = ++OperandListNum; OS << "static const MCOperandInfo OperandInfo" << N << "[] = { "; - for (unsigned i = 0, e = OperandInfo.size(); i != e; ++i) - OS << "{ " << OperandInfo[i] << " }, "; + for (const std::string &Info : OperandInfo) + OS << "{ " << Info << " }, "; OS << "};\n"; } } @@ -206,14 +205,11 @@ void InstrInfoEmitter::initOperandMapData( OpNameMapTy &OperandMap) { unsigned NumOperands = 0; - for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { - const CodeGenInstruction *Inst = NumberedInstructions[i]; - if (!Inst->TheDef->getValueAsBit("UseNamedOperandTable")) { + for (const CodeGenInstruction *Inst : NumberedInstructions) { + if (!Inst->TheDef->getValueAsBit("UseNamedOperandTable")) continue; - } std::map<unsigned, unsigned> OpList; - for (unsigned j = 0, je = Inst->Operands.size(); j != je; ++j) { - const CGIOperandList::OperandInfo &Info = Inst->Operands[j]; + for (const auto &Info : Inst->Operands) { StrUintMapIter I = Operands.find(Info.Name); if (I == Operands.end()) { @@ -256,8 +252,8 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS, OS << "namespace " << Namespace << " {\n"; OS << "namespace " << OpNameNS << " { \n"; OS << "enum {\n"; - for (StrUintMapIter i = Operands.begin(), e = Operands.end(); i != e; ++i) - OS << " " << i->first << " = " << i->second << ",\n"; + for (const auto &Op : Operands) + OS << " " << Op.first << " = " << Op.second << ",\n"; OS << "OPERAND_LAST"; OS << "\n};\n"; @@ -274,15 +270,13 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS, if (!Operands.empty()) { OS << " static const int16_t OperandMap [][" << Operands.size() << "] = {\n"; - for (OpNameMapTy::iterator i = OperandMap.begin(), e = OperandMap.end(); - i != e; ++i) { - const std::map<unsigned, unsigned> &OpList = i->first; + for (const auto &Entry : OperandMap) { + const std::map<unsigned, unsigned> &OpList = Entry.first; OS << "{"; // Emit a row of the OperandMap table - for (unsigned ii = 0, ie = Operands.size(); ii != ie; ++ii) - OS << (OpList.count(ii) == 0 ? -1 : (int)OpList.find(ii)->second) - << ", "; + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + OS << (OpList.count(i) == 0 ? -1 : (int)OpList.find(i)->second) << ", "; OS << "},\n"; } @@ -290,12 +284,9 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS, OS << " switch(Opcode) {\n"; unsigned TableIndex = 0; - for (OpNameMapTy::iterator i = OperandMap.begin(), e = OperandMap.end(); - i != e; ++i) { - std::vector<std::string> &OpcodeList = i->second; - - for (unsigned ii = 0, ie = OpcodeList.size(); ii != ie; ++ii) - OS << " case " << OpcodeList[ii] << ":\n"; + for (const auto &Entry : OperandMap) { + for (const std::string &Name : Entry.second) + OS << " case " << Name << ":\n"; OS << " return OperandMap[" << TableIndex++ << "][NamedIdx];\n"; } @@ -328,9 +319,11 @@ void InstrInfoEmitter::emitOperandTypesEnum(raw_ostream &OS, OS << "namespace OpTypes { \n"; OS << "enum OperandType {\n"; - for (unsigned oi = 0, oe = Operands.size(); oi != oe; ++oi) { - if (!Operands[oi]->isAnonymous()) - OS << " " << Operands[oi]->getName() << " = " << oi << ",\n"; + unsigned EnumVal = 0; + for (const Record *Op : Operands) { + if (!Op->isAnonymous()) + OS << " " << Op->getName() << " = " << EnumVal << ",\n"; + ++EnumVal; } OS << " OPERAND_TYPE_LIST_END" << "\n};\n"; @@ -365,9 +358,8 @@ void InstrInfoEmitter::run(raw_ostream &OS) { unsigned ListNumber = 0; // Emit all of the instruction's implicit uses and defs. - for (CodeGenTarget::inst_iterator II = Target.inst_begin(), - E = Target.inst_end(); II != E; ++II) { - Record *Inst = (*II)->TheDef; + for (const CodeGenInstruction *II : Target.instructions()) { + Record *Inst = II->TheDef; std::vector<Record*> Uses = Inst->getValueAsListOfDefs("Uses"); if (!Uses.empty()) { unsigned &IL = EmittedLists[Uses]; @@ -391,29 +383,30 @@ void InstrInfoEmitter::run(raw_ostream &OS) { const std::vector<const CodeGenInstruction*> &NumberedInstructions = Target.getInstructionsByEnumValue(); - for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) - emitRecord(*NumberedInstructions[i], i, InstrInfo, EmittedLists, - OperandInfoIDs, OS); - OS << "};\n\n"; - - // Build an array of instruction names SequenceToOffsetTable<std::string> InstrNames; - for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { - const CodeGenInstruction *Instr = NumberedInstructions[i]; - InstrNames.add(Instr->TheDef->getName()); + unsigned Num = 0; + for (const CodeGenInstruction *Inst : NumberedInstructions) { + // Keep a list of the instruction names. + InstrNames.add(Inst->TheDef->getName()); + // Emit the record into the table. + emitRecord(*Inst, Num++, InstrInfo, EmittedLists, OperandInfoIDs, OS); } + OS << "};\n\n"; + // Emit the array of instruction names. InstrNames.layout(); OS << "extern const char " << TargetName << "InstrNameData[] = {\n"; InstrNames.emit(OS, printChar); OS << "};\n\n"; OS << "extern const unsigned " << TargetName <<"InstrNameIndices[] = {"; - for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { - if (i % 8 == 0) + Num = 0; + for (const CodeGenInstruction *Inst : NumberedInstructions) { + // Newline every eight entries. + if (Num % 8 == 0) OS << "\n "; - const CodeGenInstruction *Instr = NumberedInstructions[i]; - OS << InstrNames.get(Instr->TheDef->getName()) << "U, "; + OS << InstrNames.get(Inst->TheDef->getName()) << "U, "; + ++Num; } OS << "\n};\n\n"; @@ -530,20 +523,20 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, // Emit the implicit uses and defs lists... std::vector<Record*> UseList = Inst.TheDef->getValueAsListOfDefs("Uses"); if (UseList.empty()) - OS << "NULL, "; + OS << "nullptr, "; else OS << "ImplicitList" << EmittedLists[UseList] << ", "; std::vector<Record*> DefList = Inst.TheDef->getValueAsListOfDefs("Defs"); if (DefList.empty()) - OS << "NULL, "; + OS << "nullptr, "; else OS << "ImplicitList" << EmittedLists[DefList] << ", "; // Emit the operand info. std::vector<std::string> OperandInfo = GetOperandInfo(Inst); if (OperandInfo.empty()) - OS << "0"; + OS << "nullptr"; else OS << "OperandInfo" << OpInfo.find(OperandInfo)->second; @@ -555,10 +548,10 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, else if (!Inst.DeprecatedReason.empty()) // Emit the Subtarget feature. OS << "," << Target.getInstNamespace() << "::" << Inst.DeprecatedReason - << ",0"; + << ",nullptr"; else // Instruction isn't deprecated. - OS << ",0,0"; + OS << ",0,nullptr"; OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n"; } @@ -586,18 +579,16 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) { OS << "namespace " << Namespace << " {\n"; OS << " enum {\n"; - for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { - OS << " " << NumberedInstructions[i]->TheDef->getName() - << "\t= " << i << ",\n"; - } + unsigned Num = 0; + for (const CodeGenInstruction *Inst : NumberedInstructions) + OS << " " << Inst->TheDef->getName() << "\t= " << Num++ << ",\n"; OS << " INSTRUCTION_LIST_END = " << NumberedInstructions.size() << "\n"; OS << " };\n"; OS << "namespace Sched {\n"; OS << " enum {\n"; - for (unsigned i = 0, e = SchedModels.numInstrSchedClasses(); i != e; ++i) { - OS << " " << SchedModels.getSchedClass(i).Name - << "\t= " << i << ",\n"; - } + Num = 0; + for (const auto &Class : SchedModels.explicit_classes()) + OS << " " << Class.Name << "\t= " << Num++ << ",\n"; OS << " SCHED_LIST_END = " << SchedModels.numInstrSchedClasses() << "\n"; OS << " };\n}\n}\n"; OS << "} // End llvm namespace \n"; diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index 7b0a2b6..1927ad9 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -14,6 +14,7 @@ #include "CodeGenIntrinsics.h" #include "CodeGenTarget.h" #include "SequenceToOffsetTable.h" +#include "TableGenBackends.h" #include "llvm/ADT/StringExtras.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" @@ -45,8 +46,6 @@ public: raw_ostream &OS); void EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS); - void EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints, - raw_ostream &OS); void EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS); void EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, @@ -478,11 +477,13 @@ void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints, OS << "#endif\n\n"; // End of GET_INTRINSIC_GENERATOR_GLOBAL } +namespace { enum ModRefKind { MRK_none, MRK_readonly, MRK_readnone }; +} static ModRefKind getModRefKind(const CodeGenIntrinsic &intrinsic) { switch (intrinsic.ModRef) { @@ -789,10 +790,6 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, OS << "#endif\n\n"; } -namespace llvm { - -void EmitIntrinsics(RecordKeeper &RK, raw_ostream &OS, bool TargetOnly = false) { +void llvm::EmitIntrinsics(RecordKeeper &RK, raw_ostream &OS, bool TargetOnly) { IntrinsicEmitter(RK, TargetOnly).run(OS); } - -} // End llvm namespace diff --git a/utils/TableGen/PseudoLoweringEmitter.cpp b/utils/TableGen/PseudoLoweringEmitter.cpp index 100338c..3b74ac4 100644 --- a/utils/TableGen/PseudoLoweringEmitter.cpp +++ b/utils/TableGen/PseudoLoweringEmitter.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "pseudo-lowering" #include "CodeGenInstruction.h" #include "CodeGenTarget.h" #include "llvm/ADT/IndexedMap.h" @@ -21,6 +20,8 @@ #include <vector> using namespace llvm; +#define DEBUG_TYPE "pseudo-lowering" + namespace { class PseudoLoweringEmitter { struct OpData { @@ -156,8 +157,7 @@ void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) { // If there are more operands that weren't in the DAG, they have to // be operands that have default values, or we have an error. Currently, - // Operands that are a sublass of OperandWithDefaultOp have default values. - + // Operands that are a subclass of OperandWithDefaultOp have default values. // Validate that each result pattern argument has a matching (by name) // argument in the source instruction, in either the (outs) or (ins) list. @@ -200,70 +200,74 @@ void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) { o << "bool " << Target.getName() + "AsmPrinter" << "::\n" << "emitPseudoExpansionLowering(MCStreamer &OutStreamer,\n" - << " const MachineInstr *MI) {\n" - << " switch (MI->getOpcode()) {\n" - << " default: return false;\n"; - for (unsigned i = 0, e = Expansions.size(); i != e; ++i) { - PseudoExpansion &Expansion = Expansions[i]; - CodeGenInstruction &Source = Expansion.Source; - CodeGenInstruction &Dest = Expansion.Dest; - o << " case " << Source.Namespace << "::" - << Source.TheDef->getName() << ": {\n" - << " MCInst TmpInst;\n" - << " MCOperand MCOp;\n" - << " TmpInst.setOpcode(" << Dest.Namespace << "::" - << Dest.TheDef->getName() << ");\n"; - - // Copy the operands from the source instruction. - // FIXME: Instruction operands with defaults values (predicates and cc_out - // in ARM, for example shouldn't need explicit values in the - // expansion DAG. - unsigned MIOpNo = 0; - for (unsigned OpNo = 0, E = Dest.Operands.size(); OpNo != E; - ++OpNo) { - o << " // Operand: " << Dest.Operands[OpNo].Name << "\n"; - for (unsigned i = 0, e = Dest.Operands[OpNo].MINumOperands; - i != e; ++i) { - switch (Expansion.OperandMap[MIOpNo + i].Kind) { - case OpData::Operand: - o << " lowerOperand(MI->getOperand(" - << Source.Operands[Expansion.OperandMap[MIOpNo].Data - .Operand].MIOperandNo + i - << "), MCOp);\n" - << " TmpInst.addOperand(MCOp);\n"; - break; - case OpData::Imm: - o << " TmpInst.addOperand(MCOperand::CreateImm(" - << Expansion.OperandMap[MIOpNo + i].Data.Imm << "));\n"; - break; - case OpData::Reg: { - Record *Reg = Expansion.OperandMap[MIOpNo + i].Data.Reg; - o << " TmpInst.addOperand(MCOperand::CreateReg("; - // "zero_reg" is special. - if (Reg->getName() == "zero_reg") - o << "0"; - else - o << Reg->getValueAsString("Namespace") << "::" << Reg->getName(); - o << "));\n"; - break; - } + << " const MachineInstr *MI) {\n"; + + if (!Expansions.empty()) { + o << " switch (MI->getOpcode()) {\n" + << " default: return false;\n"; + for (auto &Expansion : Expansions) { + CodeGenInstruction &Source = Expansion.Source; + CodeGenInstruction &Dest = Expansion.Dest; + o << " case " << Source.Namespace << "::" + << Source.TheDef->getName() << ": {\n" + << " MCInst TmpInst;\n" + << " MCOperand MCOp;\n" + << " TmpInst.setOpcode(" << Dest.Namespace << "::" + << Dest.TheDef->getName() << ");\n"; + + // Copy the operands from the source instruction. + // FIXME: Instruction operands with defaults values (predicates and cc_out + // in ARM, for example shouldn't need explicit values in the + // expansion DAG. + unsigned MIOpNo = 0; + for (const auto &DestOperand : Dest.Operands) { + o << " // Operand: " << DestOperand.Name << "\n"; + for (unsigned i = 0, e = DestOperand.MINumOperands; i != e; ++i) { + switch (Expansion.OperandMap[MIOpNo + i].Kind) { + case OpData::Operand: + o << " lowerOperand(MI->getOperand(" + << Source.Operands[Expansion.OperandMap[MIOpNo].Data + .Operand].MIOperandNo + i + << "), MCOp);\n" + << " TmpInst.addOperand(MCOp);\n"; + break; + case OpData::Imm: + o << " TmpInst.addOperand(MCOperand::CreateImm(" + << Expansion.OperandMap[MIOpNo + i].Data.Imm << "));\n"; + break; + case OpData::Reg: { + Record *Reg = Expansion.OperandMap[MIOpNo + i].Data.Reg; + o << " TmpInst.addOperand(MCOperand::CreateReg("; + // "zero_reg" is special. + if (Reg->getName() == "zero_reg") + o << "0"; + else + o << Reg->getValueAsString("Namespace") << "::" + << Reg->getName(); + o << "));\n"; + break; + } + } } + MIOpNo += DestOperand.MINumOperands; } - MIOpNo += Dest.Operands[OpNo].MINumOperands; - } - if (Dest.Operands.isVariadic) { - MIOpNo = Source.Operands.size() + 1; - o << " // variable_ops\n"; - o << " for (unsigned i = " << MIOpNo - << ", e = MI->getNumOperands(); i != e; ++i)\n" - << " if (lowerOperand(MI->getOperand(i), MCOp))\n" - << " TmpInst.addOperand(MCOp);\n"; + if (Dest.Operands.isVariadic) { + MIOpNo = Source.Operands.size() + 1; + o << " // variable_ops\n"; + o << " for (unsigned i = " << MIOpNo + << ", e = MI->getNumOperands(); i != e; ++i)\n" + << " if (lowerOperand(MI->getOperand(i), MCOp))\n" + << " TmpInst.addOperand(MCOp);\n"; + } + o << " EmitToStreamer(OutStreamer, TmpInst);\n" + << " break;\n" + << " }\n"; } - o << " EmitToStreamer(OutStreamer, TmpInst);\n" - << " break;\n" - << " }\n"; - } - o << " }\n return true;\n}\n\n"; + o << " }\n return true;"; + } else + o << " return false;"; + + o << "\n}\n\n"; } void PseudoLoweringEmitter::run(raw_ostream &o) { diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 61ae262..573c37f 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -225,7 +225,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, for (unsigned i = 0; i < NumSets; ++i ) { OS << " \"" << RegBank.getRegSetAt(i).Name << "\",\n"; } - OS << " 0 };\n" + OS << " nullptr };\n" << " return PressureNameTable[Idx];\n" << "}\n\n"; @@ -831,7 +831,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, // Emit the table of register unit roots. Each regunit has one or two root // registers. - OS << "extern const uint16_t " << TargetName << "RegUnitRoots[][2] = {\n"; + OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2] = {\n"; for (unsigned i = 0, e = RegBank.getNumNativeRegUnits(); i != e; ++i) { ArrayRef<const CodeGenRegister*> Roots = RegBank.getRegUnit(i).getRoots(); assert(!Roots.empty() && "All regunits must have a root register."); @@ -858,7 +858,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, // Emit the register list now. OS << " // " << Name << " Register Class...\n" - << " const uint16_t " << Name + << " const MCPhysReg " << Name << "[] = {\n "; for (unsigned i = 0, e = Order.size(); i != e; ++i) { Record *Reg = Order[i]; @@ -1068,7 +1068,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Now that all of the structs have been emitted, emit the instances. if (!RegisterClasses.empty()) { OS << "\nstatic const TargetRegisterClass *const " - << "NullRegClasses[] = { NULL };\n\n"; + << "NullRegClasses[] = { nullptr };\n\n"; // Emit register class bit mask tables. The first bit mask emitted for a // register class, RC, is the set of sub-classes, including RC itself. @@ -1135,7 +1135,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << RC.getName() << "Superclasses[] = {\n"; for (unsigned i = 0; i != Supers.size(); ++i) OS << " &" << Supers[i]->getQualifiedName() << "RegClass,\n"; - OS << " NULL\n};\n\n"; + OS << " nullptr\n};\n\n"; } // Emit methods. @@ -1189,7 +1189,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, else OS << RC.getName() << "Superclasses,\n "; if (RC.AltOrderSelect.empty()) - OS << "0\n"; + OS << "nullptr\n"; else OS << RC.getName() << "GetRawAllocationOrder\n"; OS << " };\n\n"; @@ -1258,7 +1258,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << " if (!Idx) return RC;\n --Idx;\n" << " assert(Idx < " << SubRegIndices.size() << " && \"Bad subreg\");\n" << " unsigned TV = Table[RC->getID()][Idx];\n" - << " return TV ? getRegClass(TV - 1) : 0;\n}\n\n"; + << " return TV ? getRegClass(TV - 1) : nullptr;\n}\n\n"; } EmitRegUnitPressure(OS, RegBank, ClassName); @@ -1267,7 +1267,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n"; OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[];\n"; OS << "extern const char " << TargetName << "RegStrings[];\n"; - OS << "extern const uint16_t " << TargetName << "RegUnitRoots[][2];\n"; + OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2];\n"; OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[];\n"; OS << "extern const MCRegisterInfo::SubRegCoveredBits " << TargetName << "SubRegIdxRanges[];\n"; diff --git a/utils/TableGen/SetTheory.cpp b/utils/TableGen/SetTheory.cpp index d952e68..5ead7ed 100644 --- a/utils/TableGen/SetTheory.cpp +++ b/utils/TableGen/SetTheory.cpp @@ -318,6 +318,6 @@ const RecVec *SetTheory::expand(Record *Set) { } // Set is not expandable. - return 0; + return nullptr; } diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index 71301aa..06f8694 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -11,8 +11,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "subtarget-emitter" - #include "CodeGenTarget.h" #include "CodeGenSchedule.h" #include "llvm/ADT/STLExtras.h" @@ -29,6 +27,8 @@ #include <vector> using namespace llvm; +#define DEBUG_TYPE "subtarget-emitter" + namespace { class SubtargetEmitter { // Each processor has a SchedClassDesc table with an entry for each SchedClass. @@ -578,7 +578,7 @@ EmitItineraries(raw_ostream &OS, OS << "\n"; OS << "static const llvm::InstrItinerary "; if (ItinList.empty()) { - OS << '*' << Name << " = 0;\n"; + OS << '*' << Name << " = nullptr;\n"; continue; } @@ -631,7 +631,7 @@ void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel, for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) { Record *PRDef = ProcModel.ProcResourceDefs[i]; - Record *SuperDef = 0; + Record *SuperDef = nullptr; unsigned SuperIdx = 0; unsigned NumUnits = 0; int BufferSize = PRDef->getValueAsInt("BufferSize"); @@ -676,7 +676,7 @@ Record *SubtargetEmitter::FindWriteResources( if (SchedWrite.TheDef->isSubClassOf("SchedWriteRes")) return SchedWrite.TheDef; - Record *AliasDef = 0; + Record *AliasDef = nullptr; for (RecIter AI = SchedWrite.Aliases.begin(), AE = SchedWrite.Aliases.end(); AI != AE; ++AI) { const CodeGenSchedRW &AliasRW = @@ -696,7 +696,7 @@ Record *SubtargetEmitter::FindWriteResources( return AliasDef; // Check this processor's list of write resources. - Record *ResDef = 0; + Record *ResDef = nullptr; for (RecIter WRI = ProcModel.WriteResDefs.begin(), WRE = ProcModel.WriteResDefs.end(); WRI != WRE; ++WRI) { if (!(*WRI)->isSubClassOf("WriteRes")) @@ -730,7 +730,7 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead, return SchedRead.TheDef; // Check this processor's list of aliases for SchedRead. - Record *AliasDef = 0; + Record *AliasDef = nullptr; for (RecIter AI = SchedRead.Aliases.begin(), AE = SchedRead.Aliases.end(); AI != AE; ++AI) { const CodeGenSchedRW &AliasRW = @@ -750,7 +750,7 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead, return AliasDef; // Check this processor's ReadAdvanceList. - Record *ResDef = 0; + Record *ResDef = nullptr; for (RecIter RAI = ProcModel.ReadAdvanceDefs.begin(), RAE = ProcModel.ReadAdvanceDefs.end(); RAI != RAE; ++RAI) { if (!(*RAI)->isSubClassOf("ReadAdvance")) @@ -884,7 +884,7 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel, if (!SCI->InstRWs.empty()) { // This class has a default ReadWrite list which can be overriden by // InstRW definitions. - Record *RWDef = 0; + Record *RWDef = nullptr; for (RecIter RWI = SCI->InstRWs.begin(), RWE = SCI->InstRWs.end(); RWI != RWE; ++RWI) { Record *RWModelDef = (*RWI)->getValueAsDef("SchedModel"); @@ -1195,6 +1195,7 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n"; EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ','); EmitProcessorProp(OS, PI->ModelDef, "MicroOpBufferSize", ','); + EmitProcessorProp(OS, PI->ModelDef, "LoopMicroOpBufferSize", ','); EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ','); EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ','); EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ','); @@ -1454,11 +1455,11 @@ void SubtargetEmitter::run(raw_ostream &OS) { if (NumFeatures) OS << Target << "FeatureKV, "; else - OS << "0, "; + OS << "None, "; if (NumProcs) OS << Target << "SubTypeKV, "; else - OS << "0, "; + OS << "None, "; OS << '\n'; OS.indent(22); OS << Target << "ProcSchedKV, " << Target << "WriteProcResTable, " @@ -1468,10 +1469,10 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << '\n'; OS.indent(22); OS << Target << "Stages, " << Target << "OperandCycles, " - << Target << "ForwardingPaths, "; + << Target << "ForwardingPaths"; } else - OS << "0, 0, 0, "; - OS << NumFeatures << ", " << NumProcs << ");\n}\n\n"; + OS << "0, 0, 0"; + OS << ");\n}\n\n"; OS << "} // End llvm namespace \n"; @@ -1481,7 +1482,6 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n"; OS << "#include \"llvm/Support/Debug.h\"\n"; - OS << "#include \"llvm/Support/raw_ostream.h\"\n"; ParseFeaturesFunction(OS, NumFeatures, NumProcs); OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n"; @@ -1532,13 +1532,13 @@ void SubtargetEmitter::run(raw_ostream &OS) { << " : TargetSubtargetInfo() {\n" << " InitMCSubtargetInfo(TT, CPU, FS, "; if (NumFeatures) - OS << Target << "FeatureKV, "; + OS << "makeArrayRef(" << Target << "FeatureKV, " << NumFeatures << "), "; else - OS << "0, "; + OS << "None, "; if (NumProcs) - OS << Target << "SubTypeKV, "; + OS << "makeArrayRef(" << Target << "SubTypeKV, " << NumProcs << "), "; else - OS << "0, "; + OS << "None, "; OS << '\n'; OS.indent(22); OS << Target << "ProcSchedKV, " << Target << "WriteProcResTable, " @@ -1548,10 +1548,10 @@ void SubtargetEmitter::run(raw_ostream &OS) { if (SchedModels.hasItineraries()) { OS << Target << "Stages, " << Target << "OperandCycles, " - << Target << "ForwardingPaths, "; + << Target << "ForwardingPaths"; } else - OS << "0, 0, 0, "; - OS << NumFeatures << ", " << NumProcs << ");\n}\n\n"; + OS << "0, 0, 0"; + OS << ");\n}\n\n"; EmitSchedModelHelpers(ClassName, OS); diff --git a/utils/TableGen/X86DisassemblerShared.h b/utils/TableGen/X86DisassemblerShared.h index 036e924..9e79b9c 100644 --- a/utils/TableGen/X86DisassemblerShared.h +++ b/utils/TableGen/X86DisassemblerShared.h @@ -13,23 +13,42 @@ #include <string.h> #include <string> -#define INSTRUCTION_SPECIFIER_FIELDS \ - struct OperandSpecifier operands[X86_MAX_OPERANDS]; \ - InstructionContext insnContext; \ - std::string name; \ - \ - InstructionSpecifier() { \ - insnContext = IC; \ - name = ""; \ - memset(operands, 0, sizeof(operands)); \ +#include "../../lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h" + +struct InstructionSpecifier { + llvm::X86Disassembler::OperandSpecifier + operands[llvm::X86Disassembler::X86_MAX_OPERANDS]; + llvm::X86Disassembler::InstructionContext insnContext; + std::string name; + + InstructionSpecifier() { + insnContext = llvm::X86Disassembler::IC; + name = ""; + memset(operands, 0, sizeof(operands)); } +}; -#define INSTRUCTION_IDS \ - InstrUID instructionIDs[256]; +/// Specifies whether a ModR/M byte is needed and (if so) which +/// instruction each possible value of the ModR/M byte corresponds to. Once +/// this information is known, we have narrowed down to a single instruction. +struct ModRMDecision { + uint8_t modrm_type; + llvm::X86Disassembler::InstrUID instructionIDs[256]; +}; -#include "../../lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h" +/// Specifies which set of ModR/M->instruction tables to look at +/// given a particular opcode. +struct OpcodeDecision { + ModRMDecision modRMDecisions[256]; +}; -#undef INSTRUCTION_SPECIFIER_FIELDS -#undef INSTRUCTION_IDS +/// Specifies which opcode->instruction tables to look at given +/// a particular context (set of attributes). Since there are many possible +/// contexts, the decoder first uses CONTEXTS_SYM to determine which context +/// applies given a specific set of attributes. Hence there are only IC_max +/// entries in this table, rather than 2^(ATTR_max). +struct ContextDecision { + OpcodeDecision opcodeDecisions[llvm::X86Disassembler::IC_max]; +}; #endif diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index 95651f6..ead419e 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -788,7 +788,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { OpcodeType opcodeType = (OpcodeType)-1; - ModRMFilter* filter = NULL; + ModRMFilter* filter = nullptr; uint8_t opcodeToSet = 0; switch (OpMap) { diff --git a/utils/TableGen/module.modulemap b/utils/TableGen/module.modulemap new file mode 100644 index 0000000..8871bbf --- /dev/null +++ b/utils/TableGen/module.modulemap @@ -0,0 +1,4 @@ +module TableGen { + umbrella "." + module * { export * } +} diff --git a/utils/lit/utils/check-coverage b/utils/lit/utils/check-coverage index bb3d17e..128e827 100755 --- a/utils/lit/utils/check-coverage +++ b/utils/lit/utils/check-coverage @@ -9,13 +9,13 @@ if [ ! -f setup.py ] || [ ! -d lit ]; then fi # Parse command line arguments. -if [ "$1" == "--generate-html" ]; then +if [ "$1" = "--generate-html" ]; then GENERATE_HTML=1 shift fi # If invoked with no arguments, run all the tests. -if [ $# == "0" ]; then +if [ $# = "0" ]; then set -- "tests" fi diff --git a/utils/lit/utils/check-sdist b/utils/lit/utils/check-sdist index 743a971..f03266a 100755 --- a/utils/lit/utils/check-sdist +++ b/utils/lit/utils/check-sdist @@ -1,6 +1,6 @@ #!/bin/sh -if [ $# == 1 ]; then +if [ $# = 1 ]; then cd $1 fi diff --git a/utils/lldbDataFormatters.py b/utils/lldbDataFormatters.py index 1baf398..352448d 100644 --- a/utils/lldbDataFormatters.py +++ b/utils/lldbDataFormatters.py @@ -1,10 +1,18 @@ """ -Load into LLDB with: -script import lldbDataFormatters -type synthetic add -x "^llvm::SmallVectorImpl<.+>$" -l lldbDataFormatters.SmallVectorSynthProvider -type synthetic add -x "^llvm::SmallVector<.+,.+>$" -l lldbDataFormatters.SmallVectorSynthProvider +LLDB Formatters for LLVM data types. + +Load into LLDB with 'command script import /path/to/lldbDataFormatters.py' """ +def __lldb_init_module(debugger, internal_dict): + debugger.HandleCommand('type category define -e llvm -l c++') + debugger.HandleCommand('type synthetic add -w llvm ' + '-l lldbDataFormatters.SmallVectorSynthProvider ' + '-x "^llvm::SmallVectorImpl<.+>$"') + debugger.HandleCommand('type synthetic add -w llvm ' + '-l lldbDataFormatters.SmallVectorSynthProvider ' + '-x "^llvm::SmallVector<.+,.+>$"') + # Pretty printer for llvm::SmallVector/llvm::SmallVectorImpl class SmallVectorSynthProvider: def __init__(self, valobj, dict): diff --git a/utils/llvm-build/llvmbuild/componentinfo.py b/utils/llvm-build/llvmbuild/componentinfo.py index eda3a48..b384acd 100644 --- a/utils/llvm-build/llvmbuild/componentinfo.py +++ b/utils/llvm-build/llvmbuild/componentinfo.py @@ -9,7 +9,7 @@ except: import ConfigParser as configparser import sys -from llvmbuild.util import * +from llvmbuild.util import fatal, warning class ParseError(Exception): pass diff --git a/utils/llvm-build/llvmbuild/main.py b/utils/llvm-build/llvmbuild/main.py index 6cb5c12..37aa5d8 100644 --- a/utils/llvm-build/llvmbuild/main.py +++ b/utils/llvm-build/llvmbuild/main.py @@ -5,7 +5,7 @@ import sys import llvmbuild.componentinfo as componentinfo import llvmbuild.configutil as configutil -from llvmbuild.util import * +from llvmbuild.util import fatal, note ### @@ -719,7 +719,9 @@ def add_magic_target_components(parser, project, opts): enable_targets = available_targets.values() else: # We support both space separated and semi-colon separated lists. - if ' ' in opts.enable_targets: + if opts.enable_targets == '': + enable_target_names = [] + elif ' ' in opts.enable_targets: enable_target_names = opts.enable_targets.split() else: enable_target_names = opts.enable_targets.split(';') diff --git a/utils/release/test-release.sh b/utils/release/test-release.sh index f10b822..b4d7689 100755 --- a/utils/release/test-release.sh +++ b/utils/release/test-release.sh @@ -223,7 +223,7 @@ function check_valid_urls() { echo "# Validating $proj SVN URL" if ! svn ls $Base_url/$proj/tags/RELEASE_$Release_no_dot/$RC > /dev/null 2>&1 ; then - echo "llvm $Release release candidate $RC doesn't exist!" + echo "$proj $Release release candidate $RC doesn't exist!" exit 1 fi done diff --git a/utils/yaml-bench/YAMLBench.cpp b/utils/yaml-bench/YAMLBench.cpp index 3e80f23..58b7356 100644 --- a/utils/yaml-bench/YAMLBench.cpp +++ b/utils/yaml-bench/YAMLBench.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This program executes the YAMLParser on differntly sized YAML texts and +// This program executes the YAMLParser on differently sized YAML texts and // outputs the run time. // //===----------------------------------------------------------------------===// |