diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:08:18 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:08:18 +0000 |
commit | 5ca98fd98791947eba83a1ed3f2c8191ef7afa6c (patch) | |
tree | f5944309621cee4fe0976be6f9ac619b7ebfc4c2 /utils | |
parent | 68bcb7db193e4bc81430063148253d30a791023e (diff) | |
download | src-test2-5ca98fd98791947eba83a1ed3f2c8191ef7afa6c.tar.gz src-test2-5ca98fd98791947eba83a1ed3f2c8191ef7afa6c.zip |
Notes
Diffstat (limited to 'utils')
97 files changed, 2847 insertions, 3390 deletions
diff --git a/utils/FileCheck/CMakeLists.txt b/utils/FileCheck/CMakeLists.txt index d691ceb429cc..999320f78af2 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 f2510d7dfd70..9e6a6a2c8ab4 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" @@ -28,11 +27,11 @@ #include "llvm/Support/Signals.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" #include <algorithm> #include <cctype> #include <map> #include <string> +#include <system_error> #include <vector> using namespace llvm; @@ -51,6 +50,13 @@ static cl::opt<bool> NoCanonicalizeWhiteSpace("strict-whitespace", cl::desc("Do not treat all horizontal whitespace as equivalent")); +static cl::list<std::string> ImplicitCheckNot( + "implicit-check-not", + cl::desc("Add an implicit negative check with this pattern to every\n" + "positive check. This can be used to ensure that no instances of\n" + "this pattern occur which are not matched by a positive pattern"), + cl::value_desc("pattern")); + typedef cl::list<std::string>::const_iterator prefix_iterator; //===----------------------------------------------------------------------===// @@ -136,7 +142,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 +160,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 +233,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 +319,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 +406,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 +538,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 +559,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 +778,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,24 +827,43 @@ 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; - if (error_code ec = - MemoryBuffer::getFileOrSTDIN(CheckFilename, File)) { - errs() << "Could not open check file '" << CheckFilename << "': " - << ec.message() << '\n'; + ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = + MemoryBuffer::getFileOrSTDIN(CheckFilename); + if (std::error_code EC = FileOrErr.getError()) { + errs() << "Could not open check file '" << CheckFilename + << "': " << EC.message() << '\n'; return true; } // 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); + MemoryBuffer *F = CanonicalizeInputFile(FileOrErr.get().release(), + NoCanonicalizeWhiteSpace); SM.AddNewSourceBuffer(F, SMLoc()); // Find all instances of CheckPrefix followed by : in the file. StringRef Buffer = F->getBuffer(); - std::vector<Pattern> DagNotMatches; + + std::vector<Pattern> ImplicitNegativeChecks; + for (const auto &PatternString : ImplicitCheckNot) { + // Create a buffer with fake command line content in order to display the + // command line option responsible for the specific implicit CHECK-NOT. + std::string Prefix = std::string("-") + ImplicitCheckNot.ArgStr + "='"; + std::string Suffix = "'"; + MemoryBuffer *CmdLine = MemoryBuffer::getMemBufferCopy( + Prefix + PatternString + Suffix, "command line"); + StringRef PatternInBuffer = + CmdLine->getBuffer().substr(Prefix.size(), PatternString.size()); + SM.AddNewSourceBuffer(CmdLine, SMLoc()); + + ImplicitNegativeChecks.push_back(Pattern(Check::CheckNot)); + ImplicitNegativeChecks.back().ParsePattern(PatternInBuffer, + "IMPLICIT-CHECK", SM, 0); + } + + + std::vector<Pattern> DagNotMatches = ImplicitNegativeChecks; // LineNumber keeps track of the line on which CheckPrefix instances are // found. @@ -933,6 +936,7 @@ static bool ReadCheckFile(SourceMgr &SM, PatternLoc, CheckTy)); std::swap(DagNotMatches, CheckStrings.back().DagNotStrings); + DagNotMatches = ImplicitNegativeChecks; } // Add an EOF pattern for any trailing CHECK-DAG/-NOTs, and use the first @@ -988,7 +992,8 @@ static void PrintCheckFailed(const SourceMgr &SM, const CheckString &CheckStr, /// CountNumNewlinesBetween - Count the number of newlines in the specified /// range. -static unsigned CountNumNewlinesBetween(StringRef Range) { +static unsigned CountNumNewlinesBetween(StringRef Range, + const char *&FirstNewLine) { unsigned NumNewLines = 0; while (1) { // Scan for newline. @@ -1003,6 +1008,9 @@ static unsigned CountNumNewlinesBetween(StringRef Range) { (Range[0] != Range[1])) Range = Range.substr(1); Range = Range.substr(1); + + if (NumNewLines == 1) + FirstNewLine = Range.begin(); } } @@ -1062,7 +1070,8 @@ bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const { SMLoc::getFromPointer(Buffer.data())))->getBufferStart() && "CHECK-NEXT can't be the first check in a file"); - unsigned NumNewLines = CountNumNewlinesBetween(Buffer); + const char *FirstNewLine = nullptr; + unsigned NumNewLines = CountNumNewlinesBetween(Buffer, FirstNewLine); if (NumNewLines == 0) { SM.PrintMessage(Loc, SourceMgr::DK_Error, Prefix + @@ -1081,6 +1090,8 @@ bool CheckString::CheckNext(const SourceMgr &SM, StringRef Buffer) const { SourceMgr::DK_Note, "'next' match was here"); SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), SourceMgr::DK_Note, "previous match ended here"); + SM.PrintMessage(SMLoc::getFromPointer(FirstNewLine), SourceMgr::DK_Note, + "non-matching line after previous match is here"); return true; } @@ -1240,13 +1251,14 @@ int main(int argc, char **argv) { return 2; // Open the file to check and add it to SourceMgr. - OwningPtr<MemoryBuffer> File; - if (error_code ec = - MemoryBuffer::getFileOrSTDIN(InputFilename, File)) { - errs() << "Could not open input file '" << InputFilename << "': " - << ec.message() << '\n'; + ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr = + MemoryBuffer::getFileOrSTDIN(InputFilename); + if (std::error_code EC = FileOrErr.getError()) { + errs() << "Could not open input file '" << InputFilename + << "': " << EC.message() << '\n'; return 2; } + std::unique_ptr<MemoryBuffer> File = std::move(FileOrErr.get()); if (File->getBufferSize() == 0) { errs() << "FileCheck error: '" << InputFilename << "' is empty.\n"; @@ -1256,7 +1268,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 268b7bc919a1..b8762365984d 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 deleted file mode 100644 index 0114e50c6274..000000000000 --- a/utils/FileUpdate/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -add_llvm_utility(FileUpdate - FileUpdate.cpp - ) - -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 deleted file mode 100644 index fbcd9277cd51..000000000000 --- a/utils/FileUpdate/FileUpdate.cpp +++ /dev/null @@ -1,87 +0,0 @@ -//===- FileUpdate.cpp - Conditionally update a file -----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// FileUpdate is a utility for conditionally updating a file from its input -// based on whether the input differs from the output. It is used to avoid -// unnecessary modifications in a build system. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/OwningPtr.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/Signals.h" -#include "llvm/Support/ToolOutputFile.h" -#include "llvm/Support/system_error.h" -using namespace llvm; - -static cl::opt<bool> -Quiet("quiet", cl::desc("Don't print unnecessary status information"), - cl::init(false)); - -static cl::opt<std::string> -InputFilename("input-file", cl::desc("Input file (defaults to stdin)"), - cl::init("-"), cl::value_desc("filename")); - -static cl::opt<std::string> -OutputFilename(cl::Positional, cl::desc("<output-file>"), cl::Required); - -int main(int argc, char **argv) { - sys::PrintStackTraceOnErrorSignal(); - PrettyStackTraceProgram X(argc, argv); - cl::ParseCommandLineOptions(argc, argv); - - if (OutputFilename == "-") { - errs() << argv[0] << ": error: Can't update standard output\n"; - return 1; - } - - // Get the input data. - OwningPtr<MemoryBuffer> In; - if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename, In)) { - errs() << argv[0] << ": error: Unable to get input '" - << InputFilename << "': " << ec.message() << '\n'; - return 1; - } - - // Get the output data. - OwningPtr<MemoryBuffer> Out; - MemoryBuffer::getFile(OutputFilename.c_str(), Out); - - // If the output exists and the contents match, we are done. - if (Out && In->getBufferSize() == Out->getBufferSize() && - memcmp(In->getBufferStart(), Out->getBufferStart(), - Out->getBufferSize()) == 0) { - if (!Quiet) - errs() << argv[0] << ": Not updating '" << OutputFilename - << "', contents match input.\n"; - return 0; - } - - // Otherwise, overwrite the output. - if (!Quiet) - errs() << argv[0] << ": Updating '" << OutputFilename - << "', contents changed.\n"; - std::string ErrorStr; - tool_output_file OutStream(OutputFilename.c_str(), ErrorStr, - sys::fs::F_Binary); - if (!ErrorStr.empty()) { - errs() << argv[0] << ": Unable to write output '" - << OutputFilename << "': " << ErrorStr << '\n'; - return 1; - } - - OutStream.os().write(In->getBufferStart(), In->getBufferSize()); - - // Declare success. - OutStream.keep(); - - return 0; -} diff --git a/utils/FileUpdate/Makefile b/utils/FileUpdate/Makefile deleted file mode 100644 index 1e6c0a838c27..000000000000 --- a/utils/FileUpdate/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -##===- utils/FileUpdate/Makefile ---------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../.. -TOOLNAME = FileUpdate -USEDLIBS = LLVMSupport.a - -# This tool has no plugins, optimize startup time. -TOOL_NO_EXPORTS = 1 - -# Don't install this utility -NO_INSTALL = 1 - -include $(LEVEL)/Makefile.common - diff --git a/utils/KillTheDoctor/KillTheDoctor.cpp b/utils/KillTheDoctor/KillTheDoctor.cpp index feba2e54f6a5..111bad209584 100644 --- a/utils/KillTheDoctor/KillTheDoctor.cpp +++ b/utils/KillTheDoctor/KillTheDoctor.cpp @@ -40,14 +40,15 @@ #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/WindowsError.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" #include "llvm/Support/type_traits.h" #include <algorithm> #include <cerrno> #include <cstdlib> #include <map> #include <string> +#include <system_error> // These includes must be last. #include <Windows.h> @@ -169,8 +170,10 @@ namespace { typedef ScopedHandle<FileHandle> FileScopedHandle; } -static error_code GetFileNameFromHandle(HANDLE FileHandle, - std::string& Name) { +static std::error_code windows_error(DWORD E) { return mapWindowsError(E); } + +static std::error_code GetFileNameFromHandle(HANDLE FileHandle, + std::string &Name) { char Filename[MAX_PATH+1]; bool Success = false; Name.clear(); @@ -210,7 +213,7 @@ static error_code GetFileNameFromHandle(HANDLE FileHandle, return windows_error(::GetLastError()); else { Name = Filename; - return windows_error::success; + return std::error_code(); } } @@ -220,7 +223,8 @@ static error_code GetFileNameFromHandle(HANDLE FileHandle, /// extension is present, try all extensions in PATHEXT. /// @return If ec == errc::success, The absolute path to the program. Otherwise /// the return value is undefined. -static std::string FindProgram(const std::string &Program, error_code &ec) { +static std::string FindProgram(const std::string &Program, + std::error_code &ec) { char PathName[MAX_PATH + 1]; typedef SmallVector<StringRef, 12> pathext_t; pathext_t pathext; @@ -245,11 +249,11 @@ static std::string FindProgram(const std::string &Program, error_code &ec) { ec = windows_error(::GetLastError()); else if (length > array_lengthof(PathName)) { // This may have been the file, return with error. - ec = windows_error::buffer_overflow; + ec = windows_error(ERROR_BUFFER_OVERFLOW); break; } else { // We found the path! Return it. - ec = windows_error::success; + ec = std::error_code(); break; } } @@ -312,7 +316,7 @@ int main(int argc, char **argv) { std::string CommandLine(ProgramToRun); - error_code ec; + std::error_code ec; ProgramToRun = FindProgram(ProgramToRun, ec); if (ec) { errs() << ToolName << ": Failed to find program: '" << CommandLine @@ -356,8 +360,8 @@ int main(int argc, char **argv) { &StartupInfo, &ProcessInfo); if (!success) { - errs() << ToolName << ": Failed to run program: '" << ProgramToRun - << "': " << error_code(windows_error(::GetLastError())).message() + errs() << ToolName << ": Failed to run program: '" << ProgramToRun << "': " + << std::error_code(windows_error(::GetLastError())).message() << '\n'; return -1; } @@ -420,9 +424,10 @@ int main(int argc, char **argv) { success = WaitForDebugEvent(&DebugEvent, TimeLeft); if (!success) { - ec = windows_error(::GetLastError()); + DWORD LastError = ::GetLastError(); + ec = windows_error(LastError); - if (ec == errc::timed_out) { + if (LastError == ERROR_SEM_TIMEOUT || LastError == WSAETIMEDOUT) { errs() << ToolName << ": Process timed out.\n"; ::TerminateProcess(ProcessInfo.hProcess, -1); // Otherwise other stuff starts failing... diff --git a/utils/Makefile b/utils/Makefile index ecb30bed7c63..04261923e1b5 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -8,8 +8,8 @@ ##===----------------------------------------------------------------------===## LEVEL = .. -PARALLEL_DIRS := FileCheck FileUpdate TableGen PerfectShuffle \ - count fpcmp llvm-lit not unittest +PARALLEL_DIRS := FileCheck TableGen PerfectShuffle count fpcmp llvm-lit not \ + unittest EXTRA_DIST := check-each-file codegen-diff countloc.sh \ DSAclean.py DSAextract.py emacs findsym.pl GenLibDeps.pl \ diff --git a/utils/PerfectShuffle/CMakeLists.txt b/utils/PerfectShuffle/CMakeLists.txt new file mode 100644 index 000000000000..ed70760a43e4 --- /dev/null +++ b/utils/PerfectShuffle/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_utility(llvm-PerfectShuffle + PerfectShuffle.cpp + ) diff --git a/utils/PerfectShuffle/PerfectShuffle.cpp b/utils/PerfectShuffle/PerfectShuffle.cpp index d39414eede94..f80d88563168 100644 --- a/utils/PerfectShuffle/PerfectShuffle.cpp +++ b/utils/PerfectShuffle/PerfectShuffle.cpp @@ -219,10 +219,10 @@ static void EvaluateOps(unsigned short Elt, unsigned short Vals[], int main() { // Seed the table with accesses to the LHS and RHS. ShufTab[0x0123].Cost = 0; - ShufTab[0x0123].Op = 0; + ShufTab[0x0123].Op = nullptr; ShufTab[0x0123].Arg0 = 0x0123; ShufTab[0x4567].Cost = 0; - ShufTab[0x4567].Op = 0; + ShufTab[0x4567].Op = nullptr; ShufTab[0x4567].Arg0 = 0x4567; // Seed the first-level of shuffles, shuffles whose inputs are the input to diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index de24cde4ba72..1277086ba823 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" @@ -118,6 +117,8 @@ #include <sstream> using namespace llvm; +#define DEBUG_TYPE "asm-matcher-emitter" + static cl::opt<std::string> MatchPrefix("match-prefix", cl::init(""), cl::desc("Only match instructions with the given prefix")); @@ -192,10 +193,10 @@ struct ClassInfo { /// parsing on the operand. std::string ParserMethod; - /// For register classes, the records for all the registers in this class. + /// For register classes: the records for all the registers in this class. RegisterSet Registers; - /// For custom match classes, he diagnostic kind for when the predicate fails. + /// For custom match classes: the diagnostic kind for when the predicate fails. std::string DiagnosticType; public: /// isRegisterClass() - Check if this is a register class. @@ -288,15 +289,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 { @@ -316,8 +308,8 @@ struct MatchableInfo { /// Register record if this token is singleton register. Record *SingletonReg; - explicit AsmOperand(StringRef T) : Token(T), Class(0), SubOpIdx(-1), - SingletonReg(0) {} + explicit AsmOperand(StringRef T) : Token(T), Class(nullptr), SubOpIdx(-1), + SingletonReg(nullptr) {} }; /// ResOperand - This represents a single operand in the result instruction @@ -581,6 +573,11 @@ struct SubtargetFeatureInfo { std::string getEnumName() const { return "Feature_" + TheDef->getName(); } + + void dump() { + errs() << getEnumName() << " " << Index << "\n"; + TheDef->dump(); + } }; struct OperandMatchEntry { @@ -676,7 +673,7 @@ public: assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!"); std::map<Record*, SubtargetFeatureInfo*, LessRecordByID>::const_iterator I = SubtargetFeatures.find(Def); - return I == SubtargetFeatures.end() ? 0 : I->second; + return I == SubtargetFeatures.end() ? nullptr : I->second; } RecordKeeper &getRecords() const { @@ -729,12 +726,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 +879,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 +916,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; } @@ -1028,7 +1025,7 @@ AsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) { // RegisterOperand may have an associated ParserMatchClass. If it does, // use it, else just fall back to the underlying register class. const RecordVal *R = Rec->getValue("ParserMatchClass"); - if (R == 0 || R->getValue() == 0) + if (!R || !R->getValue()) PrintFatalError("Record `" + Rec->getName() + "' does not have a ParserMatchClass!\n"); @@ -1288,7 +1285,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 = @@ -1332,6 +1329,7 @@ void AsmMatcherInfo::buildInfo() { unsigned FeatureNo = SubtargetFeatures.size(); SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo); + DEBUG(SubtargetFeatures[Pred]->dump()); assert(FeatureNo < 32 && "Too many subtarget features!"); } @@ -1359,7 +1357,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 +1373,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 @@ -1383,7 +1381,8 @@ void AsmMatcherInfo::buildInfo() { std::vector<Record*> AllInstAliases = Records.getAllDerivedDefinitions("InstAlias"); for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) { - CodeGenInstAlias *Alias = new CodeGenInstAlias(AllInstAliases[i], Target); + CodeGenInstAlias *Alias = + new CodeGenInstAlias(AllInstAliases[i], AsmVariantNo, Target); // If the tblgen -match-prefix option is specified (for tblgen hackers), // filter the set of instruction aliases we consider, based on the target @@ -1392,14 +1391,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 +1463,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 +1509,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 +1582,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() { @@ -1723,8 +1722,8 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, CvtOS << "void " << Target.getName() << ClassName << "::\n" << "convertToMCInst(unsigned Kind, MCInst &Inst, " << "unsigned Opcode,\n" - << " const SmallVectorImpl<MCParsedAsmOperand*" - << "> &Operands) {\n" + << " const OperandVector" + << " &Operands) {\n" << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n" << " const uint8_t *Converter = ConversionTable[Kind];\n" << " Inst.setOpcode(Opcode);\n" @@ -1733,7 +1732,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, << " default: llvm_unreachable(\"invalid conversion entry!\");\n" << " case CVT_Reg:\n" << " static_cast<" << TargetOperandClass - << "*>(Operands[*(p + 1)])->addRegOperands(Inst, 1);\n" + << "&>(*Operands[*(p + 1)]).addRegOperands(Inst, 1);\n" << " break;\n" << " case CVT_Tied:\n" << " Inst.addOperand(Inst.getOperand(*(p + 1)));\n" @@ -1745,7 +1744,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, OpOS << "void " << Target.getName() << ClassName << "::\n" << "convertToMapAndConstraints(unsigned Kind,\n"; OpOS.indent(27); - OpOS << "const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {\n" + OpOS << "const OperandVector &Operands) {\n" << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n" << " unsigned NumMCOperands = 0;\n" << " const uint8_t *Converter = ConversionTable[Kind];\n" @@ -1850,9 +1849,8 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // converter driver. CvtOS << " case " << Name << ":\n" << " static_cast<" << TargetOperandClass - << "*>(Operands[*(p + 1)])->" - << Op.Class->RenderMethod << "(Inst, " << OpInfo.MINumOperands - << ");\n" + << "&>(*Operands[*(p + 1)])." << Op.Class->RenderMethod + << "(Inst, " << OpInfo.MINumOperands << ");\n" << " break;\n"; // Add a handler for the operand number lookup. @@ -1907,7 +1905,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, } case MatchableInfo::ResOperand::RegOperand: { std::string Reg, Name; - if (OpInfo.Register == 0) { + if (!OpInfo.Register) { Name = "reg0"; Reg = "0"; } else { @@ -2037,10 +2035,10 @@ static void emitMatchClassEnumeration(CodeGenTarget &Target, /// emitValidateOperandClass - Emit the function to validate an operand class. static void emitValidateOperandClass(AsmMatcherInfo &Info, raw_ostream &OS) { - OS << "static unsigned validateOperandClass(MCParsedAsmOperand *GOp, " + OS << "static unsigned validateOperandClass(MCParsedAsmOperand &GOp, " << "MatchClassKind Kind) {\n"; - OS << " " << Info.Target.getName() << "Operand &Operand = *(" - << Info.Target.getName() << "Operand*)GOp;\n"; + OS << " " << Info.Target.getName() << "Operand &Operand = (" + << Info.Target.getName() << "Operand&)GOp;\n"; // The InvalidMatchClass is not to match any operand. OS << " if (Kind == InvalidMatchClass)\n"; @@ -2206,18 +2204,35 @@ static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser, OS << "}\n\n"; } +static const char *getMinimalTypeForRange(uint64_t Range) { + assert(Range <= 0xFFFFFFFFULL && "Enum too large"); + if (Range > 0xFFFF) + return "uint32_t"; + if (Range > 0xFF) + return "uint16_t"; + return "uint8_t"; +} + +static const char *getMinimalRequiredFeaturesType(const AsmMatcherInfo &Info) { + uint64_t MaxIndex = Info.SubtargetFeatures.size(); + if (MaxIndex > 0) + MaxIndex--; + return getMinimalTypeForRange(1ULL << MaxIndex); +} + /// emitSubtargetFeatureFlagEnumeration - Emit the subtarget feature flag /// definitions. static void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info, raw_ostream &OS) { OS << "// Flags for subtarget features that participate in " << "instruction matching.\n"; - OS << "enum SubtargetFeatureFlag {\n"; + OS << "enum SubtargetFeatureFlag : " << getMinimalRequiredFeaturesType(Info) + << " {\n"; for (std::map<Record*, SubtargetFeatureInfo*, LessRecordByID>::const_iterator it = Info.SubtargetFeatures.begin(), ie = Info.SubtargetFeatures.end(); it != ie; ++it) { SubtargetFeatureInfo &SFI = *it->second; - OS << " " << SFI.getEnumName() << " = (1 << " << SFI.Index << "),\n"; + OS << " " << SFI.getEnumName() << " = (1U << " << SFI.Index << "),\n"; } OS << " Feature_None = 0\n"; OS << "};\n\n"; @@ -2329,7 +2344,7 @@ static std::string GetAliasRequiredFeatures(Record *R, for (unsigned i = 0, e = ReqFeatures.size(); i != e; ++i) { SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]); - if (F == 0) + if (!F) PrintFatalError(R->getLoc(), "Predicate '" + ReqFeatures[i]->getName() + "' is not marked as an AssemblerPredicate!"); @@ -2453,15 +2468,6 @@ static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info, return true; } -static const char *getMinimalTypeForRange(uint64_t Range) { - assert(Range < 0xFFFFFFFFULL && "Enum too large"); - if (Range > 0xFFFF) - return "uint32_t"; - if (Range > 0xFF) - return "uint16_t"; - return "uint8_t"; -} - static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, const AsmMatcherInfo &Info, StringRef ClassName, StringToOffsetTable &StringTable, @@ -2476,7 +2482,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, // Emit the static custom operand parsing table; OS << "namespace {\n"; OS << " struct OperandMatchEntry {\n"; - OS << " " << getMinimalTypeForRange(1ULL << Info.SubtargetFeatures.size()) + OS << " " << getMinimalRequiredFeaturesType(Info) << " RequiredFeatures;\n"; OS << " " << getMinimalTypeForRange(MaxMnemonicIndex) << " Mnemonic;\n"; @@ -2554,7 +2560,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, // the found operand class. OS << Target.getName() << ClassName << "::OperandMatchResultTy " << Target.getName() << ClassName << "::\n" - << "tryCustomParseOperand(SmallVectorImpl<MCParsedAsmOperand*>" + << "tryCustomParseOperand(OperandVector" << " &Operands,\n unsigned MCK) {\n\n" << " switch(MCK) {\n"; @@ -2578,7 +2584,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, // a better error handling. OS << Target.getName() << ClassName << "::OperandMatchResultTy " << Target.getName() << ClassName << "::\n" - << "MatchOperandParserImpl(SmallVectorImpl<MCParsedAsmOperand*>" + << "MatchOperandParserImpl(OperandVector" << " &Operands,\n StringRef Mnemonic) {\n"; // Emit code to get the available features. @@ -2688,14 +2694,14 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " unsigned ComputeAvailableFeatures(uint64_t FeatureBits) const;\n"; OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, " << "unsigned Opcode,\n" - << " const SmallVectorImpl<MCParsedAsmOperand*> " + << " const OperandVector " << "&Operands);\n"; OS << " void convertToMapAndConstraints(unsigned Kind,\n "; - OS << " const SmallVectorImpl<MCParsedAsmOperand*> &Operands);\n"; - OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID);\n"; + OS << " const OperandVector &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" + OS << "const OperandVector &Operands,\n" << " MCInst &Inst,\n" << " unsigned &ErrorInfo," << " bool matchingInlineAsm,\n" @@ -2708,11 +2714,11 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " MatchOperand_ParseFail // operand matched but had errors\n"; OS << " };\n"; OS << " OperandMatchResultTy MatchOperandParserImpl(\n"; - OS << " SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n"; + OS << " OperandVector &Operands,\n"; OS << " StringRef Mnemonic);\n"; OS << " OperandMatchResultTy tryCustomParseOperand(\n"; - OS << " SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n"; + OS << " OperandVector &Operands,\n"; OS << " unsigned MCK);\n\n"; } @@ -2812,7 +2818,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " uint16_t Opcode;\n"; OS << " " << getMinimalTypeForRange(Info.Matchables.size()) << " ConvertFn;\n"; - OS << " " << getMinimalTypeForRange(1ULL << Info.SubtargetFeatures.size()) + OS << " " << getMinimalRequiredFeaturesType(Info) << " RequiredFeatures;\n"; OS << " " << getMinimalTypeForRange(Info.Classes.size()) << " Classes[" << MaxNumOperands << "];\n"; @@ -2891,8 +2897,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { for (unsigned VC = 0; VC != VariantCount; ++VC) { Record *AsmVariant = Target.getAsmParserVariant(VC); int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); - OS << " case " << AsmVariantNo << ": Start = MatchTable" << VC - << "; End = array_endof(MatchTable" << VC << "); break;\n"; + OS << " case " << AsmVariantNo << ": Start = std::begin(MatchTable" << VC + << "); End = std::end(MatchTable" << VC << "); break;\n"; } OS << " }\n"; OS << " // Search the table.\n"; @@ -2902,9 +2908,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "}\n\n"; // Finally, build the match function. - OS << "unsigned " - << Target.getName() << ClassName << "::\n" - << "MatchInstructionImpl(const SmallVectorImpl<MCParsedAsmOperand*>" + OS << "unsigned " << Target.getName() << ClassName << "::\n" + << "MatchInstructionImpl(const OperandVector" << " &Operands,\n"; OS << " MCInst &Inst,\n" << "unsigned &ErrorInfo, bool matchingInlineAsm, unsigned VariantID) {\n"; @@ -2921,7 +2926,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " // Get the instruction mnemonic, which is the first token.\n"; OS << " StringRef Mnemonic = ((" << Target.getName() - << "Operand*)Operands[0])->getToken();\n\n"; + << "Operand&)*Operands[0]).getToken();\n\n"; if (HasMnemonicAliases) { OS << " // Process all MnemonicAliases to remap the mnemonic.\n"; @@ -2946,8 +2951,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { for (unsigned VC = 0; VC != VariantCount; ++VC) { Record *AsmVariant = Target.getAsmParserVariant(VC); int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); - OS << " case " << AsmVariantNo << ": Start = MatchTable" << VC - << "; End = array_endof(MatchTable" << VC << "); break;\n"; + OS << " case " << AsmVariantNo << ": Start = std::begin(MatchTable" << VC + << "); End = std::end(MatchTable" << VC << "); break;\n"; } OS << " }\n"; OS << " // Search the table.\n"; @@ -2973,7 +2978,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " if (!OperandsValid) ErrorInfo = i + 1;\n"; OS << " break;\n"; OS << " }\n"; - OS << " unsigned Diag = validateOperandClass(Operands[i+1],\n"; + OS << " unsigned Diag = validateOperandClass(*Operands[i+1],\n"; OS.indent(43); OS << "(MatchClassKind)it->Classes[i]);\n"; OS << " if (Diag == Match_Success)\n"; @@ -2981,7 +2986,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " // If the generic handler indicates an invalid operand\n"; OS << " // failure, check for a special case.\n"; OS << " if (Diag == Match_InvalidOperand) {\n"; - OS << " Diag = validateTargetOperandClass(Operands[i+1],\n"; + OS << " Diag = validateTargetOperandClass(*Operands[i+1],\n"; OS.indent(43); OS << "(MatchClassKind)it->Classes[i]);\n"; OS << " if (Diag == Match_Success)\n"; @@ -3048,7 +3053,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { if (HasDeprecation) { OS << " std::string Info;\n"; OS << " if (MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, STI, Info)) {\n"; - OS << " SMLoc Loc = ((" << Target.getName() << "Operand*)Operands[0])->getStartLoc();\n"; + OS << " SMLoc Loc = ((" << Target.getName() + << "Operand&)*Operands[0]).getStartLoc();\n"; OS << " Parser.Warning(Loc, Info, None);\n"; OS << " }\n"; } diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index a18b6b559470..7ef70d31b693 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -15,6 +15,7 @@ #include "AsmWriterInst.h" #include "CodeGenTarget.h" #include "SequenceToOffsetTable.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Debug.h" @@ -29,13 +30,16 @@ #include <vector> using namespace llvm; +#define DEBUG_TYPE "asm-writer-emitter" + namespace { 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; + std::vector<std::string> PrintMethods; public: AsmWriterEmitter(RecordKeeper &R); @@ -47,9 +51,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 +145,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 +154,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) + continue; // PHI, INLINEASM, CFI_INSTRUCTION, etc. std::string Command; if (Inst->Operands.empty()) @@ -280,15 +285,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,9 +303,9 @@ 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]]; - if (AWI != 0 && + for (unsigned i = 0, e = NumberedInstructions->size(); i != e; ++i) { + AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions->at(i)]; + if (AWI && AWI->Operands[0].OperandType == AsmWriterOperand::isLiteralTextOperand && !AWI->Operands[0].Str.empty()) { @@ -316,10 +318,10 @@ 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) { + if (!AWI) { // Something not handled by the asmwriter printer. Idx = ~0U; } else if (AWI->Operands[0].OperandType != @@ -379,7 +381,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 +400,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 +414,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"; @@ -422,7 +424,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { } // Emit the string itself. - O << " const char AsmStrs[] = {\n"; + O << " static const char AsmStrs[] = {\n"; StringTable.emit(O, printChar); O << " };\n\n"; @@ -549,8 +551,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 +607,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" @@ -628,22 +630,45 @@ namespace { // alias for that pattern. class IAPrinter { std::vector<std::string> Conds; - std::map<StringRef, unsigned> OpMap; + std::map<StringRef, std::pair<int, int>> OpMap; + SmallVector<Record*, 4> ReqFeatures; + std::string Result; std::string AsmString; - SmallVector<Record*, 4> ReqFeatures; public: - IAPrinter(std::string R, std::string AS) - : Result(R), AsmString(AS) {} + IAPrinter(std::string R, std::string AS) : Result(R), AsmString(AS) {} void addCond(const std::string &C) { Conds.push_back(C); } - void addOperand(StringRef Op, unsigned Idx) { - assert(Idx < 0xFF && "Index too large!"); - OpMap[Op] = Idx; + void addOperand(StringRef Op, int OpIdx, int PrintMethodIdx = -1) { + assert(OpIdx >= 0 && OpIdx < 0xFE && "Idx out of range"); + assert(PrintMethodIdx >= -1 && PrintMethodIdx < 0xFF && + "Idx out of range"); + OpMap[Op] = std::make_pair(OpIdx, PrintMethodIdx); } - unsigned getOpIndex(StringRef Op) { return OpMap[Op]; } + bool isOpMapped(StringRef Op) { return OpMap.find(Op) != OpMap.end(); } + int getOpIndex(StringRef Op) { return OpMap[Op].first; } + std::pair<int, int> &getOpData(StringRef Op) { return OpMap[Op]; } + + std::pair<StringRef, StringRef::iterator> parseName(StringRef::iterator Start, + StringRef::iterator End) { + StringRef::iterator I = Start; + if (*I == '{') { + // ${some_name} + Start = ++I; + while (I != End && *I != '}') + ++I; + } else { + // $name, just eat the usual suspects. + while (I != End && + ((*I >= 'a' && *I <= 'z') || (*I >= 'A' && *I <= 'Z') || + (*I >= '0' && *I <= '9') || *I == '_')) + ++I; + } + + return std::make_pair(StringRef(Start, I - Start), I); + } void print(raw_ostream &O) { if (Conds.empty() && ReqFeatures.empty()) { @@ -669,28 +694,30 @@ public: // Directly mangle mapped operands into the string. Each operand is // identified by a '$' sign followed by a byte identifying the number of the // operand. We add one to the index to avoid zero bytes. - std::pair<StringRef, StringRef> ASM = StringRef(AsmString).split(' '); - SmallString<128> OutString = ASM.first; - if (!ASM.second.empty()) { - raw_svector_ostream OS(OutString); - OS << ' '; - for (StringRef::iterator I = ASM.second.begin(), E = ASM.second.end(); - I != E;) { - OS << *I; - if (*I == '$') { - StringRef::iterator Start = ++I; - while (I != E && - ((*I >= 'a' && *I <= 'z') || (*I >= 'A' && *I <= 'Z') || - (*I >= '0' && *I <= '9') || *I == '_')) - ++I; - StringRef Name(Start, I - Start); - assert(isOpMapped(Name) && "Unmapped operand!"); - OS << format("\\x%02X", (unsigned char)getOpIndex(Name) + 1); - } else { - ++I; - } + StringRef ASM(AsmString); + SmallString<128> OutString; + raw_svector_ostream OS(OutString); + for (StringRef::iterator I = ASM.begin(), E = ASM.end(); I != E;) { + OS << *I; + if (*I == '$') { + StringRef Name; + std::tie(Name, I) = parseName(++I, E); + assert(isOpMapped(Name) && "Unmapped operand!"); + + int OpIndex, PrintIndex; + std::tie(OpIndex, PrintIndex) = getOpData(Name); + if (PrintIndex == -1) { + // Can use the default printOperand route. + OS << format("\\x%02X", (unsigned char)OpIndex + 1); + } else + // 3 bytes if a PrintMethod is needed: 0xFF, the MCInst operand + // number, and which of our pre-detected Methods to call. + OS << format("\\xFF\\x%02X\\x%02X", OpIndex + 1, PrintIndex + 1); + } else { + ++I; } } + OS.flush(); // Emit the string. O.indent(6) << "AsmString = \"" << OutString.str() << "\";\n"; @@ -711,156 +738,169 @@ public: return true; } - - bool operator()(const IAPrinter &RHS) { - if (Conds.size() < RHS.Conds.size()) - return true; - - unsigned Idx = 0; - for (std::vector<std::string>::iterator - I = Conds.begin(), E = Conds.end(); I != E; ++I) - if (*I != RHS.Conds[Idx++]) - return *I < RHS.Conds[Idx++]; - - return false; - } }; } // end anonymous namespace -static unsigned CountNumOperands(StringRef AsmString) { - unsigned NumOps = 0; - std::pair<StringRef, StringRef> ASM = AsmString.split(' '); - - while (!ASM.second.empty()) { - ++NumOps; - ASM = ASM.second.split(' '); - } +static unsigned CountNumOperands(StringRef AsmString, unsigned Variant) { + std::string FlatAsmString = + CodeGenInstruction::FlattenAsmStringVariants(AsmString, Variant); + AsmString = FlatAsmString; - return NumOps; + return AsmString.count(' ') + AsmString.count('\t'); } -static unsigned CountResultNumOperands(StringRef AsmString) { - unsigned NumOps = 0; - std::pair<StringRef, StringRef> ASM = AsmString.split('\t'); - - if (!ASM.second.empty()) { - size_t I = ASM.second.find('{'); - StringRef Str = ASM.second; - if (I != StringRef::npos) - Str = ASM.second.substr(I, ASM.second.find('|', I)); - - ASM = Str.split(' '); +namespace { +struct AliasPriorityComparator { + typedef std::pair<CodeGenInstAlias *, int> ValueType; + bool operator()(const ValueType &LHS, const ValueType &RHS) { + if (LHS.second == RHS.second) { + // We don't actually care about the order, but for consistency it + // shouldn't depend on pointer comparisons. + return LHS.first->TheDef->getName() < RHS.first->TheDef->getName(); + } - do { - ++NumOps; - ASM = ASM.second.split(' '); - } while (!ASM.second.empty()); + // Aliases with larger priorities should be considered first. + return LHS.second > RHS.second; } - - return NumOps; +}; } + void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { Record *AsmWriter = Target.getAsmWriter(); - if (!AsmWriter->getValueAsBit("isMCAsmWriter")) - return; - O << "\n#ifdef PRINT_ALIAS_INSTR\n"; O << "#undef PRINT_ALIAS_INSTR\n\n"; + ////////////////////////////// + // Gather information about aliases we need to print + ////////////////////////////// + // Emit the method that prints the alias instruction. std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); + unsigned Variant = AsmWriter->getValueAsInt("Variant"); std::vector<Record*> AllInstAliases = Records.getAllDerivedDefinitions("InstAlias"); // Create a map from the qualified name to a list of potential matches. - std::map<std::string, std::vector<CodeGenInstAlias*> > AliasMap; + typedef std::set<std::pair<CodeGenInstAlias*, int>, AliasPriorityComparator> + AliasWithPriority; + std::map<std::string, AliasWithPriority> AliasMap; for (std::vector<Record*>::iterator I = AllInstAliases.begin(), E = AllInstAliases.end(); I != E; ++I) { - CodeGenInstAlias *Alias = new CodeGenInstAlias(*I, Target); + CodeGenInstAlias *Alias = new CodeGenInstAlias(*I, Variant, Target); const Record *R = *I; - if (!R->getValueAsBit("EmitAlias")) - continue; // We were told not to emit the alias, but to emit the aliasee. + int Priority = R->getValueAsInt("EmitPriority"); + if (Priority < 1) + continue; // Aliases with priority 0 are never emitted. + const DagInit *DI = R->getValueAsDag("ResultInst"); const DefInit *Op = cast<DefInit>(DI->getOperator()); - AliasMap[getQualifiedName(Op->getDef())].push_back(Alias); + AliasMap[getQualifiedName(Op->getDef())].insert(std::make_pair(Alias, + Priority)); } // A map of which conditions need to be met for each instruction operand // before it can be matched to the mnemonic. std::map<std::string, std::vector<IAPrinter*> > IAPrinterMap; - for (std::map<std::string, std::vector<CodeGenInstAlias*> >::iterator - I = AliasMap.begin(), E = AliasMap.end(); I != E; ++I) { - std::vector<CodeGenInstAlias*> &Aliases = I->second; + // A list of MCOperandPredicates for all operands in use, and the reverse map + std::vector<const Record*> MCOpPredicates; + DenseMap<const Record*, unsigned> MCOpPredicateMap; - for (std::vector<CodeGenInstAlias*>::iterator - II = Aliases.begin(), IE = Aliases.end(); II != IE; ++II) { - const CodeGenInstAlias *CGA = *II; + for (auto &Aliases : AliasMap) { + for (auto &Alias : Aliases.second) { + const CodeGenInstAlias *CGA = Alias.first; unsigned LastOpNo = CGA->ResultInstOperandIndex.size(); unsigned NumResultOps = - CountResultNumOperands(CGA->ResultInst->AsmString); + CountNumOperands(CGA->ResultInst->AsmString, Variant); // Don't emit the alias if it has more operands than what it's aliasing. - if (NumResultOps < CountNumOperands(CGA->AsmString)) + if (NumResultOps < CountNumOperands(CGA->AsmString, Variant)) continue; IAPrinter *IAP = new IAPrinter(CGA->Result->getAsString(), CGA->AsmString); + unsigned NumMIOps = 0; + for (auto &Operand : CGA->ResultOperands) + NumMIOps += Operand.getMINumOperands(); + std::string Cond; - Cond = std::string("MI->getNumOperands() == ") + llvm::utostr(LastOpNo); + Cond = std::string("MI->getNumOperands() == ") + llvm::utostr(NumMIOps); IAP->addCond(Cond); bool CantHandle = false; + unsigned MIOpNum = 0; for (unsigned i = 0, e = LastOpNo; i != e; ++i) { + std::string Op = "MI->getOperand(" + llvm::utostr(MIOpNum) + ")"; + const CodeGenInstAlias::ResultOperand &RO = CGA->ResultOperands[i]; switch (RO.Kind) { case CodeGenInstAlias::ResultOperand::K_Record: { const Record *Rec = RO.getRecord(); StringRef ROName = RO.getName(); - + int PrintMethodIdx = -1; + + // These two may have a PrintMethod, which we want to record (if it's + // the first time we've seen it) and provide an index for the aliasing + // code to use. + if (Rec->isSubClassOf("RegisterOperand") || + Rec->isSubClassOf("Operand")) { + std::string PrintMethod = Rec->getValueAsString("PrintMethod"); + if (PrintMethod != "" && PrintMethod != "printOperand") { + PrintMethodIdx = std::find(PrintMethods.begin(), + PrintMethods.end(), PrintMethod) - + PrintMethods.begin(); + if (static_cast<unsigned>(PrintMethodIdx) == PrintMethods.size()) + PrintMethods.push_back(PrintMethod); + } + } if (Rec->isSubClassOf("RegisterOperand")) Rec = Rec->getValueAsDef("RegClass"); if (Rec->isSubClassOf("RegisterClass")) { - Cond = std::string("MI->getOperand(")+llvm::utostr(i)+").isReg()"; - IAP->addCond(Cond); + IAP->addCond(Op + ".isReg()"); if (!IAP->isOpMapped(ROName)) { - IAP->addOperand(ROName, i); + IAP->addOperand(ROName, MIOpNum, PrintMethodIdx); Record *R = CGA->ResultOperands[i].getRecord(); if (R->isSubClassOf("RegisterOperand")) R = R->getValueAsDef("RegClass"); Cond = std::string("MRI.getRegClass(") + Target.getName() + "::" + - R->getName() + "RegClassID)" - ".contains(MI->getOperand(" + llvm::utostr(i) + ").getReg())"; - IAP->addCond(Cond); + R->getName() + "RegClassID)" + ".contains(" + Op + ".getReg())"; } else { - Cond = std::string("MI->getOperand(") + - llvm::utostr(i) + ").getReg() == MI->getOperand(" + + Cond = Op + ".getReg() == MI->getOperand(" + llvm::utostr(IAP->getOpIndex(ROName)) + ").getReg()"; - IAP->addCond(Cond); } } else { - assert(Rec->isSubClassOf("Operand") && "Unexpected operand!"); - // FIXME: We may need to handle these situations. - delete IAP; - IAP = 0; - CantHandle = true; - break; + // Assume all printable operands are desired for now. This can be + // overridden in the InstAlias instantiation if necessary. + IAP->addOperand(ROName, MIOpNum, PrintMethodIdx); + + // There might be an additional predicate on the MCOperand + unsigned Entry = MCOpPredicateMap[Rec]; + if (!Entry) { + if (!Rec->isValueUnset("MCOperandPredicate")) { + MCOpPredicates.push_back(Rec); + Entry = MCOpPredicates.size(); + MCOpPredicateMap[Rec] = Entry; + } else + break; // No conditions on this operand at all + } + Cond = Target.getName() + ClassName + "ValidateMCOperand(" + + Op + ", " + llvm::utostr(Entry) + ")"; } - + // for all subcases of ResultOperand::K_Record: + IAP->addCond(Cond); break; } case CodeGenInstAlias::ResultOperand::K_Imm: { - std::string Op = "MI->getOperand(" + llvm::utostr(i) + ")"; - // Just because the alias has an immediate result, doesn't mean the // MCInst will. An MCExpr could be present, for example. IAP->addCond(Op + ".isImm()"); @@ -878,21 +918,25 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { break; } - Cond = std::string("MI->getOperand(") + - llvm::utostr(i) + ").getReg() == " + Target.getName() + + Cond = Op + ".getReg() == " + Target.getName() + "::" + CGA->ResultOperands[i].getRegister()->getName(); IAP->addCond(Cond); break; } if (!IAP) break; + MIOpNum += RO.getMINumOperands(); } if (CantHandle) continue; - IAPrinterMap[I->first].push_back(IAP); + IAPrinterMap[Aliases.first].push_back(IAP); } } + ////////////////////////////// + // Write out the printAliasInstr function + ////////////////////////////// + std::string Header; raw_string_ostream HeaderO(Header); @@ -947,6 +991,11 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { return; } + if (MCOpPredicates.size()) + O << "static bool " << Target.getName() << ClassName + << "ValidateMCOperand(\n" + << " const MCOperand &MCOp, unsigned PredicateIndex);\n"; + O << HeaderO.str(); O.indent(2) << "const char *AsmString;\n"; O.indent(2) << "switch (MI->getOpcode()) {\n"; @@ -957,7 +1006,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { // Code that prints the alias, replacing the operands with the ones from the // MCInst. O << " unsigned I = 0;\n"; - O << " while (AsmString[I] != ' ' && AsmString[I] != '\\0')\n"; + O << " while (AsmString[I] != ' ' && AsmString[I] != '\t' &&\n"; + O << " AsmString[I] != '\\0')\n"; O << " ++I;\n"; O << " OS << '\\t' << StringRef(AsmString, I);\n"; @@ -966,7 +1016,13 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { O << " do {\n"; O << " if (AsmString[I] == '$') {\n"; O << " ++I;\n"; - O << " printOperand(MI, unsigned(AsmString[I++]) - 1, OS);\n"; + O << " if (AsmString[I] == (char)0xff) {\n"; + O << " ++I;\n"; + O << " int OpIdx = AsmString[I++] - 1;\n"; + O << " int PrintMethodIdx = AsmString[I++] - 1;\n"; + O << " printCustomAliasOperand(MI, OpIdx, PrintMethodIdx, OS);\n"; + O << " } else\n"; + O << " printOperand(MI, unsigned(AsmString[I++]) - 1, OS);\n"; O << " } else {\n"; O << " OS << AsmString[I++];\n"; O << " }\n"; @@ -976,6 +1032,53 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { O << " return true;\n"; O << "}\n\n"; + ////////////////////////////// + // Write out the printCustomAliasOperand function + ////////////////////////////// + + O << "void " << Target.getName() << ClassName << "::" + << "printCustomAliasOperand(\n" + << " const MCInst *MI, unsigned OpIdx,\n" + << " unsigned PrintMethodIdx, raw_ostream &OS) {\n"; + if (PrintMethods.empty()) + O << " llvm_unreachable(\"Unknown PrintMethod kind\");\n"; + else { + O << " switch (PrintMethodIdx) {\n" + << " default:\n" + << " llvm_unreachable(\"Unknown PrintMethod kind\");\n" + << " break;\n"; + + for (unsigned i = 0; i < PrintMethods.size(); ++i) { + O << " case " << i << ":\n" + << " " << PrintMethods[i] << "(MI, OpIdx, OS);\n" + << " break;\n"; + } + O << " }\n"; + } + O << "}\n\n"; + + if (MCOpPredicates.size()) { + O << "static bool " << Target.getName() << ClassName + << "ValidateMCOperand(\n" + << " const MCOperand &MCOp, unsigned PredicateIndex) {\n" + << " switch (PredicateIndex) {\n" + << " default:\n" + << " llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n" + << " break;\n"; + + for (unsigned i = 0; i < MCOpPredicates.size(); ++i) { + Init *MCOpPred = MCOpPredicates[i]->getValueInit("MCOperandPredicate"); + if (StringInit *SI = dyn_cast<StringInit>(MCOpPred)) { + O << " case " << i + 1 << ": {\n" + << SI->getValue() << "\n" + << " }\n"; + } else + llvm_unreachable("Unexpected MCOperandPredicate field!"); + } + O << " }\n" + << "}\n\n"; + } + O << "#endif // PRINT_ALIAS_INSTR\n"; } @@ -987,11 +1090,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 1c2004f6ee5d..5d9ead10b361 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 ec7d8eb10395..4cee35289f12 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 3ee197443131..feaa7c757962 100644 --- a/utils/TableGen/CMakeLists.txt +++ b/utils/TableGen/CMakeLists.txt @@ -26,9 +26,7 @@ add_tablegen(llvm-tblgen LLVM OptParserEmitter.cpp PseudoLoweringEmitter.cpp 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 8bf777839bdd..5d6d6da9cf25 100644 --- a/utils/TableGen/CTagsEmitter.cpp +++ b/utils/TableGen/CTagsEmitter.cpp @@ -13,18 +13,17 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "ctags-emitter" - #include "llvm/Support/SourceMgr.h" #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> using namespace llvm; +#define DEBUG_TYPE "ctags-emitter" + namespace llvm { extern SourceMgr SrcMgr; } namespace { @@ -38,8 +37,8 @@ public: : Id(&Name), Loc(Location) {} int operator<(const Tag &B) const { return *Id < *B.Id; } void emit(raw_ostream &OS) const { - int BufferID = SrcMgr.FindBufferContainingLoc(Loc); - MemoryBuffer *CurMB = SrcMgr.getBufferInfo(BufferID).Buffer; + const MemoryBuffer *CurMB = + SrcMgr.getMemoryBuffer(SrcMgr.FindBufferContainingLoc(Loc)); const char *BufferName = CurMB->getBufferIdentifier(); std::pair<unsigned, unsigned> LineAndColumn = SrcMgr.getLineAndColumn(Loc); OS << *Id << "\t" << BufferName << "\t" << LineAndColumn.first << "\n"; diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp index 94f3c6518ca0..6d43e8ed3877 100644 --- a/utils/TableGen/CallingConvEmitter.cpp +++ b/utils/TableGen/CallingConvEmitter.cpp @@ -112,7 +112,7 @@ void CallingConvEmitter::EmitAction(Record *Action, O << IndentStr << "if (unsigned Reg = State.AllocateReg("; O << getQualifiedName(RegList->getElementAsRecord(0)) << ")) {\n"; } else { - O << IndentStr << "static const uint16_t RegList" << ++Counter + O << IndentStr << "static const MCPhysReg RegList" << ++Counter << "[] = {\n"; O << IndentStr << " "; for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) { @@ -143,7 +143,7 @@ void CallingConvEmitter::EmitAction(Record *Action, unsigned RegListNumber = ++Counter; unsigned ShadowRegListNumber = ++Counter; - O << IndentStr << "static const uint16_t RegList" << RegListNumber + O << IndentStr << "static const MCPhysReg RegList" << RegListNumber << "[] = {\n"; O << IndentStr << " "; for (unsigned i = 0, e = RegList->getSize(); i != e; ++i) { @@ -152,7 +152,7 @@ void CallingConvEmitter::EmitAction(Record *Action, } O << "\n" << IndentStr << "};\n"; - O << IndentStr << "static const uint16_t RegList" + O << IndentStr << "static const MCPhysReg RegList" << ShadowRegListNumber << "[] = {\n"; O << IndentStr << " "; for (unsigned i = 0, e = ShadowRegList->getSize(); i != e; ++i) { @@ -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 MCPhysReg 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 c94d384901f0..4d0c0ca8e701 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"; diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 717090ae01e4..2602bbcf6f61 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -25,6 +25,8 @@ #include <set> using namespace llvm; +#define DEBUG_TYPE "dag-patterns" + //===----------------------------------------------------------------------===// // EEVT::TypeSet Implementation //===----------------------------------------------------------------------===// @@ -83,7 +85,7 @@ bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP, return false; for (unsigned i = 0, e = LegalTypes.size(); i != e; ++i) - if (Pred == 0 || Pred(LegalTypes[i])) + if (!Pred || Pred(LegalTypes[i])) TypeVec.push_back(LegalTypes[i]); // If we have nothing that matches the predicate, bail out. @@ -120,6 +122,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 +349,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 +382,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 +532,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; @@ -735,9 +738,13 @@ static unsigned getPatternSize(const TreePatternNode *P, // specified. To get best possible pattern match we'll need to dynamically // calculate the complexity of all patterns a dag can potentially map to. const ComplexPattern *AM = P->getComplexPatternInfo(CGP); - if (AM) + if (AM) { Size += AM->getNumOperands() * 3; + // We don't want to count any children twice, so return early. + return Size; + } + // If this node has some predicate function that must match, it adds to the // complexity of this node. if (!P->getPredicateFns().empty()) @@ -975,7 +982,7 @@ bool TreePatternNode::UpdateNodeTypeFromInst(unsigned ResNo, // Both RegisterClass and RegisterOperand operands derive their types from a // register class def. - Record *RC = 0; + Record *RC = nullptr; if (Operand->isSubClassOf("RegisterClass")) RC = Operand; else if (Operand->isSubClassOf("RegisterOperand")) @@ -1093,7 +1100,7 @@ static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) { // Get the result tree. DagInit *Tree = Operator->getValueAsDag("Fragment"); - Record *Op = 0; + Record *Op = nullptr; if (Tree) if (DefInit *DI = dyn_cast<DefInit>(Tree->getOperator())) Op = DI->getDef(); @@ -1116,6 +1123,12 @@ 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. + + if (Operator->isSubClassOf("ComplexPattern")) + return 1; + Operator->dump(); errs() << "Unhandled node in GetNumNodeResults\n"; exit(1); @@ -1228,8 +1241,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!"); @@ -1250,7 +1265,7 @@ SubstituteFormalArguments(std::map<std::string, TreePatternNode*> &ArgMap) { /// PatFrag references. TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { if (TP.hasError()) - return 0; + return nullptr; if (isLeaf()) return this; // nothing to do. @@ -1279,7 +1294,7 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) { if (Frag->getNumArgs() != Children.size()) { TP.error("'" + Op->getName() + "' fragment requires " + utostr(Frag->getNumArgs()) + " operands!"); - return 0; + return nullptr; } TreePatternNode *FragTree = Frag->getOnlyTree()->clone(); @@ -1417,6 +1432,9 @@ static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo, return EEVT::TypeSet(); // Unknown. } + if (R->isSubClassOf("Operand")) + return EEVT::TypeSet(getValueType(R->getValueAsDef("Type"))); + TP.error("Unknown node flavor used in pattern: " + R->getName()); return EEVT::TypeSet(MVT::Other, TP); } @@ -1429,7 +1447,7 @@ getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const { if (getOperator() != CDP.get_intrinsic_void_sdnode() && getOperator() != CDP.get_intrinsic_w_chain_sdnode() && getOperator() != CDP.get_intrinsic_wo_chain_sdnode()) - return 0; + return nullptr; unsigned IID = cast<IntInit>(getChild(0)->getLeafValue())->getValue(); return &CDP.getIntrinsicInfo(IID); @@ -1439,12 +1457,37 @@ getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const { /// return the ComplexPattern information, otherwise return null. const ComplexPattern * TreePatternNode::getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const { - if (!isLeaf()) return 0; + Record *Rec; + if (isLeaf()) { + DefInit *DI = dyn_cast<DefInit>(getLeafValue()); + if (!DI) + return nullptr; + Rec = DI->getDef(); + } else + Rec = getOperator(); - DefInit *DI = dyn_cast<DefInit>(getLeafValue()); - if (DI && DI->getDef()->isSubClassOf("ComplexPattern")) - return &CGP.getComplexPattern(DI->getDef()); - return 0; + if (!Rec->isSubClassOf("ComplexPattern")) + return nullptr; + return &CGP.getComplexPattern(Rec); +} + +unsigned TreePatternNode::getNumMIResults(const CodeGenDAGPatterns &CGP) const { + // A ComplexPattern specifically declares how many results it fills in. + if (const ComplexPattern *CP = getComplexPatternInfo(CGP)) + return CP->getNumOperands(); + + // If MIOperandInfo is specified, that gives the count. + if (isLeaf()) { + DefInit *DI = dyn_cast<DefInit>(getLeafValue()); + if (DI && DI->getDef()->isSubClassOf("Operand")) { + DagInit *MIOps = DI->getDef()->getValueAsDag("MIOperandInfo"); + if (MIOps->getNumArgs()) + return MIOps->getNumArgs(); + } + } + + // Otherwise there is just one result. + return 1; } /// NodeHasProperty - Return true if this node has the specified property. @@ -1675,9 +1718,9 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { DagInit *MIOpInfo = OperandNode->getValueAsDag("MIOperandInfo"); if (unsigned NumArgs = MIOpInfo->getNumArgs()) { // But don't do that if the whole operand is being provided by - // a single ComplexPattern. - const ComplexPattern *AM = Child->getComplexPatternInfo(CDP); - if (!AM || AM->getNumOperands() < NumArgs) { + // a single ComplexPattern-related Operand. + + if (Child->getNumMIResults(CDP) < NumArgs) { // Match first sub-operand against the child we already have. Record *SubRec = cast<DefInit>(MIOpInfo->getArg(0))->getDef(); MadeChange |= @@ -1717,6 +1760,15 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { return MadeChange; } + if (getOperator()->isSubClassOf("ComplexPattern")) { + bool MadeChange = false; + + for (unsigned i = 0; i < getNumChildren(); ++i) + MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters); + + return MadeChange; + } + assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!"); // Node transforms always take one operand. @@ -1773,6 +1825,9 @@ bool TreePatternNode::canPatternMatch(std::string &Reason, return true; } + if (getOperator()->isSubClassOf("ComplexPattern")) + return true; + // If this node is a commutative operator, check that the LHS isn't an // immediate. const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(getOperator()); @@ -1882,7 +1937,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ if (BitsInit *BI = dyn_cast<BitsInit>(TheInit)) { // Turn this into an IntInit. Init *II = BI->convertInitializerTo(IntRecTy::get()); - if (II == 0 || !isa<IntInit>(II)) + if (!II || !isa<IntInit>(II)) error("Bits value must be constants!"); return ParseTreePattern(II, OpName); } @@ -1919,6 +1974,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ !Operator->isSubClassOf("Instruction") && !Operator->isSubClassOf("SDNodeXForm") && !Operator->isSubClassOf("Intrinsic") && + !Operator->isSubClassOf("ComplexPattern") && Operator->getName() != "set" && Operator->getName() != "implicit") error("Unrecognized node '" + Operator->getName() + "'!"); @@ -1974,6 +2030,27 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ Children.insert(Children.begin(), IIDNode); } + if (Operator->isSubClassOf("ComplexPattern")) { + for (unsigned i = 0; i < Children.size(); ++i) { + TreePatternNode *Child = Children[i]; + + if (Child->getName().empty()) + error("All arguments to a ComplexPattern must be named"); + + // Check that the ComplexPattern uses are consistent: "(MY_PAT $a, $b)" + // and "(MY_PAT $b, $a)" should not be allowed in the same pattern; + // neither should "(MY_PAT_1 $a, $b)" and "(MY_PAT_2 $a, $b)". + auto OperandId = std::make_pair(Operator, i); + auto PrevOp = ComplexPatternOperands.find(Child->getName()); + if (PrevOp != ComplexPatternOperands.end()) { + if (PrevOp->getValue() != OperandId) + error("All ComplexPattern operands must appear consistently: " + "in the same order in just one ComplexPattern instance."); + } else + ComplexPatternOperands[Child->getName()] = OperandId; + } + } + unsigned NumResults = GetNumNodeResults(Operator, CDP); TreePatternNode *Result = new TreePatternNode(Operator, Children, NumResults); Result->setName(OpName); @@ -2042,9 +2119,11 @@ InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) { // If we have input named node types, propagate their types to the named // values here. if (InNamedTypes) { - // FIXME: Should be error? - assert(InNamedTypes->count(I->getKey()) && - "Named node in output pattern but not input pattern?"); + if (!InNamedTypes->count(I->getKey())) { + error("Node '" + std::string(I->getKey()) + + "' in output pattern but not input pattern"); + return true; + } const SmallVectorImpl<TreePatternNode*> &InNodes = InNamedTypes->find(I->getKey())->second; @@ -2131,6 +2210,7 @@ CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : ParsePatternFragments(); ParseDefaultOperands(); ParseInstructions(); + ParsePatternFragments(/*OutFrags*/true); ParsePatterns(); // Generate variants. For example, commutative patterns can match @@ -2204,13 +2284,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 +2351,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 +2400,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); } @@ -2535,14 +2624,11 @@ public: return; } - // Get information about the SDNode for the operator. - const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N->getOperator()); - // Notice properties of the node. - if (OpInfo.hasProperty(SDNPMayStore)) mayStore = true; - if (OpInfo.hasProperty(SDNPMayLoad)) mayLoad = true; - if (OpInfo.hasProperty(SDNPSideEffect)) hasSideEffects = true; - if (OpInfo.hasProperty(SDNPVariadic)) isVariadic = true; + if (N->NodeHasProperty(SDNPMayStore, CDP)) mayStore = true; + if (N->NodeHasProperty(SDNPMayLoad, CDP)) mayLoad = true; + if (N->NodeHasProperty(SDNPSideEffect, CDP)) hasSideEffects = true; + if (N->NodeHasProperty(SDNPVariadic, CDP)) isVariadic = true; if (const CodeGenIntrinsic *IntInfo = N->getIntrinsicInfo(CDP)) { // If this is an intrinsic, analyze it. @@ -2723,7 +2809,7 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern( // Check that all of the results occur first in the list. std::vector<Record*> Results; - TreePatternNode *Res0Node = 0; + TreePatternNode *Res0Node = nullptr; for (unsigned i = 0; i != NumResults; ++i) { if (i == CGI.Operands.size()) I->error("'" + InstResults.begin()->first + @@ -2732,13 +2818,13 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern( // Check that it exists in InstResults. TreePatternNode *RNode = InstResults[OpName]; - if (RNode == 0) + if (!RNode) I->error("Operand $" + OpName + " does not exist in operand list!"); if (i == 0) Res0Node = RNode; Record *R = cast<DefInit>(RNode->getLeafValue())->getDef(); - if (R == 0) + if (!R) I->error("Operand $" + OpName + " should be a set destination: all " "outputs must occur before inputs in operand list!"); @@ -2795,7 +2881,7 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern( // Promote the xform function to be an explicit node if set. if (Record *Xform = OpNode->getTransformFn()) { - OpNode->setTransformFn(0); + OpNode->setTransformFn(nullptr); std::vector<TreePatternNode*> Children; Children.push_back(OpNode); OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes()); @@ -2839,7 +2925,7 @@ void CodeGenDAGPatterns::ParseInstructions() { std::vector<Record*> Instrs = Records.getAllDerivedDefinitions("Instruction"); for (unsigned i = 0, e = Instrs.size(); i != e; ++i) { - ListInit *LI = 0; + ListInit *LI = nullptr; if (isa<ListInit>(Instrs[i]->getValueInit("Pattern"))) LI = Instrs[i]->getValueAsListInit("Pattern"); @@ -2874,7 +2960,7 @@ void CodeGenDAGPatterns::ParseInstructions() { // Create and insert the instruction. std::vector<Record*> ImpResults; Instructions.insert(std::make_pair(Instrs[i], - DAGInstruction(0, Results, Operands, ImpResults))); + DAGInstruction(nullptr, Results, Operands, ImpResults))); continue; // no pattern. } @@ -2891,7 +2977,7 @@ void CodeGenDAGPatterns::ParseInstructions() { E = Instructions.end(); II != E; ++II) { DAGInstruction &TheInst = II->second; TreePattern *I = TheInst.getPattern(); - if (I == 0) continue; // No pattern. + if (!I) continue; // No pattern. // FIXME: Assume only the first tree is the pattern. The others are clobber // nodes. @@ -2967,7 +3053,7 @@ void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern, // they don't exist in the input pattern. for (std::map<std::string, NameRecord>::iterator I = DstNames.begin(), E = DstNames.end(); I != E; ++I) { - if (SrcNames[I->first].first == 0) + if (SrcNames[I->first].first == nullptr) Pattern->error("Pattern has input without matching name in output: $" + I->first); } @@ -2976,7 +3062,7 @@ void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern, // name isn't used in the dest, and isn't used to tie two values together. for (std::map<std::string, NameRecord>::iterator I = SrcNames.begin(), E = SrcNames.end(); I != E; ++I) - if (DstNames[I->first].first == 0 && SrcNames[I->first].second == 1) + if (DstNames[I->first].first == nullptr && SrcNames[I->first].second == 1) Pattern->error("Pattern has dead named input: $" + I->first); PatternsToMatch.push_back(PTM); @@ -3264,7 +3350,7 @@ void CodeGenDAGPatterns::ParsePatterns() { for (unsigned ii = 0, ee = DstPattern->getNumChildren(); ii != ee; ++ii) { TreePatternNode *OpNode = DstPattern->getChild(ii); if (Record *Xform = OpNode->getTransformFn()) { - OpNode->setTransformFn(0); + OpNode->setTransformFn(nullptr); std::vector<TreePatternNode*> Children; Children.push_back(OpNode); OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes()); @@ -3416,8 +3502,8 @@ static void GenerateVariantsOf(TreePatternNode *N, std::vector<TreePatternNode*> &OutVariants, CodeGenDAGPatterns &CDP, const MultipleUseVarSet &DepVars) { - // We cannot permute leaves. - if (N->isLeaf()) { + // We cannot permute leaves or ComplexPattern uses. + if (N->isLeaf() || N->getOperator()->isSubClassOf("ComplexPattern")) { OutVariants.push_back(N); return; } diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index 6fbdd4f9a85b..fb30cdd94853 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; @@ -144,8 +148,8 @@ namespace EEVT { /// valid on completely unknown type sets. If Pred is non-null, only MVTs /// that pass the predicate are added. bool FillWithPossibleTypes(TreePattern &TP, - bool (*Pred)(MVT::SimpleValueType) = 0, - const char *PredicateName = 0); + bool (*Pred)(MVT::SimpleValueType) = nullptr, + const char *PredicateName = nullptr); }; } @@ -325,11 +329,11 @@ class TreePatternNode { public: TreePatternNode(Record *Op, const std::vector<TreePatternNode*> &Ch, unsigned NumResults) - : Operator(Op), Val(0), TransformFn(0), Children(Ch) { + : Operator(Op), Val(nullptr), TransformFn(nullptr), Children(Ch) { Types.resize(NumResults); } TreePatternNode(Init *val, unsigned NumResults) // leaf ctor - : Operator(0), Val(val), TransformFn(0) { + : Operator(nullptr), Val(val), TransformFn(nullptr) { Types.resize(NumResults); } ~TreePatternNode(); @@ -338,7 +342,7 @@ public: const std::string &getName() const { return Name; } void setName(StringRef N) { Name.assign(N.begin(), N.end()); } - bool isLeaf() const { return Val != 0; } + bool isLeaf() const { return Val != nullptr; } // Type accessors. unsigned getNumTypes() const { return Types.size(); } @@ -405,6 +409,12 @@ public: const ComplexPattern * getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const; + /// Returns the number of MachineInstr operands that would be produced by this + /// node if it mapped directly to an output Instruction's + /// operand. ComplexPattern specifies this explicitly; MIOperandInfo gives it + /// for Operands; otherwise 1. + unsigned getNumMIResults(const CodeGenDAGPatterns &CGP) const; + /// NodeHasProperty - Return true if this node has the specified property. bool NodeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const; @@ -523,6 +533,13 @@ class TreePattern { /// hasError - True if the currently processed nodes have unresolvable types /// or other non-fatal errors bool HasError; + + /// It's important that the usage of operands in ComplexPatterns is + /// consistent: each named operand can be defined by at most one + /// ComplexPattern. This records the ComplexPattern instance and the operand + /// number for each operand encountered in a ComplexPattern to aid in that + /// check. + StringMap<std::pair<Record *, unsigned>> ComplexPatternOperands; public: /// TreePattern constructor - Parse the specified DagInits into the @@ -576,7 +593,7 @@ public: /// patterns as possible. Return true if all types are inferred, false /// otherwise. Bail out if a type contradiction is found. bool InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > - *NamedTypes=0); + *NamedTypes=nullptr); /// error - If this is the first error in the current resolution step, /// print it and set the error flag. Otherwise, continue silently. @@ -615,7 +632,7 @@ public: const std::vector<Record*> &operands, const std::vector<Record*> &impresults) : Pattern(TP), Results(results), Operands(operands), - ImpResults(impresults), ResultPattern(0) {} + ImpResults(impresults), ResultPattern(nullptr) {} TreePattern *getPattern() const { return Pattern; } unsigned getNumResults() const { return Results.size(); } @@ -764,7 +781,7 @@ public: return PatternFragments.find(R)->second; } TreePattern *getPatternFragmentIfRead(Record *R) const { - if (!PatternFragments.count(R)) return 0; + if (!PatternFragments.count(R)) return nullptr; return PatternFragments.find(R)->second; } @@ -805,7 +822,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 576388b2ed1c..2577ad4d919d 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -69,7 +69,7 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { std::string EncoderMethod; std::string OperandType = "OPERAND_UNKNOWN"; unsigned NumOps = 1; - DagInit *MIOpInfo = 0; + DagInit *MIOpInfo = nullptr; if (Rec->isSubClassOf("RegisterOperand")) { PrintMethod = Rec->getValueAsString("PrintMethod"); } else if (Rec->isSubClassOf("Operand")) { @@ -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 @@ -182,7 +182,7 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) { // Find the suboperand number involved. DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo; - if (MIOpInfo == 0) + if (!MIOpInfo) PrintFatalError(TheDef->getName() + ": unknown suboperand name in '" + Op + "'"); // Find the operand with the right name. @@ -290,7 +290,7 @@ void CGIOperandList::ProcessDisableEncoding(std::string DisableEncoding) { //===----------------------------------------------------------------------===// CodeGenInstruction::CodeGenInstruction(Record *R) - : TheDef(R), Operands(R), InferredFrom(0) { + : TheDef(R), Operands(R), InferredFrom(nullptr) { Namespace = R->getValueAsString("Namespace"); AsmString = R->getValueAsString("AsmString"); @@ -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() : nullptr; 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; } @@ -497,7 +504,7 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, // throw TGError(Loc, "reg0 used for result that is not an " // "OptionalDefOperand!"); - ResOp = ResultOperand(static_cast<Record*>(0)); + ResOp = ResultOperand(static_cast<Record*>(nullptr)); return true; } @@ -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; @@ -529,13 +536,34 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, return false; } -CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) { - AsmString = R->getValueAsString("AsmString"); +unsigned CodeGenInstAlias::ResultOperand::getMINumOperands() const { + if (!isRecord()) + return 1; + + Record *Rec = getRecord(); + if (!Rec->isSubClassOf("Operand")) + return 1; + + DagInit *MIOpInfo = Rec->getValueAsDag("MIOperandInfo"); + if (MIOpInfo->getNumArgs() == 0) { + // Unspecified, so it defaults to 1 + return 1; + } + + return MIOpInfo->getNumArgs(); +} + +CodeGenInstAlias::CodeGenInstAlias(Record *R, unsigned Variant, + CodeGenTarget &T) + : TheDef(R) { Result = R->getValueAsDag("ResultInst"); + AsmString = R->getValueAsString("AsmString"); + AsmString = CodeGenInstruction::FlattenAsmStringVariants(AsmString, Variant); + // Verify that the root of the result is an instruction. DefInit *DI = dyn_cast<DefInit>(Result->getOperator()); - if (DI == 0 || !DI->getDef()->isSubClassOf("Instruction")) + if (!DI || !DI->getDef()->isSubClassOf("Instruction")) PrintFatalError(R->getLoc(), "result of inst alias should be an instruction"); @@ -620,14 +648,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 6004f6679270..f143875131b4 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> @@ -149,6 +149,12 @@ namespace llvm { OperandInfo &back() { return OperandList.back(); } const OperandInfo &back() const { return OperandList.back(); } + typedef std::vector<OperandInfo>::iterator iterator; + typedef std::vector<OperandInfo>::const_iterator const_iterator; + iterator begin() { return OperandList.begin(); } + const_iterator begin() const { return OperandList.begin(); } + iterator end() { return OperandList.end(); } + const_iterator end() const { return OperandList.end(); } /// getOperandNamed - Return the index of the operand with the specified /// non-empty name. If the instruction does not have an operand with the @@ -215,38 +221,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; @@ -318,6 +324,8 @@ namespace llvm { Record *getRecord() const { assert(isRecord()); return R; } int64_t getImm() const { assert(isImm()); return Imm; } Record *getRegister() const { assert(isReg()); return R; } + + unsigned getMINumOperands() const; }; /// ResultOperands - The decoded operands for the result instruction. @@ -330,7 +338,7 @@ namespace llvm { /// of them are matched by the operand, the second value should be -1. std::vector<std::pair<unsigned, int> > ResultInstOperandIndex; - CodeGenInstAlias(Record *R, CodeGenTarget &T); + CodeGenInstAlias(Record *R, unsigned Variant, CodeGenTarget &T); bool tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, Record *InstOpRec, bool hasSubOps, ArrayRef<SMLoc> Loc, diff --git a/utils/TableGen/CodeGenIntrinsics.h b/utils/TableGen/CodeGenIntrinsics.h index ababfa4e7e77..a9ece01c904b 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> @@ -28,6 +28,7 @@ namespace llvm { std::string Name; // The name of the LLVM function "llvm.bswap.i32" std::string EnumName; // The name of the enum "bswap_i32" std::string GCCBuiltinName;// Name of the corresponding GCC builtin, or "". + std::string MSBuiltinName; // Name of the corresponding MS builtin, or "". std::string TargetPrefix; // Target prefix, e.g. "ppc" for t-s intrinsics. /// IntrinsicSignature - This structure holds the return values and @@ -73,6 +74,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 cb7ec3e9b9ab..7e5aa9c161b4 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 @@ -326,7 +326,7 @@ Record *MapTableEmitter::getInstrForColumn(Record *KeyInstr, const std::vector<Record*> &RelatedInstrVec = RowInstrMap[KeyValue]; ListInit *ColFields = InstrMapDesc.getColFields(); - Record *MatchInstr = NULL; + Record *MatchInstr = nullptr; for (unsigned i = 0, e = RelatedInstrVec.size(); i < e; i++) { bool MatchFound = true; @@ -378,13 +378,13 @@ unsigned MapTableEmitter::emitBinSearchTable(raw_ostream &OS) { unsigned RelExists = 0; if (ColInstrs.size()) { for (unsigned j = 0; j < NumCol; j++) { - if (ColInstrs[j] != NULL) { + if (ColInstrs[j] != nullptr) { RelExists = 1; OutStr += ", "; OutStr += TargetName; 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 f2eef4f68f5a..8099f134fd0e 100644 --- a/utils/TableGen/CodeGenRegisters.cpp +++ b/utils/TableGen/CodeGenRegisters.cpp @@ -12,8 +12,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "regalloc-emitter" - #include "CodeGenRegisters.h" #include "CodeGenTarget.h" #include "llvm/ADT/IntEqClasses.h" @@ -26,6 +24,8 @@ using namespace llvm; +#define DEBUG_TYPE "regalloc-emitter" + //===----------------------------------------------------------------------===// // CodeGenSubRegIndex //===----------------------------------------------------------------------===// @@ -41,7 +41,7 @@ CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum) CodeGenSubRegIndex::CodeGenSubRegIndex(StringRef N, StringRef Nspace, unsigned Enum) - : TheDef(0), Name(N), Namespace(Nspace), Size(-1), Offset(-1), + : TheDef(nullptr), Name(N), Namespace(Nspace), Size(-1), Offset(-1), EnumValue(Enum), LaneMask(0), AllSuperRegsCovered(true) { } @@ -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"); @@ -725,7 +725,7 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, StringRef Name, Key Props) : Members(*Props.Members), - TheDef(0), + TheDef(nullptr), Name(Name), TopoSigs(RegBank.getNumTopoSigs()), EnumValue(-1), @@ -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,11 +1308,11 @@ 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. - const CodeGenRegister *Reg = 0; + const CodeGenRegister *Reg = nullptr; unsigned MaxWeight = 0, Weight = 0; for (RegUnitIterator UnitI(I->Regs); UnitI.isValid(); ++UnitI) { if (Reg != UnitI.getReg()) { @@ -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; } @@ -1933,7 +1923,7 @@ const CodeGenRegisterClass* CodeGenRegBank::getRegClassForRegister(Record *R) { const CodeGenRegister *Reg = getReg(R); ArrayRef<CodeGenRegisterClass*> RCs = getRegClasses(); - const CodeGenRegisterClass *FoundRC = 0; + const CodeGenRegisterClass *FoundRC = nullptr; for (unsigned i = 0, e = RCs.size(); i != e; ++i) { const CodeGenRegisterClass &RC = *RCs[i]; if (!RC.contains(Reg)) @@ -1948,7 +1938,7 @@ CodeGenRegBank::getRegClassForRegister(Record *R) { // If a register's classes have different types, return null. if (RC.getValueTypes() != FoundRC->getValueTypes()) - return 0; + return nullptr; // Check to see if the previously found class that contains // the register is a subclass of the current class. If so, @@ -1966,7 +1956,7 @@ CodeGenRegBank::getRegClassForRegister(Record *R) { // Multiple classes, and neither is a superclass of the other. // Return null. - return 0; + return nullptr; } return FoundRC; } diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h index 37f75b4a4868..278315ba47b3 100644 --- a/utils/TableGen/CodeGenRegisters.h +++ b/utils/TableGen/CodeGenRegisters.h @@ -15,14 +15,14 @@ #ifndef CODEGEN_REGISTERS_H #define CODEGEN_REGISTERS_H -#include "SetTheory.h" #include "llvm/ADT/ArrayRef.h" #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 "llvm/TableGen/SetTheory.h" #include <cstdlib> #include <map> #include <set> @@ -71,7 +71,7 @@ namespace llvm { // Returns NULL if this and Idx don't compose. CodeGenSubRegIndex *compose(CodeGenSubRegIndex *Idx) const { CompMap::const_iterator I = Composed.find(Idx); - return I == Composed.end() ? 0 : I->second; + return I == Composed.end() ? nullptr : I->second; } // Add a composite subreg index: this+A = B. @@ -90,7 +90,8 @@ namespace llvm { B->Offset = Offset + A->Offset; B->Size = A->Size; } - return (Ins.second || Ins.first->second == B) ? 0 : Ins.first->second; + return (Ins.second || Ins.first->second == B) ? nullptr + : Ins.first->second; } // Update the composite maps of components specified in 'ComposedOf'. @@ -335,7 +336,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 +375,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) {} @@ -419,7 +415,9 @@ namespace llvm { // contain this unit. unsigned RegClassUnitSetsIdx; - RegUnit() : Weight(0), RegClassUnitSetsIdx(0) { Roots[0] = Roots[1] = 0; } + RegUnit() : Weight(0), RegClassUnitSetsIdx(0) { + Roots[0] = Roots[1] = nullptr; + } ArrayRef<const CodeGenRegister*> getRoots() const { assert(!(Roots[1] && !Roots[0]) && "Invalid roots array"); @@ -577,7 +575,7 @@ namespace llvm { // Create a native register unit that is associated with one or two root // registers. - unsigned newRegUnit(CodeGenRegister *R0, CodeGenRegister *R1 = 0) { + unsigned newRegUnit(CodeGenRegister *R0, CodeGenRegister *R1 = nullptr) { RegUnits.resize(RegUnits.size() + 1); RegUnits.back().Roots[0] = R0; RegUnits.back().Roots[1] = R1; diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp index dd06433d6ab7..79d60ac171b8 100644 --- a/utils/TableGen/CodeGenSchedule.cpp +++ b/utils/TableGen/CodeGenSchedule.cpp @@ -7,13 +7,11 @@ // //===----------------------------------------------------------------------===// // -// 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. // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "subtarget-emitter" - #include "CodeGenSchedule.h" #include "CodeGenTarget.h" #include "llvm/ADT/STLExtras.h" @@ -23,6 +21,8 @@ using namespace llvm; +#define DEBUG_TYPE "subtarget-emitter" + #ifndef NDEBUG static void dumpIdxVec(const IdxVec &V) { for (unsigned i = 0, e = V.size(); i < e; ++i) { @@ -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,8 +58,8 @@ struct InstRegexOp : public SetTheory::Operator { InstRegexOp(const CodeGenTarget &t): Target(t) {} void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts, - ArrayRef<SMLoc> Loc) { - SmallVector<Regex*, 4> RegexList; + ArrayRef<SMLoc> Loc) override { + SmallVector<Regex, 4> RegexList; for (DagInit::const_arg_iterator AI = Expr->arg_begin(), AE = Expr->arg_end(); AI != AE; ++AI) { StringInit *SI = dyn_cast<StringInit>(*AI); @@ -72,17 +72,15 @@ struct InstRegexOp : public SetTheory::Operator { pat.insert(0, "^("); pat.insert(pat.end(), ')'); } - RegexList.push_back(new Regex(pat)); + RegexList.push_back(Regex(pat)); } for (CodeGenTarget::inst_iterator I = Target.inst_begin(), E = Target.inst_end(); I != E; ++I) { - for (SmallVectorImpl<Regex*>::iterator - RI = RegexList.begin(), RE = RegexList.end(); RI != RE; ++RI) { - if ((*RI)->match((*I)->TheDef->getName())) + for (auto &R : RegexList) { + if (R.match((*I)->TheDef->getName())) Elts.insert((*I)->TheDef); } } - DeleteContainerPointers(RegexList); } }; } // end anonymous namespace @@ -429,7 +427,7 @@ void CodeGenSchedModels::expandRWSeqForProc( const CodeGenProcModel &ProcModel) const { const CodeGenSchedRW &SchedWrite = getSchedRW(RWIdx, IsRead); - Record *AliasDef = 0; + Record *AliasDef = nullptr; for (RecIter AI = SchedWrite.Aliases.begin(), AE = SchedWrite.Aliases.end(); AI != AE; ++AI) { const CodeGenSchedRW &AliasRW = getSchedRW((*AI)->getValueAsDef("AliasRW")); @@ -1315,7 +1313,7 @@ static void inferFromTransitions(ArrayRef<PredTransition> LastTransitions, IdxVec ProcIndices(I->ProcIndices.begin(), I->ProcIndices.end()); CodeGenSchedTransition SCTrans; SCTrans.ToClassIdx = - SchedModels.addSchedClass(/*ItinClassDef=*/0, OperWritesVariant, + SchedModels.addSchedClass(/*ItinClassDef=*/nullptr, OperWritesVariant, OperReadsVariant, ProcIndices); SCTrans.ProcIndices = ProcIndices; // The final PredTerm is unique set of predicates guarding the transition. @@ -1473,11 +1471,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"); @@ -1609,7 +1619,7 @@ Record *CodeGenSchedModels::findProcResUnits(Record *ProcResKind, if (ProcResKind->isSubClassOf("ProcResourceUnits")) return ProcResKind; - Record *ProcUnitDef = 0; + Record *ProcUnitDef = nullptr; RecVec ProcResourceDefs = Records.getAllDerivedDefinitions("ProcResourceUnits"); diff --git a/utils/TableGen/CodeGenSchedule.h b/utils/TableGen/CodeGenSchedule.h index fa964cf23d2a..3fef8adf91e5 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. // //===----------------------------------------------------------------------===// @@ -15,11 +15,11 @@ #ifndef CODEGEN_SCHEDULE_H #define CODEGEN_SCHEDULE_H -#include "SetTheory.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/TableGen/Record.h" +#include "llvm/TableGen/SetTheory.h" namespace llvm { @@ -56,7 +56,7 @@ struct CodeGenSchedRW { RecVec Aliases; CodeGenSchedRW() - : Index(0), TheDef(0), IsRead(false), IsAlias(false), + : Index(0), TheDef(nullptr), IsRead(false), IsAlias(false), HasVariants(false), IsVariadic(false), IsSequence(false) {} CodeGenSchedRW(unsigned Idx, Record *Def) : Index(Idx), TheDef(Def), IsAlias(false), IsVariadic(false) { @@ -74,7 +74,7 @@ struct CodeGenSchedRW { CodeGenSchedRW(unsigned Idx, bool Read, const IdxVec &Seq, const std::string &Name) - : Index(Idx), Name(Name), TheDef(0), IsRead(Read), IsAlias(false), + : Index(Idx), Name(Name), TheDef(nullptr), IsRead(Read), IsAlias(false), HasVariants(false), IsVariadic(false), IsSequence(true), Sequence(Seq) { assert(Sequence.size() > 1 && "implied sequence needs >1 RWs"); } @@ -142,7 +142,7 @@ struct CodeGenSchedClass { // off to join another inferred class. RecVec InstRWs; - CodeGenSchedClass(): Index(0), ItinClassDef(0) {} + CodeGenSchedClass(): Index(0), ItinClassDef(nullptr) {} bool isKeyEqual(Record *IC, const IdxVec &W, const IdxVec &R) { return ItinClassDef == IC && Writes == W && Reads == R; @@ -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. // @@ -248,6 +248,28 @@ class CodeGenSchedModels { public: CodeGenSchedModels(RecordKeeper& RK, const CodeGenTarget &TGT); + // iterator access to the scheduling classes. + typedef std::vector<CodeGenSchedClass>::iterator class_iterator; + typedef std::vector<CodeGenSchedClass>::const_iterator const_class_iterator; + class_iterator classes_begin() { return SchedClasses.begin(); } + const_class_iterator classes_begin() const { return SchedClasses.begin(); } + class_iterator classes_end() { return SchedClasses.end(); } + const_class_iterator classes_end() const { return SchedClasses.end(); } + iterator_range<class_iterator> classes() { + return iterator_range<class_iterator>(classes_begin(), classes_end()); + } + iterator_range<const_class_iterator> classes() const { + return iterator_range<const_class_iterator>(classes_begin(), classes_end()); + } + iterator_range<class_iterator> explicit_classes() { + return iterator_range<class_iterator>( + classes_begin(), classes_begin() + NumInstrSchedClasses); + } + iterator_range<const_class_iterator> explicit_classes() const { + return iterator_range<const_class_iterator>( + classes_begin(), classes_begin() + NumInstrSchedClasses); + } + Record *getModelOrItinDef(Record *ProcDef) const { Record *ModelDef = ProcDef->getValueAsDef("SchedModel"); Record *ItinsDef = ProcDef->getValueAsDef("ProcItin"); diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index dd1705955824..d1b57118e0ee 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -133,7 +133,7 @@ std::string llvm::getQualifiedName(const Record *R) { /// getTarget - Return the current instance of the Target class. /// CodeGenTarget::CodeGenTarget(RecordKeeper &records) - : Records(records), RegBank(0), SchedModels(0) { + : Records(records), RegBank(nullptr), SchedModels(nullptr) { std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target"); if (Targets.size() == 0) PrintFatalError("ERROR: No 'Target' subclasses defined!"); @@ -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]; } @@ -222,7 +226,7 @@ const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const { const StringMap<CodeGenRegister*> &Regs = getRegBank().getRegistersByName(); StringMap<CodeGenRegister*>::const_iterator I = Regs.find(Name); if (I == Regs.end()) - return 0; + return nullptr; return I->second; } @@ -283,48 +287,21 @@ 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!"); + if (!Rec || I == Insts.end()) + 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", nullptr}; 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_") @@ -439,6 +459,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { if (R->getValue("GCCBuiltinName")) // Ignore a missing GCCBuiltinName field. GCCBuiltinName = R->getValueAsString("GCCBuiltinName"); + if (R->getValue("MSBuiltinName")) // Ignore a missing MSBuiltinName field. + MSBuiltinName = R->getValueAsString("MSBuiltinName"); TargetPrefix = R->getValueAsString("TargetPrefix"); Name = R->getValueAsString("LLVMName"); @@ -481,14 +503,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 +537,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 +576,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 627144302932..54143103dc18 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -171,12 +171,19 @@ public: typedef std::vector<const CodeGenInstruction*>::const_iterator inst_iterator; inst_iterator inst_begin() const{return getInstructionsByEnumValue().begin();} inst_iterator inst_end() const { return getInstructionsByEnumValue().end(); } + iterator_range<inst_iterator> instructions() const { + return iterator_range<inst_iterator>(inst_begin(), inst_end()); + } /// isLittleEndianEncoding - are instruction bit patterns defined as [0..n]? /// 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 a76ea32de3e7..82682cd5a5ad 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -18,6 +18,8 @@ #include "llvm/TableGen/TableGenBackend.h" using namespace llvm; +#define DEBUG_TYPE "dag-isel-emitter" + namespace { /// DAGISelEmitter - The top-level class which coordinates construction /// and emission of the instruction selector. @@ -155,8 +157,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 5d6a11ae0dc7..9c4079906a38 100644 --- a/utils/TableGen/DAGISelMatcher.cpp +++ b/utils/TableGen/DAGISelMatcher.cpp @@ -43,7 +43,7 @@ Matcher *Matcher::unlinkNode(Matcher *Other) { for (; Cur && Cur->getNext() != Other; Cur = Cur->getNext()) /*empty*/; - if (Cur == 0) return 0; + if (!Cur) return nullptr; Cur->takeNext(); Cur->setNext(Other->takeNext()); return this; @@ -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()) {} @@ -99,7 +108,7 @@ TreePredicateFn CheckPredicateMatcher::getPredicate() const { void ScopeMatcher::printImpl(raw_ostream &OS, unsigned indent) const { OS.indent(indent) << "Scope\n"; for (unsigned i = 0, e = getNumChildren(); i != e; ++i) { - if (getChild(i) == 0) + if (!getChild(i)) OS.indent(indent+1) << "NULL POINTER\n"; else getChild(i)->print(OS, indent+2); @@ -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 70031fa6d3b8..f8f6c546e11d 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(); @@ -205,7 +207,7 @@ public: Matcher *takeChild(unsigned i) { Matcher *Res = Children[i]; - Children[i] = 0; + Children[i] = nullptr; return Res; } @@ -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 04fe0d1824ad..00595703839c 100644 --- a/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -142,7 +142,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, switch (N->getKind()) { case Matcher::Scope: { const ScopeMatcher *SM = cast<ScopeMatcher>(N); - assert(SM->getNext() == 0 && "Shouldn't have next after scope"); + assert(SM->getNext() == nullptr && "Shouldn't have next after scope"); unsigned StartIdx = CurrentIdx; @@ -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"; @@ -718,7 +725,7 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { } static void BuildHistogram(const Matcher *M, std::vector<unsigned> &OpcodeFreq){ - for (; M != 0; M = M->getNext()) { + for (; M != nullptr; M = M->getNext()) { // Count this node. if (unsigned(M->getKind()) >= OpcodeFreq.size()) OpcodeFreq.resize(M->getKind()+1); @@ -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 ed41631456b0..97e37ba68952 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -62,6 +62,13 @@ namespace { /// insertion easier. StringMap<unsigned> VariableMap; + /// This maintains the recorded operand number that OPC_CheckComplexPattern + /// drops each sub-operand into. We don't want to insert these into + /// VariableMap because that leads to identity checking if they are + /// encountered multiple times. Biased by 1 like VariableMap for + /// consistency. + StringMap<unsigned> NamedComplexPatternOperands; + /// NextRecordedOperandNo - As we emit opcodes to record matched values in /// the RecordedNodes array, this keeps track of which slot will be next to /// record into. @@ -76,10 +83,8 @@ namespace { SmallVector<unsigned, 2> MatchedGlueResultNodes; /// MatchedComplexPatterns - This maintains a list of all of the - /// ComplexPatterns that we need to check. The patterns are known to have - /// names which were recorded. The second element of each pair is the first - /// slot number that the OPC_CheckComplexPat opcode drops the matched - /// results into. + /// ComplexPatterns that we need to check. The second element of each pair + /// is the recorded operand number of the input node. SmallVector<std::pair<const TreePatternNode*, unsigned>, 2> MatchedComplexPatterns; @@ -115,6 +120,11 @@ namespace { void EmitOperatorMatchCode(const TreePatternNode *N, TreePatternNode *NodeNoTypes); + /// If this is the first time a node with unique identifier Name has been + /// seen, record it. Otherwise, emit a check to make sure this is the same + /// node. Returns true if this is the first encounter. + bool recordUniqueNode(std::string Name); + // Result Code Generation. unsigned getNamedArgumentSlot(StringRef Name) { unsigned VarMapEntry = VariableMap[Name]; @@ -144,7 +154,7 @@ namespace { MatcherGen::MatcherGen(const PatternToMatch &pattern, const CodeGenDAGPatterns &cgp) : Pattern(pattern), CGP(cgp), NextRecordedOperandNo(0), - TheMatcher(0), CurPredicate(0) { + TheMatcher(nullptr), CurPredicate(nullptr) { // We need to produce the matcher tree for the patterns source pattern. To do // this we need to match the structure as well as the types. To do the type // matching, we want to figure out the fewest number of type checks we need to @@ -182,7 +192,7 @@ void MatcherGen::InferPossibleTypes() { /// AddMatcher - Add a matcher node to the current graph we're building. void MatcherGen::AddMatcher(Matcher *NewNode) { - if (CurPredicate != 0) + if (CurPredicate) CurPredicate->setNext(NewNode); else TheMatcher = NewNode; @@ -218,7 +228,7 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { } DefInit *DI = dyn_cast<DefInit>(N->getLeafValue()); - if (DI == 0) { + if (!DI) { errs() << "Unknown leaf kind: " << *N << "\n"; abort(); } @@ -266,7 +276,8 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { // Remember this ComplexPattern so that we can emit it after all the other // structural matches are done. - MatchedComplexPatterns.push_back(std::make_pair(N, 0)); + unsigned InputOperand = VariableMap[N->getName()] - 1; + MatchedComplexPatterns.push_back(std::make_pair(N, InputOperand)); return; } @@ -277,6 +288,25 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N, TreePatternNode *NodeNoTypes) { assert(!N->isLeaf() && "Not an operator?"); + + if (N->getOperator()->isSubClassOf("ComplexPattern")) { + // The "name" of a non-leaf complex pattern (MY_PAT $op1, $op2) is + // "MY_PAT:op1:op2". We should already have validated that the uses are + // consistent. + std::string PatternName = N->getOperator()->getName(); + for (unsigned i = 0; i < N->getNumChildren(); ++i) { + PatternName += ":"; + PatternName += N->getChild(i)->getName(); + } + + if (recordUniqueNode(PatternName)) { + auto NodeAndOpNum = std::make_pair(N, NextRecordedOperandNo - 1); + MatchedComplexPatterns.push_back(NodeAndOpNum); + } + + return; + } + const SDNodeInfo &CInfo = CGP.getSDNodeInfo(N->getOperator()); // If this is an 'and R, 1234' where the operation is AND/OR and the RHS is @@ -415,11 +445,27 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N, } } +bool MatcherGen::recordUniqueNode(std::string Name) { + unsigned &VarMapEntry = VariableMap[Name]; + if (VarMapEntry == 0) { + // If it is a named node, we must emit a 'Record' opcode. + AddMatcher(new RecordMatcher("$" + Name, NextRecordedOperandNo)); + VarMapEntry = ++NextRecordedOperandNo; + return true; + } + + // If we get here, this is a second reference to a specific name. Since + // we already have checked that the first reference is valid, we don't + // have to recursively match it, just check that it's the same as the + // previously named thing. + AddMatcher(new CheckSameMatcher(VarMapEntry-1)); + return false; +} void MatcherGen::EmitMatchCode(const TreePatternNode *N, TreePatternNode *NodeNoTypes) { // 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; @@ -432,21 +478,9 @@ void MatcherGen::EmitMatchCode(const TreePatternNode *N, // If this node has a name associated with it, capture it in VariableMap. If // we already saw this in the pattern, emit code to verify dagness. - if (!N->getName().empty()) { - unsigned &VarMapEntry = VariableMap[N->getName()]; - if (VarMapEntry == 0) { - // If it is a named node, we must emit a 'Record' opcode. - AddMatcher(new RecordMatcher("$" + N->getName(), NextRecordedOperandNo)); - VarMapEntry = ++NextRecordedOperandNo; - } else { - // If we get here, this is a second reference to a specific name. Since - // we already have checked that the first reference is valid, we don't - // have to recursively match it, just check that it's the same as the - // previously named thing. - AddMatcher(new CheckSameMatcher(VarMapEntry-1)); + if (!N->getName().empty()) + if (!recordUniqueNode(N->getName())) return; - } - } if (N->isLeaf()) EmitLeafMatchCode(N); @@ -497,16 +531,20 @@ bool MatcherGen::EmitMatcherCode(unsigned Variant) { const TreePatternNode *N = MatchedComplexPatterns[i].first; // Remember where the results of this match get stuck. - MatchedComplexPatterns[i].second = NextRecordedOperandNo; + if (N->isLeaf()) { + NamedComplexPatternOperands[N->getName()] = NextRecordedOperandNo + 1; + } else { + unsigned CurOp = NextRecordedOperandNo; + for (unsigned i = 0; i < N->getNumChildren(); ++i) { + NamedComplexPatternOperands[N->getChild(i)->getName()] = CurOp + 1; + CurOp += N->getChild(i)->getNumMIResults(CGP); + } + } // Get the slot we recorded the value in from the name on the node. - unsigned RecNodeEntry = VariableMap[N->getName()]; - assert(!N->getName().empty() && RecNodeEntry && - "Complex pattern should have a name and slot"); - --RecNodeEntry; // Entries in VariableMap are biased. + unsigned RecNodeEntry = MatchedComplexPatterns[i].second; - const ComplexPattern &CP = - CGP.getComplexPattern(((DefInit*)N->getLeafValue())->getDef()); + const ComplexPattern &CP = *N->getComplexPatternInfo(CGP); // Emit a CheckComplexPat operation, which does the match (aborting if it // fails) and pushes the matched operands onto the recorded nodes list. @@ -543,21 +581,12 @@ void MatcherGen::EmitResultOfNamedOperand(const TreePatternNode *N, SmallVectorImpl<unsigned> &ResultOps){ assert(!N->getName().empty() && "Operand not named!"); - // A reference to a complex pattern gets all of the results of the complex - // pattern's match. - if (const ComplexPattern *CP = N->getComplexPatternInfo(CGP)) { - unsigned SlotNo = 0; - for (unsigned i = 0, e = MatchedComplexPatterns.size(); i != e; ++i) - if (MatchedComplexPatterns[i].first->getName() == N->getName()) { - SlotNo = MatchedComplexPatterns[i].second; - break; - } - assert(SlotNo != 0 && "Didn't get a slot number assigned?"); + if (unsigned SlotNo = NamedComplexPatternOperands[N->getName()]) { + // Complex operands have already been completely selected, just find the + // right slot ant add the arguments directly. + for (unsigned i = 0; i < N->getNumMIResults(CGP); ++i) + ResultOps.push_back(SlotNo - 1 + i); - // The first slot entry is the node itself, the subsequent entries are the - // matched values. - for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) - ResultOps.push_back(SlotNo+i); return; } @@ -575,7 +604,8 @@ void MatcherGen::EmitResultOfNamedOperand(const TreePatternNode *N, } } - ResultOps.push_back(SlotNo); + for (unsigned i = 0; i < N->getNumMIResults(CGP); ++i) + ResultOps.push_back(SlotNo + i); } void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N, @@ -600,7 +630,7 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N, } if (Def->getName() == "zero_reg") { - AddMatcher(new EmitRegisterMatcher(0, N->getType(0))); + AddMatcher(new EmitRegisterMatcher(nullptr, N->getType(0))); ResultOps.push_back(NextRecordedOperandNo++); return; } @@ -642,7 +672,7 @@ GetInstPatternNode(const DAGInstruction &Inst, const TreePatternNode *N) { else if (/*isRoot*/ N == Pattern.getDstPattern()) InstPatNode = Pattern.getSrcPattern(); else - return 0; + return nullptr; if (InstPatNode && !InstPatNode->isLeaf() && InstPatNode->getOperator()->getName() == "set") @@ -806,7 +836,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, if (isRoot && !Pattern.getDstRegs().empty()) { // If the root came from an implicit def in the instruction handling stuff, // don't re-add it. - Record *HandledReg = 0; + Record *HandledReg = nullptr; if (II.HasOneImplicitDefWithKnownVT(CGT) != MVT::Other) HandledReg = II.ImplicitDefs[0]; @@ -850,8 +880,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 +936,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; @@ -926,7 +954,7 @@ void MatcherGen::EmitResultCode() { if (!Pattern.getDstRegs().empty()) { // If the root came from an implicit def in the instruction handling stuff, // don't re-add it. - Record *HandledReg = 0; + Record *HandledReg = nullptr; const TreePatternNode *DstPat = Pattern.getDstPattern(); if (!DstPat->isLeaf() &&DstPat->getOperator()->isSubClassOf("Instruction")){ const CodeGenTarget &CGT = CGP.getTargetInfo(); @@ -949,10 +977,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)); } @@ -965,7 +992,7 @@ Matcher *llvm::ConvertPatternToMatcher(const PatternToMatch &Pattern, // Generate the code for the matcher. if (Gen.EmitMatcherCode(Variant)) - return 0; + return nullptr; // FIXME2: Kill extra MoveParent commands at the end of the matcher sequence. // FIXME2: Split result code out to another table, and make the matcher end diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp index 82e5d63be58b..da6a9577a770 100644 --- a/utils/TableGen/DAGISelMatcherOpt.cpp +++ b/utils/TableGen/DAGISelMatcherOpt.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "isel-opt" #include "DAGISelMatcher.h" #include "CodeGenDAGPatterns.h" #include "llvm/ADT/DenseSet.h" @@ -20,20 +19,22 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; +#define DEBUG_TYPE "isel-opt" + /// ContractNodes - Turn multiple matcher node patterns like 'MoveChild+Record' /// into single compound nodes like RecordChild. -static void ContractNodes(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(); - if (N == 0) return; + if (!N) return; // If we have a scope node, walk down all of the children. if (ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N)) { 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; } @@ -41,12 +42,12 @@ static void ContractNodes(OwningPtr<Matcher> &MatcherPtr, // If we found a movechild node with a node that comes in a 'foochild' form, // transform it. if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N)) { - Matcher *New = 0; + Matcher *New = nullptr; if (RecordMatcher *RM = dyn_cast<RecordMatcher>(MC->getNext())) if (MC->getChildNo() < 8) // Only have RecordChild0...7 New = new RecordChildMatcher(MC->getChildNo(), RM->getWhatFor(), 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 +57,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 +86,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 +141,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 +165,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,18 +188,18 @@ 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(); - if (N == 0) return; + if (!N) return; // 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; } @@ -203,7 +207,7 @@ static void SinkPatternPredicates(OwningPtr<Matcher> &MatcherPtr) { // If this node isn't a CheckPatternPredicateMatcher we keep scanning until // we find one. CheckPatternPredicateMatcher *CPPM =dyn_cast<CheckPatternPredicateMatcher>(N); - if (CPPM == 0) + if (!CPPM) return SinkPatternPredicates(N->getNextPtr()); // Ok, we found one, lets try to sink it. Check if we can sink it past the @@ -214,7 +218,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(); @@ -233,7 +237,7 @@ static Matcher *FindNodeWithKind(Matcher *M, Matcher::KindTy Kind) { for (; M; M = M->getNext()) if (M->getKind() == Kind) return M; - return 0; + return nullptr; } @@ -249,14 +253,14 @@ 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; + if (!N) return; // If this is not a push node, just scan for one. ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N); - if (Scope == 0) + if (!Scope) return FactorNodes(N->getNextPtr()); // Okay, pull together the children of the scope node into a vector so we can @@ -266,10 +270,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); } @@ -332,7 +336,7 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) { // or the same as what we're looking for. If so, reorder it. if (Optn->isSimplePredicateOrRecordNode()) { Matcher *M2 = FindNodeWithKind(ScanMatcher, Optn->getKind()); - if (M2 != 0 && M2 != ScanMatcher && + if (M2 && M2 != ScanMatcher && M2->canMoveBefore(ScanMatcher) && (M2->isEqual(Optn) || M2->isContradictory(Optn))) { Matcher *MatcherWithoutM2 = ScanMatcher->unlinkNode(M2); @@ -380,7 +384,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()); @@ -396,7 +400,7 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) { } if (NewOptionsToMatch.empty()) { - MatcherPtr.reset(0); + MatcherPtr.reset(); return; } @@ -424,7 +428,7 @@ static void FactorNodes(OwningPtr<Matcher> &MatcherPtr) { CheckTypeMatcher *CTM = cast_or_null<CheckTypeMatcher>(FindNodeWithKind(NewOptionsToMatch[i], Matcher::CheckType)); - if (CTM == 0 || + if (!CTM || // iPTR checks could alias any other case without us knowing, don't // bother with them. CTM->getType() == MVT::iPTR || @@ -455,7 +459,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 +486,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 +495,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 +513,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/DFAPacketizerEmitter.cpp b/utils/TableGen/DFAPacketizerEmitter.cpp index 2549c47c3318..ea14cb973ebc 100644 --- a/utils/TableGen/DFAPacketizerEmitter.cpp +++ b/utils/TableGen/DFAPacketizerEmitter.cpp @@ -82,14 +82,15 @@ namespace { class State { public: static int currentStateNum; - int stateNum; - bool isInitial; - std::set<unsigned> stateInfo; - typedef std::map<unsigned, State *> TransitionMap; - TransitionMap Transitions; + // stateNum is the only member used for equality/ordering, all other members + // can be mutated even in const State objects. + const int stateNum; + mutable bool isInitial; + mutable std::set<unsigned> stateInfo; + typedef std::map<unsigned, const State *> TransitionMap; + mutable TransitionMap Transitions; State(); - State(const State &S); bool operator<(const State &s) const { return stateNum < s.stateNum; @@ -108,16 +109,16 @@ class State { // AddInsnClass - Return all combinations of resource reservation // which are possible from this state (PossibleStates). // - void AddInsnClass(unsigned InsnClass, std::set<unsigned> &PossibleStates); + void AddInsnClass(unsigned InsnClass, std::set<unsigned> &PossibleStates) const; // // addTransition - Add a transition from this state given the input InsnClass // - void addTransition(unsigned InsnClass, State *To); + void addTransition(unsigned InsnClass, const State *To) const; // // hasTransition - Returns true if there is a transition from this state // given the input InsnClass // - bool hasTransition(unsigned InsnClass); + bool hasTransition(unsigned InsnClass) const; }; } // End anonymous namespace. @@ -128,10 +129,9 @@ namespace { class DFA { public: DFA(); - ~DFA(); // Set of states. Need to keep this sorted to emit the transition table. - typedef std::set<State *, less_ptr<State> > StateSet; + typedef std::set<State> StateSet; StateSet states; State *currentState; @@ -139,8 +139,7 @@ public: // // Modify the DFA. // - void initialize(); - void addState(State *); + const State &newState(); // // writeTable: Print out a table representing the DFA. @@ -156,21 +155,12 @@ public: State::State() : stateNum(currentStateNum++), isInitial(false) {} - -State::State(const State &S) : - stateNum(currentStateNum++), isInitial(S.isInitial), - stateInfo(S.stateInfo) {} - -DFA::DFA(): currentState(NULL) {} - -DFA::~DFA() { - DeleteContainerPointers(states); -} +DFA::DFA(): currentState(nullptr) {} // // addTransition - Add a transition from this state given the input InsnClass // -void State::addTransition(unsigned InsnClass, State *To) { +void State::addTransition(unsigned InsnClass, const State *To) const { assert(!Transitions.count(InsnClass) && "Cannot have multiple transitions for the same input"); Transitions[InsnClass] = To; @@ -180,7 +170,7 @@ void State::addTransition(unsigned InsnClass, State *To) { // hasTransition - Returns true if there is a transition from this state // given the input InsnClass // -bool State::hasTransition(unsigned InsnClass) { +bool State::hasTransition(unsigned InsnClass) const { return Transitions.count(InsnClass) > 0; } @@ -189,7 +179,7 @@ bool State::hasTransition(unsigned InsnClass) { // which are possible from this state (PossibleStates). // void State::AddInsnClass(unsigned InsnClass, - std::set<unsigned> &PossibleStates) { + std::set<unsigned> &PossibleStates) const { // // Iterate over all resource states in currentState. // @@ -248,15 +238,10 @@ bool State::canAddInsnClass(unsigned InsnClass) const { } -void DFA::initialize() { - assert(currentState && "Missing current state"); - currentState->isInitial = true; -} - - -void DFA::addState(State *S) { - assert(!states.count(S) && "State already exists"); - states.insert(S); +const State &DFA::newState() { + auto IterPair = states.insert(State()); + assert(IterPair.second && "State already exists"); + return *IterPair.first; } @@ -292,16 +277,16 @@ void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName) { // to construct the StateEntry table. int ValidTransitions = 0; for (unsigned i = 0; i < states.size(); ++i, ++SI) { - assert (((*SI)->stateNum == (int) i) && "Mismatch in state numbers"); + assert ((SI->stateNum == (int) i) && "Mismatch in state numbers"); StateEntry[i] = ValidTransitions; for (State::TransitionMap::iterator - II = (*SI)->Transitions.begin(), IE = (*SI)->Transitions.end(); + II = SI->Transitions.begin(), IE = SI->Transitions.end(); II != IE; ++II) { OS << "{" << II->first << ", " << II->second->stateNum << "}, "; } - ValidTransitions += (*SI)->Transitions.size(); + ValidTransitions += SI->Transitions.size(); // If there are no valid transitions from this stage, we need a sentinel // transition. @@ -447,12 +432,11 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { // Run a worklist algorithm to generate the DFA. // DFA D; - State *Initial = new State; + const State *Initial = &D.newState(); Initial->isInitial = true; Initial->stateInfo.insert(0x0); - D.addState(Initial); - SmallVector<State*, 32> WorkList; - std::map<std::set<unsigned>, State*> Visited; + SmallVector<const State*, 32> WorkList; + std::map<std::set<unsigned>, const State*> Visited; WorkList.push_back(Initial); @@ -474,7 +458,7 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { // Add S' to Visited // while (!WorkList.empty()) { - State *current = WorkList.pop_back_val(); + const State *current = WorkList.pop_back_val(); for (DenseSet<unsigned>::iterator CI = allInsnClasses.begin(), CE = allInsnClasses.end(); CI != CE; ++CI) { unsigned InsnClass = *CI; @@ -486,7 +470,7 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { // if (!current->hasTransition(InsnClass) && current->canAddInsnClass(InsnClass)) { - State *NewState = NULL; + const State *NewState; current->AddInsnClass(InsnClass, NewStateResources); assert(NewStateResources.size() && "New states must be generated"); @@ -494,13 +478,12 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { // If we have seen this state before, then do not create a new state. // // - std::map<std::set<unsigned>, State*>::iterator VI; - if ((VI = Visited.find(NewStateResources)) != Visited.end()) + auto VI = Visited.find(NewStateResources); + if (VI != Visited.end()) NewState = VI->second; else { - NewState = new State; + NewState = &D.newState(); NewState->stateInfo = NewStateResources; - D.addState(NewState); Visited[NewStateResources] = NewState; WorkList.push_back(NewState); } diff --git a/utils/TableGen/DisassemblerEmitter.cpp b/utils/TableGen/DisassemblerEmitter.cpp index 5a2a41b456d7..f02051a2cd6c 100644 --- a/utils/TableGen/DisassemblerEmitter.cpp +++ b/utils/TableGen/DisassemblerEmitter.cpp @@ -117,19 +117,23 @@ 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; } // ARM and Thumb have a CHECK() macro to deal with DecodeStatuses. - if (Target.getName() == "ARM" || - Target.getName() == "Thumb" || - Target.getName() == "AArch64") { - EmitFixedLenDecoder(Records, OS, Target.getName() == "AArch64" ? "AArch64" : "ARM", + if (Target.getName() == "ARM" || Target.getName() == "Thumb" || + Target.getName() == "AArch64" || Target.getName() == "ARM64") { + std::string PredicateNamespace = Target.getName(); + if (PredicateNamespace == "Thumb") + PredicateNamespace = "ARM"; + + EmitFixedLenDecoder(Records, OS, PredicateNamespace, "if (!Check(S, ", ")) return MCDisassembler::Fail;", "S", "MCDisassembler::Fail", " MCDisassembler::DecodeStatus S = " diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp index e35cf0f15749..154f96d3d023 100644 --- a/utils/TableGen/FastISelEmitter.cpp +++ b/utils/TableGen/FastISelEmitter.cpp @@ -188,7 +188,7 @@ struct OperandsSignature { return true; } - const CodeGenRegisterClass *DstRC = 0; + const CodeGenRegisterClass *DstRC = nullptr; for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) { TreePatternNode *Op = InstPatNode->getChild(i); @@ -252,7 +252,7 @@ struct OperandsSignature { Record *OpLeafRec = OpDI->getDef(); // For now, the only other thing we accept is register operands. - const CodeGenRegisterClass *RC = 0; + const CodeGenRegisterClass *RC = nullptr; if (OpLeafRec->isSubClassOf("RegisterOperand")) OpLeafRec = OpLeafRec->getValueAsDef("RegClass"); if (OpLeafRec->isSubClassOf("RegisterClass")) @@ -459,7 +459,7 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) { // For now, ignore instructions where the first operand is not an // output register. - const CodeGenRegisterClass *DstRC = 0; + const CodeGenRegisterClass *DstRC = nullptr; std::string SubRegNo; if (Op->getName() != "EXTRACT_SUBREG") { Record *Op0Rec = II.Operands[0].Rec; @@ -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 87d18cdb9d46..42639cc4cf95 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -12,8 +12,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "decoder-emitter" - #include "CodeGenTarget.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/SmallString.h" @@ -28,13 +26,14 @@ #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> using namespace llvm; +#define DEBUG_TYPE "decoder-emitter" + namespace { struct EncodingField { unsigned Base, Width, Offset; @@ -348,7 +347,7 @@ public: unsigned BW, const FixedLenDecoderEmitter *E) : AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(), - Parent(NULL), BestIndex(-1), BitWidth(BW), Emitter(E) { + Parent(nullptr), BestIndex(-1), BitWidth(BW), Emitter(E) { for (unsigned i = 0; i < BitWidth; ++i) FilterBitValues.push_back(BIT_UNFILTERED); @@ -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 = nullptr; + 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 = nullptr; + 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()) : nullptr; + 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()) : nullptr; + 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,11 +1930,15 @@ 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"); StringInit *String = DecoderString ? - dyn_cast<StringInit>(DecoderString->getValue()) : 0; + dyn_cast<StringInit>(DecoderString->getValue()) : nullptr; if (!isReg && String && String->getValue() != "") Decoder = String->getValue(); @@ -1785,7 +1948,7 @@ static bool populateInstruction(const CodeGenInstruction &CGI, unsigned Opc, unsigned Offset = 0; for (unsigned bi = 0; bi < Bits.getNumBits(); ++bi) { - VarInit *Var = 0; + VarInit *Var = nullptr; VarBitInit *BI = dyn_cast<VarBitInit>(Bits.getBit(bi)); if (BI) Var = dyn_cast<VarInit>(BI->getBitVar()); @@ -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 d3d9cc1fd620..76f05cea3f7e 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); @@ -88,7 +88,7 @@ std::vector<std::string> InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { std::vector<std::string> Result; - for (unsigned i = 0, e = Inst.Operands.size(); i != e; ++i) { + for (auto &Op : Inst.Operands) { // Handle aggregate operands and normal operands the same way by expanding // either case into a list of operands for this op. std::vector<CGIOperandList::OperandInfo> OperandList; @@ -97,14 +97,14 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { // registers in their multi-operand operands. It may also be an anonymous // operand, which has a single operand, but no declared class for the // operand. - DagInit *MIOI = Inst.Operands[i].MIOperandInfo; + DagInit *MIOI = Op.MIOperandInfo; if (!MIOI || MIOI->getNumArgs() == 0) { // Single, anonymous, operand. - OperandList.push_back(Inst.Operands[i]); + OperandList.push_back(Op); } else { - for (unsigned j = 0, e = Inst.Operands[i].MINumOperands; j != e; ++j) { - OperandList.push_back(Inst.Operands[i]); + for (unsigned j = 0, e = Op.MINumOperands; j != e; ++j) { + OperandList.push_back(Op); Record *OpR = cast<DefInit>(MIOI->getArg(j))->getDef(); OperandList.back().Rec = OpR; @@ -134,24 +134,24 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { // Predicate operands. Check to see if the original unexpanded operand // was of type PredicateOp. - if (Inst.Operands[i].Rec->isSubClassOf("PredicateOp")) + if (Op.Rec->isSubClassOf("PredicateOp")) Res += "|(1<<MCOI::Predicate)"; // Optional def operands. Check to see if the original unexpanded operand // was of type OptionalDefOperand. - if (Inst.Operands[i].Rec->isSubClassOf("OptionalDefOperand")) + if (Op.Rec->isSubClassOf("OptionalDefOperand")) Res += "|(1<<MCOI::OptionalDef)"; // Fill in operand type. Res += ", MCOI::"; - assert(!Inst.Operands[i].OperandType.empty() && "Invalid operand type."); - Res += Inst.Operands[i].OperandType; + assert(!Op.OperandType.empty() && "Invalid operand type."); + Res += Op.OperandType; // Fill in constraint info. Res += ", "; const CGIOperandList::ConstraintInfo &Constraint = - Inst.Operands[i].Constraints[j]; + Op.Constraints[j]; if (Constraint.isNone()) Res += "0"; else if (Constraint.isEarlyClobber()) @@ -177,16 +177,15 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS, OS << "\n"; const CodeGenTarget &Target = CDP.getTargetInfo(); - for (CodeGenTarget::inst_iterator II = Target.inst_begin(), - E = Target.inst_end(); II != E; ++II) { - std::vector<std::string> OperandInfo = GetOperandInfo(**II); + for (const CodeGenInstruction *Inst : Target.instructions()) { + std::vector<std::string> OperandInfo = GetOperandInfo(*Inst); unsigned &N = OperandInfoIDs[OperandInfo]; if (N != 0) continue; N = ++OperandListNum; OS << "static const MCOperandInfo OperandInfo" << N << "[] = { "; - for (unsigned i = 0, e = OperandInfo.size(); i != e; ++i) - OS << "{ " << OperandInfo[i] << " }, "; + for (const std::string &Info : OperandInfo) + OS << "{ " << Info << " }, "; OS << "};\n"; } } @@ -200,20 +199,17 @@ 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) { unsigned NumOperands = 0; - for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { - const CodeGenInstruction *Inst = NumberedInstructions[i]; - if (!Inst->TheDef->getValueAsBit("UseNamedOperandTable")) { + for (const CodeGenInstruction *Inst : NumberedInstructions) { + if (!Inst->TheDef->getValueAsBit("UseNamedOperandTable")) continue; - } std::map<unsigned, unsigned> OpList; - for (unsigned j = 0, je = Inst->Operands.size(); j != je; ++j) { - const CGIOperandList::OperandInfo &Info = Inst->Operands[j]; + for (const auto &Info : Inst->Operands) { StrUintMapIter I = Operands.find(Info.Name); if (I == Operands.end()) { @@ -256,8 +252,8 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS, OS << "namespace " << Namespace << " {\n"; OS << "namespace " << OpNameNS << " { \n"; OS << "enum {\n"; - for (StrUintMapIter i = Operands.begin(), e = Operands.end(); i != e; ++i) - OS << " " << i->first << " = " << i->second << ",\n"; + for (const auto &Op : Operands) + OS << " " << Op.first << " = " << Op.second << ",\n"; OS << "OPERAND_LAST"; OS << "\n};\n"; @@ -274,15 +270,13 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS, if (!Operands.empty()) { OS << " static const int16_t OperandMap [][" << Operands.size() << "] = {\n"; - for (OpNameMapTy::iterator i = OperandMap.begin(), e = OperandMap.end(); - i != e; ++i) { - const std::map<unsigned, unsigned> &OpList = i->first; + for (const auto &Entry : OperandMap) { + const std::map<unsigned, unsigned> &OpList = Entry.first; OS << "{"; // Emit a row of the OperandMap table - for (unsigned ii = 0, ie = Operands.size(); ii != ie; ++ii) - OS << (OpList.count(ii) == 0 ? -1 : (int)OpList.find(ii)->second) - << ", "; + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + OS << (OpList.count(i) == 0 ? -1 : (int)OpList.find(i)->second) << ", "; OS << "},\n"; } @@ -290,12 +284,9 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS, OS << " switch(Opcode) {\n"; unsigned TableIndex = 0; - for (OpNameMapTy::iterator i = OperandMap.begin(), e = OperandMap.end(); - i != e; ++i) { - std::vector<std::string> &OpcodeList = i->second; - - for (unsigned ii = 0, ie = OpcodeList.size(); ii != ie; ++ii) - OS << " case " << OpcodeList[ii] << ":\n"; + for (const auto &Entry : OperandMap) { + for (const std::string &Name : Entry.second) + OS << " case " << Name << ":\n"; OS << " return OperandMap[" << TableIndex++ << "][NamedIdx];\n"; } @@ -328,9 +319,11 @@ void InstrInfoEmitter::emitOperandTypesEnum(raw_ostream &OS, OS << "namespace OpTypes { \n"; OS << "enum OperandType {\n"; - for (unsigned oi = 0, oe = Operands.size(); oi != oe; ++oi) { - if (!Operands[oi]->isAnonymous()) - OS << " " << Operands[oi]->getName() << " = " << oi << ",\n"; + unsigned EnumVal = 0; + for (const Record *Op : Operands) { + if (!Op->isAnonymous()) + OS << " " << Op->getName() << " = " << EnumVal << ",\n"; + ++EnumVal; } OS << " OPERAND_TYPE_LIST_END" << "\n};\n"; @@ -365,9 +358,8 @@ void InstrInfoEmitter::run(raw_ostream &OS) { unsigned ListNumber = 0; // Emit all of the instruction's implicit uses and defs. - for (CodeGenTarget::inst_iterator II = Target.inst_begin(), - E = Target.inst_end(); II != E; ++II) { - Record *Inst = (*II)->TheDef; + for (const CodeGenInstruction *II : Target.instructions()) { + Record *Inst = II->TheDef; std::vector<Record*> Uses = Inst->getValueAsListOfDefs("Uses"); if (!Uses.empty()) { unsigned &IL = EmittedLists[Uses]; @@ -391,29 +383,30 @@ void InstrInfoEmitter::run(raw_ostream &OS) { const std::vector<const CodeGenInstruction*> &NumberedInstructions = Target.getInstructionsByEnumValue(); - for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) - emitRecord(*NumberedInstructions[i], i, InstrInfo, EmittedLists, - OperandInfoIDs, OS); - OS << "};\n\n"; - - // Build an array of instruction names SequenceToOffsetTable<std::string> InstrNames; - for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { - const CodeGenInstruction *Instr = NumberedInstructions[i]; - InstrNames.add(Instr->TheDef->getName()); + unsigned Num = 0; + for (const CodeGenInstruction *Inst : NumberedInstructions) { + // Keep a list of the instruction names. + InstrNames.add(Inst->TheDef->getName()); + // Emit the record into the table. + emitRecord(*Inst, Num++, InstrInfo, EmittedLists, OperandInfoIDs, OS); } + OS << "};\n\n"; + // Emit the array of instruction names. InstrNames.layout(); OS << "extern const char " << TargetName << "InstrNameData[] = {\n"; InstrNames.emit(OS, printChar); OS << "};\n\n"; OS << "extern const unsigned " << TargetName <<"InstrNameIndices[] = {"; - for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { - if (i % 8 == 0) + Num = 0; + for (const CodeGenInstruction *Inst : NumberedInstructions) { + // Newline every eight entries. + if (Num % 8 == 0) OS << "\n "; - const CodeGenInstruction *Instr = NumberedInstructions[i]; - OS << InstrNames.get(Instr->TheDef->getName()) << "U, "; + OS << InstrNames.get(Inst->TheDef->getName()) << "U, "; + ++Num; } OS << "\n};\n\n"; @@ -530,20 +523,20 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, // Emit the implicit uses and defs lists... std::vector<Record*> UseList = Inst.TheDef->getValueAsListOfDefs("Uses"); if (UseList.empty()) - OS << "NULL, "; + OS << "nullptr, "; else OS << "ImplicitList" << EmittedLists[UseList] << ", "; std::vector<Record*> DefList = Inst.TheDef->getValueAsListOfDefs("Defs"); if (DefList.empty()) - OS << "NULL, "; + OS << "nullptr, "; else OS << "ImplicitList" << EmittedLists[DefList] << ", "; // Emit the operand info. std::vector<std::string> OperandInfo = GetOperandInfo(Inst); if (OperandInfo.empty()) - OS << "0"; + OS << "nullptr"; else OS << "OperandInfo" << OpInfo.find(OperandInfo)->second; @@ -555,10 +548,10 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, else if (!Inst.DeprecatedReason.empty()) // Emit the Subtarget feature. OS << "," << Target.getInstNamespace() << "::" << Inst.DeprecatedReason - << ",0"; + << ",nullptr"; else // Instruction isn't deprecated. - OS << ",0,0"; + OS << ",0,nullptr"; OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n"; } @@ -586,18 +579,16 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) { OS << "namespace " << Namespace << " {\n"; OS << " enum {\n"; - for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { - OS << " " << NumberedInstructions[i]->TheDef->getName() - << "\t= " << i << ",\n"; - } + unsigned Num = 0; + for (const CodeGenInstruction *Inst : NumberedInstructions) + OS << " " << Inst->TheDef->getName() << "\t= " << Num++ << ",\n"; OS << " INSTRUCTION_LIST_END = " << NumberedInstructions.size() << "\n"; OS << " };\n"; OS << "namespace Sched {\n"; OS << " enum {\n"; - for (unsigned i = 0, e = SchedModels.numInstrSchedClasses(); i != e; ++i) { - OS << " " << SchedModels.getSchedClass(i).Name - << "\t= " << i << ",\n"; - } + Num = 0; + for (const auto &Class : SchedModels.explicit_classes()) + OS << " " << Class.Name << "\t= " << Num++ << ",\n"; OS << " SCHED_LIST_END = " << SchedModels.numInstrSchedClasses() << "\n"; OS << " };\n}\n}\n"; OS << "} // End llvm namespace \n"; diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index 8f137f83d34b..34358c41a742 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -14,6 +14,7 @@ #include "CodeGenIntrinsics.h" #include "CodeGenTarget.h" #include "SequenceToOffsetTable.h" +#include "TableGenBackends.h" #include "llvm/ADT/StringExtras.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" @@ -45,8 +46,6 @@ public: raw_ostream &OS); void EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS); - void EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints, - raw_ostream &OS); void EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS); void EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, @@ -55,6 +54,8 @@ public: raw_ostream &OS); void EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS); + void EmitIntrinsicToMSBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, + raw_ostream &OS); void EmitSuffix(raw_ostream &OS); }; } // End anonymous namespace @@ -97,6 +98,9 @@ void IntrinsicEmitter::run(raw_ostream &OS) { // Emit code to translate GCC builtins into LLVM intrinsics. EmitIntrinsicToGCCBuiltinMap(Ints, OS); + // Emit code to translate MS builtins into LLVM intrinsics. + EmitIntrinsicToMSBuiltinMap(Ints, OS); + EmitSuffix(OS); } @@ -125,26 +129,13 @@ void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints, for (unsigned i = 0, e = Ints.size(); i != e; ++i) { OS << " " << Ints[i].EnumName; OS << ((i != e-1) ? ", " : " "); - OS << std::string(40-Ints[i].EnumName.size(), ' ') - << "// " << Ints[i].Name << "\n"; + if (Ints[i].EnumName.size() < 40) + OS << std::string(40-Ints[i].EnumName.size(), ' '); + OS << " // " << Ints[i].Name << "\n"; } 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 +149,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 +251,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 +298,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 +346,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 +358,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); @@ -391,7 +386,7 @@ static void ComputeFixedEncoding(const CodeGenIntrinsic &Int, case 3: TypeSig.push_back(IIT_STRUCT3); break; case 4: TypeSig.push_back(IIT_STRUCT4); break; case 5: TypeSig.push_back(IIT_STRUCT5); break; - default: assert(0 && "Unhandled case in struct"); + default: llvm_unreachable("Unhandled case in struct"); } for (unsigned i = 0, e = Int.IS.RetVTs.size(); i != e; ++i) @@ -488,11 +483,13 @@ void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints, OS << "#endif\n\n"; // End of GET_INTRINSIC_GENERATOR_GLOBAL } +namespace { enum ModRefKind { MRK_none, MRK_readonly, MRK_readnone }; +} static ModRefKind getModRefKind(const CodeGenIntrinsic &intrinsic) { switch (intrinsic.ModRef) { @@ -515,6 +512,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 +629,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 +643,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 +674,7 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { OS << " }\n"; } else { OS << " return AttributeSet();\n"; + OS << " }\n"; } } @@ -788,10 +796,55 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, OS << "#endif\n\n"; } -namespace llvm { +void IntrinsicEmitter:: +EmitIntrinsicToMSBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, + raw_ostream &OS) { + std::map<std::string, std::map<std::string, std::string>> TargetBuiltins; -void EmitIntrinsics(RecordKeeper &RK, raw_ostream &OS, bool TargetOnly = false) { - IntrinsicEmitter(RK, TargetOnly).run(OS); + for (const auto &Intrinsic : Ints) { + if (Intrinsic.MSBuiltinName.empty()) + continue; + + auto &Builtins = TargetBuiltins[Intrinsic.TargetPrefix]; + if (!Builtins.insert(std::make_pair(Intrinsic.MSBuiltinName, + Intrinsic.EnumName)).second) + PrintFatalError("Intrinsic '" + Intrinsic.TheDef->getName() + "': " + "duplicate MS builtin name!"); + } + + OS << "// Get the LLVM intrinsic that corresponds to a MS builtin.\n" + "// This is used by the C front-end. The MS builtin name is passed\n" + "// in as a BuiltinName, and a target prefix (e.g. 'arm') is passed\n" + "// in as a TargetPrefix. The result is assigned to 'IntrinsicID'.\n" + "#ifdef GET_LLVM_INTRINSIC_FOR_MS_BUILTIN\n"; + + OS << (TargetOnly ? "static " + TargetPrefix : "") << "Intrinsic::ID " + << (TargetOnly ? "" : "Intrinsic::") + << "getIntrinsicForMSBuiltin(const char *TP, const char *BN) {\n"; + OS << " StringRef BuiltinName(BN);\n" + " StringRef TargetPrefix(TP);\n" + "\n"; + + for (const auto &Builtins : TargetBuiltins) { + OS << " "; + if (Builtins.first.empty()) + OS << "/* Target Independent Builtins */ "; + else + OS << "if (TargetPrefix == \"" << Builtins.first << "\") "; + OS << "{\n"; + EmitTargetBuiltins(Builtins.second, TargetPrefix, OS); + OS << "}"; + } + + OS << " return "; + if (!TargetPrefix.empty()) + OS << "(" << TargetPrefix << "Intrinsic::ID)"; + OS << "Intrinsic::not_intrinsic;\n"; + OS << "}\n"; + + OS << "#endif\n\n"; } -} // End llvm namespace +void llvm::EmitIntrinsics(RecordKeeper &RK, raw_ostream &OS, bool TargetOnly) { + IntrinsicEmitter(RK, TargetOnly).run(OS); +} diff --git a/utils/TableGen/OptParserEmitter.cpp b/utils/TableGen/OptParserEmitter.cpp index 9c4daaf7747d..9262d7c8a02c 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; @@ -221,9 +221,11 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { // The containing option group (if any). OS << ", "; - if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) + const ListInit *GroupFlags = nullptr; + if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) { + GroupFlags = DI->getDef()->getValueAsListInit("Flags"); OS << getOptionName(*DI->getDef()); - else + } else OS << "INVALID"; // The option alias (if any). @@ -249,17 +251,19 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { } // The option flags. + OS << ", "; + int NumFlags = 0; const ListInit *LI = R.getValueAsListInit("Flags"); - if (LI->empty()) { - OS << ", 0"; - } else { - OS << ", "; - for (unsigned i = 0, e = LI->size(); i != e; ++i) { - if (i) - OS << " | "; - OS << cast<DefInit>(LI->getElement(i))->getDef()->getName(); - } + for (Init *I : *LI) + OS << (NumFlags++ ? " | " : "") + << cast<DefInit>(I)->getDef()->getName(); + if (GroupFlags) { + for (Init *I : *GroupFlags) + OS << (NumFlags++ ? " | " : "") + << cast<DefInit>(I)->getDef()->getName(); } + if (NumFlags == 0) + OS << '0'; // The option parameter field. OS << ", " << R.getValueAsInt("NumArgs"); diff --git a/utils/TableGen/PseudoLoweringEmitter.cpp b/utils/TableGen/PseudoLoweringEmitter.cpp index 1ea6f7932a3e..3b74ac41e9b3 100644 --- a/utils/TableGen/PseudoLoweringEmitter.cpp +++ b/utils/TableGen/PseudoLoweringEmitter.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "pseudo-lowering" #include "CodeGenInstruction.h" #include "CodeGenTarget.h" #include "llvm/ADT/IndexedMap.h" @@ -21,6 +20,8 @@ #include <vector> using namespace llvm; +#define DEBUG_TYPE "pseudo-lowering" + namespace { class PseudoLoweringEmitter { struct OpData { @@ -156,8 +157,7 @@ void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) { // If there are more operands that weren't in the DAG, they have to // be operands that have default values, or we have an error. Currently, - // Operands that are a sublass of OperandWithDefaultOp have default values. - + // Operands that are a subclass of OperandWithDefaultOp have default values. // Validate that each result pattern argument has a matching (by name) // argument in the source instruction, in either the (outs) or (ins) list. @@ -200,70 +200,74 @@ void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) { o << "bool " << Target.getName() + "AsmPrinter" << "::\n" << "emitPseudoExpansionLowering(MCStreamer &OutStreamer,\n" - << " const MachineInstr *MI) {\n" - << " switch (MI->getOpcode()) {\n" - << " default: return false;\n"; - for (unsigned i = 0, e = Expansions.size(); i != e; ++i) { - PseudoExpansion &Expansion = Expansions[i]; - CodeGenInstruction &Source = Expansion.Source; - CodeGenInstruction &Dest = Expansion.Dest; - o << " case " << Source.Namespace << "::" - << Source.TheDef->getName() << ": {\n" - << " MCInst TmpInst;\n" - << " MCOperand MCOp;\n" - << " TmpInst.setOpcode(" << Dest.Namespace << "::" - << Dest.TheDef->getName() << ");\n"; - - // Copy the operands from the source instruction. - // FIXME: Instruction operands with defaults values (predicates and cc_out - // in ARM, for example shouldn't need explicit values in the - // expansion DAG. - unsigned MIOpNo = 0; - for (unsigned OpNo = 0, E = Dest.Operands.size(); OpNo != E; - ++OpNo) { - o << " // Operand: " << Dest.Operands[OpNo].Name << "\n"; - for (unsigned i = 0, e = Dest.Operands[OpNo].MINumOperands; - i != e; ++i) { - switch (Expansion.OperandMap[MIOpNo + i].Kind) { - case OpData::Operand: - o << " lowerOperand(MI->getOperand(" - << Source.Operands[Expansion.OperandMap[MIOpNo].Data - .Operand].MIOperandNo + i - << "), MCOp);\n" - << " TmpInst.addOperand(MCOp);\n"; - break; - case OpData::Imm: - o << " TmpInst.addOperand(MCOperand::CreateImm(" - << Expansion.OperandMap[MIOpNo + i].Data.Imm << "));\n"; - break; - case OpData::Reg: { - Record *Reg = Expansion.OperandMap[MIOpNo + i].Data.Reg; - o << " TmpInst.addOperand(MCOperand::CreateReg("; - // "zero_reg" is special. - if (Reg->getName() == "zero_reg") - o << "0"; - else - o << Reg->getValueAsString("Namespace") << "::" << Reg->getName(); - o << "));\n"; - break; - } + << " const MachineInstr *MI) {\n"; + + if (!Expansions.empty()) { + o << " switch (MI->getOpcode()) {\n" + << " default: return false;\n"; + for (auto &Expansion : Expansions) { + CodeGenInstruction &Source = Expansion.Source; + CodeGenInstruction &Dest = Expansion.Dest; + o << " case " << Source.Namespace << "::" + << Source.TheDef->getName() << ": {\n" + << " MCInst TmpInst;\n" + << " MCOperand MCOp;\n" + << " TmpInst.setOpcode(" << Dest.Namespace << "::" + << Dest.TheDef->getName() << ");\n"; + + // Copy the operands from the source instruction. + // FIXME: Instruction operands with defaults values (predicates and cc_out + // in ARM, for example shouldn't need explicit values in the + // expansion DAG. + unsigned MIOpNo = 0; + for (const auto &DestOperand : Dest.Operands) { + o << " // Operand: " << DestOperand.Name << "\n"; + for (unsigned i = 0, e = DestOperand.MINumOperands; i != e; ++i) { + switch (Expansion.OperandMap[MIOpNo + i].Kind) { + case OpData::Operand: + o << " lowerOperand(MI->getOperand(" + << Source.Operands[Expansion.OperandMap[MIOpNo].Data + .Operand].MIOperandNo + i + << "), MCOp);\n" + << " TmpInst.addOperand(MCOp);\n"; + break; + case OpData::Imm: + o << " TmpInst.addOperand(MCOperand::CreateImm(" + << Expansion.OperandMap[MIOpNo + i].Data.Imm << "));\n"; + break; + case OpData::Reg: { + Record *Reg = Expansion.OperandMap[MIOpNo + i].Data.Reg; + o << " TmpInst.addOperand(MCOperand::CreateReg("; + // "zero_reg" is special. + if (Reg->getName() == "zero_reg") + o << "0"; + else + o << Reg->getValueAsString("Namespace") << "::" + << Reg->getName(); + o << "));\n"; + break; + } + } } + MIOpNo += DestOperand.MINumOperands; } - MIOpNo += Dest.Operands[OpNo].MINumOperands; - } - if (Dest.Operands.isVariadic) { - MIOpNo = Source.Operands.size() + 1; - o << " // variable_ops\n"; - o << " for (unsigned i = " << MIOpNo - << ", e = MI->getNumOperands(); i != e; ++i)\n" - << " if (lowerOperand(MI->getOperand(i), MCOp))\n" - << " TmpInst.addOperand(MCOp);\n"; + if (Dest.Operands.isVariadic) { + MIOpNo = Source.Operands.size() + 1; + o << " // variable_ops\n"; + o << " for (unsigned i = " << MIOpNo + << ", e = MI->getNumOperands(); i != e; ++i)\n" + << " if (lowerOperand(MI->getOperand(i), MCOp))\n" + << " TmpInst.addOperand(MCOp);\n"; + } + o << " EmitToStreamer(OutStreamer, TmpInst);\n" + << " break;\n" + << " }\n"; } - o << " OutStreamer.EmitInstruction(TmpInst);\n" - << " break;\n" - << " }\n"; - } - o << " }\n return true;\n}\n\n"; + o << " }\n return true;"; + } else + o << " return false;"; + + o << "\n}\n\n"; } void PseudoLoweringEmitter::run(raw_ostream &o) { diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index cc08df9443a3..573c37f4eef4 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -225,7 +225,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, for (unsigned i = 0; i < NumSets; ++i ) { OS << " \"" << RegBank.getRegSetAt(i).Name << "\",\n"; } - OS << " 0 };\n" + OS << " nullptr };\n" << " return PressureNameTable[Idx];\n" << "}\n\n"; @@ -831,7 +831,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, // Emit the table of register unit roots. Each regunit has one or two root // registers. - OS << "extern const uint16_t " << TargetName << "RegUnitRoots[][2] = {\n"; + OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2] = {\n"; for (unsigned i = 0, e = RegBank.getNumNativeRegUnits(); i != e; ++i) { ArrayRef<const CodeGenRegister*> Roots = RegBank.getRegUnit(i).getRoots(); assert(!Roots.empty() && "All regunits must have a root register."); @@ -858,7 +858,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, // Emit the register list now. OS << " // " << Name << " Register Class...\n" - << " const uint16_t " << Name + << " const MCPhysReg " << Name << "[] = {\n "; for (unsigned i = 0, e = Order.size(); i != e; ++i) { Record *Reg = Order[i]; @@ -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(); @@ -1067,7 +1068,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Now that all of the structs have been emitted, emit the instances. if (!RegisterClasses.empty()) { OS << "\nstatic const TargetRegisterClass *const " - << "NullRegClasses[] = { NULL };\n\n"; + << "NullRegClasses[] = { nullptr };\n\n"; // Emit register class bit mask tables. The first bit mask emitted for a // register class, RC, is the set of sub-classes, including RC itself. @@ -1134,7 +1135,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << RC.getName() << "Superclasses[] = {\n"; for (unsigned i = 0; i != Supers.size(); ++i) OS << " &" << Supers[i]->getQualifiedName() << "RegClass,\n"; - OS << " NULL\n};\n\n"; + OS << " nullptr\n};\n\n"; } // Emit methods. @@ -1188,7 +1189,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, else OS << RC.getName() << "Superclasses,\n "; if (RC.AltOrderSelect.empty()) - OS << "0\n"; + OS << "nullptr\n"; else OS << RC.getName() << "GetRawAllocationOrder\n"; OS << " };\n\n"; @@ -1257,7 +1258,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << " if (!Idx) return RC;\n --Idx;\n" << " assert(Idx < " << SubRegIndices.size() << " && \"Bad subreg\");\n" << " unsigned TV = Table[RC->getID()][Idx];\n" - << " return TV ? getRegClass(TV - 1) : 0;\n}\n\n"; + << " return TV ? getRegClass(TV - 1) : nullptr;\n}\n\n"; } EmitRegUnitPressure(OS, RegBank, ClassName); @@ -1266,7 +1267,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n"; OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[];\n"; OS << "extern const char " << TargetName << "RegStrings[];\n"; - OS << "extern const uint16_t " << TargetName << "RegUnitRoots[][2];\n"; + OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2];\n"; OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[];\n"; OS << "extern const MCRegisterInfo::SubRegCoveredBits " << TargetName << "SubRegIdxRanges[];\n"; diff --git a/utils/TableGen/SetTheory.cpp b/utils/TableGen/SetTheory.cpp deleted file mode 100644 index ad3d7c7e1893..000000000000 --- a/utils/TableGen/SetTheory.cpp +++ /dev/null @@ -1,328 +0,0 @@ -//===- SetTheory.cpp - Generate ordered sets from DAG expressions ---------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the SetTheory class that computes ordered sets of -// Records from DAG expressions. -// -//===----------------------------------------------------------------------===// - -#include "SetTheory.h" -#include "llvm/Support/Format.h" -#include "llvm/TableGen/Error.h" -#include "llvm/TableGen/Record.h" - -using namespace llvm; - -// Define the standard operators. -namespace { - -typedef SetTheory::RecSet RecSet; -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) { - 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) { - if (Expr->arg_size() < 2) - PrintFatalError(Loc, "Set difference needs at least two arguments: " + - Expr->getAsString()); - RecSet Add, Sub; - ST.evaluate(*Expr->arg_begin(), Add, Loc); - ST.evaluate(Expr->arg_begin() + 1, Expr->arg_end(), Sub, Loc); - for (RecSet::iterator I = Add.begin(), E = Add.end(); I != E; ++I) - if (!Sub.count(*I)) - Elts.insert(*I); - } -}; - -// (and S1, S2) Set intersection. -struct AndOp : public SetTheory::Operator { - virtual void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, - ArrayRef<SMLoc> Loc) { - if (Expr->arg_size() != 2) - PrintFatalError(Loc, "Set intersection requires two arguments: " + - Expr->getAsString()); - RecSet S1, S2; - ST.evaluate(Expr->arg_begin()[0], S1, Loc); - ST.evaluate(Expr->arg_begin()[1], S2, Loc); - for (RecSet::iterator I = S1.begin(), E = S1.end(); I != E; ++I) - if (S2.count(*I)) - Elts.insert(*I); - } -}; - -// 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 apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, - ArrayRef<SMLoc> Loc) { - if (Expr->arg_size() != 2) - PrintFatalError(Loc, "Operator requires (Op Set, Int) arguments: " + - Expr->getAsString()); - RecSet Set; - ST.evaluate(Expr->arg_begin()[0], Set, Loc); - IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[1]); - if (!II) - PrintFatalError(Loc, "Second argument must be an integer: " + - Expr->getAsString()); - apply2(ST, Expr, Set, II->getValue(), Elts, Loc); - } -}; - -// (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) { - if (N < 0) - PrintFatalError(Loc, "Positive shift required: " + - Expr->getAsString()); - if (unsigned(N) < Set.size()) - Elts.insert(Set.begin() + N, Set.end()); - } -}; - -// (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) { - if (N < 0) - PrintFatalError(Loc, "Positive length required: " + - Expr->getAsString()); - if (unsigned(N) > Set.size()) - N = Set.size(); - Elts.insert(Set.begin(), Set.begin() + N); - } -}; - -// Left/right rotation. -struct RotOp : public SetIntBinOp { - const bool Reverse; - - RotOp(bool Rev) : Reverse(Rev) {} - - virtual void apply2(SetTheory &ST, DagInit *Expr, - RecSet &Set, int64_t N, - RecSet &Elts, ArrayRef<SMLoc> Loc) { - if (Reverse) - N = -N; - // N > 0 -> rotate left, N < 0 -> rotate right. - if (Set.empty()) - return; - if (N < 0) - N = Set.size() - (-N % Set.size()); - else - N %= Set.size(); - Elts.insert(Set.begin() + N, Set.end()); - Elts.insert(Set.begin(), Set.begin() + N); - } -}; - -// (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) { - if (N <= 0) - PrintFatalError(Loc, "Positive stride required: " + - Expr->getAsString()); - for (unsigned I = 0; I < Set.size(); I += N) - Elts.insert(Set[I]); - } -}; - -// (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) { - // Evaluate the arguments individually. - SmallVector<RecSet, 4> Args(Expr->getNumArgs()); - unsigned MaxSize = 0; - for (unsigned i = 0, e = Expr->getNumArgs(); i != e; ++i) { - ST.evaluate(Expr->getArg(i), Args[i], Loc); - MaxSize = std::max(MaxSize, unsigned(Args[i].size())); - } - // Interleave arguments into Elts. - for (unsigned n = 0; n != MaxSize; ++n) - for (unsigned i = 0, e = Expr->getNumArgs(); i != e; ++i) - if (n < Args[i].size()) - Elts.insert(Args[i][n]); - } -}; - -// (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) { - int Step = 1; - if (Expr->arg_size() > 4) - PrintFatalError(Loc, "Bad args to (sequence \"Format\", From, To): " + - Expr->getAsString()); - else if (Expr->arg_size() == 4) { - if (IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[3])) { - Step = II->getValue(); - } else - PrintFatalError(Loc, "Stride must be an integer: " + - Expr->getAsString()); - } - - std::string Format; - if (StringInit *SI = dyn_cast<StringInit>(Expr->arg_begin()[0])) - Format = SI->getValue(); - else - PrintFatalError(Loc, "Format must be a string: " + Expr->getAsString()); - - int64_t From, To; - if (IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[1])) - From = II->getValue(); - else - PrintFatalError(Loc, "From must be an integer: " + Expr->getAsString()); - if (From < 0 || From >= (1 << 30)) - PrintFatalError(Loc, "From out of range"); - - if (IntInit *II = dyn_cast<IntInit>(Expr->arg_begin()[2])) - To = II->getValue(); - else - PrintFatalError(Loc, "From must be an integer: " + Expr->getAsString()); - if (To < 0 || To >= (1 << 30)) - PrintFatalError(Loc, "To out of range"); - - RecordKeeper &Records = - cast<DefInit>(Expr->getOperator())->getDef()->getRecords(); - - Step *= From <= To ? 1 : -1; - while (true) { - if (Step > 0 && From > To) - break; - else if (Step < 0 && From < To) - break; - std::string Name; - raw_string_ostream OS(Name); - OS << format(Format.c_str(), unsigned(From)); - Record *Rec = Records.getDef(OS.str()); - if (!Rec) - PrintFatalError(Loc, "No def named '" + Name + "': " + - Expr->getAsString()); - // Try to reevaluate Rec in case it is a set. - if (const RecVec *Result = ST.expand(Rec)) - Elts.insert(Result->begin(), Result->end()); - else - Elts.insert(Rec); - - From += Step; - } - } -}; - -// Expand a Def into a set by evaluating one of its fields. -struct FieldExpander : public SetTheory::Expander { - StringRef FieldName; - - FieldExpander(StringRef fn) : FieldName(fn) {} - - virtual void expand(SetTheory &ST, Record *Def, RecSet &Elts) { - ST.evaluate(Def->getValueInit(FieldName), Elts, Def->getLoc()); - } -}; -} // end anonymous namespace - -// Pin the vtables to this file. -void SetTheory::Operator::anchor() {} -void SetTheory::Expander::anchor() {} - - -SetTheory::SetTheory() { - addOperator("add", new AddOp); - addOperator("sub", new SubOp); - addOperator("and", new AndOp); - addOperator("shl", new ShlOp); - addOperator("trunc", new TruncOp); - addOperator("rotl", new RotOp(false)); - addOperator("rotr", new RotOp(true)); - addOperator("decimate", new DecimateOp); - addOperator("interleave", new InterleaveOp); - addOperator("sequence", new SequenceOp); -} - -void SetTheory::addOperator(StringRef Name, Operator *Op) { - Operators[Name] = Op; -} - -void SetTheory::addExpander(StringRef ClassName, Expander *E) { - Expanders[ClassName] = E; -} - -void SetTheory::addFieldExpander(StringRef ClassName, StringRef FieldName) { - addExpander(ClassName, new FieldExpander(FieldName)); -} - -void SetTheory::evaluate(Init *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) { - // A def in a list can be a just an element, or it may expand. - if (DefInit *Def = dyn_cast<DefInit>(Expr)) { - if (const RecVec *Result = expand(Def->getDef())) - return Elts.insert(Result->begin(), Result->end()); - Elts.insert(Def->getDef()); - return; - } - - // Lists simply expand. - if (ListInit *LI = dyn_cast<ListInit>(Expr)) - return evaluate(LI->begin(), LI->end(), Elts, Loc); - - // Anything else must be a DAG. - DagInit *DagExpr = dyn_cast<DagInit>(Expr); - if (!DagExpr) - PrintFatalError(Loc, "Invalid set element: " + Expr->getAsString()); - DefInit *OpInit = dyn_cast<DefInit>(DagExpr->getOperator()); - if (!OpInit) - PrintFatalError(Loc, "Bad set expression: " + Expr->getAsString()); - Operator *Op = Operators.lookup(OpInit->getDef()->getName()); - if (!Op) - PrintFatalError(Loc, "Unknown set operator: " + Expr->getAsString()); - Op->apply(*this, DagExpr, Elts, Loc); -} - -const RecVec *SetTheory::expand(Record *Set) { - // Check existing entries for Set and return early. - ExpandMap::iterator I = Expansions.find(Set); - if (I != Expansions.end()) - return &I->second; - - // This is the first time we see Set. Find a suitable expander. - const std::vector<Record*> &SC = Set->getSuperClasses(); - for (unsigned i = 0, e = SC.size(); i != e; ++i) { - // Skip unnamed superclasses. - if (!dyn_cast<StringInit>(SC[i]->getNameInit())) - continue; - if (Expander *Exp = Expanders.lookup(SC[i]->getName())) { - // This breaks recursive definitions. - RecVec &EltVec = Expansions[Set]; - RecSet Elts; - Exp->expand(*this, Set, Elts); - EltVec.assign(Elts.begin(), Elts.end()); - return &EltVec; - } - } - - // Set is not expandable. - return 0; -} - diff --git a/utils/TableGen/SetTheory.h b/utils/TableGen/SetTheory.h deleted file mode 100644 index 5baed79fb76a..000000000000 --- a/utils/TableGen/SetTheory.h +++ /dev/null @@ -1,142 +0,0 @@ -//===- SetTheory.h - Generate ordered sets from DAG expressions -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the SetTheory class that computes ordered sets of -// Records from DAG expressions. Operators for standard set operations are -// predefined, and it is possible to add special purpose set operators as well. -// -// The user may define named sets as Records of predefined classes. Set -// expanders can be added to a SetTheory instance to teach it how to find the -// elements of such a named set. -// -// These are the predefined operators. The argument lists can be individual -// elements (defs), other sets (defs of expandable classes), lists, or DAG -// expressions that are evaluated recursively. -// -// - (add S1, S2 ...) Union sets. This is also how sets are created from element -// lists. -// -// - (sub S1, S2, ...) Set difference. Every element in S1 except for the -// elements in S2, ... -// -// - (and S1, S2) Set intersection. Every element in S1 that is also in S2. -// -// - (shl S, N) Shift left. Remove the first N elements from S. -// -// - (trunc S, N) Truncate. The first N elements of S. -// -// - (rotl S, N) Rotate left. Same as (add (shl S, N), (trunc S, N)). -// -// - (rotr S, N) Rotate right. -// -// - (decimate S, N) Decimate S by picking every N'th element, starting with -// the first one. For instance, (decimate S, 2) returns the even elements of -// S. -// -// - (sequence "Format", From, To) Generate a sequence of defs with printf. -// For instance, (sequence "R%u", 0, 3) -> [ R0, R1, R2, R3 ] -// -//===----------------------------------------------------------------------===// - -#ifndef SETTHEORY_H -#define SETTHEORY_H - -#include "llvm/ADT/SetVector.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/Support/SourceMgr.h" -#include <map> -#include <vector> - -namespace llvm { - -class DagInit; -class Init; -class Record; -class RecordKeeper; - -class SetTheory { -public: - typedef std::vector<Record*> RecVec; - typedef SmallSetVector<Record*, 16> RecSet; - - /// Operator - A callback representing a DAG operator. - class Operator { - virtual void anchor(); - public: - virtual ~Operator() {} - - /// apply - Apply this operator to Expr's arguments and insert the result - /// in Elts. - virtual void apply(SetTheory&, DagInit *Expr, RecSet &Elts, - ArrayRef<SMLoc> Loc) =0; - }; - - /// Expander - A callback function that can transform a Record representing a - /// set into a fully expanded list of elements. Expanders provide a way for - /// users to define named sets that can be used in DAG expressions. - class Expander { - virtual void anchor(); - public: - virtual ~Expander() {} - - virtual void expand(SetTheory&, Record*, RecSet &Elts) =0; - }; - -private: - // Map set defs to their fully expanded contents. This serves as a memoization - // cache and it makes it possible to return const references on queries. - typedef std::map<Record*, RecVec> ExpandMap; - ExpandMap Expansions; - - // Known DAG operators by name. - StringMap<Operator*> Operators; - - // Typed expanders by class name. - StringMap<Expander*> Expanders; - -public: - /// Create a SetTheory instance with only the standard operators. - SetTheory(); - - /// addExpander - Add an expander for Records with the named super class. - void addExpander(StringRef ClassName, Expander*); - - /// addFieldExpander - Add an expander for ClassName that simply evaluates - /// FieldName in the Record to get the set elements. That is all that is - /// needed for a class like: - /// - /// class Set<dag d> { - /// dag Elts = d; - /// } - /// - void addFieldExpander(StringRef ClassName, StringRef FieldName); - - /// addOperator - Add a DAG operator. - void addOperator(StringRef Name, Operator*); - - /// evaluate - Evaluate Expr and append the resulting set to Elts. - void evaluate(Init *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc); - - /// evaluate - Evaluate a sequence of Inits and append to Elts. - template<typename Iter> - void evaluate(Iter begin, Iter end, RecSet &Elts, ArrayRef<SMLoc> Loc) { - while (begin != end) - evaluate(*begin++, Elts, Loc); - } - - /// expand - Expand a record into a set of elements if possible. Return a - /// pointer to the expanded elements, or NULL if Set cannot be expanded - /// further. - const RecVec *expand(Record *Set); -}; - -} // end namespace llvm - -#endif - diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index b9f9d0603940..a59eead6d0df 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -11,8 +11,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "subtarget-emitter" - #include "CodeGenTarget.h" #include "CodeGenSchedule.h" #include "llvm/ADT/STLExtras.h" @@ -29,6 +27,8 @@ #include <vector> using namespace llvm; +#define DEBUG_TYPE "subtarget-emitter" + namespace { class SubtargetEmitter { // Each processor has a SchedClassDesc table with an entry for each SchedClass. @@ -578,7 +578,7 @@ EmitItineraries(raw_ostream &OS, OS << "\n"; OS << "static const llvm::InstrItinerary "; if (ItinList.empty()) { - OS << '*' << Name << " = 0;\n"; + OS << '*' << Name << " = nullptr;\n"; continue; } @@ -631,7 +631,7 @@ void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel, for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) { Record *PRDef = ProcModel.ProcResourceDefs[i]; - Record *SuperDef = 0; + Record *SuperDef = nullptr; unsigned SuperIdx = 0; unsigned NumUnits = 0; int BufferSize = PRDef->getValueAsInt("BufferSize"); @@ -676,7 +676,7 @@ Record *SubtargetEmitter::FindWriteResources( if (SchedWrite.TheDef->isSubClassOf("SchedWriteRes")) return SchedWrite.TheDef; - Record *AliasDef = 0; + Record *AliasDef = nullptr; for (RecIter AI = SchedWrite.Aliases.begin(), AE = SchedWrite.Aliases.end(); AI != AE; ++AI) { const CodeGenSchedRW &AliasRW = @@ -696,7 +696,7 @@ Record *SubtargetEmitter::FindWriteResources( return AliasDef; // Check this processor's list of write resources. - Record *ResDef = 0; + Record *ResDef = nullptr; for (RecIter WRI = ProcModel.WriteResDefs.begin(), WRE = ProcModel.WriteResDefs.end(); WRI != WRE; ++WRI) { if (!(*WRI)->isSubClassOf("WriteRes")) @@ -730,7 +730,7 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead, return SchedRead.TheDef; // Check this processor's list of aliases for SchedRead. - Record *AliasDef = 0; + Record *AliasDef = nullptr; for (RecIter AI = SchedRead.Aliases.begin(), AE = SchedRead.Aliases.end(); AI != AE; ++AI) { const CodeGenSchedRW &AliasRW = @@ -750,7 +750,7 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead, return AliasDef; // Check this processor's ReadAdvanceList. - Record *ResDef = 0; + Record *ResDef = nullptr; for (RecIter RAI = ProcModel.ReadAdvanceDefs.begin(), RAE = ProcModel.ReadAdvanceDefs.end(); RAI != RAE; ++RAI) { if (!(*RAI)->isSubClassOf("ReadAdvance")) @@ -884,7 +884,7 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel, if (!SCI->InstRWs.empty()) { // This class has a default ReadWrite list which can be overriden by // InstRW definitions. - Record *RWDef = 0; + Record *RWDef = nullptr; for (RecIter RWI = SCI->InstRWs.begin(), RWE = SCI->InstRWs.end(); RWI != RWE; ++RWI) { Record *RWModelDef = (*RWI)->getValueAsDef("SchedModel"); @@ -1195,11 +1195,16 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n"; EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ','); EmitProcessorProp(OS, PI->ModelDef, "MicroOpBufferSize", ','); + EmitProcessorProp(OS, PI->ModelDef, "LoopMicroOpBufferSize", ','); EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ','); EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ','); EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ','); OS << " " << (bool)(PI->ModelDef ? + PI->ModelDef->getValueAsBit("PostRAScheduler") : 0) + << ", // " << "PostRAScheduler\n"; + + OS << " " << (bool)(PI->ModelDef ? PI->ModelDef->getValueAsBit("CompleteModel") : 0) << ", // " << "CompleteModel\n"; @@ -1454,11 +1459,11 @@ void SubtargetEmitter::run(raw_ostream &OS) { if (NumFeatures) OS << Target << "FeatureKV, "; else - OS << "0, "; + OS << "None, "; if (NumProcs) OS << Target << "SubTypeKV, "; else - OS << "0, "; + OS << "None, "; OS << '\n'; OS.indent(22); OS << Target << "ProcSchedKV, " << Target << "WriteProcResTable, " @@ -1468,10 +1473,10 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << '\n'; OS.indent(22); OS << Target << "Stages, " << Target << "OperandCycles, " - << Target << "ForwardingPaths, "; + << Target << "ForwardingPaths"; } else - OS << "0, 0, 0, "; - OS << NumFeatures << ", " << NumProcs << ");\n}\n\n"; + OS << "0, 0, 0"; + OS << ");\n}\n\n"; OS << "} // End llvm namespace \n"; @@ -1481,7 +1486,6 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n"; OS << "#include \"llvm/Support/Debug.h\"\n"; - OS << "#include \"llvm/Support/raw_ostream.h\"\n"; ParseFeaturesFunction(OS, NumFeatures, NumProcs); OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n"; @@ -1498,7 +1502,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"; @@ -1532,13 +1536,13 @@ void SubtargetEmitter::run(raw_ostream &OS) { << " : TargetSubtargetInfo() {\n" << " InitMCSubtargetInfo(TT, CPU, FS, "; if (NumFeatures) - OS << Target << "FeatureKV, "; + OS << "makeArrayRef(" << Target << "FeatureKV, " << NumFeatures << "), "; else - OS << "0, "; + OS << "None, "; if (NumProcs) - OS << Target << "SubTypeKV, "; + OS << "makeArrayRef(" << Target << "SubTypeKV, " << NumProcs << "), "; else - OS << "0, "; + OS << "None, "; OS << '\n'; OS.indent(22); OS << Target << "ProcSchedKV, " << Target << "WriteProcResTable, " @@ -1548,10 +1552,10 @@ void SubtargetEmitter::run(raw_ostream &OS) { if (SchedModels.hasItineraries()) { OS << Target << "Stages, " << Target << "OperandCycles, " - << Target << "ForwardingPaths, "; + << Target << "ForwardingPaths"; } else - OS << "0, 0, 0, "; - OS << NumFeatures << ", " << NumProcs << ");\n}\n\n"; + OS << "0, 0, 0"; + OS << ");\n}\n\n"; EmitSchedModelHelpers(ClassName, OS); diff --git a/utils/TableGen/TGValueTypes.cpp b/utils/TableGen/TGValueTypes.cpp deleted file mode 100644 index f4893f50a6ff..000000000000 --- 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 b5c3ca760db6..bbd61f5fb112 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -12,13 +12,13 @@ //===----------------------------------------------------------------------===// #include "TableGenBackends.h" // Declares all backends. -#include "SetTheory.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Main.h" #include "llvm/TableGen/Record.h" +#include "llvm/TableGen/SetTheory.h" using namespace llvm; @@ -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 3ff922b8225c..9e79b9c553a7 100644 --- a/utils/TableGen/X86DisassemblerShared.h +++ b/utils/TableGen/X86DisassemblerShared.h @@ -13,27 +13,42 @@ #include <string.h> #include <string> -#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)); \ +#include "../../lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h" + +struct InstructionSpecifier { + llvm::X86Disassembler::OperandSpecifier + operands[llvm::X86Disassembler::X86_MAX_OPERANDS]; + llvm::X86Disassembler::InstructionContext insnContext; + std::string name; + + InstructionSpecifier() { + insnContext = llvm::X86Disassembler::IC; + name = ""; + memset(operands, 0, sizeof(operands)); } +}; -#define INSTRUCTION_IDS \ - InstrUID instructionIDs[256]; +/// Specifies whether a ModR/M byte is needed and (if so) which +/// instruction each possible value of the ModR/M byte corresponds to. Once +/// this information is known, we have narrowed down to a single instruction. +struct ModRMDecision { + uint8_t modrm_type; + llvm::X86Disassembler::InstrUID instructionIDs[256]; +}; -#include "../../lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h" +/// Specifies which set of ModR/M->instruction tables to look at +/// given a particular opcode. +struct OpcodeDecision { + ModRMDecision modRMDecisions[256]; +}; -#undef INSTRUCTION_SPECIFIER_FIELDS -#undef INSTRUCTION_IDS +/// Specifies which opcode->instruction tables to look at given +/// a particular context (set of attributes). Since there are many possible +/// contexts, the decoder first uses CONTEXTS_SYM to determine which context +/// applies given a specific set of attributes. Hence there are only IC_max +/// entries in this table, rather than 2^(ATTR_max). +struct ContextDecision { + OpcodeDecision opcodeDecisions[llvm::X86Disassembler::IC_max]; +}; #endif diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp index bdb479318597..fbcc6f228ca0 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 bf8b1271e9af..1327375f7957 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 7166fe02d890..1641613aa32d 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 2cbaf7985db2..fac38389eadd 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 708e72d36e1b..b7bd822d31d6 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,33 @@ 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"); + CD8_Scale = byteFromRec(Rec, "CD8_Scale"); 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 +220,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 +255,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 +269,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,80 +442,14 @@ 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::adjustOperandEncoding(OperandEncoding &encoding) { + // The scaling factor for AVX512 compressed displacement encoding is an + // instruction attribute. Adjust the ModRM encoding type to include the + // scale for compressed displacement. + if (encoding != ENCODING_RM || CD8_Scale == 0) + return; + encoding = (OperandEncoding)(encoding + Log2_32(CD8_Scale)); + assert(encoding <= ENCODING_RM_CD64 && "Invalid CDisp scaling"); } void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex, @@ -566,7 +458,7 @@ void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex, const unsigned *operandMapping, OperandEncoding (*encodingFromString) (const std::string&, - bool hasOpSizePrefix)) { + uint8_t OpSize)) { if (optional) { if (physicalOperandIndex >= numPhysicalOperands) return; @@ -583,34 +475,20 @@ void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex, const std::string &typeName = (*Operands)[operandIndex].Rec->getName(); - Spec->operands[operandIndex].encoding = encodingFromString(typeName, - HasOpSizePrefix); + OperandEncoding encoding = encodingFromString(typeName, OpSize); + // Adjust the encoding type for an operand based on the instruction. + adjustOperandEncoding(encoding); + Spec->operands[operandIndex].encoding = encoding; 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 +540,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 +559,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 +576,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 +585,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 +598,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 +609,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 +624,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 +636,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 +646,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { HANDLE_OPERAND(rmRegister) - if (HasVEX_4VOp3Prefix) + if (HasVEX_4VOp3) HANDLE_OPERAND(vvvvRegister) if (!HasMemOp4Prefix) @@ -767,7 +660,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 +672,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 +682,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 +703,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 +716,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 +729,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 +766,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; } @@ -890,293 +801,81 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { OpcodeType opcodeType = (OpcodeType)-1; - ModRMFilter* filter = NULL; + ModRMFilter* filter = nullptr; 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 +885,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 +941,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 +958,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,10 +973,20 @@ 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("VK2", TYPE_VK2) + TYPE("VK2WM", TYPE_VK2) + TYPE("VK4", TYPE_VK4) + TYPE("VK4WM", TYPE_VK4) TYPE("VK8", TYPE_VK8) TYPE("VK8WM", TYPE_VK8) TYPE("VK16", TYPE_VK16) TYPE("VK16WM", TYPE_VK16) + TYPE("VK32", TYPE_VK32) + TYPE("VK32WM", TYPE_VK32) + TYPE("VK64", TYPE_VK64) + TYPE("VK64WM", TYPE_VK64) TYPE("GR16_NOAX", TYPE_Rv) TYPE("GR32_NOAX", TYPE_Rv) TYPE("GR64_NOAX", TYPE_R64) @@ -1289,10 +1003,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 +1015,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 +1037,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 +1056,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 +1084,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 +1108,32 @@ OperandEncoding RecognizableInstr::vvvvRegisterEncodingFromString ENCODING("VR128X", ENCODING_VVVV) ENCODING("VR256X", ENCODING_VVVV) ENCODING("VR512", ENCODING_VVVV) + ENCODING("VK1", ENCODING_VVVV) + ENCODING("VK2", ENCODING_VVVV) + ENCODING("VK4", 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("VK2WM", ENCODING_WRITEMASK) + ENCODING("VK4WM", ENCODING_WRITEMASK) ENCODING("VK8WM", ENCODING_WRITEMASK) ENCODING("VK16WM", ENCODING_WRITEMASK) + ENCODING("VK32WM", ENCODING_WRITEMASK) + ENCODING("VK64WM", 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 +1167,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 +1192,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 4d4686e07390..4bc52ebd849e 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,12 @@ 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; + // The CD8_Scale field from the record + uint8_t CD8_Scale; // Whether the instruction has the predicate "In64BitMode" bool Is64Bit; // Whether the instruction has the predicate "In32BitMode" @@ -89,12 +89,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 +108,56 @@ 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); + + /// \brief Adjust the encoding type for an operand based on the instruction. + void adjustOperandEncoding(OperandEncoding &encoding); + /// 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 +183,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 +201,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/TableGen/module.modulemap b/utils/TableGen/module.modulemap new file mode 100644 index 000000000000..8871bbfd4a2f --- /dev/null +++ b/utils/TableGen/module.modulemap @@ -0,0 +1,4 @@ +module TableGen { + umbrella "." + module * { export * } +} diff --git a/utils/buildit/build_llvm b/utils/buildit/build_llvm index 9e9321601cbf..bc609e909a92 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 8de076a8803b..2a955e66679f 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/emacs/tablegen-mode.el b/utils/emacs/tablegen-mode.el index e83a34ca1816..c0ae75100bfb 100644 --- a/utils/emacs/tablegen-mode.el +++ b/utils/emacs/tablegen-mode.el @@ -112,6 +112,7 @@ (set-syntax-table tablegen-mode-syntax-table) (make-local-variable 'comment-start) (setq comment-start "//") + (setq indent-tabs-mode nil) (run-hooks 'tablegen-mode-hook)) ; Finally, this permits the user to ; customize the mode with a hook. diff --git a/utils/kate/llvm.xml b/utils/kate/llvm.xml index dfacfb532004..5ba46ee46aca 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 6491a02dd135..7a732b384d66 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 000000000000..8cf484047596 --- /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/TODO b/utils/lit/TODO index c1a60c6f4f09..90da327be9a2 100644 --- a/utils/lit/TODO +++ b/utils/lit/TODO @@ -156,8 +156,6 @@ Miscellaneous * Move temp directory name into local test config. -* Add --show-unsupported, don't show by default? - * Support valgrind in all configs, and LLVM style valgrind. * Support a timeout / ulimit. diff --git a/utils/lit/lit/Test.py b/utils/lit/lit/Test.py index b4988f530dbb..e51bf1297762 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 4a34b77e175b..eb890674a74d 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 3967fdd020a0..46fa82dcdf1c 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/discovery.py b/utils/lit/lit/discovery.py index c3c0f283b558..876d4f31e950 100644 --- a/utils/lit/lit/discovery.py +++ b/utils/lit/lit/discovery.py @@ -200,9 +200,7 @@ def find_tests_for_inputs(lit_config, inputs): # Expand '@...' form in inputs. actual_inputs = [] for input in inputs: - if os.path.exists(input) or not input.startswith('@'): - actual_inputs.append(input) - else: + if input.startswith('@'): f = open(input[1:]) try: for ln in f: @@ -211,6 +209,8 @@ def find_tests_for_inputs(lit_config, inputs): actual_inputs.append(ln) finally: f.close() + else: + actual_inputs.append(input) # Load the tests from the inputs. tests = [] diff --git a/utils/lit/lit/formats/googletest.py b/utils/lit/lit/formats/googletest.py index b77e184d2f6d..3d14b729ed07 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 6f672a01eb3d..1f62e3563e80 100755 --- a/utils/lit/lit/main.py +++ b/utils/lit/lit/main.py @@ -34,12 +34,18 @@ 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()) - if not test.result.code.isFailure and \ - (self.opts.quiet or self.opts.succinct): + shouldShow = test.result.code.isFailure or \ + (self.opts.show_unsupported and test.result.code.name == 'UNSUPPORTED') or \ + (not self.opts.quiet and not self.opts.succinct) + if not shouldShow: return if self.progressBar: @@ -108,6 +114,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 +138,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) @@ -146,6 +170,9 @@ def main(builtinParameters = {}): group.add_option("", "--no-progress-bar", dest="useProgressBar", help="Do not use curses based progress bar", action="store_false", default=True) + group.add_option("", "--show-unsupported", dest="show_unsupported", + help="Show unsupported tests", + action="store_true", default=False) parser.add_option_group(group) group = OptionGroup(parser, "Test Execution") @@ -179,6 +206,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 +236,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 +327,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/lit/util.py b/utils/lit/lit/util.py index 2b1010c1870c..72a8b4848e08 100644 --- a/utils/lit/lit/util.py +++ b/utils/lit/lit/util.py @@ -167,3 +167,20 @@ def executeCommand(command, cwd=None, env=None): err = str(err) return out, err, exitCode + +def usePlatformSdkOnDarwin(config, lit_config): + # On Darwin, support relocatable SDKs by providing Clang with a + # default system root path. + if 'darwin' in config.target_triple: + try: + cmd = subprocess.Popen(['xcrun', '--show-sdk-path'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = cmd.communicate() + out = out.strip() + res = cmd.wait() + except OSError: + res = -1 + if res == 0 and out: + sdk_path = out + lit_config.note('using SDKROOT: %r' % sdk_path) + config.environment['SDKROOT'] = sdk_path diff --git a/utils/lit/utils/check-coverage b/utils/lit/utils/check-coverage index bb3d17e75794..128e827f22dc 100755 --- a/utils/lit/utils/check-coverage +++ b/utils/lit/utils/check-coverage @@ -9,13 +9,13 @@ if [ ! -f setup.py ] || [ ! -d lit ]; then fi # Parse command line arguments. -if [ "$1" == "--generate-html" ]; then +if [ "$1" = "--generate-html" ]; then GENERATE_HTML=1 shift fi # If invoked with no arguments, run all the tests. -if [ $# == "0" ]; then +if [ $# = "0" ]; then set -- "tests" fi diff --git a/utils/lit/utils/check-sdist b/utils/lit/utils/check-sdist index 6186446aba1f..f03266a16888 100755 --- a/utils/lit/utils/check-sdist +++ b/utils/lit/utils/check-sdist @@ -1,6 +1,6 @@ #!/bin/sh -if [ $# == 1 ]; then +if [ $# = 1 ]; then cd $1 fi @@ -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/lldbDataFormatters.py b/utils/lldbDataFormatters.py index 1baf398aa533..352448d535cd 100644 --- a/utils/lldbDataFormatters.py +++ b/utils/lldbDataFormatters.py @@ -1,10 +1,18 @@ """ -Load into LLDB with: -script import lldbDataFormatters -type synthetic add -x "^llvm::SmallVectorImpl<.+>$" -l lldbDataFormatters.SmallVectorSynthProvider -type synthetic add -x "^llvm::SmallVector<.+,.+>$" -l lldbDataFormatters.SmallVectorSynthProvider +LLDB Formatters for LLVM data types. + +Load into LLDB with 'command script import /path/to/lldbDataFormatters.py' """ +def __lldb_init_module(debugger, internal_dict): + debugger.HandleCommand('type category define -e llvm -l c++') + debugger.HandleCommand('type synthetic add -w llvm ' + '-l lldbDataFormatters.SmallVectorSynthProvider ' + '-x "^llvm::SmallVectorImpl<.+>$"') + debugger.HandleCommand('type synthetic add -w llvm ' + '-l lldbDataFormatters.SmallVectorSynthProvider ' + '-x "^llvm::SmallVector<.+,.+>$"') + # Pretty printer for llvm::SmallVector/llvm::SmallVectorImpl class SmallVectorSynthProvider: def __init__(self, valobj, dict): diff --git a/utils/llvm-build/llvmbuild/componentinfo.py b/utils/llvm-build/llvmbuild/componentinfo.py index eda3a48811d6..b384acd190ff 100644 --- a/utils/llvm-build/llvmbuild/componentinfo.py +++ b/utils/llvm-build/llvmbuild/componentinfo.py @@ -9,7 +9,7 @@ except: import ConfigParser as configparser import sys -from llvmbuild.util import * +from llvmbuild.util import fatal, warning class ParseError(Exception): pass diff --git a/utils/llvm-build/llvmbuild/main.py b/utils/llvm-build/llvmbuild/main.py index eacefdf60bfc..37aa5d84ceeb 100644 --- a/utils/llvm-build/llvmbuild/main.py +++ b/utils/llvm-build/llvmbuild/main.py @@ -5,7 +5,7 @@ import sys import llvmbuild.componentinfo as componentinfo import llvmbuild.configutil as configutil -from llvmbuild.util import * +from llvmbuild.util import fatal, note ### @@ -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 @@ -680,7 +719,9 @@ def add_magic_target_components(parser, project, opts): enable_targets = available_targets.values() else: # We support both space separated and semi-colon separated lists. - if ' ' in opts.enable_targets: + if opts.enable_targets == '': + enable_target_names = [] + elif ' ' in opts.enable_targets: enable_target_names = opts.enable_targets.split() else: enable_target_names = opts.enable_targets.split(';') @@ -780,6 +821,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 +906,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-compilers-check b/utils/llvm-compilers-check index 3173027759b7..4db8426ace88 100755 --- a/utils/llvm-compilers-check +++ b/utils/llvm-compilers-check @@ -149,6 +149,10 @@ def add_options(parser): help=("Do not do installs")) parser.add_option("--keep-going", default=False, action="store_true", help=("Keep going after failures")) + parser.add_option("--no-flavor-prefix", default=False, action="store_true", + help=("Do not append the build flavor to the install path")) + parser.add_option("--enable-werror", default=False, action="store_true", + help=("Build with -Werror")) return def check_options(parser, options, valid_builds): @@ -346,7 +350,9 @@ class Builder(threading.Thread): ssabbrev = get_short_abbrevs([ab for ab in self.source_abbrev.values()]) prefix = "[" + ssabbrev[self.source_abbrev[source]] + "-" + self.build_abbrev[build] + "]" - self.install_prefix += "/" + self.source_abbrev[source] + "/" + build + if (not self.options.no_flavor_prefix): + self.install_prefix += "/" + self.source_abbrev[source] + "/" + build + build_suffix += "/" + self.source_abbrev[source] + "/" + build self.logger = logging.getLogger(prefix) @@ -361,16 +367,13 @@ class Builder(threading.Thread): configure_flags = dict( llvm=dict(debug=["--prefix=" + self.install_prefix, - "--enable-werror", "--enable-assertions", "--disable-optimized", "--with-gcc-toolchain=" + cxxroot], release=["--prefix=" + self.install_prefix, - "--enable-werror", "--enable-optimized", "--with-gcc-toolchain=" + cxxroot], paranoid=["--prefix=" + self.install_prefix, - "--enable-werror", "--enable-assertions", "--enable-expensive-checks", "--disable-optimized", @@ -379,6 +382,11 @@ class Builder(threading.Thread): release=[], paranoid=[])) + if (self.options.enable_werror): + configure_flags["llvm"]["debug"].append("--enable-werror") + configure_flags["llvm"]["release"].append("--enable-werror") + configure_flags["llvm"]["paranoid"].append("--enable-werror") + configure_env = dict( llvm=dict(debug=dict(CC=self.cc, CXX=self.cxx), @@ -530,10 +538,6 @@ class Builder(threading.Thread): self.logger.info("[" + prefix + "] Configure failed, no configure script " + conf) return -1 - if not os.path.exists(mf): - self.logger.info("[" + prefix + "] Configure failed, no makefile " + mf) - return -1 - if os.path.exists(conf) and os.path.exists(mf): confstat = os.stat(conf) makestat = os.stat(mf) diff --git a/utils/llvm-lit/CMakeLists.txt b/utils/llvm-lit/CMakeLists.txt index b535eaecde7d..4b10354cfdea 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 77021bbc2436..ce1cac9c32e9 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 87878d5638c6..fc962021d737 100644 --- 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, 'tools', '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 91a557cc161d..000000000000 --- 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 d65f075076cf..92a4053173d6 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 6b4ef83c67e2..6c410a40ecbd 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,37 +104,29 @@ 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>
- </Expand>
- </Type>
-
- <Type Name="llvm::OwningPtr<*>">
- <DisplayString Condition="Ptr == 0">empty</DisplayString>
- <DisplayString Condition="Ptr != 0">OwningPtr {*Ptr}</DisplayString>
- <Expand>
- <Item Condition="Ptr != 0" Name="[ptr]">Ptr</Item>
+ <ExpandedItem Condition="Obj != 0">Obj</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 +135,22 @@ or create a symbolic link so it updates automatically. </Type>
<Type Name="llvm::StringMap<*,*>">
- <DisplayString>{{ NumBuckets={NumBuckets}, ItemSize={ItemSize} }}</DisplayString>
+ <DisplayString>{{ size={NumItems}, buckets={NumBuckets} }}</DisplayString>
<Expand>
- <Item Name="[NumBuckets]">NumBuckets</Item>
- <Item Name="[ItemSize]">ItemSize</Item>
- <IndexListItems>
+ <Item Name="[size]">NumItems</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 +158,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 5ff14d6692d4..4a92348ba0f9 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 f37f166c6c7b..26b7450d48b0 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/not/not.cpp b/utils/not/not.cpp index ebd16189c9bd..a5c7183bd2c9 100644 --- a/utils/not/not.cpp +++ b/utils/not/not.cpp @@ -30,7 +30,16 @@ int main(int argc, const char **argv) { std::string Program = sys::FindProgramByName(argv[0]); std::string ErrMsg; - int Result = sys::ExecuteAndWait(Program, argv, 0, 0, 0, 0, &ErrMsg); + int Result = sys::ExecuteAndWait(Program, argv, nullptr, nullptr, 0, 0, + &ErrMsg); +#ifdef _WIN32 + // Handle abort() in msvcrt -- It has exit code as 3. abort(), aka + // unreachable, should be recognized as a crash. However, some binaries use + // exit code 3 on non-crash failure paths, so only do this if we expect a + // crash. + if (ExpectCrash && Result == 3) + Result = -3; +#endif if (Result < 0) { errs() << "Error: " << ErrMsg << "\n"; if (ExpectCrash) diff --git a/utils/release/test-release.sh b/utils/release/test-release.sh index 90c5f1ab2d08..83d3e52dc934 100755 --- a/utils/release/test-release.sh +++ b/utils/release/test-release.sh @@ -26,7 +26,6 @@ Base_url="http://llvm.org/svn/llvm-project" Release="" Release_no_dot="" RC="" -DOT="" Triple="" use_gzip="no" do_checkout="yes" @@ -46,7 +45,6 @@ function usage() { echo "" echo " -release X.Y The release number to test." echo " -rc NUM The pre-release candidate number." - echo " -dot NUM The dot release to test e.g. X.Y.DOT_NUM [default: 0]" echo " -final The final release candidate." echo " -triple TRIPLE The target triple for this machine." echo " -j NUM Number of compile jobs to run. [default: 3]" @@ -69,7 +67,7 @@ while [ $# -gt 0 ]; do -release | --release ) shift Release="$1" - Release_no_dot="`echo $1 | sed -e 's,\.,,'`" + Release_no_dot="`echo $1 | sed -e 's,\.,,g'`" ;; -rc | --rc | -RC | --RC ) shift @@ -78,13 +76,6 @@ while [ $# -gt 0 ]; do -final | --final ) RC=final ;; - -dot | --dot ) - shift - DOT="$1" - if [ $DOT -eq 0 ]; then - DOT="" - fi - ;; -triple | --triple ) shift Triple="$1" @@ -146,10 +137,6 @@ while [ $# -gt 0 ]; do shift done -if [ -n "$DOT" ]; then - Release="$Release.$DOT" -fi - # Check required arguments. if [ -z "$Release" ]; then echo "error: no release number specified" @@ -230,30 +217,13 @@ if [ `uname -s` != "Darwin" ]; then check_program_exists 'objdump' fi -function get_svn_tag() { - case $1 in - # llvm and clang are the only projects currently doing dot releases. - llvm | cfe) - if [ -z $DOT ]; then - SvnTag="$RC" - else - SvnTag="dot$DOT-$RC" - fi - ;; - *) - SvnTag="$RC" - ;; - esac -} - # Make sure that the URLs are valid. function check_valid_urls() { for proj in $projects ; do echo "# Validating $proj SVN URL" - get_svn_tag "$proj" - if ! svn ls $Base_url/$proj/tags/RELEASE_$Release_no_dot/$SvnTag > /dev/null 2>&1 ; then - echo "llvm $Release release candidate $RC doesn't exist!" + if ! svn ls $Base_url/$proj/tags/RELEASE_$Release_no_dot/$RC > /dev/null 2>&1 ; then + echo "$proj $Release release candidate $RC doesn't exist!" exit 1 fi done @@ -264,9 +234,8 @@ function export_sources() { check_valid_urls for proj in $projects ; do - echo "# Exporting $proj $Release-RC$RC sources" - get_svn_tag "$proj" - if ! svn export -q $Base_url/$proj/tags/RELEASE_$Release_no_dot/$SvnTag $proj.src ; then + 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 fi diff --git a/utils/test_debuginfo.pl b/utils/test_debuginfo.pl index a6b6137c1cd2..aaf90d95468c 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 fd1a048d832b..b6d2d6d9e0e9 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 000000000000..65ef97b02816 --- /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 1a6f0f59f1d7..16bfffd8d5e5 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 fe1e83b274bc..6ded1b124b49 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 32fd9c65bfea..f5bfd4e1d2ee 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 c94ebec73736..f5447a096850 100644 --- a/utils/vim/llvm.vim +++ b/utils/vim/llvm.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: llvm " Maintainer: The LLVM team, http://llvm.org/ -" Version: $Revision: 194760 $ +" Version: $Revision: 203866 $ if version < 600 syntax clear @@ -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 c838819ebe4f..eaa232f84af9 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 f3356055276b..e88ce5daeba7 100644 --- a/utils/yaml-bench/YAMLBench.cpp +++ b/utils/yaml-bench/YAMLBench.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This program executes the YAMLParser on differntly sized YAML texts and +// This program executes the YAMLParser on differently sized YAML texts and // outputs the run time. // //===----------------------------------------------------------------------===// @@ -21,7 +21,7 @@ #include "llvm/Support/Timer.h" #include "llvm/Support/YAMLParser.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/system_error.h" +#include <system_error> using namespace llvm; @@ -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,9 +188,11 @@ 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; - if (MemoryBuffer::getFileOrSTDIN(Input, Buf)) + ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr = + MemoryBuffer::getFileOrSTDIN(Input); + if (!BufOrErr) return 1; + std::unique_ptr<MemoryBuffer> Buf = std::move(BufOrErr.get()); llvm::SourceMgr sm; if (DumpTokens) { |