diff options
Diffstat (limited to 'utils')
81 files changed, 1759 insertions, 2172 deletions
diff --git a/utils/FileCheck/CMakeLists.txt b/utils/FileCheck/CMakeLists.txt index d691ceb..999320f 100644 --- a/utils/FileCheck/CMakeLists.txt +++ b/utils/FileCheck/CMakeLists.txt @@ -3,9 +3,3 @@ add_llvm_utility(FileCheck ) target_link_libraries(FileCheck LLVMSupport) -if( MINGW ) - target_link_libraries(FileCheck imagehlp psapi shell32) -endif( MINGW ) -if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD ) - target_link_libraries(FileCheck pthread) -endif() diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index f2510d7..a1f4be9 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -16,7 +16,6 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" @@ -136,7 +135,6 @@ public: Check::CheckType getCheckTy() const { return CheckTy; } private: - static void AddFixedStringToRegEx(StringRef FixedStr, std::string &TheStr); bool AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM); void AddBackrefToRegEx(unsigned BackrefNum); @@ -155,7 +153,7 @@ private: /// (right after the opening sequence). /// \return offset of the closing sequence within Str, or npos if it was not /// found. - size_t FindRegexVarEnd(StringRef Str); + size_t FindRegexVarEnd(StringRef Str, SourceMgr &SM); }; @@ -228,7 +226,7 @@ bool Pattern::ParsePattern(StringRef PatternStr, if (PatternStr.startswith("[[")) { // Find the closing bracket pair ending the match. End is going to be an // offset relative to the beginning of the match string. - size_t End = FindRegexVarEnd(PatternStr.substr(2)); + size_t End = FindRegexVarEnd(PatternStr.substr(2), SM); if (End == StringRef::npos) { SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()), @@ -314,40 +312,13 @@ bool Pattern::ParsePattern(StringRef PatternStr, // Find the end, which is the start of the next regex. size_t FixedMatchEnd = PatternStr.find("{{"); FixedMatchEnd = std::min(FixedMatchEnd, PatternStr.find("[[")); - AddFixedStringToRegEx(PatternStr.substr(0, FixedMatchEnd), RegExStr); + RegExStr += Regex::escape(PatternStr.substr(0, FixedMatchEnd)); PatternStr = PatternStr.substr(FixedMatchEnd); } return false; } -void Pattern::AddFixedStringToRegEx(StringRef FixedStr, std::string &TheStr) { - // Add the characters from FixedStr to the regex, escaping as needed. This - // avoids "leaning toothpicks" in common patterns. - for (unsigned i = 0, e = FixedStr.size(); i != e; ++i) { - switch (FixedStr[i]) { - // These are the special characters matched in "p_ere_exp". - case '(': - case ')': - case '^': - case '$': - case '|': - case '*': - case '+': - case '?': - case '.': - case '[': - case '\\': - case '{': - TheStr += '\\'; - // FALL THROUGH. - default: - TheStr += FixedStr[i]; - break; - } - } -} - bool Pattern::AddRegExToRegEx(StringRef RS, unsigned &CurParen, SourceMgr &SM) { Regex R(RS); @@ -428,8 +399,8 @@ size_t Pattern::Match(StringRef Buffer, size_t &MatchLen, if (it == VariableTable.end()) return StringRef::npos; - // Look up the value and escape it so that we can plop it into the regex. - AddFixedStringToRegEx(it->second, Value); + // Look up the value and escape it so that we can put it into the regex. + Value += Regex::escape(it->second); } // Plop it into the regex at the adjusted offset. @@ -560,7 +531,7 @@ void Pattern::PrintFailureInfo(const SourceMgr &SM, StringRef Buffer, } } -size_t Pattern::FindRegexVarEnd(StringRef Str) { +size_t Pattern::FindRegexVarEnd(StringRef Str, SourceMgr &SM) { // Offset keeps track of the current offset within the input Str size_t Offset = 0; // [...] Nesting depth @@ -581,7 +552,12 @@ size_t Pattern::FindRegexVarEnd(StringRef Str) { BracketDepth++; break; case ']': - assert(BracketDepth > 0 && "Invalid regex"); + if (BracketDepth == 0) { + SM.PrintMessage(SMLoc::getFromPointer(Str.data()), + SourceMgr::DK_Error, + "missing closing \"]\" for regex variable"); + exit(1); + } BracketDepth--; break; } @@ -795,10 +771,11 @@ static StringRef FindFirstCandidateMatch(StringRef &Buffer, // it. This should also prevent matching the wrong prefix when one is a // substring of another. if (PrefixLoc != 0 && IsPartOfWord(Buffer[PrefixLoc - 1])) - continue; + FirstTy = Check::CheckNone; + else + FirstTy = FindCheckType(Rest, Prefix); FirstLoc = PrefixLoc; - FirstTy = FindCheckType(Rest, Prefix); FirstPrefix = Prefix; } @@ -843,7 +820,7 @@ static StringRef FindFirstMatchingPrefix(StringRef &Buffer, /// Returns true in case of an error, false otherwise. static bool ReadCheckFile(SourceMgr &SM, std::vector<CheckString> &CheckStrings) { - OwningPtr<MemoryBuffer> File; + std::unique_ptr<MemoryBuffer> File; if (error_code ec = MemoryBuffer::getFileOrSTDIN(CheckFilename, File)) { errs() << "Could not open check file '" << CheckFilename << "': " @@ -854,7 +831,7 @@ static bool ReadCheckFile(SourceMgr &SM, // If we want to canonicalize whitespace, strip excess whitespace from the // buffer containing the CHECK lines. Remove DOS style line endings. MemoryBuffer *F = - CanonicalizeInputFile(File.take(), NoCanonicalizeWhiteSpace); + CanonicalizeInputFile(File.release(), NoCanonicalizeWhiteSpace); SM.AddNewSourceBuffer(F, SMLoc()); @@ -1240,7 +1217,7 @@ int main(int argc, char **argv) { return 2; // Open the file to check and add it to SourceMgr. - OwningPtr<MemoryBuffer> File; + std::unique_ptr<MemoryBuffer> File; if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, File)) { errs() << "Could not open input file '" << InputFilename << "': " @@ -1256,7 +1233,7 @@ int main(int argc, char **argv) { // Remove duplicate spaces in the input file if requested. // Remove DOS style line endings. MemoryBuffer *F = - CanonicalizeInputFile(File.take(), NoCanonicalizeWhiteSpace); + CanonicalizeInputFile(File.release(), NoCanonicalizeWhiteSpace); SM.AddNewSourceBuffer(F, SMLoc()); diff --git a/utils/FileCheck/Makefile b/utils/FileCheck/Makefile index 268b7bc..b876236 100644 --- a/utils/FileCheck/Makefile +++ b/utils/FileCheck/Makefile @@ -14,8 +14,8 @@ USEDLIBS = LLVMSupport.a # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS = 1 -# Don't install this utility -NO_INSTALL = 1 +# FIXME: Don't install this utility +#NO_INSTALL = 1 include $(LEVEL)/Makefile.common diff --git a/utils/FileUpdate/CMakeLists.txt b/utils/FileUpdate/CMakeLists.txt index 0114e50..ce7478f 100644 --- a/utils/FileUpdate/CMakeLists.txt +++ b/utils/FileUpdate/CMakeLists.txt @@ -3,9 +3,3 @@ add_llvm_utility(FileUpdate ) target_link_libraries(FileUpdate LLVMSupport) -if( MINGW ) - target_link_libraries(FileUpdate imagehlp psapi shell32) -endif( MINGW ) -if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD ) - target_link_libraries(FileUpdate pthread) -endif() diff --git a/utils/FileUpdate/FileUpdate.cpp b/utils/FileUpdate/FileUpdate.cpp index fbcd927..5ccf3f3 100644 --- a/utils/FileUpdate/FileUpdate.cpp +++ b/utils/FileUpdate/FileUpdate.cpp @@ -13,7 +13,6 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/OwningPtr.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" @@ -44,7 +43,7 @@ int main(int argc, char **argv) { } // Get the input data. - OwningPtr<MemoryBuffer> In; + std::unique_ptr<MemoryBuffer> In; if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, In)) { errs() << argv[0] << ": error: Unable to get input '" << InputFilename << "': " << ec.message() << '\n'; @@ -52,7 +51,7 @@ int main(int argc, char **argv) { } // Get the output data. - OwningPtr<MemoryBuffer> Out; + std::unique_ptr<MemoryBuffer> Out; MemoryBuffer::getFile(OutputFilename.c_str(), Out); // If the output exists and the contents match, we are done. @@ -71,7 +70,7 @@ int main(int argc, char **argv) { << "', contents changed.\n"; std::string ErrorStr; tool_output_file OutStream(OutputFilename.c_str(), ErrorStr, - sys::fs::F_Binary); + sys::fs::F_None); if (!ErrorStr.empty()) { errs() << argv[0] << ": Unable to write output '" << OutputFilename << "': " << ErrorStr << '\n'; diff --git a/utils/TableGen/Android.mk b/utils/TableGen/Android.mk index e476cd7..8117672 100644 --- a/utils/TableGen/Android.mk +++ b/utils/TableGen/Android.mk @@ -29,7 +29,6 @@ tablegen_SRC_FILES := \ RegisterInfoEmitter.cpp \ SetTheory.cpp \ SubtargetEmitter.cpp \ - TGValueTypes.cpp \ TableGen.cpp \ X86DisassemblerTables.cpp \ X86ModRMFilters.cpp \ diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index de24cde..4169f8d 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -97,7 +97,6 @@ //===----------------------------------------------------------------------===// #include "CodeGenTarget.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" @@ -288,15 +287,6 @@ public: } }; -namespace { -/// Sort ClassInfo pointers independently of pointer value. -struct LessClassInfoPtr { - bool operator()(const ClassInfo *LHS, const ClassInfo *RHS) const { - return *LHS < *RHS; - } -}; -} - /// MatchableInfo - Helper class for storing the necessary information for an /// instruction or alias which is capable of being matched. struct MatchableInfo { @@ -729,12 +719,12 @@ void MatchableInfo::formTwoOperandAlias(StringRef Constraint) { int DstAsmOperand = findAsmOperandNamed(Ops.second); if (SrcAsmOperand == -1) PrintFatalError(TheDef->getLoc(), - "unknown source two-operand alias operand '" + - Ops.first.str() + "'."); + "unknown source two-operand alias operand '" + Ops.first + + "'."); if (DstAsmOperand == -1) PrintFatalError(TheDef->getLoc(), - "unknown destination two-operand alias operand '" + - Ops.second.str() + "'."); + "unknown destination two-operand alias operand '" + + Ops.second + "'."); // Find the ResOperand that refers to the operand we're aliasing away // and update it to refer to the combined operand instead. @@ -882,7 +872,7 @@ void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info) { // FIXME : Check and raise an error if it is a register. if (Mnemonic[0] == '$') PrintFatalError(TheDef->getLoc(), - "Invalid instruction mnemonic '" + Mnemonic.str() + "'!"); + "Invalid instruction mnemonic '" + Mnemonic + "'!"); // Remove the first operand, it is tracked in the mnemonic field. AsmOperands.erase(AsmOperands.begin()); @@ -919,22 +909,22 @@ bool MatchableInfo::validate(StringRef CommentDelimiter, bool Hack) const { StringRef Tok = AsmOperands[i].Token; if (Tok[0] == '$' && Tok.find(':') != StringRef::npos) PrintFatalError(TheDef->getLoc(), - "matchable with operand modifier '" + Tok.str() + - "' not supported by asm matcher. Mark isCodeGenOnly!"); + "matchable with operand modifier '" + Tok + + "' not supported by asm matcher. Mark isCodeGenOnly!"); // Verify that any operand is only mentioned once. // We reject aliases and ignore instructions for now. if (Tok[0] == '$' && !OperandNames.insert(Tok).second) { if (!Hack) PrintFatalError(TheDef->getLoc(), - "ERROR: matchable with tied operand '" + Tok.str() + - "' can never be matched!"); + "ERROR: matchable with tied operand '" + Tok + + "' can never be matched!"); // FIXME: Should reject these. The ARM backend hits this with $lane in a // bunch of instructions. It is unclear what the right answer is. DEBUG({ errs() << "warning: '" << TheDef->getName() << "': " << "ignoring instruction with tied operand '" - << Tok.str() << "'\n"; + << Tok << "'\n"; }); return false; } @@ -1288,7 +1278,7 @@ void AsmMatcherInfo::buildOperandMatchInfo() { /// Map containing a mask with all operands indices that can be found for /// that class inside a instruction. - typedef std::map<ClassInfo*, unsigned, LessClassInfoPtr> OpClassMaskTy; + typedef std::map<ClassInfo *, unsigned, less_ptr<ClassInfo>> OpClassMaskTy; OpClassMaskTy OpClassMask; for (std::vector<MatchableInfo*>::const_iterator it = @@ -1359,7 +1349,7 @@ void AsmMatcherInfo::buildInfo() { if (CGI.TheDef->getValueAsBit("isCodeGenOnly")) continue; - OwningPtr<MatchableInfo> II(new MatchableInfo(CGI)); + std::unique_ptr<MatchableInfo> II(new MatchableInfo(CGI)); II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); @@ -1375,7 +1365,7 @@ void AsmMatcherInfo::buildInfo() { StringRef(II->TheDef->getName()).endswith("_Int")) continue; - Matchables.push_back(II.take()); + Matchables.push_back(II.release()); } // Parse all of the InstAlias definitions and stick them in the list of @@ -1392,14 +1382,14 @@ void AsmMatcherInfo::buildInfo() { .startswith( MatchPrefix)) continue; - OwningPtr<MatchableInfo> II(new MatchableInfo(Alias)); + std::unique_ptr<MatchableInfo> II(new MatchableInfo(Alias)); II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); // Validate the alias definitions. II->validate(CommentDelimiter, false); - Matchables.push_back(II.take()); + Matchables.push_back(II.release()); } } @@ -1464,13 +1454,13 @@ void AsmMatcherInfo::buildInfo() { II->TheDef->getValueAsString("TwoOperandAliasConstraint"); if (Constraint != "") { // Start by making a copy of the original matchable. - OwningPtr<MatchableInfo> AliasII(new MatchableInfo(*II)); + std::unique_ptr<MatchableInfo> AliasII(new MatchableInfo(*II)); // Adjust it to be a two-operand alias. AliasII->formTwoOperandAlias(Constraint); // Add the alias to the matchables list. - NewMatchables.push_back(AliasII.take()); + NewMatchables.push_back(AliasII.release()); } } else II->buildAliasResultOperands(); @@ -1510,8 +1500,8 @@ buildInstructionOperandReference(MatchableInfo *II, // Map this token to an operand. unsigned Idx; if (!Operands.hasOperandNamed(OperandName, Idx)) - PrintFatalError(II->TheDef->getLoc(), "error: unable to find operand: '" + - OperandName.str() + "'"); + PrintFatalError(II->TheDef->getLoc(), + "error: unable to find operand: '" + OperandName + "'"); // If the instruction operand has multiple suboperands, but the parser // match class for the asm operand is still the default "ImmAsmOperand", @@ -1583,8 +1573,8 @@ void AsmMatcherInfo::buildAliasOperandReference(MatchableInfo *II, return; } - PrintFatalError(II->TheDef->getLoc(), "error: unable to find operand: '" + - OperandName.str() + "'"); + PrintFatalError(II->TheDef->getLoc(), + "error: unable to find operand: '" + OperandName + "'"); } void MatchableInfo::buildInstructionResultOperands() { @@ -2691,8 +2681,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << " const SmallVectorImpl<MCParsedAsmOperand*> " << "&Operands);\n"; OS << " void convertToMapAndConstraints(unsigned Kind,\n "; - OS << " const SmallVectorImpl<MCParsedAsmOperand*> &Operands);\n"; - OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);\n"; + OS << " const SmallVectorImpl<MCParsedAsmOperand*> &Operands) override;\n"; + OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) override;\n"; OS << " unsigned MatchInstructionImpl(\n"; OS.indent(27); OS << "const SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n" diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index a18b6b5..f9e1990 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -34,7 +34,7 @@ class AsmWriterEmitter { RecordKeeper &Records; CodeGenTarget Target; std::map<const CodeGenInstruction*, AsmWriterInst*> CGIAWIMap; - std::vector<const CodeGenInstruction*> NumberedInstructions; + const std::vector<const CodeGenInstruction*> *NumberedInstructions; std::vector<AsmWriterInst> Instructions; public: AsmWriterEmitter(RecordKeeper &R); @@ -47,9 +47,9 @@ private: void EmitPrintAliasInstruction(raw_ostream &O); AsmWriterInst *getAsmWriterInstByID(unsigned ID) const { - assert(ID < NumberedInstructions.size()); + assert(ID < NumberedInstructions->size()); std::map<const CodeGenInstruction*, AsmWriterInst*>::const_iterator I = - CGIAWIMap.find(NumberedInstructions[ID]); + CGIAWIMap.find(NumberedInstructions->at(ID)); assert(I != CGIAWIMap.end() && "Didn't find inst!"); return I->second; } @@ -141,7 +141,7 @@ void AsmWriterEmitter:: FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands, std::vector<unsigned> &InstIdxs, std::vector<unsigned> &InstOpsUsed) const { - InstIdxs.assign(NumberedInstructions.size(), ~0U); + InstIdxs.assign(NumberedInstructions->size(), ~0U); // This vector parallels UniqueOperandCommands, keeping track of which // instructions each case are used for. It is a comma separated string of @@ -150,9 +150,10 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands, InstrsForCase.resize(UniqueOperandCommands.size()); InstOpsUsed.assign(UniqueOperandCommands.size(), 0); - for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { + for (unsigned i = 0, e = NumberedInstructions->size(); i != e; ++i) { const AsmWriterInst *Inst = getAsmWriterInstByID(i); - if (Inst == 0) continue; // PHI, INLINEASM, PROLOG_LABEL, etc. + if (Inst == 0) + continue; // PHI, INLINEASM, CFI_INSTRUCTION, etc. std::string Command; if (Inst->Operands.empty()) @@ -280,15 +281,12 @@ static void UnescapeString(std::string &Str) { void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { Record *AsmWriter = Target.getAsmWriter(); std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); - bool isMC = AsmWriter->getValueAsBit("isMCAsmWriter"); - const char *MachineInstrClassName = isMC ? "MCInst" : "MachineInstr"; O << "/// printInstruction - This method is automatically generated by tablegen\n" "/// from the instruction set description.\n" "void " << Target.getName() << ClassName - << "::printInstruction(const " << MachineInstrClassName - << " *MI, raw_ostream &O) {\n"; + << "::printInstruction(const MCInst *MI, raw_ostream &O) {\n"; // Build an aggregate string, and build a table of offsets into it. SequenceToOffsetTable<std::string> StringTable; @@ -301,8 +299,8 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { // Add all strings to the string table upfront so it can generate an optimized // representation. - for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { - AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]]; + for (unsigned i = 0, e = NumberedInstructions->size(); i != e; ++i) { + AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions->at(i)]; if (AWI != 0 && AWI->Operands[0].OperandType == AsmWriterOperand::isLiteralTextOperand && @@ -316,8 +314,8 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { StringTable.layout(); unsigned MaxStringIdx = 0; - for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { - AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]]; + for (unsigned i = 0, e = NumberedInstructions->size(); i != e; ++i) { + AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions->at(i)]; unsigned Idx; if (AWI == 0) { // Something not handled by the asmwriter printer. @@ -379,7 +377,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { BitsLeft -= NumBits; // Remove the info about this operand. - for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { + for (unsigned i = 0, e = NumberedInstructions->size(); i != e; ++i) { if (AsmWriterInst *Inst = getAsmWriterInstByID(i)) if (!Inst->Operands.empty()) { unsigned NumOps = NumInstOpsHandled[InstIdxs[i]]; @@ -398,9 +396,9 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { // We always emit at least one 32-bit table. A second table is emitted if // more bits are needed. O<<" static const uint32_t OpInfo[] = {\n"; - for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { + for (unsigned i = 0, e = NumberedInstructions->size(); i != e; ++i) { O << " " << (OpcodeInfo[i] & 0xffffffff) << "U,\t// " - << NumberedInstructions[i]->TheDef->getName() << "\n"; + << NumberedInstructions->at(i)->TheDef->getName() << "\n"; } // Add a dummy entry so the array init doesn't end with a comma. O << " 0U\n"; @@ -412,9 +410,9 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { O << " static const uint" << ((BitsLeft < 16) ? "32" : (BitsLeft < 24) ? "16" : "8") << "_t OpInfo2[] = {\n"; - for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { + for (unsigned i = 0, e = NumberedInstructions->size(); i != e; ++i) { O << " " << (OpcodeInfo[i] >> 32) << "U,\t// " - << NumberedInstructions[i]->TheDef->getName() << "\n"; + << NumberedInstructions->at(i)->TheDef->getName() << "\n"; } // Add a dummy entry so the array init doesn't end with a comma. O << " 0U\n"; @@ -549,8 +547,8 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName, Reg.TheDef->getValueAsListOfStrings("AltNames"); if (AltNames.size() <= Idx) PrintFatalError(Reg.TheDef->getLoc(), - (Twine("Register definition missing alt name for '") + - AltName + "'.").str()); + "Register definition missing alt name for '" + + AltName + "'."); AsmName = AltNames[Idx]; } } @@ -605,8 +603,8 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) { << " switch(AltIdx) {\n" << " default: llvm_unreachable(\"Invalid register alt name index!\");\n"; for (unsigned i = 0, e = AltNameIndices.size(); i < e; ++i) { - StringRef Namespace = AltNameIndices[1]->getValueAsString("Namespace"); - StringRef AltName(AltNameIndices[i]->getName()); + std::string Namespace = AltNameIndices[1]->getValueAsString("Namespace"); + std::string AltName(AltNameIndices[i]->getName()); O << " case " << Namespace << "::" << AltName << ":\n" << " AsmStrs = AsmStrs" << AltName << ";\n" @@ -764,9 +762,6 @@ static unsigned CountResultNumOperands(StringRef AsmString) { void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { Record *AsmWriter = Target.getAsmWriter(); - if (!AsmWriter->getValueAsBit("isMCAsmWriter")) - return; - O << "\n#ifdef PRINT_ALIAS_INSTR\n"; O << "#undef PRINT_ALIAS_INSTR\n\n"; @@ -987,11 +982,10 @@ AsmWriterEmitter::AsmWriterEmitter(RecordKeeper &R) : Records(R), Target(R) { if (!(*I)->AsmString.empty() && (*I)->TheDef->getName() != "PHI") Instructions.push_back( AsmWriterInst(**I, AsmWriter->getValueAsInt("Variant"), - AsmWriter->getValueAsInt("FirstOperandColumn"), AsmWriter->getValueAsInt("OperandSpacing"))); // Get the instruction numbering. - NumberedInstructions = Target.getInstructionsByEnumValue(); + NumberedInstructions = &Target.getInstructionsByEnumValue(); // Compute the CodeGenInstruction -> AsmWriterInst mapping. Note that not // all machine instructions are necessarily being printed, so there may be diff --git a/utils/TableGen/AsmWriterInst.cpp b/utils/TableGen/AsmWriterInst.cpp index 1c2004f..5d9ead1 100644 --- a/utils/TableGen/AsmWriterInst.cpp +++ b/utils/TableGen/AsmWriterInst.cpp @@ -50,14 +50,9 @@ std::string AsmWriterOperand::getCode() const { /// AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant, - int FirstOperandColumn, int OperandSpacing) { this->CGI = &CGI; - // This is the number of tabs we've seen if we're doing columnar layout. - unsigned CurColumn = 0; - - // NOTE: Any extensions to this code need to be mirrored in the // AsmPrinter::printInlineAsm code that executes as compile time (assuming // that inline asm strings should also get the new feature)! @@ -76,20 +71,7 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, AddLiteralString("\\n"); break; case '\t': - // If the asm writer is not using a columnar layout, \t is not - // magic. - if (FirstOperandColumn == -1 || OperandSpacing == -1) { - AddLiteralString("\\t"); - } else { - // We recognize a tab as an operand delimeter. - unsigned DestColumn = FirstOperandColumn + - CurColumn++ * OperandSpacing; - Operands.push_back( - AsmWriterOperand( - "O.PadToColumn(" + - utostr(DestColumn) + ");\n", - AsmWriterOperand::isLiteralStatementOperand)); - } + AddLiteralString("\\t"); break; case '"': AddLiteralString("\\\""); @@ -106,20 +88,7 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, if (AsmString[DollarPos+1] == 'n') { AddLiteralString("\\n"); } else if (AsmString[DollarPos+1] == 't') { - // If the asm writer is not using a columnar layout, \t is not - // magic. - if (FirstOperandColumn == -1 || OperandSpacing == -1) { - AddLiteralString("\\t"); - break; - } - - // We recognize a tab as an operand delimeter. - unsigned DestColumn = FirstOperandColumn + - CurColumn++ * OperandSpacing; - Operands.push_back( - AsmWriterOperand("O.PadToColumn(" + utostr(DestColumn) + ");\n", - AsmWriterOperand::isLiteralStatementOperand)); - break; + AddLiteralString("\\t"); } else if (std::string("${|}\\").find(AsmString[DollarPos+1]) != std::string::npos) { AddLiteralString(std::string(1, AsmString[DollarPos+1])); diff --git a/utils/TableGen/AsmWriterInst.h b/utils/TableGen/AsmWriterInst.h index ec7d8eb..4cee352 100644 --- a/utils/TableGen/AsmWriterInst.h +++ b/utils/TableGen/AsmWriterInst.h @@ -89,7 +89,6 @@ namespace llvm { AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant, - int FirstOperandColumn, int OperandSpacing); /// MatchesAllButOneOp - If this instruction is exactly identical to the diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt index 3ee1974..f277608 100644 --- a/utils/TableGen/CMakeLists.txt +++ b/utils/TableGen/CMakeLists.txt @@ -28,7 +28,6 @@ add_tablegen(llvm-tblgen LLVM RegisterInfoEmitter.cpp SetTheory.cpp SubtargetEmitter.cpp - TGValueTypes.cpp TableGen.cpp X86DisassemblerTables.cpp X86ModRMFilters.cpp diff --git a/utils/TableGen/CTagsEmitter.cpp b/utils/TableGen/CTagsEmitter.cpp index 8bf7778..1d240fa 100644 --- a/utils/TableGen/CTagsEmitter.cpp +++ b/utils/TableGen/CTagsEmitter.cpp @@ -19,7 +19,6 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" -#include "llvm/TableGen/TableGenBackend.h" #include <algorithm> #include <string> #include <vector> diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp index 94f3c65..96bd336 100644 --- a/utils/TableGen/CallingConvEmitter.cpp +++ b/utils/TableGen/CallingConvEmitter.cpp @@ -185,21 +185,48 @@ void CallingConvEmitter::EmitAction(Record *Action, else O << "\n" << IndentStr << " State.getTarget().getDataLayout()" "->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()))"; - if (Action->isSubClassOf("CCAssignToStackWithShadow")) - O << ", " << getQualifiedName(Action->getValueAsDef("ShadowReg")); O << ");\n" << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset" << Counter << ", LocVT, LocInfo));\n"; O << IndentStr << "return false;\n"; + } else if (Action->isSubClassOf("CCAssignToStackWithShadow")) { + int Size = Action->getValueAsInt("Size"); + int Align = Action->getValueAsInt("Align"); + ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList"); + + unsigned ShadowRegListNumber = ++Counter; + + O << IndentStr << "static const uint16_t ShadowRegList" + << ShadowRegListNumber << "[] = {\n"; + O << IndentStr << " "; + for (unsigned i = 0, e = ShadowRegList->getSize(); i != e; ++i) { + if (i != 0) O << ", "; + O << getQualifiedName(ShadowRegList->getElementAsRecord(i)); + } + O << "\n" << IndentStr << "};\n"; + + O << IndentStr << "unsigned Offset" << ++Counter + << " = State.AllocateStack(" + << Size << ", " << Align << ", " + << "ShadowRegList" << ShadowRegListNumber << ", " + << ShadowRegList->getSize() << ");\n"; + O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset" + << Counter << ", LocVT, LocInfo));\n"; + O << IndentStr << "return false;\n"; } else if (Action->isSubClassOf("CCPromoteToType")) { Record *DestTy = Action->getValueAsDef("DestTy"); - O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; - O << IndentStr << "if (ArgFlags.isSExt())\n" - << IndentStr << IndentStr << "LocInfo = CCValAssign::SExt;\n" - << IndentStr << "else if (ArgFlags.isZExt())\n" - << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExt;\n" - << IndentStr << "else\n" - << IndentStr << IndentStr << "LocInfo = CCValAssign::AExt;\n"; + MVT::SimpleValueType DestVT = getValueType(DestTy); + O << IndentStr << "LocVT = " << getEnumName(DestVT) <<";\n"; + if (MVT(DestVT).isFloatingPoint()) { + O << IndentStr << "LocInfo = CCValAssign::FPExt;\n"; + } else { + O << IndentStr << "if (ArgFlags.isSExt())\n" + << IndentStr << IndentStr << "LocInfo = CCValAssign::SExt;\n" + << IndentStr << "else if (ArgFlags.isZExt())\n" + << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExt;\n" + << IndentStr << "else\n" + << IndentStr << IndentStr << "LocInfo = CCValAssign::AExt;\n"; + } } else if (Action->isSubClassOf("CCBitConvertToType")) { Record *DestTy = Action->getValueAsDef("DestTy"); O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n"; diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index e99a171..4d0c0ca 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -41,52 +41,16 @@ public: void run(raw_ostream &o); private: - void emitMachineOpEmitter(raw_ostream &o, const std::string &Namespace); - void emitGetValueBit(raw_ostream &o, const std::string &Namespace); - void reverseBits(std::vector<Record*> &Insts); int getVariableBit(const std::string &VarName, BitsInit *BI, int bit); std::string getInstructionCase(Record *R, CodeGenTarget &Target); void AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, unsigned &NumberedOp, + std::set<unsigned> &NamedOpIndices, std::string &Case, CodeGenTarget &Target); }; -void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) { - for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end(); - I != E; ++I) { - Record *R = *I; - if (R->getValueAsString("Namespace") == "TargetOpcode" || - R->getValueAsBit("isPseudo")) - continue; - - BitsInit *BI = R->getValueAsBitsInit("Inst"); - - unsigned numBits = BI->getNumBits(); - - SmallVector<Init *, 16> NewBits(numBits); - - for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) { - unsigned bitSwapIdx = numBits - bit - 1; - Init *OrigBit = BI->getBit(bit); - Init *BitSwap = BI->getBit(bitSwapIdx); - NewBits[bit] = BitSwap; - NewBits[bitSwapIdx] = OrigBit; - } - if (numBits % 2) { - unsigned middle = (numBits + 1) / 2; - NewBits[middle] = BI->getBit(middle); - } - - BitsInit *NewBI = BitsInit::get(NewBits); - - // Update the bits in reversed order so that emitInstrOpBits will get the - // correct endianness. - R->getValue("Inst")->setValue(NewBI); - } -} - // If the VarBitInit at position 'bit' matches the specified variable then // return the variable bit position. Otherwise return -1. int CodeEmitterGen::getVariableBit(const std::string &VarName, @@ -106,6 +70,7 @@ int CodeEmitterGen::getVariableBit(const std::string &VarName, void CodeEmitterGen:: AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, unsigned &NumberedOp, + std::set<unsigned> &NamedOpIndices, std::string &Case, CodeGenTarget &Target) { CodeGenInstruction &CGI = Target.getInstruction(R); @@ -138,9 +103,22 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, /// If this operand is not supposed to be emitted by the /// generated emitter, skip it. while (NumberedOp < NumberOps && - CGI.Operands.isFlatOperandNotEmitted(NumberedOp)) + (CGI.Operands.isFlatOperandNotEmitted(NumberedOp) || + (NamedOpIndices.size() && NamedOpIndices.count( + CGI.Operands.getSubOperandNumber(NumberedOp).first)))) { ++NumberedOp; + if (NumberedOp >= CGI.Operands.back().MIOperandNo + + CGI.Operands.back().MINumOperands) { + errs() << "Too few operands in record " << R->getName() << + " (no match for variable " << VarName << "):\n"; + errs() << *R; + errs() << '\n'; + + return; + } + } + OpIdx = NumberedOp++; } @@ -157,14 +135,14 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, Case += " // op: " + VarName + "\n" + " op = " + EncoderMethodName + "(MI, " + utostr(OpIdx); if (MCEmitter) - Case += ", Fixups"; + Case += ", Fixups, STI"; Case += ");\n"; } } else { Case += " // op: " + VarName + "\n" + " op = getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")"; if (MCEmitter) - Case += ", Fixups"; + Case += ", Fixups, STI"; Case += ");\n"; } @@ -215,6 +193,21 @@ std::string CodeEmitterGen::getInstructionCase(Record *R, const std::vector<RecordVal> &Vals = R->getValues(); unsigned NumberedOp = 0; + std::set<unsigned> NamedOpIndices; + // Collect the set of operand indices that might correspond to named + // operand, and skip these when assigning operands based on position. + if (Target.getInstructionSet()-> + getValueAsBit("noNamedPositionallyEncodedOperands")) { + CodeGenInstruction &CGI = Target.getInstruction(R); + for (unsigned i = 0, e = Vals.size(); i != e; ++i) { + unsigned OpIdx; + if (!CGI.Operands.hasOperandNamed(Vals[i].getName(), OpIdx)) + continue; + + NamedOpIndices.insert(OpIdx); + } + } + // Loop over all of the fields in the instruction, determining which are the // operands to the instruction. for (unsigned i = 0, e = Vals.size(); i != e; ++i) { @@ -223,12 +216,17 @@ std::string CodeEmitterGen::getInstructionCase(Record *R, if (Vals[i].getPrefix() || Vals[i].getValue()->isComplete()) continue; - AddCodeToMergeInOperand(R, BI, Vals[i].getName(), NumberedOp, Case, Target); + AddCodeToMergeInOperand(R, BI, Vals[i].getName(), NumberedOp, + NamedOpIndices, Case, Target); } std::string PostEmitter = R->getValueAsString("PostEncoderMethod"); - if (!PostEmitter.empty()) - Case += " Value = " + PostEmitter + "(MI, Value);\n"; + if (!PostEmitter.empty()) { + Case += " Value = " + PostEmitter + "(MI, Value"; + if (MCEmitter) + Case += ", STI"; + Case += ");\n"; + } return Case; } @@ -238,8 +236,7 @@ void CodeEmitterGen::run(raw_ostream &o) { std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); // For little-endian instruction bit encodings, reverse the bit order - if (Target.isLittleEndianEncoding()) reverseBits(Insts); - + Target.reverseBitsForLittleEndianEncoding(); const std::vector<const CodeGenInstruction*> &NumberedInstructions = Target.getInstructionsByEnumValue(); @@ -248,7 +245,8 @@ void CodeEmitterGen::run(raw_ostream &o) { o << "uint64_t " << Target.getName(); if (MCEmitter) o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n" - << " SmallVectorImpl<MCFixup> &Fixups) const {\n"; + << " SmallVectorImpl<MCFixup> &Fixups,\n" + << " const MCSubtargetInfo &STI) const {\n"; else o << "CodeEmitter::getBinaryCodeForInstr(const MachineInstr &MI) const {\n"; @@ -287,14 +285,11 @@ void CodeEmitterGen::run(raw_ostream &o) { IC != EC; ++IC) { Record *R = *IC; if (R->getValueAsString("Namespace") == "TargetOpcode" || - (R->getValueAsBit("isPseudo") && MCEmitter)) + R->getValueAsBit("isPseudo")) continue; const std::string &InstName = R->getValueAsString("Namespace") + "::" + R->getName(); - std::string Case; - if (!R->getValueAsBit("isPseudo")) { - Case = getInstructionCase(R, Target); - } + std::string Case = getInstructionCase(R, Target); CaseMap[Case].push_back(InstName); } diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 717090a..0af7e3d 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -120,6 +120,14 @@ bool EEVT::TypeSet::hasFloatingPointTypes() const { return false; } +/// hasScalarTypes - Return true if this TypeSet contains a scalar value type. +bool EEVT::TypeSet::hasScalarTypes() const { + for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) + if (isScalar(TypeVec[i])) + return true; + return false; +} + /// hasVectorTypes - Return true if this TypeSet contains a vAny or a vector /// value type. bool EEVT::TypeSet::hasVectorTypes() const { @@ -339,8 +347,9 @@ bool EEVT::TypeSet::EnforceVector(TreePattern &TP) { -/// EnforceSmallerThan - 'this' must be a smaller VT than Other. Update -/// this an other based on this information. +/// EnforceSmallerThan - 'this' must be a smaller VT than Other. For vectors +/// this shoud be based on the element type. Update this and other based on +/// this information. bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { if (TP.hasError()) return false; @@ -371,159 +380,100 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) { // If one contains vectors but the other doesn't pull vectors out. if (!hasVectorTypes()) MadeChange |= Other.EnforceScalar(TP); - if (!hasVectorTypes()) + else if (!hasScalarTypes()) + MadeChange |= Other.EnforceVector(TP); + if (!Other.hasVectorTypes()) MadeChange |= EnforceScalar(TP); + else if (!Other.hasScalarTypes()) + MadeChange |= EnforceVector(TP); - if (TypeVec.size() == 1 && Other.TypeVec.size() == 1) { - // If we are down to concrete types, this code does not currently - // handle nodes which have multiple types, where some types are - // integer, and some are fp. Assert that this is not the case. - assert(!(hasIntegerTypes() && hasFloatingPointTypes()) && - !(Other.hasIntegerTypes() && Other.hasFloatingPointTypes()) && - "SDTCisOpSmallerThanOp does not handle mixed int/fp types!"); - - // Otherwise, if these are both vector types, either this vector - // must have a larger bitsize than the other, or this element type - // must be larger than the other. - MVT Type(TypeVec[0]); - MVT OtherType(Other.TypeVec[0]); - - if (hasVectorTypes() && Other.hasVectorTypes()) { - if (Type.getSizeInBits() >= OtherType.getSizeInBits()) - if (Type.getVectorElementType().getSizeInBits() - >= OtherType.getVectorElementType().getSizeInBits()) { - TP.error("Type inference contradiction found, '" + - getName() + "' element type not smaller than '" + - Other.getName() +"'!"); - return false; - } - } else - // For scalar types, the bitsize of this type must be larger - // than that of the other. - if (Type.getSizeInBits() >= OtherType.getSizeInBits()) { - TP.error("Type inference contradiction found, '" + - getName() + "' is not smaller than '" + - Other.getName() +"'!"); - return false; - } - } - - - // Handle int and fp as disjoint sets. This won't work for patterns - // that have mixed fp/int types but those are likely rare and would - // not have been accepted by this code previously. + // For vectors we need to ensure that smaller size doesn't produce larger + // vector and vice versa. + if (isConcrete() && isVector(getConcrete())) { + MVT IVT = getConcrete(); + unsigned Size = IVT.getSizeInBits(); - // Okay, find the smallest type from the current set and remove it from the - // largest set. - MVT::SimpleValueType SmallestInt = MVT::LAST_VALUETYPE; - for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) - if (isInteger(TypeVec[i])) { - SmallestInt = TypeVec[i]; - break; - } - for (unsigned i = 1, e = TypeVec.size(); i != e; ++i) - if (isInteger(TypeVec[i]) && TypeVec[i] < SmallestInt) - SmallestInt = TypeVec[i]; + // Only keep types that have at least as many bits. + TypeSet InputSet(Other); - MVT::SimpleValueType SmallestFP = MVT::LAST_VALUETYPE; - for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) - if (isFloatingPoint(TypeVec[i])) { - SmallestFP = TypeVec[i]; - break; - } - for (unsigned i = 1, e = TypeVec.size(); i != e; ++i) - if (isFloatingPoint(TypeVec[i]) && TypeVec[i] < SmallestFP) - SmallestFP = TypeVec[i]; - - int OtherIntSize = 0; - int OtherFPSize = 0; - for (SmallVectorImpl<MVT::SimpleValueType>::iterator TVI = - Other.TypeVec.begin(); - TVI != Other.TypeVec.end(); - /* NULL */) { - if (isInteger(*TVI)) { - ++OtherIntSize; - if (*TVI == SmallestInt) { - TVI = Other.TypeVec.erase(TVI); - --OtherIntSize; + for (unsigned i = 0; i != Other.TypeVec.size(); ++i) { + assert(isVector(Other.TypeVec[i]) && "EnforceVector didn't work"); + if (MVT(Other.TypeVec[i]).getSizeInBits() < Size) { + Other.TypeVec.erase(Other.TypeVec.begin()+i--); MadeChange = true; - continue; } - } else if (isFloatingPoint(*TVI)) { - ++OtherFPSize; - if (*TVI == SmallestFP) { - TVI = Other.TypeVec.erase(TVI); - --OtherFPSize; + } + + if (Other.TypeVec.empty()) { // FIXME: Really want an SMLoc here! + TP.error("Type inference contradiction found, forcing '" + + InputSet.getName() + "' to have at least as many bits as " + + getName() + "'"); + return false; + } + } else if (Other.isConcrete() && isVector(Other.getConcrete())) { + MVT IVT = Other.getConcrete(); + unsigned Size = IVT.getSizeInBits(); + + // Only keep types with the same or fewer total bits + TypeSet InputSet(*this); + + for (unsigned i = 0; i != TypeVec.size(); ++i) { + assert(isVector(TypeVec[i]) && "EnforceVector didn't work"); + if (MVT(TypeVec[i]).getSizeInBits() > Size) { + TypeVec.erase(TypeVec.begin()+i--); MadeChange = true; - continue; } } - ++TVI; + + if (TypeVec.empty()) { // FIXME: Really want an SMLoc here! + TP.error("Type inference contradiction found, forcing '" + + InputSet.getName() + "' to have the same or fewer bits than " + + Other.getName() + "'"); + return false; + } } - // If this is the only type in the large set, the constraint can never be - // satisfied. - if ((Other.hasIntegerTypes() && OtherIntSize == 0) || - (Other.hasFloatingPointTypes() && OtherFPSize == 0)) { - TP.error("Type inference contradiction found, '" + - Other.getName() + "' has nothing larger than '" + getName() +"'!"); + // This code does not currently handle nodes which have multiple types, + // where some types are integer, and some are fp. Assert that this is not + // the case. + assert(!(hasIntegerTypes() && hasFloatingPointTypes()) && + !(Other.hasIntegerTypes() && Other.hasFloatingPointTypes()) && + "SDTCisOpSmallerThanOp does not handle mixed int/fp types!"); + + if (TP.hasError()) return false; + + // Okay, find the smallest scalar type from the other set and remove + // anything the same or smaller from the current set. + TypeSet InputSet(Other); + MVT::SimpleValueType Smallest = TypeVec[0]; + for (unsigned i = 0; i != Other.TypeVec.size(); ++i) { + if (Other.TypeVec[i] <= Smallest) { + Other.TypeVec.erase(Other.TypeVec.begin()+i--); + MadeChange = true; + } } - // Okay, find the largest type in the Other set and remove it from the - // current set. - MVT::SimpleValueType LargestInt = MVT::Other; - for (unsigned i = 0, e = Other.TypeVec.size(); i != e; ++i) - if (isInteger(Other.TypeVec[i])) { - LargestInt = Other.TypeVec[i]; - break; - } - for (unsigned i = 1, e = Other.TypeVec.size(); i != e; ++i) - if (isInteger(Other.TypeVec[i]) && Other.TypeVec[i] > LargestInt) - LargestInt = Other.TypeVec[i]; - - MVT::SimpleValueType LargestFP = MVT::Other; - for (unsigned i = 0, e = Other.TypeVec.size(); i != e; ++i) - if (isFloatingPoint(Other.TypeVec[i])) { - LargestFP = Other.TypeVec[i]; - break; - } - for (unsigned i = 1, e = Other.TypeVec.size(); i != e; ++i) - if (isFloatingPoint(Other.TypeVec[i]) && Other.TypeVec[i] > LargestFP) - LargestFP = Other.TypeVec[i]; - - int IntSize = 0; - int FPSize = 0; - for (SmallVectorImpl<MVT::SimpleValueType>::iterator TVI = - TypeVec.begin(); - TVI != TypeVec.end(); - /* NULL */) { - if (isInteger(*TVI)) { - ++IntSize; - if (*TVI == LargestInt) { - TVI = TypeVec.erase(TVI); - --IntSize; - MadeChange = true; - continue; - } - } else if (isFloatingPoint(*TVI)) { - ++FPSize; - if (*TVI == LargestFP) { - TVI = TypeVec.erase(TVI); - --FPSize; - MadeChange = true; - continue; - } + if (Other.TypeVec.empty()) { + TP.error("Type inference contradiction found, '" + InputSet.getName() + + "' has nothing larger than '" + getName() +"'!"); + return false; + } + + // Okay, find the largest scalar type from the other set and remove + // anything the same or larger from the current set. + InputSet = TypeSet(*this); + MVT::SimpleValueType Largest = Other.TypeVec[Other.TypeVec.size()-1]; + for (unsigned i = 0; i != TypeVec.size(); ++i) { + if (TypeVec[i] >= Largest) { + TypeVec.erase(TypeVec.begin()+i--); + MadeChange = true; } - ++TVI; } - // If this is the only type in the small set, the constraint can never be - // satisfied. - if ((hasIntegerTypes() && IntSize == 0) || - (hasFloatingPointTypes() && FPSize == 0)) { - TP.error("Type inference contradiction found, '" + - getName() + "' has nothing smaller than '" + Other.getName()+"'!"); + if (TypeVec.empty()) { + TP.error("Type inference contradiction found, '" + InputSet.getName() + + "' has nothing smaller than '" + Other.getName() +"'!"); return false; } @@ -580,27 +530,78 @@ bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand, /// vector type specified by VTOperand. bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand, TreePattern &TP) { + if (TP.hasError()) + return false; + // "This" must be a vector and "VTOperand" must be a vector. bool MadeChange = false; MadeChange |= EnforceVector(TP); MadeChange |= VTOperand.EnforceVector(TP); - // "This" must be larger than "VTOperand." - MadeChange |= VTOperand.EnforceSmallerThan(*this, TP); + // If one side is known to be integer or known to be FP but the other side has + // no information, get at least the type integrality info in there. + if (!hasFloatingPointTypes()) + MadeChange |= VTOperand.EnforceInteger(TP); + else if (!hasIntegerTypes()) + MadeChange |= VTOperand.EnforceFloatingPoint(TP); + if (!VTOperand.hasFloatingPointTypes()) + MadeChange |= EnforceInteger(TP); + else if (!VTOperand.hasIntegerTypes()) + MadeChange |= EnforceFloatingPoint(TP); + + assert(!isCompletelyUnknown() && !VTOperand.isCompletelyUnknown() && + "Should have a type list now"); // If we know the vector type, it forces the scalar types to agree. + // Also force one vector to have more elements than the other. if (isConcrete()) { MVT IVT = getConcrete(); + unsigned NumElems = IVT.getVectorNumElements(); IVT = IVT.getVectorElementType(); EEVT::TypeSet EltTypeSet(IVT.SimpleTy, TP); MadeChange |= VTOperand.EnforceVectorEltTypeIs(EltTypeSet, TP); + + // Only keep types that have less elements than VTOperand. + TypeSet InputSet(VTOperand); + + for (unsigned i = 0; i != VTOperand.TypeVec.size(); ++i) { + assert(isVector(VTOperand.TypeVec[i]) && "EnforceVector didn't work"); + if (MVT(VTOperand.TypeVec[i]).getVectorNumElements() >= NumElems) { + VTOperand.TypeVec.erase(VTOperand.TypeVec.begin()+i--); + MadeChange = true; + } + } + if (VTOperand.TypeVec.empty()) { // FIXME: Really want an SMLoc here! + TP.error("Type inference contradiction found, forcing '" + + InputSet.getName() + "' to have less vector elements than '" + + getName() + "'"); + return false; + } } else if (VTOperand.isConcrete()) { MVT IVT = VTOperand.getConcrete(); + unsigned NumElems = IVT.getVectorNumElements(); IVT = IVT.getVectorElementType(); EEVT::TypeSet EltTypeSet(IVT.SimpleTy, TP); MadeChange |= EnforceVectorEltTypeIs(EltTypeSet, TP); + + // Only keep types that have more elements than 'this'. + TypeSet InputSet(*this); + + for (unsigned i = 0; i != TypeVec.size(); ++i) { + assert(isVector(TypeVec[i]) && "EnforceVector didn't work"); + if (MVT(TypeVec[i]).getVectorNumElements() <= NumElems) { + TypeVec.erase(TypeVec.begin()+i--); + MadeChange = true; + } + } + if (TypeVec.empty()) { // FIXME: Really want an SMLoc here! + TP.error("Type inference contradiction found, forcing '" + + InputSet.getName() + "' to have more vector elements than '" + + VTOperand.getName() + "'"); + return false; + } } return MadeChange; @@ -1116,6 +1117,9 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { if (Operator->isSubClassOf("SDNodeXForm")) return 1; // FIXME: Generalize SDNodeXForm + if (Operator->isSubClassOf("ValueType")) + return 1; // A type-cast of one result. + Operator->dump(); errs() << "Unhandled node in GetNumNodeResults\n"; exit(1); @@ -1228,8 +1232,10 @@ SubstituteFormalArguments(std::map<std::string, TreePatternNode*> &ArgMap) { TreePatternNode *Child = getChild(i); if (Child->isLeaf()) { Init *Val = Child->getLeafValue(); - if (isa<DefInit>(Val) && - cast<DefInit>(Val)->getDef()->getName() == "node") { + // Note that, when substituting into an output pattern, Val might be an + // UnsetInit. + if (isa<UnsetInit>(Val) || (isa<DefInit>(Val) && + cast<DefInit>(Val)->getDef()->getName() == "node")) { // We found a use of a formal argument, replace it with its value. TreePatternNode *NewChild = ArgMap[Child->getName()]; assert(NewChild && "Couldn't find formal argument!"); @@ -2131,6 +2137,7 @@ CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : ParsePatternFragments(); ParseDefaultOperands(); ParseInstructions(); + ParsePatternFragments(/*OutFrags*/true); ParsePatterns(); // Generate variants. For example, commutative patterns can match @@ -2204,13 +2211,18 @@ void CodeGenDAGPatterns::ParseComplexPatterns() { /// inline fragments together as necessary, so that there are no references left /// inside a pattern fragment to a pattern fragment. /// -void CodeGenDAGPatterns::ParsePatternFragments() { +void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) { std::vector<Record*> Fragments = Records.getAllDerivedDefinitions("PatFrag"); // First step, parse all of the fragments. for (unsigned i = 0, e = Fragments.size(); i != e; ++i) { + if (OutFrags != Fragments[i]->isSubClassOf("OutPatFrag")) + continue; + DagInit *Tree = Fragments[i]->getValueAsDag("Fragment"); - TreePattern *P = new TreePattern(Fragments[i], Tree, true, *this); + TreePattern *P = + new TreePattern(Fragments[i], Tree, + !Fragments[i]->isSubClassOf("OutPatFrag"), *this); PatternFragments[Fragments[i]] = P; // Validate the argument list, converting it to set, to discard duplicates. @@ -2266,6 +2278,9 @@ void CodeGenDAGPatterns::ParsePatternFragments() { // Now that we've parsed all of the tree fragments, do a closure on them so // that there are not references to PatFrags left inside of them. for (unsigned i = 0, e = Fragments.size(); i != e; ++i) { + if (OutFrags != Fragments[i]->isSubClassOf("OutPatFrag")) + continue; + TreePattern *ThePat = PatternFragments[Fragments[i]]; ThePat->InlinePatternFragments(); @@ -2312,8 +2327,9 @@ void CodeGenDAGPatterns::ParseDefaultOperands() { /* Resolve all types */; if (TPN->ContainsUnresolvedType()) { - PrintFatalError("Value #" + utostr(i) + " of OperandWithDefaultOps '" + - DefaultOps[i]->getName() +"' doesn't have a concrete type!"); + PrintFatalError("Value #" + Twine(i) + " of OperandWithDefaultOps '" + + DefaultOps[i]->getName() + + "' doesn't have a concrete type!"); } DefaultOpInfo.DefaultOps.push_back(TPN); } diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index 6fbdd4f..d995329 100644 --- a/utils/TableGen/CodeGenDAGPatterns.h +++ b/utils/TableGen/CodeGenDAGPatterns.h @@ -96,6 +96,10 @@ namespace EEVT { /// a floating point value type. bool hasFloatingPointTypes() const; + /// hasScalarTypes - Return true if this TypeSet contains a scalar value + /// type. + bool hasScalarTypes() const; + /// hasVectorTypes - Return true if this TypeSet contains a vector value /// type. bool hasVectorTypes() const; @@ -805,7 +809,7 @@ private: void ParseNodeInfo(); void ParseNodeTransforms(); void ParseComplexPatterns(); - void ParsePatternFragments(); + void ParsePatternFragments(bool OutFrags = false); void ParseDefaultOperands(); void ParseInstructions(); void ParsePatterns(); diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 576388b..5eebb91 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -106,11 +106,11 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { // Check that the operand has a name and that it's unique. if (ArgName.empty()) - PrintFatalError("In instruction '" + R->getName() + "', operand #" + utostr(i) + - " has no name!"); + PrintFatalError("In instruction '" + R->getName() + "', operand #" + + Twine(i) + " has no name!"); if (!OperandNames.insert(ArgName).second) - PrintFatalError("In instruction '" + R->getName() + "', operand #" + utostr(i) + - " has the same name as a previous operand!"); + PrintFatalError("In instruction '" + R->getName() + "', operand #" + + Twine(i) + " has the same name as a previous operand!"); OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, EncoderMethod, OperandType, MIOperandNo, NumOps, @@ -133,8 +133,8 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { unsigned CGIOperandList::getOperandNamed(StringRef Name) const { unsigned OpIdx; if (hasOperandNamed(Name, OpIdx)) return OpIdx; - PrintFatalError("'" + TheDef->getName() + "' does not have an operand named '$" + - Name.str() + "'!"); + PrintFatalError("'" + TheDef->getName() + + "' does not have an operand named '$" + Name + "'!"); } /// hasOperandNamed - Query whether the instruction has an operand of the @@ -315,10 +315,13 @@ CodeGenInstruction::CodeGenInstruction(Record *R) hasCtrlDep = R->getValueAsBit("hasCtrlDep"); isNotDuplicable = R->getValueAsBit("isNotDuplicable"); - mayLoad = R->getValueAsBitOrUnset("mayLoad", mayLoad_Unset); - mayStore = R->getValueAsBitOrUnset("mayStore", mayStore_Unset); - hasSideEffects = R->getValueAsBitOrUnset("hasSideEffects", - hasSideEffects_Unset); + bool Unset; + mayLoad = R->getValueAsBitOrUnset("mayLoad", Unset); + mayLoad_Unset = Unset; + mayStore = R->getValueAsBitOrUnset("mayStore", Unset); + mayStore_Unset = Unset; + hasSideEffects = R->getValueAsBitOrUnset("hasSideEffects", Unset); + hasSideEffects_Unset = Unset; neverHasSideEffects = R->getValueAsBit("neverHasSideEffects"); isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove"); @@ -433,26 +436,33 @@ 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; if (ADI && ADI->getDef() == InstOpRec) { // If the operand is a record, it must have a name, and the record type // must match up with the instruction's argument type. if (Result->getArgName(AliasOpNo).empty()) - PrintFatalError(Loc, "result argument #" + utostr(AliasOpNo) + - " must have a name!"); - ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef()); + PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) + + " must have a name!"); + ResOp = ResultOperand(Result->getArgName(AliasOpNo), ResultRecord); return true; } // For register operands, the source register class can be a subclass // of the instruction register class, not just an exact match. + if (InstOpRec->isSubClassOf("RegisterOperand")) + InstOpRec = InstOpRec->getValueAsDef("RegClass"); + + if (ADI && ADI->getDef()->isSubClassOf("RegisterOperand")) + ADI = ADI->getDef()->getValueAsDef("RegClass")->getDefInit(); + if (ADI && ADI->getDef()->isSubClassOf("RegisterClass")) { if (!InstOpRec->isSubClassOf("RegisterClass")) return false; if (!T.getRegisterClass(InstOpRec) .hasSubClass(&T.getRegisterClass(ADI->getDef()))) return false; - ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef()); + ResOp = ResultOperand(Result->getArgName(AliasOpNo), ResultRecord); return true; } @@ -465,9 +475,6 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, InstOpRec = cast<DefInit>(DI->getArg(0))->getDef(); } - if (InstOpRec->isSubClassOf("RegisterOperand")) - InstOpRec = InstOpRec->getValueAsDef("RegClass"); - if (!InstOpRec->isSubClassOf("RegisterClass")) return false; @@ -481,7 +488,7 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, PrintFatalError(Loc, "result fixed register argument must " "not have a name!"); - ResOp = ResultOperand(ADI->getDef()); + ResOp = ResultOperand(ResultRecord); return true; } @@ -507,7 +514,7 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, return false; // Integer arguments can't have names. if (!Result->getArgName(AliasOpNo).empty()) - PrintFatalError(Loc, "result argument #" + utostr(AliasOpNo) + + PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) + " must not have a name!"); ResOp = ResultOperand(II->getValue()); return true; @@ -620,14 +627,14 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) { ResultInstOperandIndex.push_back(std::make_pair(i, SubOp)); ++AliasOpNo; } else { - PrintFatalError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + + PrintFatalError(R->getLoc(), "result argument #" + Twine(AliasOpNo) + " does not match instruction operand class " + (SubOp == 0 ? InstOpRec->getName() :SubRec->getName())); } } continue; } - PrintFatalError(R->getLoc(), "result argument #" + utostr(AliasOpNo) + + PrintFatalError(R->getLoc(), "result argument #" + Twine(AliasOpNo) + " does not match instruction operand class " + InstOpRec->getName()); } diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index 6004f66..00d89bf 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -15,7 +15,7 @@ #define CODEGEN_INSTRUCTION_H #include "llvm/ADT/StringRef.h" -#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/MachineValueType.h" #include "llvm/Support/SourceMgr.h" #include <string> #include <utility> @@ -215,38 +215,38 @@ namespace llvm { std::vector<Record*> ImplicitDefs, ImplicitUses; // Various boolean values we track for the instruction. - bool isReturn; - bool isBranch; - bool isIndirectBranch; - bool isCompare; - bool isMoveImm; - bool isBitcast; - bool isSelect; - bool isBarrier; - bool isCall; - bool canFoldAsLoad; - bool mayLoad; - bool mayLoad_Unset; - bool mayStore; - bool mayStore_Unset; - bool isPredicable; - bool isConvertibleToThreeAddress; - bool isCommutable; - bool isTerminator; - bool isReMaterializable; - bool hasDelaySlot; - bool usesCustomInserter; - bool hasPostISelHook; - bool hasCtrlDep; - bool isNotDuplicable; - bool hasSideEffects; - bool hasSideEffects_Unset; - bool neverHasSideEffects; - bool isAsCheapAsAMove; - bool hasExtraSrcRegAllocReq; - bool hasExtraDefRegAllocReq; - bool isCodeGenOnly; - bool isPseudo; + bool isReturn : 1; + bool isBranch : 1; + bool isIndirectBranch : 1; + bool isCompare : 1; + bool isMoveImm : 1; + bool isBitcast : 1; + bool isSelect : 1; + bool isBarrier : 1; + bool isCall : 1; + bool canFoldAsLoad : 1; + bool mayLoad : 1; + bool mayLoad_Unset : 1; + bool mayStore : 1; + bool mayStore_Unset : 1; + bool isPredicable : 1; + bool isConvertibleToThreeAddress : 1; + bool isCommutable : 1; + bool isTerminator : 1; + bool isReMaterializable : 1; + bool hasDelaySlot : 1; + bool usesCustomInserter : 1; + bool hasPostISelHook : 1; + bool hasCtrlDep : 1; + bool isNotDuplicable : 1; + bool hasSideEffects : 1; + bool hasSideEffects_Unset : 1; + bool neverHasSideEffects : 1; + bool isAsCheapAsAMove : 1; + bool hasExtraSrcRegAllocReq : 1; + bool hasExtraDefRegAllocReq : 1; + bool isCodeGenOnly : 1; + bool isPseudo : 1; std::string DeprecatedReason; bool HasComplexDeprecationPredicate; diff --git a/utils/TableGen/CodeGenIntrinsics.h b/utils/TableGen/CodeGenIntrinsics.h index ababfa4..06daa97 100644 --- a/utils/TableGen/CodeGenIntrinsics.h +++ b/utils/TableGen/CodeGenIntrinsics.h @@ -14,7 +14,7 @@ #ifndef CODEGEN_INTRINSIC_H #define CODEGEN_INTRINSIC_H -#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/MachineValueType.h" #include <string> #include <vector> @@ -73,6 +73,9 @@ namespace llvm { /// canThrow - True if the intrinsic can throw. bool canThrow; + /// isNoDuplicate - True if the intrinsic is marked as noduplicate. + bool isNoDuplicate; + /// isNoReturn - True if the intrinsic is no-return. bool isNoReturn; diff --git a/utils/TableGen/CodeGenMapTable.cpp b/utils/TableGen/CodeGenMapTable.cpp index cb7ec3e..b97126b 100644 --- a/utils/TableGen/CodeGenMapTable.cpp +++ b/utils/TableGen/CodeGenMapTable.cpp @@ -116,7 +116,7 @@ public: ColFields = MapRec->getValueAsListInit("ColFields"); // Values for the fields/attributes listed in 'ColFields'. - // Ex: KeyCol = 'noPred' -- key instruction is non predicated + // Ex: KeyCol = 'noPred' -- key instruction is non-predicated KeyCol = MapRec->getValueAsListInit("KeyCol"); // List of values for the fields/attributes listed in 'ColFields', one for @@ -384,7 +384,7 @@ unsigned MapTableEmitter::emitBinSearchTable(raw_ostream &OS) { OutStr += TargetName; OutStr += "::"; OutStr += ColInstrs[j]->getName(); - } else { OutStr += ", -1";} + } else { OutStr += ", (uint16_t)-1U";} } if (RelExists) { diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp index f2eef4f..e0e0b62 100644 --- a/utils/TableGen/CodeGenRegisters.cpp +++ b/utils/TableGen/CodeGenRegisters.cpp @@ -550,7 +550,7 @@ unsigned CodeGenRegister::getWeight(const CodeGenRegBank &RegBank) const { // registers. namespace { struct TupleExpander : SetTheory::Expander { - void expand(SetTheory &ST, Record *Def, SetTheory::RecSet &Elts) { + void expand(SetTheory &ST, Record *Def, SetTheory::RecSet &Elts) override { std::vector<Record*> Indices = Def->getValueAsListOfDefs("SubRegIndices"); unsigned Dim = Indices.size(); ListInit *SubRegs = Def->getValueAsListInit("SubRegs"); @@ -712,7 +712,7 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) unsigned Size = R->getValueAsInt("Size"); Namespace = R->getValueAsString("Namespace"); - SpillSize = Size ? Size : EVT(VTs[0]).getSizeInBits(); + SpillSize = Size ? Size : MVT(VTs[0]).getSizeInBits(); SpillAlignment = R->getValueAsInt("Alignment"); CopyCost = R->getValueAsInt("CopyCost"); Allocatable = R->getValueAsBit("isAllocatable"); @@ -782,11 +782,8 @@ namespace llvm { bool CodeGenRegisterClass::Key:: operator<(const CodeGenRegisterClass::Key &B) const { assert(Members && B.Members); - if (*Members != *B.Members) - return *Members < *B.Members; - if (SpillSize != B.SpillSize) - return SpillSize < B.SpillSize; - return SpillAlignment < B.SpillAlignment; + return std::tie(*Members, SpillSize, SpillAlignment) < + std::tie(*B.Members, B.SpillSize, B.SpillAlignment); } // Returns true if RC is a strict subclass. @@ -996,7 +993,7 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) { // Read in register class definitions. std::vector<Record*> RCs = Records.getAllDerivedDefinitions("RegisterClass"); if (RCs.empty()) - PrintFatalError(std::string("No 'RegisterClass' subclasses defined!")); + PrintFatalError("No 'RegisterClass' subclasses defined!"); // Allocate user-defined register classes. RegClasses.reserve(RCs.size()); @@ -1271,7 +1268,7 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets, assert(USetID && "register number 0 is invalid"); AllocatableRegs.insert((*Regs.begin())->EnumValue); - for (CodeGenRegister::Set::const_iterator I = llvm::next(Regs.begin()), + for (CodeGenRegister::Set::const_iterator I = std::next(Regs.begin()), E = Regs.end(); I != E; ++I) { AllocatableRegs.insert((*I)->EnumValue); UberSetIDs.join(USetID, (*I)->EnumValue); @@ -1311,7 +1308,7 @@ static void computeUberSets(std::vector<UberRegSet> &UberSets, static void computeUberWeights(std::vector<UberRegSet> &UberSets, CodeGenRegBank &RegBank) { // Skip the first unallocatable set. - for (std::vector<UberRegSet>::iterator I = llvm::next(UberSets.begin()), + for (std::vector<UberRegSet>::iterator I = std::next(UberSets.begin()), E = UberSets.end(); I != E; ++I) { // Initialize all unit weights in this set, and remember the max units/reg. @@ -1552,7 +1549,7 @@ void CodeGenRegBank::computeRegUnitSets() { // Find an existing RegUnitSet. std::vector<RegUnitSet>::const_iterator SetI = findRegUnitSet(RegUnitSets, RegUnitSets.back()); - if (SetI != llvm::prior(RegUnitSets.end())) + if (SetI != std::prev(RegUnitSets.end())) RegUnitSets.pop_back(); } @@ -1617,7 +1614,7 @@ void CodeGenRegBank::computeRegUnitSets() { // Find an existing RegUnitSet, or add the union to the unique sets. std::vector<RegUnitSet>::const_iterator SetI = findRegUnitSet(RegUnitSets, RegUnitSets.back()); - if (SetI != llvm::prior(RegUnitSets.end())) + if (SetI != std::prev(RegUnitSets.end())) RegUnitSets.pop_back(); else { DEBUG(dbgs() << "UnitSet " << RegUnitSets.size()-1 @@ -1705,16 +1702,6 @@ void CodeGenRegBank::computeRegUnitSets() { } } -struct LessUnits { - const CodeGenRegBank &RegBank; - LessUnits(const CodeGenRegBank &RB): RegBank(RB) {} - - bool operator()(unsigned ID1, unsigned ID2) { - return RegBank.getRegPressureSet(ID1).Units.size() - < RegBank.getRegPressureSet(ID2).Units.size(); - } -}; - void CodeGenRegBank::computeDerivedInfo() { computeComposites(); computeSubRegIndexLaneMasks(); @@ -1737,7 +1724,10 @@ void CodeGenRegBank::computeDerivedInfo() { RegUnitSetOrder.push_back(Idx); std::stable_sort(RegUnitSetOrder.begin(), RegUnitSetOrder.end(), - LessUnits(*this)); + [this](unsigned ID1, unsigned ID2) { + return getRegPressureSet(ID1).Units.size() < + getRegPressureSet(ID2).Units.size(); + }); for (unsigned Idx = 0, EndIdx = RegUnitSets.size(); Idx != EndIdx; ++Idx) { RegUnitSets[RegUnitSetOrder[Idx]].Order = Idx; } diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h index 37f75b4..03ffb43 100644 --- a/utils/TableGen/CodeGenRegisters.h +++ b/utils/TableGen/CodeGenRegisters.h @@ -20,7 +20,7 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SetVector.h" -#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/MachineValueType.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/TableGen/Record.h" #include <cstdlib> @@ -335,7 +335,7 @@ namespace llvm { // getSubClasses - Returns a constant BitVector of subclasses indexed by // EnumValue. - // The SubClasses vector includs an entry for this class. + // The SubClasses vector includes an entry for this class. const BitVector &getSubClasses() const { return SubClasses; } // getSuperClasses - Returns a list of super classes ordered by EnumValue. @@ -374,11 +374,6 @@ namespace llvm { unsigned SpillSize; unsigned SpillAlignment; - Key(const Key &O) - : Members(O.Members), - SpillSize(O.SpillSize), - SpillAlignment(O.SpillAlignment) {} - Key(const CodeGenRegister::Set *M, unsigned S = 0, unsigned A = 0) : Members(M), SpillSize(S), SpillAlignment(A) {} diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp index dd06433..a07524d 100644 --- a/utils/TableGen/CodeGenSchedule.cpp +++ b/utils/TableGen/CodeGenSchedule.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines structures to encapsulate the machine model as decribed in +// This file defines structures to encapsulate the machine model as described in // the target description. // //===----------------------------------------------------------------------===// @@ -39,8 +39,8 @@ static void dumpIdxVec(const SmallVectorImpl<unsigned> &V) { namespace { // (instrs a, b, ...) Evaluate and union all arguments. Identical to AddOp. struct InstrsOp : public SetTheory::Operator { - virtual void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts, - ArrayRef<SMLoc> Loc) { + void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts, + ArrayRef<SMLoc> Loc) override { ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts, Loc); } }; @@ -58,7 +58,7 @@ struct InstRegexOp : public SetTheory::Operator { InstRegexOp(const CodeGenTarget &t): Target(t) {} void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts, - ArrayRef<SMLoc> Loc) { + ArrayRef<SMLoc> Loc) override { SmallVector<Regex*, 4> RegexList; for (DagInit::const_arg_iterator AI = Expr->arg_begin(), AE = Expr->arg_end(); AI != AE; ++AI) { @@ -1473,11 +1473,23 @@ void CodeGenSchedModels::collectProcResources() { Record *ModelDef = (*WRI)->getValueAsDef("SchedModel"); addWriteRes(*WRI, getProcModel(ModelDef).Index); } + RecVec SWRDefs = Records.getAllDerivedDefinitions("SchedWriteRes"); + for (RecIter WRI = SWRDefs.begin(), WRE = SWRDefs.end(); WRI != WRE; ++WRI) { + Record *ModelDef = (*WRI)->getValueAsDef("SchedModel"); + addWriteRes(*WRI, getProcModel(ModelDef).Index); + } RecVec RADefs = Records.getAllDerivedDefinitions("ReadAdvance"); for (RecIter RAI = RADefs.begin(), RAE = RADefs.end(); RAI != RAE; ++RAI) { Record *ModelDef = (*RAI)->getValueAsDef("SchedModel"); addReadAdvance(*RAI, getProcModel(ModelDef).Index); } + RecVec SRADefs = Records.getAllDerivedDefinitions("SchedReadAdvance"); + for (RecIter RAI = SRADefs.begin(), RAE = SRADefs.end(); RAI != RAE; ++RAI) { + if ((*RAI)->getValueInit("SchedModel")->isComplete()) { + Record *ModelDef = (*RAI)->getValueAsDef("SchedModel"); + addReadAdvance(*RAI, getProcModel(ModelDef).Index); + } + } // Add ProcResGroups that are defined within this processor model, which may // not be directly referenced but may directly specify a buffer size. RecVec ProcResGroups = Records.getAllDerivedDefinitions("ProcResGroup"); diff --git a/utils/TableGen/CodeGenSchedule.h b/utils/TableGen/CodeGenSchedule.h index fa964cf..5ce679a 100644 --- a/utils/TableGen/CodeGenSchedule.h +++ b/utils/TableGen/CodeGenSchedule.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines structures to encapsulate the machine model as decribed in +// This file defines structures to encapsulate the machine model as described in // the target description. // //===----------------------------------------------------------------------===// @@ -162,7 +162,7 @@ struct CodeGenSchedClass { // ModelName is a unique name used to name an instantiation of MCSchedModel. // // ModelDef is NULL for inferred Models. This happens when a processor defines -// an itinerary but no machine model. If the processer defines neither a machine +// an itinerary but no machine model. If the processor defines neither a machine // model nor itinerary, then ModelDef remains pointing to NoModel. NoModel has // the special "NoModel" field set to true. // diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index dd17059..dd9c23c 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -143,6 +143,7 @@ CodeGenTarget::CodeGenTarget(RecordKeeper &records) } CodeGenTarget::~CodeGenTarget() { + DeleteContainerSeconds(Instructions); delete RegBank; delete SchedModels; } @@ -172,7 +173,8 @@ Record *CodeGenTarget::getInstructionSet() const { Record *CodeGenTarget::getAsmParser() const { std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers"); if (AsmParserNum >= LI.size()) - PrintFatalError("Target does not have an AsmParser #" + utostr(AsmParserNum) + "!"); + PrintFatalError("Target does not have an AsmParser #" + + Twine(AsmParserNum) + "!"); return LI[AsmParserNum]; } @@ -183,7 +185,8 @@ Record *CodeGenTarget::getAsmParserVariant(unsigned i) const { std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyParserVariants"); if (i >= LI.size()) - PrintFatalError("Target does not have an AsmParserVariant #" + utostr(i) + "!"); + PrintFatalError("Target does not have an AsmParserVariant #" + Twine(i) + + "!"); return LI[i]; } @@ -201,7 +204,8 @@ unsigned CodeGenTarget::getAsmParserVariantCount() const { Record *CodeGenTarget::getAsmWriter() const { std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters"); if (AsmWriterNum >= LI.size()) - PrintFatalError("Target does not have an AsmWriter #" + utostr(AsmWriterNum) + "!"); + PrintFatalError("Target does not have an AsmWriter #" + + Twine(AsmWriterNum) + "!"); return LI[AsmWriterNum]; } @@ -284,47 +288,20 @@ GetInstByName(const char *Name, DenseMap<const Record*, CodeGenInstruction*>::const_iterator I = Insts.find(Rec); if (Rec == 0 || I == Insts.end()) - PrintFatalError(std::string("Could not find '") + Name + "' instruction!"); + PrintFatalError(Twine("Could not find '") + Name + "' instruction!"); return I->second; } -namespace { -/// SortInstByName - Sorting predicate to sort instructions by name. -/// -struct SortInstByName { - bool operator()(const CodeGenInstruction *Rec1, - const CodeGenInstruction *Rec2) const { - return Rec1->TheDef->getName() < Rec2->TheDef->getName(); - } -}; -} - -/// getInstructionsByEnumValue - Return all of the instructions defined by the -/// target, ordered by their enum value. +/// \brief Return all of the instructions defined by the target, ordered by +/// their enum value. void CodeGenTarget::ComputeInstrsByEnum() const { // The ordering here must match the ordering in TargetOpcodes.h. static const char *const FixedInstrs[] = { - "PHI", - "INLINEASM", - "PROLOG_LABEL", - "EH_LABEL", - "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 - }; + "PHI", "INLINEASM", "CFI_INSTRUCTION", "EH_LABEL", + "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}; const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions(); for (const char *const *p = FixedInstrs; *p; ++p) { const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records); @@ -345,8 +322,10 @@ void CodeGenTarget::ComputeInstrsByEnum() const { // All of the instructions are now in random order based on the map iteration. // Sort them by name. - std::sort(InstrsByEnum.begin()+EndOfPredefines, InstrsByEnum.end(), - SortInstByName()); + std::sort(InstrsByEnum.begin() + EndOfPredefines, InstrsByEnum.end(), + [](const CodeGenInstruction *Rec1, const CodeGenInstruction *Rec2) { + return Rec1->TheDef->getName() < Rec2->TheDef->getName(); + }); } @@ -357,6 +336,46 @@ bool CodeGenTarget::isLittleEndianEncoding() const { return getInstructionSet()->getValueAsBit("isLittleEndianEncoding"); } +/// reverseBitsForLittleEndianEncoding - For little-endian instruction bit +/// encodings, reverse the bit order of all instructions. +void CodeGenTarget::reverseBitsForLittleEndianEncoding() { + if (!isLittleEndianEncoding()) + return; + + std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction"); + for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end(); + I != E; ++I) { + Record *R = *I; + if (R->getValueAsString("Namespace") == "TargetOpcode" || + R->getValueAsBit("isPseudo")) + continue; + + BitsInit *BI = R->getValueAsBitsInit("Inst"); + + unsigned numBits = BI->getNumBits(); + + SmallVector<Init *, 16> NewBits(numBits); + + for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) { + unsigned bitSwapIdx = numBits - bit - 1; + Init *OrigBit = BI->getBit(bit); + Init *BitSwap = BI->getBit(bitSwapIdx); + NewBits[bit] = BitSwap; + NewBits[bitSwapIdx] = OrigBit; + } + if (numBits % 2) { + unsigned middle = (numBits + 1) / 2; + NewBits[middle] = BI->getBit(middle); + } + + BitsInit *NewBI = BitsInit::get(NewBits); + + // Update the bits in reversed order so that emitInstrOpBits will get the + // correct endianness. + R->getValue("Inst")->setValue(NewBI); + } +} + /// guessInstructionProperties - Return true if it's OK to guess instruction /// properties instead of raising an error. /// @@ -430,6 +449,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { isCommutative = false; canThrow = false; isNoReturn = false; + isNoDuplicate = false; if (DefName.size() <= 4 || std::string(DefName.begin(), DefName.begin() + 4) != "int_") @@ -481,14 +501,14 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { // It only makes sense to use the extended and truncated vector element // variants with iAny types; otherwise, if the intrinsic is not // overloaded, all the types can be specified directly. - assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") && - !TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) || + assert(((!TyEl->isSubClassOf("LLVMExtendedType") && + !TyEl->isSubClassOf("LLVMTruncatedType")) || VT == MVT::iAny || VT == MVT::vAny) && "Expected iAny or vAny type"); } else { VT = getValueType(TyEl->getValueAsDef("VT")); } - if (EVT(VT).isOverloaded()) { + if (MVT(VT).isOverloaded()) { OverloadedVTs.push_back(VT); isOverloaded = true; } @@ -515,14 +535,14 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { // It only makes sense to use the extended and truncated vector element // variants with iAny types; otherwise, if the intrinsic is not // overloaded, all the types can be specified directly. - assert(((!TyEl->isSubClassOf("LLVMExtendedElementVectorType") && - !TyEl->isSubClassOf("LLVMTruncatedElementVectorType")) || + assert(((!TyEl->isSubClassOf("LLVMExtendedType") && + !TyEl->isSubClassOf("LLVMTruncatedType")) || VT == MVT::iAny || VT == MVT::vAny) && "Expected iAny or vAny type"); } else VT = getValueType(TyEl->getValueAsDef("VT")); - if (EVT(VT).isOverloaded()) { + if (MVT(VT).isOverloaded()) { OverloadedVTs.push_back(VT); isOverloaded = true; } @@ -554,6 +574,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { isCommutative = true; else if (Property->getName() == "Throws") canThrow = true; + else if (Property->getName() == "IntrNoDuplicate") + isNoDuplicate = true; else if (Property->getName() == "IntrNoReturn") isNoReturn = true; else if (Property->isSubClassOf("NoCapture")) { diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h index 6271443..d6458f4 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -177,6 +177,10 @@ public: /// bool isLittleEndianEncoding() const; + /// reverseBitsForLittleEndianEncoding - For little-endian instruction bit + /// encodings, reverse the bit order of all instructions. + void reverseBitsForLittleEndianEncoding(); + /// guessInstructionProperties - should we just guess unset instruction /// properties? bool guessInstructionProperties() const; diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index a76ea32..9294cd5 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -155,8 +155,7 @@ void DAGISelEmitter::run(raw_ostream &OS) { } } - Matcher *TheMatcher = new ScopeMatcher(&PatternMatchers[0], - PatternMatchers.size()); + Matcher *TheMatcher = new ScopeMatcher(PatternMatchers); TheMatcher = OptimizeMatcher(TheMatcher, CGP); //Matcher->dump(); diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp index 5d6a11a..2557bb6 100644 --- a/utils/TableGen/DAGISelMatcher.cpp +++ b/utils/TableGen/DAGISelMatcher.cpp @@ -84,6 +84,15 @@ ScopeMatcher::~ScopeMatcher() { delete Children[i]; } +SwitchOpcodeMatcher::~SwitchOpcodeMatcher() { + for (unsigned i = 0, e = Cases.size(); i != e; ++i) + delete Cases[i].second; +} + +SwitchTypeMatcher::~SwitchTypeMatcher() { + for (unsigned i = 0, e = Cases.size(); i != e; ++i) + delete Cases[i].second; +} CheckPredicateMatcher::CheckPredicateMatcher(const TreePredicateFn &pred) : Matcher(CheckPredicate), Pred(pred.getOrigPatFragRecord()) {} @@ -185,6 +194,11 @@ void CheckIntegerMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "CheckInteger " << Value << '\n'; } +void CheckChildIntegerMatcher::printImpl(raw_ostream &OS, + unsigned indent) const { + OS.indent(indent) << "CheckChildInteger " << ChildNo << " " << Value << '\n'; +} + void CheckCondCodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "CheckCondCode ISD::" << CondCodeName << '\n'; } @@ -411,6 +425,18 @@ bool CheckIntegerMatcher::isContradictoryImpl(const Matcher *M) const { return false; } +bool CheckChildIntegerMatcher::isContradictoryImpl(const Matcher *M) const { + if (const CheckChildIntegerMatcher *CCIM = dyn_cast<CheckChildIntegerMatcher>(M)) { + // If the two checks are about different nodes, we don't know if they + // conflict! + if (CCIM->getChildNo() != getChildNo()) + return false; + + return CCIM->getValue() != getValue(); + } + return false; +} + bool CheckValueTypeMatcher::isContradictoryImpl(const Matcher *M) const { if (const CheckValueTypeMatcher *CVT = dyn_cast<CheckValueTypeMatcher>(M)) return CVT->getTypeName() != getTypeName(); diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h index 70031fa..56a571f 100644 --- a/utils/TableGen/DAGISelMatcher.h +++ b/utils/TableGen/DAGISelMatcher.h @@ -10,10 +10,10 @@ #ifndef TBLGEN_DAGISELMATCHER_H #define TBLGEN_DAGISELMATCHER_H -#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/MachineValueType.h" #include "llvm/Support/Casting.h" namespace llvm { @@ -40,7 +40,7 @@ void EmitMatcherTable(const Matcher *Matcher, const CodeGenDAGPatterns &CGP, class Matcher { // The next matcher node that is executed after this one. Null if this is the // last stage of a match. - OwningPtr<Matcher> Next; + std::unique_ptr<Matcher> Next; virtual void anchor(); public: enum KindTy { @@ -64,6 +64,7 @@ public: SwitchType, // Dispatch based on type. CheckChildType, // Fail if child has wrong type. CheckInteger, // Fail if wrong val. + CheckChildInteger, // Fail if child is wrong val. CheckCondCode, // Fail if not condcode. CheckValueType, CheckComplexPat, @@ -96,9 +97,9 @@ public: Matcher *getNext() { return Next.get(); } const Matcher *getNext() const { return Next.get(); } void setNext(Matcher *C) { Next.reset(C); } - Matcher *takeNext() { return Next.take(); } + Matcher *takeNext() { return Next.release(); } - OwningPtr<Matcher> &getNextPtr() { return Next; } + std::unique_ptr<Matcher> &getNextPtr() { return Next; } bool isEqual(const Matcher *M) const { if (getKind() != M->getKind()) return false; @@ -130,6 +131,7 @@ public: case CheckType: case CheckChildType: case CheckInteger: + case CheckChildInteger: case CheckCondCode: case CheckValueType: case CheckAndImm: @@ -188,8 +190,8 @@ protected: class ScopeMatcher : public Matcher { SmallVector<Matcher*, 4> Children; public: - ScopeMatcher(Matcher *const *children, unsigned numchildren) - : Matcher(Scope), Children(children, children+numchildren) { + ScopeMatcher(ArrayRef<Matcher *> children) + : Matcher(Scope), Children(children.begin(), children.end()) { } virtual ~ScopeMatcher(); @@ -223,9 +225,9 @@ public: } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { return false; } - virtual unsigned getHashImpl() const { return 12312; } + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return false; } + unsigned getHashImpl() const override { return 12312; } }; /// RecordMatcher - Save the current node in the operand list. @@ -248,11 +250,11 @@ public: return N->getKind() == RecordNode; } - virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + bool isSafeToReorderWithPatternPredicate() const override { return true; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { return true; } - virtual unsigned getHashImpl() const { return 0; } + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return true; } + unsigned getHashImpl() const override { return 0; } }; /// RecordChildMatcher - Save a numbered child of the current node, or fail @@ -282,14 +284,14 @@ public: return N->getKind() == RecordChild; } - virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + bool isSafeToReorderWithPatternPredicate() const override { return true; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<RecordChildMatcher>(M)->getChildNo() == getChildNo(); } - virtual unsigned getHashImpl() const { return getChildNo(); } + unsigned getHashImpl() const override { return getChildNo(); } }; /// RecordMemRefMatcher - Save the current node's memref. @@ -301,12 +303,12 @@ public: return N->getKind() == RecordMemRef; } - virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + bool isSafeToReorderWithPatternPredicate() const override { return true; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { return true; } - virtual unsigned getHashImpl() const { return 0; } + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return true; } + unsigned getHashImpl() const override { return 0; } }; @@ -320,12 +322,12 @@ public: return N->getKind() == CaptureGlueInput; } - virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + bool isSafeToReorderWithPatternPredicate() const override { return true; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { return true; } - virtual unsigned getHashImpl() const { return 0; } + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return true; } + unsigned getHashImpl() const override { return 0; } }; /// MoveChildMatcher - This tells the interpreter to move into the @@ -341,14 +343,14 @@ public: return N->getKind() == MoveChild; } - virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + bool isSafeToReorderWithPatternPredicate() const override { return true; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<MoveChildMatcher>(M)->getChildNo() == getChildNo(); } - virtual unsigned getHashImpl() const { return getChildNo(); } + unsigned getHashImpl() const override { return getChildNo(); } }; /// MoveParentMatcher - This tells the interpreter to move to the parent @@ -361,12 +363,12 @@ public: return N->getKind() == MoveParent; } - virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + bool isSafeToReorderWithPatternPredicate() const override { return true; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { return true; } - virtual unsigned getHashImpl() const { return 0; } + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return true; } + unsigned getHashImpl() const override { return 0; } }; /// CheckSameMatcher - This checks to see if this node is exactly the same @@ -384,14 +386,14 @@ public: return N->getKind() == CheckSame; } - virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + bool isSafeToReorderWithPatternPredicate() const override { return true; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<CheckSameMatcher>(M)->getMatchNumber() == getMatchNumber(); } - virtual unsigned getHashImpl() const { return getMatchNumber(); } + unsigned getHashImpl() const override { return getMatchNumber(); } }; /// CheckChildSameMatcher - This checks to see if child node is exactly the same @@ -411,15 +413,15 @@ public: return N->getKind() == CheckChildSame; } - virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + bool isSafeToReorderWithPatternPredicate() const override { return true; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<CheckChildSameMatcher>(M)->ChildNo == ChildNo && cast<CheckChildSameMatcher>(M)->MatchNumber == MatchNumber; } - virtual unsigned getHashImpl() const { return (MatchNumber << 2) | ChildNo; } + unsigned getHashImpl() const override { return (MatchNumber << 2) | ChildNo; } }; /// CheckPatternPredicateMatcher - This checks the target-specific predicate @@ -437,14 +439,14 @@ public: return N->getKind() == CheckPatternPredicate; } - virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + bool isSafeToReorderWithPatternPredicate() const override { return true; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<CheckPatternPredicateMatcher>(M)->getPredicate() == Predicate; } - virtual unsigned getHashImpl() const; + unsigned getHashImpl() const override; }; /// CheckPredicateMatcher - This checks the target-specific predicate to @@ -464,11 +466,11 @@ public: //virtual bool isSafeToReorderWithPatternPredicate() const { return true; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<CheckPredicateMatcher>(M)->Pred == Pred; } - virtual unsigned getHashImpl() const; + unsigned getHashImpl() const override; }; @@ -486,13 +488,13 @@ public: return N->getKind() == CheckOpcode; } - virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + bool isSafeToReorderWithPatternPredicate() const override { return true; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const; - virtual unsigned getHashImpl() const; - virtual bool isContradictoryImpl(const Matcher *M) const; + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override; + unsigned getHashImpl() const override; + bool isContradictoryImpl(const Matcher *M) const override; }; /// SwitchOpcodeMatcher - Switch based on the current node's opcode, dispatching @@ -502,9 +504,9 @@ private: class SwitchOpcodeMatcher : public Matcher { SmallVector<std::pair<const SDNodeInfo*, Matcher*>, 8> Cases; public: - SwitchOpcodeMatcher(const std::pair<const SDNodeInfo*, Matcher*> *cases, - unsigned numcases) - : Matcher(SwitchOpcode), Cases(cases, cases+numcases) {} + SwitchOpcodeMatcher(ArrayRef<std::pair<const SDNodeInfo*, Matcher*> > cases) + : Matcher(SwitchOpcode), Cases(cases.begin(), cases.end()) {} + virtual ~SwitchOpcodeMatcher(); static inline bool classof(const Matcher *N) { return N->getKind() == SwitchOpcode; @@ -517,9 +519,9 @@ public: const Matcher *getCaseMatcher(unsigned i) const { return Cases[i].second; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { return false; } - virtual unsigned getHashImpl() const { return 4123; } + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return false; } + unsigned getHashImpl() const override { return 4123; } }; /// CheckTypeMatcher - This checks to see if the current node has the @@ -538,15 +540,15 @@ public: return N->getKind() == CheckType; } - virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + bool isSafeToReorderWithPatternPredicate() const override { return true; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<CheckTypeMatcher>(M)->Type == Type; } - virtual unsigned getHashImpl() const { return Type; } - virtual bool isContradictoryImpl(const Matcher *M) const; + unsigned getHashImpl() const override { return Type; } + bool isContradictoryImpl(const Matcher *M) const override; }; /// SwitchTypeMatcher - Switch based on the current node's type, dispatching @@ -556,9 +558,9 @@ private: class SwitchTypeMatcher : public Matcher { SmallVector<std::pair<MVT::SimpleValueType, Matcher*>, 8> Cases; public: - SwitchTypeMatcher(const std::pair<MVT::SimpleValueType, Matcher*> *cases, - unsigned numcases) - : Matcher(SwitchType), Cases(cases, cases+numcases) {} + SwitchTypeMatcher(ArrayRef<std::pair<MVT::SimpleValueType, Matcher*> > cases) + : Matcher(SwitchType), Cases(cases.begin(), cases.end()) {} + virtual ~SwitchTypeMatcher(); static inline bool classof(const Matcher *N) { return N->getKind() == SwitchType; @@ -571,9 +573,9 @@ public: const Matcher *getCaseMatcher(unsigned i) const { return Cases[i].second; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { return false; } - virtual unsigned getHashImpl() const { return 4123; } + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return false; } + unsigned getHashImpl() const override { return 4123; } }; @@ -593,16 +595,16 @@ public: return N->getKind() == CheckChildType; } - virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + bool isSafeToReorderWithPatternPredicate() const override { return true; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<CheckChildTypeMatcher>(M)->ChildNo == ChildNo && cast<CheckChildTypeMatcher>(M)->Type == Type; } - virtual unsigned getHashImpl() const { return (Type << 3) | ChildNo; } - virtual bool isContradictoryImpl(const Matcher *M) const; + unsigned getHashImpl() const override { return (Type << 3) | ChildNo; } + bool isContradictoryImpl(const Matcher *M) const override; }; @@ -620,15 +622,43 @@ public: return N->getKind() == CheckInteger; } - virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + bool isSafeToReorderWithPatternPredicate() const override { return true; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<CheckIntegerMatcher>(M)->Value == Value; } - virtual unsigned getHashImpl() const { return Value; } - virtual bool isContradictoryImpl(const Matcher *M) const; + unsigned getHashImpl() const override { return Value; } + bool isContradictoryImpl(const Matcher *M) const override; +}; + +/// CheckChildIntegerMatcher - This checks to see if the child node is a +/// ConstantSDNode with a specified integer value, if not it fails to match. +class CheckChildIntegerMatcher : public Matcher { + unsigned ChildNo; + int64_t Value; +public: + CheckChildIntegerMatcher(unsigned childno, int64_t value) + : Matcher(CheckChildInteger), ChildNo(childno), Value(value) {} + + unsigned getChildNo() const { return ChildNo; } + int64_t getValue() const { return Value; } + + static inline bool classof(const Matcher *N) { + return N->getKind() == CheckChildInteger; + } + + bool isSafeToReorderWithPatternPredicate() const override { return true; } + +private: + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { + return cast<CheckChildIntegerMatcher>(M)->ChildNo == ChildNo && + cast<CheckChildIntegerMatcher>(M)->Value == Value; + } + unsigned getHashImpl() const override { return (Value << 3) | ChildNo; } + bool isContradictoryImpl(const Matcher *M) const override; }; /// CheckCondCodeMatcher - This checks to see if the current node is a @@ -645,14 +675,14 @@ public: return N->getKind() == CheckCondCode; } - virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + bool isSafeToReorderWithPatternPredicate() const override { return true; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<CheckCondCodeMatcher>(M)->CondCodeName == CondCodeName; } - virtual unsigned getHashImpl() const; + unsigned getHashImpl() const override; }; /// CheckValueTypeMatcher - This checks to see if the current node is a @@ -669,15 +699,15 @@ public: return N->getKind() == CheckValueType; } - virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + bool isSafeToReorderWithPatternPredicate() const override { return true; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<CheckValueTypeMatcher>(M)->TypeName == TypeName; } - virtual unsigned getHashImpl() const; - bool isContradictoryImpl(const Matcher *M) const; + unsigned getHashImpl() const override; + bool isContradictoryImpl(const Matcher *M) const override; }; @@ -714,15 +744,15 @@ public: } // Not safe to move a pattern predicate past a complex pattern. - virtual bool isSafeToReorderWithPatternPredicate() const { return false; } + bool isSafeToReorderWithPatternPredicate() const override { return false; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return &cast<CheckComplexPatMatcher>(M)->Pattern == &Pattern && cast<CheckComplexPatMatcher>(M)->MatchNumber == MatchNumber; } - virtual unsigned getHashImpl() const { + unsigned getHashImpl() const override { return (unsigned)(intptr_t)&Pattern ^ MatchNumber; } }; @@ -741,14 +771,14 @@ public: return N->getKind() == CheckAndImm; } - virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + bool isSafeToReorderWithPatternPredicate() const override { return true; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<CheckAndImmMatcher>(M)->Value == Value; } - virtual unsigned getHashImpl() const { return Value; } + unsigned getHashImpl() const override { return Value; } }; /// CheckOrImmMatcher - This checks to see if the current node is an 'and' @@ -765,14 +795,14 @@ public: return N->getKind() == CheckOrImm; } - virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + bool isSafeToReorderWithPatternPredicate() const override { return true; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<CheckOrImmMatcher>(M)->Value == Value; } - virtual unsigned getHashImpl() const { return Value; } + unsigned getHashImpl() const override { return Value; } }; /// CheckFoldableChainNodeMatcher - This checks to see if the current node @@ -786,12 +816,12 @@ public: return N->getKind() == CheckFoldableChainNode; } - virtual bool isSafeToReorderWithPatternPredicate() const { return true; } + bool isSafeToReorderWithPatternPredicate() const override { return true; } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { return true; } - virtual unsigned getHashImpl() const { return 0; } + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return true; } + unsigned getHashImpl() const override { return 0; } }; /// EmitIntegerMatcher - This creates a new TargetConstant. @@ -810,12 +840,12 @@ public: } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<EmitIntegerMatcher>(M)->Val == Val && cast<EmitIntegerMatcher>(M)->VT == VT; } - virtual unsigned getHashImpl() const { return (Val << 4) | VT; } + unsigned getHashImpl() const override { return (Val << 4) | VT; } }; /// EmitStringIntegerMatcher - A target constant whose value is represented @@ -835,12 +865,12 @@ public: } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<EmitStringIntegerMatcher>(M)->Val == Val && cast<EmitStringIntegerMatcher>(M)->VT == VT; } - virtual unsigned getHashImpl() const; + unsigned getHashImpl() const override; }; /// EmitRegisterMatcher - This creates a new TargetConstant. @@ -861,12 +891,12 @@ public: } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<EmitRegisterMatcher>(M)->Reg == Reg && cast<EmitRegisterMatcher>(M)->VT == VT; } - virtual unsigned getHashImpl() const { + unsigned getHashImpl() const override { return ((unsigned)(intptr_t)Reg) << 4 | VT; } }; @@ -887,11 +917,11 @@ public: } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<EmitConvertToTargetMatcher>(M)->Slot == Slot; } - virtual unsigned getHashImpl() const { return Slot; } + unsigned getHashImpl() const override { return Slot; } }; /// EmitMergeInputChainsMatcher - Emit a node that merges a list of input @@ -901,8 +931,8 @@ private: class EmitMergeInputChainsMatcher : public Matcher { SmallVector<unsigned, 3> ChainNodes; public: - EmitMergeInputChainsMatcher(const unsigned *nodes, unsigned NumNodes) - : Matcher(EmitMergeInputChains), ChainNodes(nodes, nodes+NumNodes) {} + EmitMergeInputChainsMatcher(ArrayRef<unsigned> nodes) + : Matcher(EmitMergeInputChains), ChainNodes(nodes.begin(), nodes.end()) {} unsigned getNumNodes() const { return ChainNodes.size(); } @@ -916,11 +946,11 @@ public: } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<EmitMergeInputChainsMatcher>(M)->ChainNodes == ChainNodes; } - virtual unsigned getHashImpl() const; + unsigned getHashImpl() const override; }; /// EmitCopyToRegMatcher - Emit a CopyToReg node from a value to a physreg, @@ -941,12 +971,12 @@ public: } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<EmitCopyToRegMatcher>(M)->SrcSlot == SrcSlot && cast<EmitCopyToRegMatcher>(M)->DestPhysReg == DestPhysReg; } - virtual unsigned getHashImpl() const { + unsigned getHashImpl() const override { return SrcSlot ^ ((unsigned)(intptr_t)DestPhysReg << 4); } }; @@ -970,12 +1000,12 @@ public: } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<EmitNodeXFormMatcher>(M)->Slot == Slot && cast<EmitNodeXFormMatcher>(M)->NodeXForm == NodeXForm; } - virtual unsigned getHashImpl() const { + unsigned getHashImpl() const override { return Slot ^ ((unsigned)(intptr_t)NodeXForm << 4); } }; @@ -994,13 +1024,13 @@ class EmitNodeMatcherCommon : public Matcher { int NumFixedArityOperands; public: EmitNodeMatcherCommon(const std::string &opcodeName, - const MVT::SimpleValueType *vts, unsigned numvts, - const unsigned *operands, unsigned numops, + ArrayRef<MVT::SimpleValueType> vts, + ArrayRef<unsigned> operands, bool hasChain, bool hasInGlue, bool hasOutGlue, bool hasmemrefs, int numfixedarityoperands, bool isMorphNodeTo) : Matcher(isMorphNodeTo ? MorphNodeTo : EmitNode), OpcodeName(opcodeName), - VTs(vts, vts+numvts), Operands(operands, operands+numops), + VTs(vts.begin(), vts.end()), Operands(operands.begin(), operands.end()), HasChain(hasChain), HasInGlue(hasInGlue), HasOutGlue(hasOutGlue), HasMemRefs(hasmemrefs), NumFixedArityOperands(numfixedarityoperands) {} @@ -1033,23 +1063,23 @@ public: } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const; - virtual unsigned getHashImpl() const; + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override; + unsigned getHashImpl() const override; }; /// EmitNodeMatcher - This signals a successful match and generates a node. class EmitNodeMatcher : public EmitNodeMatcherCommon { - virtual void anchor(); + void anchor() override; unsigned FirstResultSlot; public: EmitNodeMatcher(const std::string &opcodeName, - const MVT::SimpleValueType *vts, unsigned numvts, - const unsigned *operands, unsigned numops, + ArrayRef<MVT::SimpleValueType> vts, + ArrayRef<unsigned> operands, bool hasChain, bool hasInFlag, bool hasOutFlag, bool hasmemrefs, int numfixedarityoperands, unsigned firstresultslot) - : EmitNodeMatcherCommon(opcodeName, vts, numvts, operands, numops, hasChain, + : EmitNodeMatcherCommon(opcodeName, vts, operands, hasChain, hasInFlag, hasOutFlag, hasmemrefs, numfixedarityoperands, false), FirstResultSlot(firstresultslot) {} @@ -1063,16 +1093,16 @@ public: }; class MorphNodeToMatcher : public EmitNodeMatcherCommon { - virtual void anchor(); + void anchor() override; const PatternToMatch &Pattern; public: MorphNodeToMatcher(const std::string &opcodeName, - const MVT::SimpleValueType *vts, unsigned numvts, - const unsigned *operands, unsigned numops, + ArrayRef<MVT::SimpleValueType> vts, + ArrayRef<unsigned> operands, bool hasChain, bool hasInFlag, bool hasOutFlag, bool hasmemrefs, int numfixedarityoperands, const PatternToMatch &pattern) - : EmitNodeMatcherCommon(opcodeName, vts, numvts, operands, numops, hasChain, + : EmitNodeMatcherCommon(opcodeName, vts, operands, hasChain, hasInFlag, hasOutFlag, hasmemrefs, numfixedarityoperands, true), Pattern(pattern) { @@ -1091,8 +1121,8 @@ public: class MarkGlueResultsMatcher : public Matcher { SmallVector<unsigned, 3> GlueResultNodes; public: - MarkGlueResultsMatcher(const unsigned *nodes, unsigned NumNodes) - : Matcher(MarkGlueResults), GlueResultNodes(nodes, nodes+NumNodes) {} + MarkGlueResultsMatcher(ArrayRef<unsigned> nodes) + : Matcher(MarkGlueResults), GlueResultNodes(nodes.begin(), nodes.end()) {} unsigned getNumNodes() const { return GlueResultNodes.size(); } @@ -1106,11 +1136,11 @@ public: } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<MarkGlueResultsMatcher>(M)->GlueResultNodes == GlueResultNodes; } - virtual unsigned getHashImpl() const; + unsigned getHashImpl() const override; }; /// CompleteMatchMatcher - Complete a match by replacing the results of the @@ -1120,9 +1150,9 @@ class CompleteMatchMatcher : public Matcher { SmallVector<unsigned, 2> Results; const PatternToMatch &Pattern; public: - CompleteMatchMatcher(const unsigned *results, unsigned numresults, + CompleteMatchMatcher(ArrayRef<unsigned> results, const PatternToMatch &pattern) - : Matcher(CompleteMatch), Results(results, results+numresults), + : Matcher(CompleteMatch), Results(results.begin(), results.end()), Pattern(pattern) {} unsigned getNumResults() const { return Results.size(); } @@ -1134,12 +1164,12 @@ public: } private: - virtual void printImpl(raw_ostream &OS, unsigned indent) const; - virtual bool isEqualImpl(const Matcher *M) const { + void printImpl(raw_ostream &OS, unsigned indent) const override; + bool isEqualImpl(const Matcher *M) const override { return cast<CompleteMatchMatcher>(M)->Results == Results && &cast<CompleteMatchMatcher>(M)->Pattern == &Pattern; } - virtual unsigned getHashImpl() const; + unsigned getHashImpl() const override; }; } // end namespace llvm diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp index 04fe0d1..416e8e3 100644 --- a/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -332,7 +332,6 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, // Emit the VBR. CurrentIdx += EmitVBRValue(ChildSize, OS); - OS << ' '; if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) OS << "TARGET_VAL(" << SOM->getCaseOpcode(i).getEnumName() << "),"; else @@ -379,6 +378,14 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, OS << '\n'; return Bytes; } + case Matcher::CheckChildInteger: { + OS << "OPC_CheckChild" << cast<CheckChildIntegerMatcher>(N)->getChildNo() + << "Integer, "; + unsigned Bytes=1+EmitVBRValue(cast<CheckChildIntegerMatcher>(N)->getValue(), + OS); + OS << '\n'; + return Bytes; + } case Matcher::CheckCondCode: OS << "OPC_CheckCondCode, ISD::" << cast<CheckCondCodeMatcher>(N)->getCondCodeName() << ",\n"; @@ -608,7 +615,7 @@ EmitMatcherList(const Matcher *N, unsigned Indent, unsigned CurrentIdx, void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { // Emit pattern predicates. if (!PatternPredicates.empty()) { - OS << "virtual bool CheckPatternPredicate(unsigned PredNo) const {\n"; + OS << "bool CheckPatternPredicate(unsigned PredNo) const override {\n"; OS << " switch (PredNo) {\n"; OS << " default: llvm_unreachable(\"Invalid predicate in table?\");\n"; for (unsigned i = 0, e = PatternPredicates.size(); i != e; ++i) @@ -626,8 +633,8 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { PFsByName[I->first->getName()] = I->second; if (!NodePredicates.empty()) { - OS << "virtual bool CheckNodePredicate(SDNode *Node,\n"; - OS << " unsigned PredNo) const {\n"; + OS << "bool CheckNodePredicate(SDNode *Node,\n"; + OS << " unsigned PredNo) const override {\n"; OS << " switch (PredNo) {\n"; OS << " default: llvm_unreachable(\"Invalid predicate in table?\");\n"; for (unsigned i = 0, e = NodePredicates.size(); i != e; ++i) { @@ -646,9 +653,9 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { // Emit CompletePattern matchers. // FIXME: This should be const. if (!ComplexPatterns.empty()) { - OS << "virtual bool CheckComplexPattern(SDNode *Root, SDNode *Parent,\n"; - OS << " SDValue N, unsigned PatternNo,\n"; - OS << " SmallVectorImpl<std::pair<SDValue, SDNode*> > &Result) {\n"; + OS << "bool CheckComplexPattern(SDNode *Root, SDNode *Parent,\n"; + OS << " SDValue N, unsigned PatternNo,\n"; + OS << " SmallVectorImpl<std::pair<SDValue, SDNode*> > &Result) override {\n"; OS << " unsigned NextRes = Result.size();\n"; OS << " switch (PatternNo) {\n"; OS << " default: llvm_unreachable(\"Invalid pattern # in table?\");\n"; @@ -687,7 +694,7 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { // Emit SDNodeXForm handlers. // FIXME: This should be const. if (!NodeXForms.empty()) { - OS << "virtual SDValue RunSDNodeXForm(SDValue V, unsigned XFormNo) {\n"; + OS << "SDValue RunSDNodeXForm(SDValue V, unsigned XFormNo) override {\n"; OS << " switch (XFormNo) {\n"; OS << " default: llvm_unreachable(\"Invalid xform # in table?\");\n"; @@ -769,6 +776,7 @@ void MatcherTableEmitter::EmitHistogram(const Matcher *M, case Matcher::SwitchType: OS << "OPC_SwitchType"; break; case Matcher::CheckChildType: OS << "OPC_CheckChildType"; break; case Matcher::CheckInteger: OS << "OPC_CheckInteger"; break; + case Matcher::CheckChildInteger: OS << "OPC_CheckChildInteger"; break; case Matcher::CheckCondCode: OS << "OPC_CheckCondCode"; break; case Matcher::CheckValueType: OS << "OPC_CheckValueType"; break; case Matcher::CheckComplexPat: OS << "OPC_CheckComplexPat"; break; @@ -809,7 +817,7 @@ void llvm::EmitMatcherTable(const Matcher *TheMatcher, OS << " // this.\n"; OS << " #define TARGET_VAL(X) X & 255, unsigned(X) >> 8\n"; OS << " static const unsigned char MatcherTable[] = {\n"; - unsigned TotalSize = MatcherEmitter.EmitMatcherList(TheMatcher, 5, 0, OS); + unsigned TotalSize = MatcherEmitter.EmitMatcherList(TheMatcher, 6, 0, OS); OS << " 0\n }; // Total Array size is " << (TotalSize+1) << " bytes\n\n"; MatcherEmitter.EmitHistogram(TheMatcher, OS); diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index ed41631..8ae7444 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -419,7 +419,7 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N, void MatcherGen::EmitMatchCode(const TreePatternNode *N, TreePatternNode *NodeNoTypes) { // If N and NodeNoTypes don't agree on a type, then this is a case where we - // need to do a type check. Emit the check, apply the tyep to NodeNoTypes and + // need to do a type check. Emit the check, apply the type to NodeNoTypes and // reinfer any correlated types. SmallVector<unsigned, 2> ResultsToTypeCheck; @@ -850,8 +850,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, "Node has no result"); AddMatcher(new EmitNodeMatcher(II.Namespace+"::"+II.TheDef->getName(), - ResultVTs.data(), ResultVTs.size(), - InstOps.data(), InstOps.size(), + ResultVTs, InstOps, NodeHasChain, TreeHasInGlue, TreeHasOutGlue, NodeHasMemRefs, NumFixedArityOperands, NextRecordedOperandNo)); @@ -907,8 +906,7 @@ void MatcherGen::EmitResultCode() { // merge them together into a token factor. This informs the generated code // what all the chained nodes are. if (!MatchedChainNodes.empty()) - AddMatcher(new EmitMergeInputChainsMatcher - (MatchedChainNodes.data(), MatchedChainNodes.size())); + AddMatcher(new EmitMergeInputChainsMatcher(MatchedChainNodes)); // Codegen the root of the result pattern, capturing the resulting values. SmallVector<unsigned, 8> Ops; @@ -949,10 +947,9 @@ void MatcherGen::EmitResultCode() { // If the matched pattern covers nodes which define a glue result, emit a node // that tells the matcher about them so that it can update their results. if (!MatchedGlueResultNodes.empty()) - AddMatcher(new MarkGlueResultsMatcher(MatchedGlueResultNodes.data(), - MatchedGlueResultNodes.size())); + AddMatcher(new MarkGlueResultsMatcher(MatchedGlueResultNodes)); - AddMatcher(new CompleteMatchMatcher(Ops.data(), Ops.size(), Pattern)); + AddMatcher(new CompleteMatchMatcher(Ops, Pattern)); } diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp index 82e5d63..b7f3b6c 100644 --- a/utils/TableGen/DAGISelMatcherOpt.cpp +++ b/utils/TableGen/DAGISelMatcherOpt.cpp @@ -22,7 +22,7 @@ using namespace llvm; /// ContractNodes - Turn multiple matcher node patterns like 'MoveChild+Record' /// into single compound nodes like RecordChild. -static void ContractNodes(OwningPtr<Matcher> &MatcherPtr, +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(); @@ -31,9 +31,9 @@ static void ContractNodes(OwningPtr<Matcher> &MatcherPtr, // If we have a scope node, walk down all of the children. if (ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N)) { for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) { - OwningPtr<Matcher> Child(Scope->takeChild(i)); + std::unique_ptr<Matcher> Child(Scope->takeChild(i)); ContractNodes(Child, CGP); - Scope->resetChild(i, Child.take()); + Scope->resetChild(i, Child.release()); } return; } @@ -46,7 +46,7 @@ static void ContractNodes(OwningPtr<Matcher> &MatcherPtr, if (MC->getChildNo() < 8) // Only have RecordChild0...7 New = new RecordChildMatcher(MC->getChildNo(), RM->getWhatFor(), RM->getResultNo()); - + if (CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(MC->getNext())) if (MC->getChildNo() < 8 && // Only have CheckChildType0...7 CT->getResNo() == 0) // CheckChildType checks res #0 @@ -56,9 +56,13 @@ static void ContractNodes(OwningPtr<Matcher> &MatcherPtr, if (MC->getChildNo() < 4) // Only have CheckChildSame0...3 New = new CheckChildSameMatcher(MC->getChildNo(), CS->getMatchNumber()); + if (CheckIntegerMatcher *CS = dyn_cast<CheckIntegerMatcher>(MC->getNext())) + if (MC->getChildNo() < 5) // Only have CheckChildInteger0...4 + New = new CheckChildIntegerMatcher(MC->getChildNo(), CS->getValue()); + if (New) { // Insert the new node. - New->setNext(MatcherPtr.take()); + New->setNext(MatcherPtr.release()); MatcherPtr.reset(New); // Remove the old one. MC->setNext(MC->getNext()->takeNext()); @@ -81,7 +85,7 @@ static void ContractNodes(OwningPtr<Matcher> &MatcherPtr, if (isa<EmitNodeMatcher>(N) && isa<MarkGlueResultsMatcher>(N->getNext()) && isa<CompleteMatchMatcher>(N->getNext()->getNext())) { // Unlink the two nodes from the list. - Matcher *EmitNode = MatcherPtr.take(); + Matcher *EmitNode = MatcherPtr.release(); Matcher *MFR = EmitNode->takeNext(); Matcher *Tail = MFR->takeNext(); @@ -136,8 +140,7 @@ static void ContractNodes(OwningPtr<Matcher> &MatcherPtr, const SmallVectorImpl<MVT::SimpleValueType> &VTs = EN->getVTList(); const SmallVectorImpl<unsigned> &Operands = EN->getOperandList(); MatcherPtr.reset(new MorphNodeToMatcher(EN->getOpcodeName(), - VTs.data(), VTs.size(), - Operands.data(),Operands.size(), + VTs, Operands, EN->hasChain(), EN->hasInFlag(), EN->hasOutFlag(), EN->hasMemRefs(), @@ -161,7 +164,7 @@ static void ContractNodes(OwningPtr<Matcher> &MatcherPtr, isa<RecordMatcher>(N)) && isa<CheckOpcodeMatcher>(N->getNext())) { // Unlink the two nodes from the list. - Matcher *CheckType = MatcherPtr.take(); + Matcher *CheckType = MatcherPtr.release(); Matcher *CheckOpcode = CheckType->takeNext(); Matcher *Tail = CheckOpcode->takeNext(); @@ -184,7 +187,7 @@ static void ContractNodes(OwningPtr<Matcher> &MatcherPtr, /// run a the complex pattern if the pattern predicate will fail. For this /// reason, we refuse to sink the pattern predicate past a ComplexPattern. /// -static void SinkPatternPredicates(OwningPtr<Matcher> &MatcherPtr) { +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(); @@ -193,9 +196,9 @@ static void SinkPatternPredicates(OwningPtr<Matcher> &MatcherPtr) { // Walk down all members of a scope node. if (ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N)) { for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) { - OwningPtr<Matcher> Child(Scope->takeChild(i)); + std::unique_ptr<Matcher> Child(Scope->takeChild(i)); SinkPatternPredicates(Child); - Scope->resetChild(i, Child.take()); + Scope->resetChild(i, Child.release()); } return; } @@ -214,7 +217,7 @@ static void SinkPatternPredicates(OwningPtr<Matcher> &MatcherPtr) { // Okay, we know we can sink it past at least one node. Unlink it from the // chain and scan for the new insertion point. - MatcherPtr.take(); // Don't delete CPPM. + MatcherPtr.release(); // Don't delete CPPM. MatcherPtr.reset(CPPM->takeNext()); N = MatcherPtr.get(); @@ -249,7 +252,7 @@ static Matcher *FindNodeWithKind(Matcher *M, Matcher::KindTy Kind) { /// ABC /// XYZ /// -static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) { +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; @@ -266,10 +269,10 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) { for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) { // Factor the subexpression. - OwningPtr<Matcher> Child(Scope->takeChild(i)); + std::unique_ptr<Matcher> Child(Scope->takeChild(i)); FactorNodes(Child); - if (Matcher *N = Child.take()) + if (Matcher *N = Child.release()) OptionsToMatch.push_back(N); } @@ -380,7 +383,7 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) { EqualMatchers[i] = Tmp; } - Shared->setNext(new ScopeMatcher(&EqualMatchers[0], EqualMatchers.size())); + Shared->setNext(new ScopeMatcher(EqualMatchers)); // Recursively factor the newly created node. FactorNodes(Shared->getNextPtr()); @@ -455,7 +458,7 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) { Cases.push_back(std::make_pair(&COM->getOpcode(), COM->getNext())); } - MatcherPtr.reset(new SwitchOpcodeMatcher(&Cases[0], Cases.size())); + MatcherPtr.reset(new SwitchOpcodeMatcher(Cases)); return; } @@ -482,7 +485,7 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) { } Matcher *Entries[2] = { PrevMatcher, MatcherWithoutCTM }; - Cases[Entry-1].second = new ScopeMatcher(Entries, 2); + Cases[Entry-1].second = new ScopeMatcher(Entries); continue; } @@ -491,7 +494,7 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) { } if (Cases.size() != 1) { - MatcherPtr.reset(new SwitchTypeMatcher(&Cases[0], Cases.size())); + MatcherPtr.reset(new SwitchTypeMatcher(Cases)); } else { // If we factored and ended up with one case, create it now. MatcherPtr.reset(new CheckTypeMatcher(Cases[0].first, 0)); @@ -509,9 +512,9 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) { Matcher *llvm::OptimizeMatcher(Matcher *TheMatcher, const CodeGenDAGPatterns &CGP) { - OwningPtr<Matcher> MatcherPtr(TheMatcher); + std::unique_ptr<Matcher> MatcherPtr(TheMatcher); ContractNodes(MatcherPtr, CGP); SinkPatternPredicates(MatcherPtr); FactorNodes(MatcherPtr); - return MatcherPtr.take(); + return MatcherPtr.release(); } diff --git a/utils/TableGen/DisassemblerEmitter.cpp b/utils/TableGen/DisassemblerEmitter.cpp index 5a2a41b..0020de6 100644 --- a/utils/TableGen/DisassemblerEmitter.cpp +++ b/utils/TableGen/DisassemblerEmitter.cpp @@ -117,9 +117,10 @@ void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) { for (unsigned i = 0, e = numberedInstructions.size(); i != e; ++i) RecognizableInstr::processInstr(Tables, *numberedInstructions[i], i); - if (Tables.hasConflicts()) - PrintFatalError(Target.getTargetRecord()->getLoc(), - "Primary decode conflict"); + if (Tables.hasConflicts()) { + PrintError(Target.getTargetRecord()->getLoc(), "Primary decode conflict"); + return; + } Tables.emit(OS); return; diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp index e35cf0f..3a3f836 100644 --- a/utils/TableGen/FastISelEmitter.cpp +++ b/utils/TableGen/FastISelEmitter.cpp @@ -638,7 +638,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { if ((*Memo.PhysRegs)[i] != "") - OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, " + OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, " << "TII.get(TargetOpcode::COPY), " << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n"; } @@ -729,7 +729,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { if ((*Memo.PhysRegs)[i] != "") - OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, " + OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, " << "TII.get(TargetOpcode::COPY), " << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n"; } diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp index 87d18cd..e249a94 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -28,7 +28,6 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" -#include "llvm/TableGen/TableGenBackend.h" #include <map> #include <string> #include <vector> @@ -1698,19 +1697,13 @@ void FilterChooser::emitTableEntries(DecoderTableInfo &TableInfo) const { } } -static bool populateInstruction(const CodeGenInstruction &CGI, unsigned Opc, +static bool populateInstruction(CodeGenTarget &Target, + const CodeGenInstruction &CGI, unsigned Opc, std::map<unsigned, std::vector<OperandInfo> > &Operands){ const Record &Def = *CGI.TheDef; // If all the bit positions are not specified; do not decode this instruction. // We are bound to fail! For proper disassembly, the well-known encoding bits // of the instruction must be fully specified. - // - // This also removes pseudo instructions from considerations of disassembly, - // which is a better design and less fragile than the name matchings. - // Ignore "asm parser only" instructions. - if (Def.getValueAsBit("isAsmParserOnly") || - Def.getValueAsBit("isCodeGenOnly")) - return false; BitsInit &Bits = getBitsField(Def, "Inst"); if (Bits.allInComplete()) return false; @@ -1747,14 +1740,180 @@ static bool populateInstruction(const CodeGenInstruction &CGI, unsigned Opc, for (unsigned i = 0; i < CGI.Operands.size(); ++i) { int tiedTo = CGI.Operands[i].getTiedRegister(); if (tiedTo != -1) { - TiedNames[InOutOperands[i].second] = InOutOperands[tiedTo].second; - TiedNames[InOutOperands[tiedTo].second] = InOutOperands[i].second; + std::pair<unsigned, unsigned> SO = + CGI.Operands.getSubOperandNumber(tiedTo); + TiedNames[InOutOperands[i].second] = InOutOperands[SO.first].second; + TiedNames[InOutOperands[SO.first].second] = InOutOperands[i].second; + } + } + + std::map<std::string, std::vector<OperandInfo> > NumberedInsnOperands; + std::set<std::string> NumberedInsnOperandsNoTie; + if (Target.getInstructionSet()-> + getValueAsBit("decodePositionallyEncodedOperands")) { + const std::vector<RecordVal> &Vals = Def.getValues(); + unsigned NumberedOp = 0; + + std::set<unsigned> NamedOpIndices; + if (Target.getInstructionSet()-> + getValueAsBit("noNamedPositionallyEncodedOperands")) + // Collect the set of operand indices that might correspond to named + // operand, and skip these when assigning operands based on position. + for (unsigned i = 0, e = Vals.size(); i != e; ++i) { + unsigned OpIdx; + if (!CGI.Operands.hasOperandNamed(Vals[i].getName(), OpIdx)) + continue; + + NamedOpIndices.insert(OpIdx); + } + + for (unsigned i = 0, e = Vals.size(); i != e; ++i) { + // Ignore fixed fields in the record, we're looking for values like: + // bits<5> RST = { ?, ?, ?, ?, ? }; + if (Vals[i].getPrefix() || Vals[i].getValue()->isComplete()) + continue; + + // Determine if Vals[i] actually contributes to the Inst encoding. + unsigned bi = 0; + for (; bi < Bits.getNumBits(); ++bi) { + VarInit *Var = 0; + VarBitInit *BI = dyn_cast<VarBitInit>(Bits.getBit(bi)); + if (BI) + Var = dyn_cast<VarInit>(BI->getBitVar()); + else + Var = dyn_cast<VarInit>(Bits.getBit(bi)); + + if (Var && Var->getName() == Vals[i].getName()) + break; + } + + if (bi == Bits.getNumBits()) + continue; + + // Skip variables that correspond to explicitly-named operands. + unsigned OpIdx; + if (CGI.Operands.hasOperandNamed(Vals[i].getName(), OpIdx)) + continue; + + // Get the bit range for this operand: + unsigned bitStart = bi++, bitWidth = 1; + for (; bi < Bits.getNumBits(); ++bi) { + VarInit *Var = 0; + VarBitInit *BI = dyn_cast<VarBitInit>(Bits.getBit(bi)); + if (BI) + Var = dyn_cast<VarInit>(BI->getBitVar()); + else + Var = dyn_cast<VarInit>(Bits.getBit(bi)); + + if (!Var) + break; + + if (Var->getName() != Vals[i].getName()) + break; + + ++bitWidth; + } + + unsigned NumberOps = CGI.Operands.size(); + while (NumberedOp < NumberOps && + (CGI.Operands.isFlatOperandNotEmitted(NumberedOp) || + (NamedOpIndices.size() && NamedOpIndices.count( + CGI.Operands.getSubOperandNumber(NumberedOp).first)))) + ++NumberedOp; + + OpIdx = NumberedOp++; + + // OpIdx now holds the ordered operand number of Vals[i]. + std::pair<unsigned, unsigned> SO = + CGI.Operands.getSubOperandNumber(OpIdx); + const std::string &Name = CGI.Operands[SO.first].Name; + + DEBUG(dbgs() << "Numbered operand mapping for " << Def.getName() << ": " << + Name << "(" << SO.first << ", " << SO.second << ") => " << + Vals[i].getName() << "\n"); + + std::string Decoder = ""; + Record *TypeRecord = CGI.Operands[SO.first].Rec; + + RecordVal *DecoderString = TypeRecord->getValue("DecoderMethod"); + StringInit *String = DecoderString ? + dyn_cast<StringInit>(DecoderString->getValue()) : 0; + if (String && String->getValue() != "") + Decoder = String->getValue(); + + if (Decoder == "" && + CGI.Operands[SO.first].MIOperandInfo && + CGI.Operands[SO.first].MIOperandInfo->getNumArgs()) { + Init *Arg = CGI.Operands[SO.first].MIOperandInfo-> + getArg(SO.second); + if (TypedInit *TI = cast<TypedInit>(Arg)) { + RecordRecTy *Type = cast<RecordRecTy>(TI->getType()); + TypeRecord = Type->getRecord(); + } + } + + bool isReg = false; + if (TypeRecord->isSubClassOf("RegisterOperand")) + TypeRecord = TypeRecord->getValueAsDef("RegClass"); + if (TypeRecord->isSubClassOf("RegisterClass")) { + Decoder = "Decode" + TypeRecord->getName() + "RegisterClass"; + isReg = true; + } else if (TypeRecord->isSubClassOf("PointerLikeRegClass")) { + Decoder = "DecodePointerLikeRegClass" + + utostr(TypeRecord->getValueAsInt("RegClassKind")); + isReg = true; + } + + DecoderString = TypeRecord->getValue("DecoderMethod"); + String = DecoderString ? + dyn_cast<StringInit>(DecoderString->getValue()) : 0; + if (!isReg && String && String->getValue() != "") + Decoder = String->getValue(); + + OperandInfo OpInfo(Decoder); + OpInfo.addField(bitStart, bitWidth, 0); + + NumberedInsnOperands[Name].push_back(OpInfo); + + // FIXME: For complex operands with custom decoders we can't handle tied + // sub-operands automatically. Skip those here and assume that this is + // fixed up elsewhere. + if (CGI.Operands[SO.first].MIOperandInfo && + CGI.Operands[SO.first].MIOperandInfo->getNumArgs() > 1 && + String && String->getValue() != "") + NumberedInsnOperandsNoTie.insert(Name); } } // For each operand, see if we can figure out where it is encoded. for (std::vector<std::pair<Init*, std::string> >::const_iterator NI = InOutOperands.begin(), NE = InOutOperands.end(); NI != NE; ++NI) { + if (!NumberedInsnOperands[NI->second].empty()) { + InsnOperands.insert(InsnOperands.end(), + NumberedInsnOperands[NI->second].begin(), + NumberedInsnOperands[NI->second].end()); + continue; + } else if (!NumberedInsnOperands[TiedNames[NI->second]].empty()) { + if (!NumberedInsnOperandsNoTie.count(TiedNames[NI->second])) { + // Figure out to which (sub)operand we're tied. + unsigned i = CGI.Operands.getOperandNamed(TiedNames[NI->second]); + int tiedTo = CGI.Operands[i].getTiedRegister(); + if (tiedTo == -1) { + i = CGI.Operands.getOperandNamed(NI->second); + tiedTo = CGI.Operands[i].getTiedRegister(); + } + + if (tiedTo != -1) { + std::pair<unsigned, unsigned> SO = + CGI.Operands.getSubOperandNumber(tiedTo); + + InsnOperands.push_back(NumberedInsnOperands[TiedNames[NI->second]] + [SO.second]); + } + } + continue; + } + std::string Decoder = ""; // At this point, we can locate the field, but we need to know how to @@ -1771,6 +1930,10 @@ static bool populateInstruction(const CodeGenInstruction &CGI, unsigned Opc, if (TypeRecord->isSubClassOf("RegisterClass")) { Decoder = "Decode" + TypeRecord->getName() + "RegisterClass"; isReg = true; + } else if (TypeRecord->isSubClassOf("PointerLikeRegClass")) { + Decoder = "DecodePointerLikeRegClass" + + utostr(TypeRecord->getValueAsInt("RegClassKind")); + isReg = true; } RecordVal *DecoderString = TypeRecord->getValue("DecoderMethod"); @@ -2012,6 +2175,8 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) { emitFieldFromInstruction(OS); + Target.reverseBitsForLittleEndianEncoding(); + // Parameterize the decoders based on namespace and instruction width. NumberedInstructions = &Target.getInstructionsByEnumValue(); std::map<std::pair<std::string, unsigned>, @@ -2031,7 +2196,7 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) { std::string DecoderNamespace = Def->getValueAsString("DecoderNamespace"); if (Size) { - if (populateInstruction(*Inst, i, Operands)) { + if (populateInstruction(Target, *Inst, i, Operands)) { OpcMap[std::make_pair(DecoderNamespace, Size)].push_back(i); } } diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index d3d9cc1..7aa0f40 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -59,10 +59,10 @@ private: raw_ostream &OS); void emitOperandTypesEnum(raw_ostream &OS, const CodeGenTarget &Target); void initOperandMapData( - const std::vector<const CodeGenInstruction *> NumberedInstructions, - const std::string &Namespace, - std::map<std::string, unsigned> &Operands, - OpNameMapTy &OperandMap); + const std::vector<const CodeGenInstruction *> &NumberedInstructions, + const std::string &Namespace, + std::map<std::string, unsigned> &Operands, + OpNameMapTy &OperandMap); void emitOperandNameMappings(raw_ostream &OS, const CodeGenTarget &Target, const std::vector<const CodeGenInstruction*> &NumberedInstructions); @@ -200,7 +200,7 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS, /// each instructions. This is used to generate the OperandMap table as /// well as the getNamedOperandIdx() function. void InstrInfoEmitter::initOperandMapData( - const std::vector<const CodeGenInstruction *> NumberedInstructions, + const std::vector<const CodeGenInstruction *> &NumberedInstructions, const std::string &Namespace, std::map<std::string, unsigned> &Operands, OpNameMapTy &OperandMap) { diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index 8f137f8..7b0a2b6 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -131,20 +131,6 @@ void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints, OS << "#endif\n\n"; } -struct IntrinsicNameSorter { - IntrinsicNameSorter(const std::vector<CodeGenIntrinsic> &I) - : Ints(I) {} - - // Sort in reverse order of intrinsic name so "abc.def" appears after - // "abd.def.ghi" in the overridden name matcher - bool operator()(unsigned i, unsigned j) { - return Ints[i].Name > Ints[j].Name; - } - -private: - const std::vector<CodeGenIntrinsic> &Ints; -}; - void IntrinsicEmitter:: EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { @@ -158,15 +144,17 @@ EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints, OS << " StringRef NameR(Name+6, Len-6); // Skip over 'llvm.'\n"; OS << " switch (Name[5]) { // Dispatch on first letter.\n"; OS << " default: break;\n"; - IntrinsicNameSorter Sorter(Ints); // Emit the intrinsic matching stuff by first letter. for (std::map<char, std::vector<unsigned> >::iterator I = IntMapping.begin(), E = IntMapping.end(); I != E; ++I) { OS << " case '" << I->first << "':\n"; std::vector<unsigned> &IntList = I->second; - // Sort intrinsics in reverse order of their names - std::sort(IntList.begin(), IntList.end(), Sorter); + // Sort in reverse order of intrinsic name so "abc.def" appears after + // "abd.def.ghi" in the overridden name matcher + std::sort(IntList.begin(), IntList.end(), [&](unsigned i, unsigned j) { + return Ints[i].Name > Ints[j].Name; + }); // Emit all the overloaded intrinsics first, build a table of the // non-overloaded ones. @@ -258,18 +246,19 @@ enum IIT_Info { IIT_STRUCT3 = 20, IIT_STRUCT4 = 21, IIT_STRUCT5 = 22, - IIT_EXTEND_VEC_ARG = 23, - IIT_TRUNC_VEC_ARG = 24, + IIT_EXTEND_ARG = 23, + IIT_TRUNC_ARG = 24, IIT_ANYPTR = 25, IIT_V1 = 26, - IIT_VARARG = 27 + IIT_VARARG = 27, + IIT_HALF_VEC_ARG = 28 }; static void EncodeFixedValueType(MVT::SimpleValueType VT, std::vector<unsigned char> &Sig) { - if (EVT(VT).isInteger()) { - unsigned BitWidth = EVT(VT).getSizeInBits(); + if (MVT(VT).isInteger()) { + unsigned BitWidth = MVT(VT).getSizeInBits(); switch (BitWidth) { default: PrintFatalError("unhandled integer type width in intrinsic!"); case 1: return Sig.push_back(IIT_I1); @@ -304,10 +293,12 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, if (R->isSubClassOf("LLVMMatchType")) { unsigned Number = R->getValueAsInt("Number"); assert(Number < ArgCodes.size() && "Invalid matching number!"); - if (R->isSubClassOf("LLVMExtendedElementVectorType")) - Sig.push_back(IIT_EXTEND_VEC_ARG); - else if (R->isSubClassOf("LLVMTruncatedElementVectorType")) - Sig.push_back(IIT_TRUNC_VEC_ARG); + if (R->isSubClassOf("LLVMExtendedType")) + Sig.push_back(IIT_EXTEND_ARG); + else if (R->isSubClassOf("LLVMTruncatedType")) + Sig.push_back(IIT_TRUNC_ARG); + else if (R->isSubClassOf("LLVMHalfElementsVectorType")) + Sig.push_back(IIT_HALF_VEC_ARG); else Sig.push_back(IIT_ARG); return Sig.push_back((Number << 2) | ArgCodes[Number]); @@ -350,8 +341,8 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, } } - if (EVT(VT).isVector()) { - EVT VVT = VT; + if (MVT(VT).isVector()) { + MVT VVT = VT; switch (VVT.getVectorNumElements()) { default: PrintFatalError("unhandled vector type width in intrinsic!"); case 1: Sig.push_back(IIT_V1); break; @@ -362,8 +353,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes, case 32: Sig.push_back(IIT_V32); break; } - return EncodeFixedValueType(VVT.getVectorElementType(). - getSimpleVT().SimpleTy, Sig); + return EncodeFixedValueType(VVT.getVectorElementType().SimpleTy, Sig); } EncodeFixedValueType(VT, Sig); @@ -515,6 +505,9 @@ struct AttributeComparator { if (L->canThrow != R->canThrow) return R->canThrow; + if (L->isNoDuplicate != R->isNoDuplicate) + return R->isNoDuplicate; + if (L->isNoReturn != R->isNoReturn) return R->isNoReturn; @@ -629,7 +622,8 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { ModRefKind modRef = getModRefKind(intrinsic); - if (!intrinsic.canThrow || modRef || intrinsic.isNoReturn) { + if (!intrinsic.canThrow || modRef || intrinsic.isNoReturn || + intrinsic.isNoDuplicate) { OS << " const Attribute::AttrKind Atts[] = {"; bool addComma = false; if (!intrinsic.canThrow) { @@ -642,6 +636,12 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { OS << "Attribute::NoReturn"; addComma = true; } + if (intrinsic.isNoDuplicate) { + if (addComma) + OS << ","; + OS << "Attribute::NoDuplicate"; + addComma = true; + } switch (modRef) { case MRK_none: break; @@ -667,6 +667,7 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { OS << " }\n"; } else { OS << " return AttributeSet();\n"; + OS << " }\n"; } } diff --git a/utils/TableGen/OptParserEmitter.cpp b/utils/TableGen/OptParserEmitter.cpp index 9c4daaf..c5fd7ee 100644 --- a/utils/TableGen/OptParserEmitter.cpp +++ b/utils/TableGen/OptParserEmitter.cpp @@ -13,8 +13,8 @@ #include "llvm/ADT/Twine.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" -#include <cstring> #include <cctype> +#include <cstring> #include <map> using namespace llvm; diff --git a/utils/TableGen/PseudoLoweringEmitter.cpp b/utils/TableGen/PseudoLoweringEmitter.cpp index 1ea6f79..100338c 100644 --- a/utils/TableGen/PseudoLoweringEmitter.cpp +++ b/utils/TableGen/PseudoLoweringEmitter.cpp @@ -259,7 +259,7 @@ void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) { << " if (lowerOperand(MI->getOperand(i), MCOp))\n" << " TmpInst.addOperand(MCOp);\n"; } - o << " OutStreamer.EmitInstruction(TmpInst);\n" + o << " EmitToStreamer(OutStreamer, TmpInst);\n" << " break;\n" << " }\n"; } diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index cc08df9..61ae262 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -917,7 +917,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, uint64_t Value = 0; for (unsigned b = 0, be = BI->getNumBits(); b != be; ++b) { if (BitInit *B = dyn_cast<BitInit>(BI->getBit(b))) - Value |= (uint64_t)B->getValue() << b; + Value |= (uint64_t)B->getValue() << b; } OS << " " << Value << ",\n"; } @@ -965,23 +965,24 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, OS << "struct " << ClassName << " : public TargetRegisterInfo {\n" << " explicit " << ClassName << "(unsigned RA, unsigned D = 0, unsigned E = 0, unsigned PC = 0);\n" - << " virtual bool needsStackRealignment(const MachineFunction &) const\n" + << " bool needsStackRealignment(const MachineFunction &) const override\n" << " { return false; }\n"; if (!RegBank.getSubRegIndices().empty()) { - OS << " virtual unsigned composeSubRegIndicesImpl" - << "(unsigned, unsigned) const;\n" - << " virtual const TargetRegisterClass *" - "getSubClassWithSubReg(const TargetRegisterClass*, unsigned) const;\n"; + OS << " unsigned composeSubRegIndicesImpl" + << "(unsigned, unsigned) const override;\n" + << " const TargetRegisterClass *getSubClassWithSubReg" + << "(const TargetRegisterClass*, unsigned) const override;\n"; } - OS << " virtual const RegClassWeight &getRegClassWeight(" - << "const TargetRegisterClass *RC) const;\n" - << " virtual unsigned getRegUnitWeight(unsigned RegUnit) const;\n" - << " virtual unsigned getNumRegPressureSets() const;\n" - << " virtual const char *getRegPressureSetName(unsigned Idx) const;\n" - << " virtual unsigned getRegPressureSetLimit(unsigned Idx) const;\n" - << " virtual const int *getRegClassPressureSets(" - << "const TargetRegisterClass *RC) const;\n" - << " virtual const int *getRegUnitPressureSets(unsigned RegUnit) const;\n" + OS << " const RegClassWeight &getRegClassWeight(" + << "const TargetRegisterClass *RC) const override;\n" + << " unsigned getRegUnitWeight(unsigned RegUnit) const override;\n" + << " unsigned getNumRegPressureSets() const override;\n" + << " const char *getRegPressureSetName(unsigned Idx) const override;\n" + << " unsigned getRegPressureSetLimit(unsigned Idx) const override;\n" + << " const int *getRegClassPressureSets(" + << "const TargetRegisterClass *RC) const override;\n" + << " const int *getRegUnitPressureSets(" + << "unsigned RegUnit) const override;\n" << "};\n\n"; ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses(); diff --git a/utils/TableGen/SetTheory.cpp b/utils/TableGen/SetTheory.cpp index ad3d7c7..d952e68 100644 --- a/utils/TableGen/SetTheory.cpp +++ b/utils/TableGen/SetTheory.cpp @@ -27,16 +27,16 @@ typedef SetTheory::RecVec RecVec; // (add a, b, ...) Evaluate and union all arguments. struct AddOp : public SetTheory::Operator { - virtual void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, - ArrayRef<SMLoc> Loc) { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, + ArrayRef<SMLoc> Loc) override { ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts, Loc); } }; // (sub Add, Sub, ...) Set difference. struct SubOp : public SetTheory::Operator { - virtual void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, - ArrayRef<SMLoc> Loc) { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, + ArrayRef<SMLoc> Loc) override { if (Expr->arg_size() < 2) PrintFatalError(Loc, "Set difference needs at least two arguments: " + Expr->getAsString()); @@ -51,8 +51,8 @@ struct SubOp : public SetTheory::Operator { // (and S1, S2) Set intersection. struct AndOp : public SetTheory::Operator { - virtual void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, - ArrayRef<SMLoc> Loc) { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, + ArrayRef<SMLoc> Loc) override { if (Expr->arg_size() != 2) PrintFatalError(Loc, "Set intersection requires two arguments: " + Expr->getAsString()); @@ -67,12 +67,11 @@ struct AndOp : public SetTheory::Operator { // SetIntBinOp - Abstract base class for (Op S, N) operators. struct SetIntBinOp : public SetTheory::Operator { - virtual void apply2(SetTheory &ST, DagInit *Expr, - RecSet &Set, int64_t N, - RecSet &Elts, ArrayRef<SMLoc> Loc) =0; + virtual void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, + RecSet &Elts, ArrayRef<SMLoc> Loc) = 0; - virtual void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, - ArrayRef<SMLoc> Loc) { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, + ArrayRef<SMLoc> Loc) override { if (Expr->arg_size() != 2) PrintFatalError(Loc, "Operator requires (Op Set, Int) arguments: " + Expr->getAsString()); @@ -88,9 +87,8 @@ struct SetIntBinOp : public SetTheory::Operator { // (shl S, N) Shift left, remove the first N elements. struct ShlOp : public SetIntBinOp { - virtual void apply2(SetTheory &ST, DagInit *Expr, - RecSet &Set, int64_t N, - RecSet &Elts, ArrayRef<SMLoc> Loc) { + void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, + RecSet &Elts, ArrayRef<SMLoc> Loc) override { if (N < 0) PrintFatalError(Loc, "Positive shift required: " + Expr->getAsString()); @@ -101,9 +99,8 @@ struct ShlOp : public SetIntBinOp { // (trunc S, N) Truncate after the first N elements. struct TruncOp : public SetIntBinOp { - virtual void apply2(SetTheory &ST, DagInit *Expr, - RecSet &Set, int64_t N, - RecSet &Elts, ArrayRef<SMLoc> Loc) { + void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, + RecSet &Elts, ArrayRef<SMLoc> Loc) override { if (N < 0) PrintFatalError(Loc, "Positive length required: " + Expr->getAsString()); @@ -119,9 +116,8 @@ struct RotOp : public SetIntBinOp { RotOp(bool Rev) : Reverse(Rev) {} - virtual void apply2(SetTheory &ST, DagInit *Expr, - RecSet &Set, int64_t N, - RecSet &Elts, ArrayRef<SMLoc> Loc) { + void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, + RecSet &Elts, ArrayRef<SMLoc> Loc) override { if (Reverse) N = -N; // N > 0 -> rotate left, N < 0 -> rotate right. @@ -138,9 +134,8 @@ struct RotOp : public SetIntBinOp { // (decimate S, N) Pick every N'th element of S. struct DecimateOp : public SetIntBinOp { - virtual void apply2(SetTheory &ST, DagInit *Expr, - RecSet &Set, int64_t N, - RecSet &Elts, ArrayRef<SMLoc> Loc) { + void apply2(SetTheory &ST, DagInit *Expr, RecSet &Set, int64_t N, + RecSet &Elts, ArrayRef<SMLoc> Loc) override { if (N <= 0) PrintFatalError(Loc, "Positive stride required: " + Expr->getAsString()); @@ -151,8 +146,8 @@ struct DecimateOp : public SetIntBinOp { // (interleave S1, S2, ...) Interleave elements of the arguments. struct InterleaveOp : public SetTheory::Operator { - virtual void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, - ArrayRef<SMLoc> Loc) { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, + ArrayRef<SMLoc> Loc) override { // Evaluate the arguments individually. SmallVector<RecSet, 4> Args(Expr->getNumArgs()); unsigned MaxSize = 0; @@ -170,8 +165,8 @@ struct InterleaveOp : public SetTheory::Operator { // (sequence "Format", From, To) Generate a sequence of records by name. struct SequenceOp : public SetTheory::Operator { - virtual void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, - ArrayRef<SMLoc> Loc) { + void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, + ArrayRef<SMLoc> Loc) override { int Step = 1; if (Expr->arg_size() > 4) PrintFatalError(Loc, "Bad args to (sequence \"Format\", From, To): " + @@ -238,7 +233,7 @@ struct FieldExpander : public SetTheory::Expander { FieldExpander(StringRef fn) : FieldName(fn) {} - virtual void expand(SetTheory &ST, Record *Def, RecSet &Elts) { + void expand(SetTheory &ST, Record *Def, RecSet &Elts) override { ST.evaluate(Def->getValueInit(FieldName), Elts, Def->getLoc()); } }; diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index b9f9d06..71301aa 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -1498,7 +1498,7 @@ void SubtargetEmitter::run(raw_ostream &OS) { << "StringRef FS);\n" << "public:\n" << " unsigned resolveSchedClass(unsigned SchedClass, const MachineInstr *DefMI," - << " const TargetSchedModel *SchedModel) const;\n" + << " const TargetSchedModel *SchedModel) const override;\n" << " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)" << " const;\n" << "};\n"; diff --git a/utils/TableGen/TGValueTypes.cpp b/utils/TableGen/TGValueTypes.cpp deleted file mode 100644 index f4893f5..0000000 --- a/utils/TableGen/TGValueTypes.cpp +++ /dev/null @@ -1,128 +0,0 @@ -//===- ValueTypes.cpp - Tablegen extended ValueType implementation --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// The EVT type is used by tablegen as well as in LLVM. In order to handle -// extended types, the EVT type uses support functions that call into -// LLVM's type system code. These aren't accessible in tablegen, so this -// file provides simple replacements. -// -//===----------------------------------------------------------------------===// - -#include "llvm/CodeGen/ValueTypes.h" -#include "llvm/Support/Casting.h" -#include <map> -using namespace llvm; - -namespace llvm { - -class Type { -protected: - enum TypeKind { - TK_ExtendedIntegerType, - TK_ExtendedVectorType - }; -private: - TypeKind Kind; -public: - TypeKind getKind() const { - return Kind; - } - Type(TypeKind K) : Kind(K) {} - virtual unsigned getSizeInBits() const = 0; - virtual ~Type(); -}; - -// Provide out-of-line definition to prevent weak vtable. -Type::~Type() {} - -} - -namespace { -class ExtendedIntegerType : public Type { - unsigned BitWidth; -public: - explicit ExtendedIntegerType(unsigned bits) - : Type(TK_ExtendedIntegerType), BitWidth(bits) {} - static bool classof(const Type *T) { - return T->getKind() == TK_ExtendedIntegerType; - } - virtual unsigned getSizeInBits() const { - return getBitWidth(); - } - unsigned getBitWidth() const { - return BitWidth; - } -}; - -class ExtendedVectorType : public Type { - EVT ElementType; - unsigned NumElements; -public: - ExtendedVectorType(EVT elty, unsigned num) - : Type(TK_ExtendedVectorType), ElementType(elty), NumElements(num) {} - static bool classof(const Type *T) { - return T->getKind() == TK_ExtendedVectorType; - } - virtual unsigned getSizeInBits() const { - return getNumElements() * getElementType().getSizeInBits(); - } - EVT getElementType() const { - return ElementType; - } - unsigned getNumElements() const { - return NumElements; - } -}; -} // end anonymous namespace - -static std::map<unsigned, const Type *> - ExtendedIntegerTypeMap; -static std::map<std::pair<uintptr_t, uintptr_t>, const Type *> - ExtendedVectorTypeMap; - -bool EVT::isExtendedFloatingPoint() const { - assert(isExtended() && "Type is not extended!"); - // Extended floating-point types are not supported yet. - return false; -} - -bool EVT::isExtendedInteger() const { - assert(isExtended() && "Type is not extended!"); - return isa<ExtendedIntegerType>(LLVMTy); -} - -bool EVT::isExtendedVector() const { - assert(isExtended() && "Type is not extended!"); - return isa<ExtendedVectorType>(LLVMTy); -} - -bool EVT::isExtended64BitVector() const { - assert(isExtended() && "Type is not extended!"); - return isExtendedVector() && getSizeInBits() == 64; -} - -bool EVT::isExtended128BitVector() const { - assert(isExtended() && "Type is not extended!"); - return isExtendedVector() && getSizeInBits() == 128; -} - -EVT EVT::getExtendedVectorElementType() const { - assert(isExtendedVector() && "Type is not an extended vector!"); - return static_cast<const ExtendedVectorType *>(LLVMTy)->getElementType(); -} - -unsigned EVT::getExtendedVectorNumElements() const { - assert(isExtendedVector() && "Type is not an extended vector!"); - return static_cast<const ExtendedVectorType *>(LLVMTy)->getNumElements(); -} - -unsigned EVT::getExtendedSizeInBits() const { - assert(isExtended() && "Type is not extended!"); - return LLVMTy->getSizeInBits(); -} diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index b5c3ca7..00c3a6f 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -180,3 +180,12 @@ int main(int argc, char **argv) { return TableGenMain(argv[0], &LLVMTableGenMain); } + +#ifdef __has_feature +#if __has_feature(address_sanitizer) +#include <sanitizer/lsan_interface.h> +// Disable LeakSanitizer for this binary as it has too many leaks that are not +// very interesting to fix. See compiler-rt/include/sanitizer/lsan_interface.h . +int __lsan_is_turned_off() { return 1; } +#endif // __has_feature(address_sanitizer) +#endif // defined(__has_feature) diff --git a/utils/TableGen/X86DisassemblerShared.h b/utils/TableGen/X86DisassemblerShared.h index 3ff922b..036e924 100644 --- a/utils/TableGen/X86DisassemblerShared.h +++ b/utils/TableGen/X86DisassemblerShared.h @@ -15,16 +15,12 @@ #define INSTRUCTION_SPECIFIER_FIELDS \ struct OperandSpecifier operands[X86_MAX_OPERANDS]; \ - bool filtered; \ InstructionContext insnContext; \ std::string name; \ \ InstructionSpecifier() { \ - filtered = false; \ insnContext = IC; \ name = ""; \ - modifierType = MODIFIER_NONE; \ - modifierBase = 0; \ memset(operands, 0, sizeof(operands)); \ } diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp index bdb4793..fbcc6f2 100644 --- a/utils/TableGen/X86DisassemblerTables.cpp +++ b/utils/TableGen/X86DisassemblerTables.cpp @@ -19,12 +19,54 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" -#include "llvm/TableGen/TableGenBackend.h" #include <map> using namespace llvm; using namespace X86Disassembler; +/// stringForContext - Returns a string containing the name of a particular +/// InstructionContext, usually for diagnostic purposes. +/// +/// @param insnContext - The instruction class to transform to a string. +/// @return - A statically-allocated string constant that contains the +/// name of the instruction class. +static inline const char* stringForContext(InstructionContext insnContext) { + switch (insnContext) { + default: + llvm_unreachable("Unhandled instruction class"); +#define ENUM_ENTRY(n, r, d) case n: return #n; break; +#define ENUM_ENTRY_K_B(n, r, d) ENUM_ENTRY(n, r, d) ENUM_ENTRY(n##_K_B, r, d)\ + ENUM_ENTRY(n##_KZ, r, d) ENUM_ENTRY(n##_K, r, d) ENUM_ENTRY(n##_B, r, d)\ + ENUM_ENTRY(n##_KZ_B, r, d) + INSTRUCTION_CONTEXTS +#undef ENUM_ENTRY +#undef ENUM_ENTRY_K_B + } +} + +/// stringForOperandType - Like stringForContext, but for OperandTypes. +static inline const char* stringForOperandType(OperandType type) { + switch (type) { + default: + llvm_unreachable("Unhandled type"); +#define ENUM_ENTRY(i, d) case i: return #i; + TYPES +#undef ENUM_ENTRY + } +} + +/// stringForOperandEncoding - like stringForContext, but for +/// OperandEncodings. +static inline const char* stringForOperandEncoding(OperandEncoding encoding) { + switch (encoding) { + default: + llvm_unreachable("Unhandled encoding"); +#define ENUM_ENTRY(i, d) case i: return #i; + ENCODINGS +#undef ENUM_ENTRY + } +} + /// inheritsFrom - Indicates whether all instructions in one class also belong /// to another class. /// @@ -164,12 +206,13 @@ static inline bool inheritsFrom(InstructionContext child, return inheritsFrom(child, IC_EVEX_W_XD_K) || inheritsFrom(child, IC_EVEX_L_W_XD_K); case IC_EVEX_OPSIZE_K: - return inheritsFrom(child, IC_EVEX_W_OPSIZE_K) || - inheritsFrom(child, IC_EVEX_W_OPSIZE_K); + case IC_EVEX_OPSIZE_B: + return false; case IC_EVEX_W_K: case IC_EVEX_W_XS_K: case IC_EVEX_W_XD_K: case IC_EVEX_W_OPSIZE_K: + case IC_EVEX_W_OPSIZE_B: return false; case IC_EVEX_L_K: case IC_EVEX_L_XS_K: @@ -197,7 +240,11 @@ static inline bool inheritsFrom(InstructionContext child, return false; case IC_EVEX_L2_K: case IC_EVEX_L2_B: + case IC_EVEX_L2_K_B: + case IC_EVEX_L2_KZ_B: case IC_EVEX_L2_XS_K: + case IC_EVEX_L2_XS_B: + case IC_EVEX_L2_XD_B: case IC_EVEX_L2_XD_K: case IC_EVEX_L2_OPSIZE_K: case IC_EVEX_L2_OPSIZE_B: @@ -212,6 +259,7 @@ static inline bool inheritsFrom(InstructionContext child, case IC_EVEX_L2_W_B: case IC_EVEX_L2_W_XS_K: case IC_EVEX_L2_W_XD_K: + case IC_EVEX_L2_W_XD_B: case IC_EVEX_L2_W_OPSIZE_K: case IC_EVEX_L2_W_OPSIZE_B: case IC_EVEX_L2_W_OPSIZE_K_B: @@ -222,6 +270,8 @@ static inline bool inheritsFrom(InstructionContext child, case IC_EVEX_L2_W_OPSIZE_KZ_B: return false; default: + errs() << "Unknown instruction class: " << + stringForContext((InstructionContext)parent) << "\n"; llvm_unreachable("Unknown instruction class"); } } @@ -251,49 +301,6 @@ static inline bool outranks(InstructionContext upper, return (ranks[upper] > ranks[lower]); } -/// stringForContext - Returns a string containing the name of a particular -/// InstructionContext, usually for diagnostic purposes. -/// -/// @param insnContext - The instruction class to transform to a string. -/// @return - A statically-allocated string constant that contains the -/// name of the instruction class. -static inline const char* stringForContext(InstructionContext insnContext) { - switch (insnContext) { - default: - llvm_unreachable("Unhandled instruction class"); -#define ENUM_ENTRY(n, r, d) case n: return #n; break; -#define ENUM_ENTRY_K_B(n, r, d) ENUM_ENTRY(n, r, d) ENUM_ENTRY(n##_K_B, r, d)\ - ENUM_ENTRY(n##_KZ, r, d) ENUM_ENTRY(n##_K, r, d) ENUM_ENTRY(n##_B, r, d)\ - ENUM_ENTRY(n##_KZ_B, r, d) - INSTRUCTION_CONTEXTS -#undef ENUM_ENTRY -#undef ENUM_ENTRY_K_B - } -} - -/// stringForOperandType - Like stringForContext, but for OperandTypes. -static inline const char* stringForOperandType(OperandType type) { - switch (type) { - default: - llvm_unreachable("Unhandled type"); -#define ENUM_ENTRY(i, d) case i: return #i; - TYPES -#undef ENUM_ENTRY - } -} - -/// stringForOperandEncoding - like stringForContext, but for -/// OperandEncodings. -static inline const char* stringForOperandEncoding(OperandEncoding encoding) { - switch (encoding) { - default: - llvm_unreachable("Unhandled encoding"); -#define ENUM_ENTRY(i, d) case i: return #i; - ENCODINGS -#undef ENUM_ENTRY - } -} - /// getDecisionType - Determines whether a ModRM decision with 255 entries can /// be compacted by eliminating redundant information. /// @@ -357,22 +364,6 @@ static const char* stringForDecisionType(ModRMDecisionType dt) { #undef ENUM_ENTRY } -/// stringForModifierType - Returns a statically-allocated string corresponding -/// to an opcode modifier type. -/// -/// @param mt - The modifier type. -/// @return - A pointer to the statically-allocated string (e.g., -/// "MODIFIER_NONE" for MODIFIER_NONE). -static const char* stringForModifierType(ModifierType mt) { -#define ENUM_ENTRY(n) case n: return #n; - switch(mt) { - default: - llvm_unreachable("Unknown modifier type"); - MODIFIER_TYPES - }; -#undef ENUM_ENTRY -} - DisassemblerTables::DisassemblerTables() { unsigned i; @@ -598,14 +589,6 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o, o.indent(i * 2) << "{ /* " << index << " */" << "\n"; i++; - o.indent(i * 2) << stringForModifierType( - (ModifierType)InstructionSpecifiers[index].modifierType); - o << ",\n"; - - o.indent(i * 2) << "0x"; - o << format("%02hhx", (uint16_t)InstructionSpecifiers[index].modifierBase); - o << ",\n"; - OperandListTy OperandList; for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS; ++OperandIndex) { @@ -636,14 +619,36 @@ void DisassemblerTables::emitInstructionInfo(raw_ostream &o, } void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const { + const unsigned int tableSize = 16384; o.indent(i * 2) << "static const uint8_t " CONTEXTS_STR - "[256] = {\n"; + "[" << tableSize << "] = {\n"; i++; - for (unsigned index = 0; index < 256; ++index) { + for (unsigned index = 0; index < tableSize; ++index) { o.indent(i * 2); - if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_OPSIZE)) + if (index & ATTR_EVEX) { + o << "IC_EVEX"; + if (index & ATTR_EVEXL2) + o << "_L2"; + else if (index & ATTR_EVEXL) + o << "_L"; + if (index & ATTR_REXW) + o << "_W"; + if (index & ATTR_OPSIZE) + o << "_OPSIZE"; + else if (index & ATTR_XD) + o << "_XD"; + else if (index & ATTR_XS) + o << "_XS"; + if (index & ATTR_EVEXKZ) + o << "_KZ"; + else if (index & ATTR_EVEXK) + o << "_K"; + if (index & ATTR_EVEXB) + o << "_B"; + } + else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_OPSIZE)) o << "IC_VEX_L_W_OPSIZE"; else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_XD)) o << "IC_VEX_L_W_XD"; @@ -713,7 +718,7 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const { else o << "IC"; - if (index < 255) + if (index < tableSize - 1) o << ","; else o << " "; @@ -734,11 +739,9 @@ void DisassemblerTables::emitContextDecisions(raw_ostream &o1, raw_ostream &o2, emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[1], TWOBYTE_STR); emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[2], THREEBYTE38_STR); emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[3], THREEBYTE3A_STR); - emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[4], THREEBYTEA6_STR); - emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[5], THREEBYTEA7_STR); - emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[6], XOP8_MAP_STR); - emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[7], XOP9_MAP_STR); - emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[8], XOPA_MAP_STR); + emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[4], XOP8_MAP_STR); + emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[5], XOP9_MAP_STR); + emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[6], XOPA_MAP_STR); } void DisassemblerTables::emit(raw_ostream &o) const { @@ -793,8 +796,14 @@ void DisassemblerTables::setTableFields(ModRMDecision &decision, InstructionSpecifier &previousInfo = InstructionSpecifiers[decision.instructionIDs[index]]; - if(newInfo.filtered) - continue; // filtered instructions get lowest priority + // Instructions such as MOV8ao8 and MOV8ao8_16 differ only in the + // presence of the AdSize prefix. However, the disassembler doesn't + // care about that difference in the instruction definition; it + // handles 16-bit vs. 32-bit addressing for itself based purely + // on the 0x67 prefix and the CPU mode. So there's no need to + // disambiguate between them; just let them conflict/coexist. + if (previousInfo.name + "_16" == newInfo.name) + continue; if(previousInfo.name == "NOOP" && (newInfo.name == "XCHG16ar" || newInfo.name == "XCHG32ar" || @@ -805,8 +814,7 @@ void DisassemblerTables::setTableFields(ModRMDecision &decision, if (outranks(previousInfo.insnContext, newInfo.insnContext)) continue; - if (previousInfo.insnContext == newInfo.insnContext && - !previousInfo.filtered) { + if (previousInfo.insnContext == newInfo.insnContext) { errs() << "Error: Primary decode conflict: "; errs() << newInfo.name << " would overwrite " << previousInfo.name; errs() << "\n"; diff --git a/utils/TableGen/X86DisassemblerTables.h b/utils/TableGen/X86DisassemblerTables.h index bf8b127..1327375 100644 --- a/utils/TableGen/X86DisassemblerTables.h +++ b/utils/TableGen/X86DisassemblerTables.h @@ -38,12 +38,10 @@ private: /// [1] two-byte opcodes of the form 0f __ /// [2] three-byte opcodes of the form 0f 38 __ /// [3] three-byte opcodes of the form 0f 3a __ - /// [4] three-byte opcodes of the form 0f a6 __ - /// [5] three-byte opcodes of the form 0f a7 __ - /// [6] XOP8 map opcode - /// [7] XOP9 map opcode - /// [8] XOPA map opcode - ContextDecision* Tables[9]; + /// [4] XOP8 map opcode + /// [5] XOP9 map opcode + /// [6] XOPA map opcode + ContextDecision* Tables[7]; // Table of ModRM encodings. typedef std::map<std::vector<unsigned>, unsigned> ModRMMapTy; @@ -132,8 +130,7 @@ private: /// } /// /// NAME is the name of the ContextDecision (typically one of the four names - /// ONEBYTE_SYM, TWOBYTE_SYM, THREEBYTE38_SYM, THREEBYTE3A_SYM, - /// THREEBYTEA6_SYM, and THREEBYTEA7_SYM from + /// ONEBYTE_SYM, TWOBYTE_SYM, THREEBYTE38_SYM, THREEBYTE3A_SYM from /// X86DisassemblerDecoderCommon.h). /// IC is one of the contexts in InstructionContext. There is an opcode /// decision for each possible context. diff --git a/utils/TableGen/X86ModRMFilters.cpp b/utils/TableGen/X86ModRMFilters.cpp index 7166fe0..1641613 100644 --- a/utils/TableGen/X86ModRMFilters.cpp +++ b/utils/TableGen/X86ModRMFilters.cpp @@ -17,10 +17,6 @@ void DumbFilter::anchor() { } void ModFilter::anchor() { } -void EscapeFilter::anchor() { } - -void AddRegEscapeFilter::anchor() { } - void ExtendedFilter::anchor() { } void ExactFilter::anchor() { } diff --git a/utils/TableGen/X86ModRMFilters.h b/utils/TableGen/X86ModRMFilters.h index 2cbaf79..fac3838 100644 --- a/utils/TableGen/X86ModRMFilters.h +++ b/utils/TableGen/X86ModRMFilters.h @@ -50,13 +50,13 @@ public: /// require a ModR/M byte or instructions where the entire ModR/M byte is used /// for operands. class DumbFilter : public ModRMFilter { - virtual void anchor(); + void anchor() override; public: - bool isDumb() const { + bool isDumb() const override { return true; } - - bool accepts(uint8_t modRM) const { + + bool accepts(uint8_t modRM) const override { return true; } }; @@ -65,7 +65,7 @@ public: /// Some instructions are classified based on whether they are 11 or anything /// else. This filter performs that classification. class ModFilter : public ModRMFilter { - virtual void anchor(); + void anchor() override; bool R; public: /// Constructor @@ -78,74 +78,16 @@ public: ModRMFilter(), R(r) { } - - bool accepts(uint8_t modRM) const { - if (R == ((modRM & 0xc0) == 0xc0)) - return true; - else - return false; - } -}; -/// EscapeFilter - Filters escape opcodes, which are classified in two ways. If -/// the ModR/M byte is between 0xc0 and 0xff, then there is one slot for each -/// possible value. Otherwise, there is one instruction for each value of the -/// nnn field [bits 5-3], known elsewhere as the reg field. -class EscapeFilter : public ModRMFilter { - virtual void anchor(); - bool C0_FF; - uint8_t NNN_or_ModRM; -public: - /// Constructor - /// - /// \param c0_ff True if the ModR/M byte must fall between 0xc0 and 0xff; - /// false otherwise. - /// - /// \param nnn_or_modRM If c0_ff is true, the required value of the entire - /// ModR/M byte. If c0_ff is false, the required value - /// of the nnn field. - EscapeFilter(bool c0_ff, uint8_t nnn_or_modRM) : - ModRMFilter(), - C0_FF(c0_ff), - NNN_or_ModRM(nnn_or_modRM) { - } - - bool accepts(uint8_t modRM) const { - if ((C0_FF && modRM >= 0xc0 && (modRM == NNN_or_ModRM)) || - (!C0_FF && modRM < 0xc0 && ((modRM & 0x38) >> 3) == NNN_or_ModRM)) - return true; - else - return false; - } -}; - -/// AddRegEscapeFilter - Some escape opcodes have one of the register operands -/// added to the ModR/M byte, meaning that a range of eight ModR/M values -/// maps to a single instruction. Such instructions require the ModR/M byte -/// to fall between 0xc0 and 0xff. -class AddRegEscapeFilter : public ModRMFilter { - virtual void anchor(); - uint8_t ModRM; -public: - /// Constructor - /// - /// \param modRM The value of the ModR/M byte when the register operand - /// refers to the first register in the register set. - AddRegEscapeFilter(uint8_t modRM) : ModRM(modRM) { - } - - bool accepts(uint8_t modRM) const { - if (modRM >= ModRM && modRM < ModRM + 8) - return true; - else - return false; + bool accepts(uint8_t modRM) const override { + return (R == ((modRM & 0xc0) == 0xc0)); } }; /// ExtendedFilter - Extended opcodes are classified based on the value of the /// mod field [bits 7-6] and the value of the nnn field [bits 5-3]. class ExtendedFilter : public ModRMFilter { - virtual void anchor(); + void anchor() override; bool R; uint8_t NNN; public: @@ -159,21 +101,18 @@ public: R(r), NNN(nnn) { } - - bool accepts(uint8_t modRM) const { - if (((R && ((modRM & 0xc0) == 0xc0)) || - (!R && ((modRM & 0xc0) != 0xc0))) && - (((modRM & 0x38) >> 3) == NNN)) - return true; - else - return false; + + bool accepts(uint8_t modRM) const override { + return (((R && ((modRM & 0xc0) == 0xc0)) || + (!R && ((modRM & 0xc0) != 0xc0))) && + (((modRM & 0x38) >> 3) == NNN)); } }; /// ExactFilter - The occasional extended opcode (such as VMCALL or MONITOR) /// requires the ModR/M byte to have a specific value. class ExactFilter : public ModRMFilter { - virtual void anchor(); + void anchor() override; uint8_t ModRM; public: /// Constructor @@ -183,12 +122,9 @@ public: ModRMFilter(), ModRM(modRM) { } - - bool accepts(uint8_t modRM) const { - if (ModRM == modRM) - return true; - else - return false; + + bool accepts(uint8_t modRM) const override { + return (ModRM == modRM); } }; diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index 708e72d..95651f6 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -23,6 +23,7 @@ using namespace llvm; #define MRM_MAPPING \ + MAP(C0, 32) \ MAP(C1, 33) \ MAP(C2, 34) \ MAP(C3, 35) \ @@ -31,23 +32,48 @@ using namespace llvm; MAP(C9, 38) \ MAP(CA, 39) \ MAP(CB, 40) \ - MAP(E8, 41) \ - MAP(F0, 42) \ - MAP(F8, 45) \ - MAP(F9, 46) \ - MAP(D0, 47) \ - MAP(D1, 48) \ - MAP(D4, 49) \ - MAP(D5, 50) \ - MAP(D6, 51) \ - MAP(D8, 52) \ - MAP(D9, 53) \ - MAP(DA, 54) \ - MAP(DB, 55) \ - MAP(DC, 56) \ - MAP(DD, 57) \ - MAP(DE, 58) \ - MAP(DF, 59) + MAP(D0, 41) \ + MAP(D1, 42) \ + MAP(D4, 43) \ + MAP(D5, 44) \ + MAP(D6, 45) \ + MAP(D8, 46) \ + MAP(D9, 47) \ + MAP(DA, 48) \ + MAP(DB, 49) \ + MAP(DC, 50) \ + MAP(DD, 51) \ + MAP(DE, 52) \ + MAP(DF, 53) \ + MAP(E0, 54) \ + MAP(E1, 55) \ + MAP(E2, 56) \ + MAP(E3, 57) \ + MAP(E4, 58) \ + MAP(E5, 59) \ + MAP(E8, 60) \ + MAP(E9, 61) \ + MAP(EA, 62) \ + MAP(EB, 63) \ + MAP(EC, 64) \ + MAP(ED, 65) \ + MAP(EE, 66) \ + MAP(F0, 67) \ + MAP(F1, 68) \ + MAP(F2, 69) \ + MAP(F3, 70) \ + MAP(F4, 71) \ + MAP(F5, 72) \ + MAP(F6, 73) \ + MAP(F7, 74) \ + MAP(F8, 75) \ + MAP(F9, 76) \ + MAP(FA, 77) \ + MAP(FB, 78) \ + MAP(FC, 79) \ + MAP(FD, 80) \ + MAP(FE, 81) \ + MAP(FF, 82) // A clone of X86 since we can't depend on something that is generated. namespace X86Local { @@ -59,13 +85,17 @@ namespace X86Local { MRMDestMem = 4, MRMSrcReg = 5, MRMSrcMem = 6, + RawFrmMemOffs = 7, + RawFrmSrc = 8, + RawFrmDst = 9, + RawFrmDstSrc = 10, + RawFrmImm8 = 11, + RawFrmImm16 = 12, + MRMXr = 14, MRMXm = 15, MRM0r = 16, MRM1r = 17, MRM2r = 18, MRM3r = 19, MRM4r = 20, MRM5r = 21, MRM6r = 22, MRM7r = 23, MRM0m = 24, MRM1m = 25, MRM2m = 26, MRM3m = 27, MRM4m = 28, MRM5m = 29, MRM6m = 30, MRM7m = 31, - MRMInitReg = 32, - RawFrmImm8 = 43, - RawFrmImm16 = 44, #define MAP(from, to) MRM_##from = to, MRM_MAPPING #undef MAP @@ -73,94 +103,24 @@ namespace X86Local { }; enum { - TB = 1, - REP = 2, - D8 = 3, D9 = 4, DA = 5, DB = 6, - DC = 7, DD = 8, DE = 9, DF = 10, - XD = 11, XS = 12, - T8 = 13, P_TA = 14, - A6 = 15, A7 = 16, T8XD = 17, T8XS = 18, TAXD = 19, - XOP8 = 20, XOP9 = 21, XOPA = 22 + OB = 0, TB = 1, T8 = 2, TA = 3, XOP8 = 4, XOP9 = 5, XOPA = 6 }; -} -// If rows are added to the opcode extension tables, then corresponding entries -// must be added here. -// -// If the row corresponds to a single byte (i.e., 8f), then add an entry for -// that byte to ONE_BYTE_EXTENSION_TABLES. -// -// If the row corresponds to two bytes where the first is 0f, add an entry for -// the second byte to TWO_BYTE_EXTENSION_TABLES. -// -// If the row corresponds to some other set of bytes, you will need to modify -// the code in RecognizableInstr::emitDecodePath() as well, and add new prefixes -// to the X86 TD files, except in two cases: if the first two bytes of such a -// new combination are 0f 38 or 0f 3a, you just have to add maps called -// THREE_BYTE_38_EXTENSION_TABLES and THREE_BYTE_3A_EXTENSION_TABLES and add a -// switch(Opcode) just below the case X86Local::T8: or case X86Local::TA: line -// in RecognizableInstr::emitDecodePath(). - -#define ONE_BYTE_EXTENSION_TABLES \ - EXTENSION_TABLE(80) \ - EXTENSION_TABLE(81) \ - EXTENSION_TABLE(82) \ - EXTENSION_TABLE(83) \ - EXTENSION_TABLE(8f) \ - EXTENSION_TABLE(c0) \ - EXTENSION_TABLE(c1) \ - EXTENSION_TABLE(c6) \ - EXTENSION_TABLE(c7) \ - EXTENSION_TABLE(d0) \ - EXTENSION_TABLE(d1) \ - EXTENSION_TABLE(d2) \ - EXTENSION_TABLE(d3) \ - EXTENSION_TABLE(f6) \ - EXTENSION_TABLE(f7) \ - EXTENSION_TABLE(fe) \ - EXTENSION_TABLE(ff) - -#define TWO_BYTE_EXTENSION_TABLES \ - EXTENSION_TABLE(00) \ - EXTENSION_TABLE(01) \ - EXTENSION_TABLE(0d) \ - EXTENSION_TABLE(18) \ - EXTENSION_TABLE(71) \ - EXTENSION_TABLE(72) \ - EXTENSION_TABLE(73) \ - EXTENSION_TABLE(ae) \ - EXTENSION_TABLE(ba) \ - EXTENSION_TABLE(c7) - -#define THREE_BYTE_38_EXTENSION_TABLES \ - EXTENSION_TABLE(F3) - -#define XOP9_MAP_EXTENSION_TABLES \ - EXTENSION_TABLE(01) \ - EXTENSION_TABLE(02) + enum { + PS = 1, PD = 2, XS = 3, XD = 4 + }; -using namespace X86Disassembler; + enum { + VEX = 1, XOP = 2, EVEX = 3 + }; -/// needsModRMForDecode - Indicates whether a particular instruction requires a -/// ModR/M byte for the instruction to be properly decoded. For example, a -/// MRMDestReg instruction needs the Mod field in the ModR/M byte to be set to -/// 0b11. -/// -/// @param form - The form of the instruction. -/// @return - true if the form implies that a ModR/M byte is required, false -/// otherwise. -static bool needsModRMForDecode(uint8_t form) { - if (form == X86Local::MRMDestReg || - form == X86Local::MRMDestMem || - form == X86Local::MRMSrcReg || - form == X86Local::MRMSrcMem || - (form >= X86Local::MRM0r && form <= X86Local::MRM7r) || - (form >= X86Local::MRM0m && form <= X86Local::MRM7m)) - return true; - else - return false; + enum { + OpSize16 = 1, OpSize32 = 2 + }; } +using namespace X86Disassembler; + /// isRegFormat - Indicates whether a particular form requires the Mod field of /// the ModR/M byte to be 0b11. /// @@ -168,12 +128,10 @@ static bool needsModRMForDecode(uint8_t form) { /// @return - true if the form implies that Mod must be 0b11, false /// otherwise. static bool isRegFormat(uint8_t form) { - if (form == X86Local::MRMDestReg || - form == X86Local::MRMSrcReg || - (form >= X86Local::MRM0r && form <= X86Local::MRM7r)) - return true; - else - return false; + return (form == X86Local::MRMDestReg || + form == X86Local::MRMSrcReg || + form == X86Local::MRMXr || + (form >= X86Local::MRM0r && form <= X86Local::MRM7r)); } /// byteFromBitsInit - Extracts a value at most 8 bits in width from a BitsInit. @@ -227,36 +185,32 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, return; } - Prefix = byteFromRec(Rec, "Prefix"); + OpPrefix = byteFromRec(Rec, "OpPrefixBits"); + OpMap = byteFromRec(Rec, "OpMapBits"); Opcode = byteFromRec(Rec, "Opcode"); Form = byteFromRec(Rec, "FormBits"); - SegOvr = byteFromRec(Rec, "SegOvrBits"); + Encoding = byteFromRec(Rec, "OpEncBits"); - HasOpSizePrefix = Rec->getValueAsBit("hasOpSizePrefix"); + OpSize = byteFromRec(Rec, "OpSizeBits"); HasAdSizePrefix = Rec->getValueAsBit("hasAdSizePrefix"); HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix"); - HasVEXPrefix = Rec->getValueAsBit("hasVEXPrefix"); - HasVEX_4VPrefix = Rec->getValueAsBit("hasVEX_4VPrefix"); - HasVEX_4VOp3Prefix = Rec->getValueAsBit("hasVEX_4VOp3Prefix"); + HasVEX_4V = Rec->getValueAsBit("hasVEX_4V"); + HasVEX_4VOp3 = Rec->getValueAsBit("hasVEX_4VOp3"); HasVEX_WPrefix = Rec->getValueAsBit("hasVEX_WPrefix"); HasMemOp4Prefix = Rec->getValueAsBit("hasMemOp4Prefix"); IgnoresVEX_L = Rec->getValueAsBit("ignoresVEX_L"); - HasEVEXPrefix = Rec->getValueAsBit("hasEVEXPrefix"); HasEVEX_L2Prefix = Rec->getValueAsBit("hasEVEX_L2"); HasEVEX_K = Rec->getValueAsBit("hasEVEX_K"); HasEVEX_KZ = Rec->getValueAsBit("hasEVEX_Z"); HasEVEX_B = Rec->getValueAsBit("hasEVEX_B"); - HasLockPrefix = Rec->getValueAsBit("hasLockPrefix"); IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly"); + ForceDisassemble = Rec->getValueAsBit("ForceDisassemble"); Name = Rec->getName(); AsmString = Rec->getValueAsString("AsmString"); Operands = &insn.Operands.OperandList; - IsSSE = (HasOpSizePrefix && (Name.find("16") == Name.npos)) || - (Name.find("CRC32") != Name.npos); - HasFROperands = hasFROperands(); HasVEX_LPrefix = Rec->getValueAsBit("hasVEX_L"); // Check for 64-bit inst which does not require REX @@ -265,26 +219,27 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, // FIXME: Is there some better way to check for In64BitMode? std::vector<Record*> Predicates = Rec->getValueAsListOfDefs("Predicates"); for (unsigned i = 0, e = Predicates.size(); i != e; ++i) { - if (Predicates[i]->getName().find("32Bit") != Name.npos) { + if (Predicates[i]->getName().find("Not64Bit") != Name.npos || + Predicates[i]->getName().find("In32Bit") != Name.npos) { Is32Bit = true; break; } - if (Predicates[i]->getName().find("64Bit") != Name.npos) { + if (Predicates[i]->getName().find("In64Bit") != Name.npos) { Is64Bit = true; break; } } - // FIXME: These instructions aren't marked as 64-bit in any way - Is64Bit |= Rec->getName() == "JMP64pcrel32" || - Rec->getName() == "MASKMOVDQU64" || - Rec->getName() == "POPFS64" || - Rec->getName() == "POPGS64" || - Rec->getName() == "PUSHFS64" || - Rec->getName() == "PUSHGS64" || - Rec->getName() == "REX64_PREFIX" || - Rec->getName().find("MOV64") != Name.npos || - Rec->getName().find("PUSH64") != Name.npos || - Rec->getName().find("POP64") != Name.npos; + + if (Form == X86Local::Pseudo || (IsCodeGenOnly && !ForceDisassemble)) { + ShouldBeEmitted = false; + return; + } + + // Special case since there is no attribute class for 64-bit and VEX + if (Name == "VMASKMOVDQU64") { + ShouldBeEmitted = false; + return; + } ShouldBeEmitted = true; } @@ -299,10 +254,10 @@ void RecognizableInstr::processInstr(DisassemblerTables &tables, RecognizableInstr recogInstr(tables, insn, uid); - recogInstr.emitInstructionSpecifier(tables); - - if (recogInstr.shouldBeEmitted()) + if (recogInstr.shouldBeEmitted()) { + recogInstr.emitInstructionSpecifier(); recogInstr.emitDecodePath(tables); + } } #define EVEX_KB(n) (HasEVEX_KZ && HasEVEX_B ? n##_KZ_B : \ @@ -313,169 +268,171 @@ void RecognizableInstr::processInstr(DisassemblerTables &tables, InstructionContext RecognizableInstr::insnContext() const { InstructionContext insnContext; - if (HasEVEXPrefix) { + if (Encoding == X86Local::EVEX) { if (HasVEX_LPrefix && HasEVEX_L2Prefix) { errs() << "Don't support VEX.L if EVEX_L2 is enabled: " << Name << "\n"; llvm_unreachable("Don't support VEX.L if EVEX_L2 is enabled"); } // VEX_L & VEX_W if (HasVEX_LPrefix && HasVEX_WPrefix) { - if (HasOpSizePrefix) + if (OpPrefix == X86Local::PD) insnContext = EVEX_KB(IC_EVEX_L_W_OPSIZE); - else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS) + else if (OpPrefix == X86Local::XS) insnContext = EVEX_KB(IC_EVEX_L_W_XS); - else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || - Prefix == X86Local::TAXD) + else if (OpPrefix == X86Local::XD) insnContext = EVEX_KB(IC_EVEX_L_W_XD); - else + else if (OpPrefix == X86Local::PS) insnContext = EVEX_KB(IC_EVEX_L_W); + else { + errs() << "Instruction does not use a prefix: " << Name << "\n"; + llvm_unreachable("Invalid prefix"); + } } else if (HasVEX_LPrefix) { // VEX_L - if (HasOpSizePrefix) + if (OpPrefix == X86Local::PD) insnContext = EVEX_KB(IC_EVEX_L_OPSIZE); - else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS) + else if (OpPrefix == X86Local::XS) insnContext = EVEX_KB(IC_EVEX_L_XS); - else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || - Prefix == X86Local::TAXD) + else if (OpPrefix == X86Local::XD) insnContext = EVEX_KB(IC_EVEX_L_XD); - else + else if (OpPrefix == X86Local::PS) insnContext = EVEX_KB(IC_EVEX_L); + else { + errs() << "Instruction does not use a prefix: " << Name << "\n"; + llvm_unreachable("Invalid prefix"); + } } else if (HasEVEX_L2Prefix && HasVEX_WPrefix) { // EVEX_L2 & VEX_W - if (HasOpSizePrefix) + if (OpPrefix == X86Local::PD) insnContext = EVEX_KB(IC_EVEX_L2_W_OPSIZE); - else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS) + else if (OpPrefix == X86Local::XS) insnContext = EVEX_KB(IC_EVEX_L2_W_XS); - else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || - Prefix == X86Local::TAXD) + else if (OpPrefix == X86Local::XD) insnContext = EVEX_KB(IC_EVEX_L2_W_XD); - else + else if (OpPrefix == X86Local::PS) insnContext = EVEX_KB(IC_EVEX_L2_W); + else { + errs() << "Instruction does not use a prefix: " << Name << "\n"; + llvm_unreachable("Invalid prefix"); + } } else if (HasEVEX_L2Prefix) { // EVEX_L2 - if (HasOpSizePrefix) + if (OpPrefix == X86Local::PD) insnContext = EVEX_KB(IC_EVEX_L2_OPSIZE); - else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || - Prefix == X86Local::TAXD) + else if (OpPrefix == X86Local::XD) insnContext = EVEX_KB(IC_EVEX_L2_XD); - else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS) + else if (OpPrefix == X86Local::XS) insnContext = EVEX_KB(IC_EVEX_L2_XS); - else + else if (OpPrefix == X86Local::PS) insnContext = EVEX_KB(IC_EVEX_L2); + else { + errs() << "Instruction does not use a prefix: " << Name << "\n"; + llvm_unreachable("Invalid prefix"); + } } else if (HasVEX_WPrefix) { // VEX_W - if (HasOpSizePrefix) + if (OpPrefix == X86Local::PD) insnContext = EVEX_KB(IC_EVEX_W_OPSIZE); - else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS) + else if (OpPrefix == X86Local::XS) insnContext = EVEX_KB(IC_EVEX_W_XS); - else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || - Prefix == X86Local::TAXD) + else if (OpPrefix == X86Local::XD) insnContext = EVEX_KB(IC_EVEX_W_XD); - else + else if (OpPrefix == X86Local::PS) insnContext = EVEX_KB(IC_EVEX_W); + else { + errs() << "Instruction does not use a prefix: " << Name << "\n"; + llvm_unreachable("Invalid prefix"); + } } // No L, no W - else if (HasOpSizePrefix) + else if (OpPrefix == X86Local::PD) insnContext = EVEX_KB(IC_EVEX_OPSIZE); - else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || - Prefix == X86Local::TAXD) + else if (OpPrefix == X86Local::XD) insnContext = EVEX_KB(IC_EVEX_XD); - else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS) + else if (OpPrefix == X86Local::XS) insnContext = EVEX_KB(IC_EVEX_XS); else insnContext = EVEX_KB(IC_EVEX); /// eof EVEX - } else if (HasVEX_4VPrefix || HasVEX_4VOp3Prefix|| HasVEXPrefix) { + } else if (Encoding == X86Local::VEX || Encoding == X86Local::XOP) { if (HasVEX_LPrefix && HasVEX_WPrefix) { - if (HasOpSizePrefix) + if (OpPrefix == X86Local::PD) insnContext = IC_VEX_L_W_OPSIZE; - else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS) + else if (OpPrefix == X86Local::XS) insnContext = IC_VEX_L_W_XS; - else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || - Prefix == X86Local::TAXD) + else if (OpPrefix == X86Local::XD) insnContext = IC_VEX_L_W_XD; - else + else if (OpPrefix == X86Local::PS) insnContext = IC_VEX_L_W; - } else if (HasOpSizePrefix && HasVEX_LPrefix) + else { + errs() << "Instruction does not use a prefix: " << Name << "\n"; + llvm_unreachable("Invalid prefix"); + } + } else if (OpPrefix == X86Local::PD && HasVEX_LPrefix) insnContext = IC_VEX_L_OPSIZE; - else if (HasOpSizePrefix && HasVEX_WPrefix) + else if (OpPrefix == X86Local::PD && HasVEX_WPrefix) insnContext = IC_VEX_W_OPSIZE; - else if (HasOpSizePrefix) + else if (OpPrefix == X86Local::PD) insnContext = IC_VEX_OPSIZE; - else if (HasVEX_LPrefix && - (Prefix == X86Local::XS || Prefix == X86Local::T8XS)) + else if (HasVEX_LPrefix && OpPrefix == X86Local::XS) insnContext = IC_VEX_L_XS; - else if (HasVEX_LPrefix && (Prefix == X86Local::XD || - Prefix == X86Local::T8XD || - Prefix == X86Local::TAXD)) + else if (HasVEX_LPrefix && OpPrefix == X86Local::XD) insnContext = IC_VEX_L_XD; - else if (HasVEX_WPrefix && - (Prefix == X86Local::XS || Prefix == X86Local::T8XS)) + else if (HasVEX_WPrefix && OpPrefix == X86Local::XS) insnContext = IC_VEX_W_XS; - else if (HasVEX_WPrefix && (Prefix == X86Local::XD || - Prefix == X86Local::T8XD || - Prefix == X86Local::TAXD)) + else if (HasVEX_WPrefix && OpPrefix == X86Local::XD) insnContext = IC_VEX_W_XD; - else if (HasVEX_WPrefix) + else if (HasVEX_WPrefix && OpPrefix == X86Local::PS) insnContext = IC_VEX_W; - else if (HasVEX_LPrefix) + else if (HasVEX_LPrefix && OpPrefix == X86Local::PS) insnContext = IC_VEX_L; - else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || - Prefix == X86Local::TAXD) + else if (OpPrefix == X86Local::XD) insnContext = IC_VEX_XD; - else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS) + else if (OpPrefix == X86Local::XS) insnContext = IC_VEX_XS; - else + else if (OpPrefix == X86Local::PS) insnContext = IC_VEX; + else { + errs() << "Instruction does not use a prefix: " << Name << "\n"; + llvm_unreachable("Invalid prefix"); + } } else if (Is64Bit || HasREX_WPrefix) { - if (HasREX_WPrefix && HasOpSizePrefix) + if (HasREX_WPrefix && (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD)) insnContext = IC_64BIT_REXW_OPSIZE; - else if (HasOpSizePrefix && (Prefix == X86Local::XD || - Prefix == X86Local::T8XD || - Prefix == X86Local::TAXD)) + else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XD) insnContext = IC_64BIT_XD_OPSIZE; - else if (HasOpSizePrefix && - (Prefix == X86Local::XS || Prefix == X86Local::T8XS)) + else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XS) insnContext = IC_64BIT_XS_OPSIZE; - else if (HasOpSizePrefix) + else if (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD) insnContext = IC_64BIT_OPSIZE; else if (HasAdSizePrefix) insnContext = IC_64BIT_ADSIZE; - else if (HasREX_WPrefix && - (Prefix == X86Local::XS || Prefix == X86Local::T8XS)) + else if (HasREX_WPrefix && OpPrefix == X86Local::XS) insnContext = IC_64BIT_REXW_XS; - else if (HasREX_WPrefix && (Prefix == X86Local::XD || - Prefix == X86Local::T8XD || - Prefix == X86Local::TAXD)) + else if (HasREX_WPrefix && OpPrefix == X86Local::XD) insnContext = IC_64BIT_REXW_XD; - else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || - Prefix == X86Local::TAXD) + else if (OpPrefix == X86Local::XD) insnContext = IC_64BIT_XD; - else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS) + else if (OpPrefix == X86Local::XS) insnContext = IC_64BIT_XS; else if (HasREX_WPrefix) insnContext = IC_64BIT_REXW; else insnContext = IC_64BIT; } else { - if (HasOpSizePrefix && (Prefix == X86Local::XD || - Prefix == X86Local::T8XD || - Prefix == X86Local::TAXD)) + if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XD) insnContext = IC_XD_OPSIZE; - else if (HasOpSizePrefix && - (Prefix == X86Local::XS || Prefix == X86Local::T8XS)) + else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XS) insnContext = IC_XS_OPSIZE; - else if (HasOpSizePrefix) + else if (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD) insnContext = IC_OPSIZE; else if (HasAdSizePrefix) insnContext = IC_ADSIZE; - else if (Prefix == X86Local::XD || Prefix == X86Local::T8XD || - Prefix == X86Local::TAXD) + else if (OpPrefix == X86Local::XD) insnContext = IC_XD; - else if (Prefix == X86Local::XS || Prefix == X86Local::T8XS || - Prefix == X86Local::REP) + else if (OpPrefix == X86Local::XS) insnContext = IC_XS; else insnContext = IC; @@ -484,89 +441,13 @@ InstructionContext RecognizableInstr::insnContext() const { return insnContext; } -RecognizableInstr::filter_ret RecognizableInstr::filter() const { - /////////////////// - // FILTER_STRONG - // - - // Filter out intrinsics - - assert(Rec->isSubClassOf("X86Inst") && "Can only filter X86 instructions"); - - if (Form == X86Local::Pseudo || - (IsCodeGenOnly && Name.find("_REV") == Name.npos && - Name.find("INC32") == Name.npos && Name.find("DEC32") == Name.npos)) - return FILTER_STRONG; - - - // Filter out artificial instructions but leave in the LOCK_PREFIX so it is - // printed as a separate "instruction". - - if (Name.find("_Int") != Name.npos || - Name.find("Int_") != Name.npos) - return FILTER_STRONG; - - // Filter out instructions with segment override prefixes. - // They're too messy to handle now and we'll special case them if needed. - - if (SegOvr) - return FILTER_STRONG; - - - ///////////////// - // FILTER_WEAK - // - - - // Filter out instructions with a LOCK prefix; - // prefer forms that do not have the prefix - if (HasLockPrefix) - return FILTER_WEAK; - - // Filter out alternate forms of AVX instructions - if (Name.find("_alt") != Name.npos || - (Name.find("r64r") != Name.npos && Name.find("r64r64") == Name.npos && Name.find("r64r8") == Name.npos) || - Name.find("_64mr") != Name.npos || - Name.find("rr64") != Name.npos) - return FILTER_WEAK; - - // Special cases. - - if (Name == "PUSH64i16" || - Name == "MOVPQI2QImr" || - Name == "VMOVPQI2QImr" || - Name == "VMASKMOVDQU64") - return FILTER_WEAK; - - // XACQUIRE and XRELEASE reuse REPNE and REP respectively. - // For now, just prefer the REP versions. - if (Name == "XACQUIRE_PREFIX" || - Name == "XRELEASE_PREFIX") - return FILTER_WEAK; - - return FILTER_NORMAL; -} - -bool RecognizableInstr::hasFROperands() const { - const std::vector<CGIOperandList::OperandInfo> &OperandList = *Operands; - unsigned numOperands = OperandList.size(); - - for (unsigned operandIndex = 0; operandIndex < numOperands; ++operandIndex) { - const std::string &recName = OperandList[operandIndex].Rec->getName(); - - if (recName.find("FR") != recName.npos) - return true; - } - return false; -} - void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex, unsigned &physicalOperandIndex, unsigned &numPhysicalOperands, const unsigned *operandMapping, OperandEncoding (*encodingFromString) (const std::string&, - bool hasOpSizePrefix)) { + uint8_t OpSize)) { if (optional) { if (physicalOperandIndex >= numPhysicalOperands) return; @@ -584,33 +465,17 @@ void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex, const std::string &typeName = (*Operands)[operandIndex].Rec->getName(); Spec->operands[operandIndex].encoding = encodingFromString(typeName, - HasOpSizePrefix); + OpSize); Spec->operands[operandIndex].type = typeFromString(typeName, - IsSSE, - HasREX_WPrefix, - HasOpSizePrefix); + HasREX_WPrefix, OpSize); ++operandIndex; ++physicalOperandIndex; } -void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { +void RecognizableInstr::emitInstructionSpecifier() { Spec->name = Name; - if (!ShouldBeEmitted) - return; - - switch (filter()) { - case FILTER_WEAK: - Spec->filtered = true; - break; - case FILTER_STRONG: - ShouldBeEmitted = false; - return; - case FILTER_NORMAL: - break; - } - Spec->insnContext = insnContext(); const std::vector<CGIOperandList::OperandInfo> &OperandList = *Operands; @@ -662,6 +527,17 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { unsigned physicalOperandIndex = 0; switch (Form) { + default: llvm_unreachable("Unhandled form"); + case X86Local::RawFrmSrc: + HANDLE_OPERAND(relocation); + return; + case X86Local::RawFrmDst: + HANDLE_OPERAND(relocation); + return; + case X86Local::RawFrmDstSrc: + HANDLE_OPERAND(relocation); + HANDLE_OPERAND(relocation); + return; case X86Local::RawFrm: // Operand 1 (optional) is an address or immediate. // Operand 2 (optional) is an immediate. @@ -670,6 +546,10 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { HANDLE_OPTIONAL(relocation) HANDLE_OPTIONAL(immediate) break; + case X86Local::RawFrmMemOffs: + // Operand 1 is an address. + HANDLE_OPERAND(relocation); + break; case X86Local::AddRegFrm: // Operand 1 is added to the opcode. // Operand 2 (optional) is an address. @@ -683,7 +563,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { // Operand 2 is a register operand in the Reg/Opcode field. // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - if (HasVEX_4VPrefix) + if (HasVEX_4V) assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && "Unexpected number of operands for MRMDestRegFrm with VEX_4V"); else @@ -692,7 +572,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { HANDLE_OPERAND(rmRegister) - if (HasVEX_4VPrefix) + if (HasVEX_4V) // FIXME: In AVX, the register below becomes the one encoded // in ModRMVEX and the one above the one in the VEX.VVVV field HANDLE_OPERAND(vvvvRegister) @@ -705,7 +585,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { // Operand 2 is a register operand in the Reg/Opcode field. // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - if (HasVEX_4VPrefix) + if (HasVEX_4V) assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && "Unexpected number of operands for MRMDestMemFrm with VEX_4V"); else @@ -716,7 +596,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { if (HasEVEX_K) HANDLE_OPERAND(writemaskRegister) - if (HasVEX_4VPrefix) + if (HasVEX_4V) // FIXME: In AVX, the register below becomes the one encoded // in ModRMVEX and the one above the one in the VEX.VVVV field HANDLE_OPERAND(vvvvRegister) @@ -731,7 +611,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { // Operand 3 (optional) is an immediate. // Operand 4 (optional) is an immediate. - if (HasVEX_4VPrefix || HasVEX_4VOp3Prefix) + if (HasVEX_4V || HasVEX_4VOp3) assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 5 && "Unexpected number of operands for MRMSrcRegFrm with VEX_4V"); else @@ -743,7 +623,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { if (HasEVEX_K) HANDLE_OPERAND(writemaskRegister) - if (HasVEX_4VPrefix) + if (HasVEX_4V) // FIXME: In AVX, the register below becomes the one encoded // in ModRMVEX and the one above the one in the VEX.VVVV field HANDLE_OPERAND(vvvvRegister) @@ -753,7 +633,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { HANDLE_OPERAND(rmRegister) - if (HasVEX_4VOp3Prefix) + if (HasVEX_4VOp3) HANDLE_OPERAND(vvvvRegister) if (!HasMemOp4Prefix) @@ -767,7 +647,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - if (HasVEX_4VPrefix || HasVEX_4VOp3Prefix) + if (HasVEX_4V || HasVEX_4VOp3) assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 5 && "Unexpected number of operands for MRMSrcMemFrm with VEX_4V"); else @@ -779,7 +659,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { if (HasEVEX_K) HANDLE_OPERAND(writemaskRegister) - if (HasVEX_4VPrefix) + if (HasVEX_4V) // FIXME: In AVX, the register below becomes the one encoded // in ModRMVEX and the one above the one in the VEX.VVVV field HANDLE_OPERAND(vvvvRegister) @@ -789,13 +669,14 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { HANDLE_OPERAND(memory) - if (HasVEX_4VOp3Prefix) + if (HasVEX_4VOp3) HANDLE_OPERAND(vvvvRegister) if (!HasMemOp4Prefix) HANDLE_OPTIONAL(immediate) HANDLE_OPTIONAL(immediate) // above might be a register in 7:4 break; + case X86Local::MRMXr: case X86Local::MRM0r: case X86Local::MRM1r: case X86Local::MRM2r: @@ -809,11 +690,11 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { // Operand 2 (optional) is an immediate or relocation. // Operand 3 (optional) is an immediate. unsigned kOp = (HasEVEX_K) ? 1:0; - unsigned Op4v = (HasVEX_4VPrefix) ? 1:0; + unsigned Op4v = (HasVEX_4V) ? 1:0; if (numPhysicalOperands > 3 + kOp + Op4v) llvm_unreachable("Unexpected number of operands for MRMnr"); } - if (HasVEX_4VPrefix) + if (HasVEX_4V) HANDLE_OPERAND(vvvvRegister) if (HasEVEX_K) @@ -822,6 +703,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { HANDLE_OPTIONAL(relocation) HANDLE_OPTIONAL(immediate) break; + case X86Local::MRMXm: case X86Local::MRM0m: case X86Local::MRM1m: case X86Local::MRM2m: @@ -834,12 +716,12 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { // Operand 1 is a memory operand (possibly SIB-extended) // Operand 2 (optional) is an immediate or relocation. unsigned kOp = (HasEVEX_K) ? 1:0; - unsigned Op4v = (HasVEX_4VPrefix) ? 1:0; + unsigned Op4v = (HasVEX_4V) ? 1:0; if (numPhysicalOperands < 1 + kOp + Op4v || numPhysicalOperands > 2 + kOp + Op4v) llvm_unreachable("Unexpected number of operands for MRMnm"); } - if (HasVEX_4VPrefix) + if (HasVEX_4V) HANDLE_OPERAND(vvvvRegister) if (HasEVEX_K) HANDLE_OPERAND(writemaskRegister) @@ -871,7 +753,23 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { HANDLE_OPERAND(relocation) } break; - case X86Local::MRMInitReg: + case X86Local::MRM_C0: case X86Local::MRM_C1: case X86Local::MRM_C2: + case X86Local::MRM_C3: case X86Local::MRM_C4: case X86Local::MRM_C8: + case X86Local::MRM_C9: case X86Local::MRM_CA: case X86Local::MRM_CB: + case X86Local::MRM_D0: case X86Local::MRM_D1: case X86Local::MRM_D4: + case X86Local::MRM_D5: case X86Local::MRM_D6: case X86Local::MRM_D8: + case X86Local::MRM_D9: case X86Local::MRM_DA: case X86Local::MRM_DB: + case X86Local::MRM_DC: case X86Local::MRM_DD: case X86Local::MRM_DE: + case X86Local::MRM_DF: case X86Local::MRM_E0: case X86Local::MRM_E1: + case X86Local::MRM_E2: case X86Local::MRM_E3: case X86Local::MRM_E4: + case X86Local::MRM_E5: case X86Local::MRM_E8: case X86Local::MRM_E9: + case X86Local::MRM_EA: case X86Local::MRM_EB: case X86Local::MRM_EC: + case X86Local::MRM_ED: case X86Local::MRM_EE: case X86Local::MRM_F0: + case X86Local::MRM_F1: case X86Local::MRM_F2: case X86Local::MRM_F3: + case X86Local::MRM_F4: case X86Local::MRM_F5: case X86Local::MRM_F6: + case X86Local::MRM_F7: case X86Local::MRM_F9: case X86Local::MRM_FA: + case X86Local::MRM_FB: case X86Local::MRM_FC: case X86Local::MRM_FD: + case X86Local::MRM_FE: case X86Local::MRM_FF: // Ignored. break; } @@ -893,290 +791,78 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { ModRMFilter* filter = NULL; uint8_t opcodeToSet = 0; - switch (Prefix) { - default: llvm_unreachable("Invalid prefix!"); - // Extended two-byte opcodes can start with f2 0f, f3 0f, or 0f - case X86Local::XD: - case X86Local::XS: + switch (OpMap) { + default: llvm_unreachable("Invalid map!"); + case X86Local::OB: case X86Local::TB: - opcodeType = TWOBYTE; - - switch (Opcode) { - default: - if (needsModRMForDecode(Form)) - filter = new ModFilter(isRegFormat(Form)); - else - filter = new DumbFilter(); - break; -#define EXTENSION_TABLE(n) case 0x##n: - TWO_BYTE_EXTENSION_TABLES -#undef EXTENSION_TABLE - switch (Form) { - default: - llvm_unreachable("Unhandled two-byte extended opcode"); - case X86Local::MRM0r: - case X86Local::MRM1r: - case X86Local::MRM2r: - case X86Local::MRM3r: - case X86Local::MRM4r: - case X86Local::MRM5r: - case X86Local::MRM6r: - case X86Local::MRM7r: - filter = new ExtendedFilter(true, Form - X86Local::MRM0r); - break; - case X86Local::MRM0m: - case X86Local::MRM1m: - case X86Local::MRM2m: - case X86Local::MRM3m: - case X86Local::MRM4m: - case X86Local::MRM5m: - case X86Local::MRM6m: - case X86Local::MRM7m: - filter = new ExtendedFilter(false, Form - X86Local::MRM0m); - break; - MRM_MAPPING - } // switch (Form) - break; - } // switch (Opcode) - opcodeToSet = Opcode; - break; case X86Local::T8: - case X86Local::T8XD: - case X86Local::T8XS: - opcodeType = THREEBYTE_38; - switch (Opcode) { - default: - if (needsModRMForDecode(Form)) - filter = new ModFilter(isRegFormat(Form)); - else - filter = new DumbFilter(); - break; -#define EXTENSION_TABLE(n) case 0x##n: - THREE_BYTE_38_EXTENSION_TABLES -#undef EXTENSION_TABLE - switch (Form) { - default: - llvm_unreachable("Unhandled two-byte extended opcode"); - case X86Local::MRM0r: - case X86Local::MRM1r: - case X86Local::MRM2r: - case X86Local::MRM3r: - case X86Local::MRM4r: - case X86Local::MRM5r: - case X86Local::MRM6r: - case X86Local::MRM7r: - filter = new ExtendedFilter(true, Form - X86Local::MRM0r); - break; - case X86Local::MRM0m: - case X86Local::MRM1m: - case X86Local::MRM2m: - case X86Local::MRM3m: - case X86Local::MRM4m: - case X86Local::MRM5m: - case X86Local::MRM6m: - case X86Local::MRM7m: - filter = new ExtendedFilter(false, Form - X86Local::MRM0m); - break; - MRM_MAPPING - } // switch (Form) - break; - } // switch (Opcode) - opcodeToSet = Opcode; - break; - case X86Local::P_TA: - case X86Local::TAXD: - opcodeType = THREEBYTE_3A; - if (needsModRMForDecode(Form)) - filter = new ModFilter(isRegFormat(Form)); - else - filter = new DumbFilter(); - opcodeToSet = Opcode; - break; - case X86Local::A6: - opcodeType = THREEBYTE_A6; - if (needsModRMForDecode(Form)) - filter = new ModFilter(isRegFormat(Form)); - else - filter = new DumbFilter(); - opcodeToSet = Opcode; - break; - case X86Local::A7: - opcodeType = THREEBYTE_A7; - if (needsModRMForDecode(Form)) - filter = new ModFilter(isRegFormat(Form)); - else - filter = new DumbFilter(); - opcodeToSet = Opcode; - break; + case X86Local::TA: case X86Local::XOP8: - opcodeType = XOP8_MAP; - if (needsModRMForDecode(Form)) - filter = new ModFilter(isRegFormat(Form)); - else - filter = new DumbFilter(); - opcodeToSet = Opcode; - break; case X86Local::XOP9: - opcodeType = XOP9_MAP; - switch (Opcode) { + case X86Local::XOPA: + switch (OpMap) { + default: llvm_unreachable("Unexpected map!"); + case X86Local::OB: opcodeType = ONEBYTE; break; + case X86Local::TB: opcodeType = TWOBYTE; break; + case X86Local::T8: opcodeType = THREEBYTE_38; break; + case X86Local::TA: opcodeType = THREEBYTE_3A; break; + case X86Local::XOP8: opcodeType = XOP8_MAP; break; + case X86Local::XOP9: opcodeType = XOP9_MAP; break; + case X86Local::XOPA: opcodeType = XOPA_MAP; break; + } + + switch (Form) { default: - if (needsModRMForDecode(Form)) - filter = new ModFilter(isRegFormat(Form)); - else - filter = new DumbFilter(); - break; -#define EXTENSION_TABLE(n) case 0x##n: - XOP9_MAP_EXTENSION_TABLES -#undef EXTENSION_TABLE - switch (Form) { - default: - llvm_unreachable("Unhandled XOP9 extended opcode"); - case X86Local::MRM0r: - case X86Local::MRM1r: - case X86Local::MRM2r: - case X86Local::MRM3r: - case X86Local::MRM4r: - case X86Local::MRM5r: - case X86Local::MRM6r: - case X86Local::MRM7r: - filter = new ExtendedFilter(true, Form - X86Local::MRM0r); - break; - case X86Local::MRM0m: - case X86Local::MRM1m: - case X86Local::MRM2m: - case X86Local::MRM3m: - case X86Local::MRM4m: - case X86Local::MRM5m: - case X86Local::MRM6m: - case X86Local::MRM7m: - filter = new ExtendedFilter(false, Form - X86Local::MRM0m); - break; - MRM_MAPPING - } // switch (Form) + filter = new DumbFilter(); break; - } // switch (Opcode) - opcodeToSet = Opcode; - break; - case X86Local::XOPA: - opcodeType = XOPA_MAP; - if (needsModRMForDecode(Form)) + case X86Local::MRMDestReg: case X86Local::MRMDestMem: + case X86Local::MRMSrcReg: case X86Local::MRMSrcMem: + case X86Local::MRMXr: case X86Local::MRMXm: filter = new ModFilter(isRegFormat(Form)); - else - filter = new DumbFilter(); - opcodeToSet = Opcode; - break; - case X86Local::D8: - case X86Local::D9: - case X86Local::DA: - case X86Local::DB: - case X86Local::DC: - case X86Local::DD: - case X86Local::DE: - case X86Local::DF: - assert(Opcode >= 0xc0 && "Unexpected opcode for an escape opcode"); - opcodeType = ONEBYTE; - if (Form == X86Local::AddRegFrm) { - Spec->modifierType = MODIFIER_MODRM; - Spec->modifierBase = Opcode; - filter = new AddRegEscapeFilter(Opcode); - } else { - filter = new EscapeFilter(true, Opcode); - } - opcodeToSet = 0xd8 + (Prefix - X86Local::D8); - break; - case X86Local::REP: - case 0: - opcodeType = ONEBYTE; - switch (Opcode) { -#define EXTENSION_TABLE(n) case 0x##n: - ONE_BYTE_EXTENSION_TABLES -#undef EXTENSION_TABLE - switch (Form) { - default: - llvm_unreachable("Fell through the cracks of a single-byte " - "extended opcode"); - case X86Local::MRM0r: - case X86Local::MRM1r: - case X86Local::MRM2r: - case X86Local::MRM3r: - case X86Local::MRM4r: - case X86Local::MRM5r: - case X86Local::MRM6r: - case X86Local::MRM7r: - filter = new ExtendedFilter(true, Form - X86Local::MRM0r); - break; - case X86Local::MRM0m: - case X86Local::MRM1m: - case X86Local::MRM2m: - case X86Local::MRM3m: - case X86Local::MRM4m: - case X86Local::MRM5m: - case X86Local::MRM6m: - case X86Local::MRM7m: - filter = new ExtendedFilter(false, Form - X86Local::MRM0m); - break; - MRM_MAPPING - } // switch (Form) break; - case 0xd8: - case 0xd9: - case 0xda: - case 0xdb: - case 0xdc: - case 0xdd: - case 0xde: - case 0xdf: - filter = new EscapeFilter(false, Form - X86Local::MRM0m); + case X86Local::MRM0r: case X86Local::MRM1r: + case X86Local::MRM2r: case X86Local::MRM3r: + case X86Local::MRM4r: case X86Local::MRM5r: + case X86Local::MRM6r: case X86Local::MRM7r: + filter = new ExtendedFilter(true, Form - X86Local::MRM0r); break; - default: - if (needsModRMForDecode(Form)) - filter = new ModFilter(isRegFormat(Form)); - else - filter = new DumbFilter(); + case X86Local::MRM0m: case X86Local::MRM1m: + case X86Local::MRM2m: case X86Local::MRM3m: + case X86Local::MRM4m: case X86Local::MRM5m: + case X86Local::MRM6m: case X86Local::MRM7m: + filter = new ExtendedFilter(false, Form - X86Local::MRM0m); break; - } // switch (Opcode) + MRM_MAPPING + } // switch (Form) + opcodeToSet = Opcode; - } // switch (Prefix) + break; + } // switch (OpMap) assert(opcodeType != (OpcodeType)-1 && "Opcode type not set"); assert(filter && "Filter not set"); if (Form == X86Local::AddRegFrm) { - if(Spec->modifierType != MODIFIER_MODRM) { - assert(opcodeToSet < 0xf9 && - "Not enough room for all ADDREG_FRM operands"); - - uint8_t currentOpcode; - - for (currentOpcode = opcodeToSet; - currentOpcode < opcodeToSet + 8; - ++currentOpcode) - tables.setTableFields(opcodeType, - insnContext(), - currentOpcode, - *filter, - UID, Is32Bit, IgnoresVEX_L); - - Spec->modifierType = MODIFIER_OPCODE; - Spec->modifierBase = opcodeToSet; - } else { - // modifierBase was set where MODIFIER_MODRM was set + assert(((opcodeToSet & 7) == 0) && + "ADDREG_FRM opcode not aligned"); + + uint8_t currentOpcode; + + for (currentOpcode = opcodeToSet; + currentOpcode < opcodeToSet + 8; + ++currentOpcode) tables.setTableFields(opcodeType, insnContext(), - opcodeToSet, + currentOpcode, *filter, UID, Is32Bit, IgnoresVEX_L); - } } else { tables.setTableFields(opcodeType, insnContext(), opcodeToSet, *filter, UID, Is32Bit, IgnoresVEX_L); - - Spec->modifierType = MODIFIER_NONE; - Spec->modifierBase = opcodeToSet; } delete filter; @@ -1186,36 +872,32 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { #define TYPE(str, type) if (s == str) return type; OperandType RecognizableInstr::typeFromString(const std::string &s, - bool isSSE, bool hasREX_WPrefix, - bool hasOpSizePrefix) { - if (isSSE) { - // For SSE instructions, we ignore the OpSize prefix and force operand - // sizes. - TYPE("GR16", TYPE_R16) - TYPE("GR32", TYPE_R32) - TYPE("GR64", TYPE_R64) - } + uint8_t OpSize) { if(hasREX_WPrefix) { // For instructions with a REX_W prefix, a declared 32-bit register encoding // is special. TYPE("GR32", TYPE_R32) } - if(!hasOpSizePrefix) { - // For instructions without an OpSize prefix, a declared 16-bit register or + if(OpSize == X86Local::OpSize16) { + // For OpSize16 instructions, a declared 16-bit register or + // immediate encoding is special. + TYPE("GR16", TYPE_Rv) + TYPE("i16imm", TYPE_IMMv) + } else if(OpSize == X86Local::OpSize32) { + // For OpSize32 instructions, a declared 32-bit register or // immediate encoding is special. - TYPE("GR16", TYPE_R16) - TYPE("i16imm", TYPE_IMM16) + TYPE("GR32", TYPE_Rv) } TYPE("i16mem", TYPE_Mv) - TYPE("i16imm", TYPE_IMMv) + TYPE("i16imm", TYPE_IMM16) TYPE("i16i8imm", TYPE_IMMv) - TYPE("GR16", TYPE_Rv) + TYPE("GR16", TYPE_R16) TYPE("i32mem", TYPE_Mv) TYPE("i32imm", TYPE_IMMv) TYPE("i32i8imm", TYPE_IMM32) TYPE("u32u8imm", TYPE_IMM32) - TYPE("GR32", TYPE_Rv) + TYPE("GR32", TYPE_R32) TYPE("GR32orGR64", TYPE_R32) TYPE("i64mem", TYPE_Mv) TYPE("i64i32imm", TYPE_IMM64) @@ -1246,6 +928,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("i32imm_pcrel", TYPE_REL32) TYPE("SSECC", TYPE_IMM3) TYPE("AVXCC", TYPE_IMM5) + TYPE("AVX512RC", TYPE_IMM32) TYPE("brtarget", TYPE_RELv) TYPE("uncondbrtarget", TYPE_RELv) TYPE("brtarget8", TYPE_REL8) @@ -1262,6 +945,14 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("SEGMENT_REG", TYPE_SEGMENTREG) TYPE("DEBUG_REG", TYPE_DEBUGREG) TYPE("CONTROL_REG", TYPE_CONTROLREG) + TYPE("srcidx8", TYPE_SRCIDX8) + TYPE("srcidx16", TYPE_SRCIDX16) + TYPE("srcidx32", TYPE_SRCIDX32) + TYPE("srcidx64", TYPE_SRCIDX64) + TYPE("dstidx8", TYPE_DSTIDX8) + TYPE("dstidx16", TYPE_DSTIDX16) + TYPE("dstidx32", TYPE_DSTIDX32) + TYPE("dstidx64", TYPE_DSTIDX64) TYPE("offset8", TYPE_MOFFS8) TYPE("offset16", TYPE_MOFFS16) TYPE("offset32", TYPE_MOFFS32) @@ -1269,6 +960,8 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("VR256", TYPE_XMM256) TYPE("VR256X", TYPE_XMM256) TYPE("VR512", TYPE_XMM512) + TYPE("VK1", TYPE_VK1) + TYPE("VK1WM", TYPE_VK1) TYPE("VK8", TYPE_VK8) TYPE("VK8WM", TYPE_VK8) TYPE("VK16", TYPE_VK16) @@ -1289,10 +982,10 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, #undef TYPE #define ENCODING(str, encoding) if (s == str) return encoding; -OperandEncoding RecognizableInstr::immediateEncodingFromString - (const std::string &s, - bool hasOpSizePrefix) { - if(!hasOpSizePrefix) { +OperandEncoding +RecognizableInstr::immediateEncodingFromString(const std::string &s, + uint8_t OpSize) { + if(OpSize != X86Local::OpSize16) { // For instructions without an OpSize prefix, a declared 16-bit register or // immediate encoding is special. ENCODING("i16imm", ENCODING_IW) @@ -1301,6 +994,7 @@ OperandEncoding RecognizableInstr::immediateEncodingFromString ENCODING("u32u8imm", ENCODING_IB) ENCODING("SSECC", ENCODING_IB) ENCODING("AVXCC", ENCODING_IB) + ENCODING("AVX512RC", ENCODING_IB) ENCODING("i16imm", ENCODING_Iv) ENCODING("i16i8imm", ENCODING_IB) ENCODING("i32imm", ENCODING_Iv) @@ -1322,9 +1016,10 @@ OperandEncoding RecognizableInstr::immediateEncodingFromString llvm_unreachable("Unhandled immediate encoding"); } -OperandEncoding RecognizableInstr::rmRegisterEncodingFromString - (const std::string &s, - bool hasOpSizePrefix) { +OperandEncoding +RecognizableInstr::rmRegisterEncodingFromString(const std::string &s, + uint8_t OpSize) { + ENCODING("RST", ENCODING_FP) ENCODING("GR16", ENCODING_RM) ENCODING("GR32", ENCODING_RM) ENCODING("GR32orGR64", ENCODING_RM) @@ -1340,15 +1035,16 @@ OperandEncoding RecognizableInstr::rmRegisterEncodingFromString ENCODING("VR256", ENCODING_RM) ENCODING("VR256X", ENCODING_RM) ENCODING("VR512", ENCODING_RM) + ENCODING("VK1", ENCODING_RM) ENCODING("VK8", ENCODING_RM) ENCODING("VK16", ENCODING_RM) errs() << "Unhandled R/M register encoding " << s << "\n"; llvm_unreachable("Unhandled R/M register encoding"); } -OperandEncoding RecognizableInstr::roRegisterEncodingFromString - (const std::string &s, - bool hasOpSizePrefix) { +OperandEncoding +RecognizableInstr::roRegisterEncodingFromString(const std::string &s, + uint8_t OpSize) { ENCODING("GR16", ENCODING_REG) ENCODING("GR32", ENCODING_REG) ENCODING("GR32orGR64", ENCODING_REG) @@ -1367,17 +1063,19 @@ OperandEncoding RecognizableInstr::roRegisterEncodingFromString ENCODING("FR64X", ENCODING_REG) ENCODING("FR32X", ENCODING_REG) ENCODING("VR512", ENCODING_REG) + ENCODING("VK1", ENCODING_REG) ENCODING("VK8", ENCODING_REG) ENCODING("VK16", ENCODING_REG) + ENCODING("VK1WM", ENCODING_REG) ENCODING("VK8WM", ENCODING_REG) ENCODING("VK16WM", ENCODING_REG) errs() << "Unhandled reg/opcode register encoding " << s << "\n"; llvm_unreachable("Unhandled reg/opcode register encoding"); } -OperandEncoding RecognizableInstr::vvvvRegisterEncodingFromString - (const std::string &s, - bool hasOpSizePrefix) { +OperandEncoding +RecognizableInstr::vvvvRegisterEncodingFromString(const std::string &s, + uint8_t OpSize) { ENCODING("GR32", ENCODING_VVVV) ENCODING("GR64", ENCODING_VVVV) ENCODING("FR32", ENCODING_VVVV) @@ -1389,24 +1087,26 @@ OperandEncoding RecognizableInstr::vvvvRegisterEncodingFromString ENCODING("VR128X", ENCODING_VVVV) ENCODING("VR256X", ENCODING_VVVV) ENCODING("VR512", ENCODING_VVVV) + ENCODING("VK1", ENCODING_VVVV) ENCODING("VK8", ENCODING_VVVV) ENCODING("VK16", ENCODING_VVVV) errs() << "Unhandled VEX.vvvv register encoding " << s << "\n"; llvm_unreachable("Unhandled VEX.vvvv register encoding"); } -OperandEncoding RecognizableInstr::writemaskRegisterEncodingFromString - (const std::string &s, - bool hasOpSizePrefix) { +OperandEncoding +RecognizableInstr::writemaskRegisterEncodingFromString(const std::string &s, + uint8_t OpSize) { + ENCODING("VK1WM", ENCODING_WRITEMASK) ENCODING("VK8WM", ENCODING_WRITEMASK) ENCODING("VK16WM", ENCODING_WRITEMASK) errs() << "Unhandled mask register encoding " << s << "\n"; llvm_unreachable("Unhandled mask register encoding"); } -OperandEncoding RecognizableInstr::memoryEncodingFromString - (const std::string &s, - bool hasOpSizePrefix) { +OperandEncoding +RecognizableInstr::memoryEncodingFromString(const std::string &s, + uint8_t OpSize) { ENCODING("i16mem", ENCODING_RM) ENCODING("i32mem", ENCODING_RM) ENCODING("i64mem", ENCODING_RM) @@ -1440,10 +1140,10 @@ OperandEncoding RecognizableInstr::memoryEncodingFromString llvm_unreachable("Unhandled memory encoding"); } -OperandEncoding RecognizableInstr::relocationEncodingFromString - (const std::string &s, - bool hasOpSizePrefix) { - if(!hasOpSizePrefix) { +OperandEncoding +RecognizableInstr::relocationEncodingFromString(const std::string &s, + uint8_t OpSize) { + if(OpSize != X86Local::OpSize16) { // For instructions without an OpSize prefix, a declared 16-bit register or // immediate encoding is special. ENCODING("i16imm", ENCODING_IW) @@ -1465,14 +1165,21 @@ OperandEncoding RecognizableInstr::relocationEncodingFromString ENCODING("offset16", ENCODING_Ia) ENCODING("offset32", ENCODING_Ia) ENCODING("offset64", ENCODING_Ia) + ENCODING("srcidx8", ENCODING_SI) + ENCODING("srcidx16", ENCODING_SI) + ENCODING("srcidx32", ENCODING_SI) + ENCODING("srcidx64", ENCODING_SI) + ENCODING("dstidx8", ENCODING_DI) + ENCODING("dstidx16", ENCODING_DI) + ENCODING("dstidx32", ENCODING_DI) + ENCODING("dstidx64", ENCODING_DI) errs() << "Unhandled relocation encoding " << s << "\n"; llvm_unreachable("Unhandled relocation encoding"); } -OperandEncoding RecognizableInstr::opcodeModifierEncodingFromString - (const std::string &s, - bool hasOpSizePrefix) { - ENCODING("RST", ENCODING_I) +OperandEncoding +RecognizableInstr::opcodeModifierEncodingFromString(const std::string &s, + uint8_t OpSize) { ENCODING("GR32", ENCODING_Rv) ENCODING("GR64", ENCODING_RO) ENCODING("GR16", ENCODING_Rv) diff --git a/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h index 4d4686e..77286bc 100644 --- a/utils/TableGen/X86RecognizableInstr.h +++ b/utils/TableGen/X86RecognizableInstr.h @@ -37,27 +37,27 @@ private: InstrUID UID; /// The record from the .td files corresponding to this instruction const Record* Rec; - /// The prefix field from the record - uint8_t Prefix; + /// The OpPrefix field from the record + uint8_t OpPrefix; + /// The OpMap field from the record + uint8_t OpMap; /// The opcode field from the record; this is the opcode used in the Intel /// encoding and therefore distinct from the UID uint8_t Opcode; /// The form field from the record uint8_t Form; - /// The segment override field from the record - uint8_t SegOvr; - /// The hasOpSizePrefix field from the record - bool HasOpSizePrefix; + // The encoding field from the record + uint8_t Encoding; + /// The OpSize field from the record + uint8_t OpSize; /// The hasAdSizePrefix field from the record bool HasAdSizePrefix; /// The hasREX_WPrefix field from the record bool HasREX_WPrefix; - /// The hasVEXPrefix field from the record - bool HasVEXPrefix; - /// The hasVEX_4VPrefix field from the record - bool HasVEX_4VPrefix; - /// The hasVEX_4VOp3Prefix field from the record - bool HasVEX_4VOp3Prefix; + /// The hasVEX_4V field from the record + bool HasVEX_4V; + /// The hasVEX_4VOp3 field from the record + bool HasVEX_4VOp3; /// The hasVEX_WPrefix field from the record bool HasVEX_WPrefix; /// Inferred from the operands; indicates whether the L bit in the VEX prefix is set @@ -66,8 +66,6 @@ private: bool HasMemOp4Prefix; /// The ignoreVEX_L field from the record bool IgnoresVEX_L; - /// The hasEVEXPrefix field from the record - bool HasEVEXPrefix; /// The hasEVEX_L2Prefix field from the record bool HasEVEX_L2Prefix; /// The hasEVEX_K field from the record @@ -76,10 +74,10 @@ private: bool HasEVEX_KZ; /// The hasEVEX_B field from the record bool HasEVEX_B; - /// The hasLockPrefix field from the record - bool HasLockPrefix; - /// The isCodeGenOnly filed from the record + /// The isCodeGenOnly field from the record bool IsCodeGenOnly; + /// The ForceDisassemble field from the record + bool ForceDisassemble; // Whether the instruction has the predicate "In64BitMode" bool Is64Bit; // Whether the instruction has the predicate "In32BitMode" @@ -89,12 +87,7 @@ private: std::string Name; /// The AT&T AsmString for the instruction std::string AsmString; - - /// Indicates whether the instruction is SSE - bool IsSSE; - /// Indicates whether the instruction has FR operands - MOVs with FR operands - /// are typically ignored - bool HasFROperands; + /// Indicates whether the instruction should be emitted into the decode /// tables; regardless, it will be emitted into the instruction info table bool ShouldBeEmitted; @@ -113,82 +106,53 @@ private: /// /// @return - The context in which the instruction is valid. InstructionContext insnContext() const; - - enum filter_ret { - FILTER_STRONG, // instruction has no place in the instruction tables - FILTER_WEAK, // instruction may conflict, and should be eliminated if - // it does - FILTER_NORMAL // instruction should have high priority and generate an - // error if it conflcits with any other FILTER_NORMAL - // instruction - }; - - /// filter - Determines whether the instruction should be decodable. Some - /// instructions are pure intrinsics and use unencodable operands; many - /// synthetic instructions are duplicates of other instructions; other - /// instructions only differ in the logical way in which they are used, and - /// have the same decoding. Because these would cause decode conflicts, - /// they must be filtered out. - /// - /// @return - The degree of filtering to be applied (see filter_ret). - filter_ret filter() const; - - /// hasFROperands - Returns true if any operand is a FR operand. - bool hasFROperands() const; /// typeFromString - Translates an operand type from the string provided in /// the LLVM tables to an OperandType for use in the operand specifier. /// /// @param s - The string, as extracted by calling Rec->getName() /// on a CodeGenInstruction::OperandInfo. - /// @param isSSE - Indicates whether the instruction is an SSE - /// instruction. For SSE instructions, immediates are - /// fixed-size rather than being affected by the - /// mandatory OpSize prefix. /// @param hasREX_WPrefix - Indicates whether the instruction has a REX.W /// prefix. If it does, 32-bit register operands stay /// 32-bit regardless of the operand size. - /// @param hasOpSizePrefix Indicates whether the instruction has an OpSize - /// prefix. If it does not, then 16-bit register - /// operands stay 16-bit. + /// @param OpSize Indicates the operand size of the instruction. + /// If register size does not match OpSize, then + /// register sizes keep their size. /// @return - The operand's type. - static OperandType typeFromString(const std::string& s, - bool isSSE, - bool hasREX_WPrefix, - bool hasOpSizePrefix); - + static OperandType typeFromString(const std::string& s, + bool hasREX_WPrefix, uint8_t OpSize); + /// immediateEncodingFromString - Translates an immediate encoding from the /// string provided in the LLVM tables to an OperandEncoding for use in /// the operand specifier. /// - /// @param s - See typeFromString(). - /// @param hasOpSizePrefix - Indicates whether the instruction has an OpSize - /// prefix. If it does not, then 16-bit immediate - /// operands stay 16-bit. - /// @return - The operand's encoding. + /// @param s - See typeFromString(). + /// @param OpSize - Indicates whether this is an OpSize16 instruction. + /// If it is not, then 16-bit immediate operands stay 16-bit. + /// @return - The operand's encoding. static OperandEncoding immediateEncodingFromString(const std::string &s, - bool hasOpSizePrefix); - + uint8_t OpSize); + /// rmRegisterEncodingFromString - Like immediateEncodingFromString, but /// handles operands that are in the REG field of the ModR/M byte. static OperandEncoding rmRegisterEncodingFromString(const std::string &s, - bool hasOpSizePrefix); - + uint8_t OpSize); + /// rmRegisterEncodingFromString - Like immediateEncodingFromString, but /// handles operands that are in the REG field of the ModR/M byte. static OperandEncoding roRegisterEncodingFromString(const std::string &s, - bool hasOpSizePrefix); + uint8_t OpSize); static OperandEncoding memoryEncodingFromString(const std::string &s, - bool hasOpSizePrefix); + uint8_t OpSize); static OperandEncoding relocationEncodingFromString(const std::string &s, - bool hasOpSizePrefix); + uint8_t OpSize); static OperandEncoding opcodeModifierEncodingFromString(const std::string &s, - bool hasOpSizePrefix); + uint8_t OpSize); static OperandEncoding vvvvRegisterEncodingFromString(const std::string &s, - bool HasOpSizePrefix); + uint8_t OpSize); static OperandEncoding writemaskRegisterEncodingFromString(const std::string &s, - bool HasOpSizePrefix); - + uint8_t OpSize); + /// handleOperand - Converts a single operand from the LLVM table format to /// the emitted table format, handling any duplicate operands it encounters /// and then one non-duplicate. @@ -214,8 +178,8 @@ private: const unsigned *operandMapping, OperandEncoding (*encodingFromString) (const std::string&, - bool hasOpSizePrefix)); - + uint8_t OpSize)); + /// shouldBeEmitted - Returns the shouldBeEmitted field. Although filter() /// filters out many instructions, at various points in decoding we /// determine that the instruction should not actually be decodable. In @@ -232,9 +196,7 @@ private: /// emitInstructionSpecifier - Loads the instruction specifier for the current /// instruction into a DisassemblerTables. /// - /// \param tables The DisassemblerTables to populate with the specifier for - /// the current instruction. - void emitInstructionSpecifier(DisassemblerTables &tables); + void emitInstructionSpecifier(); /// emitDecodePath - Populates the proper fields in the decode tables /// corresponding to the decode paths for this instruction. diff --git a/utils/buildit/build_llvm b/utils/buildit/build_llvm index 9e93216..bc609e9 100755 --- a/utils/buildit/build_llvm +++ b/utils/buildit/build_llvm @@ -89,6 +89,8 @@ else LLVM_VERSION="$LLVM_SUBMIT_VERSION-$LLVM_SUBMIT_SUBVERSION" fi +SDKROOT_PATH=`xcodebuild -version -sdk $SDKROOT Path` + # Figure out how many make processes to run. SYSCTL=`sysctl -n hw.activecpu` # sysctl -n hw.* does not work when invoked via B&I chroot /BuildRoot. @@ -109,7 +111,7 @@ COMMON_CONFIGURE_OPTS="\ COMMON_MAKEFLAGS="\ UNIVERSAL=1 \ - UNIVERSAL_SDK_PATH=$SDKROOT \ + UNIVERSAL_SDK_PATH=$SDKROOT_PATH \ NO_RUNTIME_LIBS=1 \ DISABLE_EDIS=1 \ REQUIRES_RTTI=1 \ @@ -141,7 +143,7 @@ if [ "$ARM_HOSTED_BUILD" = yes ]; then T=`xcrun -sdk $SDKROOT -find ${prog}` ln -s $T $DIR/bin/$prog echo '#!/bin/sh' > $P || exit 1 - echo 'exec '$T' -arch armv7 -isysroot '${SDKROOT}' "$@"' >> $P || exit 1 + echo 'exec '$T' -arch armv7 -isysroot '${SDKROOT_PATH}' "$@"' >> $P || exit 1 chmod a+x $P || exit 1 done @@ -149,7 +151,7 @@ if [ "$ARM_HOSTED_BUILD" = yes ]; then unset SDKROOT && \ $SRC_DIR/configure $COMMON_CONFIGURE_OPTS \ - --enable-targets=arm \ + --enable-targets=arm,arm64 \ --host=arm-apple-darwin10 \ --target=arm-apple-darwin10 \ --build=i686-apple-darwin10 \ @@ -171,10 +173,10 @@ if [ "$ARM_HOSTED_BUILD" = yes ]; then else # not $ARM_HOSTED_BUILD - export CC=`xcrun -find clang` - export CXX=`xcrun -find clang++` - if [ "$IOS_SIM_BUILD" = yes ]; then + export CC=`xcrun -sdk iphonesimulator -find clang` + export CXX=`xcrun -sdk iphonesimulator -find clang++` + # Use a non-standard "darwin_sim" host triple to trigger a cross-build. configure_opts="--enable-targets=x86 --host=i686-apple-darwin_sim \ --build=i686-apple-darwin10" @@ -183,15 +185,18 @@ else DEPLOYMENT_TARGET=-mios-simulator-version-min=$IPHONEOS_DEPLOYMENT_TARGET" fi else - configure_opts="--enable-targets=arm,x86" + export CC=`xcrun -sdk macosx -find clang` + export CXX=`xcrun -sdk macosx -find clang++` + + configure_opts="--enable-targets=arm,arm64,x86" if [ -n "$MACOSX_DEPLOYMENT_TARGET" ]; then COMMON_MAKEFLAGS="$COMMON_MAKEFLAGS \ DEPLOYMENT_TARGET=-mmacosx-version-min=$MACOSX_DEPLOYMENT_TARGET" fi fi - if [ $SDKROOT ]; then - CPPFLAGS="$CPPFLAGS -isysroot $SDKROOT" + if [ $SDKROOT_PATH ]; then + CPPFLAGS="$CPPFLAGS -isysroot $SDKROOT_PATH" fi for host in $HOSTS; do :; done CPPFLAGS="$CPPFLAGS -arch $host" diff --git a/utils/count/Makefile b/utils/count/Makefile index 8de076a..2a955e6 100644 --- a/utils/count/Makefile +++ b/utils/count/Makefile @@ -14,7 +14,7 @@ USEDLIBS = # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS = 1 -# Don't install this utility -NO_INSTALL = 1 +# FIXME: Don't install this utility +#NO_INSTALL = 1 include $(LEVEL)/Makefile.common diff --git a/utils/kate/llvm.xml b/utils/kate/llvm.xml index dfacfb5..5ba46ee 100644 --- a/utils/kate/llvm.xml +++ b/utils/kate/llvm.xml @@ -39,8 +39,6 @@ </list> <list name="linkage-types"> <item> private </item> - <item> linker_private </item> - <item> linker_private_weak </item> <item> internal </item> <item> available_externally </item> <item> linkonce </item> diff --git a/utils/lit/MANIFEST.in b/utils/lit/MANIFEST.in index 6491a02..7a732b3 100644 --- a/utils/lit/MANIFEST.in +++ b/utils/lit/MANIFEST.in @@ -1,7 +1,9 @@ include TODO lit.py recursive-include tests * +recursive-include examples * global-exclude *pyc global-exclude *~ prune tests/Output prune tests/*/Output prune tests/*/*/Output +prune tests/*/*/*/Output diff --git a/utils/lit/README.txt b/utils/lit/README.txt new file mode 100644 index 0000000..8cf4840 --- /dev/null +++ b/utils/lit/README.txt @@ -0,0 +1,8 @@ +=============================== + lit - A Software Testing Tool +=============================== + +lit is a portable tool for executing LLVM and Clang style test suites, +summarizing their results, and providing indication of failures. lit is designed +to be a lightweight testing tool with as simple a user interface as possible. + diff --git a/utils/lit/lit/Test.py b/utils/lit/lit/Test.py index b4988f5..e51bf12 100644 --- a/utils/lit/lit/Test.py +++ b/utils/lit/lit/Test.py @@ -128,10 +128,11 @@ class TestSuite: class Test: """Test - Information on a single test instance.""" - def __init__(self, suite, path_in_suite, config): + def __init__(self, suite, path_in_suite, config, file_path = None): self.suite = suite self.path_in_suite = path_in_suite self.config = config + self.file_path = file_path # A list of conditions under which this test is expected to fail. These # can optionally be provided by test format handlers, and will be # honored when the test result is supplied. @@ -157,6 +158,11 @@ class Test: def getFullName(self): return self.suite.config.name + ' :: ' + '/'.join(self.path_in_suite) + def getFilePath(self): + if self.file_path: + return self.file_path + return self.getSourcePath() + def getSourcePath(self): return self.suite.getSourcePath(self.path_in_suite) diff --git a/utils/lit/lit/TestingConfig.py b/utils/lit/lit/TestingConfig.py index 4a34b77..eb89067 100644 --- a/utils/lit/lit/TestingConfig.py +++ b/utils/lit/lit/TestingConfig.py @@ -1,7 +1,7 @@ import os import sys -PY2 = sys.version_info[0] < 3 +OldPy = sys.version_info[0] == 2 and sys.version_info[1] < 7 class TestingConfig: """" @@ -38,7 +38,7 @@ class TestingConfig: # The option to preserve TEMP, TMP, and TMPDIR. # This is intended to check how many temporary files would be generated # (and be not cleaned up) in automated builders. - if os.environ.has_key('LIT_PRESERVES_TMP'): + if 'LIT_PRESERVES_TMP' in os.environ: environment.update({ 'TEMP' : os.environ.get('TEMP',''), 'TMP' : os.environ.get('TMP',''), @@ -74,12 +74,14 @@ class TestingConfig: """ # Load the config script data. - f = open(path) - try: - data = f.read() - except: - litConfig.fatal('unable to load config file: %r' % (path,)) - f.close() + data = None + if not OldPy: + f = open(path) + try: + data = f.read() + except: + litConfig.fatal('unable to load config file: %r' % (path,)) + f.close() # Execute the config script to initialize the object. cfg_globals = dict(globals()) @@ -87,10 +89,10 @@ class TestingConfig: cfg_globals['lit_config'] = litConfig cfg_globals['__file__'] = path try: - if PY2: - exec("exec data in cfg_globals") + if OldPy: + execfile(path, cfg_globals) else: - exec(data, cfg_globals) + exec(compile(data, path, 'exec'), cfg_globals, None) if litConfig.debug: litConfig.note('... loaded config %r' % path) except SystemExit: diff --git a/utils/lit/lit/__init__.py b/utils/lit/lit/__init__.py index 3967fdd..46fa82d 100644 --- a/utils/lit/lit/__init__.py +++ b/utils/lit/lit/__init__.py @@ -5,7 +5,7 @@ from .main import main __author__ = 'Daniel Dunbar' __email__ = 'daniel@zuster.org' -__versioninfo__ = (0, 3, 0) +__versioninfo__ = (0, 4, 0) __version__ = '.'.join(str(v) for v in __versioninfo__) + 'dev' __all__ = [] diff --git a/utils/lit/lit/formats/googletest.py b/utils/lit/lit/formats/googletest.py index b77e184..3d14b729 100644 --- a/utils/lit/lit/formats/googletest.py +++ b/utils/lit/lit/formats/googletest.py @@ -66,7 +66,7 @@ class GoogleTest(TestFormat): # Discover the tests in this executable. for testname in self.getGTestTests(execpath, litConfig, localConfig): testPath = path_in_suite + (basename, testname) - yield lit.Test.Test(testSuite, testPath, localConfig) + yield lit.Test.Test(testSuite, testPath, localConfig, file_path=execpath) def getTestsInDirectory(self, testSuite, path_in_suite, litConfig, localConfig): diff --git a/utils/lit/lit/main.py b/utils/lit/lit/main.py index 6f672a0..c59651a 100755 --- a/utils/lit/lit/main.py +++ b/utils/lit/lit/main.py @@ -34,6 +34,10 @@ class TestingProgressDisplay(object): def update(self, test): self.completed += 1 + + if self.opts.incremental: + update_incremental_cache(test) + if self.progressBar: self.progressBar.update(float(self.completed)/self.numTests, test.getFullName()) @@ -108,6 +112,21 @@ def write_test_results(run, lit_config, testing_time, output_path): finally: f.close() +def update_incremental_cache(test): + if not test.result.code.isFailure: + return + fname = test.getFilePath() + os.utime(fname, None) + +def sort_by_incremental_cache(run): + def sortIndex(test): + fname = test.getFilePath() + try: + return -os.path.getmtime(fname) + except: + return 0 + run.tests.sort(key = lambda t: sortIndex(t)) + def main(builtinParameters = {}): # Use processes by default on Unix platforms. isWindows = platform.system() == 'Windows' @@ -117,6 +136,9 @@ def main(builtinParameters = {}): from optparse import OptionParser, OptionGroup parser = OptionParser("usage: %prog [options] {file-or-path}") + parser.add_option("", "--version", dest="show_version", + help="Show version and exit", + action="store_true", default=False) parser.add_option("-j", "--threads", dest="numThreads", metavar="N", help="Number of testing threads", type=int, action="store", default=None) @@ -179,6 +201,10 @@ def main(builtinParameters = {}): group.add_option("", "--shuffle", dest="shuffle", help="Run tests in random order", action="store_true", default=False) + group.add_option("-i", "--incremental", dest="incremental", + help="Run modified and failing tests first (updates " + "mtimes)", + action="store_true", default=False) group.add_option("", "--filter", dest="filter", metavar="REGEX", help=("Only run tests with paths matching the given " "regular expression"), @@ -205,6 +231,10 @@ def main(builtinParameters = {}): (opts, args) = parser.parse_args() + if opts.show_version: + print("lit %s" % (lit.__version__,)) + return + if not args: parser.error('No inputs specified') @@ -292,6 +322,8 @@ def main(builtinParameters = {}): # Then select the order. if opts.shuffle: random.shuffle(run.tests) + elif opts.incremental: + sort_by_incremental_cache(run) else: run.tests.sort(key = lambda t: t.getFullName()) diff --git a/utils/lit/utils/check-sdist b/utils/lit/utils/check-sdist index 6186446..743a971 100755 --- a/utils/lit/utils/check-sdist +++ b/utils/lit/utils/check-sdist @@ -12,6 +12,7 @@ find . | \ grep -v '^\./dist' | \ grep -v '^\./utils' | \ grep -v '^\./venv' | \ + grep -v '^\./notes.txt' | \ grep -v '^\./lit.egg-info' | \ grep -v '^\./lit/ExampleTests' | \ grep -v '/Output' | \ diff --git a/utils/llvm-build/llvmbuild/main.py b/utils/llvm-build/llvmbuild/main.py index eacefdf..6cb5c12 100644 --- a/utils/llvm-build/llvmbuild/main.py +++ b/utils/llvm-build/llvmbuild/main.py @@ -573,6 +573,45 @@ set_property(GLOBAL PROPERTY LLVMBUILD_LIB_DEPS_%s %s)\n""" % ( f.close() + def write_cmake_exports_fragment(self, output_path): + """ + write_cmake_exports_fragment(output_path) -> None + + Generate a CMake fragment which includes LLVMBuild library + dependencies expressed similarly to how CMake would write + them via install(EXPORT). + """ + + dependencies = list(self.get_fragment_dependencies()) + + # Write out the CMake exports fragment. + make_install_dir(os.path.dirname(output_path)) + f = open(output_path, 'w') + + f.write("""\ +# Explicit library dependency information. +# +# The following property assignments tell CMake about link +# dependencies of libraries imported from LLVM. +""") + for ci in self.ordered_component_infos: + # We only write the information for libraries currently. + if ci.type_name != 'Library': + continue + + # Skip disabled targets. + tg = ci.get_parent_target_group() + if tg and not tg.enabled: + continue + + f.write("""\ +set_property(TARGET %s PROPERTY IMPORTED_LINK_INTERFACE_LIBRARIES %s)\n""" % ( + ci.get_prefixed_library_name(), " ".join(sorted( + dep.get_prefixed_library_name() + for dep in self.get_required_libraries_for_component(ci))))) + + f.close() + def write_make_fragment(self, output_path): """ write_make_fragment(output_path) -> None @@ -780,6 +819,10 @@ def main(): dest="write_cmake_fragment", metavar="PATH", help="Write the CMake project information to PATH", action="store", default=None) + group.add_option("", "--write-cmake-exports-fragment", + dest="write_cmake_exports_fragment", metavar="PATH", + help="Write the CMake exports information to PATH", + action="store", default=None) group.add_option("", "--write-make-fragment", dest="write_make_fragment", metavar="PATH", help="Write the Makefile project information to PATH", @@ -861,6 +904,8 @@ given by --build-root) at the same SUBPATH""", # Write out the cmake fragment, if requested. if opts.write_cmake_fragment: project_info.write_cmake_fragment(opts.write_cmake_fragment) + if opts.write_cmake_exports_fragment: + project_info.write_cmake_exports_fragment(opts.write_cmake_exports_fragment) # Configure target definition files, if requested. if opts.configure_target_def_files: diff --git a/utils/llvm-lit/CMakeLists.txt b/utils/llvm-lit/CMakeLists.txt index b535eae..4b10354 100644 --- a/utils/llvm-lit/CMakeLists.txt +++ b/utils/llvm-lit/CMakeLists.txt @@ -1,4 +1,21 @@ -configure_file( - llvm-lit.in - ${LLVM_TOOLS_BINARY_DIR}/llvm-lit - ) +if (WIN32 AND NOT CYGWIN) + # llvm-lit needs suffix.py for multiprocess to find a main module. + set(suffix .py) +endif () +set(llvm_lit_path ${LLVM_RUNTIME_OUTPUT_INTDIR}/llvm-lit${suffix}) + +if(NOT "${CMAKE_CFG_INTDIR}" STREQUAL ".") + foreach(BUILD_MODE ${CMAKE_CONFIGURATION_TYPES}) + string(REPLACE ${CMAKE_CFG_INTDIR} ${BUILD_MODE} bi ${llvm_lit_path}) + configure_file( + llvm-lit.in + ${bi} + ) + endforeach() +else() + set(BUILD_MODE .) + configure_file( + llvm-lit.in + ${llvm_lit_path} + ) +endif() diff --git a/utils/llvm-lit/Makefile b/utils/llvm-lit/Makefile index 77021bb..ce1cac9 100644 --- a/utils/llvm-lit/Makefile +++ b/utils/llvm-lit/Makefile @@ -11,9 +11,14 @@ LEVEL = ../.. include $(LEVEL)/Makefile.common -all:: $(ToolDir)/llvm-lit +# llvm-lit needs suffix.py for multiprocess to find a main module. +ifeq ($(HOST_OS),MingW) + Suffix := .py +endif -$(ToolDir)/llvm-lit: llvm-lit.in Makefile $(ToolDir)/.dir +all:: $(ToolDir)/llvm-lit$(Suffix) + +$(ToolDir)/llvm-lit$(Suffix): llvm-lit.in Makefile $(ToolDir)/.dir $(Echo) "Creating 'llvm-lit' script..." $(Verb)$(ECHOPATH) s=@LLVM_SOURCE_DIR@=$(LLVM_SRC_ROOT)=g > lit.tmp $(Verb)$(ECHOPATH) s=@LLVM_BINARY_DIR@=$(LLVM_OBJ_ROOT)=g >> lit.tmp diff --git a/utils/llvm-lit/llvm-lit.in b/utils/llvm-lit/llvm-lit.in index 87878d5..a82cbf0 100755 --- a/utils/llvm-lit/llvm-lit.in +++ b/utils/llvm-lit/llvm-lit.in @@ -13,8 +13,10 @@ sys.path.insert(0, os.path.join(llvm_source_root, 'utils', 'lit')) # Set up some builtin parameters, so that by default the LLVM test suite # configuration file knows how to find the object tree. builtin_parameters = { - 'build_mode' : "@CMAKE_CFG_INTDIR@", - 'llvm_site_config' : os.path.join(llvm_obj_root, 'test', 'lit.site.cfg') + 'build_mode' : "@BUILD_MODE@", + 'llvm_site_config' : os.path.join(llvm_obj_root, 'test', 'lit.site.cfg'), + 'llvm_unit_site_config' : os.path.join(llvm_obj_root, 'test', 'Unit', + 'lit.site.cfg') } clang_obj_root = os.path.join(llvm_obj_root, 'tools', 'clang') @@ -27,6 +29,16 @@ if os.path.exists(clang_obj_root): builtin_parameters['clang_tools_extra_site_config'] = \ os.path.join(clang_tools_extra_obj_root, 'test', 'lit.site.cfg') +lld_obj_root = os.path.join(llvm_obj_root, 'projects', 'lld') +if os.path.exists(lld_obj_root): + builtin_parameters['lld_site_config'] = \ + os.path.join(lld_obj_root, 'test', 'lit.site.cfg') + +compilerrt_obj_root = os.path.join(llvm_obj_root, 'projects', 'compiler-rt') +if os.path.exists(compilerrt_obj_root): + builtin_parameters['compilerrt_site_basedir'] = \ + os.path.join(compilerrt_obj_root, 'test') + if __name__=='__main__': import lit lit.main(builtin_parameters) diff --git a/utils/llvm-native-gcc b/utils/llvm-native-gcc deleted file mode 100755 index 91a557c..0000000 --- a/utils/llvm-native-gcc +++ /dev/null @@ -1,249 +0,0 @@ -#!/usr/bin/perl -# Wrapper around LLVM tools to generate a native .o from llvm-gcc using an -# LLVM back-end (CBE by default). - -# set up defaults. -$Verbose = 0; -$SaveTemps = 1; -$PreprocessOnly = 0; -$CompileDontLink = 0; -$Backend = 'cbe'; -chomp ($ProgramName = `basename $0`); - -sub boldprint { - print "[1m", @_, "[0m"; -} - -# process command-line options. -# most of these are passed on to llvm-gcc. -$GCCOptions = ""; -for ($i = 0; $i <= $#ARGV; ++$i) { - if ($ARGV[$i] =~ /-mllvm-backend=([a-z0-9]*)/) { - $Backend = $1; - if ($ProgramName =~ /llvm-native-gcc/) { - splice (@ARGV, $i, 1); - --$i; - } - } elsif ($ARGV[$i] eq "-E") { - $PreprocessOnly = 1; - } elsif ($ARGV[$i] eq "-c") { - $GCCOptions .= " " . $ARGV[$i]; - $CompileDontLink = 1; - } elsif ($ARGV[$i] eq "-v") { - $GCCOptions .= " " . $ARGV[$i]; - $Verbose = 1; - } elsif ($ARGV[$i] eq "-o") { - $OutputFile = $ARGV[$i + 1]; - } elsif ($ARGV[$i] eq "-save-temps") { - $GCCOptions .= " " . $ARGV[$i]; - $SaveTemps = 1; - } elsif ($ARGV[$i] =~ /\.bc$/) { - push (@BytecodeFiles, $ARGV[$i]); - } elsif ($ARGV[$i] =~ /^-L/) { - $GCCOptions .= " " . $ARGV[$i]; - push (@LibDirs, $ARGV[$i]); - } elsif ($ARGV[$i] =~ /^-l/) { - $GCCOptions .= " " . $ARGV[$i]; - push (@Libs, $ARGV[$i]); - } elsif ($ARGV[$i] =~ /\.(c|cpp|cc|i|ii|C)$/) { - $LastCFile = $ARGV[$i]; - } -} - -sub GetDefaultOutputFileName { - my $DefaultOutputFileBase; - - if ($ProgramName =~ /llvm-native-gcc/) { - $DefaultOutputFileBase = $LastCFile; - } elsif ($ProgramName =~ /native-build/) { - $DefaultOutputFileBase = $BytecodeFiles[0]; - } - - my $def = $DefaultOutputFileBase; - - die "Can't figure out name of output file.\n" - unless $DefaultOutputFileBase - && (($ProgramName !~ /native-build/) - || $#BytecodeFiles == 0); - - print "Warning: defaulting output file name ", - "based on '$DefaultOutputFileBase'\n" if $Verbose; - - if ($ProgramName =~ /llvm-native-gcc/) { - $def =~ s/\.(c|cpp|cc|i|ii|C)$/.o/; - } elsif ($ProgramName =~ /native-build/) { - $def =~ s/\.bc$/.$Backend/; - if ($CompileDontLink) { - $def .= ".o"; - } - } - - return $def; -} - -# run a command, optionally echoing, and quitting if it fails: -sub run { - my $command = join(" ", @_); - print "$command\n" if $Verbose; - $command =~ s/\"/\\\"/g; - system $command and die "$0: $command failed"; -} - -sub LinkBytecodeFilesIntoTemporary { - my $FinalOutputFileName = shift @_; - my @BytecodeFiles = @_; - - my $BCFiles = join (" ", @BytecodeFiles); - my $LinkedBCFile; - if ($SaveTemps) { - $LinkedBCFile = "${FinalOutputFileName}.llvm.bc"; - } else { - $LinkedBCFile = "/tmp/nativebuild-$$.llvm.bc"; - } - run "llvm-link -o $LinkedBCFile $BCFiles"; - return $LinkedBCFile; -} - -sub CompileBytecodeToNative { - my ($BCFile, $Backend, $OutputFile) = @_; - - my $GeneratedCode; - if ($Backend eq 'cbe') { - if ($SaveTemps) { - $GeneratedCode = "${OutputFile}.c"; - } else { - $GeneratedCode = "/tmp/nativebuild-$$.c"; - } - run "llc -enable-correct-eh-support -march=c -f -o $GeneratedCode $BCFile"; - } elsif ($Backend eq 'llc') { - if ($SaveTemps) { - $GeneratedCode = "${OutputFile}.s"; - } else { - $GeneratedCode = "/tmp/nativebuild-$$.s"; - } - run "llc -enable-correct-eh-support -f -o $GeneratedCode $BCFile"; - } - my $LibDirs = join (" ", @LibDirs); - my $Libs = join (" ", @Libs); - run "gcc $GCCOptions $GeneratedCode -o $OutputFile $LibDirs $Libs"; - run "rm $BCFile $GeneratedCode" - unless $SaveTemps; -} - -sub CompileCToNative { - my ($LLVMGCCCommand, $Backend, $OutputFile) = @_; - run $LLVMGCCCommand; - if ($PreprocessOnly) { - return; - } - my $BCFile = "${OutputFile}.llvm.bc"; - if ($CompileDontLink) { - run "mv ${OutputFile} $BCFile"; - } else { # gccld messes with the output file name - run "mv ${OutputFile}.bc $BCFile"; - } - my $GeneratedCode; - if ($Backend eq 'cbe') { - $GeneratedCode = "${OutputFile}.cbe.c"; - run "llc -enable-correct-eh-support -march=c -f -o $GeneratedCode $BCFile"; - } elsif ($Backend eq 'llc') { - $GeneratedCode = "${OutputFile}.llc.s"; - run "llc -enable-correct-eh-support -f -o $GeneratedCode $BCFile"; - } - my $NativeGCCOptions = ""; - if ($CompileDontLink) { - $NativeGCCOptions = "-c"; - } - run "gcc $NativeGCCOptions $GeneratedCode -o $OutputFile"; - run "rm ${OutputFile}.llvm.bc $GeneratedCode" - unless $SaveTemps; -} - -# guess the name of the output file, if -o was not specified. -$OutputFile = GetDefaultOutputFileName () unless $OutputFile; -print "Output file is $OutputFile\n" if $Verbose; -# do all the dirty work: -if ($ProgramName eq /native-build/) { - my $LinkedBCFile = LinkBytecodeFilesIntoTemporary (@BytecodeFiles); - CompileBytecodeToNative ($LinkedBCFile, $Backend, $OutputFile); -} elsif ($ProgramName =~ /llvm-native-gcc/) { - # build the llvm-gcc command line. - $LLVMGCCCommand = join (" ", ("llvm-gcc", @ARGV)); - CompileCToNative ($LLVMGCCCommand, $Backend, $OutputFile); -} - -# we're done. -exit 0; - -__END__ - -=pod - -=head1 NAME - -llvm-native-gcc - -=head1 SYNOPSIS - -llvm-native-gcc [OPTIONS...] FILE - -native-build [OPTIONS...] FILE - -=head1 DESCRIPTION - -llvm-native-gcc is a wrapper around the LLVM command-line tools which generates -a native object (.o) file by compiling FILE with llvm-gcc, and then running -an LLVM back-end (CBE by default) over the resulting bitcode, and then -compiling the resulting code to a native object file. - -If called as "native-build", it compiles bitcode to native code, and takes -different options. - -=head1 OPTIONS - -llvm-native-gcc takes the same options as llvm-gcc. All options -except -mllvm-backend=... are passed on to llvm-gcc. - -=over 4 - -=item -mllvm-backend=BACKEND - -Use BACKEND for native code generation. - -=item -v - -Print command lines that llvm-native-gcc runs. - -=item -o FILE - -llvm-native-gcc tries to guess the name of the llvm-gcc output file by looking -for this option in the command line. If it can't find it, it finds the last C -or C++ source file named on the command line, and turns its suffix into .o. See -BUGS. - -=item -save-temps - -Save temporary files used by llvm-native-gcc (and llvm-gcc, and gcc). - -=back - -=head1 BUGS - -llvm-native-gcc only handles the case where llvm-gcc compiles a single -file per invocation. llvm-native-gcc has weak command-line argument -parsing and is a poor substitute for making gcc/gcc.c do this stuff. - -This manual page does not adequately document native-build mode. - -llvm-native-gcc is pretty gross because it represents the blind merging of two -other scripts that predated it. It could use some code clean-up. - -=head1 SEE ALSO - -gcc(1) - -=head1 AUTHOR - -Brian R. Gaeke - -=cut diff --git a/utils/llvm.grm b/utils/llvm.grm index d65f075..92a4053 100644 --- a/utils/llvm.grm +++ b/utils/llvm.grm @@ -92,8 +92,6 @@ GVInternalLinkage | dllexport | common | private - | "linker_private" - | "linker_private_weak" ; GVExternalLinkage diff --git a/utils/llvm.natvis b/utils/llvm.natvis index 6b4ef83..9874ce5 100644 --- a/utils/llvm.natvis +++ b/utils/llvm.natvis @@ -6,22 +6,10 @@ Put this file into "%USERPROFILE%\Documents\Visual Studio 2012\Visualizers" or create a symbolic link so it updates automatically.
-->
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
- <Type Name="llvm::SmallVector<*,*>">
- <DisplayString Condition="(($T1*)EndX - ($T1*)BeginX) == 0">empty</DisplayString>
- <DisplayString Condition="(($T1*)EndX - ($T1*)BeginX) != 0">{{ size={($T1*)EndX - ($T1*)BeginX} }}</DisplayString>
- <Expand>
- <Item Name="[size]">($T1*)EndX - ($T1*)BeginX</Item>
- <Item Name="[capacity]">($T1*)CapacityX - ($T1*)BeginX</Item>
- <ArrayItems>
- <Size>($T1*)EndX - ($T1*)BeginX</Size>
- <ValuePointer>($T1*)BeginX</ValuePointer>
- </ArrayItems>
- </Expand>
- </Type>
<Type Name="llvm::SmallVectorImpl<*>">
<DisplayString Condition="(($T1*)EndX - ($T1*)BeginX) == 0">empty</DisplayString>
- <DisplayString Condition="(($T1*)EndX - ($T1*)BeginX) != 0">[{($T1*)EndX - ($T1*)BeginX}]</DisplayString>
+ <DisplayString Condition="(($T1*)EndX - ($T1*)BeginX) != 0">{{ size={($T1*)EndX - ($T1*)BeginX} }}</DisplayString>
<Expand>
<Item Name="[size]">($T1*)EndX - ($T1*)BeginX</Item>
<Item Name="[capacity]">($T1*)CapacityX - ($T1*)BeginX</Item>
@@ -46,10 +34,10 @@ or create a symbolic link so it updates automatically. </Type>
<Type Name="llvm::StringRef">
- <DisplayString>[{Length}] {Data,s}</DisplayString>
- <StringView>Data,s</StringView>
+ <DisplayString>{Data,[Length]s}</DisplayString>
+ <StringView>Data,[Length]s</StringView>
<Expand>
- <Item Name="[length]">Length</Item>
+ <Item Name="[size]">Length</Item>
<ArrayItems>
<Size>Length</Size>
<ValuePointer>Data</ValuePointer>
@@ -58,43 +46,43 @@ or create a symbolic link so it updates automatically. </Type>
<Type Name="llvm::PointerIntPair<*,*,*,*>">
- <DisplayString>{Value & PointerBitMask} [{(Value >> IntShift) & IntMask}]</DisplayString>
+ <DisplayString>{(void*)(Value & PointerBitMask)} [{($T3)((Value >> IntShift) & IntMask)}]</DisplayString>
<Expand>
- <Item Name="[ptr]">Value & PointerBitMask</Item>
- <Item Name="[int]">(Value >> IntShift) & IntMask</Item>
+ <Item Name="[ptr]">($T1*)(Value & PointerBitMask)</Item>
+ <Item Name="[int]">($T3)((Value >> IntShift) & IntMask)</Item>
</Expand>
</Type>
<Type Name="llvm::PointerUnion<*,*>">
- <DisplayString Condition="((Val.Value >> Val.IntShift) & Val.IntMask) == 0">[P1] {($T1)(Val.Value & Val.PointerBitMask)}</DisplayString>
- <DisplayString Condition="((Val.Value >> Val.IntShift) & Val.IntMask) != 0">[P2] {($T2)(Val.Value & Val.PointerBitMask)}</DisplayString>
+ <DisplayString Condition="((Val.Value >> Val.IntShift) & Val.IntMask) == 0">{"$T1", s8b} {(void*)(Val.Value & Val.PointerBitMask)}</DisplayString>
+ <DisplayString Condition="((Val.Value >> Val.IntShift) & Val.IntMask) != 0">{"$T2", s8b} {(void*)(Val.Value & Val.PointerBitMask)}</DisplayString>
<Expand>
- <Item Name="[ptr]" Condition="((Val.Value >> Val.IntShift) & Val.IntMask) == 0">($T1)(Val.Value & Val.PointerBitMask)</Item>
- <Item Name="[ptr]" Condition="((Val.Value >> Val.IntShift) & Val.IntMask) != 0">($T2)(Val.Value & Val.PointerBitMask)</Item>
+ <ExpandedItem Condition="((Val.Value >> Val.IntShift) & Val.IntMask) == 0">($T1)(Val.Value & Val.PointerBitMask)</ExpandedItem>
+ <ExpandedItem Condition="((Val.Value >> Val.IntShift) & Val.IntMask) != 0">($T2)(Val.Value & Val.PointerBitMask)</ExpandedItem>
</Expand>
</Type>
<Type Name="llvm::PointerUnion3<*,*,*>">
- <DisplayString Condition="(Val.Val.Value & 2) != 2 && (Val.Val.Value & 1) != 1">[P1] {($T1)((Val.Val.Value >> 2) << 2)}</DisplayString>
- <DisplayString Condition="(Val.Val.Value & 2) == 2">[P2] {($T2)((Val.Val.Value >> 2) << 2)}</DisplayString>
- <DisplayString Condition="(Val.Val.Value & 1) == 1">[P3] {($T3)((Val.Val.Value >> 2) << 2)}</DisplayString>
+ <DisplayString Condition="(Val.Val.Value & 2) != 2 && (Val.Val.Value & 1) != 1">{"$T1", s8b} {(void*)((Val.Val.Value >> 2) << 2)}</DisplayString>
+ <DisplayString Condition="(Val.Val.Value & 2) == 2">{"$T2", s8b} {(void*)((Val.Val.Value >> 2) << 2)}</DisplayString>
+ <DisplayString Condition="(Val.Val.Value & 1) == 1">{"$T3", s8b} {(void*)((Val.Val.Value >> 2) << 2)}</DisplayString>
<Expand>
- <Item Name="[ptr]" Condition="(Val.Val.Value & 2) != 2 && (Val.Val.Value & 1) != 1">($T1)((Val.Val.Value >> 2) << 2)</Item>
- <Item Name="[ptr]" Condition="(Val.Val.Value & 2) == 2">($T2)((Val.Val.Value >> 2) << 2)</Item>
- <Item Name="[ptr]" Condition="(Val.Val.Value & 1) == 1">($T3)((Val.Val.Value >> 2) << 2)</Item>
+ <ExpandedItem Condition="(Val.Val.Value & 2) != 2 && (Val.Val.Value & 1) != 1">($T1)((Val.Val.Value >> 2) << 2)</ExpandedItem>
+ <ExpandedItem Condition="(Val.Val.Value & 2) == 2">($T2)((Val.Val.Value >> 2) << 2)</ExpandedItem>
+ <ExpandedItem Condition="(Val.Val.Value & 1) == 1">($T3)((Val.Val.Value >> 2) << 2)</ExpandedItem>
</Expand>
</Type>
<Type Name="llvm::PointerUnion4<*,*,*,*>">
- <DisplayString Condition="(Val.Val.Value & 3) != 3 && (Val.Val.Value & 2) != 2 && (Val.Val.Value & 1) != 1">[P1] {($T1)((Val.Val.Value >> 2) << 2)}</DisplayString>
- <DisplayString Condition="(Val.Val.Value & 3) != 3 && (Val.Val.Value & 2) == 2">[P2] {($T2)((Val.Val.Value >> 2) << 2)}</DisplayString>
- <DisplayString Condition="(Val.Val.Value & 3) != 3 && (Val.Val.Value & 1) == 1">[P3] {($T3)((Val.Val.Value >> 2) << 2)}</DisplayString>
- <DisplayString Condition="(Val.Val.Value & 3) == 3">[P4] {($T4)((Val.Val.Value >> 2) << 2)}</DisplayString>
+ <DisplayString Condition="(Val.Val.Value & 3) != 3 && (Val.Val.Value & 2) != 2 && (Val.Val.Value & 1) != 1">{"$T1", s8b} {(void*)((Val.Val.Value >> 2) << 2)}</DisplayString>
+ <DisplayString Condition="(Val.Val.Value & 3) != 3 && (Val.Val.Value & 2) == 2">{"$T2", s8b} {(void*)((Val.Val.Value >> 2) << 2)}</DisplayString>
+ <DisplayString Condition="(Val.Val.Value & 3) != 3 && (Val.Val.Value & 1) == 1">{"$T3", s8b} {(void*)((Val.Val.Value >> 2) << 2)}</DisplayString>
+ <DisplayString Condition="(Val.Val.Value & 3) == 3">{"$T4", s8b} {(void*)((Val.Val.Value >> 2) << 2)}</DisplayString>
<Expand>
- <Item Name="[ptr]" Condition="(Val.Val.Value & 3) != 3 && (Val.Val.Value & 2) != 2 && (Val.Val.Value & 1) != 1">($T1)((Val.Val.Value >> 2) << 2)</Item>
- <Item Name="[ptr]" Condition="(Val.Val.Value & 3) != 3 && (Val.Val.Value & 2) == 2">($T2)((Val.Val.Value >> 2) << 2)</Item>
- <Item Name="[ptr]" Condition="(Val.Val.Value & 3) != 3 && (Val.Val.Value & 1) == 1">($T3)((Val.Val.Value >> 2) << 2)</Item>
- <Item Name="[ptr]" Condition="(Val.Val.Value & 3) == 3">($T4)((Val.Val.Value >> 2) << 2)</Item>
+ <ExpandedItem Condition="(Val.Val.Value & 3) != 3 && (Val.Val.Value & 2) != 2 && (Val.Val.Value & 1) != 1">($T1)((Val.Val.Value >> 2) << 2)</ExpandedItem>
+ <ExpandedItem Condition="(Val.Val.Value & 3) != 3 && (Val.Val.Value & 2) == 2">($T2)((Val.Val.Value >> 2) << 2)</ExpandedItem>
+ <ExpandedItem Condition="(Val.Val.Value & 3) != 3 && (Val.Val.Value & 1) == 1">($T3)((Val.Val.Value >> 2) << 2)</ExpandedItem>
+ <ExpandedItem Condition="(Val.Val.Value & 3) == 3">($T4)((Val.Val.Value >> 2) << 2)</ExpandedItem>
</Expand>
</Type>
@@ -116,7 +104,7 @@ or create a symbolic link so it updates automatically. <DisplayString Condition="(Obj != 0) && (Obj->ref_cnt != 1)">RefPtr [{Obj->ref_cnt} refs] {*Obj}</DisplayString>
<Expand>
<Item Condition="Obj != 0" Name="[refs]">Obj->ref_cnt</Item>
- <Item Condition="Obj != 0" Name="[ptr]">Obj</Item>
+ <ExpandedItem Condition="Obj != 0">Obj</ExpandedItem>
</Expand>
</Type>
@@ -124,29 +112,29 @@ or create a symbolic link so it updates automatically. <DisplayString Condition="Ptr == 0">empty</DisplayString>
<DisplayString Condition="Ptr != 0">OwningPtr {*Ptr}</DisplayString>
<Expand>
- <Item Condition="Ptr != 0" Name="[ptr]">Ptr</Item>
+ <ExpandedItem Condition="Ptr != 0">Ptr</ExpandedItem>
</Expand>
</Type>
<Type Name="llvm::SmallPtrSet<*,*>">
- <DisplayString Condition="CurArray == SmallArray">{{ [Small Mode] elements={NumElements}, arraySize={CurArraySize} }}</DisplayString>
- <DisplayString Condition="CurArray != SmallArray">{{ [Big Mode] elements={NumElements}, arraySize={CurArraySize} }}</DisplayString>
+ <DisplayString Condition="CurArray == SmallArray">{{ [Small Mode] size={NumElements}, capacity={CurArraySize} }}</DisplayString>
+ <DisplayString Condition="CurArray != SmallArray">{{ [Big Mode] size={NumElements}, capacity={CurArraySize} }}</DisplayString>
<Expand>
- <Item Name="[NumElements]">NumElements</Item>
- <Item Name="[CurArraySize]">CurArraySize</Item>
- <IndexListItems>
- <Size>CurArraySize + 1</Size>
- <ValueNode>($T1*)&CurArray[$i]</ValueNode>
- </IndexListItems>
+ <Item Name="[size]">NumElements</Item>
+ <Item Name="[capacity]">CurArraySize</Item>
+ <ArrayItems>
+ <Size>CurArraySize</Size>
+ <ValuePointer>($T1*)CurArray</ValuePointer>
+ </ArrayItems>
</Expand>
</Type>
<Type Name="llvm::DenseMap<*,*,*>">
<DisplayString Condition="NumEntries == 0">empty</DisplayString>
- <DisplayString Condition="NumEntries != 0">{{ entries={NumEntries}, buckets={NumBuckets} }}</DisplayString>
+ <DisplayString Condition="NumEntries != 0">{{ size={NumEntries}, buckets={NumBuckets} }}</DisplayString>
<Expand>
- <Item Name="[NumEntries]">NumEntries</Item>
- <Item Name="[NumBuckets]">NumBuckets</Item>
+ <Item Name="[size]">NumEntries</Item>
+ <Item Name="[buckets]">NumBuckets</Item>
<ArrayItems>
<Size>NumBuckets</Size>
<ValuePointer>Buckets</ValuePointer>
@@ -155,22 +143,22 @@ or create a symbolic link so it updates automatically. </Type>
<Type Name="llvm::StringMap<*,*>">
- <DisplayString>{{ NumBuckets={NumBuckets}, ItemSize={ItemSize} }}</DisplayString>
+ <DisplayString>{{ size={ItemSize}, buckets={NumBuckets} }}</DisplayString>
<Expand>
- <Item Name="[NumBuckets]">NumBuckets</Item>
- <Item Name="[ItemSize]">ItemSize</Item>
- <IndexListItems>
+ <Item Name="[size]">ItemSize</Item>
+ <Item Name="[buckets]">NumBuckets</Item>
+ <ArrayItems>
<Size>NumBuckets</Size>
- <ValueNode>(llvm::StringMapEntry<$T1>*)TheTable[$i]</ValueNode>
- </IndexListItems>
+ <ValuePointer>(MapEntryTy**)TheTable</ValuePointer>
+ </ArrayItems>
</Expand>
</Type>
<Type Name="llvm::StringMapEntry<*>">
<DisplayString Condition="StrLen == 0">empty</DisplayString>
- <DisplayString Condition="StrLen != 0">({((llvm::StringMapEntry<$T1>*)this)+1,s}, {second})</DisplayString>
+ <DisplayString Condition="StrLen != 0">({this+1,s}, {second})</DisplayString>
<Expand>
- <Item Name="[key]">((llvm::StringMapEntry<$T1>*)this)+1,s</Item>
+ <Item Name="[key]">this+1,s</Item>
<Item Name="[value]" Condition="StrLen != 0">second</Item>
</Expand>
</Type>
@@ -178,4 +166,12 @@ or create a symbolic link so it updates automatically. <Type Name="llvm::Triple">
<DisplayString>{Data}</DisplayString>
</Type>
+
+ <Type Name="llvm::Optional<*>">
+ <DisplayString Condition="!hasVal">empty</DisplayString>
+ <DisplayString Condition="hasVal">{*(($T1 *)(unsigned char *)storage.buffer)}</DisplayString>
+ <Expand>
+ <Item Name="[underlying]" Condition="hasVal">*(($T1 *)(unsigned char *)storage.buffer)</Item>
+ </Expand>
+ </Type>
</AutoVisualizer>
diff --git a/utils/not/CMakeLists.txt b/utils/not/CMakeLists.txt index 5ff14d6..4a92348 100644 --- a/utils/not/CMakeLists.txt +++ b/utils/not/CMakeLists.txt @@ -3,9 +3,3 @@ add_llvm_utility(not ) target_link_libraries(not LLVMSupport) -if( MINGW ) - target_link_libraries(not imagehlp psapi shell32) -endif( MINGW ) -if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD ) - target_link_libraries(not pthread) -endif() diff --git a/utils/not/Makefile b/utils/not/Makefile index f37f166..26b7450 100644 --- a/utils/not/Makefile +++ b/utils/not/Makefile @@ -14,8 +14,8 @@ USEDLIBS = LLVMSupport.a # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS = 1 -# Don't install this utility -NO_INSTALL = 1 +# FIXME: Don't install this utility +#NO_INSTALL = 1 include $(LEVEL)/Makefile.common diff --git a/utils/release/test-release.sh b/utils/release/test-release.sh index 91dac4c..f10b822 100755 --- a/utils/release/test-release.sh +++ b/utils/release/test-release.sh @@ -234,7 +234,7 @@ function export_sources() { check_valid_urls for proj in $projects ; do - echo "# Exporting $proj $Release-RC$RC sources" + echo "# Exporting $proj $Release-$RC sources" if ! svn export -q $Base_url/$proj/tags/RELEASE_$Release_no_dot/$RC $proj.src ; then echo "error: failed to export $proj project" exit 1 diff --git a/utils/test_debuginfo.pl b/utils/test_debuginfo.pl index a6b6137..aaf90d9 100755 --- a/utils/test_debuginfo.pl +++ b/utils/test_debuginfo.pl @@ -71,6 +71,8 @@ system("$my_debugger $debugger_options $debugger_script_file $executable_file > # validate output. system("FileCheck", "-input-file", "$output_file", "$testcase_file"); if ($?>>8 == 1) { + print "Debugger output was:\n"; + system("cat", "$output_file"); exit 1; } else { diff --git a/utils/unittest/CMakeLists.txt b/utils/unittest/CMakeLists.txt index fd1a048..b6d2d6d 100644 --- a/utils/unittest/CMakeLists.txt +++ b/utils/unittest/CMakeLists.txt @@ -40,8 +40,9 @@ endif () add_llvm_library(gtest googletest/src/gtest-all.cc - ) -add_llvm_library(gtest_main - UnitTestMain/TestMain.cpp + LINK_LIBS + LLVMSupport # Depends on llvm::raw_ostream ) + +add_subdirectory(UnitTestMain) diff --git a/utils/unittest/UnitTestMain/CMakeLists.txt b/utils/unittest/UnitTestMain/CMakeLists.txt new file mode 100644 index 0000000..65ef97b --- /dev/null +++ b/utils/unittest/UnitTestMain/CMakeLists.txt @@ -0,0 +1,7 @@ +add_llvm_library(gtest_main + TestMain.cpp + + LINK_LIBS + gtest + LLVMSupport # Depends on llvm::cl + ) diff --git a/utils/unittest/googletest/README.LLVM b/utils/unittest/googletest/README.LLVM index 1a6f0f5..16bfffd 100644 --- a/utils/unittest/googletest/README.LLVM +++ b/utils/unittest/googletest/README.LLVM @@ -16,6 +16,7 @@ $ rm -f src/gtest_main.cc $ mv COPYING LICENSE.TXT Modified as follows: +* Added support for FreeBSD. * To GTestStreamToHelper in include/gtest/internal/gtest-internal.h, added the ability to stream with raw_os_ostream. * To refresh Haiku support in include/gtest/internal/gtest-port.h, diff --git a/utils/unittest/googletest/include/gtest/gtest-typed-test.h b/utils/unittest/googletest/include/gtest/gtest-typed-test.h index fe1e83b..6ded1b1 100644 --- a/utils/unittest/googletest/include/gtest/gtest-typed-test.h +++ b/utils/unittest/googletest/include/gtest/gtest-typed-test.h @@ -236,6 +236,8 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes); template <typename gtest_TypeParam_> \ void GTEST_CASE_NAMESPACE_(CaseName)::TestName<gtest_TypeParam_>::TestBody() +// Silencing C99 build warnings +#if 0 # define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \ namespace GTEST_CASE_NAMESPACE_(CaseName) { \ typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \ @@ -243,6 +245,7 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes); static const char* const GTEST_REGISTERED_TEST_NAMES_(CaseName) = \ GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).VerifyRegisteredTestNames(\ __FILE__, __LINE__, #__VA_ARGS__) +#endif // The 'Types' template argument below must have spaces around it // since some compilers may choke on '>>' when passing a template diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-port.h b/utils/unittest/googletest/include/gtest/internal/gtest-port.h index 32fd9c6..f5bfd4e 100644 --- a/utils/unittest/googletest/include/gtest/internal/gtest-port.h +++ b/utils/unittest/googletest/include/gtest/internal/gtest-port.h @@ -86,6 +86,7 @@ // the given platform; otherwise undefined): // GTEST_OS_AIX - IBM AIX // GTEST_OS_CYGWIN - Cygwin +// GTEST_OS_FREEBSD - FreeBSD // GTEST_OS_HAIKU - Haiku // GTEST_OS_HPUX - HP-UX // GTEST_OS_LINUX - Linux @@ -228,6 +229,8 @@ # endif // _WIN32_WCE #elif defined __APPLE__ # define GTEST_OS_MAC 1 +#elif defined __FreeBSD__ +# define GTEST_OS_FREEBSD 1 #elif defined __linux__ # define GTEST_OS_LINUX 1 # if defined(ANDROID) || defined(__ANDROID__) @@ -421,7 +424,8 @@ // // To disable threading support in Google Test, add -DGTEST_HAS_PTHREAD=0 // to your compiler flags. -# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX) +# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || \ + GTEST_OS_HPUX || GTEST_OS_FREEBSD) #endif // GTEST_HAS_PTHREAD #if GTEST_HAS_PTHREAD @@ -545,7 +549,8 @@ // pops up a dialog window that cannot be suppressed programmatically. #if (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || \ (GTEST_OS_WINDOWS_DESKTOP && _MSC_VER >= 1400) || \ - GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX) + GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || \ + GTEST_OS_HPUX || GTEST_OS_FREEBSD) # define GTEST_HAS_DEATH_TEST 1 # include <vector> // NOLINT #endif diff --git a/utils/vim/llvm.vim b/utils/vim/llvm.vim index c2ec57c..2b91823 100644 --- a/utils/vim/llvm.vim +++ b/utils/vim/llvm.vim @@ -43,8 +43,7 @@ syn keyword llvmKeyword blockaddress byval c catch cc ccc cleanup coldcc common syn keyword llvmKeyword constant datalayout declare default define deplibs syn keyword llvmKeyword dllexport dllimport except extern_weak external fastcc syn keyword llvmKeyword filter gc global hidden initialexec inlinehint inreg -syn keyword llvmKeyword intel_ocl_bicc inteldialect internal linker_private -syn keyword llvmKeyword linker_private_weak +syn keyword llvmKeyword intel_ocl_bicc inteldialect internal syn keyword llvmKeyword linkonce linkonce_odr syn keyword llvmKeyword localdynamic localexec minsize module monotonic syn keyword llvmKeyword msp430_intrcc naked nest noalias nocapture diff --git a/utils/wciia.py b/utils/wciia.py index c838819..eaa232f 100755 --- a/utils/wciia.py +++ b/utils/wciia.py @@ -110,7 +110,7 @@ if not os.path.exists(path): owners_name = find_owners(path) -# be gramatically correct +# be grammatically correct print "The owner(s) of the (" + path + ") is(are) : " + str(owners_name) exit(0) diff --git a/utils/yaml-bench/YAMLBench.cpp b/utils/yaml-bench/YAMLBench.cpp index f335605..3e80f23 100644 --- a/utils/yaml-bench/YAMLBench.cpp +++ b/utils/yaml-bench/YAMLBench.cpp @@ -69,7 +69,7 @@ static std::string prettyTag(yaml::Node *N) { if (StringRef(Tag).startswith("tag:yaml.org,2002:")) { std::string Ret = "!!"; Ret += StringRef(Tag).substr(18); - return llvm_move(Ret); + return std::move(Ret); } std::string Ret = "!<"; Ret += Tag; @@ -188,7 +188,7 @@ static std::string createJSONText(size_t MemoryMB, unsigned ValueSize) { int main(int argc, char **argv) { llvm::cl::ParseCommandLineOptions(argc, argv); if (Input.getNumOccurrences()) { - OwningPtr<MemoryBuffer> Buf; + std::unique_ptr<MemoryBuffer> Buf; if (MemoryBuffer::getFileOrSTDIN(Input, Buf)) return 1; |