Update SwiftShader to April code dump.
April code dump from Transgaming. Adds new shader compiler.
diff --git a/src/LLVM/utils/DSAextract.py b/src/LLVM/utils/DSAextract.py
index 134e945..89dece1 100644
--- a/src/LLVM/utils/DSAextract.py
+++ b/src/LLVM/utils/DSAextract.py
@@ -58,7 +58,7 @@
#read the file one line at a time
buffer = input.readline()
while buffer != '':
- #filter out the unecessary checks on all the edge lines
+ #filter out the unnecessary checks on all the edge lines
if not arrowexp.search(buffer):
#check to see if this is a node we are looking for
for regexp in regexp_list:
diff --git a/src/LLVM/utils/FileCheck/FileCheck.cpp b/src/LLVM/utils/FileCheck/FileCheck.cpp
index e7cd713..f225594 100644
--- a/src/LLVM/utils/FileCheck/FileCheck.cpp
+++ b/src/LLVM/utils/FileCheck/FileCheck.cpp
@@ -16,13 +16,15 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/System/Signals.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/system_error.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
#include <algorithm>
@@ -49,32 +51,36 @@
class Pattern {
SMLoc PatternLoc;
-
+
+ /// MatchEOF - When set, this pattern only matches the end of file. This is
+ /// used for trailing CHECK-NOTs.
+ bool MatchEOF;
+
/// FixedStr - If non-empty, this pattern is a fixed string match with the
/// specified fixed string.
StringRef FixedStr;
-
+
/// RegEx - If non-empty, this is a regex pattern.
std::string RegExStr;
-
+
/// VariableUses - Entries in this vector map to uses of a variable in the
/// pattern, e.g. "foo[[bar]]baz". In this case, the RegExStr will contain
/// "foobaz" and we'll get an entry in this vector that tells us to insert the
/// value of bar at offset 3.
std::vector<std::pair<StringRef, unsigned> > VariableUses;
-
+
/// VariableDefs - Entries in this vector map to definitions of a variable in
/// the pattern, e.g. "foo[[bar:.*]]baz". In this case, the RegExStr will
/// contain "foo(.*)baz" and VariableDefs will contain the pair "bar",1. The
/// index indicates what parenthesized value captures the variable value.
std::vector<std::pair<StringRef, unsigned> > VariableDefs;
-
+
public:
-
- Pattern() { }
-
+
+ Pattern(bool matchEOF = false) : MatchEOF(matchEOF) { }
+
bool ParsePattern(StringRef PatternStr, SourceMgr &SM);
-
+
/// Match - Match the pattern string against the input buffer Buffer. This
/// returns the position that is matched or npos if there is no match. If
/// there is a match, the size of the matched string is returned in MatchLen.
@@ -103,19 +109,19 @@
bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM) {
PatternLoc = SMLoc::getFromPointer(PatternStr.data());
-
+
// Ignore trailing whitespace.
while (!PatternStr.empty() &&
(PatternStr.back() == ' ' || PatternStr.back() == '\t'))
PatternStr = PatternStr.substr(0, PatternStr.size()-1);
-
+
// Check that there is something on the line.
if (PatternStr.empty()) {
SM.PrintMessage(PatternLoc, "found empty check string with prefix '" +
CheckPrefix+":'", "error");
return true;
}
-
+
// Check to see if this is a fixed string, or if it has regex pieces.
if (PatternStr.size() < 2 ||
(PatternStr.find("{{") == StringRef::npos &&
@@ -123,39 +129,46 @@
FixedStr = PatternStr;
return false;
}
-
+
// Paren value #0 is for the fully matched string. Any new parenthesized
- // values add from their.
+ // values add from there.
unsigned CurParen = 1;
-
+
// Otherwise, there is at least one regex piece. Build up the regex pattern
// by escaping scary characters in fixed strings, building up one big regex.
while (!PatternStr.empty()) {
// RegEx matches.
- if (PatternStr.size() >= 2 &&
- PatternStr[0] == '{' && PatternStr[1] == '{') {
-
+ if (PatternStr.startswith("{{")) {
+
// Otherwise, this is the start of a regex match. Scan for the }}.
size_t End = PatternStr.find("}}");
if (End == StringRef::npos) {
SM.PrintMessage(SMLoc::getFromPointer(PatternStr.data()),
- "found start of regex string with no end '}}'", "error");
+ "found start of regex string with no end '}}'","error");
return true;
}
-
+
+ // Enclose {{}} patterns in parens just like [[]] even though we're not
+ // capturing the result for any purpose. This is required in case the
+ // expression contains an alternation like: CHECK: abc{{x|z}}def. We
+ // want this to turn into: "abc(x|z)def" not "abcx|zdef".
+ RegExStr += '(';
+ ++CurParen;
+
if (AddRegExToRegEx(PatternStr.substr(2, End-2), CurParen, SM))
return true;
+ RegExStr += ')';
+
PatternStr = PatternStr.substr(End+2);
continue;
}
-
+
// Named RegEx matches. These are of two forms: [[foo:.*]] which matches .*
// (or some other regex) and assigns it to the FileCheck variable 'foo'. The
// second form is [[foo]] which is a reference to foo. The variable name
// itself must be of the form "[a-zA-Z_][0-9a-zA-Z_]*", otherwise we reject
// it. This is to catch some common errors.
- if (PatternStr.size() >= 2 &&
- PatternStr[0] == '[' && PatternStr[1] == '[') {
+ if (PatternStr.startswith("[[")) {
// Verify that it is terminated properly.
size_t End = PatternStr.find("]]");
if (End == StringRef::npos) {
@@ -163,14 +176,14 @@
"invalid named regex reference, no ]] found", "error");
return true;
}
-
+
StringRef MatchStr = PatternStr.substr(2, End-2);
PatternStr = PatternStr.substr(End+2);
-
+
// Get the regex name (e.g. "foo").
size_t NameEnd = MatchStr.find(':');
StringRef Name = MatchStr.substr(0, NameEnd);
-
+
if (Name.empty()) {
SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
"invalid name in named regex: empty name", "error");
@@ -179,39 +192,36 @@
// Verify that the name is well formed.
for (unsigned i = 0, e = Name.size(); i != e; ++i)
- if (Name[i] != '_' &&
- (Name[i] < 'a' || Name[i] > 'z') &&
- (Name[i] < 'A' || Name[i] > 'Z') &&
- (Name[i] < '0' || Name[i] > '9')) {
+ if (Name[i] != '_' && !isalnum(Name[i])) {
SM.PrintMessage(SMLoc::getFromPointer(Name.data()+i),
"invalid name in named regex", "error");
return true;
}
-
+
// Name can't start with a digit.
if (isdigit(Name[0])) {
SM.PrintMessage(SMLoc::getFromPointer(Name.data()),
"invalid name in named regex", "error");
return true;
}
-
+
// Handle [[foo]].
if (NameEnd == StringRef::npos) {
VariableUses.push_back(std::make_pair(Name, RegExStr.size()));
continue;
}
-
+
// Handle [[foo:.*]].
VariableDefs.push_back(std::make_pair(Name, CurParen));
RegExStr += '(';
++CurParen;
-
+
if (AddRegExToRegEx(MatchStr.substr(NameEnd+1), CurParen, SM))
return true;
RegExStr += ')';
}
-
+
// Handle fixed string matches.
// Find the end, which is the start of the next regex.
size_t FixedMatchEnd = PatternStr.find("{{");
@@ -260,7 +270,7 @@
"invalid regex: " + Error, "error");
return true;
}
-
+
RegExStr += RegexStr.str();
CurParen += R.getNumMatches();
return false;
@@ -271,6 +281,12 @@
/// there is a match, the size of the matched string is returned in MatchLen.
size_t Pattern::Match(StringRef Buffer, size_t &MatchLen,
StringMap<StringRef> &VariableTable) const {
+ // If this is the EOF pattern, match it immediately.
+ if (MatchEOF) {
+ MatchLen = 0;
+ return Buffer.size();
+ }
+
// If this is a fixed string pattern, just match it now.
if (!FixedStr.empty()) {
MatchLen = FixedStr.size();
@@ -278,14 +294,14 @@
}
// Regex match.
-
+
// If there are variable uses, we need to create a temporary string with the
// actual value.
StringRef RegExToMatch = RegExStr;
std::string TmpStr;
if (!VariableUses.empty()) {
TmpStr = RegExStr;
-
+
unsigned InsertOffset = 0;
for (unsigned i = 0, e = VariableUses.size(); i != e; ++i) {
StringMap<StringRef>::iterator it =
@@ -297,33 +313,33 @@
// Look up the value and escape it so that we can plop it into the regex.
std::string Value;
AddFixedStringToRegEx(it->second, Value);
-
+
// Plop it into the regex at the adjusted offset.
TmpStr.insert(TmpStr.begin()+VariableUses[i].second+InsertOffset,
Value.begin(), Value.end());
InsertOffset += Value.size();
}
-
+
// Match the newly constructed regex.
RegExToMatch = TmpStr;
}
-
-
+
+
SmallVector<StringRef, 4> MatchInfo;
if (!Regex(RegExToMatch, Regex::Newline).match(Buffer, &MatchInfo))
return StringRef::npos;
-
+
// Successful regex match.
assert(!MatchInfo.empty() && "Didn't get any match");
StringRef FullMatch = MatchInfo[0];
-
+
// If this defines any variables, remember their values.
for (unsigned i = 0, e = VariableDefs.size(); i != e; ++i) {
assert(VariableDefs[i].second < MatchInfo.size() &&
"Internal paren error");
VariableTable[VariableDefs[i].first] = MatchInfo[VariableDefs[i].second];
}
-
+
MatchLen = FullMatch.size();
return FullMatch.data()-Buffer.data();
}
@@ -421,19 +437,19 @@
struct CheckString {
/// Pat - The pattern to match.
Pattern Pat;
-
+
/// Loc - The location in the match file that the check string was specified.
SMLoc Loc;
-
+
/// IsCheckNext - This is true if this is a CHECK-NEXT: directive (as opposed
/// to a CHECK: directive.
bool IsCheckNext;
-
+
/// NotStrings - These are all of the strings that are disallowed from
/// occurring between this match string and the previous one (or start of
/// file).
std::vector<std::pair<SMLoc, Pattern> > NotStrings;
-
+
CheckString(const Pattern &P, SMLoc L, bool isCheckNext)
: Pat(P), Loc(L), IsCheckNext(isCheckNext) {}
};
@@ -443,26 +459,31 @@
static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB) {
SmallString<128> NewFile;
NewFile.reserve(MB->getBufferSize());
-
+
for (const char *Ptr = MB->getBufferStart(), *End = MB->getBufferEnd();
Ptr != End; ++Ptr) {
+ // Eliminate trailing dosish \r.
+ if (Ptr <= End - 2 && Ptr[0] == '\r' && Ptr[1] == '\n') {
+ continue;
+ }
+
// If C is not a horizontal whitespace, skip it.
if (*Ptr != ' ' && *Ptr != '\t') {
NewFile.push_back(*Ptr);
continue;
}
-
+
// Otherwise, add one space and advance over neighboring space.
NewFile.push_back(' ');
while (Ptr+1 != End &&
(Ptr[1] == ' ' || Ptr[1] == '\t'))
++Ptr;
}
-
+
// Free the old buffer and return a new one.
MemoryBuffer *MB2 =
MemoryBuffer::getMemBufferCopy(NewFile.str(), MB->getBufferIdentifier());
-
+
delete MB;
return MB2;
}
@@ -473,41 +494,41 @@
static bool ReadCheckFile(SourceMgr &SM,
std::vector<CheckString> &CheckStrings) {
// Open the check file, and tell SourceMgr about it.
- std::string ErrorStr;
- MemoryBuffer *F =
- MemoryBuffer::getFileOrSTDIN(CheckFilename.c_str(), &ErrorStr);
- if (F == 0) {
- errs() << "Could not open check file '" << CheckFilename << "': "
- << ErrorStr << '\n';
+ OwningPtr<MemoryBuffer> File;
+ if (error_code ec =
+ MemoryBuffer::getFileOrSTDIN(CheckFilename.c_str(), File)) {
+ errs() << "Could not open check file '" << CheckFilename << "': "
+ << ec.message() << '\n';
return true;
}
-
+ MemoryBuffer *F = File.take();
+
// If we want to canonicalize whitespace, strip excess whitespace from the
// buffer containing the CHECK lines.
if (!NoCanonicalizeWhiteSpace)
F = CanonicalizeInputFile(F);
-
+
SM.AddNewSourceBuffer(F, SMLoc());
// Find all instances of CheckPrefix followed by : in the file.
StringRef Buffer = F->getBuffer();
std::vector<std::pair<SMLoc, Pattern> > NotMatches;
-
+
while (1) {
// See if Prefix occurs in the memory buffer.
Buffer = Buffer.substr(Buffer.find(CheckPrefix));
-
+
// If we didn't find a match, we're done.
if (Buffer.empty())
break;
-
+
const char *CheckPrefixStart = Buffer.data();
-
+
// When we find a check prefix, keep track of whether we find CHECK: or
// CHECK-NEXT:
bool IsCheckNext = false, IsCheckNot = false;
-
+
// Verify that the : is present after the prefix.
if (Buffer[CheckPrefix.size()] == ':') {
Buffer = Buffer.substr(CheckPrefix.size()+1);
@@ -523,11 +544,11 @@
Buffer = Buffer.substr(1);
continue;
}
-
+
// Okay, we found the prefix, yay. Remember the rest of the line, but
// ignore leading and trailing whitespace.
Buffer = Buffer.substr(Buffer.find_first_not_of(" \t"));
-
+
// Scan ahead to the end of line.
size_t EOL = Buffer.find_first_of("\n\r");
@@ -538,10 +559,10 @@
Pattern P;
if (P.ParsePattern(Buffer.substr(0, EOL), SM))
return true;
-
+
Buffer = Buffer.substr(EOL);
-
+
// Verify that CHECK-NEXT lines have at least one CHECK line before them.
if (IsCheckNext && CheckStrings.empty()) {
SM.PrintMessage(SMLoc::getFromPointer(CheckPrefixStart),
@@ -549,34 +570,36 @@
CheckPrefix+ ": line", "error");
return true;
}
-
+
// Handle CHECK-NOT.
if (IsCheckNot) {
NotMatches.push_back(std::make_pair(SMLoc::getFromPointer(Buffer.data()),
P));
continue;
}
-
-
+
+
// Okay, add the string we captured to the output vector and move on.
CheckStrings.push_back(CheckString(P,
PatternLoc,
IsCheckNext));
std::swap(NotMatches, CheckStrings.back().NotStrings);
}
-
+
+ // Add an EOF pattern for any trailing CHECK-NOTs.
+ if (!NotMatches.empty()) {
+ CheckStrings.push_back(CheckString(Pattern(true),
+ SMLoc::getFromPointer(Buffer.data()),
+ false));
+ std::swap(NotMatches, CheckStrings.back().NotStrings);
+ }
+
if (CheckStrings.empty()) {
errs() << "error: no check strings found with prefix '" << CheckPrefix
<< ":'\n";
return true;
}
-
- if (!NotMatches.empty()) {
- errs() << "error: '" << CheckPrefix
- << "-NOT:' not supported after last check line.\n";
- return true;
- }
-
+
return false;
}
@@ -586,11 +609,11 @@
// Otherwise, we have an error, emit an error message.
SM.PrintMessage(CheckStr.Loc, "expected string not found in input",
"error");
-
+
// Print the "scanning from here" line. If the current position is at the
// end of a line, advance to the start of the next line.
Buffer = Buffer.substr(Buffer.find_first_not_of(" \t\n\r"));
-
+
SM.PrintMessage(SMLoc::getFromPointer(Buffer.data()), "scanning from here",
"note");
@@ -606,9 +629,9 @@
// Scan for newline.
Range = Range.substr(Range.find_first_of("\n\r"));
if (Range.empty()) return NumNewLines;
-
+
++NumNewLines;
-
+
// Handle \n\r and \r\n as a single newline.
if (Range.size() > 1 &&
(Range[1] == '\n' || Range[1] == '\r') &&
@@ -624,48 +647,54 @@
cl::ParseCommandLineOptions(argc, argv);
SourceMgr SM;
-
+
// Read the expected strings from the check file.
std::vector<CheckString> CheckStrings;
if (ReadCheckFile(SM, CheckStrings))
return 2;
// Open the file to check and add it to SourceMgr.
- std::string ErrorStr;
- MemoryBuffer *F =
- MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), &ErrorStr);
- if (F == 0) {
- errs() << "Could not open input file '" << InputFilename << "': "
- << ErrorStr << '\n';
+ OwningPtr<MemoryBuffer> File;
+ if (error_code ec =
+ MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), File)) {
+ errs() << "Could not open input file '" << InputFilename << "': "
+ << ec.message() << '\n';
return true;
}
+ MemoryBuffer *F = File.take();
+
+ if (F->getBufferSize() == 0) {
+ errs() << "FileCheck error: '" << InputFilename << "' is empty.\n";
+ return 1;
+ }
// Remove duplicate spaces in the input file if requested.
if (!NoCanonicalizeWhiteSpace)
F = CanonicalizeInputFile(F);
-
+
SM.AddNewSourceBuffer(F, SMLoc());
-
+
/// VariableTable - This holds all the current filecheck variables.
StringMap<StringRef> VariableTable;
-
+
// Check that we have all of the expected strings, in order, in the input
// file.
StringRef Buffer = F->getBuffer();
-
+
const char *LastMatch = Buffer.data();
-
+
for (unsigned StrNo = 0, e = CheckStrings.size(); StrNo != e; ++StrNo) {
const CheckString &CheckStr = CheckStrings[StrNo];
-
+
StringRef SearchFrom = Buffer;
-
+
// Find StrNo in the file.
size_t MatchLen = 0;
- Buffer = Buffer.substr(CheckStr.Pat.Match(Buffer, MatchLen, VariableTable));
-
+ size_t MatchPos = CheckStr.Pat.Match(Buffer, MatchLen, VariableTable);
+ Buffer = Buffer.substr(MatchPos);
+
// If we didn't find a match, reject the input.
- if (Buffer.empty()) {
+ if (MatchPos == StringRef::npos) {
PrintCheckFailed(SM, CheckStr, SearchFrom, VariableTable);
return 1;
}
@@ -690,7 +719,7 @@
"previous match was here", "note");
return 1;
}
-
+
if (NumNewLines != 1) {
SM.PrintMessage(CheckStr.Loc,
CheckPrefix+
@@ -703,7 +732,7 @@
return 1;
}
}
-
+
// If this match had "not strings", verify that they don't exist in the
// skipped region.
for (unsigned ChunkNo = 0, e = CheckStr.NotStrings.size();
@@ -713,20 +742,20 @@
MatchLen,
VariableTable);
if (Pos == StringRef::npos) continue;
-
+
SM.PrintMessage(SMLoc::getFromPointer(LastMatch+Pos),
CheckPrefix+"-NOT: string occurred!", "error");
SM.PrintMessage(CheckStr.NotStrings[ChunkNo].first,
CheckPrefix+"-NOT: pattern specified here", "note");
return 1;
}
-
+
// Otherwise, everything is good. Step over the matched text and remember
// the position after the match as the end of the last match.
Buffer = Buffer.substr(MatchLen);
LastMatch = Buffer.data();
}
-
+
return 0;
}
diff --git a/src/LLVM/utils/FileCheck/FileCheck.vcxproj b/src/LLVM/utils/FileCheck/FileCheck.vcxproj
new file mode 100644
index 0000000..607fbb7
--- /dev/null
+++ b/src/LLVM/utils/FileCheck/FileCheck.vcxproj
@@ -0,0 +1,345 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGUID>{5798BA22-433B-478C-AE04-3A5B01F9EE02}</ProjectGUID>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>FileCheck</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\bin\Debug\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">FileCheck.dir\Debug\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">FileCheck</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</GenerateManifest>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\bin\Release\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">FileCheck.dir\Release\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">FileCheck</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</GenerateManifest>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">..\..\bin\MinSizeRel\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">FileCheck.dir\MinSizeRel\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">FileCheck</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">true</GenerateManifest>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">..\..\bin\RelWithDebInfo\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">FileCheck.dir\RelWithDebInfo\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">FileCheck</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">true</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">true</GenerateManifest>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 /EHs-c- -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\FileCheck;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>Disabled</Optimization>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>Debug</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/Debug/FileCheck.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\FileCheck;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileCheck;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalOptions> /machine:X86 /debug %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;..\..\lib\Debug\LLVMSupport.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/Debug/FileCheck.lib</ImportLibrary>
+ <LinkIncremental>true</LinkIncremental>
+ <ProgramDataBaseFileName>..\..\bin/Debug/FileCheck.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 /EHs-c- -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\FileCheck;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>MaxSpeed</Optimization>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>Release</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/Release/FileCheck.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\FileCheck;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileCheck;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalOptions> /machine:X86 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;..\..\lib\Release\LLVMSupport.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/Release/FileCheck.lib</ImportLibrary>
+ <ProgramDataBaseFileName>..\..\bin/Release/FileCheck.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 /EHs-c- -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\FileCheck;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>MinSpace</Optimization>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>MinSizeRel</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/MinSizeRel/FileCheck.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\FileCheck;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileCheck;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalOptions> /machine:X86 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;..\..\lib\MinSizeRel\LLVMSupport.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/MinSizeRel/FileCheck.lib</ImportLibrary>
+ <ProgramDataBaseFileName>..\..\bin/MinSizeRel/FileCheck.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 /EHs-c- -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\FileCheck;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>MaxSpeed</Optimization>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>RelWithDebInfo</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/RelWithDebInfo/FileCheck.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\FileCheck;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileCheck;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalOptions> /machine:X86 /debug %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;..\..\lib\RelWithDebInfo\LLVMSupport.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/RelWithDebInfo/FileCheck.lib</ImportLibrary>
+ <LinkIncremental>true</LinkIncremental>
+ <ProgramDataBaseFileName>..\..\bin/RelWithDebInfo/FileCheck.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\generate.stamp</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="FileCheck.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\lib/Support/LLVMSupport.vcxproj">
+ <Project>C688DD59-C6CB-4B33-B56F-A7D6F3761524</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\..\include/llvm/intrinsics_gen.vcxproj">
+ <Project>E9B87B46-1EB0-4D95-9049-41B148FBADCD</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/src/LLVM/utils/FileCheck/FileCheck.vcxproj.filters b/src/LLVM/utils/FileCheck/FileCheck.vcxproj.filters
new file mode 100644
index 0000000..11ec996
--- /dev/null
+++ b/src/LLVM/utils/FileCheck/FileCheck.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="FileCheck.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{1733179C-6FE4-462E-9EA5-4A29A1ACFE25}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
diff --git a/src/LLVM/utils/FileCheck/INSTALL.vcxproj b/src/LLVM/utils/FileCheck/INSTALL.vcxproj
new file mode 100644
index 0000000..f3e6a9d
--- /dev/null
+++ b/src/LLVM/utils/FileCheck/INSTALL.vcxproj
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGUID>{048BB775-7681-4EE1-AACF-5A067ACEEEA5}</ProjectGUID>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>INSTALL</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileCheck;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileCheck;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileCheck;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileCheck;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\INSTALL_force.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\generate.stamp</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\ALL_BUILD.vcxproj">
+ <Project>17AECBCF-B2AE-4524-9010-9A175A8F6BFE</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/src/LLVM/utils/FileCheck/INSTALL.vcxproj.filters b/src/LLVM/utils/FileCheck/INSTALL.vcxproj.filters
new file mode 100644
index 0000000..251dd1d
--- /dev/null
+++ b/src/LLVM/utils/FileCheck/INSTALL.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\INSTALL_force.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ <CustomBuild Include="CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{71794486-B3CB-4A48-93CC-DE95557E96E1}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
diff --git a/src/LLVM/utils/FileCheck/Makefile b/src/LLVM/utils/FileCheck/Makefile
index f1af5b6..268b7bc 100644
--- a/src/LLVM/utils/FileCheck/Makefile
+++ b/src/LLVM/utils/FileCheck/Makefile
@@ -1,15 +1,15 @@
##===- utils/FileCheck/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 = FileCheck
-USEDLIBS = LLVMSupport.a LLVMSystem.a
+USEDLIBS = LLVMSupport.a
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
diff --git a/src/LLVM/utils/FileCheck/PACKAGE.vcxproj b/src/LLVM/utils/FileCheck/PACKAGE.vcxproj
new file mode 100644
index 0000000..6964f51
--- /dev/null
+++ b/src/LLVM/utils/FileCheck/PACKAGE.vcxproj
@@ -0,0 +1,277 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGUID>{1B050569-3318-48D9-8BB0-4DE9EF58B202}</ProjectGUID>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>PACKAGE</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileCheck;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileCheck;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileCheck;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileCheck;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\PACKAGE_force.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\generate.stamp</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\ALL_BUILD.vcxproj">
+ <Project>17AECBCF-B2AE-4524-9010-9A175A8F6BFE</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/src/LLVM/utils/FileCheck/PACKAGE.vcxproj.filters b/src/LLVM/utils/FileCheck/PACKAGE.vcxproj.filters
new file mode 100644
index 0000000..a570359
--- /dev/null
+++ b/src/LLVM/utils/FileCheck/PACKAGE.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\PACKAGE_force.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ <CustomBuild Include="CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{71794486-B3CB-4A48-93CC-DE95557E96E1}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
diff --git a/src/LLVM/utils/FileUpdate/FileUpdate.cpp b/src/LLVM/utils/FileUpdate/FileUpdate.cpp
index 00c2091..3ea1e4f 100644
--- a/src/LLVM/utils/FileUpdate/FileUpdate.cpp
+++ b/src/LLVM/utils/FileUpdate/FileUpdate.cpp
@@ -15,9 +15,11 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/System/Signals.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/system_error.h"
using namespace llvm;
static cl::opt<bool>
@@ -36,52 +38,50 @@
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.
- std::string ErrorStr;
- MemoryBuffer *In =
- MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), &ErrorStr);
- if (In == 0) {
+ OwningPtr<MemoryBuffer> In;
+ if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFilename.c_str(), In)) {
errs() << argv[0] << ": error: Unable to get input '"
- << InputFilename << "': " << ErrorStr << '\n';
+ << InputFilename << "': " << ec.message() << '\n';
return 1;
}
// Get the output data.
- MemoryBuffer *Out = MemoryBuffer::getFile(OutputFilename.c_str(), &ErrorStr);
+ 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)
- outs() << argv[0] << ": Not updating '" << OutputFilename
+ errs() << argv[0] << ": Not updating '" << OutputFilename
<< "', contents match input.\n";
return 0;
}
- delete Out;
-
// Otherwise, overwrite the output.
if (!Quiet)
- outs() << argv[0] << ": Updating '" << OutputFilename
+ errs() << argv[0] << ": Updating '" << OutputFilename
<< "', contents changed.\n";
- raw_fd_ostream OutStream(OutputFilename.c_str(), ErrorStr,
- raw_fd_ostream::F_Binary);
+ std::string ErrorStr;
+ tool_output_file OutStream(OutputFilename.c_str(), ErrorStr,
+ raw_fd_ostream::F_Binary);
if (!ErrorStr.empty()) {
errs() << argv[0] << ": Unable to write output '"
<< OutputFilename << "': " << ErrorStr << '\n';
return 1;
}
- OutStream.write(In->getBufferStart(), In->getBufferSize());
- OutStream.close();
+ OutStream.os().write(In->getBufferStart(), In->getBufferSize());
- if (OutStream.has_error()) {
- errs() << argv[0] << ": Could not open output file '"
- << OutputFilename << "': " << ErrorStr << '\n';
- OutStream.clear_error();
- return 1;
- }
+ // Declare success.
+ OutStream.keep();
return 0;
}
diff --git a/src/LLVM/utils/FileUpdate/FileUpdate.vcxproj b/src/LLVM/utils/FileUpdate/FileUpdate.vcxproj
new file mode 100644
index 0000000..331e91a
--- /dev/null
+++ b/src/LLVM/utils/FileUpdate/FileUpdate.vcxproj
@@ -0,0 +1,345 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGUID>{607AD764-C640-4640-8312-610B6C5113B3}</ProjectGUID>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>FileUpdate</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\bin\Debug\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">FileUpdate.dir\Debug\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">FileUpdate</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</GenerateManifest>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\bin\Release\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">FileUpdate.dir\Release\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">FileUpdate</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</GenerateManifest>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">..\..\bin\MinSizeRel\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">FileUpdate.dir\MinSizeRel\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">FileUpdate</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">true</GenerateManifest>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">..\..\bin\RelWithDebInfo\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">FileUpdate.dir\RelWithDebInfo\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">FileUpdate</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">true</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">true</GenerateManifest>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 /EHs-c- -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\FileUpdate;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>Disabled</Optimization>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>Debug</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/Debug/FileUpdate.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\FileUpdate;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileUpdate;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalOptions> /machine:X86 /debug %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;..\..\lib\Debug\LLVMSupport.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/Debug/FileUpdate.lib</ImportLibrary>
+ <LinkIncremental>true</LinkIncremental>
+ <ProgramDataBaseFileName>..\..\bin/Debug/FileUpdate.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 /EHs-c- -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\FileUpdate;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>MaxSpeed</Optimization>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>Release</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/Release/FileUpdate.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\FileUpdate;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileUpdate;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalOptions> /machine:X86 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;..\..\lib\Release\LLVMSupport.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/Release/FileUpdate.lib</ImportLibrary>
+ <ProgramDataBaseFileName>..\..\bin/Release/FileUpdate.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 /EHs-c- -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\FileUpdate;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>MinSpace</Optimization>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>MinSizeRel</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/MinSizeRel/FileUpdate.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\FileUpdate;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileUpdate;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalOptions> /machine:X86 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;..\..\lib\MinSizeRel\LLVMSupport.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/MinSizeRel/FileUpdate.lib</ImportLibrary>
+ <ProgramDataBaseFileName>..\..\bin/MinSizeRel/FileUpdate.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 /EHs-c- -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\FileUpdate;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>MaxSpeed</Optimization>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>RelWithDebInfo</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/RelWithDebInfo/FileUpdate.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\FileUpdate;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileUpdate;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalOptions> /machine:X86 /debug %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;..\..\lib\RelWithDebInfo\LLVMSupport.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/RelWithDebInfo/FileUpdate.lib</ImportLibrary>
+ <LinkIncremental>true</LinkIncremental>
+ <ProgramDataBaseFileName>..\..\bin/RelWithDebInfo/FileUpdate.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\generate.stamp</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="FileUpdate.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\lib/Support/LLVMSupport.vcxproj">
+ <Project>C688DD59-C6CB-4B33-B56F-A7D6F3761524</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\..\include/llvm/intrinsics_gen.vcxproj">
+ <Project>E9B87B46-1EB0-4D95-9049-41B148FBADCD</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/src/LLVM/utils/FileUpdate/FileUpdate.vcxproj.filters b/src/LLVM/utils/FileUpdate/FileUpdate.vcxproj.filters
new file mode 100644
index 0000000..2922de4
--- /dev/null
+++ b/src/LLVM/utils/FileUpdate/FileUpdate.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="FileUpdate.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{1733179C-6FE4-462E-9EA5-4A29A1ACFE25}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
diff --git a/src/LLVM/utils/FileUpdate/INSTALL.vcxproj b/src/LLVM/utils/FileUpdate/INSTALL.vcxproj
new file mode 100644
index 0000000..4eb24d6
--- /dev/null
+++ b/src/LLVM/utils/FileUpdate/INSTALL.vcxproj
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGUID>{048BB775-7681-4EE1-AACF-5A067ACEEEA5}</ProjectGUID>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>INSTALL</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileUpdate;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileUpdate;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileUpdate;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileUpdate;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\INSTALL_force.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\generate.stamp</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\ALL_BUILD.vcxproj">
+ <Project>17AECBCF-B2AE-4524-9010-9A175A8F6BFE</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/src/LLVM/utils/FileUpdate/INSTALL.vcxproj.filters b/src/LLVM/utils/FileUpdate/INSTALL.vcxproj.filters
new file mode 100644
index 0000000..251dd1d
--- /dev/null
+++ b/src/LLVM/utils/FileUpdate/INSTALL.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\INSTALL_force.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ <CustomBuild Include="CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{71794486-B3CB-4A48-93CC-DE95557E96E1}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
diff --git a/src/LLVM/utils/FileUpdate/Makefile b/src/LLVM/utils/FileUpdate/Makefile
index 5b545c2..1e6c0a8 100644
--- a/src/LLVM/utils/FileUpdate/Makefile
+++ b/src/LLVM/utils/FileUpdate/Makefile
@@ -1,15 +1,15 @@
##===- 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 LLVMSystem.a
+USEDLIBS = LLVMSupport.a
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
diff --git a/src/LLVM/utils/FileUpdate/PACKAGE.vcxproj b/src/LLVM/utils/FileUpdate/PACKAGE.vcxproj
new file mode 100644
index 0000000..fd8449c
--- /dev/null
+++ b/src/LLVM/utils/FileUpdate/PACKAGE.vcxproj
@@ -0,0 +1,277 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGUID>{1B050569-3318-48D9-8BB0-4DE9EF58B202}</ProjectGUID>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>PACKAGE</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileUpdate;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileUpdate;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileUpdate;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\FileUpdate;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\PACKAGE_force.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\generate.stamp</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\ALL_BUILD.vcxproj">
+ <Project>17AECBCF-B2AE-4524-9010-9A175A8F6BFE</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/src/LLVM/utils/FileUpdate/PACKAGE.vcxproj.filters b/src/LLVM/utils/FileUpdate/PACKAGE.vcxproj.filters
new file mode 100644
index 0000000..a570359
--- /dev/null
+++ b/src/LLVM/utils/FileUpdate/PACKAGE.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\PACKAGE_force.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ <CustomBuild Include="CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{71794486-B3CB-4A48-93CC-DE95557E96E1}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
diff --git a/src/LLVM/utils/GenLibDeps.pl b/src/LLVM/utils/GenLibDeps.pl
index f1f7e72..0cd9e6a 100644
--- a/src/LLVM/utils/GenLibDeps.pl
+++ b/src/LLVM/utils/GenLibDeps.pl
@@ -107,7 +107,6 @@
$libpath =~ s/^TransformUtils/Transforms\/Utils/;
$libpath =~ s/^ipa/Analysis\/IPA/;
$libpath =~ s/^ipo/Transforms\/IPO/;
- $libpath =~ s/^pic16passes/Target\/PIC16\/PIC16Passes/;
$libpath = "lib/".$libpath."/";
open DEFS, "$nmPath -sg $Directory/$lib|";
while (<DEFS>) {
@@ -150,7 +149,6 @@
$libpath =~ s/^TransformUtils/Transforms\/Utils/;
$libpath =~ s/^ipa/Analysis\/IPA/;
$libpath =~ s/^ipo/Transforms\/IPO/;
- $libpath =~ s/^pic16passes/Target\/PIC16\/PIC16Passes/;
$libpath = "lib/".$libpath."/";
open UDEFS, "$nmPath -Aup $Directory/$lib|";
while (<UDEFS>) {
@@ -204,7 +202,7 @@
print "$lib:";
if ($WHY) { print "\n"; }
} else {
- print " <dt><b>$lib</b</dt><dd><ul>\n";
+ print " <dt><b>$lib</b></dt><dd><ul>\n";
}
open UNDEFS,
"$nmPath -u $Directory/$lib | sed -e 's/^[ 0]* U //' | sort | uniq |";
diff --git a/src/LLVM/utils/GetRepositoryPath b/src/LLVM/utils/GetRepositoryPath
new file mode 100644
index 0000000..326231c
--- /dev/null
+++ b/src/LLVM/utils/GetRepositoryPath
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+usage() {
+ echo "usage: $0 <source root>"
+ echo " Prints the source control repository path of the given source"
+ echo " directory, the exact format of the revision string depends on the"
+ echo " source control system. If the source control system isn't known,"
+ echo " the output is empty and the exit code is 1."
+ exit 1
+}
+
+if [ $# != 1 ] || [ ! -d $1 ]; then
+ usage;
+fi
+
+cd $1
+if [ -d .svn ]; then
+ svn info | grep 'URL:' | cut -d: -f2-
+elif [ -d .git/svn ]; then
+ git svn info | grep 'URL:' | cut -d: -f2-
+elif [ -d .git ]; then
+ git remote -v | grep 'fetch' | awk '{ print $2 }'
+else
+ exit 1;
+fi
+
+exit 0
diff --git a/src/LLVM/utils/GetSourceVersion b/src/LLVM/utils/GetSourceVersion
index b25f2f9..cbed7da 100644
--- a/src/LLVM/utils/GetSourceVersion
+++ b/src/LLVM/utils/GetSourceVersion
@@ -1,12 +1,12 @@
#!/bin/sh
usage() {
- echo "usage: $0 <source root>"
- echo " Prints the source control revision of the given source directory,"
- echo " the exact format of the revision string depends on the source "
- echo " control system. If the source control system isn't known, the output"
- echo " is empty and the exit code is 1."
- exit 1
+ echo "usage: $0 <source root>"
+ echo " Prints the source control revision of the given source directory,"
+ echo " the exact format of the revision string depends on the source "
+ echo " control system. If the source control system isn't known, the output"
+ echo " is empty and the exit code is 1."
+ exit 1
}
if [ $# != 1 ] || [ ! -d $1 ]; then
@@ -15,13 +15,13 @@
cd $1
if [ -d .svn ]; then
- svnversion
+ svnversion | sed -e "s#\([0-9]*\)[A-Z]*#\1#"
elif [ -d .git/svn ]; then
- git svn info | grep 'Revision:' | cut -d: -f2-
+ git svn info | grep 'Revision:' | cut -d: -f2-
elif [ -d .git ]; then
- git log -1 --pretty=format:%H
+ git log -1 --pretty=format:%H
else
- exit 1;
+ exit 1;
fi
exit 0
diff --git a/src/LLVM/utils/KillTheDoctor/KillTheDoctor.cpp b/src/LLVM/utils/KillTheDoctor/KillTheDoctor.cpp
new file mode 100644
index 0000000..1ddae0b
--- /dev/null
+++ b/src/LLVM/utils/KillTheDoctor/KillTheDoctor.cpp
@@ -0,0 +1,596 @@
+//===- KillTheDoctor - Prevent Dr. Watson from stopping tests ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This program provides an extremely hacky way to stop Dr. Watson from starting
+// due to unhandled exceptions in child processes.
+//
+// This simply starts the program named in the first positional argument with
+// the arguments following it under a debugger. All this debugger does is catch
+// any unhandled exceptions thrown in the child process and close the program
+// (and hopefully tells someone about it).
+//
+// This also provides another really hacky method to prevent assert dialog boxes
+// from popping up. When --no-user32 is passed, if any process loads user32.dll,
+// we assume it is trying to call MessageBoxEx and terminate it. The proper way
+// to do this would be to actually set a break point, but there's quite a bit
+// of code involved to get the address of MessageBoxEx in the remote process's
+// address space due to Address space layout randomization (ASLR). This can be
+// added if it's ever actually needed.
+//
+// If the subprocess exits for any reason other than successful termination, -1
+// is returned. If the process exits normally the value it returned is returned.
+//
+// I hate Windows.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/type_traits.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/system_error.h"
+#include <algorithm>
+#include <cerrno>
+#include <cstdlib>
+#include <map>
+#include <string>
+#include <Windows.h>
+#include <WinError.h>
+#include <Dbghelp.h>
+#include <psapi.h>
+using namespace llvm;
+
+#undef max
+
+namespace {
+ cl::opt<std::string> ProgramToRun(cl::Positional,
+ cl::desc("<program to run>"));
+ cl::list<std::string> Argv(cl::ConsumeAfter,
+ cl::desc("<program arguments>..."));
+ cl::opt<bool> TraceExecution("x",
+ cl::desc("Print detailed output about what is being run to stderr."));
+ cl::opt<unsigned> Timeout("t", cl::init(0),
+ cl::desc("Set maximum runtime in seconds. Defaults to infinite."));
+ cl::opt<bool> NoUser32("no-user32",
+ cl::desc("Terminate process if it loads user32.dll."));
+
+ StringRef ToolName;
+
+ template <typename HandleType>
+ class ScopedHandle {
+ typedef typename HandleType::handle_type handle_type;
+
+ handle_type Handle;
+
+ public:
+ ScopedHandle()
+ : Handle(HandleType::GetInvalidHandle()) {}
+
+ explicit ScopedHandle(handle_type handle)
+ : Handle(handle) {}
+
+ ~ScopedHandle() {
+ HandleType::Destruct(Handle);
+ }
+
+ ScopedHandle& operator=(handle_type handle) {
+ // Cleanup current handle.
+ if (!HandleType::isValid(Handle))
+ HandleType::Destruct(Handle);
+ Handle = handle;
+ return *this;
+ }
+
+ operator bool() const {
+ return HandleType::isValid(Handle);
+ }
+
+ operator handle_type() {
+ return Handle;
+ }
+ };
+
+ // This implements the most common handle in the Windows API.
+ struct CommonHandle {
+ typedef HANDLE handle_type;
+
+ static handle_type GetInvalidHandle() {
+ return INVALID_HANDLE_VALUE;
+ }
+
+ static void Destruct(handle_type Handle) {
+ ::CloseHandle(Handle);
+ }
+
+ static bool isValid(handle_type Handle) {
+ return Handle != GetInvalidHandle();
+ }
+ };
+
+ struct FileMappingHandle {
+ typedef HANDLE handle_type;
+
+ static handle_type GetInvalidHandle() {
+ return NULL;
+ }
+
+ static void Destruct(handle_type Handle) {
+ ::CloseHandle(Handle);
+ }
+
+ static bool isValid(handle_type Handle) {
+ return Handle != GetInvalidHandle();
+ }
+ };
+
+ struct MappedViewOfFileHandle {
+ typedef LPVOID handle_type;
+
+ static handle_type GetInvalidHandle() {
+ return NULL;
+ }
+
+ static void Destruct(handle_type Handle) {
+ ::UnmapViewOfFile(Handle);
+ }
+
+ static bool isValid(handle_type Handle) {
+ return Handle != GetInvalidHandle();
+ }
+ };
+
+ struct ProcessHandle : CommonHandle {};
+ struct ThreadHandle : CommonHandle {};
+ struct TokenHandle : CommonHandle {};
+ struct FileHandle : CommonHandle {};
+
+ typedef ScopedHandle<FileMappingHandle> FileMappingScopedHandle;
+ typedef ScopedHandle<MappedViewOfFileHandle> MappedViewOfFileScopedHandle;
+ typedef ScopedHandle<ProcessHandle> ProcessScopedHandle;
+ typedef ScopedHandle<ThreadHandle> ThreadScopedHandle;
+ typedef ScopedHandle<TokenHandle> TokenScopedHandle;
+ typedef ScopedHandle<FileHandle> FileScopedHandle;
+}
+
+static error_code GetFileNameFromHandle(HANDLE FileHandle,
+ std::string& Name) {
+ char Filename[MAX_PATH+1];
+ bool Success = false;
+ Name.clear();
+
+ // Get the file size.
+ LARGE_INTEGER FileSize;
+ Success = ::GetFileSizeEx(FileHandle, &FileSize);
+
+ if (!Success)
+ return windows_error(::GetLastError());
+
+ // Create a file mapping object.
+ FileMappingScopedHandle FileMapping(
+ ::CreateFileMappingA(FileHandle,
+ NULL,
+ PAGE_READONLY,
+ 0,
+ 1,
+ NULL));
+
+ if (!FileMapping)
+ return windows_error(::GetLastError());
+
+ // Create a file mapping to get the file name.
+ MappedViewOfFileScopedHandle MappedFile(
+ ::MapViewOfFile(FileMapping, FILE_MAP_READ, 0, 0, 1));
+
+ if (!MappedFile)
+ return windows_error(::GetLastError());
+
+ Success = ::GetMappedFileNameA(::GetCurrentProcess(),
+ MappedFile,
+ Filename,
+ array_lengthof(Filename) - 1);
+
+ if (!Success)
+ return windows_error(::GetLastError());
+ else {
+ Name = Filename;
+ return windows_error::success;
+ }
+}
+
+static std::string QuoteProgramPathIfNeeded(StringRef Command) {
+ if (Command.find_first_of(' ') == StringRef::npos)
+ return Command;
+ else {
+ std::string ret;
+ ret.reserve(Command.size() + 3);
+ ret.push_back('"');
+ ret.append(Command.begin(), Command.end());
+ ret.push_back('"');
+ return ret;
+ }
+}
+
+/// @brief Find program using shell lookup rules.
+/// @param Program This is either an absolute path, relative path, or simple a
+/// program name. Look in PATH for any programs that match. If no
+/// 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) {
+ char PathName[MAX_PATH + 1];
+ typedef SmallVector<StringRef, 12> pathext_t;
+ pathext_t pathext;
+ // Check for the program without an extension (in case it already has one).
+ pathext.push_back("");
+ SplitString(std::getenv("PATHEXT"), pathext, ";");
+
+ for (pathext_t::iterator i = pathext.begin(), e = pathext.end(); i != e; ++i){
+ SmallString<5> ext;
+ for (std::size_t ii = 0, e = i->size(); ii != e; ++ii)
+ ext.push_back(::tolower((*i)[ii]));
+ LPCSTR Extension = NULL;
+ if (ext.size() && ext[0] == '.')
+ Extension = ext.c_str();
+ DWORD length = ::SearchPathA(NULL,
+ Program.c_str(),
+ Extension,
+ array_lengthof(PathName),
+ PathName,
+ NULL);
+ if (length == 0)
+ ec = windows_error(::GetLastError());
+ else if (length > array_lengthof(PathName)) {
+ // This may have been the file, return with error.
+ ec = windows_error::buffer_overflow;
+ break;
+ } else {
+ // We found the path! Return it.
+ ec = windows_error::success;
+ break;
+ }
+ }
+
+ // Make sure PathName is valid.
+ PathName[MAX_PATH] = 0;
+ return PathName;
+}
+
+static error_code EnableDebugPrivileges() {
+ HANDLE TokenHandle;
+ BOOL success = ::OpenProcessToken(::GetCurrentProcess(),
+ TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
+ &TokenHandle);
+ if (!success)
+ return windows_error(::GetLastError());
+
+ TokenScopedHandle Token(TokenHandle);
+ TOKEN_PRIVILEGES TokenPrivileges;
+ LUID LocallyUniqueID;
+
+ success = ::LookupPrivilegeValueA(NULL,
+ SE_DEBUG_NAME,
+ &LocallyUniqueID);
+ if (!success)
+ return windows_error(::GetLastError());
+
+ TokenPrivileges.PrivilegeCount = 1;
+ TokenPrivileges.Privileges[0].Luid = LocallyUniqueID;
+ TokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+ success = ::AdjustTokenPrivileges(Token,
+ FALSE,
+ &TokenPrivileges,
+ sizeof(TOKEN_PRIVILEGES),
+ NULL,
+ NULL);
+ // The value of success is basically useless. Either way we are just returning
+ // the value of ::GetLastError().
+ return windows_error(::GetLastError());
+}
+
+static StringRef ExceptionCodeToString(DWORD ExceptionCode) {
+ switch(ExceptionCode) {
+ case EXCEPTION_ACCESS_VIOLATION: return "EXCEPTION_ACCESS_VIOLATION";
+ case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+ return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED";
+ case EXCEPTION_BREAKPOINT: return "EXCEPTION_BREAKPOINT";
+ case EXCEPTION_DATATYPE_MISALIGNMENT:
+ return "EXCEPTION_DATATYPE_MISALIGNMENT";
+ case EXCEPTION_FLT_DENORMAL_OPERAND: return "EXCEPTION_FLT_DENORMAL_OPERAND";
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "EXCEPTION_FLT_DIVIDE_BY_ZERO";
+ case EXCEPTION_FLT_INEXACT_RESULT: return "EXCEPTION_FLT_INEXACT_RESULT";
+ case EXCEPTION_FLT_INVALID_OPERATION:
+ return "EXCEPTION_FLT_INVALID_OPERATION";
+ case EXCEPTION_FLT_OVERFLOW: return "EXCEPTION_FLT_OVERFLOW";
+ case EXCEPTION_FLT_STACK_CHECK: return "EXCEPTION_FLT_STACK_CHECK";
+ case EXCEPTION_FLT_UNDERFLOW: return "EXCEPTION_FLT_UNDERFLOW";
+ case EXCEPTION_ILLEGAL_INSTRUCTION: return "EXCEPTION_ILLEGAL_INSTRUCTION";
+ case EXCEPTION_IN_PAGE_ERROR: return "EXCEPTION_IN_PAGE_ERROR";
+ case EXCEPTION_INT_DIVIDE_BY_ZERO: return "EXCEPTION_INT_DIVIDE_BY_ZERO";
+ case EXCEPTION_INT_OVERFLOW: return "EXCEPTION_INT_OVERFLOW";
+ case EXCEPTION_INVALID_DISPOSITION: return "EXCEPTION_INVALID_DISPOSITION";
+ case EXCEPTION_NONCONTINUABLE_EXCEPTION:
+ return "EXCEPTION_NONCONTINUABLE_EXCEPTION";
+ case EXCEPTION_PRIV_INSTRUCTION: return "EXCEPTION_PRIV_INSTRUCTION";
+ case EXCEPTION_SINGLE_STEP: return "EXCEPTION_SINGLE_STEP";
+ case EXCEPTION_STACK_OVERFLOW: return "EXCEPTION_STACK_OVERFLOW";
+ default: return "<unknown>";
+ }
+}
+
+int main(int argc, char **argv) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+
+ ToolName = argv[0];
+
+ cl::ParseCommandLineOptions(argc, argv, "Dr. Watson Assassin.\n");
+ if (ProgramToRun.size() == 0) {
+ cl::PrintHelpMessage();
+ return -1;
+ }
+
+ if (Timeout > std::numeric_limits<uint32_t>::max() / 1000) {
+ errs() << ToolName << ": Timeout value too large, must be less than: "
+ << std::numeric_limits<uint32_t>::max() / 1000
+ << '\n';
+ return -1;
+ }
+
+ std::string CommandLine(ProgramToRun);
+
+ error_code ec;
+ ProgramToRun = FindProgram(ProgramToRun, ec);
+ if (ec) {
+ errs() << ToolName << ": Failed to find program: '" << CommandLine
+ << "': " << ec.message() << '\n';
+ return -1;
+ }
+
+ if (TraceExecution)
+ errs() << ToolName << ": Found Program: " << ProgramToRun << '\n';
+
+ for (std::vector<std::string>::iterator i = Argv.begin(),
+ e = Argv.end();
+ i != e; ++i) {
+ CommandLine.push_back(' ');
+ CommandLine.append(*i);
+ }
+
+ if (TraceExecution)
+ errs() << ToolName << ": Program Image Path: " << ProgramToRun << '\n'
+ << ToolName << ": Command Line: " << CommandLine << '\n';
+
+ STARTUPINFO StartupInfo;
+ PROCESS_INFORMATION ProcessInfo;
+ std::memset(&StartupInfo, 0, sizeof(StartupInfo));
+ StartupInfo.cb = sizeof(StartupInfo);
+ std::memset(&ProcessInfo, 0, sizeof(ProcessInfo));
+
+ // Set error mode to not display any message boxes. The child process inherits
+ // this.
+ ::SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
+ ::_set_error_mode(_OUT_TO_STDERR);
+
+ BOOL success = ::CreateProcessA(ProgramToRun.c_str(),
+ LPSTR(CommandLine.c_str()),
+ NULL,
+ NULL,
+ FALSE,
+ DEBUG_PROCESS,
+ NULL,
+ NULL,
+ &StartupInfo,
+ &ProcessInfo);
+ if (!success) {
+ errs() << ToolName << ": Failed to run program: '" << ProgramToRun
+ << "': " << error_code(windows_error(::GetLastError())).message()
+ << '\n';
+ return -1;
+ }
+
+ // Make sure ::CloseHandle is called on exit.
+ std::map<DWORD, HANDLE> ProcessIDToHandle;
+
+ DEBUG_EVENT DebugEvent;
+ std::memset(&DebugEvent, 0, sizeof(DebugEvent));
+ DWORD dwContinueStatus = DBG_CONTINUE;
+
+ // Run the program under the debugger until either it exits, or throws an
+ // exception.
+ if (TraceExecution)
+ errs() << ToolName << ": Debugging...\n";
+
+ while(true) {
+ DWORD TimeLeft = INFINITE;
+ if (Timeout > 0) {
+ FILETIME CreationTime, ExitTime, KernelTime, UserTime;
+ ULARGE_INTEGER a, b;
+ success = ::GetProcessTimes(ProcessInfo.hProcess,
+ &CreationTime,
+ &ExitTime,
+ &KernelTime,
+ &UserTime);
+ if (!success) {
+ ec = windows_error(::GetLastError());
+
+ errs() << ToolName << ": Failed to get process times: "
+ << ec.message() << '\n';
+ return -1;
+ }
+ a.LowPart = KernelTime.dwLowDateTime;
+ a.HighPart = KernelTime.dwHighDateTime;
+ b.LowPart = UserTime.dwLowDateTime;
+ b.HighPart = UserTime.dwHighDateTime;
+ // Convert 100-nanosecond units to milliseconds.
+ uint64_t TotalTimeMiliseconds = (a.QuadPart + b.QuadPart) / 10000;
+ // Handle the case where the process has been running for more than 49
+ // days.
+ if (TotalTimeMiliseconds > std::numeric_limits<uint32_t>::max()) {
+ errs() << ToolName << ": Timeout Failed: Process has been running for"
+ "more than 49 days.\n";
+ return -1;
+ }
+
+ // We check with > instead of using Timeleft because if
+ // TotalTimeMiliseconds is greater than Timeout * 1000, TimeLeft would
+ // underflow.
+ if (TotalTimeMiliseconds > (Timeout * 1000)) {
+ errs() << ToolName << ": Process timed out.\n";
+ ::TerminateProcess(ProcessInfo.hProcess, -1);
+ // Otherwise other stuff starts failing...
+ return -1;
+ }
+
+ TimeLeft = (Timeout * 1000) - static_cast<uint32_t>(TotalTimeMiliseconds);
+ }
+ success = WaitForDebugEvent(&DebugEvent, TimeLeft);
+
+ if (!success) {
+ ec = windows_error(::GetLastError());
+
+ if (ec == errc::timed_out) {
+ errs() << ToolName << ": Process timed out.\n";
+ ::TerminateProcess(ProcessInfo.hProcess, -1);
+ // Otherwise other stuff starts failing...
+ return -1;
+ }
+
+ errs() << ToolName << ": Failed to wait for debug event in program: '"
+ << ProgramToRun << "': " << ec.message() << '\n';
+ return -1;
+ }
+
+ switch(DebugEvent.dwDebugEventCode) {
+ case CREATE_PROCESS_DEBUG_EVENT:
+ // Make sure we remove the handle on exit.
+ if (TraceExecution)
+ errs() << ToolName << ": Debug Event: CREATE_PROCESS_DEBUG_EVENT\n";
+ ProcessIDToHandle[DebugEvent.dwProcessId] =
+ DebugEvent.u.CreateProcessInfo.hProcess;
+ ::CloseHandle(DebugEvent.u.CreateProcessInfo.hFile);
+ break;
+ case EXIT_PROCESS_DEBUG_EVENT: {
+ if (TraceExecution)
+ errs() << ToolName << ": Debug Event: EXIT_PROCESS_DEBUG_EVENT\n";
+
+ // If this is the process we originally created, exit with its exit
+ // code.
+ if (DebugEvent.dwProcessId == ProcessInfo.dwProcessId)
+ return DebugEvent.u.ExitProcess.dwExitCode;
+
+ // Otherwise cleanup any resources we have for it.
+ std::map<DWORD, HANDLE>::iterator ExitingProcess =
+ ProcessIDToHandle.find(DebugEvent.dwProcessId);
+ if (ExitingProcess == ProcessIDToHandle.end()) {
+ errs() << ToolName << ": Got unknown process id!\n";
+ return -1;
+ }
+ ::CloseHandle(ExitingProcess->second);
+ ProcessIDToHandle.erase(ExitingProcess);
+ }
+ break;
+ case CREATE_THREAD_DEBUG_EVENT:
+ ::CloseHandle(DebugEvent.u.CreateThread.hThread);
+ break;
+ case LOAD_DLL_DEBUG_EVENT: {
+ // Cleanup the file handle.
+ FileScopedHandle DLLFile(DebugEvent.u.LoadDll.hFile);
+ std::string DLLName;
+ ec = GetFileNameFromHandle(DLLFile, DLLName);
+ if (ec) {
+ DLLName = "<failed to get file name from file handle> : ";
+ DLLName += ec.message();
+ }
+ if (TraceExecution) {
+ errs() << ToolName << ": Debug Event: LOAD_DLL_DEBUG_EVENT\n";
+ errs().indent(ToolName.size()) << ": DLL Name : " << DLLName << '\n';
+ }
+
+ if (NoUser32 && sys::path::stem(DLLName) == "user32") {
+ // Program is loading user32.dll, in the applications we are testing,
+ // this only happens if an assert has fired. By now the message has
+ // already been printed, so simply close the program.
+ errs() << ToolName << ": user32.dll loaded!\n";
+ errs().indent(ToolName.size())
+ << ": This probably means that assert was called. Closing "
+ "program to prevent message box from popping up.\n";
+ dwContinueStatus = DBG_CONTINUE;
+ ::TerminateProcess(ProcessIDToHandle[DebugEvent.dwProcessId], -1);
+ return -1;
+ }
+ }
+ break;
+ case EXCEPTION_DEBUG_EVENT: {
+ // Close the application if this exception will not be handled by the
+ // child application.
+ if (TraceExecution)
+ errs() << ToolName << ": Debug Event: EXCEPTION_DEBUG_EVENT\n";
+
+ EXCEPTION_DEBUG_INFO &Exception = DebugEvent.u.Exception;
+ if (Exception.dwFirstChance > 0) {
+ if (TraceExecution) {
+ errs().indent(ToolName.size()) << ": Debug Info : ";
+ errs() << "First chance exception at "
+ << Exception.ExceptionRecord.ExceptionAddress
+ << ", exception code: "
+ << ExceptionCodeToString(
+ Exception.ExceptionRecord.ExceptionCode)
+ << " (" << Exception.ExceptionRecord.ExceptionCode << ")\n";
+ }
+ dwContinueStatus = DBG_EXCEPTION_NOT_HANDLED;
+ } else {
+ errs() << ToolName << ": Unhandled exception in: " << ProgramToRun
+ << "!\n";
+ errs().indent(ToolName.size()) << ": location: ";
+ errs() << Exception.ExceptionRecord.ExceptionAddress
+ << ", exception code: "
+ << ExceptionCodeToString(
+ Exception.ExceptionRecord.ExceptionCode)
+ << " (" << Exception.ExceptionRecord.ExceptionCode
+ << ")\n";
+ dwContinueStatus = DBG_CONTINUE;
+ ::TerminateProcess(ProcessIDToHandle[DebugEvent.dwProcessId], -1);
+ return -1;
+ }
+ }
+ break;
+ default:
+ // Do nothing.
+ if (TraceExecution)
+ errs() << ToolName << ": Debug Event: <unknown>\n";
+ break;
+ }
+
+ success = ContinueDebugEvent(DebugEvent.dwProcessId,
+ DebugEvent.dwThreadId,
+ dwContinueStatus);
+ if (!success) {
+ ec = windows_error(::GetLastError());
+ errs() << ToolName << ": Failed to continue debugging program: '"
+ << ProgramToRun << "': " << ec.message() << '\n';
+ return -1;
+ }
+
+ dwContinueStatus = DBG_CONTINUE;
+ }
+
+ assert(0 && "Fell out of debug loop. This shouldn't be possible!");
+ return -1;
+}
diff --git a/src/LLVM/utils/Makefile b/src/LLVM/utils/Makefile
index 1a4dcca..9d4dc5c 100644
--- a/src/LLVM/utils/Makefile
+++ b/src/LLVM/utils/Makefile
@@ -15,7 +15,7 @@
DSAclean.py DSAextract.py emacs findsym.pl GenLibDeps.pl \
getsrcs.sh importNLT.pl llvmdo llvmgrep llvm-native-gcc \
llvm-native-gxx makellvm NightlyTest.gnuplot NightlyTest.pl \
- NightlyTestTemplate.html NLT.schema OldenDataRecover.pl \
+ NightlyTestTemplate.html NLT.schema \
parseNLT.pl plotNLT.pl profile.pl \
webNLT.pl vim
diff --git a/src/LLVM/utils/Misc/zkill b/src/LLVM/utils/Misc/zkill
new file mode 100644
index 0000000..bc0bfd5
--- /dev/null
+++ b/src/LLVM/utils/Misc/zkill
@@ -0,0 +1,276 @@
+#!/usr/bin/env python
+
+import os
+import re
+import sys
+
+def _write_message(kind, message):
+ import inspect, os, sys
+
+ # Get the file/line where this message was generated.
+ f = inspect.currentframe()
+ # Step out of _write_message, and then out of wrapper.
+ f = f.f_back.f_back
+ file,line,_,_,_ = inspect.getframeinfo(f)
+ location = '%s:%d' % (os.path.basename(file), line)
+
+ print >>sys.stderr, '%s: %s: %s' % (location, kind, message)
+
+note = lambda message: _write_message('note', message)
+warning = lambda message: _write_message('warning', message)
+error = lambda message: (_write_message('error', message), sys.exit(1))
+
+def re_full_match(pattern, str):
+ m = re.match(pattern, str)
+ if m and m.end() != len(str):
+ m = None
+ return m
+
+def parse_time(value):
+ minutes,value = value.split(':',1)
+ if '.' in value:
+ seconds,fseconds = value.split('.',1)
+ else:
+ seconds = value
+ return int(minutes) * 60 + int(seconds) + float('.'+fseconds)
+
+def extractExecutable(command):
+ """extractExecutable - Given a string representing a command line, attempt
+ to extract the executable path, even if it includes spaces."""
+
+ # Split into potential arguments.
+ args = command.split(' ')
+
+ # Scanning from the beginning, try to see if the first N args, when joined,
+ # exist. If so that's probably the executable.
+ for i in range(1,len(args)):
+ cmd = ' '.join(args[:i])
+ if os.path.exists(cmd):
+ return cmd
+
+ # Otherwise give up and return the first "argument".
+ return args[0]
+
+class Struct:
+ def __init__(self, **kwargs):
+ self.fields = kwargs.keys()
+ self.__dict__.update(kwargs)
+
+ def __repr__(self):
+ return 'Struct(%s)' % ', '.join(['%s=%r' % (k,getattr(self,k))
+ for k in self.fields])
+
+kExpectedPSFields = [('PID', int, 'pid'),
+ ('USER', str, 'user'),
+ ('COMMAND', str, 'command'),
+ ('%CPU', float, 'cpu_percent'),
+ ('TIME', parse_time, 'cpu_time'),
+ ('VSZ', int, 'vmem_size'),
+ ('RSS', int, 'rss')]
+def getProcessTable():
+ import subprocess
+ p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ out,err = p.communicate()
+ res = p.wait()
+ if p.wait():
+ error('unable to get process table')
+ elif err.strip():
+ error('unable to get process table: %s' % err)
+
+ lns = out.split('\n')
+ it = iter(lns)
+ header = it.next().split()
+ numRows = len(header)
+
+ # Make sure we have the expected fields.
+ indexes = []
+ for field in kExpectedPSFields:
+ try:
+ indexes.append(header.index(field[0]))
+ except:
+ if opts.debug:
+ raise
+ error('unable to get process table, no %r field.' % field[0])
+
+ table = []
+ for i,ln in enumerate(it):
+ if not ln.strip():
+ continue
+
+ fields = ln.split(None, numRows - 1)
+ if len(fields) != numRows:
+ warning('unable to process row: %r' % ln)
+ continue
+
+ record = {}
+ for field,idx in zip(kExpectedPSFields, indexes):
+ value = fields[idx]
+ try:
+ record[field[2]] = field[1](value)
+ except:
+ if opts.debug:
+ raise
+ warning('unable to process %r in row: %r' % (field[0], ln))
+ break
+ else:
+ # Add our best guess at the executable.
+ record['executable'] = extractExecutable(record['command'])
+ table.append(Struct(**record))
+
+ return table
+
+def getSignalValue(name):
+ import signal
+ if name.startswith('SIG'):
+ value = getattr(signal, name)
+ if value and isinstance(value, int):
+ return value
+ error('unknown signal: %r' % name)
+
+import signal
+kSignals = {}
+for name in dir(signal):
+ if name.startswith('SIG') and name == name.upper() and name.isalpha():
+ kSignals[name[3:]] = getattr(signal, name)
+
+def main():
+ global opts
+ from optparse import OptionParser, OptionGroup
+ parser = OptionParser("usage: %prog [options] {pid}*")
+
+ # FIXME: Add -NNN and -SIGNAME options.
+
+ parser.add_option("-s", "", dest="signalName",
+ help="Name of the signal to use (default=%default)",
+ action="store", default='INT',
+ choices=kSignals.keys())
+ parser.add_option("-l", "", dest="listSignals",
+ help="List known signal names",
+ action="store_true", default=False)
+
+ parser.add_option("-n", "--dry-run", dest="dryRun",
+ help="Only print the actions that would be taken",
+ action="store_true", default=False)
+ parser.add_option("-v", "--verbose", dest="verbose",
+ help="Print more verbose output",
+ action="store_true", default=False)
+ parser.add_option("", "--debug", dest="debug",
+ help="Enable debugging output",
+ action="store_true", default=False)
+ parser.add_option("", "--force", dest="force",
+ help="Perform the specified commands, even if it seems like a bad idea",
+ action="store_true", default=False)
+
+ inf = float('inf')
+ group = OptionGroup(parser, "Process Filters")
+ group.add_option("", "--name", dest="execName", metavar="REGEX",
+ help="Kill processes whose name matches the given regexp",
+ action="store", default=None)
+ group.add_option("", "--exec", dest="execPath", metavar="REGEX",
+ help="Kill processes whose executable matches the given regexp",
+ action="store", default=None)
+ group.add_option("", "--user", dest="userName", metavar="REGEX",
+ help="Kill processes whose user matches the given regexp",
+ action="store", default=None)
+ group.add_option("", "--min-cpu", dest="minCPU", metavar="PCT",
+ help="Kill processes with CPU usage >= PCT",
+ action="store", type=float, default=None)
+ group.add_option("", "--max-cpu", dest="maxCPU", metavar="PCT",
+ help="Kill processes with CPU usage <= PCT",
+ action="store", type=float, default=inf)
+ group.add_option("", "--min-mem", dest="minMem", metavar="N",
+ help="Kill processes with virtual size >= N (MB)",
+ action="store", type=float, default=None)
+ group.add_option("", "--max-mem", dest="maxMem", metavar="N",
+ help="Kill processes with virtual size <= N (MB)",
+ action="store", type=float, default=inf)
+ group.add_option("", "--min-rss", dest="minRSS", metavar="N",
+ help="Kill processes with RSS >= N",
+ action="store", type=float, default=None)
+ group.add_option("", "--max-rss", dest="maxRSS", metavar="N",
+ help="Kill processes with RSS <= N",
+ action="store", type=float, default=inf)
+ group.add_option("", "--min-time", dest="minTime", metavar="N",
+ help="Kill processes with CPU time >= N (seconds)",
+ action="store", type=float, default=None)
+ group.add_option("", "--max-time", dest="maxTime", metavar="N",
+ help="Kill processes with CPU time <= N (seconds)",
+ action="store", type=float, default=inf)
+ parser.add_option_group(group)
+
+ (opts, args) = parser.parse_args()
+
+ if opts.listSignals:
+ items = [(v,k) for k,v in kSignals.items()]
+ items.sort()
+ for i in range(0, len(items), 4):
+ print '\t'.join(['%2d) SIG%s' % (k,v)
+ for k,v in items[i:i+4]])
+ sys.exit(0)
+
+ # Figure out the signal to use.
+ signal = kSignals[opts.signalName]
+ signalValueName = str(signal)
+ if opts.verbose:
+ name = dict((v,k) for k,v in kSignals.items()).get(signal,None)
+ if name:
+ signalValueName = name
+ note('using signal %d (SIG%s)' % (signal, name))
+ else:
+ note('using signal %d' % signal)
+
+ # Get the pid list to consider.
+ pids = set()
+ for arg in args:
+ try:
+ pids.add(int(arg))
+ except:
+ parser.error('invalid positional argument: %r' % arg)
+
+ filtered = ps = getProcessTable()
+
+ # Apply filters.
+ if pids:
+ filtered = [p for p in filtered
+ if p.pid in pids]
+ if opts.execName is not None:
+ filtered = [p for p in filtered
+ if re_full_match(opts.execName,
+ os.path.basename(p.executable))]
+ if opts.execPath is not None:
+ filtered = [p for p in filtered
+ if re_full_match(opts.execPath, p.executable)]
+ if opts.userName is not None:
+ filtered = [p for p in filtered
+ if re_full_match(opts.userName, p.user)]
+ filtered = [p for p in filtered
+ if opts.minCPU <= p.cpu_percent <= opts.maxCPU]
+ filtered = [p for p in filtered
+ if opts.minMem <= float(p.vmem_size) / (1<<20) <= opts.maxMem]
+ filtered = [p for p in filtered
+ if opts.minRSS <= p.rss <= opts.maxRSS]
+ filtered = [p for p in filtered
+ if opts.minTime <= p.cpu_time <= opts.maxTime]
+
+ if len(filtered) == len(ps):
+ if not opts.force and not opts.dryRun:
+ error('refusing to kill all processes without --force')
+
+ if not filtered:
+ warning('no processes selected')
+
+ for p in filtered:
+ if opts.verbose:
+ note('kill(%r, %s) # (user=%r, executable=%r, CPU=%2.2f%%, time=%r, vmem=%r, rss=%r)' %
+ (p.pid, signalValueName, p.user, p.executable, p.cpu_percent, p.cpu_time, p.vmem_size, p.rss))
+ if not opts.dryRun:
+ try:
+ os.kill(p.pid, signal)
+ except OSError:
+ if opts.debug:
+ raise
+ warning('unable to kill PID: %r' % p.pid)
+
+if __name__ == '__main__':
+ main()
diff --git a/src/LLVM/utils/NewNightlyTest.pl b/src/LLVM/utils/NewNightlyTest.pl
index 1b48168..da806e9 100644
--- a/src/LLVM/utils/NewNightlyTest.pl
+++ b/src/LLVM/utils/NewNightlyTest.pl
@@ -794,7 +794,7 @@
'endtime' => $endtime,
'target_triple' => $targetTriple,
- # Unused, but left around for backwards compatability.
+ # Unused, but left around for backwards compatibility.
'warnings' => "",
'cvsusercommitlist' => "",
'cvsuserupdatelist' => "",
diff --git a/src/LLVM/utils/PerfectShuffle/PerfectShuffle.cpp b/src/LLVM/utils/PerfectShuffle/PerfectShuffle.cpp
index b94a7d3..98f8f4c 100644
--- a/src/LLVM/utils/PerfectShuffle/PerfectShuffle.cpp
+++ b/src/LLVM/utils/PerfectShuffle/PerfectShuffle.cpp
@@ -15,6 +15,7 @@
//===----------------------------------------------------------------------===//
#include <iostream>
+#include <iomanip>
#include <vector>
#include <cassert>
#include <cstdlib>
@@ -400,7 +401,7 @@
// LHS, and 13 bits of RHS = 32 bits.
unsigned Val = (CostSat << 30) | (OpNum << 26) | (LHS << 13) | RHS;
- std::cout << " " << Val << "U,\t// ";
+ std::cout << " " << std::setw(10) << Val << "U, // ";
PrintMask(i, std::cout);
std::cout << ": Cost " << ShufTab[i].Cost;
std::cout << " " << (ShufTab[i].Op ? ShufTab[i].Op->getName() : "copy");
diff --git a/src/LLVM/utils/TableGen/ARMDecoderEmitter.cpp b/src/LLVM/utils/TableGen/ARMDecoderEmitter.cpp
index 8d4f6cd..145b96d 100644
--- a/src/LLVM/utils/TableGen/ARMDecoderEmitter.cpp
+++ b/src/LLVM/utils/TableGen/ARMDecoderEmitter.cpp
@@ -18,10 +18,10 @@
#include "ARMDecoderEmitter.h"
#include "CodeGenTarget.h"
-#include "Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Record.h"
#include <vector>
#include <map>
@@ -41,7 +41,7 @@
ENTRY(ARM_FORMAT_BRFRM, 2) \
ENTRY(ARM_FORMAT_BRMISCFRM, 3) \
ENTRY(ARM_FORMAT_DPFRM, 4) \
- ENTRY(ARM_FORMAT_DPSOREGFRM, 5) \
+ ENTRY(ARM_FORMAT_DPSOREGREGFRM, 5) \
ENTRY(ARM_FORMAT_LDFRM, 6) \
ENTRY(ARM_FORMAT_STFRM, 7) \
ENTRY(ARM_FORMAT_LDMISCFRM, 8) \
@@ -77,7 +77,8 @@
ENTRY(ARM_FORMAT_N3RegVecSh, 38) \
ENTRY(ARM_FORMAT_NVecExtract, 39) \
ENTRY(ARM_FORMAT_NVecMulScalar, 40) \
- ENTRY(ARM_FORMAT_NVTBL, 41)
+ ENTRY(ARM_FORMAT_NVTBL, 41) \
+ ENTRY(ARM_FORMAT_DPSOREGIMMFRM, 42)
// ARM instruction format specifies the encoding used by the instruction.
#define ENTRY(n, v) n = v,
@@ -221,7 +222,7 @@
#define BIT_WIDTH 32
// Forward declaration.
-class FilterChooser;
+class ARMFilterChooser;
// Representation of the instruction to work on.
typedef bit_value_t insn_t[BIT_WIDTH];
@@ -240,7 +241,7 @@
/// the Filter/FilterChooser combo does not know how to distinguish among the
/// Opcodes assigned.
///
-/// An example of a conflcit is
+/// An example of a conflict is
///
/// Conflict:
/// 111101000.00........00010000....
@@ -262,9 +263,9 @@
/// decoder could try to decode the even/odd register numbering and assign to
/// VST4q8a or VST4q8b, but for the time being, the decoder chooses the "a"
/// version and return the Opcode since the two have the same Asm format string.
-class Filter {
+class ARMFilter {
protected:
- FilterChooser *Owner; // points to the FilterChooser who owns this filter
+ ARMFilterChooser *Owner; // points to the FilterChooser who owns this filter
unsigned StartBit; // the starting bit position
unsigned NumBits; // number of bits to filter
bool Mixed; // a mixed region contains both set and unset bits
@@ -276,7 +277,7 @@
std::vector<unsigned> VariableInstructions;
// Map of well-known segment value to its delegate.
- std::map<unsigned, FilterChooser*> FilterChooserMap;
+ std::map<unsigned, ARMFilterChooser*> FilterChooserMap;
// Number of instructions which fall under FilteredInstructions category.
unsigned NumFiltered;
@@ -296,16 +297,17 @@
}
// Return the filter chooser for the group of instructions without constant
// segment values.
- FilterChooser &getVariableFC() {
+ ARMFilterChooser &getVariableFC() {
assert(NumFiltered == 1);
assert(FilterChooserMap.size() == 1);
return *(FilterChooserMap.find((unsigned)-1)->second);
}
- Filter(const Filter &f);
- Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, bool mixed);
+ ARMFilter(const ARMFilter &f);
+ ARMFilter(ARMFilterChooser &owner, unsigned startBit, unsigned numBits,
+ bool mixed);
- ~Filter();
+ ~ARMFilter();
// Divides the decoding task into sub tasks and delegates them to the
// inferior FilterChooser's.
@@ -333,7 +335,7 @@
ATTR_MIXED
} bitAttr_t;
-/// FilterChooser - FilterChooser chooses the best filter among a set of Filters
+/// ARMFilterChooser - FilterChooser chooses the best filter among a set of Filters
/// in order to perform the decoding of instructions at the current level.
///
/// Decoding proceeds from the top down. Based on the well-known encoding bits
@@ -348,11 +350,11 @@
/// It is useful to think of a Filter as governing the switch stmts of the
/// decoding tree. And each case is delegated to an inferior FilterChooser to
/// decide what further remaining bits to look at.
-class FilterChooser {
+class ARMFilterChooser {
static TARGET_NAME_t TargetName;
protected:
- friend class Filter;
+ friend class ARMFilter;
// Vector of codegen instructions to choose our filter.
const std::vector<const CodeGenInstruction*> &AllInstructions;
@@ -361,14 +363,14 @@
const std::vector<unsigned> Opcodes;
// Vector of candidate filters.
- std::vector<Filter> Filters;
+ std::vector<ARMFilter> Filters;
// Array of bit values passed down from our parent.
// Set to all BIT_UNFILTERED's for Parent == NULL.
bit_value_t FilterBitValues[BIT_WIDTH];
// Links to the FilterChooser above us in the decoding tree.
- FilterChooser *Parent;
+ ARMFilterChooser *Parent;
// Index of the best filter from Filters.
int BestIndex;
@@ -376,13 +378,13 @@
public:
static void setTargetName(TARGET_NAME_t tn) { TargetName = tn; }
- FilterChooser(const FilterChooser &FC) :
+ ARMFilterChooser(const ARMFilterChooser &FC) :
AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes),
Filters(FC.Filters), Parent(FC.Parent), BestIndex(FC.BestIndex) {
memcpy(FilterBitValues, FC.FilterBitValues, sizeof(FilterBitValues));
}
- FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
+ ARMFilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
const std::vector<unsigned> &IDs) :
AllInstructions(Insts), Opcodes(IDs), Filters(), Parent(NULL),
BestIndex(-1) {
@@ -392,10 +394,10 @@
doFilter();
}
- FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
- const std::vector<unsigned> &IDs,
- bit_value_t (&ParentFilterBitValues)[BIT_WIDTH],
- FilterChooser &parent) :
+ ARMFilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
+ const std::vector<unsigned> &IDs,
+ bit_value_t (&ParentFilterBitValues)[BIT_WIDTH],
+ ARMFilterChooser &parent) :
AllInstructions(Insts), Opcodes(IDs), Filters(), Parent(&parent),
BestIndex(-1) {
for (unsigned i = 0; i < BIT_WIDTH; ++i)
@@ -420,14 +422,18 @@
protected:
// Populates the insn given the uid.
void insnWithID(insn_t &Insn, unsigned Opcode) const {
+ if (AllInstructions[Opcode]->isPseudo)
+ return;
+
BitsInit &Bits = getBitsField(*AllInstructions[Opcode]->TheDef, "Inst");
for (unsigned i = 0; i < BIT_WIDTH; ++i)
Insn[i] = bitFromBits(Bits, i);
// Set Inst{21} to 1 (wback) when IndexModeBits == IndexModeUpd.
- if (getByteField(*AllInstructions[Opcode]->TheDef, "IndexModeBits")
- == IndexModeUpd)
+ Record *R = AllInstructions[Opcode]->TheDef;
+ if (R->getValue("IndexModeBits") &&
+ getByteField(*R, "IndexModeBits") == IndexModeUpd)
Insn[21] = BIT_TRUE;
}
@@ -452,7 +458,7 @@
/// dumpFilterArray on each filter chooser up to the top level one.
void dumpStack(raw_ostream &o, const char *prefix);
- Filter &bestFilter() {
+ ARMFilter &bestFilter() {
assert(BestIndex != -1 && "BestIndex not set");
return Filters[BestIndex];
}
@@ -497,11 +503,12 @@
bool emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,unsigned Opc);
// Emits code to decode the singleton, and then to decode the rest.
- void emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,Filter &Best);
+ void emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
+ ARMFilter &Best);
// Assign a single filter and run with it.
- void runSingleFilter(FilterChooser &owner, unsigned startBit, unsigned numBit,
- bool mixed);
+ void runSingleFilter(ARMFilterChooser &owner, unsigned startBit,
+ unsigned numBit, bool mixed);
// reportRegion is a helper function for filterProcessor to mark a region as
// eligible for use as a filter region.
@@ -530,7 +537,7 @@
// //
///////////////////////////
-Filter::Filter(const Filter &f) :
+ARMFilter::ARMFilter(const ARMFilter &f) :
Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits), Mixed(f.Mixed),
FilteredInstructions(f.FilteredInstructions),
VariableInstructions(f.VariableInstructions),
@@ -538,7 +545,7 @@
LastOpcFiltered(f.LastOpcFiltered), NumVariable(f.NumVariable) {
}
-Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits,
+ARMFilter::ARMFilter(ARMFilterChooser &owner, unsigned startBit, unsigned numBits,
bool mixed) : Owner(&owner), StartBit(startBit), NumBits(numBits),
Mixed(mixed) {
assert(StartBit + NumBits - 1 < BIT_WIDTH);
@@ -575,8 +582,8 @@
&& "Filter returns no instruction categories");
}
-Filter::~Filter() {
- std::map<unsigned, FilterChooser*>::iterator filterIterator;
+ARMFilter::~ARMFilter() {
+ std::map<unsigned, ARMFilterChooser*>::iterator filterIterator;
for (filterIterator = FilterChooserMap.begin();
filterIterator != FilterChooserMap.end();
filterIterator++) {
@@ -590,7 +597,7 @@
// A special case arises when there's only one entry in the filtered
// instructions. In order to unambiguously decode the singleton, we need to
// match the remaining undecoded encoding bits against the singleton.
-void Filter::recurse() {
+void ARMFilter::recurse() {
std::map<uint64_t, std::vector<unsigned> >::const_iterator mapIterator;
bit_value_t BitValueArray[BIT_WIDTH];
@@ -604,14 +611,14 @@
for (bitIndex = 0; bitIndex < NumBits; bitIndex++)
BitValueArray[StartBit + bitIndex] = BIT_UNSET;
- // Delegates to an inferior filter chooser for futher processing on this
+ // Delegates to an inferior filter chooser for further processing on this
// group of instructions whose segment values are variable.
- FilterChooserMap.insert(std::pair<unsigned, FilterChooser*>(
+ FilterChooserMap.insert(std::pair<unsigned, ARMFilterChooser*>(
(unsigned)-1,
- new FilterChooser(Owner->AllInstructions,
- VariableInstructions,
- BitValueArray,
- *Owner)
+ new ARMFilterChooser(Owner->AllInstructions,
+ VariableInstructions,
+ BitValueArray,
+ *Owner)
));
}
@@ -636,20 +643,20 @@
BitValueArray[StartBit + bitIndex] = BIT_FALSE;
}
- // Delegates to an inferior filter chooser for futher processing on this
+ // Delegates to an inferior filter chooser for further processing on this
// category of instructions.
- FilterChooserMap.insert(std::pair<unsigned, FilterChooser*>(
+ FilterChooserMap.insert(std::pair<unsigned, ARMFilterChooser*>(
mapIterator->first,
- new FilterChooser(Owner->AllInstructions,
- mapIterator->second,
- BitValueArray,
- *Owner)
+ new ARMFilterChooser(Owner->AllInstructions,
+ mapIterator->second,
+ BitValueArray,
+ *Owner)
));
}
}
// Emit code to decode instructions given a segment or segments of bits.
-void Filter::emit(raw_ostream &o, unsigned &Indentation) {
+void ARMFilter::emit(raw_ostream &o, unsigned &Indentation) {
o.indent(Indentation) << "// Check Inst{";
if (NumBits > 1)
@@ -660,7 +667,7 @@
o.indent(Indentation) << "switch (fieldFromInstruction(insn, "
<< StartBit << ", " << NumBits << ")) {\n";
- std::map<unsigned, FilterChooser*>::iterator filterIterator;
+ std::map<unsigned, ARMFilterChooser*>::iterator filterIterator;
bool DefaultCase = false;
for (filterIterator = FilterChooserMap.begin();
@@ -709,7 +716,7 @@
// Returns the number of fanout produced by the filter. More fanout implies
// the filter distinguishes more categories of instructions.
-unsigned Filter::usefulness() const {
+unsigned ARMFilter::usefulness() const {
if (VariableInstructions.size())
return FilteredInstructions.size();
else
@@ -723,10 +730,10 @@
//////////////////////////////////
// Define the symbol here.
-TARGET_NAME_t FilterChooser::TargetName;
+TARGET_NAME_t ARMFilterChooser::TargetName;
// This provides an opportunity for target specific code emission.
-void FilterChooser::emitTopHook(raw_ostream &o) {
+void ARMFilterChooser::emitTopHook(raw_ostream &o) {
if (TargetName == TARGET_ARM) {
// Emit code that references the ARMFormat data type.
o << "static const ARMFormat ARMFormats[] = {\n";
@@ -747,7 +754,7 @@
}
// Emit the top level typedef and decodeInstruction() function.
-void FilterChooser::emitTop(raw_ostream &o, unsigned &Indentation) {
+void ARMFilterChooser::emitTop(raw_ostream &o, unsigned &Indentation) {
// Run the target specific emit hook.
emitTopHook(o);
@@ -801,7 +808,7 @@
o << '\n';
- o.indent(Indentation) << "static uint16_t decodeInstruction(field_t insn) {\n";
+ o.indent(Indentation) <<"static uint16_t decodeInstruction(field_t insn) {\n";
++Indentation; ++Indentation;
// Emits code to decode the instructions.
@@ -818,7 +825,7 @@
// This provides an opportunity for target specific code emission after
// emitTop().
-void FilterChooser::emitBot(raw_ostream &o, unsigned &Indentation) {
+void ARMFilterChooser::emitBot(raw_ostream &o, unsigned &Indentation) {
if (TargetName != TARGET_THUMB) return;
// Emit code that decodes the Thumb ISA.
@@ -843,7 +850,7 @@
//
// Returns false if and on the first uninitialized bit value encountered.
// Returns true, otherwise.
-bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn,
+bool ARMFilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn,
unsigned StartBit, unsigned NumBits) const {
Field = 0;
@@ -860,7 +867,7 @@
/// dumpFilterArray - dumpFilterArray prints out debugging info for the given
/// filter array as a series of chars.
-void FilterChooser::dumpFilterArray(raw_ostream &o,
+void ARMFilterChooser::dumpFilterArray(raw_ostream &o,
bit_value_t (&filter)[BIT_WIDTH]) {
unsigned bitIndex;
@@ -884,8 +891,8 @@
/// dumpStack - dumpStack traverses the filter chooser chain and calls
/// dumpFilterArray on each filter chooser up to the top level one.
-void FilterChooser::dumpStack(raw_ostream &o, const char *prefix) {
- FilterChooser *current = this;
+void ARMFilterChooser::dumpStack(raw_ostream &o, const char *prefix) {
+ ARMFilterChooser *current = this;
while (current) {
o << prefix;
@@ -896,7 +903,7 @@
}
// Called from Filter::recurse() when singleton exists. For debug purpose.
-void FilterChooser::SingletonExists(unsigned Opc) {
+void ARMFilterChooser::SingletonExists(unsigned Opc) {
insn_t Insn0;
insnWithID(Insn0, Opc);
@@ -923,7 +930,7 @@
// This returns a list of undecoded bits of an instructions, for example,
// Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be
// decoded bits in order to verify that the instruction matches the Opcode.
-unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits,
+unsigned ARMFilterChooser::getIslands(std::vector<unsigned> &StartBits,
std::vector<unsigned> &EndBits, std::vector<uint64_t> &FieldVals,
insn_t &Insn) {
unsigned Num, BitNo;
@@ -983,7 +990,7 @@
// Emits code to decode the singleton. Return true if we have matched all the
// well-known bits.
-bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
+bool ARMFilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
unsigned Opc) {
std::vector<unsigned> StartBits;
std::vector<unsigned> EndBits;
@@ -1046,8 +1053,9 @@
}
// Emits code to decode the singleton, and then to decode the rest.
-void FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
- Filter &Best) {
+void ARMFilterChooser::emitSingletonDecoder(raw_ostream &o,
+ unsigned &Indentation,
+ ARMFilter &Best) {
unsigned Opc = Best.getSingletonOpc();
@@ -1063,10 +1071,11 @@
// Assign a single filter and run with it. Top level API client can initialize
// with a single filter to start the filtering process.
-void FilterChooser::runSingleFilter(FilterChooser &owner, unsigned startBit,
- unsigned numBit, bool mixed) {
+void ARMFilterChooser::runSingleFilter(ARMFilterChooser &owner,
+ unsigned startBit,
+ unsigned numBit, bool mixed) {
Filters.clear();
- Filter F(*this, startBit, numBit, true);
+ ARMFilter F(*this, startBit, numBit, true);
Filters.push_back(F);
BestIndex = 0; // Sole Filter instance to choose from.
bestFilter().recurse();
@@ -1074,18 +1083,18 @@
// reportRegion is a helper function for filterProcessor to mark a region as
// eligible for use as a filter region.
-void FilterChooser::reportRegion(bitAttr_t RA, unsigned StartBit,
- unsigned BitIndex, bool AllowMixed) {
+void ARMFilterChooser::reportRegion(bitAttr_t RA, unsigned StartBit,
+ unsigned BitIndex, bool AllowMixed) {
if (RA == ATTR_MIXED && AllowMixed)
- Filters.push_back(Filter(*this, StartBit, BitIndex - StartBit, true));
+ Filters.push_back(ARMFilter(*this, StartBit, BitIndex - StartBit, true));
else if (RA == ATTR_ALL_SET && !AllowMixed)
- Filters.push_back(Filter(*this, StartBit, BitIndex - StartBit, false));
+ Filters.push_back(ARMFilter(*this, StartBit, BitIndex - StartBit, false));
}
// FilterProcessor scans the well-known encoding bits of the instructions and
// builds up a list of candidate filters. It chooses the best filter and
// recursively descends down the decoding tree.
-bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) {
+bool ARMFilterChooser::filterProcessor(bool AllowMixed, bool Greedy) {
Filters.clear();
BestIndex = -1;
unsigned numInstructions = Opcodes.size();
@@ -1317,7 +1326,7 @@
// Decides on the best configuration of filter(s) to use in order to decode
// the instructions. A conflict of instructions may occur, in which case we
// dump the conflict set to the standard error.
-void FilterChooser::doFilter() {
+void ARMFilterChooser::doFilter() {
unsigned Num = Opcodes.size();
assert(Num && "FilterChooser created with no instructions");
@@ -1350,7 +1359,7 @@
// Emits code to decode our share of instructions. Returns true if the
// emitted code causes a return, which occurs if we know how to decode
// the instruction at this level or the instruction is not decodeable.
-bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) {
+bool ARMFilterChooser::emit(raw_ostream &o, unsigned &Indentation) {
if (Opcodes.size() == 1)
// There is only one instruction in the set, which is great!
// Call emitSingletonDecoder() to see whether there are any remaining
@@ -1359,7 +1368,7 @@
// Choose the best filter to do the decodings!
if (BestIndex != -1) {
- Filter &Best = bestFilter();
+ ARMFilter &Best = bestFilter();
if (Best.getNumFiltered() == 1)
emitSingletonDecoder(o, Indentation, Best);
else
@@ -1377,7 +1386,7 @@
// 2. source registers are identical => VMOVQ; otherwise => VORRq
// 3. LDR, LDRcp => return LDR for now.
// FIXME: How can we distinguish between LDR and LDRcp? Do we need to?
- // 4. tLDM, tLDM_UPD => Rn = Inst{10-8}, reglist = Inst{7-0},
+ // 4. tLDMIA, tLDMIA_UPD => Rn = Inst{10-8}, reglist = Inst{7-0},
// wback = registers<Rn> = 0
// NOTE: (tLDM, tLDM_UPD) resolution must come before Advanced SIMD
// addressing mode resolution!!!
@@ -1418,7 +1427,7 @@
<< "; // Returning LDR for {LDR, LDRcp}\n";
return true;
}
- if (name1 == "tLDM" && name2 == "tLDM_UPD") {
+ if (name1 == "tLDMIA" && name2 == "tLDMIA_UPD") {
// Inserting the opening curly brace for this case block.
--Indentation; --Indentation;
o.indent(Indentation) << "{\n";
@@ -1488,11 +1497,11 @@
class ARMDecoderEmitter::ARMDEBackend {
public:
- ARMDEBackend(ARMDecoderEmitter &frontend) :
+ ARMDEBackend(ARMDecoderEmitter &frontend, RecordKeeper &Records) :
NumberedInstructions(),
Opcodes(),
Frontend(frontend),
- Target(),
+ Target(Records),
FC(NULL)
{
if (Target.getName() == "ARM")
@@ -1538,13 +1547,14 @@
std::vector<unsigned> Opcodes2;
ARMDecoderEmitter &Frontend;
CodeGenTarget Target;
- FilterChooser *FC;
+ ARMFilterChooser *FC;
TARGET_NAME_t TargetName;
};
-bool ARMDecoderEmitter::ARMDEBackend::populateInstruction(
- const CodeGenInstruction &CGI, TARGET_NAME_t TN) {
+bool ARMDecoderEmitter::
+ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI,
+ TARGET_NAME_t TN) {
const Record &Def = *CGI.TheDef;
const StringRef Name = Def.getName();
uint8_t Form = getByteField(Def, "Form");
@@ -1559,20 +1569,15 @@
// which is a better design and less fragile than the name matchings.
if (Bits.allInComplete()) return false;
+ // Ignore "asm parser only" instructions.
+ if (Def.getValueAsBit("isAsmParserOnly"))
+ return false;
+
if (TN == TARGET_ARM) {
- // FIXME: what about Int_MemBarrierV6 and Int_SyncBarrierV6?
- if ((Name != "Int_MemBarrierV7" && Name != "Int_SyncBarrierV7") &&
- Form == ARM_FORMAT_PSEUDO)
+ if (Form == ARM_FORMAT_PSEUDO)
return false;
if (thumbInstruction(Form))
return false;
- if (Name.find("CMPz") != std::string::npos /* ||
- Name.find("CMNz") != std::string::npos */)
- return false;
-
- // Ignore pseudo instructions.
- if (Name == "BXr9" || Name == "BMOVPCRX" || Name == "BMOVPCRXr9")
- return false;
// Tail calls are other patterns that generate existing instructions.
if (Name == "TCRETURNdi" || Name == "TCRETURNdiND" ||
@@ -1583,71 +1588,14 @@
Name == "MOVr_TC")
return false;
- // VLDMQ/VSTMQ can be hanlded with the more generic VLDMD/VSTMD.
- if (Name == "VLDMQ" || Name == "VLDMQ_UPD" ||
- Name == "VSTMQ" || Name == "VSTMQ_UPD")
+ // Delegate ADR disassembly to the more generic ADDri/SUBri instructions.
+ if (Name == "ADR")
return false;
//
// The following special cases are for conflict resolutions.
//
- // NEON NLdStFrm conflict resolutions:
- //
- // 1. Ignore suffix "odd" and "odd_UPD", prefer the "even" register-
- // numbered ones which have the same Asm format string.
- // 2. Ignore VST2d64_UPD, which conflicts with VST1q64_UPD.
- // 3. Ignore VLD2d64_UPD, which conflicts with VLD1q64_UPD.
- // 4. Ignore VLD1q[_UPD], which conflicts with VLD1q64[_UPD].
- // 5. Ignore VST1q[_UPD], which conflicts with VST1q64[_UPD].
- if (Name.endswith("odd") || Name.endswith("odd_UPD") ||
- Name == "VST2d64_UPD" || Name == "VLD2d64_UPD" ||
- Name == "VLD1q" || Name == "VLD1q_UPD" ||
- Name == "VST1q" || Name == "VST1q_UPD")
- return false;
-
- // RSCSri and RSCSrs set the 's' bit, but are not predicated. We are
- // better off using the generic RSCri and RSCrs instructions.
- if (Name == "RSCSri" || Name == "RSCSrs") return false;
-
- // MOVCCr, MOVCCs, MOVCCi, FCYPScc, FCYPDcc, FNEGScc, and FNEGDcc are used
- // in the compiler to implement conditional moves. We can ignore them in
- // favor of their more generic versions of instructions.
- // See also SDNode *ARMDAGToDAGISel::Select(SDValue Op).
- if (Name == "MOVCCr" || Name == "MOVCCs" || Name == "MOVCCi" ||
- Name == "FCPYScc" || Name == "FCPYDcc" ||
- Name == "FNEGScc" || Name == "FNEGDcc")
- return false;
-
- // Ditto for VMOVDcc, VMOVScc, VNEGDcc, and VNEGScc.
- if (Name == "VMOVDcc" || Name == "VMOVScc" || Name == "VNEGDcc" ||
- Name == "VNEGScc")
- return false;
-
- // Ignore the *_sfp instructions when decoding. They are used by the
- // compiler to implement scalar floating point operations using vector
- // operations in order to work around some performance issues.
- if (Name.find("_sfp") != std::string::npos) return false;
-
- // LDM_RET is a special case of LDM (Load Multiple) where the registers
- // loaded include the PC, causing a branch to a loaded address. Ignore
- // the LDM_RET instruction when decoding.
- if (Name == "LDM_RET") return false;
-
- // Bcc is in a more generic form than B. Ignore B when decoding.
- if (Name == "B") return false;
-
- // Ignore the non-Darwin BL instructions and the TPsoft (TLS) instruction.
- if (Name == "BL" || Name == "BL_pred" || Name == "BLX" || Name == "BX" ||
- Name == "TPsoft")
- return false;
-
- // Ignore VDUPf[d|q] instructions known to conflict with VDUP32[d-q] for
- // decoding. The instruction duplicates an element from an ARM core
- // register into every element of the destination vector. There is no
- // distinction between data types.
- if (Name == "VDUPfd" || Name == "VDUPfq") return false;
-
// A8-598: VEXT
// Vector Extract extracts elements from the bottom end of the second
// operand vector and the top end of the first, concatenates them and
@@ -1663,98 +1611,62 @@
if (Name == "VEXTd16" || Name == "VEXTd32" || Name == "VEXTdf" ||
Name == "VEXTq16" || Name == "VEXTq32" || Name == "VEXTqf")
return false;
-
- // Vector Reverse is similar to Vector Extract. There is no distinction
- // between data types, other than size.
- //
- // VREV64df is equivalent to VREV64d32.
- // VREV64qf is equivalent to VREV64q32.
- if (Name == "VREV64df" || Name == "VREV64qf") return false;
-
- // VDUPLNfd is equivalent to VDUPLN32d; VDUPfdf is specialized VDUPLN32d.
- // VDUPLNfq is equivalent to VDUPLN32q; VDUPfqf is specialized VDUPLN32q.
- // VLD1df is equivalent to VLD1d32.
- // VLD1qf is equivalent to VLD1q32.
- // VLD2d64 is equivalent to VLD1q64.
- // VST1df is equivalent to VST1d32.
- // VST1qf is equivalent to VST1q32.
- // VST2d64 is equivalent to VST1q64.
- if (Name == "VDUPLNfd" || Name == "VDUPfdf" ||
- Name == "VDUPLNfq" || Name == "VDUPfqf" ||
- Name == "VLD1df" || Name == "VLD1qf" || Name == "VLD2d64" ||
- Name == "VST1df" || Name == "VST1qf" || Name == "VST2d64")
- return false;
} else if (TN == TARGET_THUMB) {
if (!thumbInstruction(Form))
return false;
- // On Darwin R9 is call-clobbered. Ignore the non-Darwin counterparts.
- if (Name == "tBL" || Name == "tBLXi" || Name == "tBLXr")
+ // A8.6.25 BX. Use the generic tBX_Rm, ignore tBX_RET and tBX_RET_vararg.
+ if (Name == "tBX_RET" || Name == "tBX_RET_vararg")
return false;
- // Ignore the TPsoft (TLS) instructions, which conflict with tBLr9.
- if (Name == "tTPsoft" || Name == "t2TPsoft")
+ // Ignore tADR, prefer tADDrPCi.
+ if (Name == "tADR")
return false;
- // Ignore tLEApcrel and tLEApcrelJT, prefer tADDrPCi.
- if (Name == "tLEApcrel" || Name == "tLEApcrelJT")
- return false;
-
- // Ignore t2LEApcrel, prefer the generic t2ADD* for disassembly printing.
- if (Name == "t2LEApcrel")
+ // Delegate t2ADR disassembly to the more generic t2ADDri12/t2SUBri12
+ // instructions.
+ if (Name == "t2ADR")
return false;
// Ignore tADDrSP, tADDspr, and tPICADD, prefer the generic tADDhirr.
// Ignore t2SUBrSPs, prefer the t2SUB[S]r[r|s].
// Ignore t2ADDrSPs, prefer the t2ADD[S]r[r|s].
- // Ignore t2ADDrSPi/t2SUBrSPi, which have more generic couterparts.
- // Ignore t2ADDrSPi12/t2SUBrSPi12, which have more generic couterparts
if (Name == "tADDrSP" || Name == "tADDspr" || Name == "tPICADD" ||
- Name == "t2SUBrSPs" || Name == "t2ADDrSPs" ||
- Name == "t2ADDrSPi" || Name == "t2SUBrSPi" ||
- Name == "t2ADDrSPi12" || Name == "t2SUBrSPi12")
+ Name == "t2SUBrSPs" || Name == "t2ADDrSPs")
+ return false;
+
+ // FIXME: Use ldr.n to work around a Darwin assembler bug.
+ // Introduce a workaround with tLDRpciDIS opcode.
+ if (Name == "tLDRpci")
return false;
// Ignore t2LDRDpci, prefer the generic t2LDRDi8, t2LDRD_PRE, t2LDRD_POST.
if (Name == "t2LDRDpci")
return false;
- // Ignore t2TBB, t2TBH and prefer the generic t2TBBgen, t2TBHgen.
- if (Name == "t2TBB" || Name == "t2TBH")
- return false;
-
// Resolve conflicts:
//
- // tBfar conflicts with tBLr9
- // tCMNz conflicts with tCMN (with assembly format strings being equal)
- // tPOP_RET/t2LDM_RET conflict with tPOP/t2LDM (ditto)
+ // t2LDMIA_RET conflict with t2LDM (ditto)
// tMOVCCi conflicts with tMOVi8
// tMOVCCr conflicts with tMOVgpr2gpr
- // tBR_JTr conflicts with tBRIND
- // tSpill conflicts with tSTRspi
// tLDRcp conflicts with tLDRspi
- // tRestore conflicts with tLDRspi
- // t2LEApcrelJT conflicts with t2LEApcrel
- if (Name == "tBfar" ||
- /* Name == "tCMNz" || */ Name == "tCMPzi8" || Name == "tCMPzr" ||
- Name == "tCMPzhir" || /* Name == "t2CMNzrr" || Name == "t2CMNzrs" ||
- Name == "t2CMNzri" || */ Name == "t2CMPzrr" || Name == "t2CMPzrs" ||
- Name == "t2CMPzri" || Name == "tPOP_RET" || Name == "t2LDM_RET" ||
- Name == "tMOVCCi" || Name == "tMOVCCr" || Name == "tBR_JTr" ||
- Name == "tSpill" || Name == "tLDRcp" || Name == "tRestore" ||
- Name == "t2LEApcrelJT")
+ // t2MOVCCi16 conflicts with tMOVi16
+ if (Name == "t2LDMIA_RET" ||
+ Name == "tMOVCCi" || Name == "tMOVCCr" ||
+ Name == "tLDRcp" ||
+ Name == "t2MOVCCi16")
return false;
}
- // Dumps the instruction encoding format.
- switch (TargetName) {
- case TARGET_ARM:
- case TARGET_THUMB:
- DEBUG(errs() << Name << " " << stringForARMFormat((ARMFormat)Form));
- break;
- }
-
DEBUG({
+ // Dumps the instruction encoding format.
+ switch (TargetName) {
+ case TARGET_ARM:
+ case TARGET_THUMB:
+ errs() << Name << " " << stringForARMFormat((ARMFormat)Form);
+ break;
+ }
+
errs() << " ";
// Dumps the instruction encoding bits.
@@ -1763,8 +1675,8 @@
errs() << '\n';
// Dumps the list of operand info.
- for (unsigned i = 0, e = CGI.OperandList.size(); i != e; ++i) {
- CodeGenInstruction::OperandInfo Info = CGI.OperandList[i];
+ for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) {
+ const CGIOperandList::OperandInfo &Info = CGI.Operands[i];
const std::string &OperandName = Info.Name;
const Record &OperandDef = *Info.Rec;
@@ -1778,32 +1690,20 @@
void ARMDecoderEmitter::ARMDEBackend::populateInstructions() {
getInstructionsByEnumValue(NumberedInstructions);
- uint16_t numUIDs = NumberedInstructions.size();
- uint16_t uid;
-
- const char *instClass = NULL;
-
- switch (TargetName) {
- case TARGET_ARM:
- instClass = "InstARM";
- break;
- default:
- assert(0 && "Unreachable code!");
- }
-
- for (uid = 0; uid < numUIDs; uid++) {
- // filter out intrinsics
- if (!NumberedInstructions[uid]->TheDef->isSubClassOf(instClass))
- continue;
-
- if (populateInstruction(*NumberedInstructions[uid], TargetName))
- Opcodes.push_back(uid);
- }
-
- // Special handling for the ARM chip, which supports two modes of execution.
- // This branch handles the Thumb opcodes.
+ unsigned numUIDs = NumberedInstructions.size();
if (TargetName == TARGET_ARM) {
- for (uid = 0; uid < numUIDs; uid++) {
+ for (unsigned uid = 0; uid < numUIDs; uid++) {
+ // filter out intrinsics
+ if (!NumberedInstructions[uid]->TheDef->isSubClassOf("InstARM"))
+ continue;
+
+ if (populateInstruction(*NumberedInstructions[uid], TargetName))
+ Opcodes.push_back(uid);
+ }
+
+ // Special handling for the ARM chip, which supports two modes of execution.
+ // This branch handles the Thumb opcodes.
+ for (unsigned uid = 0; uid < numUIDs; uid++) {
// filter out intrinsics
if (!NumberedInstructions[uid]->TheDef->isSubClassOf("InstARM")
&& !NumberedInstructions[uid]->TheDef->isSubClassOf("InstThumb"))
@@ -1812,6 +1712,18 @@
if (populateInstruction(*NumberedInstructions[uid], TARGET_THUMB))
Opcodes2.push_back(uid);
}
+
+ return;
+ }
+
+ // For other targets.
+ for (unsigned uid = 0; uid < numUIDs; uid++) {
+ Record *R = NumberedInstructions[uid]->TheDef;
+ if (R->getValueAsString("Namespace") == "TargetOpcode")
+ continue;
+
+ if (populateInstruction(*NumberedInstructions[uid], TargetName))
+ Opcodes.push_back(uid);
}
}
@@ -1826,25 +1738,25 @@
assert(0 && "Unreachable code!");
}
- o << "#include \"llvm/System/DataTypes.h\"\n";
+ o << "#include \"llvm/Support/DataTypes.h\"\n";
o << "#include <assert.h>\n";
o << '\n';
o << "namespace llvm {\n\n";
- FilterChooser::setTargetName(TargetName);
+ ARMFilterChooser::setTargetName(TargetName);
switch (TargetName) {
case TARGET_ARM: {
// Emit common utility and ARM ISA decoder.
- FC = new FilterChooser(NumberedInstructions, Opcodes);
+ FC = new ARMFilterChooser(NumberedInstructions, Opcodes);
// Reset indentation level.
unsigned Indentation = 0;
FC->emitTop(o, Indentation);
delete FC;
// Emit Thumb ISA decoder as well.
- FilterChooser::setTargetName(TARGET_THUMB);
- FC = new FilterChooser(NumberedInstructions, Opcodes2);
+ ARMFilterChooser::setTargetName(TARGET_THUMB);
+ FC = new ARMFilterChooser(NumberedInstructions, Opcodes2);
// Reset indentation level.
Indentation = 0;
FC->emitBot(o, Indentation);
@@ -1863,7 +1775,7 @@
void ARMDecoderEmitter::initBackend()
{
- Backend = new ARMDEBackend(*this);
+ Backend = new ARMDEBackend(*this, Records);
}
void ARMDecoderEmitter::run(raw_ostream &o)
diff --git a/src/LLVM/utils/TableGen/ARMDecoderEmitter.h b/src/LLVM/utils/TableGen/ARMDecoderEmitter.h
index 571a947..486f899 100644
--- a/src/LLVM/utils/TableGen/ARMDecoderEmitter.h
+++ b/src/LLVM/utils/TableGen/ARMDecoderEmitter.h
@@ -15,9 +15,8 @@
#ifndef ARMDECODEREMITTER_H
#define ARMDECODEREMITTER_H
-#include "TableGenBackend.h"
-
-#include "llvm/System/DataTypes.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/TableGen/TableGenBackend.h"
namespace llvm {
diff --git a/src/LLVM/utils/TableGen/AsmMatcherEmitter.cpp b/src/LLVM/utils/TableGen/AsmMatcherEmitter.cpp
index 08a430d..8b86c23 100644
--- a/src/LLVM/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/src/LLVM/utils/TableGen/AsmMatcherEmitter.cpp
@@ -8,7 +8,11 @@
//===----------------------------------------------------------------------===//
//
// This tablegen backend emits a target specifier matcher for converting parsed
-// assembly operands in the MCInst structures.
+// assembly operands in the MCInst structures. It also emits a matcher for
+// custom operand parsing.
+//
+// Converting assembly operands into MCInst structures
+// ---------------------------------------------------
//
// The input to the target specific matcher is a list of literal tokens and
// operands. The target specific parser should generally eliminate any syntax
@@ -20,7 +24,7 @@
// Some example inputs, for X86:
// 'addl' (immediate ...) (register ...)
// 'add' (immediate ...) (memory ...)
-// 'call' '*' %epc
+// 'call' '*' %epc
//
// The assembly matcher is responsible for converting this input into a precise
// machine instruction (i.e., an instruction with a well defined encoding). This
@@ -63,26 +67,48 @@
// In addition, the subset relation amongst classes induces a partial order
// on such tuples, which we use to resolve ambiguities.
//
-// FIXME: What do we do if a crazy case shows up where this is the wrong
-// resolution?
-//
// 2. The input can now be treated as a tuple of classes (static tokens are
// simple singleton sets). Each such tuple should generally map to a single
// instruction (we currently ignore cases where this isn't true, whee!!!),
// which we can emit a simple matcher for.
//
+// Custom Operand Parsing
+// ----------------------
+//
+// Some targets need a custom way to parse operands, some specific instructions
+// can contain arguments that can represent processor flags and other kinds of
+// identifiers that need to be mapped to specific valeus in the final encoded
+// instructions. The target specific custom operand parsing works in the
+// following way:
+//
+// 1. A operand match table is built, each entry contains a mnemonic, an
+// operand class, a mask for all operand positions for that same
+// class/mnemonic and target features to be checked while trying to match.
+//
+// 2. The operand matcher will try every possible entry with the same
+// mnemonic and will check if the target feature for this mnemonic also
+// matches. After that, if the operand to be matched has its index
+// present in the mask, a successful match occurs. Otherwise, fallback
+// to the regular operand parsing.
+//
+// 3. For a match success, each operand class that has a 'ParserMethod'
+// becomes part of a switch from where the custom method is called.
+//
//===----------------------------------------------------------------------===//
#include "AsmMatcherEmitter.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "StringMatcher.h"
#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
-#include <list>
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
#include <map>
#include <set>
using namespace llvm;
@@ -91,186 +117,8 @@
MatchPrefix("match-prefix", cl::init(""),
cl::desc("Only match instructions with the given prefix"));
-/// FlattenVariants - Flatten an .td file assembly string by selecting the
-/// variant at index \arg N.
-static std::string FlattenVariants(const std::string &AsmString,
- unsigned N) {
- StringRef Cur = AsmString;
- std::string Res = "";
-
- for (;;) {
- // Find the start of the next variant string.
- size_t VariantsStart = 0;
- for (size_t e = Cur.size(); VariantsStart != e; ++VariantsStart)
- if (Cur[VariantsStart] == '{' &&
- (VariantsStart == 0 || (Cur[VariantsStart-1] != '$' &&
- Cur[VariantsStart-1] != '\\')))
- break;
-
- // Add the prefix to the result.
- Res += Cur.slice(0, VariantsStart);
- if (VariantsStart == Cur.size())
- break;
-
- ++VariantsStart; // Skip the '{'.
-
- // Scan to the end of the variants string.
- size_t VariantsEnd = VariantsStart;
- unsigned NestedBraces = 1;
- for (size_t e = Cur.size(); VariantsEnd != e; ++VariantsEnd) {
- if (Cur[VariantsEnd] == '}' && Cur[VariantsEnd-1] != '\\') {
- if (--NestedBraces == 0)
- break;
- } else if (Cur[VariantsEnd] == '{')
- ++NestedBraces;
- }
-
- // Select the Nth variant (or empty).
- StringRef Selection = Cur.slice(VariantsStart, VariantsEnd);
- for (unsigned i = 0; i != N; ++i)
- Selection = Selection.split('|').second;
- Res += Selection.split('|').first;
-
- assert(VariantsEnd != Cur.size() &&
- "Unterminated variants in assembly string!");
- Cur = Cur.substr(VariantsEnd + 1);
- }
-
- return Res;
-}
-
-/// TokenizeAsmString - Tokenize a simplified assembly string.
-static void TokenizeAsmString(StringRef AsmString,
- SmallVectorImpl<StringRef> &Tokens) {
- unsigned Prev = 0;
- bool InTok = true;
- for (unsigned i = 0, e = AsmString.size(); i != e; ++i) {
- switch (AsmString[i]) {
- case '[':
- case ']':
- case '*':
- case '!':
- case ' ':
- case '\t':
- case ',':
- if (InTok) {
- Tokens.push_back(AsmString.slice(Prev, i));
- InTok = false;
- }
- if (!isspace(AsmString[i]) && AsmString[i] != ',')
- Tokens.push_back(AsmString.substr(i, 1));
- Prev = i + 1;
- break;
-
- case '\\':
- if (InTok) {
- Tokens.push_back(AsmString.slice(Prev, i));
- InTok = false;
- }
- ++i;
- assert(i != AsmString.size() && "Invalid quoted character");
- Tokens.push_back(AsmString.substr(i, 1));
- Prev = i + 1;
- break;
-
- case '$': {
- // If this isn't "${", treat like a normal token.
- if (i + 1 == AsmString.size() || AsmString[i + 1] != '{') {
- if (InTok) {
- Tokens.push_back(AsmString.slice(Prev, i));
- InTok = false;
- }
- Prev = i;
- break;
- }
-
- if (InTok) {
- Tokens.push_back(AsmString.slice(Prev, i));
- InTok = false;
- }
-
- StringRef::iterator End =
- std::find(AsmString.begin() + i, AsmString.end(), '}');
- assert(End != AsmString.end() && "Missing brace in operand reference!");
- size_t EndPos = End - AsmString.begin();
- Tokens.push_back(AsmString.slice(i, EndPos+1));
- Prev = EndPos + 1;
- i = EndPos;
- break;
- }
-
- default:
- InTok = true;
- }
- }
- if (InTok && Prev != AsmString.size())
- Tokens.push_back(AsmString.substr(Prev));
-}
-
-static bool IsAssemblerInstruction(StringRef Name,
- const CodeGenInstruction &CGI,
- const SmallVectorImpl<StringRef> &Tokens) {
- // Ignore "codegen only" instructions.
- if (CGI.TheDef->getValueAsBit("isCodeGenOnly"))
- return false;
-
- // Ignore pseudo ops.
- //
- // FIXME: This is a hack; can we convert these instructions to set the
- // "codegen only" bit instead?
- if (const RecordVal *Form = CGI.TheDef->getValue("Form"))
- if (Form->getValue()->getAsString() == "Pseudo")
- return false;
-
- // Ignore "Int_*" and "*_Int" instructions, which are internal aliases.
- //
- // FIXME: This is a total hack.
- if (StringRef(Name).startswith("Int_") || StringRef(Name).endswith("_Int"))
- return false;
-
- // Ignore instructions with no .s string.
- //
- // FIXME: What are these?
- if (CGI.AsmString.empty())
- return false;
-
- // FIXME: Hack; ignore any instructions with a newline in them.
- if (std::find(CGI.AsmString.begin(),
- CGI.AsmString.end(), '\n') != CGI.AsmString.end())
- return false;
-
- // Ignore instructions with attributes, these are always fake instructions for
- // simplifying codegen.
- //
- // FIXME: Is this true?
- //
- // Also, check for instructions which reference the operand multiple times;
- // this implies a constraint we would not honor.
- std::set<std::string> OperandNames;
- for (unsigned i = 1, e = Tokens.size(); i < e; ++i) {
- if (Tokens[i][0] == '$' &&
- std::find(Tokens[i].begin(),
- Tokens[i].end(), ':') != Tokens[i].end()) {
- DEBUG({
- errs() << "warning: '" << Name << "': "
- << "ignoring instruction; operand with attribute '"
- << Tokens[i] << "'\n";
- });
- return false;
- }
-
- if (Tokens[i][0] == '$' && !OperandNames.insert(Tokens[i]).second) {
- std::string Err = "'" + Name.str() + "': " +
- "invalid assembler instruction; tied operand '" + Tokens[i].str() + "'";
- throw TGError(CGI.TheDef->getLoc(), Err);
- }
- }
-
- return true;
-}
-
namespace {
-
+class AsmMatcherInfo;
struct SubtargetFeatureInfo;
/// ClassInfo - Helper class for storing the information about a particular
@@ -320,6 +168,10 @@
/// MCInst; this is not valid for Token or register kinds.
std::string RenderMethod;
+ /// ParserMethod - The name of the operand method to do a target specific
+ /// parsing on the operand.
+ std::string ParserMethod;
+
/// For register classes, the records for all the registers in this class.
std::set<Record*> Registers;
@@ -349,7 +201,7 @@
std::set<Record*> Tmp;
std::insert_iterator< std::set<Record*> > II(Tmp, Tmp.begin());
- std::set_intersection(Registers.begin(), Registers.end(),
+ std::set_intersection(Registers.begin(), Registers.end(),
RHS.Registers.begin(), RHS.Registers.end(),
II);
@@ -369,11 +221,11 @@
const ClassInfo *RHSRoot = &RHS;
while (!RHSRoot->SuperClasses.empty())
RHSRoot = RHSRoot->SuperClasses.front();
-
+
return Root == RHSRoot;
}
- /// isSubsetOf - Test whether this class is a subset of \arg RHS;
+ /// isSubsetOf - Test whether this class is a subset of \arg RHS;
bool isSubsetOf(const ClassInfo &RHS) const {
// This is a subset of RHS if it is the same class...
if (this == &RHS)
@@ -407,7 +259,7 @@
return ValueName < RHS.ValueName;
default:
- // This class preceeds the RHS if it is a proper subset of the RHS.
+ // This class precedes the RHS if it is a proper subset of the RHS.
if (isSubsetOf(RHS))
return true;
if (RHS.isSubsetOf(*this))
@@ -419,32 +271,131 @@
}
};
-/// InstructionInfo - Helper class for storing the necessary information for an
-/// instruction which is capable of being matched.
-struct InstructionInfo {
- struct Operand {
+/// MatchableInfo - Helper class for storing the necessary information for an
+/// instruction or alias which is capable of being matched.
+struct MatchableInfo {
+ struct AsmOperand {
+ /// Token - This is the token that the operand came from.
+ StringRef Token;
+
/// The unique class instance this operand should match.
ClassInfo *Class;
- /// The original operand this corresponds to, if any.
- const CodeGenInstruction::OperandInfo *OperandInfo;
+ /// The operand name this is, if anything.
+ StringRef SrcOpName;
+
+ /// The suboperand index within SrcOpName, or -1 for the entire operand.
+ int SubOpIdx;
+
+ explicit AsmOperand(StringRef T) : Token(T), Class(0), SubOpIdx(-1) {}
};
- /// InstrName - The target name for this instruction.
- std::string InstrName;
+ /// ResOperand - This represents a single operand in the result instruction
+ /// generated by the match. In cases (like addressing modes) where a single
+ /// assembler operand expands to multiple MCOperands, this represents the
+ /// single assembler operand, not the MCOperand.
+ struct ResOperand {
+ enum {
+ /// RenderAsmOperand - This represents an operand result that is
+ /// generated by calling the render method on the assembly operand. The
+ /// corresponding AsmOperand is specified by AsmOperandNum.
+ RenderAsmOperand,
- /// Instr - The instruction this matches.
- const CodeGenInstruction *Instr;
+ /// TiedOperand - This represents a result operand that is a duplicate of
+ /// a previous result operand.
+ TiedOperand,
+
+ /// ImmOperand - This represents an immediate value that is dumped into
+ /// the operand.
+ ImmOperand,
+
+ /// RegOperand - This represents a fixed register that is dumped in.
+ RegOperand
+ } Kind;
+
+ union {
+ /// This is the operand # in the AsmOperands list that this should be
+ /// copied from.
+ unsigned AsmOperandNum;
+
+ /// TiedOperandNum - This is the (earlier) result operand that should be
+ /// copied from.
+ unsigned TiedOperandNum;
+
+ /// ImmVal - This is the immediate value added to the instruction.
+ int64_t ImmVal;
+
+ /// Register - This is the register record.
+ Record *Register;
+ };
+
+ /// MINumOperands - The number of MCInst operands populated by this
+ /// operand.
+ unsigned MINumOperands;
+
+ static ResOperand getRenderedOp(unsigned AsmOpNum, unsigned NumOperands) {
+ ResOperand X;
+ X.Kind = RenderAsmOperand;
+ X.AsmOperandNum = AsmOpNum;
+ X.MINumOperands = NumOperands;
+ return X;
+ }
+
+ static ResOperand getTiedOp(unsigned TiedOperandNum) {
+ ResOperand X;
+ X.Kind = TiedOperand;
+ X.TiedOperandNum = TiedOperandNum;
+ X.MINumOperands = 1;
+ return X;
+ }
+
+ static ResOperand getImmOp(int64_t Val) {
+ ResOperand X;
+ X.Kind = ImmOperand;
+ X.ImmVal = Val;
+ X.MINumOperands = 1;
+ return X;
+ }
+
+ static ResOperand getRegOp(Record *Reg) {
+ ResOperand X;
+ X.Kind = RegOperand;
+ X.Register = Reg;
+ X.MINumOperands = 1;
+ return X;
+ }
+ };
+
+ /// TheDef - This is the definition of the instruction or InstAlias that this
+ /// matchable came from.
+ Record *const TheDef;
+
+ /// DefRec - This is the definition that it came from.
+ PointerUnion<const CodeGenInstruction*, const CodeGenInstAlias*> DefRec;
+
+ const CodeGenInstruction *getResultInst() const {
+ if (DefRec.is<const CodeGenInstruction*>())
+ return DefRec.get<const CodeGenInstruction*>();
+ return DefRec.get<const CodeGenInstAlias*>()->ResultInst;
+ }
+
+ /// ResOperands - This is the operand list that should be built for the result
+ /// MCInst.
+ std::vector<ResOperand> ResOperands;
/// AsmString - The assembly string for this instruction (with variants
- /// removed).
+ /// removed), e.g. "movsx $src, $dst".
std::string AsmString;
- /// Tokens - The tokenized assembly pattern that this instruction matches.
- SmallVector<StringRef, 4> Tokens;
+ /// Mnemonic - This is the first token of the matched instruction, its
+ /// mnemonic.
+ StringRef Mnemonic;
- /// Operands - The operands that this instruction matches.
- SmallVector<Operand, 4> Operands;
+ /// AsmOperands - The textual operands that this instruction matches,
+ /// annotated with a class and where in the OperandList they were defined.
+ /// This directly corresponds to the tokenized AsmString after the mnemonic is
+ /// removed.
+ SmallVector<AsmOperand, 4> AsmOperands;
/// Predicates - The required subtarget features to match this instruction.
SmallVector<SubtargetFeatureInfo*, 4> RequiredFeatures;
@@ -454,29 +405,79 @@
/// function.
std::string ConversionFnKind;
- /// operator< - Compare two instructions.
- bool operator<(const InstructionInfo &RHS) const {
- if (Operands.size() != RHS.Operands.size())
- return Operands.size() < RHS.Operands.size();
+ MatchableInfo(const CodeGenInstruction &CGI)
+ : TheDef(CGI.TheDef), DefRec(&CGI), AsmString(CGI.AsmString) {
+ }
+
+ MatchableInfo(const CodeGenInstAlias *Alias)
+ : TheDef(Alias->TheDef), DefRec(Alias), AsmString(Alias->AsmString) {
+ }
+
+ void Initialize(const AsmMatcherInfo &Info,
+ SmallPtrSet<Record*, 16> &SingletonRegisters);
+
+ /// Validate - Return true if this matchable is a valid thing to match against
+ /// and perform a bunch of validity checking.
+ bool Validate(StringRef CommentDelimiter, bool Hack) const;
+
+ /// getSingletonRegisterForAsmOperand - If the specified token is a singleton
+ /// register, return the Record for it, otherwise return null.
+ Record *getSingletonRegisterForAsmOperand(unsigned i,
+ const AsmMatcherInfo &Info) const;
+
+ /// FindAsmOperand - Find the AsmOperand with the specified name and
+ /// suboperand index.
+ int FindAsmOperand(StringRef N, int SubOpIdx) const {
+ for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i)
+ if (N == AsmOperands[i].SrcOpName &&
+ SubOpIdx == AsmOperands[i].SubOpIdx)
+ return i;
+ return -1;
+ }
+
+ /// FindAsmOperandNamed - Find the first AsmOperand with the specified name.
+ /// This does not check the suboperand index.
+ int FindAsmOperandNamed(StringRef N) const {
+ for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i)
+ if (N == AsmOperands[i].SrcOpName)
+ return i;
+ return -1;
+ }
+
+ void BuildInstructionResultOperands();
+ void BuildAliasResultOperands();
+
+ /// operator< - Compare two matchables.
+ bool operator<(const MatchableInfo &RHS) const {
+ // The primary comparator is the instruction mnemonic.
+ if (Mnemonic != RHS.Mnemonic)
+ return Mnemonic < RHS.Mnemonic;
+
+ if (AsmOperands.size() != RHS.AsmOperands.size())
+ return AsmOperands.size() < RHS.AsmOperands.size();
// Compare lexicographically by operand. The matcher validates that other
- // orderings wouldn't be ambiguous using \see CouldMatchAmiguouslyWith().
- for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
- if (*Operands[i].Class < *RHS.Operands[i].Class)
+ // orderings wouldn't be ambiguous using \see CouldMatchAmbiguouslyWith().
+ for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
+ if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class)
return true;
- if (*RHS.Operands[i].Class < *Operands[i].Class)
+ if (*RHS.AsmOperands[i].Class < *AsmOperands[i].Class)
return false;
}
return false;
}
- /// CouldMatchAmiguouslyWith - Check whether this instruction could
+ /// CouldMatchAmbiguouslyWith - Check whether this matchable could
/// ambiguously match the same set of operands as \arg RHS (without being a
/// strictly superior match).
- bool CouldMatchAmiguouslyWith(const InstructionInfo &RHS) {
+ bool CouldMatchAmbiguouslyWith(const MatchableInfo &RHS) {
+ // The primary comparator is the instruction mnemonic.
+ if (Mnemonic != RHS.Mnemonic)
+ return false;
+
// The number of operands is unambiguous.
- if (Operands.size() != RHS.Operands.size())
+ if (AsmOperands.size() != RHS.AsmOperands.size())
return false;
// Otherwise, make sure the ordering of the two instructions is unambiguous
@@ -485,29 +486,31 @@
// Tokens and operand kinds are unambiguous (assuming a correct target
// specific parser).
- for (unsigned i = 0, e = Operands.size(); i != e; ++i)
- if (Operands[i].Class->Kind != RHS.Operands[i].Class->Kind ||
- Operands[i].Class->Kind == ClassInfo::Token)
- if (*Operands[i].Class < *RHS.Operands[i].Class ||
- *RHS.Operands[i].Class < *Operands[i].Class)
+ for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i)
+ if (AsmOperands[i].Class->Kind != RHS.AsmOperands[i].Class->Kind ||
+ AsmOperands[i].Class->Kind == ClassInfo::Token)
+ if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class ||
+ *RHS.AsmOperands[i].Class < *AsmOperands[i].Class)
return false;
-
+
// Otherwise, this operand could commute if all operands are equivalent, or
// there is a pair of operands that compare less than and a pair that
// compare greater than.
bool HasLT = false, HasGT = false;
- for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
- if (*Operands[i].Class < *RHS.Operands[i].Class)
+ for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
+ if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class)
HasLT = true;
- if (*RHS.Operands[i].Class < *Operands[i].Class)
+ if (*RHS.AsmOperands[i].Class < *AsmOperands[i].Class)
HasGT = true;
}
return !(HasLT ^ HasGT);
}
-public:
void dump();
+
+private:
+ void TokenizeAsmString(const AsmMatcherInfo &Info);
};
/// SubtargetFeatureInfo - Helper class for storing information on a subtarget
@@ -519,26 +522,52 @@
/// \brief An unique index assigned to represent this feature.
unsigned Index;
+ SubtargetFeatureInfo(Record *D, unsigned Idx) : TheDef(D), Index(Idx) {}
+
/// \brief The name of the enumerated constant identifying this feature.
- std::string EnumName;
+ std::string getEnumName() const {
+ return "Feature_" + TheDef->getName();
+ }
};
+struct OperandMatchEntry {
+ unsigned OperandMask;
+ MatchableInfo* MI;
+ ClassInfo *CI;
+
+ static OperandMatchEntry Create(MatchableInfo* mi, ClassInfo *ci,
+ unsigned opMask) {
+ OperandMatchEntry X;
+ X.OperandMask = opMask;
+ X.CI = ci;
+ X.MI = mi;
+ return X;
+ }
+};
+
+
class AsmMatcherInfo {
public:
+ /// Tracked Records
+ RecordKeeper &Records;
+
/// The tablegen AsmParser record.
Record *AsmParser;
- /// The AsmParser "CommentDelimiter" value.
- std::string CommentDelimiter;
+ /// Target - The target information.
+ CodeGenTarget &Target;
/// The AsmParser "RegisterPrefix" value.
std::string RegisterPrefix;
/// The classes which are needed for matching.
std::vector<ClassInfo*> Classes;
-
- /// The information on the instruction to match.
- std::vector<InstructionInfo*> Instructions;
+
+ /// The information on the matchables to match.
+ std::vector<MatchableInfo*> Matchables;
+
+ /// Info for custom matching operands by user defined methods.
+ std::vector<OperandMatchEntry> OperandMatchInfo;
/// Map of Register records to their class information.
std::map<Record*, ClassInfo*> RegisterClasses;
@@ -561,108 +590,265 @@
ClassInfo *getTokenClass(StringRef Token);
/// getOperandClass - Lookup or create the class for the given operand.
- ClassInfo *getOperandClass(StringRef Token,
- const CodeGenInstruction::OperandInfo &OI);
-
- /// getSubtargetFeature - Lookup or create the subtarget feature info for the
- /// given operand.
- SubtargetFeatureInfo *getSubtargetFeature(Record *Def) {
- assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!");
-
- SubtargetFeatureInfo *&Entry = SubtargetFeatures[Def];
- if (!Entry) {
- Entry = new SubtargetFeatureInfo;
- Entry->TheDef = Def;
- Entry->Index = SubtargetFeatures.size() - 1;
- Entry->EnumName = "Feature_" + Def->getName();
- assert(Entry->Index < 32 && "Too many subtarget features!");
- }
-
- return Entry;
- }
+ ClassInfo *getOperandClass(const CGIOperandList::OperandInfo &OI,
+ int SubOpIdx = -1);
/// BuildRegisterClasses - Build the ClassInfo* instances for register
/// classes.
- void BuildRegisterClasses(CodeGenTarget &Target,
- std::set<std::string> &SingletonRegisterNames);
+ void BuildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters);
/// BuildOperandClasses - Build the ClassInfo* instances for user defined
/// operand classes.
- void BuildOperandClasses(CodeGenTarget &Target);
+ void BuildOperandClasses();
+
+ void BuildInstructionOperandReference(MatchableInfo *II, StringRef OpName,
+ unsigned AsmOpIdx);
+ void BuildAliasOperandReference(MatchableInfo *II, StringRef OpName,
+ MatchableInfo::AsmOperand &Op);
public:
- AsmMatcherInfo(Record *_AsmParser);
+ AsmMatcherInfo(Record *AsmParser,
+ CodeGenTarget &Target,
+ RecordKeeper &Records);
/// BuildInfo - Construct the various tables used during matching.
- void BuildInfo(CodeGenTarget &Target);
+ void BuildInfo();
+
+ /// BuildOperandMatchInfo - Build the necessary information to handle user
+ /// defined operand parsing methods.
+ void BuildOperandMatchInfo();
+
+ /// getSubtargetFeature - Lookup or create the subtarget feature info for the
+ /// given operand.
+ SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const {
+ assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!");
+ std::map<Record*, SubtargetFeatureInfo*>::const_iterator I =
+ SubtargetFeatures.find(Def);
+ return I == SubtargetFeatures.end() ? 0 : I->second;
+ }
+
+ RecordKeeper &getRecords() const {
+ return Records;
+ }
};
}
-void InstructionInfo::dump() {
- errs() << InstrName << " -- " << "flattened:\"" << AsmString << '\"'
- << ", tokens:[";
- for (unsigned i = 0, e = Tokens.size(); i != e; ++i) {
- errs() << Tokens[i];
- if (i + 1 != e)
- errs() << ", ";
- }
- errs() << "]\n";
+void MatchableInfo::dump() {
+ errs() << TheDef->getName() << " -- " << "flattened:\"" << AsmString <<"\"\n";
- for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
- Operand &Op = Operands[i];
+ for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
+ AsmOperand &Op = AsmOperands[i];
errs() << " op[" << i << "] = " << Op.Class->ClassName << " - ";
- if (Op.Class->Kind == ClassInfo::Token) {
- errs() << '\"' << Tokens[i] << "\"\n";
- continue;
- }
-
- if (!Op.OperandInfo) {
- errs() << "(singleton register)\n";
- continue;
- }
-
- const CodeGenInstruction::OperandInfo &OI = *Op.OperandInfo;
- errs() << OI.Name << " " << OI.Rec->getName()
- << " (" << OI.MIOperandNo << ", " << OI.MINumOperands << ")\n";
+ errs() << '\"' << Op.Token << "\"\n";
}
}
+void MatchableInfo::Initialize(const AsmMatcherInfo &Info,
+ SmallPtrSet<Record*, 16> &SingletonRegisters) {
+ // TODO: Eventually support asmparser for Variant != 0.
+ AsmString = CodeGenInstruction::FlattenAsmStringVariants(AsmString, 0);
+
+ TokenizeAsmString(Info);
+
+ // Compute the require features.
+ std::vector<Record*> Predicates =TheDef->getValueAsListOfDefs("Predicates");
+ for (unsigned i = 0, e = Predicates.size(); i != e; ++i)
+ if (SubtargetFeatureInfo *Feature =
+ Info.getSubtargetFeature(Predicates[i]))
+ RequiredFeatures.push_back(Feature);
+
+ // Collect singleton registers, if used.
+ for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
+ if (Record *Reg = getSingletonRegisterForAsmOperand(i, Info))
+ SingletonRegisters.insert(Reg);
+ }
+}
+
+/// TokenizeAsmString - Tokenize a simplified assembly string.
+void MatchableInfo::TokenizeAsmString(const AsmMatcherInfo &Info) {
+ StringRef String = AsmString;
+ unsigned Prev = 0;
+ bool InTok = true;
+ for (unsigned i = 0, e = String.size(); i != e; ++i) {
+ switch (String[i]) {
+ case '[':
+ case ']':
+ case '*':
+ case '!':
+ case ' ':
+ case '\t':
+ case ',':
+ if (InTok) {
+ AsmOperands.push_back(AsmOperand(String.slice(Prev, i)));
+ InTok = false;
+ }
+ if (!isspace(String[i]) && String[i] != ',')
+ AsmOperands.push_back(AsmOperand(String.substr(i, 1)));
+ Prev = i + 1;
+ break;
+
+ case '\\':
+ if (InTok) {
+ AsmOperands.push_back(AsmOperand(String.slice(Prev, i)));
+ InTok = false;
+ }
+ ++i;
+ assert(i != String.size() && "Invalid quoted character");
+ AsmOperands.push_back(AsmOperand(String.substr(i, 1)));
+ Prev = i + 1;
+ break;
+
+ case '$': {
+ if (InTok) {
+ AsmOperands.push_back(AsmOperand(String.slice(Prev, i)));
+ InTok = false;
+ }
+
+ // If this isn't "${", treat like a normal token.
+ if (i + 1 == String.size() || String[i + 1] != '{') {
+ Prev = i;
+ break;
+ }
+
+ StringRef::iterator End = std::find(String.begin() + i, String.end(),'}');
+ assert(End != String.end() && "Missing brace in operand reference!");
+ size_t EndPos = End - String.begin();
+ AsmOperands.push_back(AsmOperand(String.slice(i, EndPos+1)));
+ Prev = EndPos + 1;
+ i = EndPos;
+ break;
+ }
+
+ case '.':
+ if (InTok)
+ AsmOperands.push_back(AsmOperand(String.slice(Prev, i)));
+ Prev = i;
+ InTok = true;
+ break;
+
+ default:
+ InTok = true;
+ }
+ }
+ if (InTok && Prev != String.size())
+ AsmOperands.push_back(AsmOperand(String.substr(Prev)));
+
+ // The first token of the instruction is the mnemonic, which must be a
+ // simple string, not a $foo variable or a singleton register.
+ assert(!AsmOperands.empty() && "Instruction has no tokens?");
+ Mnemonic = AsmOperands[0].Token;
+ if (Mnemonic[0] == '$' || getSingletonRegisterForAsmOperand(0, Info))
+ throw TGError(TheDef->getLoc(),
+ "Invalid instruction mnemonic '" + Mnemonic.str() + "'!");
+
+ // Remove the first operand, it is tracked in the mnemonic field.
+ AsmOperands.erase(AsmOperands.begin());
+}
+
+bool MatchableInfo::Validate(StringRef CommentDelimiter, bool Hack) const {
+ // Reject matchables with no .s string.
+ if (AsmString.empty())
+ throw TGError(TheDef->getLoc(), "instruction with empty asm string");
+
+ // Reject any matchables with a newline in them, they should be marked
+ // isCodeGenOnly if they are pseudo instructions.
+ if (AsmString.find('\n') != std::string::npos)
+ throw TGError(TheDef->getLoc(),
+ "multiline instruction is not valid for the asmparser, "
+ "mark it isCodeGenOnly");
+
+ // Remove comments from the asm string. We know that the asmstring only
+ // has one line.
+ if (!CommentDelimiter.empty() &&
+ StringRef(AsmString).find(CommentDelimiter) != StringRef::npos)
+ throw TGError(TheDef->getLoc(),
+ "asmstring for instruction has comment character in it, "
+ "mark it isCodeGenOnly");
+
+ // Reject matchables with operand modifiers, these aren't something we can
+ // handle, the target should be refactored to use operands instead of
+ // modifiers.
+ //
+ // Also, check for instructions which reference the operand multiple times;
+ // this implies a constraint we would not honor.
+ std::set<std::string> OperandNames;
+ for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
+ StringRef Tok = AsmOperands[i].Token;
+ if (Tok[0] == '$' && Tok.find(':') != StringRef::npos)
+ throw TGError(TheDef->getLoc(),
+ "matchable with operand modifier '" + Tok.str() +
+ "' 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)
+ throw TGError(TheDef->getLoc(),
+ "ERROR: matchable with tied operand '" + Tok.str() +
+ "' 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";
+ });
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/// getSingletonRegisterForAsmOperand - If the specified token is a singleton
+/// register, return the register name, otherwise return a null StringRef.
+Record *MatchableInfo::
+getSingletonRegisterForAsmOperand(unsigned i, const AsmMatcherInfo &Info) const{
+ StringRef Tok = AsmOperands[i].Token;
+ if (!Tok.startswith(Info.RegisterPrefix))
+ return 0;
+
+ StringRef RegName = Tok.substr(Info.RegisterPrefix.size());
+ if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(RegName))
+ return Reg->TheDef;
+
+ // If there is no register prefix (i.e. "%" in "%eax"), then this may
+ // be some random non-register token, just ignore it.
+ if (Info.RegisterPrefix.empty())
+ return 0;
+
+ // Otherwise, we have something invalid prefixed with the register prefix,
+ // such as %foo.
+ std::string Err = "unable to find register for '" + RegName.str() +
+ "' (which matches register prefix)";
+ throw TGError(TheDef->getLoc(), Err);
+}
+
static std::string getEnumNameForToken(StringRef Str) {
std::string Res;
-
+
for (StringRef::iterator it = Str.begin(), ie = Str.end(); it != ie; ++it) {
switch (*it) {
case '*': Res += "_STAR_"; break;
case '%': Res += "_PCT_"; break;
case ':': Res += "_COLON_"; break;
-
+ case '!': Res += "_EXCLAIM_"; break;
+ case '.': Res += "_DOT_"; break;
default:
- if (isalnum(*it)) {
+ if (isalnum(*it))
Res += *it;
- } else {
+ else
Res += "_" + utostr((unsigned) *it) + "_";
- }
}
}
return Res;
}
-/// getRegisterRecord - Get the register record for \arg name, or 0.
-static Record *getRegisterRecord(CodeGenTarget &Target, StringRef Name) {
- for (unsigned i = 0, e = Target.getRegisters().size(); i != e; ++i) {
- const CodeGenRegister &Reg = Target.getRegisters()[i];
- if (Name == Reg.TheDef->getValueAsString("AsmName"))
- return Reg.TheDef;
- }
-
- return 0;
-}
-
ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) {
ClassInfo *&Entry = TokenClasses[Token];
-
+
if (!Entry) {
Entry = new ClassInfo();
Entry->Kind = ClassInfo::Token;
@@ -671,6 +857,7 @@
Entry->ValueName = Token;
Entry->PredicateMethod = "<invalid>";
Entry->RenderMethod = "<invalid>";
+ Entry->ParserMethod = "";
Classes.push_back(Entry);
}
@@ -678,65 +865,84 @@
}
ClassInfo *
-AsmMatcherInfo::getOperandClass(StringRef Token,
- const CodeGenInstruction::OperandInfo &OI) {
- if (OI.Rec->isSubClassOf("RegisterClass")) {
- ClassInfo *CI = RegisterClassClasses[OI.Rec];
+AsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI,
+ int SubOpIdx) {
+ Record *Rec = OI.Rec;
+ if (SubOpIdx != -1)
+ Rec = dynamic_cast<DefInit*>(OI.MIOperandInfo->getArg(SubOpIdx))->getDef();
- if (!CI) {
- PrintError(OI.Rec->getLoc(), "register class has no class info!");
- throw std::string("ERROR: Missing register class!");
+ if (Rec->isSubClassOf("RegisterOperand")) {
+ // 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)
+ throw "Record `" + Rec->getName() +
+ "' does not have a ParserMatchClass!\n";
+
+ if (DefInit *DI= dynamic_cast<DefInit*>(R->getValue())) {
+ Record *MatchClass = DI->getDef();
+ if (ClassInfo *CI = AsmOperandClasses[MatchClass])
+ return CI;
}
+ // No custom match class. Just use the register class.
+ Record *ClassRec = Rec->getValueAsDef("RegClass");
+ if (!ClassRec)
+ throw TGError(Rec->getLoc(), "RegisterOperand `" + Rec->getName() +
+ "' has no associated register class!\n");
+ if (ClassInfo *CI = RegisterClassClasses[ClassRec])
+ return CI;
+ throw TGError(Rec->getLoc(), "register class has no class info!");
+ }
+
+
+ if (Rec->isSubClassOf("RegisterClass")) {
+ if (ClassInfo *CI = RegisterClassClasses[Rec])
+ return CI;
+ throw TGError(Rec->getLoc(), "register class has no class info!");
+ }
+
+ assert(Rec->isSubClassOf("Operand") && "Unexpected operand!");
+ Record *MatchClass = Rec->getValueAsDef("ParserMatchClass");
+ if (ClassInfo *CI = AsmOperandClasses[MatchClass])
return CI;
- }
- assert(OI.Rec->isSubClassOf("Operand") && "Unexpected operand!");
- Record *MatchClass = OI.Rec->getValueAsDef("ParserMatchClass");
- ClassInfo *CI = AsmOperandClasses[MatchClass];
-
- if (!CI) {
- PrintError(OI.Rec->getLoc(), "operand has no match class!");
- throw std::string("ERROR: Missing match class!");
- }
-
- return CI;
+ throw TGError(Rec->getLoc(), "operand has no match class!");
}
-void AsmMatcherInfo::BuildRegisterClasses(CodeGenTarget &Target,
- std::set<std::string>
- &SingletonRegisterNames) {
- std::vector<CodeGenRegisterClass> RegisterClasses;
- std::vector<CodeGenRegister> Registers;
-
- RegisterClasses = Target.getRegisterClasses();
- Registers = Target.getRegisters();
+void AsmMatcherInfo::
+BuildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
+ const std::vector<CodeGenRegister*> &Registers =
+ Target.getRegBank().getRegisters();
+ ArrayRef<CodeGenRegisterClass*> RegClassList =
+ Target.getRegBank().getRegClasses();
// The register sets used for matching.
std::set< std::set<Record*> > RegisterSets;
- // Gather the defined sets.
- for (std::vector<CodeGenRegisterClass>::iterator it = RegisterClasses.begin(),
- ie = RegisterClasses.end(); it != ie; ++it)
- RegisterSets.insert(std::set<Record*>(it->Elements.begin(),
- it->Elements.end()));
+ // Gather the defined sets.
+ for (ArrayRef<CodeGenRegisterClass*>::const_iterator it =
+ RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it)
+ RegisterSets.insert(std::set<Record*>(
+ (*it)->getOrder().begin(), (*it)->getOrder().end()));
// Add any required singleton sets.
- for (std::set<std::string>::iterator it = SingletonRegisterNames.begin(),
- ie = SingletonRegisterNames.end(); it != ie; ++it)
- if (Record *Rec = getRegisterRecord(Target, *it))
- RegisterSets.insert(std::set<Record*>(&Rec, &Rec + 1));
-
+ for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(),
+ ie = SingletonRegisters.end(); it != ie; ++it) {
+ Record *Rec = *it;
+ RegisterSets.insert(std::set<Record*>(&Rec, &Rec + 1));
+ }
+
// Introduce derived sets where necessary (when a register does not determine
// a unique register set class), and build the mapping of registers to the set
// they should classify to.
std::map<Record*, std::set<Record*> > RegisterMap;
- for (std::vector<CodeGenRegister>::iterator it = Registers.begin(),
+ for (std::vector<CodeGenRegister*>::const_iterator it = Registers.begin(),
ie = Registers.end(); it != ie; ++it) {
- CodeGenRegister &CGR = *it;
+ const CodeGenRegister &CGR = **it;
// Compute the intersection of all sets containing this register.
std::set<Record*> ContainingSet;
-
+
for (std::set< std::set<Record*> >::iterator it = RegisterSets.begin(),
ie = RegisterSets.end(); it != ie; ++it) {
if (!it->count(CGR.TheDef))
@@ -744,14 +950,14 @@
if (ContainingSet.empty()) {
ContainingSet = *it;
- } else {
- std::set<Record*> Tmp;
- std::swap(Tmp, ContainingSet);
- std::insert_iterator< std::set<Record*> > II(ContainingSet,
- ContainingSet.begin());
- std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(),
- II);
+ continue;
}
+
+ std::set<Record*> Tmp;
+ std::swap(Tmp, ContainingSet);
+ std::insert_iterator< std::set<Record*> > II(ContainingSet,
+ ContainingSet.begin());
+ std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(), II);
}
if (!ContainingSet.empty()) {
@@ -784,59 +990,63 @@
ClassInfo *CI = RegisterSetClasses[*it];
for (std::set< std::set<Record*> >::iterator it2 = RegisterSets.begin(),
ie2 = RegisterSets.end(); it2 != ie2; ++it2)
- if (*it != *it2 &&
+ if (*it != *it2 &&
std::includes(it2->begin(), it2->end(), it->begin(), it->end()))
CI->SuperClasses.push_back(RegisterSetClasses[*it2]);
}
// Name the register classes which correspond to a user defined RegisterClass.
- for (std::vector<CodeGenRegisterClass>::iterator it = RegisterClasses.begin(),
- ie = RegisterClasses.end(); it != ie; ++it) {
- ClassInfo *CI = RegisterSetClasses[std::set<Record*>(it->Elements.begin(),
- it->Elements.end())];
+ for (ArrayRef<CodeGenRegisterClass*>::const_iterator
+ it = RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) {
+ const CodeGenRegisterClass &RC = **it;
+ // Def will be NULL for non-user defined register classes.
+ Record *Def = RC.getDef();
+ if (!Def)
+ continue;
+ ClassInfo *CI = RegisterSetClasses[std::set<Record*>(RC.getOrder().begin(),
+ RC.getOrder().end())];
if (CI->ValueName.empty()) {
- CI->ClassName = it->getName();
- CI->Name = "MCK_" + it->getName();
- CI->ValueName = it->getName();
+ CI->ClassName = RC.getName();
+ CI->Name = "MCK_" + RC.getName();
+ CI->ValueName = RC.getName();
} else
- CI->ValueName = CI->ValueName + "," + it->getName();
+ CI->ValueName = CI->ValueName + "," + RC.getName();
- RegisterClassClasses.insert(std::make_pair(it->TheDef, CI));
+ RegisterClassClasses.insert(std::make_pair(Def, CI));
}
// Populate the map for individual registers.
for (std::map<Record*, std::set<Record*> >::iterator it = RegisterMap.begin(),
ie = RegisterMap.end(); it != ie; ++it)
- this->RegisterClasses[it->first] = RegisterSetClasses[it->second];
+ RegisterClasses[it->first] = RegisterSetClasses[it->second];
// Name the register classes which correspond to singleton registers.
- for (std::set<std::string>::iterator it = SingletonRegisterNames.begin(),
- ie = SingletonRegisterNames.end(); it != ie; ++it) {
- if (Record *Rec = getRegisterRecord(Target, *it)) {
- ClassInfo *CI = this->RegisterClasses[Rec];
- assert(CI && "Missing singleton register class info!");
+ for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(),
+ ie = SingletonRegisters.end(); it != ie; ++it) {
+ Record *Rec = *it;
+ ClassInfo *CI = RegisterClasses[Rec];
+ assert(CI && "Missing singleton register class info!");
- if (CI->ValueName.empty()) {
- CI->ClassName = Rec->getName();
- CI->Name = "MCK_" + Rec->getName();
- CI->ValueName = Rec->getName();
- } else
- CI->ValueName = CI->ValueName + "," + Rec->getName();
- }
+ if (CI->ValueName.empty()) {
+ CI->ClassName = Rec->getName();
+ CI->Name = "MCK_" + Rec->getName();
+ CI->ValueName = Rec->getName();
+ } else
+ CI->ValueName = CI->ValueName + "," + Rec->getName();
}
}
-void AsmMatcherInfo::BuildOperandClasses(CodeGenTarget &Target) {
- std::vector<Record*> AsmOperands;
- AsmOperands = Records.getAllDerivedDefinitions("AsmOperandClass");
+void AsmMatcherInfo::BuildOperandClasses() {
+ std::vector<Record*> AsmOperands =
+ Records.getAllDerivedDefinitions("AsmOperandClass");
// Pre-populate AsmOperandClasses map.
- for (std::vector<Record*>::iterator it = AsmOperands.begin(),
+ for (std::vector<Record*>::iterator it = AsmOperands.begin(),
ie = AsmOperands.end(); it != ie; ++it)
AsmOperandClasses[*it] = new ClassInfo();
unsigned Index = 0;
- for (std::vector<Record*>::iterator it = AsmOperands.begin(),
+ for (std::vector<Record*>::iterator it = AsmOperands.begin(),
ie = AsmOperands.end(); it != ie; ++it, ++Index) {
ClassInfo *CI = AsmOperandClasses[*it];
CI->Kind = ClassInfo::UserClass0 + Index;
@@ -864,7 +1074,7 @@
if (StringInit *SI = dynamic_cast<StringInit*>(PMName)) {
CI->PredicateMethod = SI->getValue();
} else {
- assert(dynamic_cast<UnsetInit*>(PMName) &&
+ assert(dynamic_cast<UnsetInit*>(PMName) &&
"Unexpected PredicateMethod field!");
CI->PredicateMethod = "is" + CI->ClassName;
}
@@ -879,128 +1089,192 @@
CI->RenderMethod = "add" + CI->ClassName + "Operands";
}
+ // Get the parse method name or leave it as empty.
+ Init *PRMName = (*it)->getValueInit("ParserMethod");
+ if (StringInit *SI = dynamic_cast<StringInit*>(PRMName))
+ CI->ParserMethod = SI->getValue();
+
AsmOperandClasses[*it] = CI;
Classes.push_back(CI);
}
}
-AsmMatcherInfo::AsmMatcherInfo(Record *_AsmParser)
- : AsmParser(_AsmParser),
- CommentDelimiter(AsmParser->getValueAsString("CommentDelimiter")),
- RegisterPrefix(AsmParser->getValueAsString("RegisterPrefix"))
-{
+AsmMatcherInfo::AsmMatcherInfo(Record *asmParser,
+ CodeGenTarget &target,
+ RecordKeeper &records)
+ : Records(records), AsmParser(asmParser), Target(target),
+ RegisterPrefix(AsmParser->getValueAsString("RegisterPrefix")) {
}
-void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
+/// BuildOperandMatchInfo - Build the necessary information to handle user
+/// defined operand parsing methods.
+void AsmMatcherInfo::BuildOperandMatchInfo() {
+
+ /// Map containing a mask with all operands indicies that can be found for
+ /// that class inside a instruction.
+ std::map<ClassInfo*, unsigned> OpClassMask;
+
+ for (std::vector<MatchableInfo*>::const_iterator it =
+ Matchables.begin(), ie = Matchables.end();
+ it != ie; ++it) {
+ MatchableInfo &II = **it;
+ OpClassMask.clear();
+
+ // Keep track of all operands of this instructions which belong to the
+ // same class.
+ for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) {
+ MatchableInfo::AsmOperand &Op = II.AsmOperands[i];
+ if (Op.Class->ParserMethod.empty())
+ continue;
+ unsigned &OperandMask = OpClassMask[Op.Class];
+ OperandMask |= (1 << i);
+ }
+
+ // Generate operand match info for each mnemonic/operand class pair.
+ for (std::map<ClassInfo*, unsigned>::iterator iit = OpClassMask.begin(),
+ iie = OpClassMask.end(); iit != iie; ++iit) {
+ unsigned OpMask = iit->second;
+ ClassInfo *CI = iit->first;
+ OperandMatchInfo.push_back(OperandMatchEntry::Create(&II, CI, OpMask));
+ }
+ }
+}
+
+void AsmMatcherInfo::BuildInfo() {
+ // Build information about all of the AssemblerPredicates.
+ std::vector<Record*> AllPredicates =
+ Records.getAllDerivedDefinitions("Predicate");
+ for (unsigned i = 0, e = AllPredicates.size(); i != e; ++i) {
+ Record *Pred = AllPredicates[i];
+ // Ignore predicates that are not intended for the assembler.
+ if (!Pred->getValueAsBit("AssemblerMatcherPredicate"))
+ continue;
+
+ if (Pred->getName().empty())
+ throw TGError(Pred->getLoc(), "Predicate has no name!");
+
+ unsigned FeatureNo = SubtargetFeatures.size();
+ SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo);
+ assert(FeatureNo < 32 && "Too many subtarget features!");
+ }
+
+ std::string CommentDelimiter = AsmParser->getValueAsString("CommentDelimiter");
+
// Parse the instructions; we need to do this first so that we can gather the
// singleton register classes.
- std::set<std::string> SingletonRegisterNames;
-
- const std::vector<const CodeGenInstruction*> &InstrList =
- Target.getInstructionsByEnumValue();
-
- for (unsigned i = 0, e = InstrList.size(); i != e; ++i) {
- const CodeGenInstruction &CGI = *InstrList[i];
+ SmallPtrSet<Record*, 16> SingletonRegisters;
+ for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
+ E = Target.inst_end(); I != E; ++I) {
+ const CodeGenInstruction &CGI = **I;
+ // If the tblgen -match-prefix option is specified (for tblgen hackers),
+ // filter the set of instructions we consider.
if (!StringRef(CGI.TheDef->getName()).startswith(MatchPrefix))
continue;
- OwningPtr<InstructionInfo> II(new InstructionInfo());
-
- II->InstrName = CGI.TheDef->getName();
- II->Instr = &CGI;
- II->AsmString = FlattenVariants(CGI.AsmString, 0);
-
- // Remove comments from the asm string.
- if (!CommentDelimiter.empty()) {
- size_t Idx = StringRef(II->AsmString).find(CommentDelimiter);
- if (Idx != StringRef::npos)
- II->AsmString = II->AsmString.substr(0, Idx);
- }
-
- TokenizeAsmString(II->AsmString, II->Tokens);
-
- // Ignore instructions which shouldn't be matched.
- if (!IsAssemblerInstruction(CGI.TheDef->getName(), CGI, II->Tokens))
+ // Ignore "codegen only" instructions.
+ if (CGI.TheDef->getValueAsBit("isCodeGenOnly"))
continue;
- // Collect singleton registers, if used.
- if (!RegisterPrefix.empty()) {
- for (unsigned i = 0, e = II->Tokens.size(); i != e; ++i) {
- if (II->Tokens[i].startswith(RegisterPrefix)) {
- StringRef RegName = II->Tokens[i].substr(RegisterPrefix.size());
- Record *Rec = getRegisterRecord(Target, RegName);
-
- if (!Rec) {
- std::string Err = "unable to find register for '" + RegName.str() +
- "' (which matches register prefix)";
- throw TGError(CGI.TheDef->getLoc(), Err);
- }
+ // Validate the operand list to ensure we can handle this instruction.
+ for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) {
+ const CGIOperandList::OperandInfo &OI = CGI.Operands[i];
- SingletonRegisterNames.insert(RegName);
+ // Validate tied operands.
+ if (OI.getTiedRegister() != -1) {
+ // If we have a tied operand that consists of multiple MCOperands,
+ // reject it. We reject aliases and ignore instructions for now.
+ if (OI.MINumOperands != 1) {
+ // 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: '" << CGI.TheDef->getName() << "': "
+ << "ignoring instruction with multi-operand tied operand '"
+ << OI.Name << "'\n";
+ });
+ continue;
}
}
}
- // Compute the require features.
- ListInit *Predicates = CGI.TheDef->getValueAsListInit("Predicates");
- for (unsigned i = 0, e = Predicates->getSize(); i != e; ++i) {
- if (DefInit *Pred = dynamic_cast<DefInit*>(Predicates->getElement(i))) {
- // Ignore OptForSize and OptForSpeed, they aren't really requirements,
- // rather they are hints to isel.
- //
- // FIXME: Find better way to model this.
- if (Pred->getDef()->getName() == "OptForSize" ||
- Pred->getDef()->getName() == "OptForSpeed")
- continue;
+ OwningPtr<MatchableInfo> II(new MatchableInfo(CGI));
- // FIXME: Total hack; for now, we just limit ourselves to In32BitMode
- // and In64BitMode, because we aren't going to have the right feature
- // masks for SSE and friends. We need to decide what we are going to do
- // about CPU subtypes to implement this the right way.
- if (Pred->getDef()->getName() != "In32BitMode" &&
- Pred->getDef()->getName() != "In64BitMode")
- continue;
+ II->Initialize(*this, SingletonRegisters);
- II->RequiredFeatures.push_back(getSubtargetFeature(Pred->getDef()));
- }
- }
+ // Ignore instructions which shouldn't be matched and diagnose invalid
+ // instruction definitions with an error.
+ if (!II->Validate(CommentDelimiter, true))
+ continue;
- Instructions.push_back(II.take());
+ // Ignore "Int_*" and "*_Int" instructions, which are internal aliases.
+ //
+ // FIXME: This is a total hack.
+ if (StringRef(II->TheDef->getName()).startswith("Int_") ||
+ StringRef(II->TheDef->getName()).endswith("_Int"))
+ continue;
+
+ Matchables.push_back(II.take());
+ }
+
+ // Parse all of the InstAlias definitions and stick them in the list of
+ // matchables.
+ std::vector<Record*> AllInstAliases =
+ Records.getAllDerivedDefinitions("InstAlias");
+ for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) {
+ CodeGenInstAlias *Alias = new CodeGenInstAlias(AllInstAliases[i], Target);
+
+ // If the tblgen -match-prefix option is specified (for tblgen hackers),
+ // filter the set of instruction aliases we consider, based on the target
+ // instruction.
+ if (!StringRef(Alias->ResultInst->TheDef->getName()).startswith(
+ MatchPrefix))
+ continue;
+
+ OwningPtr<MatchableInfo> II(new MatchableInfo(Alias));
+
+ II->Initialize(*this, SingletonRegisters);
+
+ // Validate the alias definitions.
+ II->Validate(CommentDelimiter, false);
+
+ Matchables.push_back(II.take());
}
// Build info for the register classes.
- BuildRegisterClasses(Target, SingletonRegisterNames);
+ BuildRegisterClasses(SingletonRegisters);
// Build info for the user defined assembly operand classes.
- BuildOperandClasses(Target);
+ BuildOperandClasses();
- // Build the instruction information.
- for (std::vector<InstructionInfo*>::iterator it = Instructions.begin(),
- ie = Instructions.end(); it != ie; ++it) {
- InstructionInfo *II = *it;
+ // Build the information about matchables, now that we have fully formed
+ // classes.
+ for (std::vector<MatchableInfo*>::iterator it = Matchables.begin(),
+ ie = Matchables.end(); it != ie; ++it) {
+ MatchableInfo *II = *it;
- for (unsigned i = 0, e = II->Tokens.size(); i != e; ++i) {
- StringRef Token = II->Tokens[i];
+ // Parse the tokens after the mnemonic.
+ // Note: BuildInstructionOperandReference may insert new AsmOperands, so
+ // don't precompute the loop bound.
+ for (unsigned i = 0; i != II->AsmOperands.size(); ++i) {
+ MatchableInfo::AsmOperand &Op = II->AsmOperands[i];
+ StringRef Token = Op.Token;
// Check for singleton registers.
- if (!RegisterPrefix.empty() && Token.startswith(RegisterPrefix)) {
- StringRef RegName = II->Tokens[i].substr(RegisterPrefix.size());
- InstructionInfo::Operand Op;
- Op.Class = RegisterClasses[getRegisterRecord(Target, RegName)];
- Op.OperandInfo = 0;
+ if (Record *RegRecord = II->getSingletonRegisterForAsmOperand(i, *this)) {
+ Op.Class = RegisterClasses[RegRecord];
assert(Op.Class && Op.Class->Registers.size() == 1 &&
"Unexpected class for singleton register");
- II->Operands.push_back(Op);
continue;
}
// Check for simple tokens.
if (Token[0] != '$') {
- InstructionInfo::Operand Op;
Op.Class = getTokenClass(Token);
- Op.OperandInfo = 0;
- II->Operands.push_back(Op);
+ continue;
+ }
+
+ if (Token.size() > 1 && isdigit(Token[1])) {
+ Op.Class = getTokenClass(Token);
continue;
}
@@ -1011,58 +1285,204 @@
else
OperandName = Token.substr(1);
- // Map this token to an operand. FIXME: Move elsewhere.
- unsigned Idx;
- try {
- Idx = II->Instr->getOperandNamed(OperandName);
- } catch(...) {
- throw std::string("error: unable to find operand: '" +
- OperandName.str() + "'");
- }
-
- // FIXME: This is annoying, the named operand may be tied (e.g.,
- // XCHG8rm). What we want is the untied operand, which we now have to
- // grovel for. Only worry about this for single entry operands, we have to
- // clean this up anyway.
- const CodeGenInstruction::OperandInfo *OI = &II->Instr->OperandList[Idx];
- if (OI->Constraints[0].isTied()) {
- unsigned TiedOp = OI->Constraints[0].getTiedOperand();
-
- // The tied operand index is an MIOperand index, find the operand that
- // contains it.
- for (unsigned i = 0, e = II->Instr->OperandList.size(); i != e; ++i) {
- if (II->Instr->OperandList[i].MIOperandNo == TiedOp) {
- OI = &II->Instr->OperandList[i];
- break;
- }
- }
-
- assert(OI && "Unable to find tied operand target!");
- }
-
- InstructionInfo::Operand Op;
- Op.Class = getOperandClass(Token, *OI);
- Op.OperandInfo = OI;
- II->Operands.push_back(Op);
+ if (II->DefRec.is<const CodeGenInstruction*>())
+ BuildInstructionOperandReference(II, OperandName, i);
+ else
+ BuildAliasOperandReference(II, OperandName, Op);
}
+
+ if (II->DefRec.is<const CodeGenInstruction*>())
+ II->BuildInstructionResultOperands();
+ else
+ II->BuildAliasResultOperands();
}
- // Reorder classes so that classes preceed super classes.
+ // Reorder classes so that classes precede super classes.
std::sort(Classes.begin(), Classes.end(), less_ptr<ClassInfo>());
}
-static std::pair<unsigned, unsigned> *
-GetTiedOperandAtIndex(SmallVectorImpl<std::pair<unsigned, unsigned> > &List,
- unsigned Index) {
- for (unsigned i = 0, e = List.size(); i != e; ++i)
- if (Index == List[i].first)
- return &List[i];
+/// BuildInstructionOperandReference - The specified operand is a reference to a
+/// named operand such as $src. Resolve the Class and OperandInfo pointers.
+void AsmMatcherInfo::
+BuildInstructionOperandReference(MatchableInfo *II,
+ StringRef OperandName,
+ unsigned AsmOpIdx) {
+ const CodeGenInstruction &CGI = *II->DefRec.get<const CodeGenInstruction*>();
+ const CGIOperandList &Operands = CGI.Operands;
+ MatchableInfo::AsmOperand *Op = &II->AsmOperands[AsmOpIdx];
- return 0;
+ // Map this token to an operand.
+ unsigned Idx;
+ if (!Operands.hasOperandNamed(OperandName, Idx))
+ throw TGError(II->TheDef->getLoc(), "error: unable to find operand: '" +
+ OperandName.str() + "'");
+
+ // If the instruction operand has multiple suboperands, but the parser
+ // match class for the asm operand is still the default "ImmAsmOperand",
+ // then handle each suboperand separately.
+ if (Op->SubOpIdx == -1 && Operands[Idx].MINumOperands > 1) {
+ Record *Rec = Operands[Idx].Rec;
+ assert(Rec->isSubClassOf("Operand") && "Unexpected operand!");
+ Record *MatchClass = Rec->getValueAsDef("ParserMatchClass");
+ if (MatchClass && MatchClass->getValueAsString("Name") == "Imm") {
+ // Insert remaining suboperands after AsmOpIdx in II->AsmOperands.
+ StringRef Token = Op->Token; // save this in case Op gets moved
+ for (unsigned SI = 1, SE = Operands[Idx].MINumOperands; SI != SE; ++SI) {
+ MatchableInfo::AsmOperand NewAsmOp(Token);
+ NewAsmOp.SubOpIdx = SI;
+ II->AsmOperands.insert(II->AsmOperands.begin()+AsmOpIdx+SI, NewAsmOp);
+ }
+ // Replace Op with first suboperand.
+ Op = &II->AsmOperands[AsmOpIdx]; // update the pointer in case it moved
+ Op->SubOpIdx = 0;
+ }
+ }
+
+ // Set up the operand class.
+ Op->Class = getOperandClass(Operands[Idx], Op->SubOpIdx);
+
+ // If the named operand is tied, canonicalize it to the untied operand.
+ // For example, something like:
+ // (outs GPR:$dst), (ins GPR:$src)
+ // with an asmstring of
+ // "inc $src"
+ // we want to canonicalize to:
+ // "inc $dst"
+ // so that we know how to provide the $dst operand when filling in the result.
+ int OITied = Operands[Idx].getTiedRegister();
+ if (OITied != -1) {
+ // The tied operand index is an MIOperand index, find the operand that
+ // contains it.
+ std::pair<unsigned, unsigned> Idx = Operands.getSubOperandNumber(OITied);
+ OperandName = Operands[Idx.first].Name;
+ Op->SubOpIdx = Idx.second;
+ }
+
+ Op->SrcOpName = OperandName;
}
-static void EmitConvertToMCInst(CodeGenTarget &Target,
- std::vector<InstructionInfo*> &Infos,
+/// BuildAliasOperandReference - When parsing an operand reference out of the
+/// matching string (e.g. "movsx $src, $dst"), determine what the class of the
+/// operand reference is by looking it up in the result pattern definition.
+void AsmMatcherInfo::BuildAliasOperandReference(MatchableInfo *II,
+ StringRef OperandName,
+ MatchableInfo::AsmOperand &Op) {
+ const CodeGenInstAlias &CGA = *II->DefRec.get<const CodeGenInstAlias*>();
+
+ // Set up the operand class.
+ for (unsigned i = 0, e = CGA.ResultOperands.size(); i != e; ++i)
+ if (CGA.ResultOperands[i].isRecord() &&
+ CGA.ResultOperands[i].getName() == OperandName) {
+ // It's safe to go with the first one we find, because CodeGenInstAlias
+ // validates that all operands with the same name have the same record.
+ unsigned ResultIdx = CGA.ResultInstOperandIndex[i].first;
+ Op.SubOpIdx = CGA.ResultInstOperandIndex[i].second;
+ Op.Class = getOperandClass(CGA.ResultInst->Operands[ResultIdx],
+ Op.SubOpIdx);
+ Op.SrcOpName = OperandName;
+ return;
+ }
+
+ throw TGError(II->TheDef->getLoc(), "error: unable to find operand: '" +
+ OperandName.str() + "'");
+}
+
+void MatchableInfo::BuildInstructionResultOperands() {
+ const CodeGenInstruction *ResultInst = getResultInst();
+
+ // Loop over all operands of the result instruction, determining how to
+ // populate them.
+ for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) {
+ const CGIOperandList::OperandInfo &OpInfo = ResultInst->Operands[i];
+
+ // If this is a tied operand, just copy from the previously handled operand.
+ int TiedOp = OpInfo.getTiedRegister();
+ if (TiedOp != -1) {
+ ResOperands.push_back(ResOperand::getTiedOp(TiedOp));
+ continue;
+ }
+
+ // Find out what operand from the asmparser this MCInst operand comes from.
+ int SrcOperand = FindAsmOperandNamed(OpInfo.Name);
+ if (OpInfo.Name.empty() || SrcOperand == -1)
+ throw TGError(TheDef->getLoc(), "Instruction '" +
+ TheDef->getName() + "' has operand '" + OpInfo.Name +
+ "' that doesn't appear in asm string!");
+
+ // Check if the one AsmOperand populates the entire operand.
+ unsigned NumOperands = OpInfo.MINumOperands;
+ if (AsmOperands[SrcOperand].SubOpIdx == -1) {
+ ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, NumOperands));
+ continue;
+ }
+
+ // Add a separate ResOperand for each suboperand.
+ for (unsigned AI = 0; AI < NumOperands; ++AI) {
+ assert(AsmOperands[SrcOperand+AI].SubOpIdx == (int)AI &&
+ AsmOperands[SrcOperand+AI].SrcOpName == OpInfo.Name &&
+ "unexpected AsmOperands for suboperands");
+ ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand + AI, 1));
+ }
+ }
+}
+
+void MatchableInfo::BuildAliasResultOperands() {
+ const CodeGenInstAlias &CGA = *DefRec.get<const CodeGenInstAlias*>();
+ const CodeGenInstruction *ResultInst = getResultInst();
+
+ // Loop over all operands of the result instruction, determining how to
+ // populate them.
+ unsigned AliasOpNo = 0;
+ unsigned LastOpNo = CGA.ResultInstOperandIndex.size();
+ for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) {
+ const CGIOperandList::OperandInfo *OpInfo = &ResultInst->Operands[i];
+
+ // If this is a tied operand, just copy from the previously handled operand.
+ int TiedOp = OpInfo->getTiedRegister();
+ if (TiedOp != -1) {
+ ResOperands.push_back(ResOperand::getTiedOp(TiedOp));
+ continue;
+ }
+
+ // Handle all the suboperands for this operand.
+ const std::string &OpName = OpInfo->Name;
+ for ( ; AliasOpNo < LastOpNo &&
+ CGA.ResultInstOperandIndex[AliasOpNo].first == i; ++AliasOpNo) {
+ int SubIdx = CGA.ResultInstOperandIndex[AliasOpNo].second;
+
+ // Find out what operand from the asmparser that this MCInst operand
+ // comes from.
+ switch (CGA.ResultOperands[AliasOpNo].Kind) {
+ default: assert(0 && "unexpected InstAlias operand kind");
+ case CodeGenInstAlias::ResultOperand::K_Record: {
+ StringRef Name = CGA.ResultOperands[AliasOpNo].getName();
+ int SrcOperand = FindAsmOperand(Name, SubIdx);
+ if (SrcOperand == -1)
+ throw TGError(TheDef->getLoc(), "Instruction '" +
+ TheDef->getName() + "' has operand '" + OpName +
+ "' that doesn't appear in asm string!");
+ unsigned NumOperands = (SubIdx == -1 ? OpInfo->MINumOperands : 1);
+ ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand,
+ NumOperands));
+ break;
+ }
+ case CodeGenInstAlias::ResultOperand::K_Imm: {
+ int64_t ImmVal = CGA.ResultOperands[AliasOpNo].getImm();
+ ResOperands.push_back(ResOperand::getImmOp(ImmVal));
+ break;
+ }
+ case CodeGenInstAlias::ResultOperand::K_Reg: {
+ Record *Reg = CGA.ResultOperands[AliasOpNo].getRegister();
+ ResOperands.push_back(ResOperand::getRegOp(Reg));
+ break;
+ }
+ }
+ }
+ }
+}
+
+static void EmitConvertToMCInst(CodeGenTarget &Target, StringRef ClassName,
+ std::vector<MatchableInfo*> &Infos,
raw_ostream &OS) {
// Write the convert function to a separate stream, so we can drop it after
// the enum.
@@ -1073,8 +1493,8 @@
std::set<std::string> GeneratedFns;
// Start the unified conversion function.
-
- CvtOS << "static void ConvertToMCInst(ConversionKind Kind, MCInst &Inst, "
+ CvtOS << "bool " << Target.getName() << ClassName << "::\n";
+ CvtOS << "ConvertToMCInst(unsigned Kind, MCInst &Inst, "
<< "unsigned Opcode,\n"
<< " const SmallVectorImpl<MCParsedAsmOperand*"
<< "> &Operands) {\n";
@@ -1084,92 +1504,94 @@
// Start the enum, which we will generate inline.
- OS << "// Unified function for converting operants to MCInst instances.\n\n";
+ OS << "// Unified function for converting operands to MCInst instances.\n\n";
OS << "enum ConversionKind {\n";
-
+
// TargetOperandClass - This is the target's operand class, like X86Operand.
std::string TargetOperandClass = Target.getName() + "Operand";
-
- for (std::vector<InstructionInfo*>::const_iterator it = Infos.begin(),
+
+ for (std::vector<MatchableInfo*>::const_iterator it = Infos.begin(),
ie = Infos.end(); it != ie; ++it) {
- InstructionInfo &II = **it;
+ MatchableInfo &II = **it;
- // Order the (class) operands by the order to convert them into an MCInst.
- SmallVector<std::pair<unsigned, unsigned>, 4> MIOperandList;
- for (unsigned i = 0, e = II.Operands.size(); i != e; ++i) {
- InstructionInfo::Operand &Op = II.Operands[i];
- if (Op.OperandInfo)
- MIOperandList.push_back(std::make_pair(Op.OperandInfo->MIOperandNo, i));
- }
+ // Check if we have a custom match function.
+ std::string AsmMatchConverter =
+ II.getResultInst()->TheDef->getValueAsString("AsmMatchConverter");
+ if (!AsmMatchConverter.empty()) {
+ std::string Signature = "ConvertCustom_" + AsmMatchConverter;
+ II.ConversionFnKind = Signature;
- // Find any tied operands.
- SmallVector<std::pair<unsigned, unsigned>, 4> TiedOperands;
- for (unsigned i = 0, e = II.Instr->OperandList.size(); i != e; ++i) {
- const CodeGenInstruction::OperandInfo &OpInfo = II.Instr->OperandList[i];
- for (unsigned j = 0, e = OpInfo.Constraints.size(); j != e; ++j) {
- const CodeGenInstruction::ConstraintInfo &CI = OpInfo.Constraints[j];
- if (CI.isTied())
- TiedOperands.push_back(std::make_pair(OpInfo.MIOperandNo + j,
- CI.getTiedOperand()));
- }
- }
+ // Check if we have already generated this signature.
+ if (!GeneratedFns.insert(Signature).second)
+ continue;
- std::sort(MIOperandList.begin(), MIOperandList.end());
+ // If not, emit it now. Add to the enum list.
+ OS << " " << Signature << ",\n";
- // Compute the total number of operands.
- unsigned NumMIOperands = 0;
- for (unsigned i = 0, e = II.Instr->OperandList.size(); i != e; ++i) {
- const CodeGenInstruction::OperandInfo &OI = II.Instr->OperandList[i];
- NumMIOperands = std::max(NumMIOperands,
- OI.MIOperandNo + OI.MINumOperands);
+ CvtOS << " case " << Signature << ":\n";
+ CvtOS << " return " << AsmMatchConverter
+ << "(Inst, Opcode, Operands);\n";
+ continue;
}
// Build the conversion function signature.
std::string Signature = "Convert";
- unsigned CurIndex = 0;
- for (unsigned i = 0, e = MIOperandList.size(); i != e; ++i) {
- InstructionInfo::Operand &Op = II.Operands[MIOperandList[i].second];
- assert(CurIndex <= Op.OperandInfo->MIOperandNo &&
- "Duplicate match for instruction operand!");
-
- // Skip operands which weren't matched by anything, this occurs when the
- // .td file encodes "implicit" operands as explicit ones.
- //
- // FIXME: This should be removed from the MCInst structure.
- for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex) {
- std::pair<unsigned, unsigned> *Tie = GetTiedOperandAtIndex(TiedOperands,
- CurIndex);
- if (!Tie)
- Signature += "__Imp";
+ std::string CaseBody;
+ raw_string_ostream CaseOS(CaseBody);
+
+ // Compute the convert enum and the case body.
+ for (unsigned i = 0, e = II.ResOperands.size(); i != e; ++i) {
+ const MatchableInfo::ResOperand &OpInfo = II.ResOperands[i];
+
+ // Generate code to populate each result operand.
+ switch (OpInfo.Kind) {
+ case MatchableInfo::ResOperand::RenderAsmOperand: {
+ // This comes from something we parsed.
+ MatchableInfo::AsmOperand &Op = II.AsmOperands[OpInfo.AsmOperandNum];
+
+ // Registers are always converted the same, don't duplicate the
+ // conversion function based on them.
+ Signature += "__";
+ if (Op.Class->isRegisterClass())
+ Signature += "Reg";
else
- Signature += "__Tie" + utostr(Tie->second);
+ Signature += Op.Class->ClassName;
+ Signature += utostr(OpInfo.MINumOperands);
+ Signature += "_" + itostr(OpInfo.AsmOperandNum);
+
+ CaseOS << " ((" << TargetOperandClass << "*)Operands["
+ << (OpInfo.AsmOperandNum+1) << "])->" << Op.Class->RenderMethod
+ << "(Inst, " << OpInfo.MINumOperands << ");\n";
+ break;
}
- Signature += "__";
-
- // Registers are always converted the same, don't duplicate the conversion
- // function based on them.
- //
- // FIXME: We could generalize this based on the render method, if it
- // mattered.
- if (Op.Class->isRegisterClass())
- Signature += "Reg";
- else
- Signature += Op.Class->ClassName;
- Signature += utostr(Op.OperandInfo->MINumOperands);
- Signature += "_" + utostr(MIOperandList[i].second);
-
- CurIndex += Op.OperandInfo->MINumOperands;
- }
-
- // Add any trailing implicit operands.
- for (; CurIndex != NumMIOperands; ++CurIndex) {
- std::pair<unsigned, unsigned> *Tie = GetTiedOperandAtIndex(TiedOperands,
- CurIndex);
- if (!Tie)
- Signature += "__Imp";
- else
- Signature += "__Tie" + utostr(Tie->second);
+ case MatchableInfo::ResOperand::TiedOperand: {
+ // If this operand is tied to a previous one, just copy the MCInst
+ // operand from the earlier one.We can only tie single MCOperand values.
+ //assert(OpInfo.MINumOperands == 1 && "Not a singular MCOperand");
+ unsigned TiedOp = OpInfo.TiedOperandNum;
+ assert(i > TiedOp && "Tied operand precedes its target!");
+ CaseOS << " Inst.addOperand(Inst.getOperand(" << TiedOp << "));\n";
+ Signature += "__Tie" + utostr(TiedOp);
+ break;
+ }
+ case MatchableInfo::ResOperand::ImmOperand: {
+ int64_t Val = OpInfo.ImmVal;
+ CaseOS << " Inst.addOperand(MCOperand::CreateImm(" << Val << "));\n";
+ Signature += "__imm" + itostr(Val);
+ break;
+ }
+ case MatchableInfo::ResOperand::RegOperand: {
+ if (OpInfo.Register == 0) {
+ CaseOS << " Inst.addOperand(MCOperand::CreateReg(0));\n";
+ Signature += "__reg0";
+ } else {
+ std::string N = getQualifiedName(OpInfo.Register);
+ CaseOS << " Inst.addOperand(MCOperand::CreateReg(" << N << "));\n";
+ Signature += "__reg" + OpInfo.Register->getName();
+ }
+ }
+ }
}
II.ConversionFnKind = Signature;
@@ -1178,72 +1600,25 @@
if (!GeneratedFns.insert(Signature).second)
continue;
- // If not, emit it now.
-
- // Add to the enum list.
+ // If not, emit it now. Add to the enum list.
OS << " " << Signature << ",\n";
- // And to the convert function.
CvtOS << " case " << Signature << ":\n";
- CurIndex = 0;
- for (unsigned i = 0, e = MIOperandList.size(); i != e; ++i) {
- InstructionInfo::Operand &Op = II.Operands[MIOperandList[i].second];
-
- // Add the implicit operands.
- for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex) {
- // See if this is a tied operand.
- std::pair<unsigned, unsigned> *Tie = GetTiedOperandAtIndex(TiedOperands,
- CurIndex);
-
- if (!Tie) {
- // If not, this is some implicit operand. Just assume it is a register
- // for now.
- CvtOS << " Inst.addOperand(MCOperand::CreateReg(0));\n";
- } else {
- // Copy the tied operand.
- assert(Tie->first>Tie->second && "Tied operand preceeds its target!");
- CvtOS << " Inst.addOperand(Inst.getOperand("
- << Tie->second << "));\n";
- }
- }
-
- CvtOS << " ((" << TargetOperandClass << "*)Operands["
- << MIOperandList[i].second
- << "])->" << Op.Class->RenderMethod
- << "(Inst, " << Op.OperandInfo->MINumOperands << ");\n";
- CurIndex += Op.OperandInfo->MINumOperands;
- }
-
- // And add trailing implicit operands.
- for (; CurIndex != NumMIOperands; ++CurIndex) {
- std::pair<unsigned, unsigned> *Tie = GetTiedOperandAtIndex(TiedOperands,
- CurIndex);
-
- if (!Tie) {
- // If not, this is some implicit operand. Just assume it is a register
- // for now.
- CvtOS << " Inst.addOperand(MCOperand::CreateReg(0));\n";
- } else {
- // Copy the tied operand.
- assert(Tie->first>Tie->second && "Tied operand preceeds its target!");
- CvtOS << " Inst.addOperand(Inst.getOperand("
- << Tie->second << "));\n";
- }
- }
-
- CvtOS << " return;\n";
+ CvtOS << CaseOS.str();
+ CvtOS << " return true;\n";
}
// Finish the convert function.
CvtOS << " }\n";
+ CvtOS << " return false;\n";
CvtOS << "}\n\n";
// Finish the enum, and drop the convert function after it.
OS << " NumConversionVariants\n";
OS << "};\n\n";
-
+
OS << CvtOS.str();
}
@@ -1257,7 +1632,7 @@
<< "/// instruction matching.\n";
OS << "enum MatchClassKind {\n";
OS << " InvalidMatchClass = 0,\n";
- for (std::vector<ClassInfo*>::iterator it = Infos.begin(),
+ for (std::vector<ClassInfo*>::iterator it = Infos.begin(),
ie = Infos.end(); it != ie; ++it) {
ClassInfo &CI = **it;
OS << " " << CI.Name << ", // ";
@@ -1278,64 +1653,54 @@
OS << "}\n\n";
}
-/// EmitClassifyOperand - Emit the function to classify an operand.
-static void EmitClassifyOperand(CodeGenTarget &Target,
- AsmMatcherInfo &Info,
- raw_ostream &OS) {
- OS << "static MatchClassKind ClassifyOperand(MCParsedAsmOperand *GOp) {\n"
- << " " << Target.getName() << "Operand &Operand = *("
- << Target.getName() << "Operand*)GOp;\n";
+/// EmitValidateOperandClass - Emit the function to validate an operand class.
+static void EmitValidateOperandClass(AsmMatcherInfo &Info,
+ raw_ostream &OS) {
+ OS << "static bool ValidateOperandClass(MCParsedAsmOperand *GOp, "
+ << "MatchClassKind Kind) {\n";
+ OS << " " << Info.Target.getName() << "Operand &Operand = *("
+ << Info.Target.getName() << "Operand*)GOp;\n";
- // Classify tokens.
+ // The InvalidMatchClass is not to match any operand.
+ OS << " if (Kind == InvalidMatchClass)\n";
+ OS << " return false;\n\n";
+
+ // Check for Token operands first.
OS << " if (Operand.isToken())\n";
- OS << " return MatchTokenString(Operand.getToken());\n\n";
+ OS << " return MatchTokenString(Operand.getToken()) == Kind;\n\n";
- // Classify registers.
- //
- // FIXME: Don't hardcode isReg, getReg.
+ // Check for register operands, including sub-classes.
OS << " if (Operand.isReg()) {\n";
+ OS << " MatchClassKind OpKind;\n";
OS << " switch (Operand.getReg()) {\n";
- OS << " default: return InvalidMatchClass;\n";
- for (std::map<Record*, ClassInfo*>::iterator
+ OS << " default: OpKind = InvalidMatchClass; break;\n";
+ for (std::map<Record*, ClassInfo*>::iterator
it = Info.RegisterClasses.begin(), ie = Info.RegisterClasses.end();
it != ie; ++it)
- OS << " case " << Target.getName() << "::"
- << it->first->getName() << ": return " << it->second->Name << ";\n";
+ OS << " case " << Info.Target.getName() << "::"
+ << it->first->getName() << ": OpKind = " << it->second->Name
+ << "; break;\n";
OS << " }\n";
+ OS << " return IsSubclass(OpKind, Kind);\n";
OS << " }\n\n";
- // Classify user defined operands.
- for (std::vector<ClassInfo*>::iterator it = Info.Classes.begin(),
+ // Check the user classes. We don't care what order since we're only
+ // actually matching against one of them.
+ for (std::vector<ClassInfo*>::iterator it = Info.Classes.begin(),
ie = Info.Classes.end(); it != ie; ++it) {
ClassInfo &CI = **it;
if (!CI.isUserClass())
continue;
- OS << " // '" << CI.ClassName << "' class";
- if (!CI.SuperClasses.empty()) {
- OS << ", subclass of ";
- for (unsigned i = 0, e = CI.SuperClasses.size(); i != e; ++i) {
- if (i) OS << ", ";
- OS << "'" << CI.SuperClasses[i]->ClassName << "'";
- assert(CI < *CI.SuperClasses[i] && "Invalid class relation!");
- }
- }
- OS << "\n";
-
- OS << " if (Operand." << CI.PredicateMethod << "()) {\n";
-
- // Validate subclass relationships.
- if (!CI.SuperClasses.empty()) {
- for (unsigned i = 0, e = CI.SuperClasses.size(); i != e; ++i)
- OS << " assert(Operand." << CI.SuperClasses[i]->PredicateMethod
- << "() && \"Invalid class relationship!\");\n";
- }
-
- OS << " return " << CI.Name << ";\n";
+ OS << " // '" << CI.ClassName << "' class\n";
+ OS << " if (Kind == " << CI.Name
+ << " && Operand." << CI.PredicateMethod << "()) {\n";
+ OS << " return true;\n";
OS << " }\n\n";
}
- OS << " return InvalidMatchClass;\n";
+
+ OS << " return false;\n";
OS << "}\n\n";
}
@@ -1351,13 +1716,13 @@
OS << " switch (A) {\n";
OS << " default:\n";
OS << " return false;\n";
- for (std::vector<ClassInfo*>::iterator it = Infos.begin(),
+ for (std::vector<ClassInfo*>::iterator it = Infos.begin(),
ie = Infos.end(); it != ie; ++it) {
ClassInfo &A = **it;
if (A.Kind != ClassInfo::Token) {
std::vector<StringRef> SuperClasses;
- for (std::vector<ClassInfo*>::iterator it = Infos.begin(),
+ for (std::vector<ClassInfo*>::iterator it = Infos.begin(),
ie = Infos.end(); it != ie; ++it) {
ClassInfo &B = **it;
@@ -1386,153 +1751,25 @@
OS << "}\n\n";
}
-typedef std::pair<std::string, std::string> StringPair;
-
-/// FindFirstNonCommonLetter - Find the first character in the keys of the
-/// string pairs that is not shared across the whole set of strings. All
-/// strings are assumed to have the same length.
-static unsigned
-FindFirstNonCommonLetter(const std::vector<const StringPair*> &Matches) {
- assert(!Matches.empty());
- for (unsigned i = 0, e = Matches[0]->first.size(); i != e; ++i) {
- // Check to see if letter i is the same across the set.
- char Letter = Matches[0]->first[i];
-
- for (unsigned str = 0, e = Matches.size(); str != e; ++str)
- if (Matches[str]->first[i] != Letter)
- return i;
- }
-
- return Matches[0]->first.size();
-}
-
-/// EmitStringMatcherForChar - Given a set of strings that are known to be the
-/// same length and whose characters leading up to CharNo are the same, emit
-/// code to verify that CharNo and later are the same.
-///
-/// \return - True if control can leave the emitted code fragment.
-static bool EmitStringMatcherForChar(const std::string &StrVariableName,
- const std::vector<const StringPair*> &Matches,
- unsigned CharNo, unsigned IndentCount,
- raw_ostream &OS) {
- assert(!Matches.empty() && "Must have at least one string to match!");
- std::string Indent(IndentCount*2+4, ' ');
-
- // If we have verified that the entire string matches, we're done: output the
- // matching code.
- if (CharNo == Matches[0]->first.size()) {
- assert(Matches.size() == 1 && "Had duplicate keys to match on");
-
- // FIXME: If Matches[0].first has embeded \n, this will be bad.
- OS << Indent << Matches[0]->second << "\t // \"" << Matches[0]->first
- << "\"\n";
- return false;
- }
-
- // Bucket the matches by the character we are comparing.
- std::map<char, std::vector<const StringPair*> > MatchesByLetter;
-
- for (unsigned i = 0, e = Matches.size(); i != e; ++i)
- MatchesByLetter[Matches[i]->first[CharNo]].push_back(Matches[i]);
-
-
- // If we have exactly one bucket to match, see how many characters are common
- // across the whole set and match all of them at once.
- if (MatchesByLetter.size() == 1) {
- unsigned FirstNonCommonLetter = FindFirstNonCommonLetter(Matches);
- unsigned NumChars = FirstNonCommonLetter-CharNo;
-
- // Emit code to break out if the prefix doesn't match.
- if (NumChars == 1) {
- // Do the comparison with if (Str[1] != 'f')
- // FIXME: Need to escape general characters.
- OS << Indent << "if (" << StrVariableName << "[" << CharNo << "] != '"
- << Matches[0]->first[CharNo] << "')\n";
- OS << Indent << " break;\n";
- } else {
- // Do the comparison with if (Str.substr(1,3) != "foo").
- // FIXME: Need to escape general strings.
- OS << Indent << "if (" << StrVariableName << ".substr(" << CharNo << ","
- << NumChars << ") != \"";
- OS << Matches[0]->first.substr(CharNo, NumChars) << "\")\n";
- OS << Indent << " break;\n";
- }
-
- return EmitStringMatcherForChar(StrVariableName, Matches,
- FirstNonCommonLetter, IndentCount, OS);
- }
-
- // Otherwise, we have multiple possible things, emit a switch on the
- // character.
- OS << Indent << "switch (" << StrVariableName << "[" << CharNo << "]) {\n";
- OS << Indent << "default: break;\n";
-
- for (std::map<char, std::vector<const StringPair*> >::iterator LI =
- MatchesByLetter.begin(), E = MatchesByLetter.end(); LI != E; ++LI) {
- // TODO: escape hard stuff (like \n) if we ever care about it.
- OS << Indent << "case '" << LI->first << "':\t // "
- << LI->second.size() << " strings to match.\n";
- if (EmitStringMatcherForChar(StrVariableName, LI->second, CharNo+1,
- IndentCount+1, OS))
- OS << Indent << " break;\n";
- }
-
- OS << Indent << "}\n";
- return true;
-}
-
-
-/// EmitStringMatcher - Given a list of strings and code to execute when they
-/// match, output a simple switch tree to classify the input string.
-///
-/// If a match is found, the code in Vals[i].second is executed; control must
-/// not exit this code fragment. If nothing matches, execution falls through.
-///
-/// \param StrVariableName - The name of the variable to test.
-static void EmitStringMatcher(const std::string &StrVariableName,
- const std::vector<StringPair> &Matches,
- raw_ostream &OS) {
- // First level categorization: group strings by length.
- std::map<unsigned, std::vector<const StringPair*> > MatchesByLength;
-
- for (unsigned i = 0, e = Matches.size(); i != e; ++i)
- MatchesByLength[Matches[i].first.size()].push_back(&Matches[i]);
-
- // Output a switch statement on length and categorize the elements within each
- // bin.
- OS << " switch (" << StrVariableName << ".size()) {\n";
- OS << " default: break;\n";
-
- for (std::map<unsigned, std::vector<const StringPair*> >::iterator LI =
- MatchesByLength.begin(), E = MatchesByLength.end(); LI != E; ++LI) {
- OS << " case " << LI->first << ":\t // " << LI->second.size()
- << " strings to match.\n";
- if (EmitStringMatcherForChar(StrVariableName, LI->second, 0, 0, OS))
- OS << " break;\n";
- }
-
- OS << " }\n";
-}
-
-
/// EmitMatchTokenString - Emit the function to match a token string to the
/// appropriate match class value.
static void EmitMatchTokenString(CodeGenTarget &Target,
std::vector<ClassInfo*> &Infos,
raw_ostream &OS) {
// Construct the match list.
- std::vector<StringPair> Matches;
- for (std::vector<ClassInfo*>::iterator it = Infos.begin(),
+ std::vector<StringMatcher::StringPair> Matches;
+ for (std::vector<ClassInfo*>::iterator it = Infos.begin(),
ie = Infos.end(); it != ie; ++it) {
ClassInfo &CI = **it;
if (CI.Kind == ClassInfo::Token)
- Matches.push_back(StringPair(CI.ValueName, "return " + CI.Name + ";"));
+ Matches.push_back(StringMatcher::StringPair(CI.ValueName,
+ "return " + CI.Name + ";"));
}
OS << "static MatchClassKind MatchTokenString(StringRef Name) {\n";
- EmitStringMatcher("Name", Matches, OS);
+ StringMatcher("Name", Matches, OS).Emit();
OS << " return InvalidMatchClass;\n";
OS << "}\n\n";
@@ -1543,28 +1780,30 @@
static void EmitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser,
raw_ostream &OS) {
// Construct the match list.
- std::vector<StringPair> Matches;
- for (unsigned i = 0, e = Target.getRegisters().size(); i != e; ++i) {
- const CodeGenRegister &Reg = Target.getRegisters()[i];
- if (Reg.TheDef->getValueAsString("AsmName").empty())
+ std::vector<StringMatcher::StringPair> Matches;
+ const std::vector<CodeGenRegister*> &Regs =
+ Target.getRegBank().getRegisters();
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ const CodeGenRegister *Reg = Regs[i];
+ if (Reg->TheDef->getValueAsString("AsmName").empty())
continue;
- Matches.push_back(StringPair(Reg.TheDef->getValueAsString("AsmName"),
- "return " + utostr(i + 1) + ";"));
+ Matches.push_back(StringMatcher::StringPair(
+ Reg->TheDef->getValueAsString("AsmName"),
+ "return " + utostr(Reg->EnumValue) + ";"));
}
-
+
OS << "static unsigned MatchRegisterName(StringRef Name) {\n";
- EmitStringMatcher("Name", Matches, OS);
-
+ StringMatcher("Name", Matches, OS).Emit();
+
OS << " return 0;\n";
OS << "}\n\n";
}
/// EmitSubtargetFeatureFlagEnumeration - Emit the subtarget feature flag
/// definitions.
-static void EmitSubtargetFeatureFlagEnumeration(CodeGenTarget &Target,
- AsmMatcherInfo &Info,
+static void EmitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info,
raw_ostream &OS) {
OS << "// Flags for subtarget features that participate in "
<< "instruction matching.\n";
@@ -1573,7 +1812,7 @@
it = Info.SubtargetFeatures.begin(),
ie = Info.SubtargetFeatures.end(); it != ie; ++it) {
SubtargetFeatureInfo &SFI = *it->second;
- OS << " " << SFI.EnumName << " = (1 << " << SFI.Index << "),\n";
+ OS << " " << SFI.getEnumName() << " = (1 << " << SFI.Index << "),\n";
}
OS << " Feature_None = 0\n";
OS << "};\n\n";
@@ -1581,89 +1820,411 @@
/// EmitComputeAvailableFeatures - Emit the function to compute the list of
/// available features given a subtarget.
-static void EmitComputeAvailableFeatures(CodeGenTarget &Target,
- AsmMatcherInfo &Info,
+static void EmitComputeAvailableFeatures(AsmMatcherInfo &Info,
raw_ostream &OS) {
std::string ClassName =
Info.AsmParser->getValueAsString("AsmParserClassName");
- OS << "unsigned " << Target.getName() << ClassName << "::\n"
- << "ComputeAvailableFeatures(const " << Target.getName()
- << "Subtarget *Subtarget) const {\n";
+ OS << "unsigned " << Info.Target.getName() << ClassName << "::\n"
+ << "ComputeAvailableFeatures(uint64_t FB) const {\n";
OS << " unsigned Features = 0;\n";
for (std::map<Record*, SubtargetFeatureInfo*>::const_iterator
it = Info.SubtargetFeatures.begin(),
ie = Info.SubtargetFeatures.end(); it != ie; ++it) {
SubtargetFeatureInfo &SFI = *it->second;
- OS << " if (" << SFI.TheDef->getValueAsString("CondString")
- << ")\n";
- OS << " Features |= " << SFI.EnumName << ";\n";
+
+ OS << " if (";
+ std::string CondStorage = SFI.TheDef->getValueAsString("AssemblerCondString");
+ StringRef Conds = CondStorage;
+ std::pair<StringRef,StringRef> Comma = Conds.split(',');
+ bool First = true;
+ do {
+ if (!First)
+ OS << " && ";
+
+ bool Neg = false;
+ StringRef Cond = Comma.first;
+ if (Cond[0] == '!') {
+ Neg = true;
+ Cond = Cond.substr(1);
+ }
+
+ OS << "((FB & " << Info.Target.getName() << "::" << Cond << ")";
+ if (Neg)
+ OS << " == 0";
+ else
+ OS << " != 0";
+ OS << ")";
+
+ if (Comma.second.empty())
+ break;
+
+ First = false;
+ Comma = Comma.second.split(',');
+ } while (true);
+
+ OS << ")\n";
+ OS << " Features |= " << SFI.getEnumName() << ";\n";
}
OS << " return Features;\n";
OS << "}\n\n";
}
+static std::string GetAliasRequiredFeatures(Record *R,
+ const AsmMatcherInfo &Info) {
+ std::vector<Record*> ReqFeatures = R->getValueAsListOfDefs("Predicates");
+ std::string Result;
+ unsigned NumFeatures = 0;
+ for (unsigned i = 0, e = ReqFeatures.size(); i != e; ++i) {
+ SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]);
+
+ if (F == 0)
+ throw TGError(R->getLoc(), "Predicate '" + ReqFeatures[i]->getName() +
+ "' is not marked as an AssemblerPredicate!");
+
+ if (NumFeatures)
+ Result += '|';
+
+ Result += F->getEnumName();
+ ++NumFeatures;
+ }
+
+ if (NumFeatures > 1)
+ Result = '(' + Result + ')';
+ return Result;
+}
+
+/// EmitMnemonicAliases - If the target has any MnemonicAlias<> definitions,
+/// emit a function for them and return true, otherwise return false.
+static bool EmitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info) {
+ // Ignore aliases when match-prefix is set.
+ if (!MatchPrefix.empty())
+ return false;
+
+ std::vector<Record*> Aliases =
+ Info.getRecords().getAllDerivedDefinitions("MnemonicAlias");
+ if (Aliases.empty()) return false;
+
+ OS << "static void ApplyMnemonicAliases(StringRef &Mnemonic, "
+ "unsigned Features) {\n";
+
+ // Keep track of all the aliases from a mnemonic. Use an std::map so that the
+ // iteration order of the map is stable.
+ std::map<std::string, std::vector<Record*> > AliasesFromMnemonic;
+
+ for (unsigned i = 0, e = Aliases.size(); i != e; ++i) {
+ Record *R = Aliases[i];
+ AliasesFromMnemonic[R->getValueAsString("FromMnemonic")].push_back(R);
+ }
+
+ // Process each alias a "from" mnemonic at a time, building the code executed
+ // by the string remapper.
+ std::vector<StringMatcher::StringPair> Cases;
+ for (std::map<std::string, std::vector<Record*> >::iterator
+ I = AliasesFromMnemonic.begin(), E = AliasesFromMnemonic.end();
+ I != E; ++I) {
+ const std::vector<Record*> &ToVec = I->second;
+
+ // Loop through each alias and emit code that handles each case. If there
+ // are two instructions without predicates, emit an error. If there is one,
+ // emit it last.
+ std::string MatchCode;
+ int AliasWithNoPredicate = -1;
+
+ for (unsigned i = 0, e = ToVec.size(); i != e; ++i) {
+ Record *R = ToVec[i];
+ std::string FeatureMask = GetAliasRequiredFeatures(R, Info);
+
+ // If this unconditionally matches, remember it for later and diagnose
+ // duplicates.
+ if (FeatureMask.empty()) {
+ if (AliasWithNoPredicate != -1) {
+ // We can't have two aliases from the same mnemonic with no predicate.
+ PrintError(ToVec[AliasWithNoPredicate]->getLoc(),
+ "two MnemonicAliases with the same 'from' mnemonic!");
+ throw TGError(R->getLoc(), "this is the other MnemonicAlias.");
+ }
+
+ AliasWithNoPredicate = i;
+ continue;
+ }
+ if (R->getValueAsString("ToMnemonic") == I->first)
+ throw TGError(R->getLoc(), "MnemonicAlias to the same string");
+
+ if (!MatchCode.empty())
+ MatchCode += "else ";
+ MatchCode += "if ((Features & " + FeatureMask + ") == "+FeatureMask+")\n";
+ MatchCode += " Mnemonic = \"" +R->getValueAsString("ToMnemonic")+"\";\n";
+ }
+
+ if (AliasWithNoPredicate != -1) {
+ Record *R = ToVec[AliasWithNoPredicate];
+ if (!MatchCode.empty())
+ MatchCode += "else\n ";
+ MatchCode += "Mnemonic = \"" + R->getValueAsString("ToMnemonic")+"\";\n";
+ }
+
+ MatchCode += "return;";
+
+ Cases.push_back(std::make_pair(I->first, MatchCode));
+ }
+
+ StringMatcher("Mnemonic", Cases, OS).Emit();
+ OS << "}\n\n";
+
+ return true;
+}
+
+static void EmitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
+ const AsmMatcherInfo &Info, StringRef ClassName) {
+ // Emit the static custom operand parsing table;
+ OS << "namespace {\n";
+ OS << " struct OperandMatchEntry {\n";
+ OS << " const char *Mnemonic;\n";
+ OS << " unsigned OperandMask;\n";
+ OS << " MatchClassKind Class;\n";
+ OS << " unsigned RequiredFeatures;\n";
+ OS << " };\n\n";
+
+ OS << " // Predicate for searching for an opcode.\n";
+ OS << " struct LessOpcodeOperand {\n";
+ OS << " bool operator()(const OperandMatchEntry &LHS, StringRef RHS) {\n";
+ OS << " return StringRef(LHS.Mnemonic) < RHS;\n";
+ OS << " }\n";
+ OS << " bool operator()(StringRef LHS, const OperandMatchEntry &RHS) {\n";
+ OS << " return LHS < StringRef(RHS.Mnemonic);\n";
+ OS << " }\n";
+ OS << " bool operator()(const OperandMatchEntry &LHS,";
+ OS << " const OperandMatchEntry &RHS) {\n";
+ OS << " return StringRef(LHS.Mnemonic) < StringRef(RHS.Mnemonic);\n";
+ OS << " }\n";
+ OS << " };\n";
+
+ OS << "} // end anonymous namespace.\n\n";
+
+ OS << "static const OperandMatchEntry OperandMatchTable["
+ << Info.OperandMatchInfo.size() << "] = {\n";
+
+ OS << " /* Mnemonic, Operand List Mask, Operand Class, Features */\n";
+ for (std::vector<OperandMatchEntry>::const_iterator it =
+ Info.OperandMatchInfo.begin(), ie = Info.OperandMatchInfo.end();
+ it != ie; ++it) {
+ const OperandMatchEntry &OMI = *it;
+ const MatchableInfo &II = *OMI.MI;
+
+ OS << " { \"" << II.Mnemonic << "\""
+ << ", " << OMI.OperandMask;
+
+ OS << " /* ";
+ bool printComma = false;
+ for (int i = 0, e = 31; i !=e; ++i)
+ if (OMI.OperandMask & (1 << i)) {
+ if (printComma)
+ OS << ", ";
+ OS << i;
+ printComma = true;
+ }
+ OS << " */";
+
+ OS << ", " << OMI.CI->Name
+ << ", ";
+
+ // Write the required features mask.
+ if (!II.RequiredFeatures.empty()) {
+ for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) {
+ if (i) OS << "|";
+ OS << II.RequiredFeatures[i]->getEnumName();
+ }
+ } else
+ OS << "0";
+ OS << " },\n";
+ }
+ OS << "};\n\n";
+
+ // Emit the operand class switch to call the correct custom parser for
+ // the found operand class.
+ OS << Target.getName() << ClassName << "::OperandMatchResultTy "
+ << Target.getName() << ClassName << "::\n"
+ << "TryCustomParseOperand(SmallVectorImpl<MCParsedAsmOperand*>"
+ << " &Operands,\n unsigned MCK) {\n\n"
+ << " switch(MCK) {\n";
+
+ for (std::vector<ClassInfo*>::const_iterator it = Info.Classes.begin(),
+ ie = Info.Classes.end(); it != ie; ++it) {
+ ClassInfo *CI = *it;
+ if (CI->ParserMethod.empty())
+ continue;
+ OS << " case " << CI->Name << ":\n"
+ << " return " << CI->ParserMethod << "(Operands);\n";
+ }
+
+ OS << " default:\n";
+ OS << " return MatchOperand_NoMatch;\n";
+ OS << " }\n";
+ OS << " return MatchOperand_NoMatch;\n";
+ OS << "}\n\n";
+
+ // Emit the static custom operand parser. This code is very similar with
+ // the other matcher. Also use MatchResultTy here just in case we go for
+ // a better error handling.
+ OS << Target.getName() << ClassName << "::OperandMatchResultTy "
+ << Target.getName() << ClassName << "::\n"
+ << "MatchOperandParserImpl(SmallVectorImpl<MCParsedAsmOperand*>"
+ << " &Operands,\n StringRef Mnemonic) {\n";
+
+ // Emit code to get the available features.
+ OS << " // Get the current feature set.\n";
+ OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n";
+
+ OS << " // Get the next operand index.\n";
+ OS << " unsigned NextOpNum = Operands.size()-1;\n";
+
+ // Emit code to search the table.
+ OS << " // Search the table.\n";
+ OS << " std::pair<const OperandMatchEntry*, const OperandMatchEntry*>";
+ OS << " MnemonicRange =\n";
+ OS << " std::equal_range(OperandMatchTable, OperandMatchTable+"
+ << Info.OperandMatchInfo.size() << ", Mnemonic,\n"
+ << " LessOpcodeOperand());\n\n";
+
+ OS << " if (MnemonicRange.first == MnemonicRange.second)\n";
+ OS << " return MatchOperand_NoMatch;\n\n";
+
+ OS << " for (const OperandMatchEntry *it = MnemonicRange.first,\n"
+ << " *ie = MnemonicRange.second; it != ie; ++it) {\n";
+
+ OS << " // equal_range guarantees that instruction mnemonic matches.\n";
+ OS << " assert(Mnemonic == it->Mnemonic);\n\n";
+
+ // Emit check that the required features are available.
+ OS << " // check if the available features match\n";
+ OS << " if ((AvailableFeatures & it->RequiredFeatures) "
+ << "!= it->RequiredFeatures) {\n";
+ OS << " continue;\n";
+ OS << " }\n\n";
+
+ // Emit check to ensure the operand number matches.
+ OS << " // check if the operand in question has a custom parser.\n";
+ OS << " if (!(it->OperandMask & (1 << NextOpNum)))\n";
+ OS << " continue;\n\n";
+
+ // Emit call to the custom parser method
+ OS << " // call custom parse method to handle the operand\n";
+ OS << " OperandMatchResultTy Result = ";
+ OS << "TryCustomParseOperand(Operands, it->Class);\n";
+ OS << " if (Result != MatchOperand_NoMatch)\n";
+ OS << " return Result;\n";
+ OS << " }\n\n";
+
+ OS << " // Okay, we had no match.\n";
+ OS << " return MatchOperand_NoMatch;\n";
+ OS << "}\n\n";
+}
+
void AsmMatcherEmitter::run(raw_ostream &OS) {
- CodeGenTarget Target;
+ CodeGenTarget Target(Records);
Record *AsmParser = Target.getAsmParser();
std::string ClassName = AsmParser->getValueAsString("AsmParserClassName");
// Compute the information on the instructions to match.
- AsmMatcherInfo Info(AsmParser);
- Info.BuildInfo(Target);
+ AsmMatcherInfo Info(AsmParser, Target, Records);
+ Info.BuildInfo();
// Sort the instruction table using the partial order on classes. We use
// stable_sort to ensure that ambiguous instructions are still
// deterministically ordered.
- std::stable_sort(Info.Instructions.begin(), Info.Instructions.end(),
- less_ptr<InstructionInfo>());
-
+ std::stable_sort(Info.Matchables.begin(), Info.Matchables.end(),
+ less_ptr<MatchableInfo>());
+
DEBUG_WITH_TYPE("instruction_info", {
- for (std::vector<InstructionInfo*>::iterator
- it = Info.Instructions.begin(), ie = Info.Instructions.end();
+ for (std::vector<MatchableInfo*>::iterator
+ it = Info.Matchables.begin(), ie = Info.Matchables.end();
it != ie; ++it)
(*it)->dump();
});
- // Check for ambiguous instructions.
- unsigned NumAmbiguous = 0;
- for (unsigned i = 0, e = Info.Instructions.size(); i != e; ++i) {
- for (unsigned j = i + 1; j != e; ++j) {
- InstructionInfo &A = *Info.Instructions[i];
- InstructionInfo &B = *Info.Instructions[j];
-
- if (A.CouldMatchAmiguouslyWith(B)) {
- DEBUG_WITH_TYPE("ambiguous_instrs", {
- errs() << "warning: ambiguous instruction match:\n";
- A.dump();
- errs() << "\nis incomparable with:\n";
- B.dump();
- errs() << "\n\n";
- });
- ++NumAmbiguous;
+ // Check for ambiguous matchables.
+ DEBUG_WITH_TYPE("ambiguous_instrs", {
+ unsigned NumAmbiguous = 0;
+ for (unsigned i = 0, e = Info.Matchables.size(); i != e; ++i) {
+ for (unsigned j = i + 1; j != e; ++j) {
+ MatchableInfo &A = *Info.Matchables[i];
+ MatchableInfo &B = *Info.Matchables[j];
+
+ if (A.CouldMatchAmbiguouslyWith(B)) {
+ errs() << "warning: ambiguous matchables:\n";
+ A.dump();
+ errs() << "\nis incomparable with:\n";
+ B.dump();
+ errs() << "\n\n";
+ ++NumAmbiguous;
+ }
}
}
- }
- if (NumAmbiguous)
- DEBUG_WITH_TYPE("ambiguous_instrs", {
- errs() << "warning: " << NumAmbiguous
- << " ambiguous instructions!\n";
- });
+ if (NumAmbiguous)
+ errs() << "warning: " << NumAmbiguous
+ << " ambiguous matchables!\n";
+ });
+
+ // Compute the information on the custom operand parsing.
+ Info.BuildOperandMatchInfo();
// Write the output.
EmitSourceFileHeader("Assembly Matcher Source Fragment", OS);
+ // Information for the class declaration.
+ OS << "\n#ifdef GET_ASSEMBLER_HEADER\n";
+ OS << "#undef GET_ASSEMBLER_HEADER\n";
+ OS << " // This should be included into the middle of the declaration of\n";
+ OS << " // your subclasses implementation of MCTargetAsmParser.\n";
+ OS << " unsigned ComputeAvailableFeatures(uint64_t FeatureBits) const;\n";
+ OS << " bool ConvertToMCInst(unsigned Kind, MCInst &Inst, "
+ << "unsigned Opcode,\n"
+ << " const SmallVectorImpl<MCParsedAsmOperand*> "
+ << "&Operands);\n";
+ OS << " bool MnemonicIsValid(StringRef Mnemonic);\n";
+ OS << " unsigned MatchInstructionImpl(\n";
+ OS << " const SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n";
+ OS << " MCInst &Inst, unsigned &ErrorInfo);\n";
+
+ if (Info.OperandMatchInfo.size()) {
+ OS << "\n enum OperandMatchResultTy {\n";
+ OS << " MatchOperand_Success, // operand matched successfully\n";
+ OS << " MatchOperand_NoMatch, // operand did not match\n";
+ OS << " MatchOperand_ParseFail // operand matched but had errors\n";
+ OS << " };\n";
+ OS << " OperandMatchResultTy MatchOperandParserImpl(\n";
+ OS << " SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n";
+ OS << " StringRef Mnemonic);\n";
+
+ OS << " OperandMatchResultTy TryCustomParseOperand(\n";
+ OS << " SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n";
+ OS << " unsigned MCK);\n\n";
+ }
+
+ OS << "#endif // GET_ASSEMBLER_HEADER_INFO\n\n";
+
+ OS << "\n#ifdef GET_REGISTER_MATCHER\n";
+ OS << "#undef GET_REGISTER_MATCHER\n\n";
+
// Emit the subtarget feature enumeration.
- EmitSubtargetFeatureFlagEnumeration(Target, Info, OS);
+ EmitSubtargetFeatureFlagEnumeration(Info, OS);
// Emit the function to match a register name to number.
EmitMatchRegisterName(Target, AsmParser, OS);
-
- OS << "#ifndef REGISTERS_ONLY\n\n";
+
+ OS << "#endif // GET_REGISTER_MATCHER\n\n";
+
+
+ OS << "\n#ifdef GET_MATCHER_IMPLEMENTATION\n";
+ OS << "#undef GET_MATCHER_IMPLEMENTATION\n\n";
+
+ // Generate the function that remaps for mnemonic aliases.
+ bool HasMnemonicAliases = EmitMnemonicAliases(OS, Info);
// Generate the unified function to convert operands into an MCInst.
- EmitConvertToMCInst(Target, Info.Instructions, OS);
+ EmitConvertToMCInst(Target, ClassName, Info.Matchables, OS);
// Emit the enumeration for classes which participate in matching.
EmitMatchClassEnumeration(Target, Info.Classes, OS);
@@ -1671,30 +2232,21 @@
// Emit the routine to match token strings to their match class.
EmitMatchTokenString(Target, Info.Classes, OS);
- // Emit the routine to classify an operand.
- EmitClassifyOperand(Target, Info, OS);
-
// Emit the subclass predicate routine.
EmitIsSubclass(Target, Info.Classes, OS);
- // Emit the available features compute function.
- EmitComputeAvailableFeatures(Target, Info, OS);
+ // Emit the routine to validate an operand against a match class.
+ EmitValidateOperandClass(Info, OS);
- // Finally, build the match function.
+ // Emit the available features compute function.
+ EmitComputeAvailableFeatures(Info, OS);
+
size_t MaxNumOperands = 0;
- for (std::vector<InstructionInfo*>::const_iterator it =
- Info.Instructions.begin(), ie = Info.Instructions.end();
+ for (std::vector<MatchableInfo*>::const_iterator it =
+ Info.Matchables.begin(), ie = Info.Matchables.end();
it != ie; ++it)
- MaxNumOperands = std::max(MaxNumOperands, (*it)->Operands.size());
-
- const std::string &MatchName =
- AsmParser->getValueAsString("MatchInstructionName");
- OS << "bool " << Target.getName() << ClassName << "::\n"
- << MatchName
- << "(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n";
- OS.indent(MatchName.size() + 1);
- OS << "MCInst &Inst) {\n";
+ MaxNumOperands = std::max(MaxNumOperands, (*it)->AsmOperands.size());
// Emit the static match table; unused classes get initalized to 0 which is
// guaranteed to be InvalidMatchClass.
@@ -1706,23 +2258,44 @@
// order the match kinds appropriately (putting mnemonics last), then we
// should only end up using a few bits for each class, especially the ones
// following the mnemonic.
- OS << " static const struct MatchEntry {\n";
+ OS << "namespace {\n";
+ OS << " struct MatchEntry {\n";
OS << " unsigned Opcode;\n";
+ OS << " const char *Mnemonic;\n";
OS << " ConversionKind ConvertFn;\n";
OS << " MatchClassKind Classes[" << MaxNumOperands << "];\n";
OS << " unsigned RequiredFeatures;\n";
- OS << " } MatchTable[" << Info.Instructions.size() << "] = {\n";
+ OS << " };\n\n";
- for (std::vector<InstructionInfo*>::const_iterator it =
- Info.Instructions.begin(), ie = Info.Instructions.end();
+ OS << " // Predicate for searching for an opcode.\n";
+ OS << " struct LessOpcode {\n";
+ OS << " bool operator()(const MatchEntry &LHS, StringRef RHS) {\n";
+ OS << " return StringRef(LHS.Mnemonic) < RHS;\n";
+ OS << " }\n";
+ OS << " bool operator()(StringRef LHS, const MatchEntry &RHS) {\n";
+ OS << " return LHS < StringRef(RHS.Mnemonic);\n";
+ OS << " }\n";
+ OS << " bool operator()(const MatchEntry &LHS, const MatchEntry &RHS) {\n";
+ OS << " return StringRef(LHS.Mnemonic) < StringRef(RHS.Mnemonic);\n";
+ OS << " }\n";
+ OS << " };\n";
+
+ OS << "} // end anonymous namespace.\n\n";
+
+ OS << "static const MatchEntry MatchTable["
+ << Info.Matchables.size() << "] = {\n";
+
+ for (std::vector<MatchableInfo*>::const_iterator it =
+ Info.Matchables.begin(), ie = Info.Matchables.end();
it != ie; ++it) {
- InstructionInfo &II = **it;
+ MatchableInfo &II = **it;
- OS << " { " << Target.getName() << "::" << II.InstrName
+ OS << " { " << Target.getName() << "::"
+ << II.getResultInst()->TheDef->getName() << ", \"" << II.Mnemonic << "\""
<< ", " << II.ConversionFnKind << ", { ";
- for (unsigned i = 0, e = II.Operands.size(); i != e; ++i) {
- InstructionInfo::Operand &Op = II.Operands[i];
-
+ for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) {
+ MatchableInfo::AsmOperand &Op = II.AsmOperands[i];
+
if (i) OS << ", ";
OS << Op.Class->Name;
}
@@ -1732,7 +2305,7 @@
if (!II.RequiredFeatures.empty()) {
for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) {
if (i) OS << "|";
- OS << II.RequiredFeatures[i]->EnumName;
+ OS << II.RequiredFeatures[i]->getEnumName();
}
} else
OS << "0";
@@ -1740,52 +2313,115 @@
OS << "},\n";
}
- OS << " };\n\n";
+ OS << "};\n\n";
+ // A method to determine if a mnemonic is in the list.
+ OS << "bool " << Target.getName() << ClassName << "::\n"
+ << "MnemonicIsValid(StringRef Mnemonic) {\n";
+ OS << " // Search the table.\n";
+ OS << " std::pair<const MatchEntry*, const MatchEntry*> MnemonicRange =\n";
+ OS << " std::equal_range(MatchTable, MatchTable+"
+ << Info.Matchables.size() << ", Mnemonic, LessOpcode());\n";
+ OS << " return MnemonicRange.first != MnemonicRange.second;\n";
+ OS << "}\n\n";
+
+ // Finally, build the match function.
+ OS << "unsigned "
+ << Target.getName() << ClassName << "::\n"
+ << "MatchInstructionImpl(const SmallVectorImpl<MCParsedAsmOperand*>"
+ << " &Operands,\n";
+ OS << " MCInst &Inst, unsigned &ErrorInfo) {\n";
// Emit code to get the available features.
OS << " // Get the current feature set.\n";
OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n";
+ OS << " // Get the instruction mnemonic, which is the first token.\n";
+ OS << " StringRef Mnemonic = ((" << Target.getName()
+ << "Operand*)Operands[0])->getToken();\n\n";
+
+ if (HasMnemonicAliases) {
+ OS << " // Process all MnemonicAliases to remap the mnemonic.\n";
+ OS << " ApplyMnemonicAliases(Mnemonic, AvailableFeatures);\n\n";
+ }
+
// Emit code to compute the class list for this operand vector.
OS << " // Eliminate obvious mismatches.\n";
- OS << " if (Operands.size() > " << MaxNumOperands << ")\n";
- OS << " return true;\n\n";
-
- OS << " // Compute the class list for this operand vector.\n";
- OS << " MatchClassKind Classes[" << MaxNumOperands << "];\n";
- OS << " for (unsigned i = 0, e = Operands.size(); i != e; ++i) {\n";
- OS << " Classes[i] = ClassifyOperand(Operands[i]);\n\n";
-
- OS << " // Check for invalid operands before matching.\n";
- OS << " if (Classes[i] == InvalidMatchClass)\n";
- OS << " return true;\n";
+ OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n";
+ OS << " ErrorInfo = " << (MaxNumOperands+1) << ";\n";
+ OS << " return Match_InvalidOperand;\n";
OS << " }\n\n";
- OS << " // Mark unused classes.\n";
- OS << " for (unsigned i = Operands.size(), e = " << MaxNumOperands << "; "
- << "i != e; ++i)\n";
- OS << " Classes[i] = InvalidMatchClass;\n\n";
+ OS << " // Some state to try to produce better error messages.\n";
+ OS << " bool HadMatchOtherThanFeatures = false;\n";
+ OS << " bool HadMatchOtherThanPredicate = false;\n";
+ OS << " unsigned RetCode = Match_InvalidOperand;\n";
+ OS << " // Set ErrorInfo to the operand that mismatches if it is\n";
+ OS << " // wrong for all instances of the instruction.\n";
+ OS << " ErrorInfo = ~0U;\n";
// Emit code to search the table.
OS << " // Search the table.\n";
- OS << " for (const MatchEntry *it = MatchTable, "
- << "*ie = MatchTable + " << Info.Instructions.size()
- << "; it != ie; ++it) {\n";
+ OS << " std::pair<const MatchEntry*, const MatchEntry*> MnemonicRange =\n";
+ OS << " std::equal_range(MatchTable, MatchTable+"
+ << Info.Matchables.size() << ", Mnemonic, LessOpcode());\n\n";
- // Emit check that the required features are available.
- OS << " if ((AvailableFeatures & it->RequiredFeatures) "
- << "!= it->RequiredFeatures)\n";
- OS << " continue;\n";
+ OS << " // Return a more specific error code if no mnemonics match.\n";
+ OS << " if (MnemonicRange.first == MnemonicRange.second)\n";
+ OS << " return Match_MnemonicFail;\n\n";
+
+ OS << " for (const MatchEntry *it = MnemonicRange.first, "
+ << "*ie = MnemonicRange.second;\n";
+ OS << " it != ie; ++it) {\n";
+
+ OS << " // equal_range guarantees that instruction mnemonic matches.\n";
+ OS << " assert(Mnemonic == it->Mnemonic);\n";
// Emit check that the subclasses match.
- for (unsigned i = 0; i != MaxNumOperands; ++i) {
- OS << " if (!IsSubclass(Classes["
- << i << "], it->Classes[" << i << "]))\n";
- OS << " continue;\n";
- }
+ OS << " bool OperandsValid = true;\n";
+ OS << " for (unsigned i = 0; i != " << MaxNumOperands << "; ++i) {\n";
+ OS << " if (i + 1 >= Operands.size()) {\n";
+ OS << " OperandsValid = (it->Classes[i] == " <<"InvalidMatchClass);\n";
+ OS << " break;\n";
+ OS << " }\n";
+ OS << " if (ValidateOperandClass(Operands[i+1], it->Classes[i]))\n";
+ OS << " continue;\n";
+ OS << " // If this operand is broken for all of the instances of this\n";
+ OS << " // mnemonic, keep track of it so we can report loc info.\n";
+ OS << " if (it == MnemonicRange.first || ErrorInfo <= i+1)\n";
+ OS << " ErrorInfo = i+1;\n";
+ OS << " // Otherwise, just reject this instance of the mnemonic.\n";
+ OS << " OperandsValid = false;\n";
+ OS << " break;\n";
+ OS << " }\n\n";
+
+ OS << " if (!OperandsValid) continue;\n";
+
+ // Emit check that the required features are available.
+ OS << " if ((AvailableFeatures & it->RequiredFeatures) "
+ << "!= it->RequiredFeatures) {\n";
+ OS << " HadMatchOtherThanFeatures = true;\n";
+ OS << " continue;\n";
+ OS << " }\n";
OS << "\n";
- OS << " ConvertToMCInst(it->ConvertFn, Inst, it->Opcode, Operands);\n";
+ OS << " // We have selected a definite instruction, convert the parsed\n"
+ << " // operands into the appropriate MCInst.\n";
+ OS << " if (!ConvertToMCInst(it->ConvertFn, Inst,\n"
+ << " it->Opcode, Operands))\n";
+ OS << " return Match_ConversionFail;\n";
+ OS << "\n";
+
+ // Verify the instruction with the target-specific match predicate function.
+ OS << " // We have a potential match. Check the target predicate to\n"
+ << " // handle any context sensitive constraints.\n"
+ << " unsigned MatchResult;\n"
+ << " if ((MatchResult = checkTargetMatchPredicate(Inst)) !="
+ << " Match_Success) {\n"
+ << " Inst.clear();\n"
+ << " RetCode = MatchResult;\n"
+ << " HadMatchOtherThanPredicate = true;\n"
+ << " continue;\n"
+ << " }\n\n";
// Call the post-processing function, if used.
std::string InsnCleanupFn =
@@ -1793,11 +2429,17 @@
if (!InsnCleanupFn.empty())
OS << " " << InsnCleanupFn << "(Inst);\n";
- OS << " return false;\n";
+ OS << " return Match_Success;\n";
OS << " }\n\n";
- OS << " return true;\n";
+ OS << " // Okay, we had no match. Try to return a useful error code.\n";
+ OS << " if (HadMatchOtherThanPredicate || !HadMatchOtherThanFeatures)";
+ OS << " return RetCode;\n";
+ OS << " return Match_MissingFeature;\n";
OS << "}\n\n";
-
- OS << "#endif // REGISTERS_ONLY\n";
+
+ if (Info.OperandMatchInfo.size())
+ EmitCustomOperandParsing(OS, Target, Info, ClassName);
+
+ OS << "#endif // GET_MATCHER_IMPLEMENTATION\n\n";
}
diff --git a/src/LLVM/utils/TableGen/AsmMatcherEmitter.h b/src/LLVM/utils/TableGen/AsmMatcherEmitter.h
index 729c938..e04ac10 100644
--- a/src/LLVM/utils/TableGen/AsmMatcherEmitter.h
+++ b/src/LLVM/utils/TableGen/AsmMatcherEmitter.h
@@ -15,9 +15,7 @@
#ifndef ASMMATCHER_EMITTER_H
#define ASMMATCHER_EMITTER_H
-#include "TableGenBackend.h"
-#include <map>
-#include <vector>
+#include "llvm/TableGen/TableGenBackend.h"
#include <cassert>
namespace llvm {
diff --git a/src/LLVM/utils/TableGen/AsmWriterEmitter.cpp b/src/LLVM/utils/TableGen/AsmWriterEmitter.cpp
index 23f13c2..3123e11 100644
--- a/src/LLVM/utils/TableGen/AsmWriterEmitter.cpp
+++ b/src/LLVM/utils/TableGen/AsmWriterEmitter.cpp
@@ -15,10 +15,12 @@
#include "AsmWriterEmitter.h"
#include "AsmWriterInst.h"
#include "CodeGenTarget.h"
-#include "Record.h"
#include "StringToOffsetTable.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
#include <algorithm>
using namespace llvm;
@@ -101,22 +103,22 @@
}
void AsmWriterEmitter::
-FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
+FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
std::vector<unsigned> &InstIdxs,
std::vector<unsigned> &InstOpsUsed) const {
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
// enums.
std::vector<std::string> InstrsForCase;
InstrsForCase.resize(UniqueOperandCommands.size());
InstOpsUsed.assign(UniqueOperandCommands.size(), 0);
-
+
for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
const AsmWriterInst *Inst = getAsmWriterInstByID(i);
if (Inst == 0) continue; // PHI, INLINEASM, PROLOG_LABEL, etc.
-
+
std::string Command;
if (Inst->Operands.empty())
continue; // Instruction already done.
@@ -143,13 +145,13 @@
InstOpsUsed.push_back(1);
}
}
-
+
// For each entry of UniqueOperandCommands, there is a set of instructions
// that uses it. If the next command of all instructions in the set are
// identical, fold it into the command.
for (unsigned CommandIdx = 0, e = UniqueOperandCommands.size();
CommandIdx != e; ++CommandIdx) {
-
+
for (unsigned Op = 1; ; ++Op) {
// Scan for the first instruction in the set.
std::vector<unsigned>::iterator NIT =
@@ -158,7 +160,7 @@
// If this instruction has no more operands, we isn't anything to merge
// into this command.
- const AsmWriterInst *FirstInst =
+ const AsmWriterInst *FirstInst =
getAsmWriterInstByID(NIT-InstIdxs.begin());
if (!FirstInst || FirstInst->Operands.size() == Op)
break;
@@ -175,7 +177,7 @@
NIT = std::find(NIT+1, InstIdxs.end(), CommandIdx)) {
// Okay, found another instruction in this command set. If the operand
// matches, we're ok, otherwise bail out.
- const AsmWriterInst *OtherInst =
+ const AsmWriterInst *OtherInst =
getAsmWriterInstByID(NIT-InstIdxs.begin());
if (OtherInst &&
@@ -189,16 +191,16 @@
}
}
if (!AllSame) break;
-
+
// Okay, everything in this command set has the same next operand. Add it
// to UniqueOperandCommands and remember that it was consumed.
std::string Command = " " + FirstInst->Operands[Op].getCode() + "\n";
-
+
UniqueOperandCommands[CommandIdx] += Command;
InstOpsUsed[CommandIdx]++;
}
}
-
+
// Prepend some of the instructions each case is used for onto the case val.
for (unsigned i = 0, e = InstrsForCase.size(); i != e; ++i) {
std::string Instrs = InstrsForCase[i];
@@ -206,9 +208,9 @@
Instrs.erase(Instrs.begin()+70, Instrs.end());
Instrs += "...";
}
-
+
if (!Instrs.empty())
- UniqueOperandCommands[i] = " // " + Instrs + "\n" +
+ UniqueOperandCommands[i] = " // " + Instrs + "\n" +
UniqueOperandCommands[i];
}
}
@@ -240,15 +242,18 @@
/// EmitPrintInstruction - Generate the code for the "printInstruction" method
/// implementation.
void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
- CodeGenTarget Target;
+ CodeGenTarget Target(Records);
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 MachineInstr *MI, raw_ostream &O) {\n";
+ << "::printInstruction(const " << MachineInstrClassName
+ << " *MI, raw_ostream &O) {\n";
std::vector<AsmWriterInst> Instructions;
@@ -257,14 +262,14 @@
if (!(*I)->AsmString.empty() &&
(*I)->TheDef->getName() != "PHI")
Instructions.push_back(
- AsmWriterInst(**I,
+ AsmWriterInst(**I,
AsmWriter->getValueAsInt("Variant"),
AsmWriter->getValueAsInt("FirstOperandColumn"),
AsmWriter->getValueAsInt("OperandSpacing")));
// Get the instruction numbering.
NumberedInstructions = Target.getInstructionsByEnumValue();
-
+
// Compute the CodeGenInstruction -> AsmWriterInst mapping. Note that not
// all machine instructions are necessarily being printed, so there may be
// target instructions not in this map.
@@ -273,11 +278,11 @@
// Build an aggregate string, and build a table of offsets into it.
StringToOffsetTable StringTable;
-
+
/// OpcodeInfo - This encodes the index of the string to use for the first
/// chunk of the output as well as indices used for operand printing.
std::vector<unsigned> OpcodeInfo;
-
+
unsigned MaxStringIdx = 0;
for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]];
@@ -285,7 +290,7 @@
if (AWI == 0) {
// Something not handled by the asmwriter printer.
Idx = ~0U;
- } else if (AWI->Operands[0].OperandType !=
+ } else if (AWI->Operands[0].OperandType !=
AsmWriterOperand::isLiteralTextOperand ||
AWI->Operands[0].Str.empty()) {
// Something handled by the asmwriter printer, but with no leading string.
@@ -295,51 +300,51 @@
UnescapeString(Str);
Idx = StringTable.GetOrAddStringOffset(Str);
MaxStringIdx = std::max(MaxStringIdx, Idx);
-
+
// Nuke the string from the operand list. It is now handled!
AWI->Operands.erase(AWI->Operands.begin());
}
-
+
// Bias offset by one since we want 0 as a sentinel.
OpcodeInfo.push_back(Idx+1);
}
-
+
// Figure out how many bits we used for the string index.
unsigned AsmStrBits = Log2_32_Ceil(MaxStringIdx+2);
-
+
// To reduce code size, we compactify common instructions into a few bits
// in the opcode-indexed table.
unsigned BitsLeft = 32-AsmStrBits;
std::vector<std::vector<std::string> > TableDrivenOperandPrinters;
-
+
while (1) {
std::vector<std::string> UniqueOperandCommands;
std::vector<unsigned> InstIdxs;
std::vector<unsigned> NumInstOpsHandled;
FindUniqueOperandCommands(UniqueOperandCommands, InstIdxs,
NumInstOpsHandled);
-
+
// If we ran out of operands to print, we're done.
if (UniqueOperandCommands.empty()) break;
-
+
// Compute the number of bits we need to represent these cases, this is
// ceil(log2(numentries)).
unsigned NumBits = Log2_32_Ceil(UniqueOperandCommands.size());
-
+
// If we don't have enough bits for this operand, don't include it.
if (NumBits > BitsLeft) {
DEBUG(errs() << "Not enough bits to densely encode " << NumBits
<< " more bits\n");
break;
}
-
+
// Otherwise, we can include this in the initial lookup table. Add it in.
BitsLeft -= NumBits;
for (unsigned i = 0, e = InstIdxs.size(); i != e; ++i)
if (InstIdxs[i] != ~0U)
OpcodeInfo[i] |= InstIdxs[i] << (BitsLeft+AsmStrBits);
-
+
// Remove the info about this operand.
for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
if (AsmWriterInst *Inst = getAsmWriterInstByID(i))
@@ -351,13 +356,13 @@
Inst->Operands.begin()+NumOps);
}
}
-
+
// Remember the handlers for this set of operands.
TableDrivenOperandPrinters.push_back(UniqueOperandCommands);
}
-
-
-
+
+
+
O<<" static const unsigned OpInfo[] = {\n";
for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
O << " " << OpcodeInfo[i] << "U,\t// "
@@ -366,7 +371,7 @@
// Add a dummy entry so the array init doesn't end with a comma.
O << " 0U\n";
O << " };\n\n";
-
+
// Emit the string itself.
O << " const char *AsmStrs = \n";
StringTable.EmitString(O);
@@ -388,13 +393,13 @@
// ceil(log2(numentries)).
unsigned NumBits = Log2_32_Ceil(Commands.size());
assert(NumBits <= BitsLeft && "consistency error");
-
+
// Emit code to extract this field from Bits.
BitsLeft -= NumBits;
-
+
O << "\n // Fragment " << i << " encoded into " << NumBits
<< " bits for " << Commands.size() << " unique commands.\n";
-
+
if (Commands.size() == 2) {
// Emit two possibilitys with if/else.
O << " if ((Bits >> " << (BitsLeft+AsmStrBits) << ") & "
@@ -403,11 +408,14 @@
<< " } else {\n"
<< Commands[0]
<< " }\n\n";
+ } else if (Commands.size() == 1) {
+ // Emit a single possibility.
+ O << Commands[0] << "\n\n";
} else {
O << " switch ((Bits >> " << (BitsLeft+AsmStrBits) << ") & "
<< ((1 << NumBits)-1) << ") {\n"
<< " default: // unreachable.\n";
-
+
// Print out all the cases.
for (unsigned i = 0, e = Commands.size(); i != e; ++i) {
O << " case " << i << ":\n";
@@ -417,7 +425,7 @@
O << " }\n\n";
}
}
-
+
// Okay, delete instructions with no operand info left.
for (unsigned i = 0, e = Instructions.size(); i != e; ++i) {
// Entire instruction has been emitted?
@@ -428,12 +436,12 @@
}
}
-
+
// Because this is a vector, we want to emit from the end. Reverse all of the
// elements in the vector.
std::reverse(Instructions.begin(), Instructions.end());
-
-
+
+
// Now that we've emitted all of the operand info that fit into 32 bits, emit
// information for those instructions that are left. This is a less dense
// encoding, but we expect the main 32-bit table to handle the majority of
@@ -451,57 +459,118 @@
O << "}\n";
}
-
-void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
- CodeGenTarget Target;
- Record *AsmWriter = Target.getAsmWriter();
- std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
- const std::vector<CodeGenRegister> &Registers = Target.getRegisters();
-
+static void
+emitRegisterNameString(raw_ostream &O, StringRef AltName,
+ const std::vector<CodeGenRegister*> &Registers) {
StringToOffsetTable StringTable;
- O <<
- "\n\n/// getRegisterName - This method is automatically generated by tblgen\n"
- "/// from the register set description. This returns the assembler name\n"
- "/// for the specified register.\n"
- "const char *" << Target.getName() << ClassName
- << "::getRegisterName(unsigned RegNo) {\n"
- << " assert(RegNo && RegNo < " << (Registers.size()+1)
- << " && \"Invalid register number!\");\n"
- << "\n"
- << " static const unsigned RegAsmOffset[] = {";
+ O << " static const unsigned RegAsmOffset" << AltName << "[] = {\n ";
for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
- const CodeGenRegister &Reg = Registers[i];
+ const CodeGenRegister &Reg = *Registers[i];
- std::string AsmName = Reg.TheDef->getValueAsString("AsmName");
- if (AsmName.empty())
- AsmName = Reg.getName();
-
-
- if ((i % 14) == 0)
- O << "\n ";
-
- O << StringTable.GetOrAddStringOffset(AsmName) << ", ";
+ std::string AsmName;
+ // "NoRegAltName" is special. We don't need to do a lookup for that,
+ // as it's just a reference to the default register name.
+ if (AltName == "" || AltName == "NoRegAltName") {
+ AsmName = Reg.TheDef->getValueAsString("AsmName");
+ if (AsmName.empty())
+ AsmName = Reg.getName();
+ } else {
+ // Make sure the register has an alternate name for this index.
+ std::vector<Record*> AltNameList =
+ Reg.TheDef->getValueAsListOfDefs("RegAltNameIndices");
+ unsigned Idx = 0, e;
+ for (e = AltNameList.size();
+ Idx < e && (AltNameList[Idx]->getName() != AltName);
+ ++Idx)
+ ;
+ // If the register has an alternate name for this index, use it.
+ // Otherwise, leave it empty as an error flag.
+ if (Idx < e) {
+ std::vector<std::string> AltNames =
+ Reg.TheDef->getValueAsListOfStrings("AltNames");
+ if (AltNames.size() <= Idx)
+ throw TGError(Reg.TheDef->getLoc(),
+ (Twine("Register definition missing alt name for '") +
+ AltName + "'.").str());
+ AsmName = AltNames[Idx];
+ }
+ }
+
+ O << StringTable.GetOrAddStringOffset(AsmName);
+ if (((i + 1) % 14) == 0)
+ O << ",\n ";
+ else
+ O << ", ";
+
}
O << "0\n"
<< " };\n"
<< "\n";
-
- O << " const char *AsmStrs =\n";
+
+ O << " const char *AsmStrs" << AltName << " =\n";
StringTable.EmitString(O);
O << ";\n";
-
- O << " return AsmStrs+RegAsmOffset[RegNo-1];\n"
+}
+
+void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
+ CodeGenTarget Target(Records);
+ Record *AsmWriter = Target.getAsmWriter();
+ std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
+ const std::vector<CodeGenRegister*> &Registers =
+ Target.getRegBank().getRegisters();
+ std::vector<Record*> AltNameIndices = Target.getRegAltNameIndices();
+ bool hasAltNames = AltNameIndices.size() > 1;
+
+ O <<
+ "\n\n/// getRegisterName - This method is automatically generated by tblgen\n"
+ "/// from the register set description. This returns the assembler name\n"
+ "/// for the specified register.\n"
+ "const char *" << Target.getName() << ClassName << "::";
+ if (hasAltNames)
+ O << "\ngetRegisterName(unsigned RegNo, unsigned AltIdx) {\n";
+ else
+ O << "getRegisterName(unsigned RegNo) {\n";
+ O << " assert(RegNo && RegNo < " << (Registers.size()+1)
+ << " && \"Invalid register number!\");\n"
+ << "\n";
+
+ if (hasAltNames) {
+ for (unsigned i = 0, e = AltNameIndices.size(); i < e; ++i)
+ emitRegisterNameString(O, AltNameIndices[i]->getName(), Registers);
+ } else
+ emitRegisterNameString(O, "", Registers);
+
+ if (hasAltNames) {
+ O << " const unsigned *RegAsmOffset;\n"
+ << " const char *AsmStrs;\n"
+ << " switch(AltIdx) {\n"
+ << " default: assert(0 && \"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());
+ O << " case " << Namespace << "::" << AltName
+ << ":\n"
+ << " AsmStrs = AsmStrs" << AltName << ";\n"
+ << " RegAsmOffset = RegAsmOffset" << AltName << ";\n"
+ << " break;\n";
+ }
+ O << "}\n";
+ }
+
+ O << " assert (*(AsmStrs+RegAsmOffset[RegNo-1]) &&\n"
+ << " \"Invalid alt name index for register!\");\n"
+ << " return AsmStrs+RegAsmOffset[RegNo-1];\n"
<< "}\n";
}
void AsmWriterEmitter::EmitGetInstructionName(raw_ostream &O) {
- CodeGenTarget Target;
+ CodeGenTarget Target(Records);
Record *AsmWriter = Target.getAsmWriter();
std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
const std::vector<const CodeGenInstruction*> &NumberedInstructions =
Target.getInstructionsByEnumValue();
-
+
StringToOffsetTable StringTable;
O <<
"\n\n#ifdef GET_INSTRUCTION_NAME\n"
@@ -517,32 +586,436 @@
<< " static const unsigned InstAsmOffset[] = {";
for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
const CodeGenInstruction &Inst = *NumberedInstructions[i];
-
+
std::string AsmName = Inst.TheDef->getName();
if ((i % 14) == 0)
O << "\n ";
-
+
O << StringTable.GetOrAddStringOffset(AsmName) << ", ";
}
O << "0\n"
<< " };\n"
<< "\n";
-
+
O << " const char *Strs =\n";
StringTable.EmitString(O);
O << ";\n";
-
+
O << " return Strs+InstAsmOffset[Opcode];\n"
<< "}\n\n#endif\n";
}
+namespace {
+// IAPrinter - Holds information about an InstAlias. Two InstAliases match if
+// they both have the same conditionals. In which case, we cannot print out the
+// alias for that pattern.
+class IAPrinter {
+ std::vector<std::string> Conds;
+ std::map<StringRef, unsigned> OpMap;
+ std::string Result;
+ std::string AsmString;
+ std::vector<Record*> ReqFeatures;
+public:
+ 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) { OpMap[Op] = Idx; }
+ unsigned getOpIndex(StringRef Op) { return OpMap[Op]; }
+ bool isOpMapped(StringRef Op) { return OpMap.find(Op) != OpMap.end(); }
+
+ void print(raw_ostream &O) {
+ if (Conds.empty() && ReqFeatures.empty()) {
+ O.indent(6) << "return true;\n";
+ return;
+ }
+
+ O << "if (";
+
+ for (std::vector<std::string>::iterator
+ I = Conds.begin(), E = Conds.end(); I != E; ++I) {
+ if (I != Conds.begin()) {
+ O << " &&\n";
+ O.indent(8);
+ }
+
+ O << *I;
+ }
+
+ O << ") {\n";
+ O.indent(6) << "// " << Result << "\n";
+ O.indent(6) << "AsmString = \"" << AsmString << "\";\n";
+
+ for (std::map<StringRef, unsigned>::iterator
+ I = OpMap.begin(), E = OpMap.end(); I != E; ++I)
+ O.indent(6) << "OpMap.push_back(std::make_pair(\"" << I->first << "\", "
+ << I->second << "));\n";
+
+ O.indent(6) << "break;\n";
+ O.indent(4) << '}';
+ }
+
+ bool operator==(const IAPrinter &RHS) {
+ if (Conds.size() != RHS.Conds.size())
+ return false;
+
+ unsigned Idx = 0;
+ for (std::vector<std::string>::iterator
+ I = Conds.begin(), E = Conds.end(); I != E; ++I)
+ if (*I != RHS.Conds[Idx++])
+ return false;
+
+ 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 void EmitGetMapOperandNumber(raw_ostream &O) {
+ O << "static unsigned getMapOperandNumber("
+ << "const SmallVectorImpl<std::pair<StringRef, unsigned> > &OpMap,\n";
+ O << " StringRef Name) {\n";
+ O << " for (SmallVectorImpl<std::pair<StringRef, unsigned> >::"
+ << "const_iterator\n";
+ O << " I = OpMap.begin(), E = OpMap.end(); I != E; ++I)\n";
+ O << " if (I->first == Name)\n";
+ O << " return I->second;\n";
+ O << " assert(false && \"Operand not in map!\");\n";
+ O << " return 0;\n";
+ O << "}\n\n";
+}
+
+void AsmWriterEmitter::EmitRegIsInRegClass(raw_ostream &O) {
+ CodeGenTarget Target(Records);
+
+ // Enumerate the register classes.
+ ArrayRef<CodeGenRegisterClass*> RegisterClasses =
+ Target.getRegBank().getRegClasses();
+
+ O << "namespace { // Register classes\n";
+ O << " enum RegClass {\n";
+
+ // Emit the register enum value for each RegisterClass.
+ for (unsigned I = 0, E = RegisterClasses.size(); I != E; ++I) {
+ if (I != 0) O << ",\n";
+ O << " RC_" << RegisterClasses[I]->getName();
+ }
+
+ O << "\n };\n";
+ O << "} // end anonymous namespace\n\n";
+
+ // Emit a function that returns 'true' if a regsiter is part of a particular
+ // register class. I.e., RAX is part of GR64 on X86.
+ O << "static bool regIsInRegisterClass"
+ << "(unsigned RegClass, unsigned Reg) {\n";
+
+ // Emit the switch that checks if a register belongs to a particular register
+ // class.
+ O << " switch (RegClass) {\n";
+ O << " default: break;\n";
+
+ for (unsigned I = 0, E = RegisterClasses.size(); I != E; ++I) {
+ const CodeGenRegisterClass &RC = *RegisterClasses[I];
+
+ // Give the register class a legal C name if it's anonymous.
+ std::string Name = RC.getName();
+ O << " case RC_" << Name << ":\n";
+
+ // Emit the register list now.
+ unsigned IE = RC.getOrder().size();
+ if (IE == 1) {
+ O << " if (Reg == " << getQualifiedName(RC.getOrder()[0]) << ")\n";
+ O << " return true;\n";
+ } else {
+ O << " switch (Reg) {\n";
+ O << " default: break;\n";
+
+ for (unsigned II = 0; II != IE; ++II) {
+ Record *Reg = RC.getOrder()[II];
+ O << " case " << getQualifiedName(Reg) << ":\n";
+ }
+
+ O << " return true;\n";
+ O << " }\n";
+ }
+
+ O << " break;\n";
+ }
+
+ O << " }\n\n";
+ O << " return false;\n";
+ O << "}\n\n";
+}
+
+static unsigned CountNumOperands(StringRef AsmString) {
+ unsigned NumOps = 0;
+ std::pair<StringRef, StringRef> ASM = AsmString.split(' ');
+
+ while (!ASM.second.empty()) {
+ ++NumOps;
+ ASM = ASM.second.split(' ');
+ }
+
+ return NumOps;
+}
+
+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(' ');
+
+ do {
+ ++NumOps;
+ ASM = ASM.second.split(' ');
+ } while (!ASM.second.empty());
+ }
+
+ return NumOps;
+}
+
+void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
+ CodeGenTarget Target(Records);
+ Record *AsmWriter = Target.getAsmWriter();
+
+ if (!AsmWriter->getValueAsBit("isMCAsmWriter"))
+ return;
+
+ O << "\n#ifdef PRINT_ALIAS_INSTR\n";
+ O << "#undef PRINT_ALIAS_INSTR\n\n";
+
+ EmitRegIsInRegClass(O);
+
+ // Emit the method that prints the alias instruction.
+ std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
+
+ 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;
+ for (std::vector<Record*>::iterator
+ I = AllInstAliases.begin(), E = AllInstAliases.end(); I != E; ++I) {
+ CodeGenInstAlias *Alias = new CodeGenInstAlias(*I, Target);
+ const Record *R = *I;
+ if (!R->getValueAsBit("EmitAlias"))
+ continue; // We were told not to emit the alias, but to emit the aliasee.
+ const DagInit *DI = R->getValueAsDag("ResultInst");
+ const DefInit *Op = dynamic_cast<const DefInit*>(DI->getOperator());
+ AliasMap[getQualifiedName(Op->getDef())].push_back(Alias);
+ }
+
+ // A map of which conditions need to be met for each instruction operand
+ // before it can be matched to the mnemonic.
+ std::map<std::string, std::vector<IAPrinter*> > IAPrinterMap;
+
+ for (std::map<std::string, std::vector<CodeGenInstAlias*> >::iterator
+ I = AliasMap.begin(), E = AliasMap.end(); I != E; ++I) {
+ std::vector<CodeGenInstAlias*> &Aliases = I->second;
+
+ for (std::vector<CodeGenInstAlias*>::iterator
+ II = Aliases.begin(), IE = Aliases.end(); II != IE; ++II) {
+ const CodeGenInstAlias *CGA = *II;
+ unsigned LastOpNo = CGA->ResultInstOperandIndex.size();
+ unsigned NumResultOps =
+ CountResultNumOperands(CGA->ResultInst->AsmString);
+
+ // Don't emit the alias if it has more operands than what it's aliasing.
+ if (NumResultOps < CountNumOperands(CGA->AsmString))
+ continue;
+
+ IAPrinter *IAP = new IAPrinter(CGA->Result->getAsString(),
+ CGA->AsmString);
+
+ std::string Cond;
+ Cond = std::string("MI->getNumOperands() == ") + llvm::utostr(LastOpNo);
+ IAP->addCond(Cond);
+
+ std::map<StringRef, unsigned> OpMap;
+ bool CantHandle = false;
+
+ for (unsigned i = 0, e = LastOpNo; i != e; ++i) {
+ const CodeGenInstAlias::ResultOperand &RO = CGA->ResultOperands[i];
+
+ switch (RO.Kind) {
+ default: assert(0 && "unexpected InstAlias operand kind");
+ case CodeGenInstAlias::ResultOperand::K_Record: {
+ const Record *Rec = RO.getRecord();
+ StringRef ROName = RO.getName();
+
+
+ if (Rec->isSubClassOf("RegisterOperand"))
+ Rec = Rec->getValueAsDef("RegClass");
+ if (Rec->isSubClassOf("RegisterClass")) {
+ Cond = std::string("MI->getOperand(")+llvm::utostr(i)+").isReg()";
+ IAP->addCond(Cond);
+
+ if (!IAP->isOpMapped(ROName)) {
+ IAP->addOperand(ROName, i);
+ Cond = std::string("regIsInRegisterClass(RC_") +
+ CGA->ResultOperands[i].getRecord()->getName() +
+ ", MI->getOperand(" + llvm::utostr(i) + ").getReg())";
+ IAP->addCond(Cond);
+ } else {
+ Cond = std::string("MI->getOperand(") +
+ llvm::utostr(i) + ").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;
+ }
+
+ break;
+ }
+ case CodeGenInstAlias::ResultOperand::K_Imm:
+ Cond = std::string("MI->getOperand(") +
+ llvm::utostr(i) + ").getImm() == " +
+ llvm::utostr(CGA->ResultOperands[i].getImm());
+ IAP->addCond(Cond);
+ break;
+ case CodeGenInstAlias::ResultOperand::K_Reg:
+ Cond = std::string("MI->getOperand(") +
+ llvm::utostr(i) + ").getReg() == " + Target.getName() +
+ "::" + CGA->ResultOperands[i].getRegister()->getName();
+ IAP->addCond(Cond);
+ break;
+ }
+
+ if (!IAP) break;
+ }
+
+ if (CantHandle) continue;
+ IAPrinterMap[I->first].push_back(IAP);
+ }
+ }
+
+ std::string Header;
+ raw_string_ostream HeaderO(Header);
+
+ HeaderO << "bool " << Target.getName() << ClassName
+ << "::printAliasInstr(const MCInst"
+ << " *MI, raw_ostream &OS) {\n";
+
+ std::string Cases;
+ raw_string_ostream CasesO(Cases);
+
+ for (std::map<std::string, std::vector<IAPrinter*> >::iterator
+ I = IAPrinterMap.begin(), E = IAPrinterMap.end(); I != E; ++I) {
+ std::vector<IAPrinter*> &IAPs = I->second;
+ std::vector<IAPrinter*> UniqueIAPs;
+
+ for (std::vector<IAPrinter*>::iterator
+ II = IAPs.begin(), IE = IAPs.end(); II != IE; ++II) {
+ IAPrinter *LHS = *II;
+ bool IsDup = false;
+ for (std::vector<IAPrinter*>::iterator
+ III = IAPs.begin(), IIE = IAPs.end(); III != IIE; ++III) {
+ IAPrinter *RHS = *III;
+ if (LHS != RHS && *LHS == *RHS) {
+ IsDup = true;
+ break;
+ }
+ }
+
+ if (!IsDup) UniqueIAPs.push_back(LHS);
+ }
+
+ if (UniqueIAPs.empty()) continue;
+
+ CasesO.indent(2) << "case " << I->first << ":\n";
+
+ for (std::vector<IAPrinter*>::iterator
+ II = UniqueIAPs.begin(), IE = UniqueIAPs.end(); II != IE; ++II) {
+ IAPrinter *IAP = *II;
+ CasesO.indent(4);
+ IAP->print(CasesO);
+ CasesO << '\n';
+ }
+
+ CasesO.indent(4) << "return false;\n";
+ }
+
+ if (CasesO.str().empty()) {
+ O << HeaderO.str();
+ O << " return false;\n";
+ O << "}\n\n";
+ O << "#endif // PRINT_ALIAS_INSTR\n";
+ return;
+ }
+
+ EmitGetMapOperandNumber(O);
+
+ O << HeaderO.str();
+ O.indent(2) << "StringRef AsmString;\n";
+ O.indent(2) << "SmallVector<std::pair<StringRef, unsigned>, 4> OpMap;\n";
+ O.indent(2) << "switch (MI->getOpcode()) {\n";
+ O.indent(2) << "default: return false;\n";
+ O << CasesO.str();
+ O.indent(2) << "}\n\n";
+
+ // Code that prints the alias, replacing the operands with the ones from the
+ // MCInst.
+ O << " std::pair<StringRef, StringRef> ASM = AsmString.split(' ');\n";
+ O << " OS << '\\t' << ASM.first;\n";
+
+ O << " if (!ASM.second.empty()) {\n";
+ O << " OS << '\\t';\n";
+ O << " for (StringRef::iterator\n";
+ O << " I = ASM.second.begin(), E = ASM.second.end(); I != E; ) {\n";
+ O << " if (*I == '$') {\n";
+ O << " StringRef::iterator Start = ++I;\n";
+ O << " while (I != E &&\n";
+ O << " ((*I >= 'a' && *I <= 'z') ||\n";
+ O << " (*I >= 'A' && *I <= 'Z') ||\n";
+ O << " (*I >= '0' && *I <= '9') ||\n";
+ O << " *I == '_'))\n";
+ O << " ++I;\n";
+ O << " StringRef Name(Start, I - Start);\n";
+ O << " printOperand(MI, getMapOperandNumber(OpMap, Name), OS);\n";
+ O << " } else {\n";
+ O << " OS << *I++;\n";
+ O << " }\n";
+ O << " }\n";
+ O << " }\n\n";
+
+ O << " return true;\n";
+ O << "}\n\n";
+
+ O << "#endif // PRINT_ALIAS_INSTR\n";
+}
void AsmWriterEmitter::run(raw_ostream &O) {
EmitSourceFileHeader("Assembly Writer Source Fragment", O);
-
+
EmitPrintInstruction(O);
EmitGetRegisterName(O);
EmitGetInstructionName(O);
+ EmitPrintAliasInstruction(O);
}
diff --git a/src/LLVM/utils/TableGen/AsmWriterEmitter.h b/src/LLVM/utils/TableGen/AsmWriterEmitter.h
index 9f7d776..731e31c 100644
--- a/src/LLVM/utils/TableGen/AsmWriterEmitter.h
+++ b/src/LLVM/utils/TableGen/AsmWriterEmitter.h
@@ -15,7 +15,7 @@
#ifndef ASMWRITER_EMITTER_H
#define ASMWRITER_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include <map>
#include <vector>
#include <cassert>
@@ -38,6 +38,8 @@
void EmitPrintInstruction(raw_ostream &o);
void EmitGetRegisterName(raw_ostream &o);
void EmitGetInstructionName(raw_ostream &o);
+ void EmitRegIsInRegClass(raw_ostream &O);
+ void EmitPrintAliasInstruction(raw_ostream &O);
AsmWriterInst *getAsmWriterInstByID(unsigned ID) const {
assert(ID < NumberedInstructions.size());
diff --git a/src/LLVM/utils/TableGen/AsmWriterInst.cpp b/src/LLVM/utils/TableGen/AsmWriterInst.cpp
index b2228b0..350a2cc 100644
--- a/src/LLVM/utils/TableGen/AsmWriterInst.cpp
+++ b/src/LLVM/utils/TableGen/AsmWriterInst.cpp
@@ -13,8 +13,8 @@
#include "AsmWriterInst.h"
#include "CodeGenTarget.h"
-#include "Record.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/TableGen/Record.h"
using namespace llvm;
@@ -53,8 +53,6 @@
int OperandSpacing) {
this->CGI = &CGI;
- unsigned CurVariant = ~0U; // ~0 if we are outside a {.|.|.} region, other #.
-
// This is the number of tabs we've seen if we're doing columnar layout.
unsigned CurColumn = 0;
@@ -62,54 +60,48 @@
// 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)!
- const std::string &AsmString = CGI.AsmString;
+ std::string AsmString = CGI.FlattenAsmStringVariants(CGI.AsmString, Variant);
std::string::size_type LastEmitted = 0;
while (LastEmitted != AsmString.size()) {
std::string::size_type DollarPos =
- AsmString.find_first_of("${|}\\", LastEmitted);
+ AsmString.find_first_of("$\\", LastEmitted);
if (DollarPos == std::string::npos) DollarPos = AsmString.size();
// Emit a constant string fragment.
-
if (DollarPos != LastEmitted) {
- if (CurVariant == Variant || CurVariant == ~0U) {
- for (; LastEmitted != DollarPos; ++LastEmitted)
- switch (AsmString[LastEmitted]) {
- case '\n':
- 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));
- }
- break;
- case '"':
- AddLiteralString("\\\"");
- break;
- case '\\':
- AddLiteralString("\\\\");
- break;
- default:
- AddLiteralString(std::string(1, AsmString[LastEmitted]));
- break;
- }
- } else {
- LastEmitted = DollarPos;
- }
+ for (; LastEmitted != DollarPos; ++LastEmitted)
+ switch (AsmString[LastEmitted]) {
+ case '\n':
+ 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));
+ }
+ break;
+ case '"':
+ AddLiteralString("\\\"");
+ break;
+ case '\\':
+ AddLiteralString("\\\\");
+ break;
+ default:
+ AddLiteralString(std::string(1, AsmString[LastEmitted]));
+ break;
+ }
} else if (AsmString[DollarPos] == '\\') {
- if (DollarPos+1 != AsmString.size() &&
- (CurVariant == Variant || CurVariant == ~0U)) {
+ if (DollarPos+1 != AsmString.size()) {
if (AsmString[DollarPos+1] == 'n') {
AddLiteralString("\\n");
} else if (AsmString[DollarPos+1] == 't') {
@@ -137,29 +129,9 @@
LastEmitted = DollarPos+2;
continue;
}
- } else if (AsmString[DollarPos] == '{') {
- if (CurVariant != ~0U)
- throw "Nested variants found for instruction '" +
- CGI.TheDef->getName() + "'!";
- LastEmitted = DollarPos+1;
- CurVariant = 0; // We are now inside of the variant!
- } else if (AsmString[DollarPos] == '|') {
- if (CurVariant == ~0U)
- throw "'|' character found outside of a variant in instruction '"
- + CGI.TheDef->getName() + "'!";
- ++CurVariant;
- ++LastEmitted;
- } else if (AsmString[DollarPos] == '}') {
- if (CurVariant == ~0U)
- throw "'}' character found outside of a variant in instruction '"
- + CGI.TheDef->getName() + "'!";
- ++LastEmitted;
- CurVariant = ~0U;
} else if (DollarPos+1 != AsmString.size() &&
AsmString[DollarPos+1] == '$') {
- if (CurVariant == Variant || CurVariant == ~0U) {
- AddLiteralString("$"); // "$$" -> $
- }
+ AddLiteralString("$"); // "$$" -> $
LastEmitted = DollarPos+2;
} else {
// Get the name of the variable.
@@ -226,16 +198,12 @@
Modifier));
} else {
// Otherwise, normal operand.
- unsigned OpNo = CGI.getOperandNamed(VarName);
- CodeGenInstruction::OperandInfo OpInfo = CGI.OperandList[OpNo];
+ unsigned OpNo = CGI.Operands.getOperandNamed(VarName);
+ CGIOperandList::OperandInfo OpInfo = CGI.Operands[OpNo];
- if (CurVariant == Variant || CurVariant == ~0U) {
- unsigned MIOp = OpInfo.MIOperandNo;
- Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName,
- OpNo,
- MIOp,
- Modifier));
- }
+ unsigned MIOp = OpInfo.MIOperandNo;
+ Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName,
+ OpNo, MIOp, Modifier));
}
LastEmitted = VarEnd;
}
diff --git a/src/LLVM/utils/TableGen/AsmWriterInst.h b/src/LLVM/utils/TableGen/AsmWriterInst.h
index 20b8588..ec7d8eb 100644
--- a/src/LLVM/utils/TableGen/AsmWriterInst.h
+++ b/src/LLVM/utils/TableGen/AsmWriterInst.h
@@ -23,51 +23,51 @@
namespace llvm {
class CodeGenInstruction;
class Record;
-
+
struct AsmWriterOperand {
enum OpType {
// Output this text surrounded by quotes to the asm.
- isLiteralTextOperand,
+ isLiteralTextOperand,
// This is the name of a routine to call to print the operand.
isMachineInstrOperand,
// Output this text verbatim to the asm writer. It is code that
// will output some text to the asm.
isLiteralStatementOperand
} OperandType;
-
+
/// Str - For isLiteralTextOperand, this IS the literal text. For
/// isMachineInstrOperand, this is the PrinterMethodName for the operand..
- /// For isLiteralStatementOperand, this is the code to insert verbatim
+ /// For isLiteralStatementOperand, this is the code to insert verbatim
/// into the asm writer.
std::string Str;
-
+
/// CGIOpNo - For isMachineInstrOperand, this is the index of the operand in
/// the CodeGenInstruction.
unsigned CGIOpNo;
-
+
/// MiOpNo - For isMachineInstrOperand, this is the operand number of the
/// machine instruction.
unsigned MIOpNo;
-
+
/// MiModifier - For isMachineInstrOperand, this is the modifier string for
/// an operand, specified with syntax like ${opname:modifier}.
std::string MiModifier;
-
+
// To make VS STL happy
AsmWriterOperand(OpType op = isLiteralTextOperand):OperandType(op) {}
-
+
AsmWriterOperand(const std::string &LitStr,
OpType op = isLiteralTextOperand)
: OperandType(op), Str(LitStr) {}
-
+
AsmWriterOperand(const std::string &Printer,
unsigned _CGIOpNo,
unsigned _MIOpNo,
const std::string &Modifier,
- OpType op = isMachineInstrOperand)
+ OpType op = isMachineInstrOperand)
: OperandType(op), Str(Printer), CGIOpNo(_CGIOpNo), MIOpNo(_MIOpNo),
MiModifier(Modifier) {}
-
+
bool operator!=(const AsmWriterOperand &Other) const {
if (OperandType != Other.OperandType || Str != Other.Str) return true;
if (OperandType == isMachineInstrOperand)
@@ -77,26 +77,26 @@
bool operator==(const AsmWriterOperand &Other) const {
return !operator!=(Other);
}
-
+
/// getCode - Return the code that prints this operand.
std::string getCode() const;
};
-
+
class AsmWriterInst {
public:
std::vector<AsmWriterOperand> Operands;
const CodeGenInstruction *CGI;
-
- AsmWriterInst(const CodeGenInstruction &CGI,
+
+ AsmWriterInst(const CodeGenInstruction &CGI,
unsigned Variant,
int FirstOperandColumn,
int OperandSpacing);
-
+
/// MatchesAllButOneOp - If this instruction is exactly identical to the
/// specified instruction except for one differing operand, return the
/// differing operand number. Otherwise return ~0.
unsigned MatchesAllButOneOp(const AsmWriterInst &Other) const;
-
+
private:
void AddLiteralString(const std::string &Str) {
// If the last operand was already a literal text string, append this to
diff --git a/src/LLVM/utils/TableGen/CallingConvEmitter.cpp b/src/LLVM/utils/TableGen/CallingConvEmitter.cpp
index 7643609..fcdaa08 100644
--- a/src/LLVM/utils/TableGen/CallingConvEmitter.cpp
+++ b/src/LLVM/utils/TableGen/CallingConvEmitter.cpp
@@ -13,8 +13,8 @@
//===----------------------------------------------------------------------===//
#include "CallingConvEmitter.h"
-#include "Record.h"
#include "CodeGenTarget.h"
+#include "llvm/TableGen/Record.h"
using namespace llvm;
void CallingConvEmitter::run(raw_ostream &O) {
@@ -26,9 +26,9 @@
// other.
for (unsigned i = 0, e = CCs.size(); i != e; ++i) {
O << "static bool " << CCs[i]->getName()
- << "(unsigned ValNo, EVT ValVT,\n"
+ << "(unsigned ValNo, MVT ValVT,\n"
<< std::string(CCs[i]->getName().size()+13, ' ')
- << "EVT LocVT, CCValAssign::LocInfo LocInfo,\n"
+ << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
<< std::string(CCs[i]->getName().size()+13, ' ')
<< "ISD::ArgFlagsTy ArgFlags, CCState &State);\n";
}
@@ -44,9 +44,9 @@
Counter = 0;
O << "\n\nstatic bool " << CC->getName()
- << "(unsigned ValNo, EVT ValVT,\n"
+ << "(unsigned ValNo, MVT ValVT,\n"
<< std::string(CC->getName().size()+13, ' ')
- << "EVT LocVT, CCValAssign::LocInfo LocInfo,\n"
+ << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
<< std::string(CC->getName().size()+13, ' ')
<< "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n";
// Emit all of the actions, in order.
@@ -163,12 +163,12 @@
O << Size << ", ";
else
O << "\n" << IndentStr << " State.getTarget().getTargetData()"
- "->getTypeAllocSize(LocVT.getTypeForEVT(State.getContext())), ";
+ "->getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())), ";
if (Align)
O << Align;
else
O << "\n" << IndentStr << " State.getTarget().getTargetData()"
- "->getABITypeAlignment(LocVT.getTypeForEVT(State.getContext()))";
+ "->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()))";
if (Action->isSubClassOf("CCAssignToStackWithShadow"))
O << ", " << getQualifiedName(Action->getValueAsDef("ShadowReg"));
O << ");\n" << IndentStr
diff --git a/src/LLVM/utils/TableGen/CallingConvEmitter.h b/src/LLVM/utils/TableGen/CallingConvEmitter.h
index 7fc2507..7bddd6c 100644
--- a/src/LLVM/utils/TableGen/CallingConvEmitter.h
+++ b/src/LLVM/utils/TableGen/CallingConvEmitter.h
@@ -15,9 +15,7 @@
#ifndef CALLINGCONV_EMITTER_H
#define CALLINGCONV_EMITTER_H
-#include "TableGenBackend.h"
-#include <map>
-#include <vector>
+#include "llvm/TableGen/TableGenBackend.h"
#include <cassert>
namespace llvm {
diff --git a/src/LLVM/utils/TableGen/CodeEmitterGen.cpp b/src/LLVM/utils/TableGen/CodeEmitterGen.cpp
index ec702c2..c5a1526 100644
--- a/src/LLVM/utils/TableGen/CodeEmitterGen.cpp
+++ b/src/LLVM/utils/TableGen/CodeEmitterGen.cpp
@@ -15,73 +15,217 @@
#include "CodeEmitterGen.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
+#include <map>
using namespace llvm;
+// FIXME: Somewhat hackish to use a command line option for this. There should
+// be a CodeEmitter class in the Target.td that controls this sort of thing
+// instead.
+static cl::opt<bool>
+MCEmitter("mc-emitter",
+ cl::desc("Generate CodeEmitter for use with the MC library."),
+ cl::init(false));
+
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")
+ if (R->getValueAsString("Namespace") == "TargetOpcode" ||
+ R->getValueAsBit("isPseudo"))
continue;
BitsInit *BI = R->getValueAsBitsInit("Inst");
unsigned numBits = BI->getNumBits();
- BitsInit *NewBI = new BitsInit(numBits);
+
+ 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);
- NewBI->setBit(bit, BitSwap);
- NewBI->setBit(bitSwapIdx, OrigBit);
+ NewBits[bit] = BitSwap;
+ NewBits[bitSwapIdx] = OrigBit;
}
if (numBits % 2) {
unsigned middle = (numBits + 1) / 2;
- NewBI->setBit(middle, BI->getBit(middle));
+ 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,
- BitsInit *BI, int bit) {
+ BitsInit *BI, int bit) {
if (VarBitInit *VBI = dynamic_cast<VarBitInit*>(BI->getBit(bit))) {
- TypedInit *TI = VBI->getVariable();
+ if (VarInit *VI = dynamic_cast<VarInit*>(VBI->getVariable()))
+ if (VI->getName() == VarName)
+ return VBI->getBitNum();
+ } else if (VarInit *VI = dynamic_cast<VarInit*>(BI->getBit(bit))) {
+ if (VI->getName() == VarName)
+ return 0;
+ }
+
+ return -1;
+}
+
+void CodeEmitterGen::
+AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName,
+ unsigned &NumberedOp,
+ std::string &Case, CodeGenTarget &Target) {
+ CodeGenInstruction &CGI = Target.getInstruction(R);
+
+ // Determine if VarName actually contributes to the Inst encoding.
+ int bit = BI->getNumBits()-1;
+
+ // Scan for a bit that this contributed to.
+ for (; bit >= 0; ) {
+ if (getVariableBit(VarName, BI, bit) != -1)
+ break;
- if (VarInit *VI = dynamic_cast<VarInit*>(TI)) {
- if (VI->getName() == VarName) return VBI->getBitNum();
- }
+ --bit;
}
- return -1;
-}
+ // If we found no bits, ignore this value, otherwise emit the call to get the
+ // operand encoding.
+ if (bit < 0) return;
+
+ // If the operand matches by name, reference according to that
+ // operand number. Non-matching operands are assumed to be in
+ // order.
+ unsigned OpIdx;
+ if (CGI.Operands.hasOperandNamed(VarName, OpIdx)) {
+ // Get the machine operand number for the indicated operand.
+ OpIdx = CGI.Operands[OpIdx].MIOperandNo;
+ assert(!CGI.Operands.isFlatOperandNotEmitted(OpIdx) &&
+ "Explicitly used operand also marked as not emitted!");
+ } else {
+ /// If this operand is not supposed to be emitted by the
+ /// generated emitter, skip it.
+ while (CGI.Operands.isFlatOperandNotEmitted(NumberedOp))
+ ++NumberedOp;
+ OpIdx = NumberedOp++;
+ }
+
+ std::pair<unsigned, unsigned> SO = CGI.Operands.getSubOperandNumber(OpIdx);
+ std::string &EncoderMethodName = CGI.Operands[SO.first].EncoderMethodName;
+
+ // If the source operand has a custom encoder, use it. This will
+ // get the encoding for all of the suboperands.
+ if (!EncoderMethodName.empty()) {
+ // A custom encoder has all of the information for the
+ // sub-operands, if there are more than one, so only
+ // query the encoder once per source operand.
+ if (SO.second == 0) {
+ Case += " // op: " + VarName + "\n" +
+ " op = " + EncoderMethodName + "(MI, " + utostr(OpIdx);
+ if (MCEmitter)
+ Case += ", Fixups";
+ Case += ");\n";
+ }
+ } else {
+ Case += " // op: " + VarName + "\n" +
+ " op = getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")";
+ if (MCEmitter)
+ Case += ", Fixups";
+ Case += ");\n";
+ }
+
+ for (; bit >= 0; ) {
+ int varBit = getVariableBit(VarName, BI, bit);
+
+ // If this bit isn't from a variable, skip it.
+ if (varBit == -1) {
+ --bit;
+ continue;
+ }
+
+ // Figure out the consecutive range of bits covered by this operand, in
+ // order to generate better encoding code.
+ int beginInstBit = bit;
+ int beginVarBit = varBit;
+ int N = 1;
+ for (--bit; bit >= 0;) {
+ varBit = getVariableBit(VarName, BI, bit);
+ if (varBit == -1 || varBit != (beginVarBit - N)) break;
+ ++N;
+ --bit;
+ }
+
+ unsigned opMask = ~0U >> (32-N);
+ int opShift = beginVarBit - N + 1;
+ opMask <<= opShift;
+ opShift = beginInstBit - beginVarBit;
+
+ if (opShift > 0) {
+ Case += " Value |= (op & " + utostr(opMask) + "U) << " +
+ itostr(opShift) + ";\n";
+ } else if (opShift < 0) {
+ Case += " Value |= (op & " + utostr(opMask) + "U) >> " +
+ itostr(-opShift) + ";\n";
+ } else {
+ Case += " Value |= op & " + utostr(opMask) + "U;\n";
+ }
+ }
+}
+std::string CodeEmitterGen::getInstructionCase(Record *R,
+ CodeGenTarget &Target) {
+ std::string Case;
+
+ BitsInit *BI = R->getValueAsBitsInit("Inst");
+ const std::vector<RecordVal> &Vals = R->getValues();
+ unsigned NumberedOp = 0;
+
+ // 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) {
+ // Ignore fixed fields in the record, we're looking for values like:
+ // bits<5> RST = { ?, ?, ?, ?, ? };
+ if (Vals[i].getPrefix() || Vals[i].getValue()->isComplete())
+ continue;
+
+ AddCodeToMergeInOperand(R, BI, Vals[i].getName(), NumberedOp, Case, Target);
+ }
+
+ std::string PostEmitter = R->getValueAsString("PostEncoderMethod");
+ if (!PostEmitter.empty())
+ Case += " Value = " + PostEmitter + "(MI, Value);\n";
+
+ return Case;
+}
+
void CodeEmitterGen::run(raw_ostream &o) {
- CodeGenTarget Target;
+ CodeGenTarget Target(Records);
std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
-
+
// For little-endian instruction bit encodings, reverse the bit order
if (Target.isLittleEndianEncoding()) reverseBits(Insts);
EmitSourceFileHeader("Machine Code Emitter", o);
- std::string Namespace = Insts[0]->getValueAsString("Namespace") + "::";
-
+
const std::vector<const CodeGenInstruction*> &NumberedInstructions =
Target.getInstructionsByEnumValue();
// Emit function declaration
- o << "unsigned " << Target.getName() << "CodeEmitter::"
- << "getBinaryCodeForInstr(const MachineInstr &MI) {\n";
+ o << "unsigned " << Target.getName();
+ if (MCEmitter)
+ o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n"
+ << " SmallVectorImpl<MCFixup> &Fixups) const {\n";
+ else
+ o << "CodeEmitter::getBinaryCodeForInstr(const MachineInstr &MI) const {\n";
// Emit instruction base values
o << " static const unsigned InstBits[] = {\n";
@@ -91,109 +235,47 @@
IN != EN; ++IN) {
const CodeGenInstruction *CGI = *IN;
Record *R = CGI->TheDef;
-
- if (R->getValueAsString("Namespace") == "TargetOpcode") {
+
+ if (R->getValueAsString("Namespace") == "TargetOpcode" ||
+ R->getValueAsBit("isPseudo")) {
o << " 0U,\n";
continue;
}
-
+
BitsInit *BI = R->getValueAsBitsInit("Inst");
- // Start by filling in fixed values...
+ // Start by filling in fixed values.
unsigned Value = 0;
for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
- if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1))) {
+ if (BitInit *B = dynamic_cast<BitInit*>(BI->getBit(e-i-1)))
Value |= B->getValue() << (e-i-1);
- }
}
o << " " << Value << "U," << '\t' << "// " << R->getName() << "\n";
}
o << " 0U\n };\n";
-
+
// Map to accumulate all the cases.
std::map<std::string, std::vector<std::string> > CaseMap;
-
+
// Construct all cases statement for each opcode
for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end();
IC != EC; ++IC) {
Record *R = *IC;
- if (R->getValueAsString("Namespace") == "TargetOpcode")
+ if (R->getValueAsString("Namespace") == "TargetOpcode" ||
+ R->getValueAsBit("isPseudo"))
continue;
- const std::string &InstName = R->getName();
- std::string Case("");
+ const std::string &InstName = R->getValueAsString("Namespace") + "::"
+ + R->getName();
+ std::string Case = getInstructionCase(R, Target);
- BitsInit *BI = R->getValueAsBitsInit("Inst");
- const std::vector<RecordVal> &Vals = R->getValues();
- CodeGenInstruction &CGI = Target.getInstruction(R);
-
- // Loop over all of the fields in the instruction, determining which are the
- // operands to the instruction.
- unsigned op = 0;
- for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
- if (!Vals[i].getPrefix() && !Vals[i].getValue()->isComplete()) {
- // Is the operand continuous? If so, we can just mask and OR it in
- // instead of doing it bit-by-bit, saving a lot in runtime cost.
- const std::string &VarName = Vals[i].getName();
- bool gotOp = false;
-
- for (int bit = BI->getNumBits()-1; bit >= 0; ) {
- int varBit = getVariableBit(VarName, BI, bit);
-
- if (varBit == -1) {
- --bit;
- } else {
- int beginInstBit = bit;
- int beginVarBit = varBit;
- int N = 1;
-
- for (--bit; bit >= 0;) {
- varBit = getVariableBit(VarName, BI, bit);
- if (varBit == -1 || varBit != (beginVarBit - N)) break;
- ++N;
- --bit;
- }
-
- if (!gotOp) {
- /// If this operand is not supposed to be emitted by the generated
- /// emitter, skip it.
- while (CGI.isFlatOperandNotEmitted(op))
- ++op;
-
- Case += " // op: " + VarName + "\n"
- + " op = getMachineOpValue(MI, MI.getOperand("
- + utostr(op++) + "));\n";
- gotOp = true;
- }
-
- unsigned opMask = ~0U >> (32-N);
- int opShift = beginVarBit - N + 1;
- opMask <<= opShift;
- opShift = beginInstBit - beginVarBit;
-
- if (opShift > 0) {
- Case += " Value |= (op & " + utostr(opMask) + "U) << "
- + itostr(opShift) + ";\n";
- } else if (opShift < 0) {
- Case += " Value |= (op & " + utostr(opMask) + "U) >> "
- + itostr(-opShift) + ";\n";
- } else {
- Case += " Value |= op & " + utostr(opMask) + "U;\n";
- }
- }
- }
- }
- }
-
- std::vector<std::string> &InstList = CaseMap[Case];
- InstList.push_back(InstName);
+ CaseMap[Case].push_back(InstName);
}
-
// Emit initial function code
o << " const unsigned opcode = MI.getOpcode();\n"
<< " unsigned Value = InstBits[opcode];\n"
<< " unsigned op = 0;\n"
- << " op = op; // suppress warning\n"
+ << " (void)op; // suppress warning\n"
<< " switch (opcode) {\n";
// Emit each case statement
@@ -204,7 +286,7 @@
for (int i = 0, N = InstList.size(); i < N; i++) {
if (i) o << "\n";
- o << " case " << Namespace << InstList[i] << ":";
+ o << " case " << InstList[i] << ":";
}
o << " {\n";
o << Case;
diff --git a/src/LLVM/utils/TableGen/CodeEmitterGen.h b/src/LLVM/utils/TableGen/CodeEmitterGen.h
index f0b3229..7f6ee2a 100644
--- a/src/LLVM/utils/TableGen/CodeEmitterGen.h
+++ b/src/LLVM/utils/TableGen/CodeEmitterGen.h
@@ -14,8 +14,7 @@
#ifndef CODEMITTERGEN_H
#define CODEMITTERGEN_H
-#include "TableGenBackend.h"
-#include <map>
+#include "llvm/TableGen/TableGenBackend.h"
#include <vector>
#include <string>
@@ -23,6 +22,7 @@
class RecordVal;
class BitsInit;
+class CodeGenTarget;
class CodeEmitterGen : public TableGenBackend {
RecordKeeper &Records;
@@ -36,6 +36,12 @@
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::string &Case, CodeGenTarget &Target);
+
};
} // End llvm namespace
diff --git a/src/LLVM/utils/TableGen/CodeGenDAGPatterns.cpp b/src/LLVM/utils/TableGen/CodeGenDAGPatterns.cpp
index 303aa6c..dbf1662 100644
--- a/src/LLVM/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/src/LLVM/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -13,7 +13,8 @@
//===----------------------------------------------------------------------===//
#include "CodeGenDAGPatterns.h"
-#include "Record.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
@@ -56,11 +57,11 @@
EEVT::TypeSet::TypeSet(const std::vector<MVT::SimpleValueType> &VTList) {
assert(!VTList.empty() && "empty list?");
TypeVec.append(VTList.begin(), VTList.end());
-
+
if (!VTList.empty())
assert(VTList[0] != MVT::iAny && VTList[0] != MVT::vAny &&
VTList[0] != MVT::fAny);
-
+
// Verify no duplicates.
array_pod_sort(TypeVec.begin(), TypeVec.end());
assert(std::unique(TypeVec.begin(), TypeVec.end()) == TypeVec.end());
@@ -72,9 +73,9 @@
bool (*Pred)(MVT::SimpleValueType),
const char *PredicateName) {
assert(isCompletelyUnknown());
- const std::vector<MVT::SimpleValueType> &LegalTypes =
+ const std::vector<MVT::SimpleValueType> &LegalTypes =
TP.getDAGPatterns().getTargetInfo().getLegalValueTypes();
-
+
for (unsigned i = 0, e = LegalTypes.size(); i != e; ++i)
if (Pred == 0 || Pred(LegalTypes[i]))
TypeVec.push_back(LegalTypes[i]);
@@ -82,14 +83,14 @@
// If we have nothing that matches the predicate, bail out.
if (TypeVec.empty())
TP.error("Type inference contradiction found, no " +
- std::string(PredicateName) + " types found");
+ std::string(PredicateName) + " types found");
// No need to sort with one element.
if (TypeVec.size() == 1) return true;
// Remove duplicates.
array_pod_sort(TypeVec.begin(), TypeVec.end());
TypeVec.erase(std::unique(TypeVec.begin(), TypeVec.end()), TypeVec.end());
-
+
return true;
}
@@ -100,7 +101,7 @@
if (isInteger(TypeVec[i]))
return true;
return false;
-}
+}
/// hasFloatingPointTypes - Return true if this TypeSet contains an fAny or
/// a floating point value type.
@@ -109,7 +110,7 @@
if (isFloatingPoint(TypeVec[i]))
return true;
return false;
-}
+}
/// hasVectorTypes - Return true if this TypeSet contains a vAny or a vector
/// value type.
@@ -123,9 +124,9 @@
std::string EEVT::TypeSet::getName() const {
if (TypeVec.empty()) return "<empty>";
-
+
std::string Result;
-
+
for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) {
std::string VTName = llvm::getEnumName(TypeVec[i]);
// Strip off MVT:: prefix if present.
@@ -134,7 +135,7 @@
if (i) Result += ':';
Result += VTName;
}
-
+
if (TypeVec.size() == 1)
return Result;
return "{" + Result + "}";
@@ -146,14 +147,14 @@
bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){
if (InVT.isCompletelyUnknown() || *this == InVT)
return false;
-
+
if (isCompletelyUnknown()) {
*this = InVT;
return true;
}
-
+
assert(TypeVec.size() >= 1 && InVT.TypeVec.size() >= 1 && "No unknowns");
-
+
// Handle the abstract cases, seeing if we can resolve them better.
switch (TypeVec[0]) {
default: break;
@@ -163,26 +164,26 @@
EEVT::TypeSet InCopy(InVT);
InCopy.EnforceInteger(TP);
InCopy.EnforceScalar(TP);
-
+
if (InCopy.isConcrete()) {
// If the RHS has one integer type, upgrade iPTR to i32.
TypeVec[0] = InVT.TypeVec[0];
return true;
}
-
+
// If the input has multiple scalar integers, this doesn't add any info.
if (!InCopy.isCompletelyUnknown())
return false;
}
break;
}
-
+
// If the input constraint is iAny/iPTR and this is an integer type list,
// remove non-integer types from the list.
if ((InVT.TypeVec[0] == MVT::iPTR || InVT.TypeVec[0] == MVT::iPTRAny) &&
hasIntegerTypes()) {
bool MadeChange = EnforceInteger(TP);
-
+
// If we're merging in iPTR/iPTRAny and the node currently has a list of
// multiple different integer types, replace them with a single iPTR.
if ((InVT.TypeVec[0] == MVT::iPTR || InVT.TypeVec[0] == MVT::iPTRAny) &&
@@ -191,10 +192,10 @@
TypeVec[0] = InVT.TypeVec[0];
MadeChange = true;
}
-
+
return MadeChange;
}
-
+
// If this is a type list and the RHS is a typelist as well, eliminate entries
// from this list that aren't in the other one.
bool MadeChange = false;
@@ -207,16 +208,16 @@
InInVT = true;
break;
}
-
+
if (InInVT) continue;
TypeVec.erase(TypeVec.begin()+i--);
MadeChange = true;
}
-
+
// If we removed all of our types, we have a type contradiction.
if (!TypeVec.empty())
return MadeChange;
-
+
// FIXME: Really want an SMLoc here!
TP.error("Type inference contradiction found, merging '" +
InVT.getName() + "' into '" + InputSet.getName() + "'");
@@ -232,12 +233,12 @@
return false;
TypeSet InputSet(*this);
-
+
// Filter out all the fp types.
for (unsigned i = 0; i != TypeVec.size(); ++i)
if (!isInteger(TypeVec[i]))
TypeVec.erase(TypeVec.begin()+i--);
-
+
if (TypeVec.empty())
TP.error("Type inference contradiction found, '" +
InputSet.getName() + "' needs to be integer");
@@ -254,12 +255,12 @@
return false;
TypeSet InputSet(*this);
-
+
// Filter out all the fp types.
for (unsigned i = 0; i != TypeVec.size(); ++i)
if (!isFloatingPoint(TypeVec[i]))
TypeVec.erase(TypeVec.begin()+i--);
-
+
if (TypeVec.empty())
TP.error("Type inference contradiction found, '" +
InputSet.getName() + "' needs to be floating point");
@@ -276,12 +277,12 @@
return false;
TypeSet InputSet(*this);
-
+
// Filter out all the vector types.
for (unsigned i = 0; i != TypeVec.size(); ++i)
if (!isScalar(TypeVec[i]))
TypeVec.erase(TypeVec.begin()+i--);
-
+
if (TypeVec.empty())
TP.error("Type inference contradiction found, '" +
InputSet.getName() + "' needs to be scalar");
@@ -296,14 +297,14 @@
TypeSet InputSet(*this);
bool MadeChange = false;
-
+
// Filter out all the scalar types.
for (unsigned i = 0; i != TypeVec.size(); ++i)
if (!isVector(TypeVec[i])) {
TypeVec.erase(TypeVec.begin()+i--);
MadeChange = true;
}
-
+
if (TypeVec.empty())
TP.error("Type inference contradiction found, '" +
InputSet.getName() + "' needs to be a vector");
@@ -317,13 +318,13 @@
bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
// Both operands must be integer or FP, but we don't care which.
bool MadeChange = false;
-
+
if (isCompletelyUnknown())
MadeChange = FillWithPossibleTypes(TP);
if (Other.isCompletelyUnknown())
MadeChange = Other.FillWithPossibleTypes(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())
@@ -334,62 +335,165 @@
MadeChange |= EnforceInteger(TP);
else if (!Other.hasIntegerTypes())
MadeChange |= EnforceFloatingPoint(TP);
-
+
assert(!isCompletelyUnknown() && !Other.isCompletelyUnknown() &&
"Should have a type list now");
-
+
// If one contains vectors but the other doesn't pull vectors out.
if (!hasVectorTypes())
MadeChange |= Other.EnforceScalar(TP);
if (!hasVectorTypes())
MadeChange |= EnforceScalar(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.
+ EVT Type(TypeVec[0]);
+ EVT 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() +"'!");
+ }
+ 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() +"'!");
+
+ }
- // 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!");
-
+
+ // 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.
+
// Okay, find the smallest type from the current set and remove it from the
// largest set.
- MVT::SimpleValueType Smallest = TypeVec[0];
+ 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 (TypeVec[i] < Smallest)
- Smallest = TypeVec[i];
-
+ if (isInteger(TypeVec[i]) && TypeVec[i] < SmallestInt)
+ SmallestInt = TypeVec[i];
+
+ 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 (SmallVector<MVT::SimpleValueType, 2>::iterator TVI =
+ Other.TypeVec.begin();
+ TVI != Other.TypeVec.end();
+ /* NULL */) {
+ if (isInteger(*TVI)) {
+ ++OtherIntSize;
+ if (*TVI == SmallestInt) {
+ TVI = Other.TypeVec.erase(TVI);
+ --OtherIntSize;
+ MadeChange = true;
+ continue;
+ }
+ }
+ else if (isFloatingPoint(*TVI)) {
+ ++OtherFPSize;
+ if (*TVI == SmallestFP) {
+ TVI = Other.TypeVec.erase(TVI);
+ --OtherFPSize;
+ MadeChange = true;
+ continue;
+ }
+ }
+ ++TVI;
+ }
+
// If this is the only type in the large set, the constraint can never be
// satisfied.
- if (Other.TypeVec.size() == 1 && Other.TypeVec[0] == Smallest)
+ if ((Other.hasIntegerTypes() && OtherIntSize == 0)
+ || (Other.hasFloatingPointTypes() && OtherFPSize == 0))
TP.error("Type inference contradiction found, '" +
Other.getName() + "' has nothing larger than '" + getName() +"'!");
-
- SmallVector<MVT::SimpleValueType, 2>::iterator TVI =
- std::find(Other.TypeVec.begin(), Other.TypeVec.end(), Smallest);
- if (TVI != Other.TypeVec.end()) {
- Other.TypeVec.erase(TVI);
- MadeChange = true;
- }
-
+
// Okay, find the largest type in the Other set and remove it from the
// current set.
- MVT::SimpleValueType Largest = Other.TypeVec[0];
+ 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 (Other.TypeVec[i] > Largest)
- Largest = Other.TypeVec[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 (SmallVector<MVT::SimpleValueType, 2>::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;
+ }
+ }
+ ++TVI;
+ }
+
// If this is the only type in the small set, the constraint can never be
// satisfied.
- if (TypeVec.size() == 1 && TypeVec[0] == Largest)
+ if ((hasIntegerTypes() && IntSize == 0)
+ || (hasFloatingPointTypes() && FPSize == 0))
TP.error("Type inference contradiction found, '" +
getName() + "' has nothing smaller than '" + Other.getName()+"'!");
-
- TVI = std::find(TypeVec.begin(), TypeVec.end(), Largest);
- if (TVI != TypeVec.end()) {
- TypeVec.erase(TVI);
- MadeChange = true;
- }
-
+
return MadeChange;
}
@@ -406,7 +510,7 @@
if (isConcrete()) {
EVT IVT = getConcrete();
IVT = IVT.getVectorElementType();
- return MadeChange |
+ return MadeChange |
VTOperand.MergeInTypeInfo(IVT.getSimpleVT().SimpleTy, TP);
}
@@ -414,11 +518,11 @@
// disagree.
if (!VTOperand.isConcrete())
return MadeChange;
-
+
MVT::SimpleValueType VT = VTOperand.getConcrete();
-
+
TypeSet InputSet(*this);
-
+
// Filter out all the types which don't have the right element type.
for (unsigned i = 0; i != TypeVec.size(); ++i) {
assert(isVector(TypeVec[i]) && "EnforceVector didn't work");
@@ -427,13 +531,43 @@
MadeChange = true;
}
}
-
+
if (TypeVec.empty()) // FIXME: Really want an SMLoc here!
TP.error("Type inference contradiction found, forcing '" +
InputSet.getName() + "' to have a vector element");
return MadeChange;
}
+/// EnforceVectorSubVectorTypeIs - 'this' is now constrainted to be a
+/// vector type specified by VTOperand.
+bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand,
+ TreePattern &TP) {
+ // "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 we know the vector type, it forces the scalar types to agree.
+ if (isConcrete()) {
+ EVT IVT = getConcrete();
+ IVT = IVT.getVectorElementType();
+
+ EEVT::TypeSet EltTypeSet(IVT.getSimpleVT().SimpleTy, TP);
+ MadeChange |= VTOperand.EnforceVectorEltTypeIs(EltTypeSet, TP);
+ } else if (VTOperand.isConcrete()) {
+ EVT IVT = VTOperand.getConcrete();
+ IVT = IVT.getVectorElementType();
+
+ EEVT::TypeSet EltTypeSet(IVT.getSimpleVT().SimpleTy, TP);
+ MadeChange |= EnforceVectorEltTypeIs(EltTypeSet, TP);
+ }
+
+ return MadeChange;
+}
+
//===----------------------------------------------------------------------===//
// Helpers for working with extended types.
@@ -447,44 +581,102 @@
/// Const iterator shorthand for DepVarMap
typedef DepVarMap::const_iterator DepVarMap_citer;
-namespace {
-void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) {
+static void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) {
if (N->isLeaf()) {
- if (dynamic_cast<DefInit*>(N->getLeafValue()) != NULL) {
+ if (dynamic_cast<DefInit*>(N->getLeafValue()) != NULL)
DepMap[N->getName()]++;
- }
} else {
for (size_t i = 0, e = N->getNumChildren(); i != e; ++i)
FindDepVarsOf(N->getChild(i), DepMap);
}
}
-
-//! Find dependent variables within child patterns
-/*!
- */
-void FindDepVars(TreePatternNode *N, MultipleUseVarSet &DepVars) {
+
+/// Find dependent variables within child patterns
+static void FindDepVars(TreePatternNode *N, MultipleUseVarSet &DepVars) {
DepVarMap depcounts;
FindDepVarsOf(N, depcounts);
for (DepVarMap_citer i = depcounts.begin(); i != depcounts.end(); ++i) {
- if (i->second > 1) { // std::pair<std::string, int>
+ if (i->second > 1) // std::pair<std::string, int>
DepVars.insert(i->first);
- }
}
}
-//! Dump the dependent variable set:
-void DumpDepVars(MultipleUseVarSet &DepVars) {
+#ifndef NDEBUG
+/// Dump the dependent variable set:
+static void DumpDepVars(MultipleUseVarSet &DepVars) {
if (DepVars.empty()) {
DEBUG(errs() << "<empty set>");
} else {
DEBUG(errs() << "[ ");
- for (MultipleUseVarSet::const_iterator i = DepVars.begin(), e = DepVars.end();
- i != e; ++i) {
+ for (MultipleUseVarSet::const_iterator i = DepVars.begin(),
+ e = DepVars.end(); i != e; ++i) {
DEBUG(errs() << (*i) << " ");
}
DEBUG(errs() << "]");
}
}
+#endif
+
+
+//===----------------------------------------------------------------------===//
+// TreePredicateFn Implementation
+//===----------------------------------------------------------------------===//
+
+/// TreePredicateFn constructor. Here 'N' is a subclass of PatFrag.
+TreePredicateFn::TreePredicateFn(TreePattern *N) : PatFragRec(N) {
+ assert((getPredCode().empty() || getImmCode().empty()) &&
+ ".td file corrupt: can't have a node predicate *and* an imm predicate");
+}
+
+std::string TreePredicateFn::getPredCode() const {
+ return PatFragRec->getRecord()->getValueAsCode("PredicateCode");
+}
+
+std::string TreePredicateFn::getImmCode() const {
+ return PatFragRec->getRecord()->getValueAsCode("ImmediateCode");
+}
+
+
+/// isAlwaysTrue - Return true if this is a noop predicate.
+bool TreePredicateFn::isAlwaysTrue() const {
+ return getPredCode().empty() && getImmCode().empty();
+}
+
+/// Return the name to use in the generated code to reference this, this is
+/// "Predicate_foo" if from a pattern fragment "foo".
+std::string TreePredicateFn::getFnName() const {
+ return "Predicate_" + PatFragRec->getRecord()->getName();
+}
+
+/// getCodeToRunOnSDNode - Return the code for the function body that
+/// evaluates this predicate. The argument is expected to be in "Node",
+/// not N. This handles casting and conversion to a concrete node type as
+/// appropriate.
+std::string TreePredicateFn::getCodeToRunOnSDNode() const {
+ // Handle immediate predicates first.
+ std::string ImmCode = getImmCode();
+ if (!ImmCode.empty()) {
+ std::string Result =
+ " int64_t Imm = cast<ConstantSDNode>(Node)->getSExtValue();\n";
+ return Result + ImmCode;
+ }
+
+ // Handle arbitrary node predicates.
+ assert(!getPredCode().empty() && "Don't have any predicate code!");
+ std::string ClassName;
+ if (PatFragRec->getOnlyTree()->isLeaf())
+ ClassName = "SDNode";
+ else {
+ Record *Op = PatFragRec->getOnlyTree()->getOperator();
+ ClassName = PatFragRec->getDAGPatterns().getSDNodeInfo(Op).getSDClassName();
+ }
+ std::string Result;
+ if (ClassName == "SDNode")
+ Result = " SDNode *N = Node;\n";
+ else
+ Result = " " + ClassName + "*N = cast<" + ClassName + ">(Node);\n";
+
+ return Result + getPredCode();
}
//===----------------------------------------------------------------------===//
@@ -502,7 +694,7 @@
// e.g. (set R32:$dst, 0).
if (P->isLeaf() && dynamic_cast<IntInit*>(P->getLeafValue()))
Size += 2;
-
+
// FIXME: This is a hack to statically increase the priority of patterns
// which maps a sub-dag to a complex pattern. e.g. favors LEA over ADD.
// Later we can allow complexity / cost for each pattern to be (optionally)
@@ -511,12 +703,12 @@
const ComplexPattern *AM = P->getComplexPatternInfo(CGP);
if (AM)
Size += AM->getNumOperands() * 3;
-
+
// If this node has some predicate function that must match, it adds to the
// complexity of this node.
if (!P->getPredicateFns().empty())
++Size;
-
+
// Count children in the count if they are also nodes.
for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i) {
TreePatternNode *Child = P->getChild(i);
@@ -524,7 +716,7 @@
Child->getType(0) != MVT::Other)
Size += getPatternSize(Child, CGP);
else if (Child->isLeaf()) {
- if (dynamic_cast<IntInit*>(Child->getLeafValue()))
+ if (dynamic_cast<IntInit*>(Child->getLeafValue()))
Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2).
else if (Child->getComplexPatternInfo(CGP))
Size += getPatternSize(Child, CGP);
@@ -532,7 +724,7 @@
++Size;
}
}
-
+
return Size;
}
@@ -573,13 +765,13 @@
SDTypeConstraint::SDTypeConstraint(Record *R) {
OperandNo = R->getValueAsInt("OperandNum");
-
+
if (R->isSubClassOf("SDTCisVT")) {
ConstraintType = SDTCisVT;
x.SDTCisVT_Info.VT = getValueType(R->getValueAsDef("VT"));
if (x.SDTCisVT_Info.VT == MVT::isVoid)
throw TGError(R->getLoc(), "Cannot use 'Void' as type to SDTCisVT");
-
+
} else if (R->isSubClassOf("SDTCisPtrTy")) {
ConstraintType = SDTCisPtrTy;
} else if (R->isSubClassOf("SDTCisInt")) {
@@ -593,15 +785,19 @@
x.SDTCisSameAs_Info.OtherOperandNum = R->getValueAsInt("OtherOperandNum");
} else if (R->isSubClassOf("SDTCisVTSmallerThanOp")) {
ConstraintType = SDTCisVTSmallerThanOp;
- x.SDTCisVTSmallerThanOp_Info.OtherOperandNum =
+ x.SDTCisVTSmallerThanOp_Info.OtherOperandNum =
R->getValueAsInt("OtherOperandNum");
} else if (R->isSubClassOf("SDTCisOpSmallerThanOp")) {
ConstraintType = SDTCisOpSmallerThanOp;
- x.SDTCisOpSmallerThanOp_Info.BigOperandNum =
+ x.SDTCisOpSmallerThanOp_Info.BigOperandNum =
R->getValueAsInt("BigOperandNum");
} else if (R->isSubClassOf("SDTCisEltOfVec")) {
ConstraintType = SDTCisEltOfVec;
x.SDTCisEltOfVec_Info.OtherOperandNum = R->getValueAsInt("OtherOpNum");
+ } else if (R->isSubClassOf("SDTCisSubVecOfVec")) {
+ ConstraintType = SDTCisSubVecOfVec;
+ x.SDTCisSubVecOfVec_Info.OtherOperandNum =
+ R->getValueAsInt("OtherOpNum");
} else {
errs() << "Unrecognized SDTypeConstraint '" << R->getName() << "'!\n";
exit(1);
@@ -618,11 +814,11 @@
ResNo = OpNo;
return N;
}
-
+
OpNo -= NumResults;
-
+
if (OpNo >= N->getNumChildren()) {
- errs() << "Invalid operand number in type constraint "
+ errs() << "Invalid operand number in type constraint "
<< (OpNo+NumResults) << " ";
N->dump();
errs() << '\n';
@@ -641,7 +837,7 @@
TreePattern &TP) const {
unsigned ResNo = 0; // The result number being referenced.
TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NodeInfo, ResNo);
-
+
switch (ConstraintType) {
default: assert(0 && "Unknown constraint type!");
case SDTCisVT:
@@ -676,9 +872,9 @@
TP.error(N->getOperator()->getName() + " expects a VT operand!");
MVT::SimpleValueType VT =
getValueType(static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef());
-
+
EEVT::TypeSet TypeListTmp(VT, TP);
-
+
unsigned OResNo = 0;
TreePatternNode *OtherNode =
getOperandNum(x.SDTCisVTSmallerThanOp_Info.OtherOperandNum, N, NodeInfo,
@@ -699,13 +895,24 @@
TreePatternNode *VecOperand =
getOperandNum(x.SDTCisEltOfVec_Info.OtherOperandNum, N, NodeInfo,
VResNo);
-
+
// Filter vector types out of VecOperand that don't have the right element
// type.
return VecOperand->getExtType(VResNo).
EnforceVectorEltTypeIs(NodeToApply->getExtType(ResNo), TP);
}
- }
+ case SDTCisSubVecOfVec: {
+ unsigned VResNo = 0;
+ TreePatternNode *BigVecOperand =
+ getOperandNum(x.SDTCisSubVecOfVec_Info.OtherOperandNum, N, NodeInfo,
+ VResNo);
+
+ // Filter vector types out of BigVecOperand that don't have the
+ // right subvector type.
+ return BigVecOperand->getExtType(VResNo).
+ EnforceVectorSubVectorTypeIs(NodeToApply->getExtType(ResNo), TP);
+ }
+ }
return false;
}
@@ -718,7 +925,7 @@
Record *TypeProfile = R->getValueAsDef("TypeProfile");
NumResults = TypeProfile->getValueAsInt("NumResults");
NumOperands = TypeProfile->getValueAsInt("NumOperands");
-
+
// Parse the properties.
Properties = 0;
std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties");
@@ -729,12 +936,12 @@
Properties |= 1 << SDNPAssociative;
} else if (PropList[i]->getName() == "SDNPHasChain") {
Properties |= 1 << SDNPHasChain;
- } else if (PropList[i]->getName() == "SDNPOutFlag") {
- Properties |= 1 << SDNPOutFlag;
- } else if (PropList[i]->getName() == "SDNPInFlag") {
- Properties |= 1 << SDNPInFlag;
- } else if (PropList[i]->getName() == "SDNPOptInFlag") {
- Properties |= 1 << SDNPOptInFlag;
+ } else if (PropList[i]->getName() == "SDNPOutGlue") {
+ Properties |= 1 << SDNPOutGlue;
+ } else if (PropList[i]->getName() == "SDNPInGlue") {
+ Properties |= 1 << SDNPInGlue;
+ } else if (PropList[i]->getName() == "SDNPOptInGlue") {
+ Properties |= 1 << SDNPOptInGlue;
} else if (PropList[i]->getName() == "SDNPMayStore") {
Properties |= 1 << SDNPMayStore;
} else if (PropList[i]->getName() == "SDNPMayLoad") {
@@ -751,8 +958,8 @@
exit(1);
}
}
-
-
+
+
// Parse the type constraints.
std::vector<Record*> ConstraintList =
TypeProfile->getValueAsListOfDefs("Constraints");
@@ -767,12 +974,12 @@
assert(NumResults <= 1 &&
"We only work with nodes with zero or one result so far!");
assert(ResNo == 0 && "Only handles single result nodes so far");
-
+
for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i) {
// Make sure that this applies to the correct node result.
if (TypeConstraints[i].OperandNo >= NumResults) // FIXME: need value #
continue;
-
+
switch (TypeConstraints[i].ConstraintType) {
default: break;
case SDTypeConstraint::SDTCisVT:
@@ -799,20 +1006,20 @@
if (Operator->getName() == "set" ||
Operator->getName() == "implicit")
return 0; // All return nothing.
-
+
if (Operator->isSubClassOf("Intrinsic"))
return CDP.getIntrinsic(Operator).IS.RetVTs.size();
-
+
if (Operator->isSubClassOf("SDNode"))
return CDP.getSDNodeInfo(Operator).getNumResults();
-
+
if (Operator->isSubClassOf("PatFrag")) {
// If we've already parsed this pattern fragment, get it. Otherwise, handle
// the forward reference case where one pattern fragment references another
// before it is processed.
if (TreePattern *PFRec = CDP.getPatternFragmentIfRead(Operator))
return PFRec->getOnlyTree()->getNumTypes();
-
+
// Get the result tree.
DagInit *Tree = Operator->getValueAsDag("Fragment");
Record *Op = 0;
@@ -821,22 +1028,22 @@
assert(Op && "Invalid Fragment");
return GetNumNodeResults(Op, CDP);
}
-
+
if (Operator->isSubClassOf("Instruction")) {
CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(Operator);
// FIXME: Should allow access to all the results here.
- unsigned NumDefsToAdd = InstInfo.NumDefs ? 1 : 0;
-
+ unsigned NumDefsToAdd = InstInfo.Operands.NumDefs ? 1 : 0;
+
// Add on one implicit def if it has a resolvable type.
if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other)
++NumDefsToAdd;
return NumDefsToAdd;
}
-
+
if (Operator->isSubClassOf("SDNodeXForm"))
return 1; // FIXME: Generalize SDNodeXForm
-
+
Operator->dump();
errs() << "Unhandled node in GetNumNodeResults\n";
exit(1);
@@ -862,9 +1069,9 @@
}
OS << ")";
}
-
+
for (unsigned i = 0, e = PredicateFns.size(); i != e; ++i)
- OS << "<<P:" << PredicateFns[i] << ">>";
+ OS << "<<P:" << PredicateFns[i].getFnName() << ">>";
if (TransformFn)
OS << "<<X:" << TransformFn->getName() << ">>";
if (!getName().empty())
@@ -900,7 +1107,7 @@
}
return getLeafValue() == N->getLeafValue();
}
-
+
if (N->getOperator() != getOperator() ||
N->getNumChildren() != getNumChildren()) return false;
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
@@ -944,7 +1151,7 @@
void TreePatternNode::
SubstituteFormalArguments(std::map<std::string, TreePatternNode*> &ArgMap) {
if (isLeaf()) return;
-
+
for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
TreePatternNode *Child = getChild(i);
if (Child->isLeaf()) {
@@ -972,7 +1179,7 @@
TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
if (isLeaf()) return this; // nothing to do.
Record *Op = getOperator();
-
+
if (!Op->isSubClassOf("PatFrag")) {
// Just recursively inline children nodes.
for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
@@ -991,7 +1198,7 @@
// Otherwise, we found a reference to a fragment. First, look up its
// TreePattern record.
TreePattern *Frag = TP.getDAGPatterns().getPatternFragment(Op);
-
+
// Verify that we are passing the right number of operands.
if (Frag->getNumArgs() != Children.size())
TP.error("'" + Op->getName() + "' fragment requires " +
@@ -999,9 +1206,9 @@
TreePatternNode *FragTree = Frag->getOnlyTree()->clone();
- std::string Code = Op->getValueAsCode("Predicate");
- if (!Code.empty())
- FragTree->addPredicateFn("Predicate_"+Op->getName());
+ TreePredicateFn PredFn(Frag);
+ if (!PredFn.isAlwaysTrue())
+ FragTree->addPredicateFn(PredFn);
// Resolve formal arguments to their actual value.
if (Frag->getNumArgs()) {
@@ -1009,10 +1216,10 @@
std::map<std::string, TreePatternNode*> ArgMap;
for (unsigned i = 0, e = Frag->getNumArgs(); i != e; ++i)
ArgMap[Frag->getArgName(i)] = getChild(i)->InlinePatternFragments(TP);
-
+
FragTree->SubstituteFormalArguments(ArgMap);
}
-
+
FragTree->setName(getName());
for (unsigned i = 0, e = Types.size(); i != e; ++i)
FragTree->UpdateNodeType(i, getExtType(i), TP);
@@ -1023,7 +1230,7 @@
// Get a new copy of this fragment to stitch into here.
//delete this; // FIXME: implement refcounting!
-
+
// The fragment we inlined could have recursive inlining that is needed. See
// if there are any pattern fragments in it and inline them as needed.
return FragTree->InlinePatternFragments(TP);
@@ -1035,24 +1242,34 @@
///
static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo,
bool NotRegisters, TreePattern &TP) {
+ // Check to see if this is a register operand.
+ if (R->isSubClassOf("RegisterOperand")) {
+ assert(ResNo == 0 && "Regoperand ref only has one result!");
+ if (NotRegisters)
+ return EEVT::TypeSet(); // Unknown.
+ Record *RegClass = R->getValueAsDef("RegClass");
+ const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
+ return EEVT::TypeSet(T.getRegisterClass(RegClass).getValueTypes());
+ }
+
// Check to see if this is a register or a register class.
if (R->isSubClassOf("RegisterClass")) {
assert(ResNo == 0 && "Regclass ref only has one result!");
- if (NotRegisters)
+ if (NotRegisters)
return EEVT::TypeSet(); // Unknown.
const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
return EEVT::TypeSet(T.getRegisterClass(R).getValueTypes());
}
-
+
if (R->isSubClassOf("PatFrag")) {
assert(ResNo == 0 && "FIXME: PatFrag with multiple results?");
// Pattern fragment types will be resolved when they are inlined.
return EEVT::TypeSet(); // Unknown.
}
-
+
if (R->isSubClassOf("Register")) {
assert(ResNo == 0 && "Registers only produce one result!");
- if (NotRegisters)
+ if (NotRegisters)
return EEVT::TypeSet(); // Unknown.
const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
return EEVT::TypeSet(T.getRegisterVTs(R));
@@ -1062,16 +1279,16 @@
assert(ResNo == 0 && "SubRegisterIndices only produce one result!");
return EEVT::TypeSet();
}
-
+
if (R->isSubClassOf("ValueType") || R->isSubClassOf("CondCode")) {
assert(ResNo == 0 && "This node only has one result!");
// Using a VTSDNode or CondCodeSDNode.
return EEVT::TypeSet(MVT::Other, TP);
}
-
+
if (R->isSubClassOf("ComplexPattern")) {
assert(ResNo == 0 && "FIXME: ComplexPattern with multiple results?");
- if (NotRegisters)
+ if (NotRegisters)
return EEVT::TypeSet(); // Unknown.
return EEVT::TypeSet(TP.getDAGPatterns().getComplexPattern(R).getValueType(),
TP);
@@ -1080,13 +1297,13 @@
assert(ResNo == 0 && "Regclass can only have one result!");
return EEVT::TypeSet(MVT::iPTR, TP);
}
-
+
if (R->getName() == "node" || R->getName() == "srcvalue" ||
R->getName() == "zero_reg") {
// Placeholder.
return EEVT::TypeSet(); // Unknown.
}
-
+
TP.error("Unknown node flavor used in pattern: " + R->getName());
return EEVT::TypeSet(MVT::Other, TP);
}
@@ -1100,8 +1317,8 @@
getOperator() != CDP.get_intrinsic_w_chain_sdnode() &&
getOperator() != CDP.get_intrinsic_wo_chain_sdnode())
return 0;
-
- unsigned IID =
+
+ unsigned IID =
dynamic_cast<IntInit*>(getChild(0)->getLeafValue())->getValue();
return &CDP.getIntrinsicInfo(IID);
}
@@ -1111,7 +1328,7 @@
const ComplexPattern *
TreePatternNode::getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const {
if (!isLeaf()) return 0;
-
+
DefInit *DI = dynamic_cast<DefInit*>(getLeafValue());
if (DI && DI->getDef()->isSubClassOf("ComplexPattern"))
return &CGP.getComplexPattern(DI->getDef());
@@ -1126,10 +1343,10 @@
return CP->hasProperty(Property);
return false;
}
-
+
Record *Operator = getOperator();
if (!Operator->isSubClassOf("SDNode")) return false;
-
+
return CGP.getSDNodeInfo(Operator).hasProperty(Property);
}
@@ -1146,7 +1363,7 @@
if (getChild(i)->TreeHasProperty(Property, CGP))
return true;
return false;
-}
+}
/// isCommutativeIntrinsic - Return true if the node corresponds to a
/// commutative intrinsic.
@@ -1173,27 +1390,27 @@
NotRegisters, TP), TP);
return MadeChange;
}
-
+
if (IntInit *II = dynamic_cast<IntInit*>(getLeafValue())) {
assert(Types.size() == 1 && "Invalid IntInit");
-
+
// Int inits are always integers. :)
bool MadeChange = Types[0].EnforceInteger(TP);
-
+
if (!Types[0].isConcrete())
return MadeChange;
-
+
MVT::SimpleValueType VT = getType(0);
if (VT == MVT::iPTR || VT == MVT::iPTRAny)
return MadeChange;
-
+
unsigned Size = EVT(VT).getSizeInBits();
// Make sure that the value is representable for this type.
if (Size >= 32) return MadeChange;
-
+
int Val = (II->getValue() << (32-Size)) >> (32-Size);
if (Val == II->getValue()) return MadeChange;
-
+
// If sign-extended doesn't fit, does it fit as unsigned?
unsigned ValueMask;
unsigned UnsignedVal;
@@ -1202,34 +1419,34 @@
if ((ValueMask & UnsignedVal) == UnsignedVal)
return MadeChange;
-
+
TP.error("Integer value '" + itostr(II->getValue())+
"' is out of range for type '" + getEnumName(getType(0)) + "'!");
return MadeChange;
}
return false;
}
-
+
// special handling for set, which isn't really an SDNode.
if (getOperator()->getName() == "set") {
assert(getNumTypes() == 0 && "Set doesn't produce a value");
assert(getNumChildren() >= 2 && "Missing RHS of a set?");
unsigned NC = getNumChildren();
-
+
TreePatternNode *SetVal = getChild(NC-1);
bool MadeChange = SetVal->ApplyTypeConstraints(TP, NotRegisters);
for (unsigned i = 0; i < NC-1; ++i) {
TreePatternNode *Child = getChild(i);
MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters);
-
+
// Types of operands must match.
MadeChange |= Child->UpdateNodeType(0, SetVal->getExtType(i), TP);
MadeChange |= SetVal->UpdateNodeType(i, Child->getExtType(0), TP);
}
return MadeChange;
}
-
+
if (getOperator()->getName() == "implicit") {
assert(getNumTypes() == 0 && "Node doesn't produce a value");
@@ -1238,15 +1455,15 @@
MadeChange = getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
return MadeChange;
}
-
+
if (getOperator()->getName() == "COPY_TO_REGCLASS") {
bool MadeChange = false;
MadeChange |= getChild(0)->ApplyTypeConstraints(TP, NotRegisters);
MadeChange |= getChild(1)->ApplyTypeConstraints(TP, NotRegisters);
-
+
assert(getChild(0)->getNumTypes() == 1 &&
getChild(1)->getNumTypes() == 1 && "Unhandled case");
-
+
// child #1 of COPY_TO_REGCLASS should be a register class. We don't care
// what type it gets, so if it didn't get a concrete type just give it the
// first viable type from the reg class.
@@ -1257,14 +1474,14 @@
}
return MadeChange;
}
-
+
if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) {
bool MadeChange = false;
// Apply the result type to the node.
unsigned NumRetVTs = Int->IS.RetVTs.size();
unsigned NumParamVTs = Int->IS.ParamVTs.size();
-
+
for (unsigned i = 0, e = NumRetVTs; i != e; ++i)
MadeChange |= UpdateNodeType(i, Int->IS.RetVTs[i], TP);
@@ -1275,73 +1492,78 @@
// Apply type info to the intrinsic ID.
MadeChange |= getChild(0)->UpdateNodeType(0, MVT::iPTR, TP);
-
+
for (unsigned i = 0, e = getNumChildren()-1; i != e; ++i) {
MadeChange |= getChild(i+1)->ApplyTypeConstraints(TP, NotRegisters);
-
+
MVT::SimpleValueType OpVT = Int->IS.ParamVTs[i];
assert(getChild(i+1)->getNumTypes() == 1 && "Unhandled case");
MadeChange |= getChild(i+1)->UpdateNodeType(0, OpVT, TP);
}
return MadeChange;
}
-
+
if (getOperator()->isSubClassOf("SDNode")) {
const SDNodeInfo &NI = CDP.getSDNodeInfo(getOperator());
-
+
// Check that the number of operands is sane. Negative operands -> varargs.
if (NI.getNumOperands() >= 0 &&
getNumChildren() != (unsigned)NI.getNumOperands())
TP.error(getOperator()->getName() + " node requires exactly " +
itostr(NI.getNumOperands()) + " operands!");
-
+
bool MadeChange = NI.ApplyTypeConstraints(this, TP);
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
return MadeChange;
}
-
+
if (getOperator()->isSubClassOf("Instruction")) {
const DAGInstruction &Inst = CDP.getInstruction(getOperator());
CodeGenInstruction &InstInfo =
CDP.getTargetInfo().getInstruction(getOperator());
-
+
bool MadeChange = false;
// Apply the result types to the node, these come from the things in the
// (outs) list of the instruction.
// FIXME: Cap at one result so far.
- unsigned NumResultsToAdd = InstInfo.NumDefs ? 1 : 0;
+ unsigned NumResultsToAdd = InstInfo.Operands.NumDefs ? 1 : 0;
for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo) {
Record *ResultNode = Inst.getResult(ResNo);
-
+
if (ResultNode->isSubClassOf("PointerLikeRegClass")) {
MadeChange |= UpdateNodeType(ResNo, MVT::iPTR, TP);
+ } else if (ResultNode->isSubClassOf("RegisterOperand")) {
+ Record *RegClass = ResultNode->getValueAsDef("RegClass");
+ const CodeGenRegisterClass &RC =
+ CDP.getTargetInfo().getRegisterClass(RegClass);
+ MadeChange |= UpdateNodeType(ResNo, RC.getValueTypes(), TP);
} else if (ResultNode->getName() == "unknown") {
// Nothing to do.
} else {
assert(ResultNode->isSubClassOf("RegisterClass") &&
"Operands should be register classes!");
- const CodeGenRegisterClass &RC =
+ const CodeGenRegisterClass &RC =
CDP.getTargetInfo().getRegisterClass(ResultNode);
MadeChange |= UpdateNodeType(ResNo, RC.getValueTypes(), TP);
}
}
-
+
// If the instruction has implicit defs, we apply the first one as a result.
// FIXME: This sucks, it should apply all implicit defs.
if (!InstInfo.ImplicitDefs.empty()) {
unsigned ResNo = NumResultsToAdd;
-
+
// FIXME: Generalize to multiple possible types and multiple possible
// ImplicitDefs.
MVT::SimpleValueType VT =
InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo());
-
+
if (VT != MVT::Other)
MadeChange |= UpdateNodeType(ResNo, VT, TP);
}
-
+
// If this is an INSERT_SUBREG, constrain the source and destination VTs to
// be the same.
if (getOperator()->getName() == "INSERT_SUBREG") {
@@ -1353,7 +1575,7 @@
unsigned ChildNo = 0;
for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) {
Record *OperandNode = Inst.getOperand(i);
-
+
// If the instruction expects a predicate or optional def operand, we
// codegen this by setting the operand to it's default value if it has a
// non-empty DefaultOps field.
@@ -1361,20 +1583,25 @@
OperandNode->isSubClassOf("OptionalDefOperand")) &&
!CDP.getDefaultOperand(OperandNode).DefaultOps.empty())
continue;
-
+
// Verify that we didn't run out of provided operands.
if (ChildNo >= getNumChildren())
TP.error("Instruction '" + getOperator()->getName() +
"' expects more operands than were provided.");
-
+
MVT::SimpleValueType VT;
TreePatternNode *Child = getChild(ChildNo++);
unsigned ChildResNo = 0; // Instructions always use res #0 of their op.
-
+
if (OperandNode->isSubClassOf("RegisterClass")) {
- const CodeGenRegisterClass &RC =
+ const CodeGenRegisterClass &RC =
CDP.getTargetInfo().getRegisterClass(OperandNode);
MadeChange |= Child->UpdateNodeType(ChildResNo, RC.getValueTypes(), TP);
+ } else if (OperandNode->isSubClassOf("RegisterOperand")) {
+ Record *RegClass = OperandNode->getValueAsDef("RegClass");
+ const CodeGenRegisterClass &RC =
+ CDP.getTargetInfo().getRegisterClass(RegClass);
+ MadeChange |= Child->UpdateNodeType(ChildResNo, RC.getValueTypes(), TP);
} else if (OperandNode->isSubClassOf("Operand")) {
VT = getValueType(OperandNode->getValueAsDef("Type"));
MadeChange |= Child->UpdateNodeType(ChildResNo, VT, TP);
@@ -1392,12 +1619,12 @@
if (ChildNo != getNumChildren())
TP.error("Instruction '" + getOperator()->getName() +
"' was provided too many operands!");
-
+
return MadeChange;
}
-
+
assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!");
-
+
// Node transforms always take one operand.
if (getNumChildren() != 1)
TP.error("Node transform '" + getOperator()->getName() +
@@ -1405,7 +1632,7 @@
bool MadeChange = getChild(0)->ApplyTypeConstraints(TP, NotRegisters);
-
+
// If either the output or input of the xform does not have exact
// type info. We assume they must be the same. Otherwise, it is perfectly
// legal to transform from one type to a completely different type.
@@ -1435,7 +1662,7 @@
/// used as a sanity check for .td files (to prevent people from writing stuff
/// that can never possibly work), and to prevent the pattern permuter from
/// generating stuff that is useless.
-bool TreePatternNode::canPatternMatch(std::string &Reason,
+bool TreePatternNode::canPatternMatch(std::string &Reason,
const CodeGenDAGPatterns &CDP) {
if (isLeaf()) return true;
@@ -1449,7 +1676,7 @@
// TODO:
return true;
}
-
+
// If this node is a commutative operator, check that the LHS isn't an
// immediate.
const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(getOperator());
@@ -1466,7 +1693,7 @@
}
}
}
-
+
return true;
}
@@ -1506,7 +1733,7 @@
void TreePattern::ComputeNamedNodes(TreePatternNode *N) {
if (!N->getName().empty())
NamedNodes[N->getName()].push_back(N);
-
+
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
ComputeNamedNodes(N->getChild(i));
}
@@ -1515,15 +1742,16 @@
TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
if (DefInit *DI = dynamic_cast<DefInit*>(TheInit)) {
Record *R = DI->getDef();
-
+
// Direct reference to a leaf DagNode or PatFrag? Turn it into a
- // TreePatternNode if its own. For example:
+ // TreePatternNode of its own. For example:
/// (foo GPR, imm) -> (foo GPR, (imm))
if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag"))
- return ParseTreePattern(new DagInit(DI, "",
- std::vector<std::pair<Init*, std::string> >()),
- OpName);
-
+ return ParseTreePattern(
+ DagInit::get(DI, "",
+ std::vector<std::pair<Init*, std::string> >()),
+ OpName);
+
// Input argument?
TreePatternNode *Res = new TreePatternNode(DI, 1);
if (R->getName() == "node" && !OpName.empty()) {
@@ -1535,16 +1763,16 @@
Res->setName(OpName);
return Res;
}
-
+
if (IntInit *II = dynamic_cast<IntInit*>(TheInit)) {
if (!OpName.empty())
error("Constant int argument should not have a name!");
return new TreePatternNode(II, 1);
}
-
+
if (BitsInit *BI = dynamic_cast<BitsInit*>(TheInit)) {
// Turn this into an IntInit.
- Init *II = BI->convertInitializerTo(new IntRecTy());
+ Init *II = BI->convertInitializerTo(IntRecTy::get());
if (II == 0 || !dynamic_cast<IntInit*>(II))
error("Bits value must be constants!");
return ParseTreePattern(II, OpName);
@@ -1558,34 +1786,34 @@
DefInit *OpDef = dynamic_cast<DefInit*>(Dag->getOperator());
if (!OpDef) error("Pattern has unexpected operator type!");
Record *Operator = OpDef->getDef();
-
+
if (Operator->isSubClassOf("ValueType")) {
// If the operator is a ValueType, then this must be "type cast" of a leaf
// node.
if (Dag->getNumArgs() != 1)
error("Type cast only takes one operand!");
-
+
TreePatternNode *New = ParseTreePattern(Dag->getArg(0), Dag->getArgName(0));
-
+
// Apply the type cast.
assert(New->getNumTypes() == 1 && "FIXME: Unhandled");
New->UpdateNodeType(0, getValueType(Operator), *this);
-
+
if (!OpName.empty())
error("ValueType cast should not have a name!");
return New;
}
-
+
// Verify that this is something that makes sense for an operator.
- if (!Operator->isSubClassOf("PatFrag") &&
+ if (!Operator->isSubClassOf("PatFrag") &&
!Operator->isSubClassOf("SDNode") &&
- !Operator->isSubClassOf("Instruction") &&
+ !Operator->isSubClassOf("Instruction") &&
!Operator->isSubClassOf("SDNodeXForm") &&
!Operator->isSubClassOf("Intrinsic") &&
Operator->getName() != "set" &&
Operator->getName() != "implicit")
error("Unrecognized node '" + Operator->getName() + "'!");
-
+
// Check to see if this is something that is illegal in an input pattern.
if (isInputPattern) {
if (Operator->isSubClassOf("Instruction") ||
@@ -1594,7 +1822,7 @@
} else {
if (Operator->isSubClassOf("Intrinsic"))
error("Cannot use '" + Operator->getName() + "' in an output pattern!");
-
+
if (Operator->isSubClassOf("SDNode") &&
Operator->getName() != "imm" &&
Operator->getName() != "fpimm" &&
@@ -1609,15 +1837,15 @@
Operator->getName() != "vt")
error("Cannot use '" + Operator->getName() + "' in an output pattern!");
}
-
+
std::vector<TreePatternNode*> Children;
// Parse all the operands.
for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i)
Children.push_back(ParseTreePattern(Dag->getArg(i), Dag->getArgName(i)));
-
+
// If the operator is an intrinsic, then this is just syntactic sugar for for
- // (intrinsic_* <number>, ..children..). Pick the right intrinsic node, and
+ // (intrinsic_* <number>, ..children..). Pick the right intrinsic node, and
// convert the intrinsic name to a number.
if (Operator->isSubClassOf("Intrinsic")) {
const CodeGenIntrinsic &Int = getDAGPatterns().getIntrinsic(Operator);
@@ -1632,15 +1860,15 @@
Operator = getDAGPatterns().get_intrinsic_w_chain_sdnode();
else // Otherwise, no chain.
Operator = getDAGPatterns().get_intrinsic_wo_chain_sdnode();
-
- TreePatternNode *IIDNode = new TreePatternNode(new IntInit(IID), 1);
+
+ TreePatternNode *IIDNode = new TreePatternNode(IntInit::get(IID), 1);
Children.insert(Children.begin(), IIDNode);
}
-
+
unsigned NumResults = GetNumNodeResults(Operator, CDP);
TreePatternNode *Result = new TreePatternNode(Operator, Children, NumResults);
Result->setName(OpName);
-
+
if (!Dag->getName().empty()) {
assert(Result->getName().empty());
Result->setName(Dag->getName());
@@ -1698,10 +1926,10 @@
}
// If there are constraints on our named nodes, apply them.
- for (StringMap<SmallVector<TreePatternNode*,1> >::iterator
+ for (StringMap<SmallVector<TreePatternNode*,1> >::iterator
I = NamedNodes.begin(), E = NamedNodes.end(); I != E; ++I) {
SmallVectorImpl<TreePatternNode*> &Nodes = I->second;
-
+
// If we have input named node types, propagate their types to the named
// values here.
if (InNamedTypes) {
@@ -1721,10 +1949,11 @@
// def : Pat<(v1i64 (bitconvert(v2i32 DPR:$src))), (v1i64 DPR:$src)>;
if (Nodes[i] == Trees[0] && Nodes[i]->isLeaf()) {
DefInit *DI = dynamic_cast<DefInit*>(Nodes[i]->getLeafValue());
- if (DI && DI->getDef()->isSubClassOf("RegisterClass"))
+ if (DI && (DI->getDef()->isSubClassOf("RegisterClass") ||
+ DI->getDef()->isSubClassOf("RegisterOperand")))
continue;
}
-
+
assert(Nodes[i]->getNumTypes() == 1 &&
InNodes[0]->getNumTypes() == 1 &&
"FIXME: cannot name multiple result nodes yet");
@@ -1732,7 +1961,7 @@
*this);
}
}
-
+
// If there are multiple nodes with the same name, they must all have the
// same type.
if (I->second.size() > 1) {
@@ -1740,14 +1969,14 @@
TreePatternNode *N1 = Nodes[i], *N2 = Nodes[i+1];
assert(N1->getNumTypes() == 1 && N2->getNumTypes() == 1 &&
"FIXME: cannot name multiple result nodes yet");
-
+
MadeChange |= N1->UpdateNodeType(0, N2->getExtType(0), *this);
MadeChange |= N2->UpdateNodeType(0, N1->getExtType(0), *this);
}
}
}
}
-
+
bool HasUnresolvedTypes = false;
for (unsigned i = 0, e = Trees.size(); i != e; ++i)
HasUnresolvedTypes |= Trees[i]->ContainsUnresolvedType();
@@ -1763,7 +1992,7 @@
OS << ")";
}
OS << ": ";
-
+
if (Trees.size() > 1)
OS << "[\n";
for (unsigned i = 0, e = Trees.size(); i != e; ++i) {
@@ -1782,7 +2011,9 @@
// CodeGenDAGPatterns implementation
//
-CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : Records(R) {
+CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) :
+ Records(R), Target(R) {
+
Intrinsics = LoadIntrinsics(Records, false);
TgtIntrinsics = LoadIntrinsics(Records, true);
ParseNodeInfo();
@@ -1792,7 +2023,7 @@
ParseDefaultOperands();
ParseInstructions();
ParsePatterns();
-
+
// Generate variants. For example, commutative patterns can match
// multiple ways. Add them to PatternsToMatch as well.
GenerateVariants();
@@ -1863,20 +2094,20 @@
///
void CodeGenDAGPatterns::ParsePatternFragments() {
std::vector<Record*> Fragments = Records.getAllDerivedDefinitions("PatFrag");
-
+
// First step, parse all of the fragments.
for (unsigned i = 0, e = Fragments.size(); i != e; ++i) {
DagInit *Tree = Fragments[i]->getValueAsDag("Fragment");
TreePattern *P = new TreePattern(Fragments[i], Tree, true, *this);
PatternFragments[Fragments[i]] = P;
-
+
// Validate the argument list, converting it to set, to discard duplicates.
std::vector<std::string> &Args = P->getArgList();
std::set<std::string> OperandsSet(Args.begin(), Args.end());
-
+
if (OperandsSet.count(""))
P->error("Cannot have unnamed 'node' values in pattern fragment!");
-
+
// Parse the operands list.
DagInit *OpsList = Fragments[i]->getValueAsDag("Operands");
DefInit *OpsOp = dynamic_cast<DefInit*>(OpsList->getOperator());
@@ -1887,8 +2118,8 @@
OpsOp->getDef()->getName() != "outs" &&
OpsOp->getDef()->getName() != "ins"))
P->error("Operands list should start with '(ops ... '!");
-
- // Copy over the arguments.
+
+ // Copy over the arguments.
Args.clear();
for (unsigned j = 0, e = OpsList->getNumArgs(); j != e; ++j) {
if (!dynamic_cast<DefInit*>(OpsList->getArg(j)) ||
@@ -1903,30 +2134,30 @@
OperandsSet.erase(OpsList->getArgName(j));
Args.push_back(OpsList->getArgName(j));
}
-
+
if (!OperandsSet.empty())
P->error("Operands list does not contain an entry for operand '" +
*OperandsSet.begin() + "'!");
// If there is a code init for this fragment, keep track of the fact that
// this fragment uses it.
- std::string Code = Fragments[i]->getValueAsCode("Predicate");
- if (!Code.empty())
- P->getOnlyTree()->addPredicateFn("Predicate_"+Fragments[i]->getName());
-
+ TreePredicateFn PredFn(P);
+ if (!PredFn.isAlwaysTrue())
+ P->getOnlyTree()->addPredicateFn(PredFn);
+
// If there is a node transformation corresponding to this, keep track of
// it.
Record *Transform = Fragments[i]->getValueAsDef("OperandTransform");
if (!getSDNodeTransform(Transform).second.empty()) // not noop xform?
P->getOnlyTree()->setTransformFn(Transform);
}
-
+
// 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) {
TreePattern *ThePat = PatternFragments[Fragments[i]];
ThePat->InlinePatternFragments();
-
+
// Infer as many types as possible. Don't worry about it if we don't infer
// all of them, some may depend on the inputs of the pattern.
try {
@@ -1937,7 +2168,7 @@
// actually used by instructions, the type consistency error will be
// reported there.
}
-
+
// If debugging, print out the pattern fragment result.
DEBUG(ThePat->dump());
}
@@ -1950,33 +2181,33 @@
// Find some SDNode.
assert(!SDNodes.empty() && "No SDNodes parsed?");
- Init *SomeSDNode = new DefInit(SDNodes.begin()->first);
-
+ Init *SomeSDNode = DefInit::get(SDNodes.begin()->first);
+
for (unsigned iter = 0; iter != 2; ++iter) {
for (unsigned i = 0, e = DefaultOps[iter].size(); i != e; ++i) {
DagInit *DefaultInfo = DefaultOps[iter][i]->getValueAsDag("DefaultOps");
-
+
// Clone the DefaultInfo dag node, changing the operator from 'ops' to
// SomeSDnode so that we can parse this.
std::vector<std::pair<Init*, std::string> > Ops;
for (unsigned op = 0, e = DefaultInfo->getNumArgs(); op != e; ++op)
Ops.push_back(std::make_pair(DefaultInfo->getArg(op),
DefaultInfo->getArgName(op)));
- DagInit *DI = new DagInit(SomeSDNode, "", Ops);
-
+ DagInit *DI = DagInit::get(SomeSDNode, "", Ops);
+
// Create a TreePattern to parse this.
TreePattern P(DefaultOps[iter][i], DI, false, *this);
assert(P.getNumTrees() == 1 && "This ctor can only produce one tree!");
// Copy the operands over into a DAGDefaultOperand.
DAGDefaultOperand DefaultOpInfo;
-
+
TreePatternNode *T = P.getTree(0);
for (unsigned op = 0, e = T->getNumChildren(); op != e; ++op) {
TreePatternNode *TPN = T->getChild(op);
while (TPN->ApplyTypeConstraints(P, false))
/* Resolve all types */;
-
+
if (TPN->ContainsUnresolvedType()) {
if (iter == 0)
throw "Value #" + utostr(i) + " of PredicateOperand '" +
@@ -2002,7 +2233,8 @@
if (Pat->getName().empty()) {
if (Pat->isLeaf()) {
DefInit *DI = dynamic_cast<DefInit*>(Pat->getLeafValue());
- if (DI && DI->getDef()->isSubClassOf("RegisterClass"))
+ if (DI && (DI->getDef()->isSubClassOf("RegisterClass") ||
+ DI->getDef()->isSubClassOf("RegisterOperand")))
I->error("Input " + DI->getDef()->getName() + " must be named!");
}
return false;
@@ -2033,7 +2265,7 @@
assert(Slot->getNumChildren() == 0 && "can't be a use with children!");
SlotRec = Slot->getOperator();
}
-
+
// Ensure that the inputs agree if we've already seen this input.
if (Rec != SlotRec)
I->error("All $" + Pat->getName() + " inputs must agree with each other");
@@ -2056,13 +2288,13 @@
I->error("Cannot specify a transform function for a non-input value!");
return;
}
-
+
if (Pat->getOperator()->getName() == "implicit") {
for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) {
TreePatternNode *Dest = Pat->getChild(i);
if (!Dest->isLeaf())
I->error("implicitly defined value should be a register!");
-
+
DefInit *Val = dynamic_cast<DefInit*>(Dest->getLeafValue());
if (!Val || !Val->getDef()->isSubClassOf("Register"))
I->error("implicitly defined value should be a register!");
@@ -2070,7 +2302,7 @@
}
return;
}
-
+
if (Pat->getOperator()->getName() != "set") {
// If this is not a set, verify that the children nodes are not void typed,
// and recurse.
@@ -2080,35 +2312,36 @@
FindPatternInputsAndOutputs(I, Pat->getChild(i), InstInputs, InstResults,
InstImpResults);
}
-
+
// If this is a non-leaf node with no children, treat it basically as if
// it were a leaf. This handles nodes like (imm).
bool isUse = HandleUse(I, Pat, InstInputs);
-
+
if (!isUse && Pat->getTransformFn())
I->error("Cannot specify a transform function for a non-input value!");
return;
}
-
+
// Otherwise, this is a set, validate and collect instruction results.
if (Pat->getNumChildren() == 0)
I->error("set requires operands!");
-
+
if (Pat->getTransformFn())
I->error("Cannot specify a transform function on a set node!");
-
+
// Check the set destinations.
unsigned NumDests = Pat->getNumChildren()-1;
for (unsigned i = 0; i != NumDests; ++i) {
TreePatternNode *Dest = Pat->getChild(i);
if (!Dest->isLeaf())
I->error("set destination should be a register!");
-
+
DefInit *Val = dynamic_cast<DefInit*>(Dest->getLeafValue());
if (!Val)
I->error("set destination should be a register!");
if (Val->getDef()->isSubClassOf("RegisterClass") ||
+ Val->getDef()->isSubClassOf("RegisterOperand") ||
Val->getDef()->isSubClassOf("PointerLikeRegClass")) {
if (Dest->getName().empty())
I->error("set destination must have a name!");
@@ -2121,7 +2354,7 @@
I->error("set destination should be a register!");
}
}
-
+
// Verify and collect info from the computation.
FindPatternInputsAndOutputs(I, Pat->getChild(NumDests),
InstInputs, InstResults, InstImpResults);
@@ -2135,13 +2368,14 @@
const CodeGenDAGPatterns &CDP;
bool &mayStore;
bool &mayLoad;
+ bool &IsBitcast;
bool &HasSideEffects;
bool &IsVariadic;
public:
InstAnalyzer(const CodeGenDAGPatterns &cdp,
- bool &maystore, bool &mayload, bool &hse, bool &isv)
- : CDP(cdp), mayStore(maystore), mayLoad(mayload), HasSideEffects(hse),
- IsVariadic(isv) {
+ bool &maystore, bool &mayload, bool &isbc, bool &hse, bool &isv)
+ : CDP(cdp), mayStore(maystore), mayLoad(mayload), IsBitcast(isbc),
+ HasSideEffects(hse), IsVariadic(isv) {
}
/// Analyze - Analyze the specified instruction, returning true if the
@@ -2160,6 +2394,29 @@
}
private:
+ bool IsNodeBitcast(const TreePatternNode *N) const {
+ if (HasSideEffects || mayLoad || mayStore || IsVariadic)
+ return false;
+
+ if (N->getNumChildren() != 2)
+ return false;
+
+ const TreePatternNode *N0 = N->getChild(0);
+ if (!N0->isLeaf() || !dynamic_cast<DefInit*>(N0->getLeafValue()))
+ return false;
+
+ const TreePatternNode *N1 = N->getChild(1);
+ if (N1->isLeaf())
+ return false;
+ if (N1->getNumChildren() != 1 || !N1->getChild(0)->isLeaf())
+ return false;
+
+ const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N1->getOperator());
+ if (OpInfo.getNumResults() != 1 || OpInfo.getNumOperands() != 1)
+ return false;
+ return OpInfo.getEnumName() == "ISD::BITCAST";
+ }
+
void AnalyzeNode(const TreePatternNode *N) {
if (N->isLeaf()) {
if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) {
@@ -2180,8 +2437,10 @@
AnalyzeNode(N->getChild(i));
// Ignore set nodes, which are not SDNodes.
- if (N->getOperator()->getName() == "set")
+ if (N->getOperator()->getName() == "set") {
+ IsBitcast = IsNodeBitcast(N);
return;
+ }
// Get information about the SDNode for the operator.
const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N->getOperator());
@@ -2210,12 +2469,13 @@
static void InferFromPattern(const CodeGenInstruction &Inst,
bool &MayStore, bool &MayLoad,
+ bool &IsBitcast,
bool &HasSideEffects, bool &IsVariadic,
const CodeGenDAGPatterns &CDP) {
- MayStore = MayLoad = HasSideEffects = IsVariadic = false;
+ MayStore = MayLoad = IsBitcast = HasSideEffects = IsVariadic = false;
bool HadPattern =
- InstAnalyzer(CDP, MayStore, MayLoad, HasSideEffects, IsVariadic)
+ InstAnalyzer(CDP, MayStore, MayLoad, IsBitcast, HasSideEffects, IsVariadic)
.Analyze(Inst.TheDef);
// InstAnalyzer only correctly analyzes mayStore/mayLoad so far.
@@ -2254,8 +2514,8 @@
"which already inferred this.\n", Inst.TheDef->getName().c_str());
HasSideEffects = true;
}
-
- if (Inst.isVariadic)
+
+ if (Inst.Operands.isVariadic)
IsVariadic = true; // Can warn if we want.
}
@@ -2264,64 +2524,64 @@
/// resolved instructions.
void CodeGenDAGPatterns::ParseInstructions() {
std::vector<Record*> Instrs = Records.getAllDerivedDefinitions("Instruction");
-
+
for (unsigned i = 0, e = Instrs.size(); i != e; ++i) {
ListInit *LI = 0;
-
+
if (dynamic_cast<ListInit*>(Instrs[i]->getValueInit("Pattern")))
LI = Instrs[i]->getValueAsListInit("Pattern");
-
+
// If there is no pattern, only collect minimal information about the
// instruction for its operand list. We have to assume that there is one
// result, as we have no detailed info.
if (!LI || LI->getSize() == 0) {
std::vector<Record*> Results;
std::vector<Record*> Operands;
-
+
CodeGenInstruction &InstInfo = Target.getInstruction(Instrs[i]);
- if (InstInfo.OperandList.size() != 0) {
- if (InstInfo.NumDefs == 0) {
+ if (InstInfo.Operands.size() != 0) {
+ if (InstInfo.Operands.NumDefs == 0) {
// These produce no results
- for (unsigned j = 0, e = InstInfo.OperandList.size(); j < e; ++j)
- Operands.push_back(InstInfo.OperandList[j].Rec);
+ for (unsigned j = 0, e = InstInfo.Operands.size(); j < e; ++j)
+ Operands.push_back(InstInfo.Operands[j].Rec);
} else {
// Assume the first operand is the result.
- Results.push_back(InstInfo.OperandList[0].Rec);
-
+ Results.push_back(InstInfo.Operands[0].Rec);
+
// The rest are inputs.
- for (unsigned j = 1, e = InstInfo.OperandList.size(); j < e; ++j)
- Operands.push_back(InstInfo.OperandList[j].Rec);
+ for (unsigned j = 1, e = InstInfo.Operands.size(); j < e; ++j)
+ Operands.push_back(InstInfo.Operands[j].Rec);
}
}
-
+
// Create and insert the instruction.
std::vector<Record*> ImpResults;
- Instructions.insert(std::make_pair(Instrs[i],
+ Instructions.insert(std::make_pair(Instrs[i],
DAGInstruction(0, Results, Operands, ImpResults)));
continue; // no pattern.
}
-
+
// Parse the instruction.
TreePattern *I = new TreePattern(Instrs[i], LI, true, *this);
// Inline pattern fragments into it.
I->InlinePatternFragments();
-
+
// Infer as many types as possible. If we cannot infer all of them, we can
// never do anything with this instruction pattern: report it to the user.
if (!I->InferAllTypes())
I->error("Could not infer all types in pattern!");
-
- // InstInputs - Keep track of all of the inputs of the instruction, along
+
+ // InstInputs - Keep track of all of the inputs of the instruction, along
// with the record they are declared as.
std::map<std::string, TreePatternNode*> InstInputs;
-
+
// InstResults - Keep track of all the virtual registers that are 'set'
// in the instruction, including what reg class they are.
std::map<std::string, TreePatternNode*> InstResults;
std::vector<Record*> InstImpResults;
-
+
// Verify that the top-level forms in the instruction are of void type, and
// fill in the InstResults map.
for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) {
@@ -2348,29 +2608,29 @@
std::vector<Record*> Results;
TreePatternNode *Res0Node = 0;
for (unsigned i = 0; i != NumResults; ++i) {
- if (i == CGI.OperandList.size())
+ if (i == CGI.Operands.size())
I->error("'" + InstResults.begin()->first +
"' set but does not appear in operand list!");
- const std::string &OpName = CGI.OperandList[i].Name;
-
+ const std::string &OpName = CGI.Operands[i].Name;
+
// Check that it exists in InstResults.
TreePatternNode *RNode = InstResults[OpName];
if (RNode == 0)
I->error("Operand $" + OpName + " does not exist in operand list!");
-
+
if (i == 0)
Res0Node = RNode;
Record *R = dynamic_cast<DefInit*>(RNode->getLeafValue())->getDef();
if (R == 0)
I->error("Operand $" + OpName + " should be a set destination: all "
"outputs must occur before inputs in operand list!");
-
- if (CGI.OperandList[i].Rec != R)
+
+ if (CGI.Operands[i].Rec != R)
I->error("Operand $" + OpName + " class mismatch!");
-
+
// Remember the return type.
- Results.push_back(CGI.OperandList[i].Rec);
-
+ Results.push_back(CGI.Operands[i].Rec);
+
// Okay, this one checks out.
InstResults.erase(OpName);
}
@@ -2381,8 +2641,8 @@
std::vector<TreePatternNode*> ResultNodeOperands;
std::vector<Record*> Operands;
- for (unsigned i = NumResults, e = CGI.OperandList.size(); i != e; ++i) {
- CodeGenInstruction::OperandInfo &Op = CGI.OperandList[i];
+ for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) {
+ CGIOperandList::OperandInfo &Op = CGI.Operands[i];
const std::string &OpName = Op.Name;
if (OpName.empty())
I->error("Operand #" + utostr(i) + " in operands list has no name!");
@@ -2403,7 +2663,7 @@
}
TreePatternNode *InVal = InstInputsCheck[OpName];
InstInputsCheck.erase(OpName); // It occurred, remove from map.
-
+
if (InVal->isLeaf() &&
dynamic_cast<DefInit*>(InVal->getLeafValue())) {
Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef();
@@ -2412,13 +2672,13 @@
" between the operand and pattern");
}
Operands.push_back(Op.Rec);
-
+
// Construct the result for the dest-pattern operand list.
TreePatternNode *OpNode = InVal->clone();
-
+
// No predicate is useful on the result.
OpNode->clearPredicateFns();
-
+
// Promote the xform function to be an explicit node if set.
if (Record *Xform = OpNode->getTransformFn()) {
OpNode->setTransformFn(0);
@@ -2426,10 +2686,10 @@
Children.push_back(OpNode);
OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes());
}
-
+
ResultNodeOperands.push_back(OpNode);
}
-
+
if (!InstInputsCheck.empty())
I->error("Input operand $" + InstInputsCheck.begin()->first +
" occurs in pattern but not in operands list!");
@@ -2454,10 +2714,10 @@
DAGInstruction &TheInsertedInst = Instructions.find(I->getRecord())->second;
TheInsertedInst.setResultPattern(Temp.getOnlyTree());
-
+
DEBUG(I->dump());
}
-
+
// If we can, convert the instructions to be patterns that are matched!
for (std::map<Record*, DAGInstruction, RecordPtrCmp>::iterator II =
Instructions.begin(),
@@ -2476,10 +2736,11 @@
// Not a set (store or something?)
SrcPattern = Pattern;
}
-
+
Record *Instr = II->first;
AddPatternToMatch(I,
- PatternToMatch(Instr->getValueAsListInit("Predicates"),
+ PatternToMatch(Instr,
+ Instr->getValueAsListInit("Predicates"),
SrcPattern,
TheInst.getResultPattern(),
TheInst.getImpResults(),
@@ -2491,7 +2752,7 @@
typedef std::pair<const TreePatternNode*, unsigned> NameRecord;
-static void FindNames(const TreePatternNode *P,
+static void FindNames(const TreePatternNode *P,
std::map<std::string, NameRecord> &Names,
const TreePattern *PatternTop) {
if (!P->getName().empty()) {
@@ -2503,7 +2764,7 @@
PatternTop->error("repetition of value: $" + P->getName() +
" where different uses have different types!");
}
-
+
if (!P->isLeaf()) {
for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i)
FindNames(P->getChild(i), Names, PatternTop);
@@ -2516,7 +2777,7 @@
std::string Reason;
if (!PTM.getSrcPattern()->canPatternMatch(Reason, *this))
Pattern->error("Pattern can never match: " + Reason);
-
+
// If the source pattern's root is a complex pattern, that complex pattern
// must specify the nodes it can potentially match.
if (const ComplexPattern *CP =
@@ -2524,8 +2785,8 @@
if (CP->getRootNodes().empty())
Pattern->error("ComplexPattern at root must specify list of opcodes it"
" could match");
-
-
+
+
// Find all of the named values in the input and output, ensure they have the
// same type.
std::map<std::string, NameRecord> SrcNames, DstNames;
@@ -2540,14 +2801,14 @@
Pattern->error("Pattern has input without matching name in output: $" +
I->first);
}
-
+
// Scan all of the named values in the source pattern, rejecting them if the
// 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)
Pattern->error("Pattern has dead named input: $" + I->first);
-
+
PatternsToMatch.push_back(PTM);
}
@@ -2560,13 +2821,20 @@
CodeGenInstruction &InstInfo =
const_cast<CodeGenInstruction &>(*Instructions[i]);
// Determine properties of the instruction from its pattern.
- bool MayStore, MayLoad, HasSideEffects, IsVariadic;
- InferFromPattern(InstInfo, MayStore, MayLoad, HasSideEffects, IsVariadic,
- *this);
+ bool MayStore, MayLoad, IsBitcast, HasSideEffects, IsVariadic;
+ InferFromPattern(InstInfo, MayStore, MayLoad, IsBitcast,
+ HasSideEffects, IsVariadic, *this);
InstInfo.mayStore = MayStore;
InstInfo.mayLoad = MayLoad;
+ InstInfo.isBitcast = IsBitcast;
InstInfo.hasSideEffects = HasSideEffects;
- InstInfo.isVariadic = IsVariadic;
+ InstInfo.Operands.isVariadic = IsVariadic;
+
+ // Sanity checks.
+ if (InstInfo.isReMaterializable && InstInfo.hasSideEffects)
+ throw TGError(InstInfo.TheDef->getLoc(), "The instruction " +
+ InstInfo.TheDef->getName() +
+ " is rematerializable AND has unmodeled side effects?");
}
}
@@ -2576,7 +2844,7 @@
static bool ForceArbitraryInstResultType(TreePatternNode *N, TreePattern &TP) {
if (N->isLeaf())
return false;
-
+
// Analyze children.
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
if (ForceArbitraryInstResultType(N->getChild(i), TP))
@@ -2590,12 +2858,12 @@
for (unsigned i = 0, e = N->getNumTypes(); i != e; ++i) {
if (N->getExtType(i).isCompletelyUnknown() || N->getExtType(i).isConcrete())
continue;
-
+
// Otherwise, force its type to the first possibility (an arbitrary choice).
if (N->getExtType(i).MergeInTypeInfo(N->getExtType(i).getTypeList()[0], TP))
return true;
}
-
+
return false;
}
@@ -2609,20 +2877,20 @@
// Inline pattern fragments into it.
Pattern->InlinePatternFragments();
-
+
ListInit *LI = CurPattern->getValueAsListInit("ResultInstrs");
if (LI->getSize() == 0) continue; // no pattern.
-
+
// Parse the instruction.
TreePattern *Result = new TreePattern(CurPattern, LI, false, *this);
-
+
// Inline pattern fragments into it.
Result->InlinePatternFragments();
if (Result->getNumTrees() != 1)
Result->error("Cannot handle instructions producing instructions "
"with temporaries yet!");
-
+
bool IterateInference;
bool InferredAllPatternTypes, InferredAllResultTypes;
do {
@@ -2630,14 +2898,14 @@
// can never do anything with this pattern: report it to the user.
InferredAllPatternTypes =
Pattern->InferAllTypes(&Pattern->getNamedNodesMap());
-
+
// Infer as many types as possible. If we cannot infer all of them, we
// can never do anything with this pattern: report it to the user.
InferredAllResultTypes =
Result->InferAllTypes(&Pattern->getNamedNodesMap());
IterateInference = false;
-
+
// Apply the type of the result to the source pattern. This helps us
// resolve cases where the input type is known to be a pointer type (which
// is considered resolved), but the result knows it needs to be 32- or
@@ -2650,7 +2918,7 @@
IterateInference |= Result->getTree(0)->
UpdateNodeType(i, Pattern->getTree(0)->getExtType(i), *Result);
}
-
+
// If our iteration has converged and the input pattern's types are fully
// resolved but the result pattern is not fully resolved, we may have a
// situation where we have two instructions in the result pattern and
@@ -2665,7 +2933,7 @@
IterateInference = ForceArbitraryInstResultType(Result->getTree(0),
*Result);
} while (IterateInference);
-
+
// Verify that we inferred enough types that we can do something with the
// pattern and result. If these fire the user has to add type casts.
if (!InferredAllPatternTypes)
@@ -2674,7 +2942,7 @@
Pattern->dump();
Result->error("Could not infer all types in pattern result!");
}
-
+
// Validate that the input pattern is correct.
std::map<std::string, TreePatternNode*> InstInputs;
std::map<std::string, TreePatternNode*> InstResults;
@@ -2702,16 +2970,17 @@
DstPattern = new TreePatternNode(DstPattern->getOperator(),
ResultNodeOperands,
DstPattern->getNumTypes());
-
+
for (unsigned i = 0, e = Result->getOnlyTree()->getNumTypes(); i != e; ++i)
DstPattern->setType(i, Result->getOnlyTree()->getExtType(i));
-
+
TreePattern Temp(Result->getRecord(), DstPattern, false, *this);
Temp.InferAllTypes();
-
+
AddPatternToMatch(Pattern,
- PatternToMatch(CurPattern->getValueAsListInit("Predicates"),
+ PatternToMatch(CurPattern,
+ CurPattern->getValueAsListInit("Predicates"),
Pattern->getTree(0),
Temp.getOnlyTree(), InstImpResults,
CurPattern->getValueAsInt("AddedComplexity"),
@@ -2721,7 +2990,7 @@
/// CombineChildVariants - Given a bunch of permutations of each child of the
/// 'operator' node, put them together in all possible ways.
-static void CombineChildVariants(TreePatternNode *Orig,
+static void CombineChildVariants(TreePatternNode *Orig,
const std::vector<std::vector<TreePatternNode*> > &ChildVariants,
std::vector<TreePatternNode*> &OutVariants,
CodeGenDAGPatterns &CDP,
@@ -2730,7 +2999,7 @@
for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i)
if (ChildVariants[i].empty())
return;
-
+
// The end result is an all-pairs construction of the resultant pattern.
std::vector<unsigned> Idxs;
Idxs.resize(ChildVariants.size());
@@ -2751,21 +3020,21 @@
NewChildren.push_back(ChildVariants[i][Idxs[i]]);
TreePatternNode *R = new TreePatternNode(Orig->getOperator(), NewChildren,
Orig->getNumTypes());
-
+
// Copy over properties.
R->setName(Orig->getName());
R->setPredicateFns(Orig->getPredicateFns());
R->setTransformFn(Orig->getTransformFn());
for (unsigned i = 0, e = Orig->getNumTypes(); i != e; ++i)
R->setType(i, Orig->getExtType(i));
-
+
// If this pattern cannot match, do not include it as a variant.
std::string ErrString;
if (!R->canPatternMatch(ErrString, CDP)) {
delete R;
} else {
bool AlreadyExists = false;
-
+
// Scan to see if this pattern has already been emitted. We can get
// duplication due to things like commuting:
// (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a)
@@ -2775,13 +3044,13 @@
AlreadyExists = true;
break;
}
-
+
if (AlreadyExists)
delete R;
else
OutVariants.push_back(R);
}
-
+
// Increment indices to the next permutation by incrementing the
// indicies from last index backward, e.g., generate the sequence
// [0, 0], [0, 1], [1, 0], [1, 1].
@@ -2798,7 +3067,7 @@
/// CombineChildVariants - A helper function for binary operators.
///
-static void CombineChildVariants(TreePatternNode *Orig,
+static void CombineChildVariants(TreePatternNode *Orig,
const std::vector<TreePatternNode*> &LHS,
const std::vector<TreePatternNode*> &RHS,
std::vector<TreePatternNode*> &OutVariants,
@@ -2808,14 +3077,14 @@
ChildVariants.push_back(LHS);
ChildVariants.push_back(RHS);
CombineChildVariants(Orig, ChildVariants, OutVariants, CDP, DepVars);
-}
+}
static void GatherChildrenOfAssociativeOpcode(TreePatternNode *N,
std::vector<TreePatternNode *> &Children) {
assert(N->getNumChildren()==2 &&"Associative but doesn't have 2 children!");
Record *Operator = N->getOperator();
-
+
// Only permit raw nodes.
if (!N->getName().empty() || !N->getPredicateFns().empty() ||
N->getTransformFn()) {
@@ -2852,7 +3121,7 @@
// If this node is associative, re-associate.
if (NodeInfo.hasProperty(SDNPAssociative)) {
- // Re-associate by pulling together all of the linked operators
+ // Re-associate by pulling together all of the linked operators
std::vector<TreePatternNode*> MaximalChildren;
GatherChildrenOfAssociativeOpcode(N, MaximalChildren);
@@ -2864,11 +3133,11 @@
GenerateVariantsOf(MaximalChildren[0], AVariants, CDP, DepVars);
GenerateVariantsOf(MaximalChildren[1], BVariants, CDP, DepVars);
GenerateVariantsOf(MaximalChildren[2], CVariants, CDP, DepVars);
-
+
// There are only two ways we can permute the tree:
// (A op B) op C and A op (B op C)
// Within these forms, we can also permute A/B/C.
-
+
// Generate legal pair permutations of A/B/C.
std::vector<TreePatternNode*> ABVariants;
std::vector<TreePatternNode*> BAVariants;
@@ -2901,7 +3170,7 @@
return;
}
}
-
+
// Compute permutations of all children.
std::vector<std::vector<TreePatternNode*> > ChildVariants;
ChildVariants.resize(N->getNumChildren());
@@ -2953,7 +3222,7 @@
// match multiple ways. Add them to PatternsToMatch as well.
void CodeGenDAGPatterns::GenerateVariants() {
DEBUG(errs() << "Generating instruction variants.\n");
-
+
// Loop over all of the patterns we've collected, checking to see if we can
// generate variants of the instruction, through the exploitation of
// identities. This permits the target to provide aggressive matching without
@@ -2970,7 +3239,8 @@
DEBUG(errs() << "Dependent/multiply used variables: ");
DEBUG(DumpDepVars(DepVars));
DEBUG(errs() << "\n");
- GenerateVariantsOf(PatternsToMatch[i].getSrcPattern(), Variants, *this, DepVars);
+ GenerateVariantsOf(PatternsToMatch[i].getSrcPattern(), Variants, *this,
+ DepVars);
assert(!Variants.empty() && "Must create at least original variant!");
Variants.erase(Variants.begin()); // Remove the original pattern.
@@ -2988,7 +3258,7 @@
DEBUG(errs() << " VAR#" << v << ": ";
Variant->dump();
errs() << "\n");
-
+
// Scan to see if an instruction or explicit pattern already matches this.
bool AlreadyExists = false;
for (unsigned p = 0, e = PatternsToMatch.size(); p != e; ++p) {
@@ -2997,7 +3267,8 @@
PatternsToMatch[p].getPredicates())
continue;
// Check to see if this variant already exists.
- if (Variant->isIsomorphicTo(PatternsToMatch[p].getSrcPattern(), DepVars)) {
+ if (Variant->isIsomorphicTo(PatternsToMatch[p].getSrcPattern(),
+ DepVars)) {
DEBUG(errs() << " *** ALREADY EXISTS, ignoring variant.\n");
AlreadyExists = true;
break;
@@ -3008,7 +3279,8 @@
// Otherwise, add it to the list of patterns we have.
PatternsToMatch.
- push_back(PatternToMatch(PatternsToMatch[i].getPredicates(),
+ push_back(PatternToMatch(PatternsToMatch[i].getSrcRecord(),
+ PatternsToMatch[i].getPredicates(),
Variant, PatternsToMatch[i].getDstPattern(),
PatternsToMatch[i].getDstRegs(),
PatternsToMatch[i].getAddedComplexity(),
diff --git a/src/LLVM/utils/TableGen/CodeGenDAGPatterns.h b/src/LLVM/utils/TableGen/CodeGenDAGPatterns.h
index 0a1362a..936fd01 100644
--- a/src/LLVM/utils/TableGen/CodeGenDAGPatterns.h
+++ b/src/LLVM/utils/TableGen/CodeGenDAGPatterns.h
@@ -26,7 +26,7 @@
namespace llvm {
class Record;
- struct Init;
+ class Init;
class ListInit;
class DagInit;
class SDNodeInfo;
@@ -58,50 +58,50 @@
public:
TypeSet() {}
TypeSet(MVT::SimpleValueType VT, TreePattern &TP);
- TypeSet(const std::vector<MVT::SimpleValueType> &VTList);
-
+ TypeSet(const std::vector<MVT::SimpleValueType> &VTList);
+
bool isCompletelyUnknown() const { return TypeVec.empty(); }
-
+
bool isConcrete() const {
if (TypeVec.size() != 1) return false;
unsigned char T = TypeVec[0]; (void)T;
assert(T < MVT::LAST_VALUETYPE || T == MVT::iPTR || T == MVT::iPTRAny);
return true;
}
-
+
MVT::SimpleValueType getConcrete() const {
assert(isConcrete() && "Type isn't concrete yet");
return (MVT::SimpleValueType)TypeVec[0];
}
-
+
bool isDynamicallyResolved() const {
return getConcrete() == MVT::iPTR || getConcrete() == MVT::iPTRAny;
}
-
+
const SmallVectorImpl<MVT::SimpleValueType> &getTypeList() const {
assert(!TypeVec.empty() && "Not a type list!");
return TypeVec;
}
-
+
bool isVoid() const {
return TypeVec.size() == 1 && TypeVec[0] == MVT::isVoid;
}
-
+
/// hasIntegerTypes - Return true if this TypeSet contains any integer value
/// types.
bool hasIntegerTypes() const;
-
+
/// hasFloatingPointTypes - Return true if this TypeSet contains an fAny or
/// a floating point value type.
bool hasFloatingPointTypes() const;
-
+
/// hasVectorTypes - Return true if this TypeSet contains a vector value
/// type.
bool hasVectorTypes() const;
-
+
/// getName() - Return this TypeSet as a string.
std::string getName() const;
-
+
/// MergeInTypeInfo - This merges in type information from the specified
/// argument. If 'this' changes, it returns true. If the two types are
/// contradictory (e.g. merge f32 into i32) then this throws an exception.
@@ -126,14 +126,18 @@
/// EnforceSmallerThan - 'this' must be a smaller VT than Other. Update
/// this an other based on this information.
bool EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP);
-
+
/// EnforceVectorEltTypeIs - 'this' is now constrainted to be a vector type
/// whose element is VT.
bool EnforceVectorEltTypeIs(EEVT::TypeSet &VT, TreePattern &TP);
-
+
+ /// EnforceVectorSubVectorTypeIs - 'this' is now constrainted to
+ /// be a vector type VT.
+ bool EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VT, TreePattern &TP);
+
bool operator!=(const TypeSet &RHS) const { return TypeVec != RHS.TypeVec; }
bool operator==(const TypeSet &RHS) const { return TypeVec == RHS.TypeVec; }
-
+
private:
/// FillWithPossibleTypes - Set to all legal types and return true, only
/// valid on completely unknown type sets. If Pred is non-null, only MVTs
@@ -151,13 +155,14 @@
/// corresponding to the SDTypeConstraint tablegen class in Target.td.
struct SDTypeConstraint {
SDTypeConstraint(Record *R);
-
+
unsigned OperandNo; // The operand # this constraint applies to.
- enum {
- SDTCisVT, SDTCisPtrTy, SDTCisInt, SDTCisFP, SDTCisVec, SDTCisSameAs,
- SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp, SDTCisEltOfVec
+ enum {
+ SDTCisVT, SDTCisPtrTy, SDTCisInt, SDTCisFP, SDTCisVec, SDTCisSameAs,
+ SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp, SDTCisEltOfVec,
+ SDTCisSubVecOfVec
} ConstraintType;
-
+
union { // The discriminated union.
struct {
MVT::SimpleValueType VT;
@@ -174,6 +179,9 @@
struct {
unsigned OtherOperandNum;
} SDTCisEltOfVec_Info;
+ struct {
+ unsigned OtherOperandNum;
+ } SDTCisSubVecOfVec_Info;
} x;
/// ApplyTypeConstraint - Given a node in a pattern, apply this type
@@ -197,25 +205,25 @@
std::vector<SDTypeConstraint> TypeConstraints;
public:
SDNodeInfo(Record *R); // Parse the specified record.
-
+
unsigned getNumResults() const { return NumResults; }
-
+
/// getNumOperands - This is the number of operands required or -1 if
/// variadic.
int getNumOperands() const { return NumOperands; }
Record *getRecord() const { return Def; }
const std::string &getEnumName() const { return EnumName; }
const std::string &getSDClassName() const { return SDClassName; }
-
+
const std::vector<SDTypeConstraint> &getTypeConstraints() const {
return TypeConstraints;
}
-
+
/// getKnownType - If the type constraints on this node imply a fixed type
/// (e.g. all stores return void, etc), then return it as an
/// MVT::SimpleValueType. Otherwise, return MVT::Other.
MVT::SimpleValueType getKnownType(unsigned ResNo) const;
-
+
/// hasProperty - Return true if this node has the specified property.
///
bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); }
@@ -231,6 +239,57 @@
return MadeChange;
}
};
+
+/// TreePredicateFn - This is an abstraction that represents the predicates on
+/// a PatFrag node. This is a simple one-word wrapper around a pointer to
+/// provide nice accessors.
+class TreePredicateFn {
+ /// PatFragRec - This is the TreePattern for the PatFrag that we
+ /// originally came from.
+ TreePattern *PatFragRec;
+public:
+ /// TreePredicateFn constructor. Here 'N' is a subclass of PatFrag.
+ TreePredicateFn(TreePattern *N);
+
+
+ TreePattern *getOrigPatFragRecord() const { return PatFragRec; }
+
+ /// isAlwaysTrue - Return true if this is a noop predicate.
+ bool isAlwaysTrue() const;
+
+ bool isImmediatePattern() const { return !getImmCode().empty(); }
+
+ /// getImmediatePredicateCode - Return the code that evaluates this pattern if
+ /// this is an immediate predicate. It is an error to call this on a
+ /// non-immediate pattern.
+ std::string getImmediatePredicateCode() const {
+ std::string Result = getImmCode();
+ assert(!Result.empty() && "Isn't an immediate pattern!");
+ return Result;
+ }
+
+
+ bool operator==(const TreePredicateFn &RHS) const {
+ return PatFragRec == RHS.PatFragRec;
+ }
+
+ bool operator!=(const TreePredicateFn &RHS) const { return !(*this == RHS); }
+
+ /// Return the name to use in the generated code to reference this, this is
+ /// "Predicate_foo" if from a pattern fragment "foo".
+ std::string getFnName() const;
+
+ /// getCodeToRunOnSDNode - Return the code for the function body that
+ /// evaluates this predicate. The argument is expected to be in "Node",
+ /// not N. This handles casting and conversion to a concrete node type as
+ /// appropriate.
+ std::string getCodeToRunOnSDNode() const;
+
+private:
+ std::string getPredCode() const;
+ std::string getImmCode() const;
+};
+
/// FIXME: TreePatternNode's can be shared in some cases (due to dag-shaped
/// patterns), and as such should be ref counted. We currently just leak all
@@ -240,31 +299,31 @@
/// result may be a set of possible types. After (successful) type inference,
/// each is a single concrete type.
SmallVector<EEVT::TypeSet, 1> Types;
-
+
/// Operator - The Record for the operator if this is an interior node (not
/// a leaf).
Record *Operator;
-
+
/// Val - The init value (e.g. the "GPRC" record, or "7") for a leaf.
///
Init *Val;
-
+
/// Name - The name given to this node with the :$foo notation.
///
std::string Name;
-
+
/// PredicateFns - The predicate functions to execute on this node to check
/// for a match. If this list is empty, no predicate is involved.
- std::vector<std::string> PredicateFns;
-
+ std::vector<TreePredicateFn> PredicateFns;
+
/// TransformFn - The transformation function to execute on this node before
/// it can be substituted into the resulting instruction on a pattern match.
Record *TransformFn;
-
+
std::vector<TreePatternNode*> Children;
public:
TreePatternNode(Record *Op, const std::vector<TreePatternNode*> &Ch,
- unsigned NumResults)
+ unsigned NumResults)
: Operator(Op), Val(0), TransformFn(0), Children(Ch) {
Types.resize(NumResults);
}
@@ -273,12 +332,12 @@
Types.resize(NumResults);
}
~TreePatternNode();
-
+
const std::string &getName() const { return Name; }
void setName(StringRef N) { Name.assign(N.begin(), N.end()); }
-
+
bool isLeaf() const { return Val != 0; }
-
+
// Type accessors.
unsigned getNumTypes() const { return Types.size(); }
MVT::SimpleValueType getType(unsigned ResNo) const {
@@ -288,7 +347,7 @@
const EEVT::TypeSet &getExtType(unsigned ResNo) const { return Types[ResNo]; }
EEVT::TypeSet &getExtType(unsigned ResNo) { return Types[ResNo]; }
void setType(unsigned ResNo, const EEVT::TypeSet &T) { Types[ResNo] = T; }
-
+
bool hasTypeSet(unsigned ResNo) const {
return Types[ResNo].isConcrete();
}
@@ -298,16 +357,16 @@
bool isTypeDynamicallyResolved(unsigned ResNo) const {
return Types[ResNo].isDynamicallyResolved();
}
-
+
Init *getLeafValue() const { assert(isLeaf()); return Val; }
Record *getOperator() const { assert(!isLeaf()); return Operator; }
-
+
unsigned getNumChildren() const { return Children.size(); }
TreePatternNode *getChild(unsigned N) const { return Children[N]; }
void setChild(unsigned i, TreePatternNode *N) {
Children[i] = N;
}
-
+
/// hasChild - Return true if N is any of our children.
bool hasChild(const TreePatternNode *N) const {
for (unsigned i = 0, e = Children.size(); i != e; ++i)
@@ -315,14 +374,18 @@
return false;
}
- const std::vector<std::string> &getPredicateFns() const {return PredicateFns;}
+ bool hasAnyPredicate() const { return !PredicateFns.empty(); }
+
+ const std::vector<TreePredicateFn> &getPredicateFns() const {
+ return PredicateFns;
+ }
void clearPredicateFns() { PredicateFns.clear(); }
- void setPredicateFns(const std::vector<std::string> &Fns) {
+ void setPredicateFns(const std::vector<TreePredicateFn> &Fns) {
assert(PredicateFns.empty() && "Overwriting non-empty predicate list!");
PredicateFns = Fns;
}
- void addPredicateFn(const std::string &Fn) {
- assert(!Fn.empty() && "Empty predicate string!");
+ void addPredicateFn(const TreePredicateFn &Fn) {
+ assert(!Fn.isAlwaysTrue() && "Empty predicate string!");
if (std::find(PredicateFns.begin(), PredicateFns.end(), Fn) ==
PredicateFns.end())
PredicateFns.push_back(Fn);
@@ -330,7 +393,7 @@
Record *getTransformFn() const { return TransformFn; }
void setTransformFn(Record *Fn) { TransformFn = Fn; }
-
+
/// getIntrinsicInfo - If this node corresponds to an intrinsic, return the
/// CodeGenIntrinsic information for it, otherwise return a null pointer.
const CodeGenIntrinsic *getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const;
@@ -342,18 +405,18 @@
/// NodeHasProperty - Return true if this node has the specified property.
bool NodeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const;
-
+
/// TreeHasProperty - Return true if any node in this tree has the specified
/// property.
bool TreeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const;
-
+
/// isCommutativeIntrinsic - Return true if the node is an intrinsic which is
/// marked isCommutative.
bool isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const;
-
+
void print(raw_ostream &OS) const;
void dump() const;
-
+
public: // Higher level manipulation routines.
/// clone - Return a new copy of this tree.
@@ -362,14 +425,14 @@
/// RemoveAllTypes - Recursively strip all the types of this tree.
void RemoveAllTypes();
-
+
/// isIsomorphicTo - Return true if this node is recursively isomorphic to
/// the specified node. For this comparison, all of the state of the node
/// is considered, except for the assigned name. Nodes with differing names
/// that are otherwise identical are considered isomorphic.
bool isIsomorphicTo(const TreePatternNode *N,
const MultipleUseVarSet &DepVars) const;
-
+
/// SubstituteFormalArguments - Replace the formal arguments in this tree
/// with actual values specified by ArgMap.
void SubstituteFormalArguments(std::map<std::string,
@@ -379,13 +442,13 @@
/// fragments, inline them into place, giving us a pattern without any
/// PatFrag references.
TreePatternNode *InlinePatternFragments(TreePattern &TP);
-
+
/// ApplyTypeConstraints - Apply all of the type constraints relevant to
/// this node and its children in the tree. This returns true if it makes a
/// change, false otherwise. If a type contradiction is found, throw an
/// exception.
bool ApplyTypeConstraints(TreePattern &TP, bool NotRegisters);
-
+
/// UpdateNodeType - Set the node type of N to VT if VT contains
/// information. If N already contains a conflicting type, then throw an
/// exception. This returns true if any information was updated.
@@ -399,18 +462,18 @@
TreePattern &TP) {
return Types[ResNo].MergeInTypeInfo(EEVT::TypeSet(InTy, TP), TP);
}
-
+
/// ContainsUnresolvedType - Return true if this tree contains any
/// unresolved types.
bool ContainsUnresolvedType() const {
for (unsigned i = 0, e = Types.size(); i != e; ++i)
if (!Types[i].isConcrete()) return true;
-
+
for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
if (getChild(i)->ContainsUnresolvedType()) return true;
return false;
}
-
+
/// canPatternMatch - If it is impossible for this pattern to match on this
/// target, fill in Reason and return false. Otherwise, return true.
bool canPatternMatch(std::string &Reason, const CodeGenDAGPatterns &CDP);
@@ -420,7 +483,7 @@
TPN.print(OS);
return OS;
}
-
+
/// TreePattern - Represent a pattern, used for instructions, pattern
/// fragments, etc.
@@ -430,19 +493,19 @@
/// Note that PatFrag's only have a single tree.
///
std::vector<TreePatternNode*> Trees;
-
+
/// NamedNodes - This is all of the nodes that have names in the trees in this
/// pattern.
StringMap<SmallVector<TreePatternNode*,1> > NamedNodes;
-
+
/// TheRecord - The actual TableGen record corresponding to this pattern.
///
Record *TheRecord;
-
+
/// Args - This is a list of all of the arguments to this pattern (for
/// PatFrag patterns), which are the 'node' markers in this pattern.
std::vector<std::string> Args;
-
+
/// CDP - the top-level object coordinating this madness.
///
CodeGenDAGPatterns &CDP;
@@ -451,7 +514,7 @@
/// False if this is an output pattern, something to emit.
bool isInputPattern;
public:
-
+
/// TreePattern constructor - Parse the specified DagInits into the
/// current record.
TreePattern(Record *TheRec, ListInit *RawPat, bool isInput,
@@ -460,7 +523,7 @@
CodeGenDAGPatterns &ise);
TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput,
CodeGenDAGPatterns &ise);
-
+
/// getTrees - Return the tree patterns which corresponds to this pattern.
///
const std::vector<TreePatternNode*> &getTrees() const { return Trees; }
@@ -470,25 +533,25 @@
assert(Trees.size() == 1 && "Doesn't have exactly one pattern!");
return Trees[0];
}
-
+
const StringMap<SmallVector<TreePatternNode*,1> > &getNamedNodesMap() {
if (NamedNodes.empty())
ComputeNamedNodes();
return NamedNodes;
}
-
+
/// getRecord - Return the actual TableGen record corresponding to this
/// pattern.
///
Record *getRecord() const { return TheRecord; }
-
+
unsigned getNumArgs() const { return Args.size(); }
const std::string &getArgName(unsigned i) const {
assert(i < Args.size() && "Argument reference out of range!");
return Args[i];
}
std::vector<std::string> &getArgList() { return Args; }
-
+
CodeGenDAGPatterns &getDAGPatterns() const { return CDP; }
/// InlinePatternFragments - If this pattern refers to any pattern
@@ -498,20 +561,20 @@
for (unsigned i = 0, e = Trees.size(); i != e; ++i)
Trees[i] = Trees[i]->InlinePatternFragments(*this);
}
-
+
/// InferAllTypes - Infer/propagate as many types throughout the expression
/// patterns as possible. Return true if all types are inferred, false
/// otherwise. Throw an exception if a type contradiction is found.
bool InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> >
*NamedTypes=0);
-
+
/// error - Throw an exception, prefixing it with information about this
/// pattern.
void error(const std::string &Msg) const;
-
+
void print(raw_ostream &OS) const;
void dump() const;
-
+
private:
TreePatternNode *ParseTreePattern(Init *DI, StringRef OpName);
void ComputeNamedNodes();
@@ -535,7 +598,7 @@
const std::vector<Record*> &results,
const std::vector<Record*> &operands,
const std::vector<Record*> &impresults)
- : Pattern(TP), Results(results), Operands(operands),
+ : Pattern(TP), Results(results), Operands(operands),
ImpResults(impresults), ResultPattern(0) {}
const TreePattern *getPattern() const { return Pattern; }
@@ -543,14 +606,14 @@
unsigned getNumOperands() const { return Operands.size(); }
unsigned getNumImpResults() const { return ImpResults.size(); }
const std::vector<Record*>& getImpResults() const { return ImpResults; }
-
+
void setResultPattern(TreePatternNode *R) { ResultPattern = R; }
-
+
Record *getResult(unsigned RN) const {
assert(RN < Results.size());
return Results[RN];
}
-
+
Record *getOperand(unsigned ON) const {
assert(ON < Operands.size());
return Operands[ON];
@@ -560,21 +623,22 @@
assert(RN < ImpResults.size());
return ImpResults[RN];
}
-
+
TreePatternNode *getResultPattern() const { return ResultPattern; }
};
-
+
/// PatternToMatch - Used by CodeGenDAGPatterns to keep tab of patterns
/// processed to produce isel.
class PatternToMatch {
public:
- PatternToMatch(ListInit *preds,
+ PatternToMatch(Record *srcrecord, ListInit *preds,
TreePatternNode *src, TreePatternNode *dst,
const std::vector<Record*> &dstregs,
unsigned complexity, unsigned uid)
- : Predicates(preds), SrcPattern(src), DstPattern(dst),
+ : SrcRecord(srcrecord), Predicates(preds), SrcPattern(src), DstPattern(dst),
Dstregs(dstregs), AddedComplexity(complexity), ID(uid) {}
+ Record *SrcRecord; // Originating Record for the pattern.
ListInit *Predicates; // Top level predicate conditions to match.
TreePatternNode *SrcPattern; // Source pattern to match.
TreePatternNode *DstPattern; // Resulting pattern.
@@ -582,6 +646,7 @@
unsigned AddedComplexity; // Add to matching pattern complexity.
unsigned ID; // Unique ID for the record.
+ Record *getSrcRecord() const { return SrcRecord; }
ListInit *getPredicates() const { return Predicates; }
TreePatternNode *getSrcPattern() const { return SrcPattern; }
TreePatternNode *getDstPattern() const { return DstPattern; }
@@ -589,7 +654,7 @@
unsigned getAddedComplexity() const { return AddedComplexity; }
std::string getPredicateCheck() const;
-
+
/// Compute the complexity metric for the input pattern. This roughly
/// corresponds to the number of nodes that are covered.
unsigned getPatternComplexity(const CodeGenDAGPatterns &CGP) const;
@@ -599,60 +664,60 @@
struct RecordPtrCmp {
bool operator()(const Record *LHS, const Record *RHS) const;
};
-
+
class CodeGenDAGPatterns {
RecordKeeper &Records;
CodeGenTarget Target;
std::vector<CodeGenIntrinsic> Intrinsics;
std::vector<CodeGenIntrinsic> TgtIntrinsics;
-
+
std::map<Record*, SDNodeInfo, RecordPtrCmp> SDNodes;
std::map<Record*, std::pair<Record*, std::string>, RecordPtrCmp> SDNodeXForms;
std::map<Record*, ComplexPattern, RecordPtrCmp> ComplexPatterns;
std::map<Record*, TreePattern*, RecordPtrCmp> PatternFragments;
std::map<Record*, DAGDefaultOperand, RecordPtrCmp> DefaultOperands;
std::map<Record*, DAGInstruction, RecordPtrCmp> Instructions;
-
+
// Specific SDNode definitions:
Record *intrinsic_void_sdnode;
Record *intrinsic_w_chain_sdnode, *intrinsic_wo_chain_sdnode;
-
+
/// PatternsToMatch - All of the things we are matching on the DAG. The first
/// value is the pattern to match, the second pattern is the result to
/// emit.
std::vector<PatternToMatch> PatternsToMatch;
public:
- CodeGenDAGPatterns(RecordKeeper &R);
+ CodeGenDAGPatterns(RecordKeeper &R);
~CodeGenDAGPatterns();
-
+
CodeGenTarget &getTargetInfo() { return Target; }
const CodeGenTarget &getTargetInfo() const { return Target; }
-
+
Record *getSDNodeNamed(const std::string &Name) const;
-
+
const SDNodeInfo &getSDNodeInfo(Record *R) const {
assert(SDNodes.count(R) && "Unknown node!");
return SDNodes.find(R)->second;
}
-
+
// Node transformation lookups.
typedef std::pair<Record*, std::string> NodeXForm;
const NodeXForm &getSDNodeTransform(Record *R) const {
assert(SDNodeXForms.count(R) && "Invalid transform!");
return SDNodeXForms.find(R)->second;
}
-
+
typedef std::map<Record*, NodeXForm, RecordPtrCmp>::const_iterator
nx_iterator;
nx_iterator nx_begin() const { return SDNodeXForms.begin(); }
nx_iterator nx_end() const { return SDNodeXForms.end(); }
-
+
const ComplexPattern &getComplexPattern(Record *R) const {
assert(ComplexPatterns.count(R) && "Unknown addressing mode!");
return ComplexPatterns.find(R)->second;
}
-
+
const CodeGenIntrinsic &getIntrinsic(Record *R) const {
for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i)
if (Intrinsics[i].TheDef == R) return Intrinsics[i];
@@ -661,7 +726,7 @@
assert(0 && "Unknown intrinsic!");
abort();
}
-
+
const CodeGenIntrinsic &getIntrinsicInfo(unsigned IID) const {
if (IID-1 < Intrinsics.size())
return Intrinsics[IID-1];
@@ -670,7 +735,7 @@
assert(0 && "Bad intrinsic ID!");
abort();
}
-
+
unsigned getIntrinsicID(Record *R) const {
for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i)
if (Intrinsics[i].TheDef == R) return i;
@@ -679,12 +744,12 @@
assert(0 && "Unknown intrinsic!");
abort();
}
-
+
const DAGDefaultOperand &getDefaultOperand(Record *R) const {
assert(DefaultOperands.count(R) &&"Isn't an analyzed default operand!");
return DefaultOperands.find(R)->second;
}
-
+
// Pattern Fragment information.
TreePattern *getPatternFragment(Record *R) const {
assert(PatternFragments.count(R) && "Invalid pattern fragment request!");
@@ -694,7 +759,7 @@
if (!PatternFragments.count(R)) return 0;
return PatternFragments.find(R)->second;
}
-
+
typedef std::map<Record*, TreePattern*, RecordPtrCmp>::const_iterator
pf_iterator;
pf_iterator pf_begin() const { return PatternFragments.begin(); }
@@ -704,14 +769,14 @@
typedef std::vector<PatternToMatch>::const_iterator ptm_iterator;
ptm_iterator ptm_begin() const { return PatternsToMatch.begin(); }
ptm_iterator ptm_end() const { return PatternsToMatch.end(); }
-
-
-
+
+
+
const DAGInstruction &getInstruction(Record *R) const {
assert(Instructions.count(R) && "Unknown instruction!");
return Instructions.find(R)->second;
}
-
+
Record *get_intrinsic_void_sdnode() const {
return intrinsic_void_sdnode;
}
@@ -721,7 +786,7 @@
Record *get_intrinsic_wo_chain_sdnode() const {
return intrinsic_wo_chain_sdnode;
}
-
+
bool hasTargetIntrinsics() { return !TgtIntrinsics.empty(); }
private:
@@ -734,7 +799,7 @@
void ParsePatterns();
void InferInstructionFlags();
void GenerateVariants();
-
+
void AddPatternToMatch(const TreePattern *Pattern, const PatternToMatch &PTM);
void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
std::map<std::string,
diff --git a/src/LLVM/utils/TableGen/CodeGenInstruction.cpp b/src/LLVM/utils/TableGen/CodeGenInstruction.cpp
index 01a1fe1..53d499f 100644
--- a/src/LLVM/utils/TableGen/CodeGenInstruction.cpp
+++ b/src/LLVM/utils/TableGen/CodeGenInstruction.cpp
@@ -13,122 +13,22 @@
#include "CodeGenInstruction.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/STLExtras.h"
#include <set>
using namespace llvm;
-static void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) {
- // EARLY_CLOBBER: @early $reg
- std::string::size_type wpos = CStr.find_first_of(" \t");
- std::string::size_type start = CStr.find_first_not_of(" \t");
- std::string Tok = CStr.substr(start, wpos - start);
- if (Tok == "@earlyclobber") {
- std::string Name = CStr.substr(wpos+1);
- wpos = Name.find_first_not_of(" \t");
- if (wpos == std::string::npos)
- throw "Illegal format for @earlyclobber constraint: '" + CStr + "'";
- Name = Name.substr(wpos);
- std::pair<unsigned,unsigned> Op =
- I->ParseOperandName(Name, false);
+//===----------------------------------------------------------------------===//
+// CGIOperandList Implementation
+//===----------------------------------------------------------------------===//
- // Build the string for the operand
- if (!I->OperandList[Op.first].Constraints[Op.second].isNone())
- throw "Operand '" + Name + "' cannot have multiple constraints!";
- I->OperandList[Op.first].Constraints[Op.second] =
- CodeGenInstruction::ConstraintInfo::getEarlyClobber();
- return;
- }
-
- // Only other constraint is "TIED_TO" for now.
- std::string::size_type pos = CStr.find_first_of('=');
- assert(pos != std::string::npos && "Unrecognized constraint");
- start = CStr.find_first_not_of(" \t");
- std::string Name = CStr.substr(start, pos - start);
-
- // TIED_TO: $src1 = $dst
- wpos = Name.find_first_of(" \t");
- if (wpos == std::string::npos)
- throw "Illegal format for tied-to constraint: '" + CStr + "'";
- std::string DestOpName = Name.substr(0, wpos);
- std::pair<unsigned,unsigned> DestOp = I->ParseOperandName(DestOpName, false);
-
- Name = CStr.substr(pos+1);
- wpos = Name.find_first_not_of(" \t");
- if (wpos == std::string::npos)
- throw "Illegal format for tied-to constraint: '" + CStr + "'";
-
- std::pair<unsigned,unsigned> SrcOp =
- I->ParseOperandName(Name.substr(wpos), false);
- if (SrcOp > DestOp)
- throw "Illegal tied-to operand constraint '" + CStr + "'";
-
-
- unsigned FlatOpNo = I->getFlattenedOperandNumber(SrcOp);
-
- if (!I->OperandList[DestOp.first].Constraints[DestOp.second].isNone())
- throw "Operand '" + DestOpName + "' cannot have multiple constraints!";
- I->OperandList[DestOp.first].Constraints[DestOp.second] =
- CodeGenInstruction::ConstraintInfo::getTied(FlatOpNo);
-}
-
-static void ParseConstraints(const std::string &CStr, CodeGenInstruction *I) {
- // Make sure the constraints list for each operand is large enough to hold
- // constraint info, even if none is present.
- for (unsigned i = 0, e = I->OperandList.size(); i != e; ++i)
- I->OperandList[i].Constraints.resize(I->OperandList[i].MINumOperands);
-
- if (CStr.empty()) return;
-
- const std::string delims(",");
- std::string::size_type bidx, eidx;
-
- bidx = CStr.find_first_not_of(delims);
- while (bidx != std::string::npos) {
- eidx = CStr.find_first_of(delims, bidx);
- if (eidx == std::string::npos)
- eidx = CStr.length();
-
- ParseConstraint(CStr.substr(bidx, eidx - bidx), I);
- bidx = CStr.find_first_not_of(delims, eidx);
- }
-}
-
-CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
- : TheDef(R), AsmString(AsmStr) {
- Namespace = R->getValueAsString("Namespace");
-
- isReturn = R->getValueAsBit("isReturn");
- isBranch = R->getValueAsBit("isBranch");
- isIndirectBranch = R->getValueAsBit("isIndirectBranch");
- isCompare = R->getValueAsBit("isCompare");
- isBarrier = R->getValueAsBit("isBarrier");
- isCall = R->getValueAsBit("isCall");
- canFoldAsLoad = R->getValueAsBit("canFoldAsLoad");
- mayLoad = R->getValueAsBit("mayLoad");
- mayStore = R->getValueAsBit("mayStore");
- isPredicable = R->getValueAsBit("isPredicable");
- isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress");
- isCommutable = R->getValueAsBit("isCommutable");
- isTerminator = R->getValueAsBit("isTerminator");
- isReMaterializable = R->getValueAsBit("isReMaterializable");
- hasDelaySlot = R->getValueAsBit("hasDelaySlot");
- usesCustomInserter = R->getValueAsBit("usesCustomInserter");
- hasCtrlDep = R->getValueAsBit("hasCtrlDep");
- isNotDuplicable = R->getValueAsBit("isNotDuplicable");
- hasSideEffects = R->getValueAsBit("hasSideEffects");
- neverHasSideEffects = R->getValueAsBit("neverHasSideEffects");
- isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove");
- hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq");
- hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq");
+CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
+ isPredicable = false;
hasOptionalDef = false;
isVariadic = false;
- ImplicitDefs = R->getValueAsListOfDefs("Defs");
- ImplicitUses = R->getValueAsListOfDefs("Uses");
-
- if (neverHasSideEffects + hasSideEffects > 1)
- throw R->getName() + ": multiple conflicting side-effect flags set!";
DagInit *OutDI = R->getValueAsDag("OutOperandList");
@@ -137,16 +37,16 @@
throw R->getName() + ": invalid def name for output list: use 'outs'";
} else
throw R->getName() + ": invalid output list: use 'outs'";
-
+
NumDefs = OutDI->getNumArgs();
-
+
DagInit *InDI = R->getValueAsDag("InOperandList");
if (DefInit *Init = dynamic_cast<DefInit*>(InDI->getOperator())) {
if (Init->getDef()->getName() != "ins")
throw R->getName() + ": invalid def name for input list: use 'ins'";
} else
throw R->getName() + ": invalid input list: use 'ins'";
-
+
unsigned MIOperandNo = 0;
std::set<std::string> OperandNames;
for (unsigned i = 0, e = InDI->getNumArgs()+OutDI->getNumArgs(); i != e; ++i){
@@ -159,25 +59,32 @@
ArgInit = InDI->getArg(i-NumDefs);
ArgName = InDI->getArgName(i-NumDefs);
}
-
+
DefInit *Arg = dynamic_cast<DefInit*>(ArgInit);
if (!Arg)
throw "Illegal operand for the '" + R->getName() + "' instruction!";
Record *Rec = Arg->getDef();
std::string PrintMethod = "printOperand";
+ std::string EncoderMethod;
+ std::string OperandType = "OPERAND_UNKNOWN";
unsigned NumOps = 1;
DagInit *MIOpInfo = 0;
- if (Rec->isSubClassOf("Operand")) {
+ if (Rec->isSubClassOf("RegisterOperand")) {
PrintMethod = Rec->getValueAsString("PrintMethod");
+ } else if (Rec->isSubClassOf("Operand")) {
+ PrintMethod = Rec->getValueAsString("PrintMethod");
+ OperandType = Rec->getValueAsString("OperandType");
+ // If there is an explicit encoder method, use it.
+ EncoderMethod = Rec->getValueAsString("EncoderMethod");
MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
// Verify that MIOpInfo has an 'ops' root value.
if (!dynamic_cast<DefInit*>(MIOpInfo->getOperator()) ||
dynamic_cast<DefInit*>(MIOpInfo->getOperator())
- ->getDef()->getName() != "ops")
+ ->getDef()->getName() != "ops")
throw "Bad value for MIOperandInfo in operand '" + Rec->getName() +
- "'\n";
+ "'\n";
// If we have MIOpInfo, then we have #operands equal to number of entries
// in MIOperandInfo.
@@ -191,59 +98,61 @@
} else if (Rec->getName() == "variable_ops") {
isVariadic = true;
continue;
- } else if (!Rec->isSubClassOf("RegisterClass") &&
- Rec->getName() != "ptr_rc" && Rec->getName() != "unknown")
+ } else if (Rec->isSubClassOf("RegisterClass")) {
+ OperandType = "OPERAND_REGISTER";
+ } else if (!Rec->isSubClassOf("PointerLikeRegClass") &&
+ Rec->getName() != "unknown")
throw "Unknown operand class '" + Rec->getName() +
- "' in '" + R->getName() + "' instruction!";
+ "' in '" + R->getName() + "' instruction!";
// Check that the operand has a name and that it's unique.
if (ArgName.empty())
throw "In instruction '" + R->getName() + "', operand #" + utostr(i) +
- " has no name!";
+ " has no name!";
if (!OperandNames.insert(ArgName).second)
throw "In instruction '" + R->getName() + "', operand #" + utostr(i) +
- " has the same name as a previous operand!";
+ " has the same name as a previous operand!";
- OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod,
- MIOperandNo, NumOps, MIOpInfo));
+ OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, EncoderMethod,
+ OperandType, MIOperandNo, NumOps,
+ MIOpInfo));
MIOperandNo += NumOps;
}
- // Parse Constraints.
- ParseConstraints(R->getValueAsString("Constraints"), this);
- // Parse the DisableEncoding field.
- std::string DisableEncoding = R->getValueAsString("DisableEncoding");
- while (1) {
- std::string OpName;
- tie(OpName, DisableEncoding) = getToken(DisableEncoding, " ,\t");
- if (OpName.empty()) break;
-
- // Figure out which operand this is.
- std::pair<unsigned,unsigned> Op = ParseOperandName(OpName, false);
-
- // Mark the operand as not-to-be encoded.
- if (Op.second >= OperandList[Op.first].DoNotEncode.size())
- OperandList[Op.first].DoNotEncode.resize(Op.second+1);
- OperandList[Op.first].DoNotEncode[Op.second] = true;
- }
+ // Make sure the constraints list for each operand is large enough to hold
+ // constraint info, even if none is present.
+ for (unsigned i = 0, e = OperandList.size(); i != e; ++i)
+ OperandList[i].Constraints.resize(OperandList[i].MINumOperands);
}
+
/// getOperandNamed - Return the index of the operand with the specified
/// non-empty name. If the instruction does not have an operand with the
/// specified name, throw an exception.
///
-unsigned CodeGenInstruction::getOperandNamed(const std::string &Name) const {
+unsigned CGIOperandList::getOperandNamed(StringRef Name) const {
+ unsigned OpIdx;
+ if (hasOperandNamed(Name, OpIdx)) return OpIdx;
+ throw "'" + TheDef->getName() + "' does not have an operand named '$" +
+ Name.str() + "'!";
+}
+
+/// hasOperandNamed - Query whether the instruction has an operand of the
+/// given name. If so, return true and set OpIdx to the index of the
+/// operand. Otherwise, return false.
+bool CGIOperandList::hasOperandNamed(StringRef Name, unsigned &OpIdx) const {
assert(!Name.empty() && "Cannot search for operand with no name!");
for (unsigned i = 0, e = OperandList.size(); i != e; ++i)
- if (OperandList[i].Name == Name) return i;
- throw "Instruction '" + TheDef->getName() +
- "' does not have an operand named '$" + Name + "'!";
+ if (OperandList[i].Name == Name) {
+ OpIdx = i;
+ return true;
+ }
+ return false;
}
std::pair<unsigned,unsigned>
-CodeGenInstruction::ParseOperandName(const std::string &Op,
- bool AllowWholeOp) {
+CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
if (Op.empty() || Op[0] != '$')
throw TheDef->getName() + ": Illegal operand name: '" + Op + "'";
@@ -266,7 +175,7 @@
if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp &&
SubOpName.empty())
throw TheDef->getName() + ": Illegal to refer to"
- " whole operand part of complex operand '" + Op + "'";
+ " whole operand part of complex operand '" + Op + "'";
// Otherwise, return the operand.
return std::make_pair(OpIdx, 0U);
@@ -286,6 +195,142 @@
throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'";
}
+static void ParseConstraint(const std::string &CStr, CGIOperandList &Ops) {
+ // EARLY_CLOBBER: @early $reg
+ std::string::size_type wpos = CStr.find_first_of(" \t");
+ std::string::size_type start = CStr.find_first_not_of(" \t");
+ std::string Tok = CStr.substr(start, wpos - start);
+ if (Tok == "@earlyclobber") {
+ std::string Name = CStr.substr(wpos+1);
+ wpos = Name.find_first_not_of(" \t");
+ if (wpos == std::string::npos)
+ throw "Illegal format for @earlyclobber constraint: '" + CStr + "'";
+ Name = Name.substr(wpos);
+ std::pair<unsigned,unsigned> Op = Ops.ParseOperandName(Name, false);
+
+ // Build the string for the operand
+ if (!Ops[Op.first].Constraints[Op.second].isNone())
+ throw "Operand '" + Name + "' cannot have multiple constraints!";
+ Ops[Op.first].Constraints[Op.second] =
+ CGIOperandList::ConstraintInfo::getEarlyClobber();
+ return;
+ }
+
+ // Only other constraint is "TIED_TO" for now.
+ std::string::size_type pos = CStr.find_first_of('=');
+ assert(pos != std::string::npos && "Unrecognized constraint");
+ start = CStr.find_first_not_of(" \t");
+ std::string Name = CStr.substr(start, pos - start);
+
+ // TIED_TO: $src1 = $dst
+ wpos = Name.find_first_of(" \t");
+ if (wpos == std::string::npos)
+ throw "Illegal format for tied-to constraint: '" + CStr + "'";
+ std::string DestOpName = Name.substr(0, wpos);
+ std::pair<unsigned,unsigned> DestOp = Ops.ParseOperandName(DestOpName, false);
+
+ Name = CStr.substr(pos+1);
+ wpos = Name.find_first_not_of(" \t");
+ if (wpos == std::string::npos)
+ throw "Illegal format for tied-to constraint: '" + CStr + "'";
+
+ std::pair<unsigned,unsigned> SrcOp =
+ Ops.ParseOperandName(Name.substr(wpos), false);
+ if (SrcOp > DestOp)
+ throw "Illegal tied-to operand constraint '" + CStr + "'";
+
+
+ unsigned FlatOpNo = Ops.getFlattenedOperandNumber(SrcOp);
+
+ if (!Ops[DestOp.first].Constraints[DestOp.second].isNone())
+ throw "Operand '" + DestOpName + "' cannot have multiple constraints!";
+ Ops[DestOp.first].Constraints[DestOp.second] =
+ CGIOperandList::ConstraintInfo::getTied(FlatOpNo);
+}
+
+static void ParseConstraints(const std::string &CStr, CGIOperandList &Ops) {
+ if (CStr.empty()) return;
+
+ const std::string delims(",");
+ std::string::size_type bidx, eidx;
+
+ bidx = CStr.find_first_not_of(delims);
+ while (bidx != std::string::npos) {
+ eidx = CStr.find_first_of(delims, bidx);
+ if (eidx == std::string::npos)
+ eidx = CStr.length();
+
+ ParseConstraint(CStr.substr(bidx, eidx - bidx), Ops);
+ bidx = CStr.find_first_not_of(delims, eidx);
+ }
+}
+
+void CGIOperandList::ProcessDisableEncoding(std::string DisableEncoding) {
+ while (1) {
+ std::pair<StringRef, StringRef> P = getToken(DisableEncoding, " ,\t");
+ std::string OpName = P.first;
+ DisableEncoding = P.second;
+ if (OpName.empty()) break;
+
+ // Figure out which operand this is.
+ std::pair<unsigned,unsigned> Op = ParseOperandName(OpName, false);
+
+ // Mark the operand as not-to-be encoded.
+ if (Op.second >= OperandList[Op.first].DoNotEncode.size())
+ OperandList[Op.first].DoNotEncode.resize(Op.second+1);
+ OperandList[Op.first].DoNotEncode[Op.second] = true;
+ }
+
+}
+
+//===----------------------------------------------------------------------===//
+// CodeGenInstruction Implementation
+//===----------------------------------------------------------------------===//
+
+CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R), Operands(R) {
+ Namespace = R->getValueAsString("Namespace");
+ AsmString = R->getValueAsString("AsmString");
+
+ isReturn = R->getValueAsBit("isReturn");
+ isBranch = R->getValueAsBit("isBranch");
+ isIndirectBranch = R->getValueAsBit("isIndirectBranch");
+ isCompare = R->getValueAsBit("isCompare");
+ isMoveImm = R->getValueAsBit("isMoveImm");
+ isBitcast = R->getValueAsBit("isBitcast");
+ isBarrier = R->getValueAsBit("isBarrier");
+ isCall = R->getValueAsBit("isCall");
+ canFoldAsLoad = R->getValueAsBit("canFoldAsLoad");
+ mayLoad = R->getValueAsBit("mayLoad");
+ mayStore = R->getValueAsBit("mayStore");
+ isPredicable = Operands.isPredicable || R->getValueAsBit("isPredicable");
+ isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress");
+ isCommutable = R->getValueAsBit("isCommutable");
+ isTerminator = R->getValueAsBit("isTerminator");
+ isReMaterializable = R->getValueAsBit("isReMaterializable");
+ hasDelaySlot = R->getValueAsBit("hasDelaySlot");
+ usesCustomInserter = R->getValueAsBit("usesCustomInserter");
+ hasPostISelHook = R->getValueAsBit("hasPostISelHook");
+ hasCtrlDep = R->getValueAsBit("hasCtrlDep");
+ isNotDuplicable = R->getValueAsBit("isNotDuplicable");
+ hasSideEffects = R->getValueAsBit("hasSideEffects");
+ neverHasSideEffects = R->getValueAsBit("neverHasSideEffects");
+ isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove");
+ hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq");
+ hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq");
+ isCodeGenOnly = R->getValueAsBit("isCodeGenOnly");
+ isPseudo = R->getValueAsBit("isPseudo");
+ ImplicitDefs = R->getValueAsListOfDefs("Defs");
+ ImplicitUses = R->getValueAsListOfDefs("Uses");
+
+ if (neverHasSideEffects + hasSideEffects > 1)
+ throw R->getName() + ": multiple conflicting side-effect flags set!";
+
+ // Parse Constraints.
+ ParseConstraints(R->getValueAsString("Constraints"), Operands);
+
+ // Parse the DisableEncoding field.
+ Operands.ProcessDisableEncoding(R->getValueAsString("DisableEncoding"));
+}
/// HasOneImplicitDefWithKnownVT - If the instruction has at least one
/// implicit def and it has a known VT, return the VT, otherwise return
@@ -293,14 +338,223 @@
MVT::SimpleValueType CodeGenInstruction::
HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const {
if (ImplicitDefs.empty()) return MVT::Other;
-
+
// Check to see if the first implicit def has a resolvable type.
Record *FirstImplicitDef = ImplicitDefs[0];
assert(FirstImplicitDef->isSubClassOf("Register"));
- const std::vector<MVT::SimpleValueType> &RegVTs =
+ const std::vector<MVT::SimpleValueType> &RegVTs =
TargetInfo.getRegisterVTs(FirstImplicitDef);
if (RegVTs.size() == 1)
return RegVTs[0];
return MVT::Other;
}
+
+/// FlattenAsmStringVariants - Flatten the specified AsmString to only
+/// include text from the specified variant, returning the new string.
+std::string CodeGenInstruction::
+FlattenAsmStringVariants(StringRef Cur, unsigned Variant) {
+ std::string Res = "";
+
+ for (;;) {
+ // Find the start of the next variant string.
+ size_t VariantsStart = 0;
+ for (size_t e = Cur.size(); VariantsStart != e; ++VariantsStart)
+ if (Cur[VariantsStart] == '{' &&
+ (VariantsStart == 0 || (Cur[VariantsStart-1] != '$' &&
+ Cur[VariantsStart-1] != '\\')))
+ break;
+
+ // Add the prefix to the result.
+ Res += Cur.slice(0, VariantsStart);
+ if (VariantsStart == Cur.size())
+ break;
+
+ ++VariantsStart; // Skip the '{'.
+
+ // Scan to the end of the variants string.
+ size_t VariantsEnd = VariantsStart;
+ unsigned NestedBraces = 1;
+ for (size_t e = Cur.size(); VariantsEnd != e; ++VariantsEnd) {
+ if (Cur[VariantsEnd] == '}' && Cur[VariantsEnd-1] != '\\') {
+ if (--NestedBraces == 0)
+ break;
+ } else if (Cur[VariantsEnd] == '{')
+ ++NestedBraces;
+ }
+
+ // Select the Nth variant (or empty).
+ StringRef Selection = Cur.slice(VariantsStart, VariantsEnd);
+ for (unsigned i = 0; i != Variant; ++i)
+ Selection = Selection.split('|').second;
+ Res += Selection.split('|').first;
+
+ assert(VariantsEnd != Cur.size() &&
+ "Unterminated variants in assembly string!");
+ Cur = Cur.substr(VariantsEnd + 1);
+ }
+
+ return Res;
+}
+
+
+//===----------------------------------------------------------------------===//
+/// CodeGenInstAlias Implementation
+//===----------------------------------------------------------------------===//
+
+/// tryAliasOpMatch - This is a helper function for the CodeGenInstAlias
+/// constructor. It checks if an argument in an InstAlias pattern matches
+/// the corresponding operand of the instruction. It returns true on a
+/// successful match, with ResOp set to the result operand to be used.
+bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
+ Record *InstOpRec, bool hasSubOps,
+ SMLoc Loc, CodeGenTarget &T,
+ ResultOperand &ResOp) {
+ Init *Arg = Result->getArg(AliasOpNo);
+ DefInit *ADI = dynamic_cast<DefInit*>(Arg);
+
+ 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())
+ throw TGError(Loc, "result argument #" + utostr(AliasOpNo) +
+ " must have a name!");
+ ResOp = ResultOperand(Result->getArgName(AliasOpNo), ADI->getDef());
+ return true;
+ }
+
+ // Handle explicit registers.
+ if (ADI && ADI->getDef()->isSubClassOf("Register")) {
+ if (InstOpRec->isSubClassOf("OptionalDefOperand")) {
+ DagInit *DI = InstOpRec->getValueAsDag("MIOperandInfo");
+ // The operand info should only have a single (register) entry. We
+ // want the register class of it.
+ InstOpRec = dynamic_cast<DefInit*>(DI->getArg(0))->getDef();
+ }
+
+ if (InstOpRec->isSubClassOf("RegisterOperand"))
+ InstOpRec = InstOpRec->getValueAsDef("RegClass");
+
+ if (!InstOpRec->isSubClassOf("RegisterClass"))
+ return false;
+
+ if (!T.getRegisterClass(InstOpRec)
+ .contains(T.getRegBank().getReg(ADI->getDef())))
+ throw TGError(Loc, "fixed register " + ADI->getDef()->getName() +
+ " is not a member of the " + InstOpRec->getName() +
+ " register class!");
+
+ if (!Result->getArgName(AliasOpNo).empty())
+ throw TGError(Loc, "result fixed register argument must "
+ "not have a name!");
+
+ ResOp = ResultOperand(ADI->getDef());
+ return true;
+ }
+
+ // Handle "zero_reg" for optional def operands.
+ if (ADI && ADI->getDef()->getName() == "zero_reg") {
+
+ // Check if this is an optional def.
+ if (!InstOpRec->isSubClassOf("OptionalDefOperand"))
+ throw TGError(Loc, "reg0 used for result that is not an "
+ "OptionalDefOperand!");
+
+ ResOp = ResultOperand(static_cast<Record*>(0));
+ return true;
+ }
+
+ if (IntInit *II = dynamic_cast<IntInit*>(Arg)) {
+ if (hasSubOps || !InstOpRec->isSubClassOf("Operand"))
+ return false;
+ // Integer arguments can't have names.
+ if (!Result->getArgName(AliasOpNo).empty())
+ throw TGError(Loc, "result argument #" + utostr(AliasOpNo) +
+ " must not have a name!");
+ ResOp = ResultOperand(II->getValue());
+ return true;
+ }
+
+ return false;
+}
+
+CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
+ AsmString = R->getValueAsString("AsmString");
+ Result = R->getValueAsDag("ResultInst");
+
+ // Verify that the root of the result is an instruction.
+ DefInit *DI = dynamic_cast<DefInit*>(Result->getOperator());
+ if (DI == 0 || !DI->getDef()->isSubClassOf("Instruction"))
+ throw TGError(R->getLoc(), "result of inst alias should be an instruction");
+
+ ResultInst = &T.getInstruction(DI->getDef());
+
+ // NameClass - If argument names are repeated, we need to verify they have
+ // the same class.
+ StringMap<Record*> NameClass;
+ for (unsigned i = 0, e = Result->getNumArgs(); i != e; ++i) {
+ DefInit *ADI = dynamic_cast<DefInit*>(Result->getArg(i));
+ if (!ADI || Result->getArgName(i).empty())
+ continue;
+ // Verify we don't have something like: (someinst GR16:$foo, GR32:$foo)
+ // $foo can exist multiple times in the result list, but it must have the
+ // same type.
+ Record *&Entry = NameClass[Result->getArgName(i)];
+ if (Entry && Entry != ADI->getDef())
+ throw TGError(R->getLoc(), "result value $" + Result->getArgName(i) +
+ " is both " + Entry->getName() + " and " +
+ ADI->getDef()->getName() + "!");
+ Entry = ADI->getDef();
+ }
+
+ // Decode and validate the arguments of the result.
+ unsigned AliasOpNo = 0;
+ for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) {
+
+ // Tied registers don't have an entry in the result dag.
+ if (ResultInst->Operands[i].getTiedRegister() != -1)
+ continue;
+
+ if (AliasOpNo >= Result->getNumArgs())
+ throw TGError(R->getLoc(), "not enough arguments for instruction!");
+
+ Record *InstOpRec = ResultInst->Operands[i].Rec;
+ unsigned NumSubOps = ResultInst->Operands[i].MINumOperands;
+ ResultOperand ResOp(static_cast<int64_t>(0));
+ if (tryAliasOpMatch(Result, AliasOpNo, InstOpRec, (NumSubOps > 1),
+ R->getLoc(), T, ResOp)) {
+ ResultOperands.push_back(ResOp);
+ ResultInstOperandIndex.push_back(std::make_pair(i, -1));
+ ++AliasOpNo;
+ continue;
+ }
+
+ // If the argument did not match the instruction operand, and the operand
+ // is composed of multiple suboperands, try matching the suboperands.
+ if (NumSubOps > 1) {
+ DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo;
+ for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) {
+ if (AliasOpNo >= Result->getNumArgs())
+ throw TGError(R->getLoc(), "not enough arguments for instruction!");
+ Record *SubRec = dynamic_cast<DefInit*>(MIOI->getArg(SubOp))->getDef();
+ if (tryAliasOpMatch(Result, AliasOpNo, SubRec, false,
+ R->getLoc(), T, ResOp)) {
+ ResultOperands.push_back(ResOp);
+ ResultInstOperandIndex.push_back(std::make_pair(i, SubOp));
+ ++AliasOpNo;
+ } else {
+ throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
+ " does not match instruction operand class " +
+ (SubOp == 0 ? InstOpRec->getName() :SubRec->getName()));
+ }
+ }
+ continue;
+ }
+ throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
+ " does not match instruction operand class " +
+ InstOpRec->getName());
+ }
+
+ if (AliasOpNo != Result->getNumArgs())
+ throw TGError(R->getLoc(), "too many operands for instruction!");
+}
diff --git a/src/LLVM/utils/TableGen/CodeGenInstruction.h b/src/LLVM/utils/TableGen/CodeGenInstruction.h
index b02d0d3..468277a 100644
--- a/src/LLVM/utils/TableGen/CodeGenInstruction.h
+++ b/src/LLVM/utils/TableGen/CodeGenInstruction.h
@@ -15,6 +15,8 @@
#define CODEGEN_INSTRUCTION_H
#include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/SourceMgr.h"
#include <string>
#include <vector>
#include <utility>
@@ -23,16 +25,10 @@
class Record;
class DagInit;
class CodeGenTarget;
+ class StringRef;
- class CodeGenInstruction {
+ class CGIOperandList {
public:
- Record *TheDef; // The actual record defining this instruction.
- std::string Namespace; // The namespace the instruction is in.
-
- /// AsmString - The format string used to emit a .s file for the
- /// instruction.
- std::string AsmString;
-
class ConstraintInfo {
enum { None, EarlyClobber, Tied } Kind;
unsigned OtherTiedOperand;
@@ -45,24 +41,24 @@
I.OtherTiedOperand = 0;
return I;
}
-
+
static ConstraintInfo getTied(unsigned Op) {
ConstraintInfo I;
I.Kind = Tied;
I.OtherTiedOperand = Op;
return I;
}
-
+
bool isNone() const { return Kind == None; }
bool isEarlyClobber() const { return Kind == EarlyClobber; }
bool isTied() const { return Kind == Tied; }
-
+
unsigned getTiedOperand() const {
assert(isTied());
return OtherTiedOperand;
}
};
-
+
/// OperandInfo - The information we keep track of for each operand in the
/// operand list for a tablegen instruction.
struct OperandInfo {
@@ -78,6 +74,14 @@
/// the asmprinter.
std::string PrinterMethodName;
+ /// EncoderMethodName - The method used to get the machine operand value
+ /// for binary encoding. "getMachineOpValue" by default.
+ std::string EncoderMethodName;
+
+ /// OperandType - A value from MCOI::OperandType representing the type of
+ /// the operand.
+ std::string OperandType;
+
/// MIOperandNo - Currently (this is meant to be phased out), some logical
/// operands correspond to multiple MachineInstr operands. In the X86
/// target for example, one address operand is represented as 4
@@ -91,21 +95,38 @@
/// the DisableEncoding list. These should not be emitted by the code
/// emitter.
std::vector<bool> DoNotEncode;
-
+
/// MIOperandInfo - Default MI operand type. Note an operand may be made
/// up of multiple MI operands.
DagInit *MIOperandInfo;
-
+
/// Constraint info for this operand. This operand can have pieces, so we
/// track constraint info for each.
std::vector<ConstraintInfo> Constraints;
- OperandInfo(Record *R, const std::string &N, const std::string &PMN,
- unsigned MION, unsigned MINO, DagInit *MIOI)
- : Rec(R), Name(N), PrinterMethodName(PMN), MIOperandNo(MION),
- MINumOperands(MINO), MIOperandInfo(MIOI) {}
+ OperandInfo(Record *R, const std::string &N, const std::string &PMN,
+ const std::string &EMN, const std::string &OT, unsigned MION,
+ unsigned MINO, DagInit *MIOI)
+ : Rec(R), Name(N), PrinterMethodName(PMN), EncoderMethodName(EMN),
+ OperandType(OT), MIOperandNo(MION), MINumOperands(MINO),
+ MIOperandInfo(MIOI) {}
+
+
+ /// getTiedOperand - If this operand is tied to another one, return the
+ /// other operand number. Otherwise, return -1.
+ int getTiedRegister() const {
+ for (unsigned j = 0, e = Constraints.size(); j != e; ++j) {
+ const CGIOperandList::ConstraintInfo &CI = Constraints[j];
+ if (CI.isTied()) return CI.getTiedOperand();
+ }
+ return -1;
+ }
};
+ CGIOperandList(Record *D);
+
+ Record *TheDef; // The actual record containing this OperandList.
+
/// NumDefs - Number of def operands declared, this is the number of
/// elements in the instruction's (outs) list.
///
@@ -115,6 +136,81 @@
/// type (which is a record).
std::vector<OperandInfo> OperandList;
+ // Information gleaned from the operand list.
+ bool isPredicable;
+ bool hasOptionalDef;
+ bool isVariadic;
+
+ // Provide transparent accessors to the operand list.
+ bool empty() const { return OperandList.empty(); }
+ unsigned size() const { return OperandList.size(); }
+ const OperandInfo &operator[](unsigned i) const { return OperandList[i]; }
+ OperandInfo &operator[](unsigned i) { return OperandList[i]; }
+ OperandInfo &back() { return OperandList.back(); }
+ const OperandInfo &back() const { return OperandList.back(); }
+
+
+ /// getOperandNamed - Return the index of the operand with the specified
+ /// non-empty name. If the instruction does not have an operand with the
+ /// specified name, throw an exception.
+ unsigned getOperandNamed(StringRef Name) const;
+
+ /// hasOperandNamed - Query whether the instruction has an operand of the
+ /// given name. If so, return true and set OpIdx to the index of the
+ /// operand. Otherwise, return false.
+ bool hasOperandNamed(StringRef Name, unsigned &OpIdx) const;
+
+ /// ParseOperandName - Parse an operand name like "$foo" or "$foo.bar",
+ /// where $foo is a whole operand and $foo.bar refers to a suboperand.
+ /// This throws an exception if the name is invalid. If AllowWholeOp is
+ /// true, references to operands with suboperands are allowed, otherwise
+ /// not.
+ std::pair<unsigned,unsigned> ParseOperandName(const std::string &Op,
+ bool AllowWholeOp = true);
+
+ /// getFlattenedOperandNumber - Flatten a operand/suboperand pair into a
+ /// flat machineinstr operand #.
+ unsigned getFlattenedOperandNumber(std::pair<unsigned,unsigned> Op) const {
+ return OperandList[Op.first].MIOperandNo + Op.second;
+ }
+
+ /// getSubOperandNumber - Unflatten a operand number into an
+ /// operand/suboperand pair.
+ std::pair<unsigned,unsigned> getSubOperandNumber(unsigned Op) const {
+ for (unsigned i = 0; ; ++i) {
+ assert(i < OperandList.size() && "Invalid flat operand #");
+ if (OperandList[i].MIOperandNo+OperandList[i].MINumOperands > Op)
+ return std::make_pair(i, Op-OperandList[i].MIOperandNo);
+ }
+ }
+
+
+ /// isFlatOperandNotEmitted - Return true if the specified flat operand #
+ /// should not be emitted with the code emitter.
+ bool isFlatOperandNotEmitted(unsigned FlatOpNo) const {
+ std::pair<unsigned,unsigned> Op = getSubOperandNumber(FlatOpNo);
+ if (OperandList[Op.first].DoNotEncode.size() > Op.second)
+ return OperandList[Op.first].DoNotEncode[Op.second];
+ return false;
+ }
+
+ void ProcessDisableEncoding(std::string Value);
+ };
+
+
+ class CodeGenInstruction {
+ public:
+ Record *TheDef; // The actual record defining this instruction.
+ std::string Namespace; // The namespace the instruction is in.
+
+ /// AsmString - The format string used to emit a .s file for the
+ /// instruction.
+ std::string AsmString;
+
+ /// Operands - This is information about the (ins) and (outs) list specified
+ /// to the instruction.
+ CGIOperandList Operands;
+
/// ImplicitDefs/ImplicitUses - These are lists of registers that are
/// implicitly defined and used by the instruction.
std::vector<Record*> ImplicitDefs, ImplicitUses;
@@ -124,6 +220,8 @@
bool isBranch;
bool isIndirectBranch;
bool isCompare;
+ bool isMoveImm;
+ bool isBitcast;
bool isBarrier;
bool isCall;
bool canFoldAsLoad;
@@ -135,62 +233,93 @@
bool isReMaterializable;
bool hasDelaySlot;
bool usesCustomInserter;
- bool isVariadic;
+ bool hasPostISelHook;
bool hasCtrlDep;
bool isNotDuplicable;
- bool hasOptionalDef;
bool hasSideEffects;
bool neverHasSideEffects;
bool isAsCheapAsAMove;
bool hasExtraSrcRegAllocReq;
bool hasExtraDefRegAllocReq;
-
- /// ParseOperandName - Parse an operand name like "$foo" or "$foo.bar",
- /// where $foo is a whole operand and $foo.bar refers to a suboperand.
- /// This throws an exception if the name is invalid. If AllowWholeOp is
- /// true, references to operands with suboperands are allowed, otherwise
- /// not.
- std::pair<unsigned,unsigned> ParseOperandName(const std::string &Op,
- bool AllowWholeOp = true);
-
- /// getFlattenedOperandNumber - Flatten a operand/suboperand pair into a
- /// flat machineinstr operand #.
- unsigned getFlattenedOperandNumber(std::pair<unsigned,unsigned> Op) const {
- return OperandList[Op.first].MIOperandNo + Op.second;
- }
-
- /// getSubOperandNumber - Unflatten a operand number into an
- /// operand/suboperand pair.
- std::pair<unsigned,unsigned> getSubOperandNumber(unsigned Op) const {
- for (unsigned i = 0; ; ++i) {
- assert(i < OperandList.size() && "Invalid flat operand #");
- if (OperandList[i].MIOperandNo+OperandList[i].MINumOperands > Op)
- return std::make_pair(i, Op-OperandList[i].MIOperandNo);
- }
- }
-
-
- /// isFlatOperandNotEmitted - Return true if the specified flat operand #
- /// should not be emitted with the code emitter.
- bool isFlatOperandNotEmitted(unsigned FlatOpNo) const {
- std::pair<unsigned,unsigned> Op = getSubOperandNumber(FlatOpNo);
- if (OperandList[Op.first].DoNotEncode.size() > Op.second)
- return OperandList[Op.first].DoNotEncode[Op.second];
- return false;
- }
+ bool isCodeGenOnly;
+ bool isPseudo;
- CodeGenInstruction(Record *R, const std::string &AsmStr);
- /// getOperandNamed - Return the index of the operand with the specified
- /// non-empty name. If the instruction does not have an operand with the
- /// specified name, throw an exception.
- unsigned getOperandNamed(const std::string &Name) const;
-
+ CodeGenInstruction(Record *R);
+
/// HasOneImplicitDefWithKnownVT - If the instruction has at least one
/// implicit def and it has a known VT, return the VT, otherwise return
/// MVT::Other.
- MVT::SimpleValueType
+ MVT::SimpleValueType
HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const;
+
+
+ /// FlattenAsmStringVariants - Flatten the specified AsmString to only
+ /// include text from the specified variant, returning the new string.
+ static std::string FlattenAsmStringVariants(StringRef AsmString,
+ unsigned Variant);
+ };
+
+
+ /// CodeGenInstAlias - This represents an InstAlias definition.
+ class CodeGenInstAlias {
+ public:
+ Record *TheDef; // The actual record defining this InstAlias.
+
+ /// AsmString - The format string used to emit a .s file for the
+ /// instruction.
+ std::string AsmString;
+
+ /// Result - The result instruction.
+ DagInit *Result;
+
+ /// ResultInst - The instruction generated by the alias (decoded from
+ /// Result).
+ CodeGenInstruction *ResultInst;
+
+
+ struct ResultOperand {
+ private:
+ StringRef Name;
+ Record *R;
+
+ int64_t Imm;
+ public:
+ enum {
+ K_Record,
+ K_Imm,
+ K_Reg
+ } Kind;
+
+ ResultOperand(StringRef N, Record *r) : Name(N), R(r), Kind(K_Record) {}
+ ResultOperand(int64_t I) : Imm(I), Kind(K_Imm) {}
+ ResultOperand(Record *r) : R(r), Kind(K_Reg) {}
+
+ bool isRecord() const { return Kind == K_Record; }
+ bool isImm() const { return Kind == K_Imm; }
+ bool isReg() const { return Kind == K_Reg; }
+
+ StringRef getName() const { assert(isRecord()); return Name; }
+ Record *getRecord() const { assert(isRecord()); return R; }
+ int64_t getImm() const { assert(isImm()); return Imm; }
+ Record *getRegister() const { assert(isReg()); return R; }
+ };
+
+ /// ResultOperands - The decoded operands for the result instruction.
+ std::vector<ResultOperand> ResultOperands;
+
+ /// ResultInstOperandIndex - For each operand, this vector holds a pair of
+ /// indices to identify the corresponding operand in the result
+ /// instruction. The first index specifies the operand and the second
+ /// index specifies the suboperand. If there are no suboperands or if all
+ /// 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);
+
+ bool tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
+ Record *InstOpRec, bool hasSubOps, SMLoc Loc,
+ CodeGenTarget &T, ResultOperand &ResOp);
};
}
diff --git a/src/LLVM/utils/TableGen/CodeGenIntrinsics.h b/src/LLVM/utils/TableGen/CodeGenIntrinsics.h
index 3208c0d..3f6ba61 100644
--- a/src/LLVM/utils/TableGen/CodeGenIntrinsics.h
+++ b/src/LLVM/utils/TableGen/CodeGenIntrinsics.h
@@ -69,6 +69,9 @@
/// isCommutative - True if the intrinsic is commutative.
bool isCommutative;
+
+ /// canThrow - True if the intrinsic can throw.
+ bool canThrow;
enum ArgAttribute {
NoCapture
diff --git a/src/LLVM/utils/TableGen/CodeGenRegisters.cpp b/src/LLVM/utils/TableGen/CodeGenRegisters.cpp
new file mode 100644
index 0000000..8de4615
--- /dev/null
+++ b/src/LLVM/utils/TableGen/CodeGenRegisters.cpp
@@ -0,0 +1,845 @@
+//===- CodeGenRegisters.cpp - Register and RegisterClass Info -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines structures to encapsulate information gleaned from the
+// target register and register class definitions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenRegisters.h"
+#include "CodeGenTarget.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// CodeGenRegister
+//===----------------------------------------------------------------------===//
+
+CodeGenRegister::CodeGenRegister(Record *R, unsigned Enum)
+ : TheDef(R),
+ EnumValue(Enum),
+ CostPerUse(R->getValueAsInt("CostPerUse")),
+ SubRegsComplete(false)
+{}
+
+const std::string &CodeGenRegister::getName() const {
+ return TheDef->getName();
+}
+
+namespace {
+ struct Orphan {
+ CodeGenRegister *SubReg;
+ Record *First, *Second;
+ Orphan(CodeGenRegister *r, Record *a, Record *b)
+ : SubReg(r), First(a), Second(b) {}
+ };
+}
+
+const CodeGenRegister::SubRegMap &
+CodeGenRegister::getSubRegs(CodeGenRegBank &RegBank) {
+ // Only compute this map once.
+ if (SubRegsComplete)
+ return SubRegs;
+ SubRegsComplete = true;
+
+ std::vector<Record*> SubList = TheDef->getValueAsListOfDefs("SubRegs");
+ std::vector<Record*> Indices = TheDef->getValueAsListOfDefs("SubRegIndices");
+ if (SubList.size() != Indices.size())
+ throw TGError(TheDef->getLoc(), "Register " + getName() +
+ " SubRegIndices doesn't match SubRegs");
+
+ // First insert the direct subregs and make sure they are fully indexed.
+ for (unsigned i = 0, e = SubList.size(); i != e; ++i) {
+ CodeGenRegister *SR = RegBank.getReg(SubList[i]);
+ if (!SubRegs.insert(std::make_pair(Indices[i], SR)).second)
+ throw TGError(TheDef->getLoc(), "SubRegIndex " + Indices[i]->getName() +
+ " appears twice in Register " + getName());
+ }
+
+ // Keep track of inherited subregs and how they can be reached.
+ SmallVector<Orphan, 8> Orphans;
+
+ // Clone inherited subregs and place duplicate entries on Orphans.
+ // Here the order is important - earlier subregs take precedence.
+ for (unsigned i = 0, e = SubList.size(); i != e; ++i) {
+ CodeGenRegister *SR = RegBank.getReg(SubList[i]);
+ const SubRegMap &Map = SR->getSubRegs(RegBank);
+
+ // Add this as a super-register of SR now all sub-registers are in the list.
+ // This creates a topological ordering, the exact order depends on the
+ // order getSubRegs is called on all registers.
+ SR->SuperRegs.push_back(this);
+
+ for (SubRegMap::const_iterator SI = Map.begin(), SE = Map.end(); SI != SE;
+ ++SI) {
+ if (!SubRegs.insert(*SI).second)
+ Orphans.push_back(Orphan(SI->second, Indices[i], SI->first));
+
+ // Noop sub-register indexes are possible, so avoid duplicates.
+ if (SI->second != SR)
+ SI->second->SuperRegs.push_back(this);
+ }
+ }
+
+ // Process the composites.
+ ListInit *Comps = TheDef->getValueAsListInit("CompositeIndices");
+ for (unsigned i = 0, e = Comps->size(); i != e; ++i) {
+ DagInit *Pat = dynamic_cast<DagInit*>(Comps->getElement(i));
+ if (!Pat)
+ throw TGError(TheDef->getLoc(), "Invalid dag '" +
+ Comps->getElement(i)->getAsString() +
+ "' in CompositeIndices");
+ DefInit *BaseIdxInit = dynamic_cast<DefInit*>(Pat->getOperator());
+ if (!BaseIdxInit || !BaseIdxInit->getDef()->isSubClassOf("SubRegIndex"))
+ throw TGError(TheDef->getLoc(), "Invalid SubClassIndex in " +
+ Pat->getAsString());
+
+ // Resolve list of subreg indices into R2.
+ CodeGenRegister *R2 = this;
+ for (DagInit::const_arg_iterator di = Pat->arg_begin(),
+ de = Pat->arg_end(); di != de; ++di) {
+ DefInit *IdxInit = dynamic_cast<DefInit*>(*di);
+ if (!IdxInit || !IdxInit->getDef()->isSubClassOf("SubRegIndex"))
+ throw TGError(TheDef->getLoc(), "Invalid SubClassIndex in " +
+ Pat->getAsString());
+ const SubRegMap &R2Subs = R2->getSubRegs(RegBank);
+ SubRegMap::const_iterator ni = R2Subs.find(IdxInit->getDef());
+ if (ni == R2Subs.end())
+ throw TGError(TheDef->getLoc(), "Composite " + Pat->getAsString() +
+ " refers to bad index in " + R2->getName());
+ R2 = ni->second;
+ }
+
+ // Insert composite index. Allow overriding inherited indices etc.
+ SubRegs[BaseIdxInit->getDef()] = R2;
+
+ // R2 is no longer an orphan.
+ for (unsigned j = 0, je = Orphans.size(); j != je; ++j)
+ if (Orphans[j].SubReg == R2)
+ Orphans[j].SubReg = 0;
+ }
+
+ // Now Orphans contains the inherited subregisters without a direct index.
+ // Create inferred indexes for all missing entries.
+ for (unsigned i = 0, e = Orphans.size(); i != e; ++i) {
+ Orphan &O = Orphans[i];
+ if (!O.SubReg)
+ continue;
+ SubRegs[RegBank.getCompositeSubRegIndex(O.First, O.Second, true)] =
+ O.SubReg;
+ }
+ return SubRegs;
+}
+
+void
+CodeGenRegister::addSubRegsPreOrder(SetVector<CodeGenRegister*> &OSet) const {
+ assert(SubRegsComplete && "Must precompute sub-registers");
+ std::vector<Record*> Indices = TheDef->getValueAsListOfDefs("SubRegIndices");
+ for (unsigned i = 0, e = Indices.size(); i != e; ++i) {
+ CodeGenRegister *SR = SubRegs.find(Indices[i])->second;
+ if (OSet.insert(SR))
+ SR->addSubRegsPreOrder(OSet);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// RegisterTuples
+//===----------------------------------------------------------------------===//
+
+// A RegisterTuples def is used to generate pseudo-registers from lists of
+// sub-registers. We provide a SetTheory expander class that returns the new
+// registers.
+namespace {
+struct TupleExpander : SetTheory::Expander {
+ void expand(SetTheory &ST, Record *Def, SetTheory::RecSet &Elts) {
+ std::vector<Record*> Indices = Def->getValueAsListOfDefs("SubRegIndices");
+ unsigned Dim = Indices.size();
+ ListInit *SubRegs = Def->getValueAsListInit("SubRegs");
+ if (Dim != SubRegs->getSize())
+ throw TGError(Def->getLoc(), "SubRegIndices and SubRegs size mismatch");
+ if (Dim < 2)
+ throw TGError(Def->getLoc(), "Tuples must have at least 2 sub-registers");
+
+ // Evaluate the sub-register lists to be zipped.
+ unsigned Length = ~0u;
+ SmallVector<SetTheory::RecSet, 4> Lists(Dim);
+ for (unsigned i = 0; i != Dim; ++i) {
+ ST.evaluate(SubRegs->getElement(i), Lists[i]);
+ Length = std::min(Length, unsigned(Lists[i].size()));
+ }
+
+ if (Length == 0)
+ return;
+
+ // Precompute some types.
+ Record *RegisterCl = Def->getRecords().getClass("Register");
+ RecTy *RegisterRecTy = RecordRecTy::get(RegisterCl);
+ StringInit *BlankName = StringInit::get("");
+
+ // Zip them up.
+ for (unsigned n = 0; n != Length; ++n) {
+ std::string Name;
+ Record *Proto = Lists[0][n];
+ std::vector<Init*> Tuple;
+ unsigned CostPerUse = 0;
+ for (unsigned i = 0; i != Dim; ++i) {
+ Record *Reg = Lists[i][n];
+ if (i) Name += '_';
+ Name += Reg->getName();
+ Tuple.push_back(DefInit::get(Reg));
+ CostPerUse = std::max(CostPerUse,
+ unsigned(Reg->getValueAsInt("CostPerUse")));
+ }
+
+ // Create a new Record representing the synthesized register. This record
+ // is only for consumption by CodeGenRegister, it is not added to the
+ // RecordKeeper.
+ Record *NewReg = new Record(Name, Def->getLoc(), Def->getRecords());
+ Elts.insert(NewReg);
+
+ // Copy Proto super-classes.
+ for (unsigned i = 0, e = Proto->getSuperClasses().size(); i != e; ++i)
+ NewReg->addSuperClass(Proto->getSuperClasses()[i]);
+
+ // Copy Proto fields.
+ for (unsigned i = 0, e = Proto->getValues().size(); i != e; ++i) {
+ RecordVal RV = Proto->getValues()[i];
+
+ // Replace the sub-register list with Tuple.
+ if (RV.getName() == "SubRegs")
+ RV.setValue(ListInit::get(Tuple, RegisterRecTy));
+
+ // Provide a blank AsmName. MC hacks are required anyway.
+ if (RV.getName() == "AsmName")
+ RV.setValue(BlankName);
+
+ // CostPerUse is aggregated from all Tuple members.
+ if (RV.getName() == "CostPerUse")
+ RV.setValue(IntInit::get(CostPerUse));
+
+ // Copy fields from the RegisterTuples def.
+ if (RV.getName() == "SubRegIndices" ||
+ RV.getName() == "CompositeIndices") {
+ NewReg->addValue(*Def->getValue(RV.getName()));
+ continue;
+ }
+
+ // Some fields get their default uninitialized value.
+ if (RV.getName() == "DwarfNumbers" ||
+ RV.getName() == "DwarfAlias" ||
+ RV.getName() == "Aliases") {
+ if (const RecordVal *DefRV = RegisterCl->getValue(RV.getName()))
+ NewReg->addValue(*DefRV);
+ continue;
+ }
+
+ // Everything else is copied from Proto.
+ NewReg->addValue(RV);
+ }
+ }
+ }
+};
+}
+
+//===----------------------------------------------------------------------===//
+// CodeGenRegisterClass
+//===----------------------------------------------------------------------===//
+
+CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
+ : TheDef(R), Name(R->getName()), EnumValue(-1) {
+ // Rename anonymous register classes.
+ if (R->getName().size() > 9 && R->getName()[9] == '.') {
+ static unsigned AnonCounter = 0;
+ R->setName("AnonRegClass_"+utostr(AnonCounter++));
+ }
+
+ std::vector<Record*> TypeList = R->getValueAsListOfDefs("RegTypes");
+ for (unsigned i = 0, e = TypeList.size(); i != e; ++i) {
+ Record *Type = TypeList[i];
+ if (!Type->isSubClassOf("ValueType"))
+ throw "RegTypes list member '" + Type->getName() +
+ "' does not derive from the ValueType class!";
+ VTs.push_back(getValueType(Type));
+ }
+ assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!");
+
+ // Allocation order 0 is the full set. AltOrders provides others.
+ const SetTheory::RecVec *Elements = RegBank.getSets().expand(R);
+ ListInit *AltOrders = R->getValueAsListInit("AltOrders");
+ Orders.resize(1 + AltOrders->size());
+
+ // Default allocation order always contains all registers.
+ for (unsigned i = 0, e = Elements->size(); i != e; ++i) {
+ Orders[0].push_back((*Elements)[i]);
+ Members.insert(RegBank.getReg((*Elements)[i]));
+ }
+
+ // Alternative allocation orders may be subsets.
+ SetTheory::RecSet Order;
+ for (unsigned i = 0, e = AltOrders->size(); i != e; ++i) {
+ RegBank.getSets().evaluate(AltOrders->getElement(i), Order);
+ Orders[1 + i].append(Order.begin(), Order.end());
+ // Verify that all altorder members are regclass members.
+ while (!Order.empty()) {
+ CodeGenRegister *Reg = RegBank.getReg(Order.back());
+ Order.pop_back();
+ if (!contains(Reg))
+ throw TGError(R->getLoc(), " AltOrder register " + Reg->getName() +
+ " is not a class member");
+ }
+ }
+
+ // SubRegClasses is a list<dag> containing (RC, subregindex, ...) dags.
+ ListInit *SRC = R->getValueAsListInit("SubRegClasses");
+ for (ListInit::const_iterator i = SRC->begin(), e = SRC->end(); i != e; ++i) {
+ DagInit *DAG = dynamic_cast<DagInit*>(*i);
+ if (!DAG) throw "SubRegClasses must contain DAGs";
+ DefInit *DAGOp = dynamic_cast<DefInit*>(DAG->getOperator());
+ Record *RCRec;
+ if (!DAGOp || !(RCRec = DAGOp->getDef())->isSubClassOf("RegisterClass"))
+ throw "Operator '" + DAG->getOperator()->getAsString() +
+ "' in SubRegClasses is not a RegisterClass";
+ // Iterate over args, all SubRegIndex instances.
+ for (DagInit::const_arg_iterator ai = DAG->arg_begin(), ae = DAG->arg_end();
+ ai != ae; ++ai) {
+ DefInit *Idx = dynamic_cast<DefInit*>(*ai);
+ Record *IdxRec;
+ if (!Idx || !(IdxRec = Idx->getDef())->isSubClassOf("SubRegIndex"))
+ throw "Argument '" + (*ai)->getAsString() +
+ "' in SubRegClasses is not a SubRegIndex";
+ if (!SubRegClasses.insert(std::make_pair(IdxRec, RCRec)).second)
+ throw "SubRegIndex '" + IdxRec->getName() + "' mentioned twice";
+ }
+ }
+
+ // Allow targets to override the size in bits of the RegisterClass.
+ unsigned Size = R->getValueAsInt("Size");
+
+ Namespace = R->getValueAsString("Namespace");
+ SpillSize = Size ? Size : EVT(VTs[0]).getSizeInBits();
+ SpillAlignment = R->getValueAsInt("Alignment");
+ CopyCost = R->getValueAsInt("CopyCost");
+ Allocatable = R->getValueAsBit("isAllocatable");
+ AltOrderSelect = R->getValueAsCode("AltOrderSelect");
+}
+
+// Create an inferred register class that was missing from the .td files.
+// Most properties will be inherited from the closest super-class after the
+// class structure has been computed.
+CodeGenRegisterClass::CodeGenRegisterClass(StringRef Name, Key Props)
+ : Members(*Props.Members),
+ TheDef(0),
+ Name(Name),
+ EnumValue(-1),
+ SpillSize(Props.SpillSize),
+ SpillAlignment(Props.SpillAlignment),
+ CopyCost(0),
+ Allocatable(true) {
+}
+
+// Compute inherited propertied for a synthesized register class.
+void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) {
+ assert(!getDef() && "Only synthesized classes can inherit properties");
+ assert(!SuperClasses.empty() && "Synthesized class without super class");
+
+ // The last super-class is the smallest one.
+ CodeGenRegisterClass &Super = *SuperClasses.back();
+
+ // Most properties are copied directly.
+ // Exceptions are members, size, and alignment
+ Namespace = Super.Namespace;
+ VTs = Super.VTs;
+ CopyCost = Super.CopyCost;
+ Allocatable = Super.Allocatable;
+ AltOrderSelect = Super.AltOrderSelect;
+
+ // Copy all allocation orders, filter out foreign registers from the larger
+ // super-class.
+ Orders.resize(Super.Orders.size());
+ for (unsigned i = 0, ie = Super.Orders.size(); i != ie; ++i)
+ for (unsigned j = 0, je = Super.Orders[i].size(); j != je; ++j)
+ if (contains(RegBank.getReg(Super.Orders[i][j])))
+ Orders[i].push_back(Super.Orders[i][j]);
+}
+
+bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const {
+ return Members.count(Reg);
+}
+
+namespace llvm {
+ raw_ostream &operator<<(raw_ostream &OS, const CodeGenRegisterClass::Key &K) {
+ OS << "{ S=" << K.SpillSize << ", A=" << K.SpillAlignment;
+ for (CodeGenRegister::Set::const_iterator I = K.Members->begin(),
+ E = K.Members->end(); I != E; ++I)
+ OS << ", " << (*I)->getName();
+ return OS << " }";
+ }
+}
+
+// This is a simple lexicographical order that can be used to search for sets.
+// It is not the same as the topological order provided by TopoOrderRC.
+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;
+}
+
+// Returns true if RC is a strict subclass.
+// RC is a sub-class of this class if it is a valid replacement for any
+// instruction operand where a register of this classis required. It must
+// satisfy these conditions:
+//
+// 1. All RC registers are also in this.
+// 2. The RC spill size must not be smaller than our spill size.
+// 3. RC spill alignment must be compatible with ours.
+//
+static bool testSubClass(const CodeGenRegisterClass *A,
+ const CodeGenRegisterClass *B) {
+ return A->SpillAlignment && B->SpillAlignment % A->SpillAlignment == 0 &&
+ A->SpillSize <= B->SpillSize &&
+ std::includes(A->getMembers().begin(), A->getMembers().end(),
+ B->getMembers().begin(), B->getMembers().end(),
+ CodeGenRegister::Less());
+}
+
+/// Sorting predicate for register classes. This provides a topological
+/// ordering that arranges all register classes before their sub-classes.
+///
+/// Register classes with the same registers, spill size, and alignment form a
+/// clique. They will be ordered alphabetically.
+///
+static int TopoOrderRC(const void *PA, const void *PB) {
+ const CodeGenRegisterClass *A = *(const CodeGenRegisterClass* const*)PA;
+ const CodeGenRegisterClass *B = *(const CodeGenRegisterClass* const*)PB;
+ if (A == B)
+ return 0;
+
+ // Order by descending set size. Note that the classes' allocation order may
+ // not have been computed yet. The Members set is always vaild.
+ if (A->getMembers().size() > B->getMembers().size())
+ return -1;
+ if (A->getMembers().size() < B->getMembers().size())
+ return 1;
+
+ // Order by ascending spill size.
+ if (A->SpillSize < B->SpillSize)
+ return -1;
+ if (A->SpillSize > B->SpillSize)
+ return 1;
+
+ // Order by ascending spill alignment.
+ if (A->SpillAlignment < B->SpillAlignment)
+ return -1;
+ if (A->SpillAlignment > B->SpillAlignment)
+ return 1;
+
+ // Finally order by name as a tie breaker.
+ return A->getName() < B->getName();
+}
+
+std::string CodeGenRegisterClass::getQualifiedName() const {
+ if (Namespace.empty())
+ return getName();
+ else
+ return Namespace + "::" + getName();
+}
+
+// Compute sub-classes of all register classes.
+// Assume the classes are ordered topologically.
+void CodeGenRegisterClass::computeSubClasses(CodeGenRegBank &RegBank) {
+ ArrayRef<CodeGenRegisterClass*> RegClasses = RegBank.getRegClasses();
+
+ // Visit backwards so sub-classes are seen first.
+ for (unsigned rci = RegClasses.size(); rci; --rci) {
+ CodeGenRegisterClass &RC = *RegClasses[rci - 1];
+ RC.SubClasses.resize(RegClasses.size());
+ RC.SubClasses.set(RC.EnumValue);
+
+ // Normally, all subclasses have IDs >= rci, unless RC is part of a clique.
+ for (unsigned s = rci; s != RegClasses.size(); ++s) {
+ if (RC.SubClasses.test(s))
+ continue;
+ CodeGenRegisterClass *SubRC = RegClasses[s];
+ if (!testSubClass(&RC, SubRC))
+ continue;
+ // SubRC is a sub-class. Grap all its sub-classes so we won't have to
+ // check them again.
+ RC.SubClasses |= SubRC->SubClasses;
+ }
+
+ // Sweep up missed clique members. They will be immediately preceeding RC.
+ for (unsigned s = rci - 1; s && testSubClass(&RC, RegClasses[s - 1]); --s)
+ RC.SubClasses.set(s - 1);
+ }
+
+ // Compute the SuperClasses lists from the SubClasses vectors.
+ for (unsigned rci = 0; rci != RegClasses.size(); ++rci) {
+ const BitVector &SC = RegClasses[rci]->getSubClasses();
+ for (int s = SC.find_first(); s >= 0; s = SC.find_next(s)) {
+ if (unsigned(s) == rci)
+ continue;
+ RegClasses[s]->SuperClasses.push_back(RegClasses[rci]);
+ }
+ }
+
+ // With the class hierarchy in place, let synthesized register classes inherit
+ // properties from their closest super-class. The iteration order here can
+ // propagate properties down multiple levels.
+ for (unsigned rci = 0; rci != RegClasses.size(); ++rci)
+ if (!RegClasses[rci]->getDef())
+ RegClasses[rci]->inheritProperties(RegBank);
+}
+
+//===----------------------------------------------------------------------===//
+// CodeGenRegBank
+//===----------------------------------------------------------------------===//
+
+CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) : Records(Records) {
+ // Configure register Sets to understand register classes and tuples.
+ Sets.addFieldExpander("RegisterClass", "MemberList");
+ Sets.addExpander("RegisterTuples", new TupleExpander());
+
+ // Read in the user-defined (named) sub-register indices.
+ // More indices will be synthesized later.
+ SubRegIndices = Records.getAllDerivedDefinitions("SubRegIndex");
+ std::sort(SubRegIndices.begin(), SubRegIndices.end(), LessRecord());
+ NumNamedIndices = SubRegIndices.size();
+
+ // Read in the register definitions.
+ std::vector<Record*> Regs = Records.getAllDerivedDefinitions("Register");
+ std::sort(Regs.begin(), Regs.end(), LessRecord());
+ Registers.reserve(Regs.size());
+ // Assign the enumeration values.
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i)
+ getReg(Regs[i]);
+
+ // Expand tuples and number the new registers.
+ std::vector<Record*> Tups =
+ Records.getAllDerivedDefinitions("RegisterTuples");
+ for (unsigned i = 0, e = Tups.size(); i != e; ++i) {
+ const std::vector<Record*> *TupRegs = Sets.expand(Tups[i]);
+ for (unsigned j = 0, je = TupRegs->size(); j != je; ++j)
+ getReg((*TupRegs)[j]);
+ }
+
+ // Precompute all sub-register maps now all the registers are known.
+ // This will create Composite entries for all inferred sub-register indices.
+ for (unsigned i = 0, e = Registers.size(); i != e; ++i)
+ Registers[i]->getSubRegs(*this);
+
+ // Read in register class definitions.
+ std::vector<Record*> RCs = Records.getAllDerivedDefinitions("RegisterClass");
+ if (RCs.empty())
+ throw std::string("No 'RegisterClass' subclasses defined!");
+
+ // Allocate user-defined register classes.
+ RegClasses.reserve(RCs.size());
+ for (unsigned i = 0, e = RCs.size(); i != e; ++i)
+ addToMaps(new CodeGenRegisterClass(*this, RCs[i]));
+
+ // Infer missing classes to create a full algebra.
+ computeInferredRegisterClasses();
+
+ // Order register classes topologically and assign enum values.
+ array_pod_sort(RegClasses.begin(), RegClasses.end(), TopoOrderRC);
+ for (unsigned i = 0, e = RegClasses.size(); i != e; ++i)
+ RegClasses[i]->EnumValue = i;
+ CodeGenRegisterClass::computeSubClasses(*this);
+}
+
+CodeGenRegister *CodeGenRegBank::getReg(Record *Def) {
+ CodeGenRegister *&Reg = Def2Reg[Def];
+ if (Reg)
+ return Reg;
+ Reg = new CodeGenRegister(Def, Registers.size() + 1);
+ Registers.push_back(Reg);
+ return Reg;
+}
+
+void CodeGenRegBank::addToMaps(CodeGenRegisterClass *RC) {
+ RegClasses.push_back(RC);
+
+ if (Record *Def = RC->getDef())
+ Def2RC.insert(std::make_pair(Def, RC));
+
+ // Duplicate classes are rejected by insert().
+ // That's OK, we only care about the properties handled by CGRC::Key.
+ CodeGenRegisterClass::Key K(*RC);
+ Key2RC.insert(std::make_pair(K, RC));
+}
+
+CodeGenRegisterClass *CodeGenRegBank::getRegClass(Record *Def) {
+ if (CodeGenRegisterClass *RC = Def2RC[Def])
+ return RC;
+
+ throw TGError(Def->getLoc(), "Not a known RegisterClass!");
+}
+
+Record *CodeGenRegBank::getCompositeSubRegIndex(Record *A, Record *B,
+ bool create) {
+ // Look for an existing entry.
+ Record *&Comp = Composite[std::make_pair(A, B)];
+ if (Comp || !create)
+ return Comp;
+
+ // None exists, synthesize one.
+ std::string Name = A->getName() + "_then_" + B->getName();
+ Comp = new Record(Name, SMLoc(), Records);
+ SubRegIndices.push_back(Comp);
+ return Comp;
+}
+
+unsigned CodeGenRegBank::getSubRegIndexNo(Record *idx) {
+ std::vector<Record*>::const_iterator i =
+ std::find(SubRegIndices.begin(), SubRegIndices.end(), idx);
+ assert(i != SubRegIndices.end() && "Not a SubRegIndex");
+ return (i - SubRegIndices.begin()) + 1;
+}
+
+void CodeGenRegBank::computeComposites() {
+ for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
+ CodeGenRegister *Reg1 = Registers[i];
+ const CodeGenRegister::SubRegMap &SRM1 = Reg1->getSubRegs();
+ for (CodeGenRegister::SubRegMap::const_iterator i1 = SRM1.begin(),
+ e1 = SRM1.end(); i1 != e1; ++i1) {
+ Record *Idx1 = i1->first;
+ CodeGenRegister *Reg2 = i1->second;
+ // Ignore identity compositions.
+ if (Reg1 == Reg2)
+ continue;
+ const CodeGenRegister::SubRegMap &SRM2 = Reg2->getSubRegs();
+ // Try composing Idx1 with another SubRegIndex.
+ for (CodeGenRegister::SubRegMap::const_iterator i2 = SRM2.begin(),
+ e2 = SRM2.end(); i2 != e2; ++i2) {
+ std::pair<Record*, Record*> IdxPair(Idx1, i2->first);
+ CodeGenRegister *Reg3 = i2->second;
+ // Ignore identity compositions.
+ if (Reg2 == Reg3)
+ continue;
+ // OK Reg1:IdxPair == Reg3. Find the index with Reg:Idx == Reg3.
+ for (CodeGenRegister::SubRegMap::const_iterator i1d = SRM1.begin(),
+ e1d = SRM1.end(); i1d != e1d; ++i1d) {
+ if (i1d->second == Reg3) {
+ std::pair<CompositeMap::iterator, bool> Ins =
+ Composite.insert(std::make_pair(IdxPair, i1d->first));
+ // Conflicting composition? Emit a warning but allow it.
+ if (!Ins.second && Ins.first->second != i1d->first) {
+ errs() << "Warning: SubRegIndex " << getQualifiedName(Idx1)
+ << " and " << getQualifiedName(IdxPair.second)
+ << " compose ambiguously as "
+ << getQualifiedName(Ins.first->second) << " or "
+ << getQualifiedName(i1d->first) << "\n";
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // We don't care about the difference between (Idx1, Idx2) -> Idx2 and invalid
+ // compositions, so remove any mappings of that form.
+ for (CompositeMap::iterator i = Composite.begin(), e = Composite.end();
+ i != e;) {
+ CompositeMap::iterator j = i;
+ ++i;
+ if (j->first.second == j->second)
+ Composite.erase(j);
+ }
+}
+
+// Compute sets of overlapping registers.
+//
+// The standard set is all super-registers and all sub-registers, but the
+// target description can add arbitrary overlapping registers via the 'Aliases'
+// field. This complicates things, but we can compute overlapping sets using
+// the following rules:
+//
+// 1. The relation overlap(A, B) is reflexive and symmetric but not transitive.
+//
+// 2. overlap(A, B) implies overlap(A, S) for all S in supers(B).
+//
+// Alternatively:
+//
+// overlap(A, B) iff there exists:
+// A' in { A, subregs(A) } and B' in { B, subregs(B) } such that:
+// A' = B' or A' in aliases(B') or B' in aliases(A').
+//
+// Here subregs(A) is the full flattened sub-register set returned by
+// A.getSubRegs() while aliases(A) is simply the special 'Aliases' field in the
+// description of register A.
+//
+// This also implies that registers with a common sub-register are considered
+// overlapping. This can happen when forming register pairs:
+//
+// P0 = (R0, R1)
+// P1 = (R1, R2)
+// P2 = (R2, R3)
+//
+// In this case, we will infer an overlap between P0 and P1 because of the
+// shared sub-register R1. There is no overlap between P0 and P2.
+//
+void CodeGenRegBank::
+computeOverlaps(std::map<const CodeGenRegister*, CodeGenRegister::Set> &Map) {
+ assert(Map.empty());
+
+ // Collect overlaps that don't follow from rule 2.
+ for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
+ CodeGenRegister *Reg = Registers[i];
+ CodeGenRegister::Set &Overlaps = Map[Reg];
+
+ // Reg overlaps itself.
+ Overlaps.insert(Reg);
+
+ // All super-registers overlap.
+ const CodeGenRegister::SuperRegList &Supers = Reg->getSuperRegs();
+ Overlaps.insert(Supers.begin(), Supers.end());
+
+ // Form symmetrical relations from the special Aliases[] lists.
+ std::vector<Record*> RegList = Reg->TheDef->getValueAsListOfDefs("Aliases");
+ for (unsigned i2 = 0, e2 = RegList.size(); i2 != e2; ++i2) {
+ CodeGenRegister *Reg2 = getReg(RegList[i2]);
+ CodeGenRegister::Set &Overlaps2 = Map[Reg2];
+ const CodeGenRegister::SuperRegList &Supers2 = Reg2->getSuperRegs();
+ // Reg overlaps Reg2 which implies it overlaps supers(Reg2).
+ Overlaps.insert(Reg2);
+ Overlaps.insert(Supers2.begin(), Supers2.end());
+ Overlaps2.insert(Reg);
+ Overlaps2.insert(Supers.begin(), Supers.end());
+ }
+ }
+
+ // Apply rule 2. and inherit all sub-register overlaps.
+ for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
+ CodeGenRegister *Reg = Registers[i];
+ CodeGenRegister::Set &Overlaps = Map[Reg];
+ const CodeGenRegister::SubRegMap &SRM = Reg->getSubRegs();
+ for (CodeGenRegister::SubRegMap::const_iterator i2 = SRM.begin(),
+ e2 = SRM.end(); i2 != e2; ++i2) {
+ CodeGenRegister::Set &Overlaps2 = Map[i2->second];
+ Overlaps.insert(Overlaps2.begin(), Overlaps2.end());
+ }
+ }
+}
+
+void CodeGenRegBank::computeDerivedInfo() {
+ computeComposites();
+}
+
+// Infer missing register classes.
+//
+// For every register class RC, make sure that the set of registers in RC with
+// a given SubIxx sub-register form a register class.
+void CodeGenRegBank::computeInferredRegisterClasses() {
+ // When this function is called, the register classes have not been sorted
+ // and assigned EnumValues yet. That means getSubClasses(),
+ // getSuperClasses(), and hasSubClass() functions are defunct.
+
+ // Map SubRegIndex to register set.
+ typedef std::map<Record*, CodeGenRegister::Set, LessRecord> SubReg2SetMap;
+
+ // Visit all register classes, including the ones being added by the loop.
+ for (unsigned rci = 0; rci != RegClasses.size(); ++rci) {
+ CodeGenRegisterClass &RC = *RegClasses[rci];
+
+ // Compute the set of registers supporting each SubRegIndex.
+ SubReg2SetMap SRSets;
+ for (CodeGenRegister::Set::const_iterator RI = RC.getMembers().begin(),
+ RE = RC.getMembers().end(); RI != RE; ++RI) {
+ const CodeGenRegister::SubRegMap &SRM = (*RI)->getSubRegs();
+ for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(),
+ E = SRM.end(); I != E; ++I)
+ SRSets[I->first].insert(*RI);
+ }
+
+ // Find matching classes for all SRSets entries. Iterate in SubRegIndex
+ // numerical order to visit synthetic indices last.
+ for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) {
+ Record *SubIdx = SubRegIndices[sri];
+ SubReg2SetMap::const_iterator I = SRSets.find(SubIdx);
+ // Unsupported SubRegIndex. Skip it.
+ if (I == SRSets.end())
+ continue;
+ // In most cases, all RC registers support the SubRegIndex.
+ if (I->second.size() == RC.getMembers().size()) {
+ RC.setSubClassWithSubReg(SubIdx, &RC);
+ continue;
+ }
+
+ // This is a real subset. See if we have a matching class.
+ CodeGenRegisterClass::Key K(&I->second, RC.SpillSize, RC.SpillAlignment);
+ RCKeyMap::const_iterator FoundI = Key2RC.find(K);
+ if (FoundI != Key2RC.end()) {
+ RC.setSubClassWithSubReg(SubIdx, FoundI->second);
+ continue;
+ }
+
+ // Class doesn't exist.
+ CodeGenRegisterClass *NewRC =
+ new CodeGenRegisterClass(RC.getName() + "_with_" +
+ I->first->getName(), K);
+ addToMaps(NewRC);
+ RC.setSubClassWithSubReg(SubIdx, NewRC);
+ }
+ }
+}
+
+/// getRegisterClassForRegister - Find the register class that contains the
+/// specified physical register. If the register is not in a register class,
+/// return null. If the register is in multiple classes, and the classes have a
+/// superset-subset relationship and the same set of types, return the
+/// superclass. Otherwise return null.
+const CodeGenRegisterClass*
+CodeGenRegBank::getRegClassForRegister(Record *R) {
+ const CodeGenRegister *Reg = getReg(R);
+ ArrayRef<CodeGenRegisterClass*> RCs = getRegClasses();
+ const CodeGenRegisterClass *FoundRC = 0;
+ for (unsigned i = 0, e = RCs.size(); i != e; ++i) {
+ const CodeGenRegisterClass &RC = *RCs[i];
+ if (!RC.contains(Reg))
+ continue;
+
+ // If this is the first class that contains the register,
+ // make a note of it and go on to the next class.
+ if (!FoundRC) {
+ FoundRC = &RC;
+ continue;
+ }
+
+ // If a register's classes have different types, return null.
+ if (RC.getValueTypes() != FoundRC->getValueTypes())
+ return 0;
+
+ // Check to see if the previously found class that contains
+ // the register is a subclass of the current class. If so,
+ // prefer the superclass.
+ if (RC.hasSubClass(FoundRC)) {
+ FoundRC = &RC;
+ continue;
+ }
+
+ // Check to see if the previously found class that contains
+ // the register is a superclass of the current class. If so,
+ // prefer the superclass.
+ if (FoundRC->hasSubClass(&RC))
+ continue;
+
+ // Multiple classes, and neither is a superclass of the other.
+ // Return null.
+ return 0;
+ }
+ return FoundRC;
+}
diff --git a/src/LLVM/utils/TableGen/CodeGenRegisters.h b/src/LLVM/utils/TableGen/CodeGenRegisters.h
index 344f77f..4fc34b0 100644
--- a/src/LLVM/utils/TableGen/CodeGenRegisters.h
+++ b/src/LLVM/utils/TableGen/CodeGenRegisters.h
@@ -15,40 +15,116 @@
#ifndef CODEGEN_REGISTERS_H
#define CODEGEN_REGISTERS_H
+#include "SetTheory.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
-#include <string>
-#include <vector>
+#include "llvm/ADT/SetVector.h"
#include <cstdlib>
+#include <map>
+#include <string>
+#include <set>
+#include <vector>
namespace llvm {
- class Record;
+ class CodeGenRegBank;
/// CodeGenRegister - Represents a register definition.
struct CodeGenRegister {
Record *TheDef;
+ unsigned EnumValue;
+ unsigned CostPerUse;
+
+ // Map SubRegIndex -> Register.
+ typedef std::map<Record*, CodeGenRegister*, LessRecord> SubRegMap;
+
+ CodeGenRegister(Record *R, unsigned Enum);
+
const std::string &getName() const;
- unsigned DeclaredSpillSize, DeclaredSpillAlignment;
- CodeGenRegister(Record *R);
+
+ // Get a map of sub-registers computed lazily.
+ // This includes unique entries for all sub-sub-registers.
+ const SubRegMap &getSubRegs(CodeGenRegBank&);
+
+ const SubRegMap &getSubRegs() const {
+ assert(SubRegsComplete && "Must precompute sub-registers");
+ return SubRegs;
+ }
+
+ // Add sub-registers to OSet following a pre-order defined by the .td file.
+ void addSubRegsPreOrder(SetVector<CodeGenRegister*> &OSet) const;
+
+ // List of super-registers in topological order, small to large.
+ typedef std::vector<CodeGenRegister*> SuperRegList;
+
+ // Get the list of super-registers.
+ // This is only valid after computeDerivedInfo has visited all registers.
+ const SuperRegList &getSuperRegs() const {
+ assert(SubRegsComplete && "Must precompute sub-registers");
+ return SuperRegs;
+ }
+
+ // Order CodeGenRegister pointers by EnumValue.
+ struct Less {
+ bool operator()(const CodeGenRegister *A,
+ const CodeGenRegister *B) const {
+ assert(A && B);
+ return A->EnumValue < B->EnumValue;
+ }
+ };
+
+ // Canonically ordered set.
+ typedef std::set<const CodeGenRegister*, Less> Set;
+
+ private:
+ bool SubRegsComplete;
+ SubRegMap SubRegs;
+ SuperRegList SuperRegs;
};
- struct CodeGenRegisterClass {
+ class CodeGenRegisterClass {
+ CodeGenRegister::Set Members;
+ // Allocation orders. Order[0] always contains all registers in Members.
+ std::vector<SmallVector<Record*, 16> > Orders;
+ // Bit mask of sub-classes including this, indexed by their EnumValue.
+ BitVector SubClasses;
+ // List of super-classes, topologocally ordered to have the larger classes
+ // first. This is the same as sorting by EnumValue.
+ SmallVector<CodeGenRegisterClass*, 4> SuperClasses;
Record *TheDef;
+ std::string Name;
+
+ // For a synthesized class, inherit missing properties from the nearest
+ // super-class.
+ void inheritProperties(CodeGenRegBank&);
+
+ // Map SubRegIndex -> sub-class
+ DenseMap<Record*, CodeGenRegisterClass*> SubClassWithSubReg;
+
+ public:
+ unsigned EnumValue;
std::string Namespace;
- std::vector<Record*> Elements;
std::vector<MVT::SimpleValueType> VTs;
unsigned SpillSize;
unsigned SpillAlignment;
int CopyCost;
+ bool Allocatable;
// Map SubRegIndex -> RegisterClass
DenseMap<Record*,Record*> SubRegClasses;
- std::string MethodProtos, MethodBodies;
+ std::string AltOrderSelect;
- const std::string &getName() const;
+ // Return the Record that defined this class, or NULL if the class was
+ // created by TableGen.
+ Record *getDef() const { return TheDef; }
+
+ const std::string &getName() const { return Name; }
+ std::string getQualifiedName() const;
const std::vector<MVT::SimpleValueType> &getValueTypes() const {return VTs;}
unsigned getNumValueTypes() const { return VTs.size(); }
-
+
MVT::SimpleValueType getValueTypeNum(unsigned VTNum) const {
if (VTNum < VTs.size())
return VTs[VTNum];
@@ -56,7 +132,169 @@
abort();
}
- CodeGenRegisterClass(Record *R);
+ // Return true if this this class contains the register.
+ bool contains(const CodeGenRegister*) const;
+
+ // Returns true if RC is a subclass.
+ // RC is a sub-class of this class if it is a valid replacement for any
+ // instruction operand where a register of this classis required. It must
+ // satisfy these conditions:
+ //
+ // 1. All RC registers are also in this.
+ // 2. The RC spill size must not be smaller than our spill size.
+ // 3. RC spill alignment must be compatible with ours.
+ //
+ bool hasSubClass(const CodeGenRegisterClass *RC) const {
+ return SubClasses.test(RC->EnumValue);
+ }
+
+ // getSubClassWithSubReg - Returns the largest sub-class where all
+ // registers have a SubIdx sub-register.
+ CodeGenRegisterClass *getSubClassWithSubReg(Record *SubIdx) const {
+ return SubClassWithSubReg.lookup(SubIdx);
+ }
+
+ void setSubClassWithSubReg(Record *SubIdx, CodeGenRegisterClass *SubRC) {
+ SubClassWithSubReg[SubIdx] = SubRC;
+ }
+
+ // getSubClasses - Returns a constant BitVector of subclasses indexed by
+ // EnumValue.
+ // The SubClasses vector includs an entry for this class.
+ const BitVector &getSubClasses() const { return SubClasses; }
+
+ // getSuperClasses - Returns a list of super classes ordered by EnumValue.
+ // The array does not include an entry for this class.
+ ArrayRef<CodeGenRegisterClass*> getSuperClasses() const {
+ return SuperClasses;
+ }
+
+ // Returns an ordered list of class members.
+ // The order of registers is the same as in the .td file.
+ // No = 0 is the default allocation order, No = 1 is the first alternative.
+ ArrayRef<Record*> getOrder(unsigned No = 0) const {
+ return Orders[No];
+ }
+
+ // Return the total number of allocation orders available.
+ unsigned getNumOrders() const { return Orders.size(); }
+
+ // Get the set of registers. This set contains the same registers as
+ // getOrder(0).
+ const CodeGenRegister::Set &getMembers() const { return Members; }
+
+ CodeGenRegisterClass(CodeGenRegBank&, Record *R);
+
+ // A key representing the parts of a register class used for forming
+ // sub-classes. Note the ordering provided by this key is not the same as
+ // the topological order used for the EnumValues.
+ struct Key {
+ const CodeGenRegister::Set *Members;
+ 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) {}
+
+ Key(const CodeGenRegisterClass &RC)
+ : Members(&RC.getMembers()),
+ SpillSize(RC.SpillSize),
+ SpillAlignment(RC.SpillAlignment) {}
+
+ // Lexicographical order of (Members, SpillSize, SpillAlignment).
+ bool operator<(const Key&) const;
+ };
+
+ // Create a non-user defined register class.
+ CodeGenRegisterClass(StringRef Name, Key Props);
+
+ // Called by CodeGenRegBank::CodeGenRegBank().
+ static void computeSubClasses(CodeGenRegBank&);
+ };
+
+ // CodeGenRegBank - Represent a target's registers and the relations between
+ // them.
+ class CodeGenRegBank {
+ RecordKeeper &Records;
+ SetTheory Sets;
+
+ std::vector<Record*> SubRegIndices;
+ unsigned NumNamedIndices;
+ std::vector<CodeGenRegister*> Registers;
+ DenseMap<Record*, CodeGenRegister*> Def2Reg;
+
+ // Register classes.
+ std::vector<CodeGenRegisterClass*> RegClasses;
+ DenseMap<Record*, CodeGenRegisterClass*> Def2RC;
+ typedef std::map<CodeGenRegisterClass::Key, CodeGenRegisterClass*> RCKeyMap;
+ RCKeyMap Key2RC;
+
+ // Add RC to *2RC maps.
+ void addToMaps(CodeGenRegisterClass*);
+
+ // Infer missing register classes.
+ void computeInferredRegisterClasses();
+
+ // Composite SubRegIndex instances.
+ // Map (SubRegIndex, SubRegIndex) -> SubRegIndex.
+ typedef DenseMap<std::pair<Record*, Record*>, Record*> CompositeMap;
+ CompositeMap Composite;
+
+ // Populate the Composite map from sub-register relationships.
+ void computeComposites();
+
+ public:
+ CodeGenRegBank(RecordKeeper&);
+
+ SetTheory &getSets() { return Sets; }
+
+ // Sub-register indices. The first NumNamedIndices are defined by the user
+ // in the .td files. The rest are synthesized such that all sub-registers
+ // have a unique name.
+ const std::vector<Record*> &getSubRegIndices() { return SubRegIndices; }
+ unsigned getNumNamedIndices() { return NumNamedIndices; }
+
+ // Map a SubRegIndex Record to its enum value.
+ unsigned getSubRegIndexNo(Record *idx);
+
+ // Find or create a sub-register index representing the A+B composition.
+ Record *getCompositeSubRegIndex(Record *A, Record *B, bool create = false);
+
+ const std::vector<CodeGenRegister*> &getRegisters() { return Registers; }
+
+ // Find a register from its Record def.
+ CodeGenRegister *getReg(Record*);
+
+ ArrayRef<CodeGenRegisterClass*> getRegClasses() const {
+ return RegClasses;
+ }
+
+ // Find a register class from its def.
+ CodeGenRegisterClass *getRegClass(Record*);
+
+ /// getRegisterClassForRegister - Find the register class that contains the
+ /// specified physical register. If the register is not in a register
+ /// class, return null. If the register is in multiple classes, and the
+ /// classes have a superset-subset relationship and the same set of types,
+ /// return the superclass. Otherwise return null.
+ const CodeGenRegisterClass* getRegClassForRegister(Record *R);
+
+ // Computed derived records such as missing sub-register indices.
+ void computeDerivedInfo();
+
+ // Compute full overlap sets for every register. These sets include the
+ // rarely used aliases that are neither sub nor super-registers.
+ //
+ // Map[R1].count(R2) is reflexive and symmetric, but not transitive.
+ //
+ // If R1 is a sub-register of R2, Map[R1] is a subset of Map[R2].
+ void computeOverlaps(std::map<const CodeGenRegister*,
+ CodeGenRegister::Set> &Map);
};
}
diff --git a/src/LLVM/utils/TableGen/CodeGenTarget.cpp b/src/LLVM/utils/TableGen/CodeGenTarget.cpp
index cbfe2ad..4a7bad7 100644
--- a/src/LLVM/utils/TableGen/CodeGenTarget.cpp
+++ b/src/LLVM/utils/TableGen/CodeGenTarget.cpp
@@ -16,7 +16,7 @@
#include "CodeGenTarget.h"
#include "CodeGenIntrinsics.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/CommandLine.h"
@@ -48,47 +48,49 @@
std::string llvm::getEnumName(MVT::SimpleValueType T) {
switch (T) {
- case MVT::Other: return "MVT::Other";
- case MVT::i1: return "MVT::i1";
- case MVT::i8: return "MVT::i8";
- case MVT::i16: return "MVT::i16";
- case MVT::i32: return "MVT::i32";
- case MVT::i64: return "MVT::i64";
- case MVT::i128: return "MVT::i128";
- case MVT::iAny: return "MVT::iAny";
- case MVT::fAny: return "MVT::fAny";
- case MVT::vAny: return "MVT::vAny";
- case MVT::f32: return "MVT::f32";
- case MVT::f64: return "MVT::f64";
- case MVT::f80: return "MVT::f80";
- case MVT::f128: return "MVT::f128";
+ case MVT::Other: return "MVT::Other";
+ case MVT::i1: return "MVT::i1";
+ case MVT::i8: return "MVT::i8";
+ case MVT::i16: return "MVT::i16";
+ case MVT::i32: return "MVT::i32";
+ case MVT::i64: return "MVT::i64";
+ case MVT::i128: return "MVT::i128";
+ case MVT::iAny: return "MVT::iAny";
+ case MVT::fAny: return "MVT::fAny";
+ case MVT::vAny: return "MVT::vAny";
+ case MVT::f32: return "MVT::f32";
+ case MVT::f64: return "MVT::f64";
+ case MVT::f80: return "MVT::f80";
+ case MVT::f128: return "MVT::f128";
case MVT::ppcf128: return "MVT::ppcf128";
- case MVT::Flag: return "MVT::Flag";
- case MVT::isVoid:return "MVT::isVoid";
- case MVT::v2i8: return "MVT::v2i8";
- case MVT::v4i8: return "MVT::v4i8";
- case MVT::v8i8: return "MVT::v8i8";
- case MVT::v16i8: return "MVT::v16i8";
- case MVT::v32i8: return "MVT::v32i8";
- case MVT::v2i16: return "MVT::v2i16";
- case MVT::v4i16: return "MVT::v4i16";
- case MVT::v8i16: return "MVT::v8i16";
- case MVT::v16i16: return "MVT::v16i16";
- case MVT::v2i32: return "MVT::v2i32";
- case MVT::v4i32: return "MVT::v4i32";
- case MVT::v8i32: return "MVT::v8i32";
- case MVT::v1i64: return "MVT::v1i64";
- case MVT::v2i64: return "MVT::v2i64";
- case MVT::v4i64: return "MVT::v4i64";
- case MVT::v8i64: return "MVT::v8i64";
- case MVT::v2f32: return "MVT::v2f32";
- case MVT::v4f32: return "MVT::v4f32";
- case MVT::v8f32: return "MVT::v8f32";
- case MVT::v2f64: return "MVT::v2f64";
- case MVT::v4f64: return "MVT::v4f64";
+ case MVT::x86mmx: return "MVT::x86mmx";
+ case MVT::Glue: return "MVT::Glue";
+ case MVT::isVoid: return "MVT::isVoid";
+ case MVT::v2i8: return "MVT::v2i8";
+ case MVT::v4i8: return "MVT::v4i8";
+ case MVT::v8i8: return "MVT::v8i8";
+ case MVT::v16i8: return "MVT::v16i8";
+ case MVT::v32i8: return "MVT::v32i8";
+ case MVT::v2i16: return "MVT::v2i16";
+ case MVT::v4i16: return "MVT::v4i16";
+ case MVT::v8i16: return "MVT::v8i16";
+ case MVT::v16i16: return "MVT::v16i16";
+ case MVT::v2i32: return "MVT::v2i32";
+ case MVT::v4i32: return "MVT::v4i32";
+ case MVT::v8i32: return "MVT::v8i32";
+ case MVT::v1i64: return "MVT::v1i64";
+ case MVT::v2i64: return "MVT::v2i64";
+ case MVT::v4i64: return "MVT::v4i64";
+ case MVT::v8i64: return "MVT::v8i64";
+ case MVT::v2f32: return "MVT::v2f32";
+ case MVT::v4f32: return "MVT::v4f32";
+ case MVT::v8f32: return "MVT::v8f32";
+ case MVT::v2f64: return "MVT::v2f64";
+ case MVT::v4f64: return "MVT::v4f64";
case MVT::Metadata: return "MVT::Metadata";
- case MVT::iPTR: return "MVT::iPTR";
+ case MVT::iPTR: return "MVT::iPTR";
case MVT::iPTRAny: return "MVT::iPTRAny";
+ case MVT::untyped: return "MVT::untyped";
default: assert(0 && "ILLEGAL VALUE TYPE!"); return "";
}
}
@@ -97,17 +99,18 @@
/// namespace qualifier if the record contains one.
///
std::string llvm::getQualifiedName(const Record *R) {
- std::string Namespace = R->getValueAsString("Namespace");
+ std::string Namespace;
+ if (R->getValue("Namespace"))
+ Namespace = R->getValueAsString("Namespace");
if (Namespace.empty()) return R->getName();
return Namespace + "::" + R->getName();
}
-
-
/// getTarget - Return the current instance of the Target class.
///
-CodeGenTarget::CodeGenTarget() {
+CodeGenTarget::CodeGenTarget(RecordKeeper &records)
+ : Records(records), RegBank(0) {
std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");
if (Targets.size() == 0)
throw std::string("ERROR: No 'Target' subclasses defined!");
@@ -155,54 +158,41 @@
return LI[AsmWriterNum];
}
-void CodeGenTarget::ReadRegisters() const {
- std::vector<Record*> Regs = Records.getAllDerivedDefinitions("Register");
- if (Regs.empty())
- throw std::string("No 'Register' subclasses defined!");
- std::sort(Regs.begin(), Regs.end(), LessRecord());
-
- Registers.reserve(Regs.size());
- Registers.assign(Regs.begin(), Regs.end());
+CodeGenRegBank &CodeGenTarget::getRegBank() const {
+ if (!RegBank)
+ RegBank = new CodeGenRegBank(Records);
+ return *RegBank;
}
-CodeGenRegister::CodeGenRegister(Record *R) : TheDef(R) {
- DeclaredSpillSize = R->getValueAsInt("SpillSize");
- DeclaredSpillAlignment = R->getValueAsInt("SpillAlignment");
+void CodeGenTarget::ReadRegAltNameIndices() const {
+ RegAltNameIndices = Records.getAllDerivedDefinitions("RegAltNameIndex");
+ std::sort(RegAltNameIndices.begin(), RegAltNameIndices.end(), LessRecord());
}
-const std::string &CodeGenRegister::getName() const {
- return TheDef->getName();
-}
+/// getRegisterByName - If there is a register with the specific AsmName,
+/// return it.
+const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {
+ const std::vector<CodeGenRegister*> &Regs = getRegBank().getRegisters();
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i)
+ if (Regs[i]->TheDef->getValueAsString("AsmName") == Name)
+ return Regs[i];
-void CodeGenTarget::ReadSubRegIndices() const {
- SubRegIndices = Records.getAllDerivedDefinitions("SubRegIndex");
- std::sort(SubRegIndices.begin(), SubRegIndices.end(), LessRecord());
-}
-
-void CodeGenTarget::ReadRegisterClasses() const {
- std::vector<Record*> RegClasses =
- Records.getAllDerivedDefinitions("RegisterClass");
- if (RegClasses.empty())
- throw std::string("No 'RegisterClass' subclasses defined!");
-
- RegisterClasses.reserve(RegClasses.size());
- RegisterClasses.assign(RegClasses.begin(), RegClasses.end());
+ return 0;
}
std::vector<MVT::SimpleValueType> CodeGenTarget::
getRegisterVTs(Record *R) const {
+ const CodeGenRegister *Reg = getRegBank().getReg(R);
std::vector<MVT::SimpleValueType> Result;
- const std::vector<CodeGenRegisterClass> &RCs = getRegisterClasses();
+ ArrayRef<CodeGenRegisterClass*> RCs = getRegBank().getRegClasses();
for (unsigned i = 0, e = RCs.size(); i != e; ++i) {
- const CodeGenRegisterClass &RC = RegisterClasses[i];
- for (unsigned ei = 0, ee = RC.Elements.size(); ei != ee; ++ei) {
- if (R == RC.Elements[ei]) {
- const std::vector<MVT::SimpleValueType> &InVTs = RC.getValueTypes();
- Result.insert(Result.end(), InVTs.begin(), InVTs.end());
- }
+ const CodeGenRegisterClass &RC = *RCs[i];
+ if (RC.contains(Reg)) {
+ const std::vector<MVT::SimpleValueType> &InVTs = RC.getValueTypes();
+ Result.insert(Result.end(), InVTs.begin(), InVTs.end());
}
}
-
+
// Remove duplicates.
array_pod_sort(Result.begin(), Result.end());
Result.erase(std::unique(Result.begin(), Result.end()), Result.end());
@@ -210,76 +200,12 @@
}
-CodeGenRegisterClass::CodeGenRegisterClass(Record *R) : TheDef(R) {
- // Rename anonymous register classes.
- if (R->getName().size() > 9 && R->getName()[9] == '.') {
- static unsigned AnonCounter = 0;
- R->setName("AnonRegClass_"+utostr(AnonCounter++));
- }
-
- std::vector<Record*> TypeList = R->getValueAsListOfDefs("RegTypes");
- for (unsigned i = 0, e = TypeList.size(); i != e; ++i) {
- Record *Type = TypeList[i];
- if (!Type->isSubClassOf("ValueType"))
- throw "RegTypes list member '" + Type->getName() +
- "' does not derive from the ValueType class!";
- VTs.push_back(getValueType(Type));
- }
- assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!");
-
- std::vector<Record*> RegList = R->getValueAsListOfDefs("MemberList");
- for (unsigned i = 0, e = RegList.size(); i != e; ++i) {
- Record *Reg = RegList[i];
- if (!Reg->isSubClassOf("Register"))
- throw "Register Class member '" + Reg->getName() +
- "' does not derive from the Register class!";
- Elements.push_back(Reg);
- }
-
- // SubRegClasses is a list<dag> containing (RC, subregindex, ...) dags.
- ListInit *SRC = R->getValueAsListInit("SubRegClasses");
- for (ListInit::const_iterator i = SRC->begin(), e = SRC->end(); i != e; ++i) {
- DagInit *DAG = dynamic_cast<DagInit*>(*i);
- if (!DAG) throw "SubRegClasses must contain DAGs";
- DefInit *DAGOp = dynamic_cast<DefInit*>(DAG->getOperator());
- Record *RCRec;
- if (!DAGOp || !(RCRec = DAGOp->getDef())->isSubClassOf("RegisterClass"))
- throw "Operator '" + DAG->getOperator()->getAsString() +
- "' in SubRegClasses is not a RegisterClass";
- // Iterate over args, all SubRegIndex instances.
- for (DagInit::const_arg_iterator ai = DAG->arg_begin(), ae = DAG->arg_end();
- ai != ae; ++ai) {
- DefInit *Idx = dynamic_cast<DefInit*>(*ai);
- Record *IdxRec;
- if (!Idx || !(IdxRec = Idx->getDef())->isSubClassOf("SubRegIndex"))
- throw "Argument '" + (*ai)->getAsString() +
- "' in SubRegClasses is not a SubRegIndex";
- if (!SubRegClasses.insert(std::make_pair(IdxRec, RCRec)).second)
- throw "SubRegIndex '" + IdxRec->getName() + "' mentioned twice";
- }
- }
-
- // Allow targets to override the size in bits of the RegisterClass.
- unsigned Size = R->getValueAsInt("Size");
-
- Namespace = R->getValueAsString("Namespace");
- SpillSize = Size ? Size : EVT(VTs[0]).getSizeInBits();
- SpillAlignment = R->getValueAsInt("Alignment");
- CopyCost = R->getValueAsInt("CopyCost");
- MethodBodies = R->getValueAsCode("MethodBodies");
- MethodProtos = R->getValueAsCode("MethodProtos");
-}
-
-const std::string &CodeGenRegisterClass::getName() const {
- return TheDef->getName();
-}
-
void CodeGenTarget::ReadLegalValueTypes() const {
- const std::vector<CodeGenRegisterClass> &RCs = getRegisterClasses();
+ ArrayRef<CodeGenRegisterClass*> RCs = getRegBank().getRegClasses();
for (unsigned i = 0, e = RCs.size(); i != e; ++i)
- for (unsigned ri = 0, re = RCs[i].VTs.size(); ri != re; ++ri)
- LegalValueTypes.push_back(RCs[i].VTs[ri]);
-
+ for (unsigned ri = 0, re = RCs[i]->VTs.size(); ri != re; ++ri)
+ LegalValueTypes.push_back(RCs[i]->VTs[ri]);
+
// Remove duplicates.
std::sort(LegalValueTypes.begin(), LegalValueTypes.end());
LegalValueTypes.erase(std::unique(LegalValueTypes.begin(),
@@ -294,20 +220,16 @@
throw std::string("No 'Instruction' subclasses defined!");
// Parse the instructions defined in the .td file.
- std::string InstFormatName =
- getAsmWriter()->getValueAsString("InstFormatName");
-
- for (unsigned i = 0, e = Insts.size(); i != e; ++i) {
- std::string AsmStr = Insts[i]->getValueAsString(InstFormatName);
- Instructions[Insts[i]] = new CodeGenInstruction(Insts[i], AsmStr);
- }
+ for (unsigned i = 0, e = Insts.size(); i != e; ++i)
+ Instructions[Insts[i]] = new CodeGenInstruction(Insts[i]);
}
static const CodeGenInstruction *
GetInstByName(const char *Name,
- const DenseMap<const Record*, CodeGenInstruction*> &Insts) {
+ const DenseMap<const Record*, CodeGenInstruction*> &Insts,
+ RecordKeeper &Records) {
const Record *Rec = Records.getDef(Name);
-
+
DenseMap<const Record*, CodeGenInstruction*>::const_iterator
I = Insts.find(Rec);
if (Rec == 0 || I == Insts.end())
@@ -349,7 +271,7 @@
};
const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions();
for (const char *const *p = FixedInstrs; *p; ++p) {
- const CodeGenInstruction *Instr = GetInstByName(*p, Insts);
+ const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records);
assert(Instr && "Missing target independent instruction");
assert(Instr->Namespace == "TargetOpcode" && "Bad namespace");
InstrsByEnum.push_back(Instr);
@@ -394,8 +316,8 @@
for (unsigned i = 0, e = PropList.size(); i != e; ++i)
if (PropList[i]->getName() == "SDNPHasChain") {
Properties |= 1 << SDNPHasChain;
- } else if (PropList[i]->getName() == "SDNPOptInFlag") {
- Properties |= 1 << SDNPOptInFlag;
+ } else if (PropList[i]->getName() == "SDNPOptInGlue") {
+ Properties |= 1 << SDNPOptInGlue;
} else if (PropList[i]->getName() == "SDNPMayStore") {
Properties |= 1 << SDNPMayStore;
} else if (PropList[i]->getName() == "SDNPMayLoad") {
@@ -406,6 +328,10 @@
Properties |= 1 << SDNPMemOperand;
} else if (PropList[i]->getName() == "SDNPVariadic") {
Properties |= 1 << SDNPVariadic;
+ } else if (PropList[i]->getName() == "SDNPWantRoot") {
+ Properties |= 1 << SDNPWantRoot;
+ } else if (PropList[i]->getName() == "SDNPWantParent") {
+ Properties |= 1 << SDNPWantParent;
} else {
errs() << "Unsupported SD Node property '" << PropList[i]->getName()
<< "' on ComplexPattern '" << R->getName() << "'!\n";
@@ -420,7 +346,7 @@
std::vector<CodeGenIntrinsic> llvm::LoadIntrinsics(const RecordKeeper &RC,
bool TargetOnly) {
std::vector<Record*> I = RC.getAllDerivedDefinitions("Intrinsic");
-
+
std::vector<CodeGenIntrinsic> Result;
for (unsigned i = 0, e = I.size(); i != e; ++i) {
@@ -437,8 +363,9 @@
ModRef = ReadWriteMem;
isOverloaded = false;
isCommutative = false;
-
- if (DefName.size() <= 4 ||
+ canThrow = false;
+
+ if (DefName.size() <= 4 ||
std::string(DefName.begin(), DefName.begin() + 4) != "int_")
throw "Intrinsic '" + DefName + "' does not start with 'int_'!";
@@ -458,11 +385,11 @@
Name += (EnumName[i] == '_') ? '.' : EnumName[i];
} else {
// Verify it starts with "llvm.".
- if (Name.size() <= 5 ||
+ if (Name.size() <= 5 ||
std::string(Name.begin(), Name.begin() + 5) != "llvm.")
throw "Intrinsic '" + DefName + "'s name does not start with 'llvm.'!";
}
-
+
// If TargetPrefix is specified, make sure that Name starts with
// "llvm.<targetprefix>.".
if (!TargetPrefix.empty()) {
@@ -472,7 +399,7 @@
throw "Intrinsic '" + DefName + "' does not start with 'llvm." +
TargetPrefix + ".'!";
}
-
+
// Parse the list of return types.
std::vector<MVT::SimpleValueType> OverloadedVTs;
ListInit *TypeList = R->getValueAsListInit("RetTypes");
@@ -503,11 +430,11 @@
// Reject invalid types.
if (VT == MVT::isVoid)
throw "Intrinsic '" + DefName + " has void in result type list!";
-
+
IS.RetVTs.push_back(VT);
IS.RetTypeDefs.push_back(TyEl);
}
-
+
// Parse the list of parameter types.
TypeList = R->getValueAsListInit("ParamTypes");
for (unsigned i = 0, e = TypeList->getSize(); i != e; ++i) {
@@ -528,16 +455,16 @@
"Expected iAny or vAny type");
} else
VT = getValueType(TyEl->getValueAsDef("VT"));
-
+
if (EVT(VT).isOverloaded()) {
OverloadedVTs.push_back(VT);
isOverloaded = true;
}
-
+
// Reject invalid types.
if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/)
throw "Intrinsic '" + DefName + " has void in result type list!";
-
+
IS.ParamVTs.push_back(VT);
IS.ParamTypeDefs.push_back(TyEl);
}
@@ -548,7 +475,7 @@
Record *Property = PropList->getElementAsRecord(i);
assert(Property->isSubClassOf("IntrinsicProperty") &&
"Expected a property!");
-
+
if (Property->getName() == "IntrNoMem")
ModRef = NoMem;
else if (Property->getName() == "IntrReadArgMem")
@@ -559,10 +486,15 @@
ModRef = ReadWriteArgMem;
else if (Property->getName() == "Commutative")
isCommutative = true;
+ else if (Property->getName() == "Throws")
+ canThrow = true;
else if (Property->isSubClassOf("NoCapture")) {
unsigned ArgNo = Property->getValueAsInt("ArgNo");
ArgumentAttributes.push_back(std::make_pair(ArgNo, NoCapture));
} else
assert(0 && "Unknown property!");
}
+
+ // Sort the argument attributes for later benefit.
+ std::sort(ArgumentAttributes.begin(), ArgumentAttributes.end());
}
diff --git a/src/LLVM/utils/TableGen/CodeGenTarget.h b/src/LLVM/utils/TableGen/CodeGenTarget.h
index 6b06b66..730216c 100644
--- a/src/LLVM/utils/TableGen/CodeGenTarget.h
+++ b/src/LLVM/utils/TableGen/CodeGenTarget.h
@@ -19,7 +19,7 @@
#include "CodeGenRegisters.h"
#include "CodeGenInstruction.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -32,17 +32,19 @@
// SDNPMemOperand: indicates that a node touches memory and therefore must
// have an associated memory operand that describes the access.
enum SDNP {
- SDNPCommutative,
- SDNPAssociative,
+ SDNPCommutative,
+ SDNPAssociative,
SDNPHasChain,
- SDNPOutFlag,
- SDNPInFlag,
- SDNPOptInFlag,
+ SDNPOutGlue,
+ SDNPInGlue,
+ SDNPOptInGlue,
SDNPMayLoad,
SDNPMayStore,
SDNPSideEffect,
SDNPMemOperand,
- SDNPVariadic
+ SDNPVariadic,
+ SDNPWantRoot,
+ SDNPWantParent
};
/// getValueType - Return the MVT::SimpleValueType that the specified TableGen
@@ -55,26 +57,24 @@
/// getQualifiedName - Return the name of the specified record, with a
/// namespace qualifier if the record contains one.
std::string getQualifiedName(const Record *R);
-
+
/// CodeGenTarget - This class corresponds to the Target class in the .td files.
///
class CodeGenTarget {
+ RecordKeeper &Records;
Record *TargetRec;
mutable DenseMap<const Record*, CodeGenInstruction*> Instructions;
- mutable std::vector<CodeGenRegister> Registers;
- mutable std::vector<Record*> SubRegIndices;
- mutable std::vector<CodeGenRegisterClass> RegisterClasses;
+ mutable CodeGenRegBank *RegBank;
+ mutable std::vector<Record*> RegAltNameIndices;
mutable std::vector<MVT::SimpleValueType> LegalValueTypes;
- void ReadRegisters() const;
- void ReadSubRegIndices() const;
- void ReadRegisterClasses() const;
+ void ReadRegAltNameIndices() const;
void ReadInstructions() const;
void ReadLegalValueTypes() const;
-
+
mutable std::vector<const CodeGenInstruction*> InstrsByEnum;
public:
- CodeGenTarget();
+ CodeGenTarget(RecordKeeper &Records);
Record *getTargetRecord() const { return TargetRec; }
const std::string &getName() const;
@@ -95,109 +95,38 @@
///
Record *getAsmWriter() const;
- const std::vector<CodeGenRegister> &getRegisters() const {
- if (Registers.empty()) ReadRegisters();
- return Registers;
- }
+ /// getRegBank - Return the register bank description.
+ CodeGenRegBank &getRegBank() const;
- const std::vector<Record*> &getSubRegIndices() const {
- if (SubRegIndices.empty()) ReadSubRegIndices();
- return SubRegIndices;
- }
+ /// getRegisterByName - If there is a register with the specific AsmName,
+ /// return it.
+ const CodeGenRegister *getRegisterByName(StringRef Name) const;
- // Map a SubRegIndex Record to its number.
- unsigned getSubRegIndexNo(Record *idx) const {
- if (SubRegIndices.empty()) ReadSubRegIndices();
- std::vector<Record*>::const_iterator i =
- std::find(SubRegIndices.begin(), SubRegIndices.end(), idx);
- assert(i != SubRegIndices.end() && "Not a SubRegIndex");
- return (i - SubRegIndices.begin()) + 1;
- }
-
- const std::vector<CodeGenRegisterClass> &getRegisterClasses() const {
- if (RegisterClasses.empty()) ReadRegisterClasses();
- return RegisterClasses;
+ const std::vector<Record*> &getRegAltNameIndices() const {
+ if (RegAltNameIndices.empty()) ReadRegAltNameIndices();
+ return RegAltNameIndices;
}
const CodeGenRegisterClass &getRegisterClass(Record *R) const {
- const std::vector<CodeGenRegisterClass> &RC = getRegisterClasses();
- for (unsigned i = 0, e = RC.size(); i != e; ++i)
- if (RC[i].TheDef == R)
- return RC[i];
- assert(0 && "Didn't find the register class");
- abort();
- }
-
- /// getRegisterClassForRegister - Find the register class that contains the
- /// specified physical register. If the register is not in a register
- /// class, return null. If the register is in multiple classes, and the
- /// classes have a superset-subset relationship and the same set of
- /// types, return the superclass. Otherwise return null.
- const CodeGenRegisterClass *getRegisterClassForRegister(Record *R) const {
- const std::vector<CodeGenRegisterClass> &RCs = getRegisterClasses();
- const CodeGenRegisterClass *FoundRC = 0;
- for (unsigned i = 0, e = RCs.size(); i != e; ++i) {
- const CodeGenRegisterClass &RC = RegisterClasses[i];
- for (unsigned ei = 0, ee = RC.Elements.size(); ei != ee; ++ei) {
- if (R != RC.Elements[ei])
- continue;
-
- // If a register's classes have different types, return null.
- if (FoundRC && RC.getValueTypes() != FoundRC->getValueTypes())
- return 0;
-
- // If this is the first class that contains the register,
- // make a note of it and go on to the next class.
- if (!FoundRC) {
- FoundRC = &RC;
- break;
- }
-
- std::vector<Record *> Elements(RC.Elements);
- std::vector<Record *> FoundElements(FoundRC->Elements);
- std::sort(Elements.begin(), Elements.end());
- std::sort(FoundElements.begin(), FoundElements.end());
-
- // Check to see if the previously found class that contains
- // the register is a subclass of the current class. If so,
- // prefer the superclass.
- if (std::includes(Elements.begin(), Elements.end(),
- FoundElements.begin(), FoundElements.end())) {
- FoundRC = &RC;
- break;
- }
-
- // Check to see if the previously found class that contains
- // the register is a superclass of the current class. If so,
- // prefer the superclass.
- if (std::includes(FoundElements.begin(), FoundElements.end(),
- Elements.begin(), Elements.end()))
- break;
-
- // Multiple classes, and neither is a superclass of the other.
- // Return null.
- return 0;
- }
- }
- return FoundRC;
+ return *getRegBank().getRegClass(R);
}
/// getRegisterVTs - Find the union of all possible SimpleValueTypes for the
/// specified physical register.
std::vector<MVT::SimpleValueType> getRegisterVTs(Record *R) const;
-
+
const std::vector<MVT::SimpleValueType> &getLegalValueTypes() const {
if (LegalValueTypes.empty()) ReadLegalValueTypes();
return LegalValueTypes;
}
-
+
/// isLegalValueType - Return true if the specified value type is natively
/// supported by the target (i.e. there are registers that directly hold it).
bool isLegalValueType(MVT::SimpleValueType VT) const {
const std::vector<MVT::SimpleValueType> &LegalVTs = getLegalValueTypes();
for (unsigned i = 0, e = LegalVTs.size(); i != e; ++i)
if (LegalVTs[i] == VT) return true;
- return false;
+ return false;
}
private:
@@ -206,7 +135,7 @@
return Instructions;
}
public:
-
+
CodeGenInstruction &getInstruction(const Record *InstRec) const {
if (Instructions.empty()) ReadInstructions();
DenseMap<const Record*, CodeGenInstruction*>::iterator I =
@@ -226,12 +155,12 @@
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(); }
-
-
+
+
/// isLittleEndianEncoding - are instruction bit patterns defined as [0..n]?
///
bool isLittleEndianEncoding() const;
-
+
private:
void ComputeInstrsByEnum() const;
};
diff --git a/src/LLVM/utils/TableGen/DAGISelEmitter.cpp b/src/LLVM/utils/TableGen/DAGISelEmitter.cpp
index 04c7710..7db9003 100644
--- a/src/LLVM/utils/TableGen/DAGISelEmitter.cpp
+++ b/src/LLVM/utils/TableGen/DAGISelEmitter.cpp
@@ -13,7 +13,7 @@
#include "DAGISelEmitter.h"
#include "DAGISelMatcher.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/Support/Debug.h"
using namespace llvm;
@@ -27,7 +27,7 @@
static unsigned getResultPatternCost(TreePatternNode *P,
CodeGenDAGPatterns &CGP) {
if (P->isLeaf()) return 0;
-
+
unsigned Cost = 0;
Record *Op = P->getOperator();
if (Op->isSubClassOf("Instruction")) {
@@ -43,7 +43,7 @@
/// getResultPatternCodeSize - Compute the code size of instructions for this
/// pattern.
-static unsigned getResultPatternSize(TreePatternNode *P,
+static unsigned getResultPatternSize(TreePatternNode *P,
CodeGenDAGPatterns &CGP) {
if (P->isLeaf()) return 0;
@@ -57,51 +57,6 @@
return Cost;
}
-//===----------------------------------------------------------------------===//
-// Predicate emitter implementation.
-//
-
-void DAGISelEmitter::EmitPredicateFunctions(raw_ostream &OS) {
- OS << "\n// Predicate functions.\n";
-
- // Walk the pattern fragments, adding them to a map, which sorts them by
- // name.
- typedef std::map<std::string, std::pair<Record*, TreePattern*> > PFsByNameTy;
- PFsByNameTy PFsByName;
-
- for (CodeGenDAGPatterns::pf_iterator I = CGP.pf_begin(), E = CGP.pf_end();
- I != E; ++I)
- PFsByName.insert(std::make_pair(I->first->getName(), *I));
-
-
- for (PFsByNameTy::iterator I = PFsByName.begin(), E = PFsByName.end();
- I != E; ++I) {
- Record *PatFragRecord = I->second.first;// Record that derives from PatFrag.
- TreePattern *P = I->second.second;
-
- // If there is a code init for this fragment, emit the predicate code.
- std::string Code = PatFragRecord->getValueAsCode("Predicate");
- if (Code.empty()) continue;
-
- if (P->getOnlyTree()->isLeaf())
- OS << "inline bool Predicate_" << PatFragRecord->getName()
- << "(SDNode *N) const {\n";
- else {
- std::string ClassName =
- CGP.getSDNodeInfo(P->getOnlyTree()->getOperator()).getSDClassName();
- const char *C2 = ClassName == "SDNode" ? "N" : "inN";
-
- OS << "inline bool Predicate_" << PatFragRecord->getName()
- << "(SDNode *" << C2 << ") const {\n";
- if (ClassName != "SDNode")
- OS << " " << ClassName << " *N = cast<" << ClassName << ">(inN);\n";
- }
- OS << Code << "\n}\n";
- }
-
- OS << "\n\n";
-}
-
namespace {
// PatternSortingPredicate - return true if we prefer to match LHS before RHS.
// In particular, we want to match maximal patterns first and lowest cost within
@@ -109,21 +64,21 @@
struct PatternSortingPredicate {
PatternSortingPredicate(CodeGenDAGPatterns &cgp) : CGP(cgp) {}
CodeGenDAGPatterns &CGP;
-
+
bool operator()(const PatternToMatch *LHS, const PatternToMatch *RHS) {
const TreePatternNode *LHSSrc = LHS->getSrcPattern();
const TreePatternNode *RHSSrc = RHS->getSrcPattern();
-
+
if (LHSSrc->getNumTypes() != 0 && RHSSrc->getNumTypes() != 0 &&
LHSSrc->getType(0) != RHSSrc->getType(0)) {
MVT::SimpleValueType V1 = LHSSrc->getType(0), V2 = RHSSrc->getType(0);
if (MVT(V1).isVector() != MVT(V2).isVector())
return MVT(V2).isVector();
-
+
if (MVT(V1).isFloatingPoint() != MVT(V2).isFloatingPoint())
return MVT(V2).isFloatingPoint();
}
-
+
// Otherwise, if the patterns might both match, sort based on complexity,
// which means that we prefer to match patterns that cover more nodes in the
// input over nodes that cover fewer.
@@ -131,18 +86,18 @@
unsigned RHSSize = RHS->getPatternComplexity(CGP);
if (LHSSize > RHSSize) return true; // LHS -> bigger -> less cost
if (LHSSize < RHSSize) return false;
-
+
// If the patterns have equal complexity, compare generated instruction cost
unsigned LHSCost = getResultPatternCost(LHS->getDstPattern(), CGP);
unsigned RHSCost = getResultPatternCost(RHS->getDstPattern(), CGP);
if (LHSCost < RHSCost) return true;
if (LHSCost > RHSCost) return false;
-
+
unsigned LHSPatSize = getResultPatternSize(LHS->getDstPattern(), CGP);
unsigned RHSPatSize = getResultPatternSize(RHS->getDstPattern(), CGP);
if (LHSPatSize < RHSPatSize) return true;
if (LHSPatSize > RHSPatSize) return false;
-
+
// Sort based on the UID of the pattern, giving us a deterministic ordering
// if all other sorting conditions fail.
assert(LHS == RHS || LHS->ID != RHS->ID);
@@ -155,7 +110,7 @@
void DAGISelEmitter::run(raw_ostream &OS) {
EmitSourceFileHeader("DAG Instruction Selector for the " +
CGP.getTargetInfo().getName() + " target", OS);
-
+
OS << "// *** NOTE: This file is #included into the middle of the target\n"
<< "// *** instruction selector class. These functions are really "
<< "methods.\n\n";
@@ -168,9 +123,6 @@
errs() << "\n";
});
- // FIXME: These are being used by hand written code, gross.
- EmitPredicateFunctions(OS);
-
// Add all the patterns to a temporary list so we can sort them.
std::vector<const PatternToMatch*> Patterns;
for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(), E = CGP.ptm_end();
@@ -180,8 +132,8 @@
// We want to process the matches in order of minimal cost. Sort the patterns
// so the least cost one is at the start.
std::sort(Patterns.begin(), Patterns.end(), PatternSortingPredicate(CGP));
-
-
+
+
// Convert each variant of each pattern into a Matcher.
std::vector<Matcher*> PatternMatchers;
for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
@@ -192,7 +144,7 @@
break;
}
}
-
+
Matcher *TheMatcher = new ScopeMatcher(&PatternMatchers[0],
PatternMatchers.size());
diff --git a/src/LLVM/utils/TableGen/DAGISelEmitter.h b/src/LLVM/utils/TableGen/DAGISelEmitter.h
index 5ffdde8..9c9fe42 100644
--- a/src/LLVM/utils/TableGen/DAGISelEmitter.h
+++ b/src/LLVM/utils/TableGen/DAGISelEmitter.h
@@ -14,9 +14,8 @@
#ifndef DAGISEL_EMITTER_H
#define DAGISEL_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include "CodeGenDAGPatterns.h"
-#include <set>
namespace llvm {
@@ -31,8 +30,6 @@
// run - Output the isel, returning true on failure.
void run(raw_ostream &OS);
-private:
- void EmitPredicateFunctions(raw_ostream &OS);
};
} // End llvm namespace
diff --git a/src/LLVM/utils/TableGen/DAGISelMatcher.cpp b/src/LLVM/utils/TableGen/DAGISelMatcher.cpp
index 9f12a68..1367e8d 100644
--- a/src/LLVM/utils/TableGen/DAGISelMatcher.cpp
+++ b/src/LLVM/utils/TableGen/DAGISelMatcher.cpp
@@ -10,7 +10,7 @@
#include "DAGISelMatcher.h"
#include "CodeGenDAGPatterns.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/StringExtras.h"
using namespace llvm;
@@ -35,7 +35,7 @@
Matcher *Matcher::unlinkNode(Matcher *Other) {
if (this == Other)
return takeNext();
-
+
// Scan until we find the predecessor of Other.
Matcher *Cur = this;
for (; Cur && Cur->getNext() != Other; Cur = Cur->getNext())
@@ -67,11 +67,11 @@
// We can move simple predicates before record nodes.
if (isSimplePredicateNode())
return Other->isSimplePredicateOrRecordNode();
-
+
// We can move record nodes across simple predicates.
if (isSimplePredicateOrRecordNode())
return isSimplePredicateNode();
-
+
// We can't move record nodes across each other etc.
return false;
}
@@ -83,6 +83,15 @@
}
+CheckPredicateMatcher::CheckPredicateMatcher(const TreePredicateFn &pred)
+ : Matcher(CheckPredicate), Pred(pred.getOrigPatFragRecord()) {}
+
+TreePredicateFn CheckPredicateMatcher::getPredicate() const {
+ return TreePredicateFn(Pred);
+}
+
+
+
// printImpl methods.
void ScopeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
@@ -107,8 +116,8 @@
OS.indent(indent) << "RecordMemRef\n";
}
-void CaptureFlagInputMatcher::printImpl(raw_ostream &OS, unsigned indent) const{
- OS.indent(indent) << "CaptureFlagInput\n";
+void CaptureGlueInputMatcher::printImpl(raw_ostream &OS, unsigned indent) const{
+ OS.indent(indent) << "CaptureGlueInput\n";
}
void MoveChildMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
@@ -129,7 +138,7 @@
}
void CheckPredicateMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
- OS.indent(indent) << "CheckPredicate " << PredName << '\n';
+ OS.indent(indent) << "CheckPredicate " << getPredicate().getFnName() << '\n';
}
void CheckOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
@@ -246,8 +255,8 @@
OS << ")\n";
}
-void MarkFlagResultsMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
- OS.indent(indent) << "MarkFlagResults <todo: args>\n";
+void MarkGlueResultsMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "MarkGlueResults <todo: args>\n";
}
void CompleteMatchMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
@@ -263,7 +272,7 @@
}
unsigned CheckPredicateMatcher::getHashImpl() const {
- return HashString(PredName);
+ return HashString(getPredicate().getFnName());
}
unsigned CheckOpcodeMatcher::getHashImpl() const {
@@ -296,17 +305,16 @@
bool CheckOpcodeMatcher::isEqualImpl(const Matcher *M) const {
// Note: pointer equality isn't enough here, we have to check the enum names
- // to ensure that the nodes are for the same opcode.
+ // to ensure that the nodes are for the same opcode.
return cast<CheckOpcodeMatcher>(M)->Opcode.getEnumName() ==
Opcode.getEnumName();
}
-
bool EmitNodeMatcherCommon::isEqualImpl(const Matcher *m) const {
const EmitNodeMatcherCommon *M = cast<EmitNodeMatcherCommon>(m);
return M->OpcodeName == OpcodeName && M->VTs == VTs &&
M->Operands == Operands && M->HasChain == HasChain &&
- M->HasInFlag == HasInFlag && M->HasOutFlag == HasOutFlag &&
+ M->HasInGlue == HasInGlue && M->HasOutGlue == HasOutGlue &&
M->HasMemRefs == HasMemRefs &&
M->NumFixedArityOperands == NumFixedArityOperands;
}
@@ -316,12 +324,12 @@
}
-unsigned MarkFlagResultsMatcher::getHashImpl() const {
- return HashUnsigneds(FlagResultNodes.begin(), FlagResultNodes.end());
+unsigned MarkGlueResultsMatcher::getHashImpl() const {
+ return HashUnsigneds(GlueResultNodes.begin(), GlueResultNodes.end());
}
unsigned CompleteMatchMatcher::getHashImpl() const {
- return HashUnsigneds(Results.begin(), Results.end()) ^
+ return HashUnsigneds(Results.begin(), Results.end()) ^
((unsigned)(intptr_t)&Pattern << 8);
}
@@ -332,15 +340,15 @@
// If the two types are the same, then they are the same, so they don't
// contradict.
if (T1 == T2) return false;
-
+
// If either type is about iPtr, then they don't conflict unless the other
// one is not a scalar integer type.
if (T1 == MVT::iPTR)
return !MVT(T2).isInteger() || MVT(T2).isVector();
-
+
if (T2 == MVT::iPTR)
return !MVT(T1).isInteger() || MVT(T1).isVector();
-
+
// Otherwise, they are two different non-iPTR types, they conflict.
return true;
}
@@ -349,10 +357,10 @@
if (const CheckOpcodeMatcher *COM = dyn_cast<CheckOpcodeMatcher>(M)) {
// One node can't have two different opcodes!
// Note: pointer equality isn't enough here, we have to check the enum names
- // to ensure that the nodes are for the same opcode.
+ // to ensure that the nodes are for the same opcode.
return COM->getOpcode().getEnumName() != getOpcode().getEnumName();
}
-
+
// If the node has a known type, and if the type we're checking for is
// different, then we know they contradict. For example, a check for
// ISD::STORE will never be true at the same time a check for Type i32 is.
@@ -360,12 +368,12 @@
// If checking for a result the opcode doesn't have, it can't match.
if (CT->getResNo() >= getOpcode().getNumResults())
return true;
-
+
MVT::SimpleValueType NodeType = getOpcode().getKnownType(CT->getResNo());
if (NodeType != MVT::Other)
return TypesAreContradictory(NodeType, CT->getType());
}
-
+
return false;
}
@@ -381,12 +389,12 @@
// conflict!
if (CC->getChildNo() != getChildNo())
return false;
-
+
return TypesAreContradictory(getType(), CC->getType());
}
return false;
}
-
+
bool CheckIntegerMatcher::isContradictoryImpl(const Matcher *M) const {
if (const CheckIntegerMatcher *CIM = dyn_cast<CheckIntegerMatcher>(M))
return CIM->getValue() != getValue();
diff --git a/src/LLVM/utils/TableGen/DAGISelMatcher.h b/src/LLVM/utils/TableGen/DAGISelMatcher.h
index d9b25d5..dcb8da7 100644
--- a/src/LLVM/utils/TableGen/DAGISelMatcher.h
+++ b/src/LLVM/utils/TableGen/DAGISelMatcher.h
@@ -17,6 +17,7 @@
#include "llvm/Support/Casting.h"
namespace llvm {
+ struct CodeGenRegister;
class CodeGenDAGPatterns;
class Matcher;
class PatternToMatch;
@@ -24,6 +25,8 @@
class ComplexPattern;
class Record;
class SDNodeInfo;
+ class TreePredicateFn;
+ class TreePattern;
Matcher *ConvertPatternToMatcher(const PatternToMatch &Pattern,unsigned Variant,
const CodeGenDAGPatterns &CGP);
@@ -31,7 +34,7 @@
void EmitMatcherTable(const Matcher *Matcher, const CodeGenDAGPatterns &CGP,
raw_ostream &OS);
-
+
/// Matcher - Base class for all the the DAG ISel Matcher representation
/// nodes.
class Matcher {
@@ -45,10 +48,10 @@
RecordNode, // Record the current node.
RecordChild, // Record a child of the current node.
RecordMemRef, // Record the memref in the current node.
- CaptureFlagInput, // If the current node has an input flag, save it.
+ CaptureGlueInput, // If the current node has an input glue, save it.
MoveChild, // Move current node to specified child.
MoveParent, // Move current node to parent.
-
+
// Predicate checking.
CheckSame, // Fail if not same as prev match.
CheckPatternPredicate,
@@ -65,7 +68,7 @@
CheckAndImm,
CheckOrImm,
CheckFoldableChainNode,
-
+
// Node creation/emisssion.
EmitInteger, // Create a TargetConstant
EmitStringInteger, // Create a TargetConstant from a string.
@@ -75,7 +78,7 @@
EmitCopyToReg, // Emit a copytoreg into a physreg.
EmitNode, // Create a DAG node
EmitNodeXForm, // Run a SDNodeXForm
- MarkFlagResults, // Indicate which interior nodes have flag results.
+ MarkGlueResults, // Indicate which interior nodes have glue results.
CompleteMatch, // Finish a match and update the results.
MorphNodeTo // Build a node, finish a match and update results.
};
@@ -85,7 +88,7 @@
Matcher(KindTy K) : Kind(K) {}
public:
virtual ~Matcher() {}
-
+
KindTy getKind() const { return Kind; }
Matcher *getNext() { return Next.get(); }
@@ -94,25 +97,25 @@
Matcher *takeNext() { return Next.take(); }
OwningPtr<Matcher> &getNextPtr() { return Next; }
-
+
static inline bool classof(const Matcher *) { return true; }
-
+
bool isEqual(const Matcher *M) const {
if (getKind() != M->getKind()) return false;
return isEqualImpl(M);
}
-
+
unsigned getHash() const {
// Clear the high bit so we don't conflict with tombstones etc.
return ((getHashImpl() << 4) ^ getKind()) & (~0U>>1);
}
-
+
/// isSafeToReorderWithPatternPredicate - Return true if it is safe to sink a
/// PatternPredicate node past this one.
virtual bool isSafeToReorderWithPatternPredicate() const {
return false;
}
-
+
/// isSimplePredicateNode - Return true if this is a simple predicate that
/// operates on the node or its children without potential side effects or a
/// change of the current node.
@@ -134,28 +137,28 @@
return true;
}
}
-
+
/// isSimplePredicateOrRecordNode - Return true if this is a record node or
/// a simple predicate.
bool isSimplePredicateOrRecordNode() const {
return isSimplePredicateNode() ||
getKind() == RecordNode || getKind() == RecordChild;
}
-
+
/// unlinkNode - Unlink the specified node from this chain. If Other == this,
/// we unlink the next pointer and return it. Otherwise we unlink Other from
/// the list and return this.
Matcher *unlinkNode(Matcher *Other);
-
+
/// canMoveBefore - Return true if this matcher is the same as Other, or if
/// we can move this matcher past all of the nodes in-between Other and this
/// node. Other must be equal to or before this.
bool canMoveBefore(const Matcher *Other) const;
-
+
/// canMoveBefore - Return true if it is safe to move the current matcher
/// across the specified one.
bool canMoveBeforeNode(const Matcher *Other) const;
-
+
/// isContradictory - Return true of these two matchers could never match on
/// the same node.
bool isContradictory(const Matcher *Other) const {
@@ -167,7 +170,7 @@
return isContradictoryImpl(Other);
return Other->isContradictoryImpl(this);
}
-
+
void print(raw_ostream &OS, unsigned indent = 0) const;
void printOne(raw_ostream &OS) const;
void dump() const;
@@ -177,7 +180,7 @@
virtual unsigned getHashImpl() const = 0;
virtual bool isContradictoryImpl(const Matcher *M) const { return false; }
};
-
+
/// ScopeMatcher - This attempts to match each of its children to find the first
/// one that successfully matches. If one child fails, it tries the next child.
/// If none of the children match then this check fails. It never has a 'next'.
@@ -188,12 +191,12 @@
: Matcher(Scope), Children(children, children+numchildren) {
}
virtual ~ScopeMatcher();
-
+
unsigned getNumChildren() const { return Children.size(); }
-
+
Matcher *getChild(unsigned i) { return Children[i]; }
const Matcher *getChild(unsigned i) const { return Children[i]; }
-
+
void resetChild(unsigned i, Matcher *N) {
delete Children[i];
Children[i] = N;
@@ -204,7 +207,7 @@
Children[i] = 0;
return Res;
}
-
+
void setNumChildren(unsigned NC) {
if (NC < Children.size()) {
// delete any children we're about to lose pointers to.
@@ -217,7 +220,7 @@
static inline bool classof(const Matcher *N) {
return N->getKind() == Scope;
}
-
+
private:
virtual void printImpl(raw_ostream &OS, unsigned indent) const;
virtual bool isEqualImpl(const Matcher *M) const { return false; }
@@ -229,38 +232,38 @@
/// WhatFor - This is a string indicating why we're recording this. This
/// should only be used for comment generation not anything semantic.
std::string WhatFor;
-
+
/// ResultNo - The slot number in the RecordedNodes vector that this will be,
/// just printed as a comment.
unsigned ResultNo;
public:
RecordMatcher(const std::string &whatfor, unsigned resultNo)
: Matcher(RecordNode), WhatFor(whatfor), ResultNo(resultNo) {}
-
+
const std::string &getWhatFor() const { return WhatFor; }
unsigned getResultNo() const { return ResultNo; }
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == RecordNode;
}
-
+
virtual bool isSafeToReorderWithPatternPredicate() const { 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; }
};
-
+
/// RecordChildMatcher - Save a numbered child of the current node, or fail
/// the match if it doesn't exist. This is logically equivalent to:
/// MoveChild N + RecordNode + MoveParent.
class RecordChildMatcher : public Matcher {
unsigned ChildNo;
-
+
/// WhatFor - This is a string indicating why we're recording this. This
/// should only be used for comment generation not anything semantic.
std::string WhatFor;
-
+
/// ResultNo - The slot number in the RecordedNodes vector that this will be,
/// just printed as a comment.
unsigned ResultNo;
@@ -269,7 +272,7 @@
unsigned resultNo)
: Matcher(RecordChild), ChildNo(childno), WhatFor(whatfor),
ResultNo(resultNo) {}
-
+
unsigned getChildNo() const { return ChildNo; }
const std::string &getWhatFor() const { return WhatFor; }
unsigned getResultNo() const { return ResultNo; }
@@ -277,7 +280,7 @@
static inline bool classof(const Matcher *N) {
return N->getKind() == RecordChild;
}
-
+
virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
private:
@@ -287,16 +290,16 @@
}
virtual unsigned getHashImpl() const { return getChildNo(); }
};
-
+
/// RecordMemRefMatcher - Save the current node's memref.
class RecordMemRefMatcher : public Matcher {
public:
RecordMemRefMatcher() : Matcher(RecordMemRef) {}
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == RecordMemRef;
}
-
+
virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
private:
@@ -305,17 +308,17 @@
virtual unsigned getHashImpl() const { return 0; }
};
-
-/// CaptureFlagInputMatcher - If the current record has a flag input, record
+
+/// CaptureGlueInputMatcher - If the current record has a glue input, record
/// it so that it is used as an input to the generated code.
-class CaptureFlagInputMatcher : public Matcher {
+class CaptureGlueInputMatcher : public Matcher {
public:
- CaptureFlagInputMatcher() : Matcher(CaptureFlagInput) {}
-
+ CaptureGlueInputMatcher() : Matcher(CaptureGlueInput) {}
+
static inline bool classof(const Matcher *N) {
- return N->getKind() == CaptureFlagInput;
+ return N->getKind() == CaptureGlueInput;
}
-
+
virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
private:
@@ -323,20 +326,20 @@
virtual bool isEqualImpl(const Matcher *M) const { return true; }
virtual unsigned getHashImpl() const { return 0; }
};
-
+
/// MoveChildMatcher - This tells the interpreter to move into the
/// specified child node.
class MoveChildMatcher : public Matcher {
unsigned ChildNo;
public:
MoveChildMatcher(unsigned childNo) : Matcher(MoveChild), ChildNo(childNo) {}
-
+
unsigned getChildNo() const { return ChildNo; }
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == MoveChild;
}
-
+
virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
private:
@@ -346,17 +349,17 @@
}
virtual unsigned getHashImpl() const { return getChildNo(); }
};
-
+
/// MoveParentMatcher - This tells the interpreter to move to the parent
/// of the current node.
class MoveParentMatcher : public Matcher {
public:
MoveParentMatcher() : Matcher(MoveParent) {}
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == MoveParent;
}
-
+
virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
private:
@@ -373,13 +376,13 @@
public:
CheckSameMatcher(unsigned matchnumber)
: Matcher(CheckSame), MatchNumber(matchnumber) {}
-
+
unsigned getMatchNumber() const { return MatchNumber; }
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == CheckSame;
}
-
+
virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
private:
@@ -389,7 +392,7 @@
}
virtual unsigned getHashImpl() const { return getMatchNumber(); }
};
-
+
/// CheckPatternPredicateMatcher - This checks the target-specific predicate
/// to see if the entire pattern is capable of matching. This predicate does
/// not take a node as input. This is used for subtarget feature checks etc.
@@ -398,13 +401,13 @@
public:
CheckPatternPredicateMatcher(StringRef predicate)
: Matcher(CheckPatternPredicate), Predicate(predicate) {}
-
+
StringRef getPredicate() const { return Predicate; }
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == CheckPatternPredicate;
}
-
+
virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
private:
@@ -414,33 +417,32 @@
}
virtual unsigned getHashImpl() const;
};
-
+
/// CheckPredicateMatcher - This checks the target-specific predicate to
/// see if the node is acceptable.
class CheckPredicateMatcher : public Matcher {
- StringRef PredName;
+ TreePattern *Pred;
public:
- CheckPredicateMatcher(StringRef predname)
- : Matcher(CheckPredicate), PredName(predname) {}
-
- StringRef getPredicateName() const { return PredName; }
+ CheckPredicateMatcher(const TreePredicateFn &pred);
+
+ TreePredicateFn getPredicate() const;
static inline bool classof(const Matcher *N) {
return N->getKind() == CheckPredicate;
}
-
+
// TODO: Ok?
//virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
private:
virtual void printImpl(raw_ostream &OS, unsigned indent) const;
virtual bool isEqualImpl(const Matcher *M) const {
- return cast<CheckPredicateMatcher>(M)->PredName == PredName;
+ return cast<CheckPredicateMatcher>(M)->Pred == Pred;
}
virtual unsigned getHashImpl() const;
};
-
-
+
+
/// CheckOpcodeMatcher - This checks to see if the current node has the
/// specified opcode, if not it fails to match.
class CheckOpcodeMatcher : public Matcher {
@@ -448,13 +450,13 @@
public:
CheckOpcodeMatcher(const SDNodeInfo &opcode)
: Matcher(CheckOpcode), Opcode(opcode) {}
-
+
const SDNodeInfo &getOpcode() const { return Opcode; }
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == CheckOpcode;
}
-
+
virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
private:
@@ -478,19 +480,19 @@
static inline bool classof(const Matcher *N) {
return N->getKind() == SwitchOpcode;
}
-
+
unsigned getNumCases() const { return Cases.size(); }
-
+
const SDNodeInfo &getCaseOpcode(unsigned i) const { return *Cases[i].first; }
Matcher *getCaseMatcher(unsigned i) { return Cases[i].second; }
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; }
};
-
+
/// CheckTypeMatcher - This checks to see if the current node has the
/// specified type at the specified result, if not it fails to match.
class CheckTypeMatcher : public Matcher {
@@ -499,14 +501,14 @@
public:
CheckTypeMatcher(MVT::SimpleValueType type, unsigned resno)
: Matcher(CheckType), Type(type), ResNo(resno) {}
-
+
MVT::SimpleValueType getType() const { return Type; }
unsigned getResNo() const { return ResNo; }
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == CheckType;
}
-
+
virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
private:
@@ -517,7 +519,7 @@
virtual unsigned getHashImpl() const { return Type; }
virtual bool isContradictoryImpl(const Matcher *M) const;
};
-
+
/// SwitchTypeMatcher - Switch based on the current node's type, dispatching
/// to one matcher per case. If the type doesn't match any of the cases,
/// then the match fails. This is semantically equivalent to a Scope node where
@@ -528,24 +530,24 @@
SwitchTypeMatcher(const std::pair<MVT::SimpleValueType, Matcher*> *cases,
unsigned numcases)
: Matcher(SwitchType), Cases(cases, cases+numcases) {}
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == SwitchType;
}
-
+
unsigned getNumCases() const { return Cases.size(); }
-
+
MVT::SimpleValueType getCaseType(unsigned i) const { return Cases[i].first; }
Matcher *getCaseMatcher(unsigned i) { return Cases[i].second; }
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; }
};
-
-
+
+
/// CheckChildTypeMatcher - This checks to see if a child node has the
/// specified type, if not it fails to match.
class CheckChildTypeMatcher : public Matcher {
@@ -554,14 +556,14 @@
public:
CheckChildTypeMatcher(unsigned childno, MVT::SimpleValueType type)
: Matcher(CheckChildType), ChildNo(childno), Type(type) {}
-
+
unsigned getChildNo() const { return ChildNo; }
MVT::SimpleValueType getType() const { return Type; }
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == CheckChildType;
}
-
+
virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
private:
@@ -573,7 +575,7 @@
virtual unsigned getHashImpl() const { return (Type << 3) | ChildNo; }
virtual bool isContradictoryImpl(const Matcher *M) const;
};
-
+
/// CheckIntegerMatcher - This checks to see if the current node is a
/// ConstantSDNode with the specified integer value, if not it fails to match.
@@ -582,13 +584,13 @@
public:
CheckIntegerMatcher(int64_t value)
: Matcher(CheckInteger), Value(value) {}
-
+
int64_t getValue() const { return Value; }
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == CheckInteger;
}
-
+
virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
private:
@@ -599,7 +601,7 @@
virtual unsigned getHashImpl() const { return Value; }
virtual bool isContradictoryImpl(const Matcher *M) const;
};
-
+
/// CheckCondCodeMatcher - This checks to see if the current node is a
/// CondCodeSDNode with the specified condition, if not it fails to match.
class CheckCondCodeMatcher : public Matcher {
@@ -607,13 +609,13 @@
public:
CheckCondCodeMatcher(StringRef condcodename)
: Matcher(CheckCondCode), CondCodeName(condcodename) {}
-
+
StringRef getCondCodeName() const { return CondCodeName; }
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == CheckCondCode;
}
-
+
virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
private:
@@ -623,7 +625,7 @@
}
virtual unsigned getHashImpl() const;
};
-
+
/// CheckValueTypeMatcher - This checks to see if the current node is a
/// VTSDNode with the specified type, if not it fails to match.
class CheckValueTypeMatcher : public Matcher {
@@ -631,13 +633,13 @@
public:
CheckValueTypeMatcher(StringRef type_name)
: Matcher(CheckValueType), TypeName(type_name) {}
-
+
StringRef getTypeName() const { return TypeName; }
static inline bool classof(const Matcher *N) {
return N->getKind() == CheckValueType;
}
-
+
virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
private:
@@ -648,21 +650,21 @@
virtual unsigned getHashImpl() const;
bool isContradictoryImpl(const Matcher *M) const;
};
-
-
-
+
+
+
/// CheckComplexPatMatcher - This node runs the specified ComplexPattern on
/// the current node.
class CheckComplexPatMatcher : public Matcher {
const ComplexPattern &Pattern;
-
- /// MatchNumber - This is the recorded nodes slot that contains the node we want to
- /// match against.
+
+ /// MatchNumber - This is the recorded nodes slot that contains the node we
+ /// want to match against.
unsigned MatchNumber;
-
+
/// Name - The name of the node we're matching, for comment emission.
std::string Name;
-
+
/// FirstResult - This is the first slot in the RecordedNodes list that the
/// result of the match populates.
unsigned FirstResult;
@@ -671,17 +673,17 @@
const std::string &name, unsigned firstresult)
: Matcher(CheckComplexPat), Pattern(pattern), MatchNumber(matchnumber),
Name(name), FirstResult(firstresult) {}
-
+
const ComplexPattern &getPattern() const { return Pattern; }
unsigned getMatchNumber() const { return MatchNumber; }
-
+
const std::string getName() const { return Name; }
unsigned getFirstResult() const { return FirstResult; }
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == CheckComplexPat;
}
-
+
// Not safe to move a pattern predicate past a complex pattern.
virtual bool isSafeToReorderWithPatternPredicate() const { return false; }
@@ -695,7 +697,7 @@
return (unsigned)(intptr_t)&Pattern ^ MatchNumber;
}
};
-
+
/// CheckAndImmMatcher - This checks to see if the current node is an 'and'
/// with something equivalent to the specified immediate.
class CheckAndImmMatcher : public Matcher {
@@ -703,13 +705,13 @@
public:
CheckAndImmMatcher(int64_t value)
: Matcher(CheckAndImm), Value(value) {}
-
+
int64_t getValue() const { return Value; }
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == CheckAndImm;
}
-
+
virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
private:
@@ -727,13 +729,13 @@
public:
CheckOrImmMatcher(int64_t value)
: Matcher(CheckOrImm), Value(value) {}
-
+
int64_t getValue() const { return Value; }
static inline bool classof(const Matcher *N) {
return N->getKind() == CheckOrImm;
}
-
+
virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
private:
@@ -750,11 +752,11 @@
public:
CheckFoldableChainNodeMatcher()
: Matcher(CheckFoldableChainNode) {}
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == CheckFoldableChainNode;
}
-
+
virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
private:
@@ -770,14 +772,14 @@
public:
EmitIntegerMatcher(int64_t val, MVT::SimpleValueType vt)
: Matcher(EmitInteger), Val(val), VT(vt) {}
-
+
int64_t getValue() const { return Val; }
MVT::SimpleValueType getVT() const { return VT; }
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == EmitInteger;
}
-
+
private:
virtual void printImpl(raw_ostream &OS, unsigned indent) const;
virtual bool isEqualImpl(const Matcher *M) const {
@@ -795,14 +797,14 @@
public:
EmitStringIntegerMatcher(const std::string &val, MVT::SimpleValueType vt)
: Matcher(EmitStringInteger), Val(val), VT(vt) {}
-
+
const std::string &getValue() const { return Val; }
MVT::SimpleValueType getVT() const { return VT; }
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == EmitStringInteger;
}
-
+
private:
virtual void printImpl(raw_ostream &OS, unsigned indent) const;
virtual bool isEqualImpl(const Matcher *M) const {
@@ -811,24 +813,24 @@
}
virtual unsigned getHashImpl() const;
};
-
+
/// EmitRegisterMatcher - This creates a new TargetConstant.
class EmitRegisterMatcher : public Matcher {
/// Reg - The def for the register that we're emitting. If this is null, then
/// this is a reference to zero_reg.
- Record *Reg;
+ const CodeGenRegister *Reg;
MVT::SimpleValueType VT;
public:
- EmitRegisterMatcher(Record *reg, MVT::SimpleValueType vt)
+ EmitRegisterMatcher(const CodeGenRegister *reg, MVT::SimpleValueType vt)
: Matcher(EmitRegister), Reg(reg), VT(vt) {}
-
- Record *getReg() const { return Reg; }
+
+ const CodeGenRegister *getReg() const { return Reg; }
MVT::SimpleValueType getVT() const { return VT; }
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == EmitRegister;
}
-
+
private:
virtual void printImpl(raw_ostream &OS, unsigned indent) const;
virtual bool isEqualImpl(const Matcher *M) const {
@@ -848,13 +850,13 @@
public:
EmitConvertToTargetMatcher(unsigned slot)
: Matcher(EmitConvertToTarget), Slot(slot) {}
-
+
unsigned getSlot() const { return Slot; }
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == EmitConvertToTarget;
}
-
+
private:
virtual void printImpl(raw_ostream &OS, unsigned indent) const;
virtual bool isEqualImpl(const Matcher *M) const {
@@ -862,7 +864,7 @@
}
virtual unsigned getHashImpl() const { return Slot; }
};
-
+
/// EmitMergeInputChainsMatcher - Emit a node that merges a list of input
/// chains together with a token factor. The list of nodes are the nodes in the
/// matched pattern that have chain input/outputs. This node adds all input
@@ -872,18 +874,18 @@
public:
EmitMergeInputChainsMatcher(const unsigned *nodes, unsigned NumNodes)
: Matcher(EmitMergeInputChains), ChainNodes(nodes, nodes+NumNodes) {}
-
+
unsigned getNumNodes() const { return ChainNodes.size(); }
-
+
unsigned getNode(unsigned i) const {
assert(i < ChainNodes.size());
return ChainNodes[i];
- }
-
+ }
+
static inline bool classof(const Matcher *N) {
return N->getKind() == EmitMergeInputChains;
}
-
+
private:
virtual void printImpl(raw_ostream &OS, unsigned indent) const;
virtual bool isEqualImpl(const Matcher *M) const {
@@ -891,9 +893,9 @@
}
virtual unsigned getHashImpl() const;
};
-
+
/// EmitCopyToRegMatcher - Emit a CopyToReg node from a value to a physreg,
-/// pushing the chain and flag results.
+/// pushing the chain and glue results.
///
class EmitCopyToRegMatcher : public Matcher {
unsigned SrcSlot; // Value to copy into the physreg.
@@ -901,27 +903,27 @@
public:
EmitCopyToRegMatcher(unsigned srcSlot, Record *destPhysReg)
: Matcher(EmitCopyToReg), SrcSlot(srcSlot), DestPhysReg(destPhysReg) {}
-
+
unsigned getSrcSlot() const { return SrcSlot; }
Record *getDestPhysReg() const { return DestPhysReg; }
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == EmitCopyToReg;
}
-
+
private:
virtual void printImpl(raw_ostream &OS, unsigned indent) const;
virtual bool isEqualImpl(const Matcher *M) const {
return cast<EmitCopyToRegMatcher>(M)->SrcSlot == SrcSlot &&
- cast<EmitCopyToRegMatcher>(M)->DestPhysReg == DestPhysReg;
+ cast<EmitCopyToRegMatcher>(M)->DestPhysReg == DestPhysReg;
}
virtual unsigned getHashImpl() const {
return SrcSlot ^ ((unsigned)(intptr_t)DestPhysReg << 4);
}
};
-
-
-
+
+
+
/// EmitNodeXFormMatcher - Emit an operation that runs an SDNodeXForm on a
/// recorded node and records the result.
class EmitNodeXFormMatcher : public Matcher {
@@ -930,33 +932,33 @@
public:
EmitNodeXFormMatcher(unsigned slot, Record *nodeXForm)
: Matcher(EmitNodeXForm), Slot(slot), NodeXForm(nodeXForm) {}
-
+
unsigned getSlot() const { return Slot; }
Record *getNodeXForm() const { return NodeXForm; }
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == EmitNodeXForm;
}
-
+
private:
virtual void printImpl(raw_ostream &OS, unsigned indent) const;
virtual bool isEqualImpl(const Matcher *M) const {
return cast<EmitNodeXFormMatcher>(M)->Slot == Slot &&
- cast<EmitNodeXFormMatcher>(M)->NodeXForm == NodeXForm;
+ cast<EmitNodeXFormMatcher>(M)->NodeXForm == NodeXForm;
}
virtual unsigned getHashImpl() const {
return Slot ^ ((unsigned)(intptr_t)NodeXForm << 4);
}
};
-
+
/// EmitNodeMatcherCommon - Common class shared between EmitNode and
/// MorphNodeTo.
class EmitNodeMatcherCommon : public Matcher {
std::string OpcodeName;
const SmallVector<MVT::SimpleValueType, 3> VTs;
const SmallVector<unsigned, 6> Operands;
- bool HasChain, HasInFlag, HasOutFlag, HasMemRefs;
-
+ bool HasChain, HasInGlue, HasOutGlue, HasMemRefs;
+
/// NumFixedArityOperands - If this is a fixed arity node, this is set to -1.
/// If this is a varidic node, this is set to the number of fixed arity
/// operands in the root of the pattern. The rest are appended to this node.
@@ -965,16 +967,16 @@
EmitNodeMatcherCommon(const std::string &opcodeName,
const MVT::SimpleValueType *vts, unsigned numvts,
const unsigned *operands, unsigned numops,
- bool hasChain, bool hasInFlag, bool hasOutFlag,
+ 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),
- HasChain(hasChain), HasInFlag(hasInFlag), HasOutFlag(hasOutFlag),
+ HasChain(hasChain), HasInGlue(hasInGlue), HasOutGlue(hasOutGlue),
HasMemRefs(hasmemrefs), NumFixedArityOperands(numfixedarityoperands) {}
-
+
const std::string &getOpcodeName() const { return OpcodeName; }
-
+
unsigned getNumVTs() const { return VTs.size(); }
MVT::SimpleValueType getVT(unsigned i) const {
assert(i < VTs.size());
@@ -986,27 +988,27 @@
assert(i < Operands.size());
return Operands[i];
}
-
+
const SmallVectorImpl<MVT::SimpleValueType> &getVTList() const { return VTs; }
const SmallVectorImpl<unsigned> &getOperandList() const { return Operands; }
-
+
bool hasChain() const { return HasChain; }
- bool hasInFlag() const { return HasInFlag; }
- bool hasOutFlag() const { return HasOutFlag; }
+ bool hasInFlag() const { return HasInGlue; }
+ bool hasOutFlag() const { return HasOutGlue; }
bool hasMemRefs() const { return HasMemRefs; }
int getNumFixedArityOperands() const { return NumFixedArityOperands; }
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == EmitNode || N->getKind() == MorphNodeTo;
}
-
+
private:
virtual void printImpl(raw_ostream &OS, unsigned indent) const;
virtual bool isEqualImpl(const Matcher *M) const;
virtual unsigned getHashImpl() const;
};
-
+
/// EmitNodeMatcher - This signals a successful match and generates a node.
class EmitNodeMatcher : public EmitNodeMatcherCommon {
unsigned FirstResultSlot;
@@ -1021,15 +1023,15 @@
hasInFlag, hasOutFlag, hasmemrefs,
numfixedarityoperands, false),
FirstResultSlot(firstresultslot) {}
-
+
unsigned getFirstResultSlot() const { return FirstResultSlot; }
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == EmitNode;
}
-
+
};
-
+
class MorphNodeToMatcher : public EmitNodeMatcherCommon {
const PatternToMatch &Pattern;
public:
@@ -1044,38 +1046,38 @@
numfixedarityoperands, true),
Pattern(pattern) {
}
-
+
const PatternToMatch &getPattern() const { return Pattern; }
static inline bool classof(const Matcher *N) {
return N->getKind() == MorphNodeTo;
}
};
-
-/// MarkFlagResultsMatcher - This node indicates which non-root nodes in the
-/// pattern produce flags. This allows CompleteMatchMatcher to update them
-/// with the output flag of the resultant code.
-class MarkFlagResultsMatcher : public Matcher {
- SmallVector<unsigned, 3> FlagResultNodes;
+
+/// MarkGlueResultsMatcher - This node indicates which non-root nodes in the
+/// pattern produce glue. This allows CompleteMatchMatcher to update them
+/// with the output glue of the resultant code.
+class MarkGlueResultsMatcher : public Matcher {
+ SmallVector<unsigned, 3> GlueResultNodes;
public:
- MarkFlagResultsMatcher(const unsigned *nodes, unsigned NumNodes)
- : Matcher(MarkFlagResults), FlagResultNodes(nodes, nodes+NumNodes) {}
-
- unsigned getNumNodes() const { return FlagResultNodes.size(); }
-
+ MarkGlueResultsMatcher(const unsigned *nodes, unsigned NumNodes)
+ : Matcher(MarkGlueResults), GlueResultNodes(nodes, nodes+NumNodes) {}
+
+ unsigned getNumNodes() const { return GlueResultNodes.size(); }
+
unsigned getNode(unsigned i) const {
- assert(i < FlagResultNodes.size());
- return FlagResultNodes[i];
- }
-
- static inline bool classof(const Matcher *N) {
- return N->getKind() == MarkFlagResults;
+ assert(i < GlueResultNodes.size());
+ return GlueResultNodes[i];
}
-
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == MarkGlueResults;
+ }
+
private:
virtual void printImpl(raw_ostream &OS, unsigned indent) const;
virtual bool isEqualImpl(const Matcher *M) const {
- return cast<MarkFlagResultsMatcher>(M)->FlagResultNodes == FlagResultNodes;
+ return cast<MarkGlueResultsMatcher>(M)->GlueResultNodes == GlueResultNodes;
}
virtual unsigned getHashImpl() const;
};
@@ -1095,11 +1097,11 @@
unsigned getNumResults() const { return Results.size(); }
unsigned getResult(unsigned R) const { return Results[R]; }
const PatternToMatch &getPattern() const { return Pattern; }
-
+
static inline bool classof(const Matcher *N) {
return N->getKind() == CompleteMatch;
}
-
+
private:
virtual void printImpl(raw_ostream &OS, unsigned indent) const;
virtual bool isEqualImpl(const Matcher *M) const {
@@ -1108,7 +1110,7 @@
}
virtual unsigned getHashImpl() const;
};
-
+
} // end namespace llvm
#endif
diff --git a/src/LLVM/utils/TableGen/DAGISelMatcherEmitter.cpp b/src/LLVM/utils/TableGen/DAGISelMatcherEmitter.cpp
index dfbfe80..3b65b2a 100644
--- a/src/LLVM/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ b/src/LLVM/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -13,7 +13,7 @@
#include "DAGISelMatcher.h"
#include "CodeGenDAGPatterns.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
@@ -33,8 +33,12 @@
namespace {
class MatcherTableEmitter {
const CodeGenDAGPatterns &CGP;
- StringMap<unsigned> NodePredicateMap, PatternPredicateMap;
- std::vector<std::string> NodePredicates, PatternPredicates;
+
+ DenseMap<TreePattern *, unsigned> NodePredicateMap;
+ std::vector<TreePredicateFn> NodePredicates;
+
+ StringMap<unsigned> PatternPredicateMap;
+ std::vector<std::string> PatternPredicates;
DenseMap<const ComplexPattern*, unsigned> ComplexPatternMap;
std::vector<const ComplexPattern*> ComplexPatterns;
@@ -44,26 +48,28 @@
std::vector<Record*> NodeXForms;
public:
- MatcherTableEmitter(const CodeGenDAGPatterns &cgp) : CGP(cgp) {}
+ MatcherTableEmitter(const CodeGenDAGPatterns &cgp)
+ : CGP(cgp) {}
unsigned EmitMatcherList(const Matcher *N, unsigned Indent,
unsigned StartIdx, formatted_raw_ostream &OS);
-
+
void EmitPredicateFunctions(formatted_raw_ostream &OS);
-
+
void EmitHistogram(const Matcher *N, formatted_raw_ostream &OS);
private:
unsigned EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
formatted_raw_ostream &OS);
-
- unsigned getNodePredicate(StringRef PredName) {
- unsigned &Entry = NodePredicateMap[PredName];
+
+ unsigned getNodePredicate(TreePredicateFn Pred) {
+ unsigned &Entry = NodePredicateMap[Pred.getOrigPatFragRecord()];
if (Entry == 0) {
- NodePredicates.push_back(PredName.str());
+ NodePredicates.push_back(Pred);
Entry = NodePredicates.size();
}
return Entry-1;
}
+
unsigned getPatternPredicate(StringRef PredName) {
unsigned &Entry = PatternPredicateMap[PredName];
if (Entry == 0) {
@@ -72,7 +78,6 @@
}
return Entry-1;
}
-
unsigned getComplexPat(const ComplexPattern &P) {
unsigned &Entry = ComplexPatternMap[&P];
if (Entry == 0) {
@@ -81,7 +86,7 @@
}
return Entry-1;
}
-
+
unsigned getNodeXFormID(Record *Rec) {
unsigned &Entry = NodeXFormMap[Rec];
if (Entry == 0) {
@@ -90,13 +95,13 @@
}
return Entry-1;
}
-
+
};
} // end anonymous namespace.
static unsigned GetVBRSize(unsigned Val) {
if (Val <= 127) return 1;
-
+
unsigned NumBytes = 0;
while (Val >= 128) {
Val >>= 7;
@@ -112,7 +117,7 @@
OS << Val << ", ";
return 1;
}
-
+
uint64_t InVal = Val;
unsigned NumBytes = 0;
while (Val >= 128) {
@@ -133,14 +138,14 @@
EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
formatted_raw_ostream &OS) {
OS.PadToColumn(Indent*2);
-
+
switch (N->getKind()) {
case Matcher::Scope: {
const ScopeMatcher *SM = cast<ScopeMatcher>(N);
assert(SM->getNext() == 0 && "Shouldn't have next after scope");
-
+
unsigned StartIdx = CurrentIdx;
-
+
// Emit all of the children.
for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i) {
if (i == 0) {
@@ -164,29 +169,29 @@
unsigned VBRSize = 0;
do {
VBRSize = GetVBRSize(ChildSize);
-
+
TmpBuf.clear();
raw_svector_ostream OS(TmpBuf);
formatted_raw_ostream FOS(OS);
ChildSize = EmitMatcherList(SM->getChild(i), Indent+1,
CurrentIdx+VBRSize, FOS);
} while (GetVBRSize(ChildSize) != VBRSize);
-
+
assert(ChildSize != 0 && "Should not have a zero-sized child!");
-
+
CurrentIdx += EmitVBRValue(ChildSize, OS);
if (!OmitComments) {
OS << "/*->" << CurrentIdx+ChildSize << "*/";
-
+
if (i == 0)
OS.PadToColumn(CommentIndent) << "// " << SM->getNumChildren()
<< " children in Scope";
}
-
+
OS << '\n' << TmpBuf.str();
CurrentIdx += ChildSize;
}
-
+
// Emit a zero as a sentinel indicating end of 'Scope'.
if (!OmitComments)
OS << "/*" << CurrentIdx << "*/";
@@ -196,7 +201,7 @@
OS << '\n';
return CurrentIdx - StartIdx + 1;
}
-
+
case Matcher::RecordNode:
OS << "OPC_RecordNode,";
if (!OmitComments)
@@ -215,30 +220,30 @@
<< cast<RecordChildMatcher>(N)->getWhatFor();
OS << '\n';
return 1;
-
+
case Matcher::RecordMemRef:
OS << "OPC_RecordMemRef,\n";
return 1;
-
- case Matcher::CaptureFlagInput:
- OS << "OPC_CaptureFlagInput,\n";
+
+ case Matcher::CaptureGlueInput:
+ OS << "OPC_CaptureGlueInput,\n";
return 1;
-
+
case Matcher::MoveChild:
OS << "OPC_MoveChild, " << cast<MoveChildMatcher>(N)->getChildNo() << ",\n";
return 2;
-
+
case Matcher::MoveParent:
OS << "OPC_MoveParent,\n";
return 1;
-
+
case Matcher::CheckSame:
OS << "OPC_CheckSame, "
<< cast<CheckSameMatcher>(N)->getMatchNumber() << ",\n";
return 2;
case Matcher::CheckPatternPredicate: {
- StringRef Pred = cast<CheckPatternPredicateMatcher>(N)->getPredicate();
+ StringRef Pred =cast<CheckPatternPredicateMatcher>(N)->getPredicate();
OS << "OPC_CheckPatternPredicate, " << getPatternPredicate(Pred) << ',';
if (!OmitComments)
OS.PadToColumn(CommentIndent) << "// " << Pred;
@@ -246,23 +251,23 @@
return 2;
}
case Matcher::CheckPredicate: {
- StringRef Pred = cast<CheckPredicateMatcher>(N)->getPredicateName();
+ TreePredicateFn Pred = cast<CheckPredicateMatcher>(N)->getPredicate();
OS << "OPC_CheckPredicate, " << getNodePredicate(Pred) << ',';
if (!OmitComments)
- OS.PadToColumn(CommentIndent) << "// " << Pred;
+ OS.PadToColumn(CommentIndent) << "// " << Pred.getFnName();
OS << '\n';
return 2;
}
case Matcher::CheckOpcode:
- OS << "OPC_CheckOpcode, TARGET_OPCODE("
+ OS << "OPC_CheckOpcode, TARGET_VAL("
<< cast<CheckOpcodeMatcher>(N)->getOpcode().getEnumName() << "),\n";
return 3;
-
+
case Matcher::SwitchOpcode:
case Matcher::SwitchType: {
unsigned StartIdx = CurrentIdx;
-
+
unsigned NumCases;
if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) {
OS << "OPC_SwitchOpcode ";
@@ -276,7 +281,7 @@
OS << "/*" << NumCases << " cases */";
OS << ", ";
++CurrentIdx;
-
+
// For each case we emit the size, then the opcode, then the matcher.
for (unsigned i = 0, e = NumCases; i != e; ++i) {
const Matcher *Child;
@@ -288,7 +293,7 @@
Child = cast<SwitchTypeMatcher>(N)->getCaseMatcher(i);
IdxSize = 1; // size of type in table is 1 byte.
}
-
+
// We need to encode the opcode and the offset of the case code before
// emitting the case code. Handle this by buffering the output into a
// string while we get the size. Unfortunately, the offset of the
@@ -299,29 +304,29 @@
unsigned VBRSize = 0;
do {
VBRSize = GetVBRSize(ChildSize);
-
+
TmpBuf.clear();
raw_svector_ostream OS(TmpBuf);
formatted_raw_ostream FOS(OS);
ChildSize = EmitMatcherList(Child, Indent+1, CurrentIdx+VBRSize+IdxSize,
FOS);
} while (GetVBRSize(ChildSize) != VBRSize);
-
+
assert(ChildSize != 0 && "Should not have a zero-sized child!");
-
+
if (i != 0) {
OS.PadToColumn(Indent*2);
if (!OmitComments)
OS << (isa<SwitchOpcodeMatcher>(N) ?
"/*SwitchOpcode*/ " : "/*SwitchType*/ ");
}
-
+
// Emit the VBR.
CurrentIdx += EmitVBRValue(ChildSize, OS);
-
+
OS << ' ';
if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N))
- OS << "TARGET_OPCODE(" << SOM->getCaseOpcode(i).getEnumName() << "),";
+ OS << "TARGET_VAL(" << SOM->getCaseOpcode(i).getEnumName() << "),";
else
OS << getEnumName(cast<SwitchTypeMatcher>(N)->getCaseType(i)) << ',';
@@ -351,13 +356,13 @@
OS << "OPC_CheckType, "
<< getEnumName(cast<CheckTypeMatcher>(N)->getType()) << ",\n";
return 2;
-
+
case Matcher::CheckChildType:
OS << "OPC_CheckChild"
<< cast<CheckChildTypeMatcher>(N)->getChildNo() << "Type, "
<< getEnumName(cast<CheckChildTypeMatcher>(N)->getType()) << ",\n";
return 2;
-
+
case Matcher::CheckInteger: {
OS << "OPC_CheckInteger, ";
unsigned Bytes=1+EmitVBRValue(cast<CheckIntegerMatcher>(N)->getValue(), OS);
@@ -368,7 +373,7 @@
OS << "OPC_CheckCondCode, ISD::"
<< cast<CheckCondCodeMatcher>(N)->getCondCodeName() << ",\n";
return 2;
-
+
case Matcher::CheckValueType:
OS << "OPC_CheckValueType, MVT::"
<< cast<CheckValueTypeMatcher>(N)->getTypeName() << ",\n";
@@ -379,20 +384,20 @@
const ComplexPattern &Pattern = CCPM->getPattern();
OS << "OPC_CheckComplexPat, /*CP*/" << getComplexPat(Pattern) << ", /*#*/"
<< CCPM->getMatchNumber() << ',';
-
+
if (!OmitComments) {
OS.PadToColumn(CommentIndent) << "// " << Pattern.getSelectFunc();
OS << ":$" << CCPM->getName();
for (unsigned i = 0, e = Pattern.getNumOperands(); i != e; ++i)
OS << " #" << CCPM->getFirstResult()+i;
-
+
if (Pattern.hasProperty(SDNPHasChain))
OS << " + chain result";
}
OS << '\n';
return 3;
}
-
+
case Matcher::CheckAndImm: {
OS << "OPC_CheckAndImm, ";
unsigned Bytes=1+EmitVBRValue(cast<CheckAndImmMatcher>(N)->getValue(), OS);
@@ -406,11 +411,11 @@
OS << '\n';
return Bytes;
}
-
+
case Matcher::CheckFoldableChainNode:
OS << "OPC_CheckFoldableChainNode,\n";
return 1;
-
+
case Matcher::EmitInteger: {
int64_t Val = cast<EmitIntegerMatcher>(N)->getValue();
OS << "OPC_EmitInteger, "
@@ -427,35 +432,45 @@
<< Val << ",\n";
return 3;
}
-
- case Matcher::EmitRegister:
- OS << "OPC_EmitRegister, "
- << getEnumName(cast<EmitRegisterMatcher>(N)->getVT()) << ", ";
- if (Record *R = cast<EmitRegisterMatcher>(N)->getReg())
- OS << getQualifiedName(R) << ",\n";
- else {
- OS << "0 ";
- if (!OmitComments)
- OS << "/*zero_reg*/";
- OS << ",\n";
+
+ case Matcher::EmitRegister: {
+ const EmitRegisterMatcher *Matcher = cast<EmitRegisterMatcher>(N);
+ const CodeGenRegister *Reg = Matcher->getReg();
+ // If the enum value of the register is larger than one byte can handle,
+ // use EmitRegister2.
+ if (Reg && Reg->EnumValue > 255) {
+ OS << "OPC_EmitRegister2, " << getEnumName(Matcher->getVT()) << ", ";
+ OS << "TARGET_VAL(" << getQualifiedName(Reg->TheDef) << "),\n";
+ return 4;
+ } else {
+ OS << "OPC_EmitRegister, " << getEnumName(Matcher->getVT()) << ", ";
+ if (Reg) {
+ OS << getQualifiedName(Reg->TheDef) << ",\n";
+ } else {
+ OS << "0 ";
+ if (!OmitComments)
+ OS << "/*zero_reg*/";
+ OS << ",\n";
+ }
+ return 3;
}
- return 3;
-
+ }
+
case Matcher::EmitConvertToTarget:
OS << "OPC_EmitConvertToTarget, "
<< cast<EmitConvertToTargetMatcher>(N)->getSlot() << ",\n";
return 2;
-
+
case Matcher::EmitMergeInputChains: {
const EmitMergeInputChainsMatcher *MN =
cast<EmitMergeInputChainsMatcher>(N);
-
+
// Handle the specialized forms OPC_EmitMergeInputChains1_0 and 1_1.
if (MN->getNumNodes() == 1 && MN->getNode(0) < 2) {
OS << "OPC_EmitMergeInputChains1_" << MN->getNode(0) << ",\n";
return 1;
}
-
+
OS << "OPC_EmitMergeInputChains, " << MN->getNumNodes() << ", ";
for (unsigned i = 0, e = MN->getNumNodes(); i != e; ++i)
OS << MN->getNode(i) << ", ";
@@ -477,21 +492,21 @@
OS <<'\n';
return 3;
}
-
+
case Matcher::EmitNode:
case Matcher::MorphNodeTo: {
const EmitNodeMatcherCommon *EN = cast<EmitNodeMatcherCommon>(N);
OS << (isa<EmitNodeMatcher>(EN) ? "OPC_EmitNode" : "OPC_MorphNodeTo");
- OS << ", TARGET_OPCODE(" << EN->getOpcodeName() << "), 0";
-
+ OS << ", TARGET_VAL(" << EN->getOpcodeName() << "), 0";
+
if (EN->hasChain()) OS << "|OPFL_Chain";
- if (EN->hasInFlag()) OS << "|OPFL_FlagInput";
- if (EN->hasOutFlag()) OS << "|OPFL_FlagOutput";
+ if (EN->hasInFlag()) OS << "|OPFL_GlueInput";
+ if (EN->hasOutFlag()) OS << "|OPFL_GlueOutput";
if (EN->hasMemRefs()) OS << "|OPFL_MemRefs";
if (EN->getNumFixedArityOperands() != -1)
OS << "|OPFL_Variadic" << EN->getNumFixedArityOperands();
OS << ",\n";
-
+
OS.PadToColumn(Indent*2+4) << EN->getNumVTs();
if (!OmitComments)
OS << "/*#VTs*/";
@@ -506,7 +521,7 @@
unsigned NumOperandBytes = 0;
for (unsigned i = 0, e = EN->getNumOperands(); i != e; ++i)
NumOperandBytes += EmitVBRValue(EN->getOperand(i), OS);
-
+
if (!OmitComments) {
// Print the result #'s for EmitNode.
if (const EmitNodeMatcher *E = dyn_cast<EmitNodeMatcher>(EN)) {
@@ -521,19 +536,19 @@
if (const MorphNodeToMatcher *SNT = dyn_cast<MorphNodeToMatcher>(N)) {
OS.PadToColumn(Indent*2) << "// Src: "
- << *SNT->getPattern().getSrcPattern() << " - Complexity = "
+ << *SNT->getPattern().getSrcPattern() << " - Complexity = "
<< SNT->getPattern().getPatternComplexity(CGP) << '\n';
OS.PadToColumn(Indent*2) << "// Dst: "
<< *SNT->getPattern().getDstPattern() << '\n';
}
} else
OS << '\n';
-
+
return 6+EN->getNumVTs()+NumOperandBytes;
}
- case Matcher::MarkFlagResults: {
- const MarkFlagResultsMatcher *CFR = cast<MarkFlagResultsMatcher>(N);
- OS << "OPC_MarkFlagResults, " << CFR->getNumNodes() << ", ";
+ case Matcher::MarkGlueResults: {
+ const MarkGlueResultsMatcher *CFR = cast<MarkGlueResultsMatcher>(N);
+ OS << "OPC_MarkGlueResults, " << CFR->getNumNodes() << ", ";
unsigned NumOperandBytes = 0;
for (unsigned i = 0, e = CFR->getNumNodes(); i != e; ++i)
NumOperandBytes += EmitVBRValue(CFR->getNode(i), OS);
@@ -549,7 +564,7 @@
OS << '\n';
if (!OmitComments) {
OS.PadToColumn(Indent*2) << "// Src: "
- << *CM->getPattern().getSrcPattern() << " - Complexity = "
+ << *CM->getPattern().getSrcPattern() << " - Complexity = "
<< CM->getPattern().getPatternComplexity(CGP) << '\n';
OS.PadToColumn(Indent*2) << "// Dst: "
<< *CM->getPattern().getDstPattern();
@@ -573,7 +588,7 @@
unsigned MatcherSize = EmitMatcher(N, Indent, CurrentIdx, OS);
Size += MatcherSize;
CurrentIdx += MatcherSize;
-
+
// If there are other nodes in this list, iterate to them, otherwise we're
// done.
N = N->getNext();
@@ -592,49 +607,38 @@
OS << " }\n";
OS << "}\n\n";
}
-
+
// Emit Node predicates.
// FIXME: Annoyingly, these are stored by name, which we never even emit. Yay?
StringMap<TreePattern*> PFsByName;
-
+
for (CodeGenDAGPatterns::pf_iterator I = CGP.pf_begin(), E = CGP.pf_end();
I != E; ++I)
PFsByName[I->first->getName()] = I->second;
-
+
if (!NodePredicates.empty()) {
OS << "bool CheckNodePredicate(SDNode *Node, unsigned PredNo) const {\n";
OS << " switch (PredNo) {\n";
OS << " default: assert(0 && \"Invalid predicate in table?\");\n";
for (unsigned i = 0, e = NodePredicates.size(); i != e; ++i) {
- // FIXME: Storing this by name is horrible.
- TreePattern *P =PFsByName[NodePredicates[i].substr(strlen("Predicate_"))];
- assert(P && "Unknown name?");
-
// Emit the predicate code corresponding to this pattern.
- std::string Code = P->getRecord()->getValueAsCode("Predicate");
- assert(!Code.empty() && "No code in this predicate");
- OS << " case " << i << ": { // " << NodePredicates[i] << '\n';
- std::string ClassName;
- if (P->getOnlyTree()->isLeaf())
- ClassName = "SDNode";
- else
- ClassName =
- CGP.getSDNodeInfo(P->getOnlyTree()->getOperator()).getSDClassName();
- if (ClassName == "SDNode")
- OS << " SDNode *N = Node;\n";
- else
- OS << " " << ClassName << "*N = cast<" << ClassName << ">(Node);\n";
- OS << Code << "\n }\n";
+ TreePredicateFn PredFn = NodePredicates[i];
+
+ assert(!PredFn.isAlwaysTrue() && "No code in this predicate");
+ OS << " case " << i << ": { // " << NodePredicates[i].getFnName() <<'\n';
+
+ OS << PredFn.getCodeToRunOnSDNode() << "\n }\n";
}
OS << " }\n";
OS << "}\n\n";
}
-
+
// Emit CompletePattern matchers.
// FIXME: This should be const.
if (!ComplexPatterns.empty()) {
- OS << "bool CheckComplexPattern(SDNode *Root, SDValue N,\n";
- OS << " unsigned PatternNo, SmallVectorImpl<SDValue> &Result) {\n";
+ OS << "bool CheckComplexPattern(SDNode *Root, SDNode *Parent, SDValue N,\n";
+ OS << " unsigned PatternNo,\n";
+ OS << " SmallVectorImpl<std::pair<SDValue, SDNode*> > &Result) {\n";
OS << " unsigned NextRes = Result.size();\n";
OS << " switch (PatternNo) {\n";
OS << " default: assert(0 && \"Invalid pattern # in table?\");\n";
@@ -644,41 +648,52 @@
if (P.hasProperty(SDNPHasChain))
++NumOps; // Get the chained node too.
-
+
OS << " case " << i << ":\n";
OS << " Result.resize(NextRes+" << NumOps << ");\n";
OS << " return " << P.getSelectFunc();
- OS << "(Root, N";
+ OS << "(";
+ // If the complex pattern wants the root of the match, pass it in as the
+ // first argument.
+ if (P.hasProperty(SDNPWantRoot))
+ OS << "Root, ";
+
+ // If the complex pattern wants the parent of the operand being matched,
+ // pass it in as the next argument.
+ if (P.hasProperty(SDNPWantParent))
+ OS << "Parent, ";
+
+ OS << "N";
for (unsigned i = 0; i != NumOps; ++i)
- OS << ", Result[NextRes+" << i << ']';
+ OS << ", Result[NextRes+" << i << "].first";
OS << ");\n";
}
OS << " }\n";
OS << "}\n\n";
}
-
-
+
+
// Emit SDNodeXForm handlers.
// FIXME: This should be const.
if (!NodeXForms.empty()) {
OS << "SDValue RunSDNodeXForm(SDValue V, unsigned XFormNo) {\n";
OS << " switch (XFormNo) {\n";
OS << " default: assert(0 && \"Invalid xform # in table?\");\n";
-
+
// FIXME: The node xform could take SDValue's instead of SDNode*'s.
for (unsigned i = 0, e = NodeXForms.size(); i != e; ++i) {
const CodeGenDAGPatterns::NodeXForm &Entry =
CGP.getSDNodeTransform(NodeXForms[i]);
-
+
Record *SDNode = Entry.first;
const std::string &Code = Entry.second;
-
+
OS << " case " << i << ": { ";
if (!OmitComments)
OS << "// " << NodeXForms[i]->getName();
OS << '\n';
-
+
std::string ClassName = CGP.getSDNodeInfo(SDNode).getSDClassName();
if (ClassName == "SDNode")
OS << " SDNode *N = V.getNode();\n";
@@ -698,12 +713,12 @@
if (unsigned(M->getKind()) >= OpcodeFreq.size())
OpcodeFreq.resize(M->getKind()+1);
OpcodeFreq[M->getKind()]++;
-
+
// Handle recursive nodes.
if (const ScopeMatcher *SM = dyn_cast<ScopeMatcher>(M)) {
for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i)
BuildHistogram(SM->getChild(i), OpcodeFreq);
- } else if (const SwitchOpcodeMatcher *SOM =
+ } else if (const SwitchOpcodeMatcher *SOM =
dyn_cast<SwitchOpcodeMatcher>(M)) {
for (unsigned i = 0, e = SOM->getNumCases(); i != e; ++i)
BuildHistogram(SOM->getCaseMatcher(i), OpcodeFreq);
@@ -718,19 +733,19 @@
formatted_raw_ostream &OS) {
if (OmitComments)
return;
-
+
std::vector<unsigned> OpcodeFreq;
BuildHistogram(M, OpcodeFreq);
-
+
OS << " // Opcode Histogram:\n";
for (unsigned i = 0, e = OpcodeFreq.size(); i != e; ++i) {
OS << " // #";
switch ((Matcher::KindTy)i) {
- case Matcher::Scope: OS << "OPC_Scope"; break;
- case Matcher::RecordNode: OS << "OPC_RecordNode"; break;
+ case Matcher::Scope: OS << "OPC_Scope"; break;
+ case Matcher::RecordNode: OS << "OPC_RecordNode"; break;
case Matcher::RecordChild: OS << "OPC_RecordChild"; break;
case Matcher::RecordMemRef: OS << "OPC_RecordMemRef"; break;
- case Matcher::CaptureFlagInput: OS << "OPC_CaptureFlagInput"; break;
+ case Matcher::CaptureGlueInput: OS << "OPC_CaptureGlueInput"; break;
case Matcher::MoveChild: OS << "OPC_MoveChild"; break;
case Matcher::MoveParent: OS << "OPC_MoveParent"; break;
case Matcher::CheckSame: OS << "OPC_CheckSame"; break;
@@ -759,10 +774,10 @@
case Matcher::EmitNode: OS << "OPC_EmitNode"; break;
case Matcher::MorphNodeTo: OS << "OPC_MorphNodeTo"; break;
case Matcher::EmitNodeXForm: OS << "OPC_EmitNodeXForm"; break;
- case Matcher::MarkFlagResults: OS << "OPC_MarkFlagResults"; break;
- case Matcher::CompleteMatch: OS << "OPC_CompleteMatch"; break;
+ case Matcher::MarkGlueResults: OS << "OPC_MarkGlueResults"; break;
+ case Matcher::CompleteMatch: OS << "OPC_CompleteMatch"; break;
}
-
+
OS.PadToColumn(40) << " = " << OpcodeFreq[i] << '\n';
}
OS << '\n';
@@ -770,26 +785,28 @@
void llvm::EmitMatcherTable(const Matcher *TheMatcher,
- const CodeGenDAGPatterns &CGP, raw_ostream &O) {
+ const CodeGenDAGPatterns &CGP,
+ raw_ostream &O) {
formatted_raw_ostream OS(O);
-
+
OS << "// The main instruction selector code.\n";
OS << "SDNode *SelectCode(SDNode *N) {\n";
MatcherTableEmitter MatcherEmitter(CGP);
- OS << " // Opcodes are emitted as 2 bytes, TARGET_OPCODE handles this.\n";
- OS << " #define TARGET_OPCODE(X) X & 255, unsigned(X) >> 8\n";
+ OS << " // Some target values are emitted as 2 bytes, TARGET_VAL handles\n";
+ 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);
OS << " 0\n }; // Total Array size is " << (TotalSize+1) << " bytes\n\n";
-
+
MatcherEmitter.EmitHistogram(TheMatcher, OS);
-
- OS << " #undef TARGET_OPCODE\n";
+
+ OS << " #undef TARGET_VAL\n";
OS << " return SelectCodeCommon(N, MatcherTable,sizeof(MatcherTable));\n}\n";
OS << '\n';
-
+
// Next up, emit the function for node and pattern predicates:
MatcherEmitter.EmitPredicateFunctions(OS);
}
diff --git a/src/LLVM/utils/TableGen/DAGISelMatcherGen.cpp b/src/LLVM/utils/TableGen/DAGISelMatcherGen.cpp
index aba6636..49ad956 100644
--- a/src/LLVM/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/src/LLVM/utils/TableGen/DAGISelMatcherGen.cpp
@@ -9,7 +9,9 @@
#include "DAGISelMatcher.h"
#include "CodeGenDAGPatterns.h"
-#include "Record.h"
+#include "CodeGenRegisters.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include <utility>
@@ -23,14 +25,14 @@
const CodeGenTarget &T) {
bool FoundRC = false;
MVT::SimpleValueType VT = MVT::Other;
- const std::vector<CodeGenRegisterClass> &RCs = T.getRegisterClasses();
- std::vector<Record*>::const_iterator Element;
-
+ const CodeGenRegister *Reg = T.getRegBank().getReg(R);
+ ArrayRef<CodeGenRegisterClass*> RCs = T.getRegBank().getRegClasses();
+
for (unsigned rc = 0, e = RCs.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RCs[rc];
- if (!std::count(RC.Elements.begin(), RC.Elements.end(), R))
+ const CodeGenRegisterClass &RC = *RCs[rc];
+ if (!RC.contains(Reg))
continue;
-
+
if (!FoundRC) {
FoundRC = true;
VT = RC.getValueTypeNum(0);
@@ -48,30 +50,30 @@
class MatcherGen {
const PatternToMatch &Pattern;
const CodeGenDAGPatterns &CGP;
-
+
/// PatWithNoTypes - This is a clone of Pattern.getSrcPattern() that starts
/// out with all of the types removed. This allows us to insert type checks
/// as we scan the tree.
TreePatternNode *PatWithNoTypes;
-
+
/// VariableMap - A map from variable names ('$dst') to the recorded operand
/// number that they were captured as. These are biased by 1 to make
/// insertion easier.
StringMap<unsigned> VariableMap;
-
+
/// 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.
unsigned NextRecordedOperandNo;
-
+
/// MatchedChainNodes - This maintains the position in the recorded nodes
/// array of all of the recorded input nodes that have chains.
SmallVector<unsigned, 2> MatchedChainNodes;
- /// MatchedFlagResultNodes - This maintains the position in the recorded
- /// nodes array of all of the recorded input nodes that have flag results.
- SmallVector<unsigned, 2> MatchedFlagResultNodes;
-
+ /// MatchedGlueResultNodes - This maintains the position in the recorded
+ /// nodes array of all of the recorded input nodes that have glue results.
+ 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
@@ -79,40 +81,39 @@
/// results into.
SmallVector<std::pair<const TreePatternNode*,
unsigned>, 2> MatchedComplexPatterns;
-
+
/// PhysRegInputs - List list has an entry for each explicitly specified
/// physreg input to the pattern. The first elt is the Register node, the
/// second is the recorded slot number the input pattern match saved it in.
SmallVector<std::pair<Record*, unsigned>, 2> PhysRegInputs;
-
+
/// Matcher - This is the top level of the generated matcher, the result.
Matcher *TheMatcher;
-
+
/// CurPredicate - As we emit matcher nodes, this points to the latest check
/// which should have future checks stuck into its Next position.
Matcher *CurPredicate;
public:
MatcherGen(const PatternToMatch &pattern, const CodeGenDAGPatterns &cgp);
-
+
~MatcherGen() {
delete PatWithNoTypes;
}
-
+
bool EmitMatcherCode(unsigned Variant);
void EmitResultCode();
-
+
Matcher *GetMatcher() const { return TheMatcher; }
- Matcher *GetCurPredicate() const { return CurPredicate; }
private:
void AddMatcher(Matcher *NewNode);
void InferPossibleTypes();
-
+
// Matcher Generation.
void EmitMatchCode(const TreePatternNode *N, TreePatternNode *NodeNoTypes);
void EmitLeafMatchCode(const TreePatternNode *N);
void EmitOperatorMatchCode(const TreePatternNode *N,
TreePatternNode *NodeNoTypes);
-
+
// Result Code Generation.
unsigned getNamedArgumentSlot(StringRef Name) {
unsigned VarMapEntry = VariableMap[Name];
@@ -124,7 +125,7 @@
/// GetInstPatternNode - Get the pattern for an instruction.
const TreePatternNode *GetInstPatternNode(const DAGInstruction &Ins,
const TreePatternNode *N);
-
+
void EmitResultOperand(const TreePatternNode *N,
SmallVectorImpl<unsigned> &ResultOps);
void EmitResultOfNamedOperand(const TreePatternNode *N,
@@ -136,7 +137,7 @@
void EmitResultSDNodeXFormAsOperand(const TreePatternNode *N,
SmallVectorImpl<unsigned> &ResultOps);
};
-
+
} // end anon namespace.
MatcherGen::MatcherGen(const PatternToMatch &pattern,
@@ -157,7 +158,7 @@
//
PatWithNoTypes = Pattern.getSrcPattern()->clone();
PatWithNoTypes->RemoveAllTypes();
-
+
// If there are types that are manifestly known, infer them.
InferPossibleTypes();
}
@@ -170,7 +171,7 @@
// TP - Get *SOME* tree pattern, we don't care which. It is only used for
// diagnostics, which we know are impossible at this point.
TreePattern &TP = *CGP.pf_begin()->second;
-
+
try {
bool MadeChange = true;
while (MadeChange)
@@ -183,7 +184,7 @@
}
-/// AddMatcher - Add a matcher node to the current graph we're building.
+/// AddMatcher - Add a matcher node to the current graph we're building.
void MatcherGen::AddMatcher(Matcher *NewNode) {
if (CurPredicate != 0)
CurPredicate->setNext(NewNode);
@@ -200,7 +201,7 @@
/// EmitLeafMatchCode - Generate matching code for leaf nodes.
void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) {
assert(N->isLeaf() && "Not a leaf?");
-
+
// Direct match against an integer constant.
if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
// If this is the root of the dag we're matching, we emit a redundant opcode
@@ -213,16 +214,17 @@
return AddMatcher(new CheckIntegerMatcher(II->getValue()));
}
-
+
DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue());
if (DI == 0) {
errs() << "Unknown leaf kind: " << *DI << "\n";
abort();
}
-
+
Record *LeafRec = DI->getDef();
if (// Handle register references. Nothing to do here, they always match.
- LeafRec->isSubClassOf("RegisterClass") ||
+ LeafRec->isSubClassOf("RegisterClass") ||
+ LeafRec->isSubClassOf("RegisterOperand") ||
LeafRec->isSubClassOf("PointerLikeRegClass") ||
LeafRec->isSubClassOf("SubRegIndex") ||
// Place holder for SRCVALUE nodes. Nothing to do here.
@@ -230,20 +232,20 @@
return;
// If we have a physreg reference like (mul gpr:$src, EAX) then we need to
- // record the register
+ // record the register
if (LeafRec->isSubClassOf("Register")) {
AddMatcher(new RecordMatcher("physreg input "+LeafRec->getName(),
NextRecordedOperandNo));
PhysRegInputs.push_back(std::make_pair(LeafRec, NextRecordedOperandNo++));
return;
}
-
+
if (LeafRec->isSubClassOf("ValueType"))
return AddMatcher(new CheckValueTypeMatcher(LeafRec->getName()));
-
+
if (LeafRec->isSubClassOf("CondCode"))
return AddMatcher(new CheckCondCodeMatcher(LeafRec->getName()));
-
+
if (LeafRec->isSubClassOf("ComplexPattern")) {
// We can't model ComplexPattern uses that don't have their name taken yet.
// The OPC_CheckComplexPattern operation implicitly records the results.
@@ -257,7 +259,7 @@
MatchedComplexPatterns.push_back(std::make_pair(N, 0));
return;
}
-
+
errs() << "Unknown leaf kind: " << *N << "\n";
abort();
}
@@ -266,7 +268,7 @@
TreePatternNode *NodeNoTypes) {
assert(!N->isLeaf() && "Not an operator?");
const SDNodeInfo &CInfo = CGP.getSDNodeInfo(N->getOperator());
-
+
// If this is an 'and R, 1234' where the operation is AND/OR and the RHS is
// a constant without a predicate fn that has more that one bit set, handle
// this as a special case. This is usually for targets that have special
@@ -277,7 +279,7 @@
// them from the mask in the dag. For example, it might turn 'AND X, 255'
// into 'AND X, 254' if it knows the low bit is set. Emit code that checks
// to handle this.
- if ((N->getOperator()->getName() == "and" ||
+ if ((N->getOperator()->getName() == "and" ||
N->getOperator()->getName() == "or") &&
N->getChild(1)->isLeaf() && N->getChild(1)->getPredicateFns().empty() &&
N->getPredicateFns().empty()) {
@@ -303,15 +305,15 @@
}
}
}
-
+
// Check that the current opcode lines up.
AddMatcher(new CheckOpcodeMatcher(CInfo));
-
+
// If this node has memory references (i.e. is a load or store), tell the
// interpreter to capture them in the memref array.
if (N->NodeHasProperty(SDNPMemOperand, CGP))
AddMatcher(new RecordMemRefMatcher());
-
+
// If this node has a chain, then the chain is operand #0 is the SDNode, and
// the child numbers of the node are all offset by one.
unsigned OpNo = 0;
@@ -322,7 +324,7 @@
NextRecordedOperandNo));
// Remember all of the input chains our pattern will match.
MatchedChainNodes.push_back(NextRecordedOperandNo++);
-
+
// Don't look at the input chain when matching the tree pattern to the
// SDNode.
OpNo = 1;
@@ -353,11 +355,11 @@
// If there is a node between the root and this node, then we definitely
// need to emit the check.
bool NeedCheck = !Root->hasChild(N);
-
+
// If it *is* an immediate child of the root, we can still need a check if
// the root SDNode has multiple inputs. For us, this means that it is an
// intrinsic, has multiple operands, or has other inputs like chain or
- // flag).
+ // glue).
if (!NeedCheck) {
const SDNodeInfo &PInfo = CGP.getSDNodeInfo(Root->getOperator());
NeedCheck =
@@ -366,34 +368,34 @@
Root->getOperator() == CGP.get_intrinsic_wo_chain_sdnode() ||
PInfo.getNumOperands() > 1 ||
PInfo.hasProperty(SDNPHasChain) ||
- PInfo.hasProperty(SDNPInFlag) ||
- PInfo.hasProperty(SDNPOptInFlag);
+ PInfo.hasProperty(SDNPInGlue) ||
+ PInfo.hasProperty(SDNPOptInGlue);
}
-
+
if (NeedCheck)
AddMatcher(new CheckFoldableChainNodeMatcher());
}
}
- // If this node has an output flag and isn't the root, remember it.
- if (N->NodeHasProperty(SDNPOutFlag, CGP) &&
+ // If this node has an output glue and isn't the root, remember it.
+ if (N->NodeHasProperty(SDNPOutGlue, CGP) &&
N != Pattern.getSrcPattern()) {
- // TODO: This redundantly records nodes with both flags and chains.
-
+ // TODO: This redundantly records nodes with both glues and chains.
+
// Record the node and remember it in our chained nodes list.
AddMatcher(new RecordMatcher("'" + N->getOperator()->getName() +
- "' flag output node",
+ "' glue output node",
NextRecordedOperandNo));
- // Remember all of the nodes with output flags our pattern will match.
- MatchedFlagResultNodes.push_back(NextRecordedOperandNo++);
+ // Remember all of the nodes with output glue our pattern will match.
+ MatchedGlueResultNodes.push_back(NextRecordedOperandNo++);
}
-
- // If this node is known to have an input flag or if it *might* have an input
- // flag, capture it as the flag input of the pattern.
- if (N->NodeHasProperty(SDNPOptInFlag, CGP) ||
- N->NodeHasProperty(SDNPInFlag, CGP))
- AddMatcher(new CaptureFlagInputMatcher());
-
+
+ // If this node is known to have an input glue or if it *might* have an input
+ // glue, capture it as the glue input of the pattern.
+ if (N->NodeHasProperty(SDNPOptInGlue, CGP) ||
+ N->NodeHasProperty(SDNPInGlue, CGP))
+ AddMatcher(new CaptureGlueInputMatcher());
+
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
// Get the code suitable for matching this child. Move to the child, check
// it then move back to the parent.
@@ -410,14 +412,14 @@
// need to do a type check. Emit the check, apply the tyep to NodeNoTypes and
// reinfer any correlated types.
SmallVector<unsigned, 2> ResultsToTypeCheck;
-
+
for (unsigned i = 0, e = NodeNoTypes->getNumTypes(); i != e; ++i) {
if (NodeNoTypes->getExtType(i) == N->getExtType(i)) continue;
NodeNoTypes->setType(i, N->getExtType(i));
InferPossibleTypes();
ResultsToTypeCheck.push_back(i);
}
-
+
// 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()) {
@@ -435,16 +437,16 @@
return;
}
}
-
+
if (N->isLeaf())
EmitLeafMatchCode(N);
else
EmitOperatorMatchCode(N, NodeNoTypes);
-
+
// If there are node predicates for this node, generate their checks.
for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i)
AddMatcher(new CheckPredicateMatcher(N->getPredicateFns()[i]));
-
+
for (unsigned i = 0, e = ResultsToTypeCheck.size(); i != e; ++i)
AddMatcher(new CheckTypeMatcher(N->getType(ResultsToTypeCheck[i]),
ResultsToTypeCheck[i]));
@@ -463,27 +465,27 @@
const std::vector<Record*> &OpNodes = CP->getRootNodes();
assert(!OpNodes.empty() &&"Complex Pattern must specify what it can match");
if (Variant >= OpNodes.size()) return true;
-
+
AddMatcher(new CheckOpcodeMatcher(CGP.getSDNodeInfo(OpNodes[Variant])));
} else {
if (Variant != 0) return true;
}
-
+
// Emit the matcher for the pattern structure and types.
EmitMatchCode(Pattern.getSrcPattern(), PatWithNoTypes);
-
+
// If the pattern has a predicate on it (e.g. only enabled when a subtarget
// feature is around, do the check).
if (!Pattern.getPredicateCheck().empty())
AddMatcher(new CheckPatternPredicateMatcher(Pattern.getPredicateCheck()));
-
+
// Now that we've completed the structural type match, emit any ComplexPattern
// checks (e.g. addrmode matches). We emit this after the structural match
// because they are generally more expensive to evaluate and more difficult to
// factor.
for (unsigned i = 0, e = MatchedComplexPatterns.size(); i != e; ++i) {
const TreePatternNode *N = MatchedComplexPatterns[i].first;
-
+
// Remember where the results of this match get stuck.
MatchedComplexPatterns[i].second = NextRecordedOperandNo;
@@ -492,15 +494,15 @@
assert(!N->getName().empty() && RecNodeEntry &&
"Complex pattern should have a name and slot");
--RecNodeEntry; // Entries in VariableMap are biased.
-
+
const ComplexPattern &CP =
CGP.getComplexPattern(((DefInit*)N->getLeafValue())->getDef());
-
+
// Emit a CheckComplexPat operation, which does the match (aborting if it
// fails) and pushes the matched operands onto the recorded nodes list.
AddMatcher(new CheckComplexPatMatcher(CP, RecNodeEntry,
N->getName(), NextRecordedOperandNo));
-
+
// Record the right number of operands.
NextRecordedOperandNo += CP.getNumOperands();
if (CP.hasProperty(SDNPHasChain)) {
@@ -508,17 +510,17 @@
// fact that we just recorded a chain input. The chain input will be
// matched as the last operand of the predicate if it was successful.
++NextRecordedOperandNo; // Chained node operand.
-
+
// It is the last operand recorded.
assert(NextRecordedOperandNo > 1 &&
"Should have recorded input/result chains at least!");
MatchedChainNodes.push_back(NextRecordedOperandNo-1);
}
-
- // TODO: Complex patterns can't have output flags, if they did, we'd want
+
+ // TODO: Complex patterns can't have output glues, if they did, we'd want
// to record them.
}
-
+
return false;
}
@@ -530,7 +532,7 @@
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)) {
@@ -541,7 +543,7 @@
break;
}
assert(SlotNo != 0 && "Didn't get a slot number assigned?");
-
+
// 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)
@@ -562,62 +564,67 @@
return;
}
}
-
+
ResultOps.push_back(SlotNo);
}
void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N,
SmallVectorImpl<unsigned> &ResultOps) {
assert(N->isLeaf() && "Must be a leaf");
-
+
if (IntInit *II = dynamic_cast<IntInit*>(N->getLeafValue())) {
AddMatcher(new EmitIntegerMatcher(II->getValue(), N->getType(0)));
ResultOps.push_back(NextRecordedOperandNo++);
return;
}
-
+
// If this is an explicit register reference, handle it.
if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) {
- if (DI->getDef()->isSubClassOf("Register")) {
- AddMatcher(new EmitRegisterMatcher(DI->getDef(), N->getType(0)));
+ Record *Def = DI->getDef();
+ if (Def->isSubClassOf("Register")) {
+ const CodeGenRegister *Reg =
+ CGP.getTargetInfo().getRegBank().getReg(Def);
+ AddMatcher(new EmitRegisterMatcher(Reg, N->getType(0)));
ResultOps.push_back(NextRecordedOperandNo++);
return;
}
-
- if (DI->getDef()->getName() == "zero_reg") {
+
+ if (Def->getName() == "zero_reg") {
AddMatcher(new EmitRegisterMatcher(0, N->getType(0)));
ResultOps.push_back(NextRecordedOperandNo++);
return;
}
-
+
// Handle a reference to a register class. This is used
// in COPY_TO_SUBREG instructions.
- if (DI->getDef()->isSubClassOf("RegisterClass")) {
- std::string Value = getQualifiedName(DI->getDef()) + "RegClassID";
+ if (Def->isSubClassOf("RegisterOperand"))
+ Def = Def->getValueAsDef("RegClass");
+ if (Def->isSubClassOf("RegisterClass")) {
+ std::string Value = getQualifiedName(Def) + "RegClassID";
AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32));
ResultOps.push_back(NextRecordedOperandNo++);
return;
}
// Handle a subregister index. This is used for INSERT_SUBREG etc.
- if (DI->getDef()->isSubClassOf("SubRegIndex")) {
- std::string Value = getQualifiedName(DI->getDef());
+ if (Def->isSubClassOf("SubRegIndex")) {
+ std::string Value = getQualifiedName(Def);
AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32));
ResultOps.push_back(NextRecordedOperandNo++);
return;
}
}
-
+
errs() << "unhandled leaf node: \n";
N->dump();
}
/// GetInstPatternNode - Get the pattern for an instruction.
-///
+///
const TreePatternNode *MatcherGen::
GetInstPatternNode(const DAGInstruction &Inst, const TreePatternNode *N) {
const TreePattern *InstPat = Inst.getPattern();
-
+
// FIXME2?: Assume actual pattern comes before "implicit".
TreePatternNode *InstPatNode;
if (InstPat)
@@ -626,14 +633,43 @@
InstPatNode = Pattern.getSrcPattern();
else
return 0;
-
+
if (InstPatNode && !InstPatNode->isLeaf() &&
InstPatNode->getOperator()->getName() == "set")
InstPatNode = InstPatNode->getChild(InstPatNode->getNumChildren()-1);
-
+
return InstPatNode;
}
+static bool
+mayInstNodeLoadOrStore(const TreePatternNode *N,
+ const CodeGenDAGPatterns &CGP) {
+ Record *Op = N->getOperator();
+ const CodeGenTarget &CGT = CGP.getTargetInfo();
+ CodeGenInstruction &II = CGT.getInstruction(Op);
+ return II.mayLoad || II.mayStore;
+}
+
+static unsigned
+numNodesThatMayLoadOrStore(const TreePatternNode *N,
+ const CodeGenDAGPatterns &CGP) {
+ if (N->isLeaf())
+ return 0;
+
+ Record *OpRec = N->getOperator();
+ if (!OpRec->isSubClassOf("Instruction"))
+ return 0;
+
+ unsigned Count = 0;
+ if (mayInstNodeLoadOrStore(N, CGP))
+ ++Count;
+
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
+ Count += numNodesThatMayLoadOrStore(N->getChild(i), CGP);
+
+ return Count;
+}
+
void MatcherGen::
EmitResultInstructionAsOperand(const TreePatternNode *N,
SmallVectorImpl<unsigned> &OutputOps) {
@@ -641,7 +677,7 @@
const CodeGenTarget &CGT = CGP.getTargetInfo();
CodeGenInstruction &II = CGT.getInstruction(Op);
const DAGInstruction &Inst = CGP.getInstruction(Op);
-
+
// If we can, get the pattern for the instruction we're generating. We derive
// a variety of information from this pattern, such as whether it has a chain.
//
@@ -650,27 +686,27 @@
// nodes can't duplicate.
const TreePatternNode *InstPatNode = GetInstPatternNode(Inst, N);
- // NodeHasChain - Whether the instruction node we're creating takes chains.
+ // NodeHasChain - Whether the instruction node we're creating takes chains.
bool NodeHasChain = InstPatNode &&
InstPatNode->TreeHasProperty(SDNPHasChain, CGP);
-
+
bool isRoot = N == Pattern.getDstPattern();
- // TreeHasOutFlag - True if this tree has a flag.
- bool TreeHasInFlag = false, TreeHasOutFlag = false;
+ // TreeHasOutGlue - True if this tree has glue.
+ bool TreeHasInGlue = false, TreeHasOutGlue = false;
if (isRoot) {
const TreePatternNode *SrcPat = Pattern.getSrcPattern();
- TreeHasInFlag = SrcPat->TreeHasProperty(SDNPOptInFlag, CGP) ||
- SrcPat->TreeHasProperty(SDNPInFlag, CGP);
-
+ TreeHasInGlue = SrcPat->TreeHasProperty(SDNPOptInGlue, CGP) ||
+ SrcPat->TreeHasProperty(SDNPInGlue, CGP);
+
// FIXME2: this is checking the entire pattern, not just the node in
// question, doing this just for the root seems like a total hack.
- TreeHasOutFlag = SrcPat->TreeHasProperty(SDNPOutFlag, CGP);
+ TreeHasOutGlue = SrcPat->TreeHasProperty(SDNPOutGlue, CGP);
}
// NumResults - This is the number of results produced by the instruction in
// the "outs" list.
- unsigned NumResults = Inst.getNumResults();
+ unsigned NumResults = Inst.getNumResults();
// Loop over all of the operands of the instruction pattern, emitting code
// to fill them all in. The node 'N' usually has number children equal to
@@ -679,41 +715,41 @@
// in the 'execute always' values. Match up the node operands to the
// instruction operands to do this.
SmallVector<unsigned, 8> InstOps;
- for (unsigned ChildNo = 0, InstOpNo = NumResults, e = II.OperandList.size();
+ for (unsigned ChildNo = 0, InstOpNo = NumResults, e = II.Operands.size();
InstOpNo != e; ++InstOpNo) {
-
+
// Determine what to emit for this operand.
- Record *OperandNode = II.OperandList[InstOpNo].Rec;
+ Record *OperandNode = II.Operands[InstOpNo].Rec;
if ((OperandNode->isSubClassOf("PredicateOperand") ||
OperandNode->isSubClassOf("OptionalDefOperand")) &&
!CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) {
// This is a predicate or optional def operand; emit the
// 'default ops' operands.
const DAGDefaultOperand &DefaultOp
- = CGP.getDefaultOperand(OperandNode);
+ = CGP.getDefaultOperand(OperandNode);
for (unsigned i = 0, e = DefaultOp.DefaultOps.size(); i != e; ++i)
EmitResultOperand(DefaultOp.DefaultOps[i], InstOps);
continue;
}
-
+
const TreePatternNode *Child = N->getChild(ChildNo);
-
+
// Otherwise this is a normal operand or a predicate operand without
// 'execute always'; emit it.
unsigned BeforeAddingNumOps = InstOps.size();
EmitResultOperand(Child, InstOps);
assert(InstOps.size() > BeforeAddingNumOps && "Didn't add any operands");
-
+
// If the operand is an instruction and it produced multiple results, just
// take the first one.
if (!Child->isLeaf() && Child->getOperator()->isSubClassOf("Instruction"))
InstOps.resize(BeforeAddingNumOps+1);
-
+
++ChildNo;
}
-
- // If this node has an input flag or explicitly specified input physregs, we
- // need to add chained and flagged copyfromreg nodes and materialize the flag
+
+ // If this node has input glue or explicitly specified input physregs, we
+ // need to add chained and glued copyfromreg nodes and materialize the glue
// input.
if (isRoot && !PhysRegInputs.empty()) {
// Emit all of the CopyToReg nodes for the input physical registers. These
@@ -721,18 +757,18 @@
for (unsigned i = 0, e = PhysRegInputs.size(); i != e; ++i)
AddMatcher(new EmitCopyToRegMatcher(PhysRegInputs[i].second,
PhysRegInputs[i].first));
- // Even if the node has no other flag inputs, the resultant node must be
- // flagged to the CopyFromReg nodes we just generated.
- TreeHasInFlag = true;
+ // Even if the node has no other glue inputs, the resultant node must be
+ // glued to the CopyFromReg nodes we just generated.
+ TreeHasInGlue = true;
}
-
- // Result order: node results, chain, flags
-
+
+ // Result order: node results, chain, glue
+
// Determine the result types.
SmallVector<MVT::SimpleValueType, 4> ResultVTs;
for (unsigned i = 0, e = N->getNumTypes(); i != e; ++i)
ResultVTs.push_back(N->getType(i));
-
+
// If this is the root instruction of a pattern that has physical registers in
// its result pattern, add output VTs for them. For example, X86 has:
// (set AL, (mul ...))
@@ -744,7 +780,7 @@
Record *HandledReg = 0;
if (II.HasOneImplicitDefWithKnownVT(CGT) != MVT::Other)
HandledReg = II.ImplicitDefs[0];
-
+
for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i) {
Record *Reg = Pattern.getDstRegs()[i];
if (!Reg->isSubClassOf("Register") || Reg == HandledReg) continue;
@@ -759,36 +795,41 @@
if (isRoot &&
(Pattern.getSrcPattern()->NodeHasProperty(SDNPVariadic, CGP)))
NumFixedArityOperands = Pattern.getSrcPattern()->getNumChildren();
-
- // If this is the root node and any of the nodes matched nodes in the input
- // pattern have MemRefs in them, have the interpreter collect them and plop
- // them onto this node.
- //
- // FIXME3: This is actively incorrect for result patterns where the root of
- // the pattern is not the memory reference and is also incorrect when the
- // result pattern has multiple memory-referencing instructions. For example,
- // in the X86 backend, this pattern causes the memrefs to get attached to the
- // CVTSS2SDrr instead of the MOVSSrm:
- //
- // def : Pat<(extloadf32 addr:$src),
- // (CVTSS2SDrr (MOVSSrm addr:$src))>;
- //
- bool NodeHasMemRefs =
- isRoot && Pattern.getSrcPattern()->TreeHasProperty(SDNPMemOperand, CGP);
- assert((!ResultVTs.empty() || TreeHasOutFlag || NodeHasChain) &&
+ // If this is the root node and multiple matched nodes in the input pattern
+ // have MemRefs in them, have the interpreter collect them and plop them onto
+ // this node. If there is just one node with MemRefs, leave them on that node
+ // even if it is not the root.
+ //
+ // FIXME3: This is actively incorrect for result patterns with multiple
+ // memory-referencing instructions.
+ bool PatternHasMemOperands =
+ Pattern.getSrcPattern()->TreeHasProperty(SDNPMemOperand, CGP);
+
+ bool NodeHasMemRefs = false;
+ if (PatternHasMemOperands) {
+ unsigned NumNodesThatLoadOrStore =
+ numNodesThatMayLoadOrStore(Pattern.getDstPattern(), CGP);
+ bool NodeIsUniqueLoadOrStore = mayInstNodeLoadOrStore(N, CGP) &&
+ NumNodesThatLoadOrStore == 1;
+ NodeHasMemRefs =
+ NodeIsUniqueLoadOrStore || (isRoot && (mayInstNodeLoadOrStore(N, CGP) ||
+ NumNodesThatLoadOrStore != 1));
+ }
+
+ assert((!ResultVTs.empty() || TreeHasOutGlue || NodeHasChain) &&
"Node has no result");
-
+
AddMatcher(new EmitNodeMatcher(II.Namespace+"::"+II.TheDef->getName(),
ResultVTs.data(), ResultVTs.size(),
InstOps.data(), InstOps.size(),
- NodeHasChain, TreeHasInFlag, TreeHasOutFlag,
+ NodeHasChain, TreeHasInGlue, TreeHasOutGlue,
NodeHasMemRefs, NumFixedArityOperands,
NextRecordedOperandNo));
-
- // The non-chain and non-flag results of the newly emitted node get recorded.
+
+ // The non-chain and non-glue results of the newly emitted node get recorded.
for (unsigned i = 0, e = ResultVTs.size(); i != e; ++i) {
- if (ResultVTs[i] == MVT::Other || ResultVTs[i] == MVT::Flag) break;
+ if (ResultVTs[i] == MVT::Other || ResultVTs[i] == MVT::Glue) break;
OutputOps.push_back(NextRecordedOperandNo++);
}
}
@@ -800,7 +841,7 @@
// Emit the operand.
SmallVector<unsigned, 8> InputOps;
-
+
// FIXME2: Could easily generalize this to support multiple inputs and outputs
// to the SDNodeXForm. For now we just support one input and one output like
// the old instruction selector.
@@ -839,7 +880,7 @@
if (!MatchedChainNodes.empty())
AddMatcher(new EmitMergeInputChainsMatcher
(MatchedChainNodes.data(), MatchedChainNodes.size()));
-
+
// Codegen the root of the result pattern, capturing the resulting values.
SmallVector<unsigned, 8> Ops;
EmitResultOperand(Pattern.getDstPattern(), Ops);
@@ -847,11 +888,11 @@
// At this point, we have however many values the result pattern produces.
// However, the input pattern might not need all of these. If there are
// excess values at the end (such as implicit defs of condition codes etc)
- // just lop them off. This doesn't need to worry about flags or chains, just
+ // just lop them off. This doesn't need to worry about glue or chains, just
// explicit results.
//
unsigned NumSrcResults = Pattern.getSrcPattern()->getNumTypes();
-
+
// If the pattern also has (implicit) results, count them as well.
if (!Pattern.getDstRegs().empty()) {
// If the root came from an implicit def in the instruction handling stuff,
@@ -865,23 +906,23 @@
if (II.HasOneImplicitDefWithKnownVT(CGT) != MVT::Other)
HandledReg = II.ImplicitDefs[0];
}
-
+
for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i) {
Record *Reg = Pattern.getDstRegs()[i];
if (!Reg->isSubClassOf("Register") || Reg == HandledReg) continue;
++NumSrcResults;
}
- }
-
+ }
+
assert(Ops.size() >= NumSrcResults && "Didn't provide enough results");
Ops.resize(NumSrcResults);
- // If the matched pattern covers nodes which define a flag result, emit a node
+ // 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 (!MatchedFlagResultNodes.empty())
- AddMatcher(new MarkFlagResultsMatcher(MatchedFlagResultNodes.data(),
- MatchedFlagResultNodes.size()));
-
+ if (!MatchedGlueResultNodes.empty())
+ AddMatcher(new MarkGlueResultsMatcher(MatchedGlueResultNodes.data(),
+ MatchedGlueResultNodes.size()));
+
AddMatcher(new CompleteMatchMatcher(Ops.data(), Ops.size(), Pattern));
}
@@ -896,12 +937,12 @@
// Generate the code for the matcher.
if (Gen.EmitMatcherCode(Variant))
return 0;
-
+
// 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
// with an "Emit <index>" command. This allows result generation stuff to be
// shared and factored?
-
+
// If the match succeeds, then we generate Pattern.
Gen.EmitResultCode();
diff --git a/src/LLVM/utils/TableGen/DAGISelMatcherOpt.cpp b/src/LLVM/utils/TableGen/DAGISelMatcherOpt.cpp
index c73bdb9..f996422 100644
--- a/src/LLVM/utils/TableGen/DAGISelMatcherOpt.cpp
+++ b/src/LLVM/utils/TableGen/DAGISelMatcherOpt.cpp
@@ -18,7 +18,6 @@
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
-#include <vector>
using namespace llvm;
/// ContractNodes - Turn multiple matcher node patterns like 'MoveChild+Record'
@@ -75,7 +74,7 @@
// MarkFlagResults->EmitNode->CompleteMatch when we can to encourage
// MorphNodeTo formation. This is safe because MarkFlagResults never refers
// to the root of the pattern.
- if (isa<EmitNodeMatcher>(N) && isa<MarkFlagResultsMatcher>(N->getNext()) &&
+ if (isa<EmitNodeMatcher>(N) && isa<MarkGlueResultsMatcher>(N->getNext()) &&
isa<CompleteMatchMatcher>(N->getNext()->getNext())) {
// Unlink the two nodes from the list.
Matcher *EmitNode = MatcherPtr.take();
@@ -100,7 +99,7 @@
if (CM->getResult(i) != RootResultFirst+i)
ResultsMatch = false;
- // If the selected node defines a subset of the flag/chain results, we
+ // If the selected node defines a subset of the glue/chain results, we
// can't use MorphNodeTo. For example, we can't use MorphNodeTo if the
// matched pattern has a chain but the root node doesn't.
const PatternToMatch &Pattern = CM->getPattern();
@@ -109,23 +108,23 @@
Pattern.getSrcPattern()->NodeHasProperty(SDNPHasChain, CGP))
ResultsMatch = false;
- // If the matched node has a flag and the output root doesn't, we can't
+ // If the matched node has glue and the output root doesn't, we can't
// use MorphNodeTo.
//
- // NOTE: Strictly speaking, we don't have to check for the flag here
+ // NOTE: Strictly speaking, we don't have to check for glue here
// because the code in the pattern generator doesn't handle it right. We
// do it anyway for thoroughness.
if (!EN->hasOutFlag() &&
- Pattern.getSrcPattern()->NodeHasProperty(SDNPOutFlag, CGP))
+ Pattern.getSrcPattern()->NodeHasProperty(SDNPOutGlue, CGP))
ResultsMatch = false;
// If the root result node defines more results than the source root node
- // *and* has a chain or flag input, then we can't match it because it
- // would end up replacing the extra result with the chain/flag.
+ // *and* has a chain or glue input, then we can't match it because it
+ // would end up replacing the extra result with the chain/glue.
#if 0
- if ((EN->hasFlag() || EN->hasChain()) &&
- EN->getNumNonChainFlagVTs() > ... need to get no results reliably ...)
+ if ((EN->hasGlue() || EN->hasChain()) &&
+ EN->getNumNonChainGlueVTs() > ... need to get no results reliably ...)
ResultMatch = false;
#endif
diff --git a/src/LLVM/utils/TableGen/DisassemblerEmitter.cpp b/src/LLVM/utils/TableGen/DisassemblerEmitter.cpp
index 3284366..ff314e9 100644
--- a/src/LLVM/utils/TableGen/DisassemblerEmitter.cpp
+++ b/src/LLVM/utils/TableGen/DisassemblerEmitter.cpp
@@ -9,10 +9,12 @@
#include "DisassemblerEmitter.h"
#include "CodeGenTarget.h"
-#include "Record.h"
#include "X86DisassemblerTables.h"
#include "X86RecognizableInstr.h"
#include "ARMDecoderEmitter.h"
+#include "FixedLenDecoderEmitter.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
using namespace llvm;
using namespace llvm::X86Disassembler;
@@ -39,12 +41,12 @@
/// all cases as a 64-bit instruction with only OPSIZE set. (The XS prefix
/// may have effects on its execution, but does not change the instruction
/// returned.) This allows considerable space savings in other tables.
-/// - Four tables (ONEBYTE_SYM, TWOBYTE_SYM, THREEBYTE38_SYM, and
-/// THREEBYTE3A_SYM) contain the hierarchy that the decoder traverses while
-/// decoding an instruction. At the lowest level of this hierarchy are
-/// instruction UIDs, 16-bit integers that can be used to uniquely identify
-/// the instruction and correspond exactly to its position in the list of
-/// CodeGenInstructions for the target.
+/// - Six tables (ONEBYTE_SYM, TWOBYTE_SYM, THREEBYTE38_SYM, THREEBYTE3A_SYM,
+/// THREEBYTEA6_SYM, and THREEBYTEA7_SYM contain the hierarchy that the
+/// decoder traverses while decoding an instruction. At the lowest level of
+/// this hierarchy are instruction UIDs, 16-bit integers that can be used to
+/// uniquely identify the instruction and correspond exactly to its position
+/// in the list of CodeGenInstructions for the target.
/// - One table (INSTRUCTIONS_SYM) contains information about the operands of
/// each instruction and how to decode them.
///
@@ -94,7 +96,7 @@
/// instruction.
void DisassemblerEmitter::run(raw_ostream &OS) {
- CodeGenTarget Target;
+ CodeGenTarget Target(Records);
OS << "/*===- TableGen'erated file "
<< "---------------------------------------*- C -*-===*\n"
@@ -126,12 +128,16 @@
return;
}
- // Fixed-instruction-length targets use a common disassembler.
- if (Target.getName() == "ARM") {
- ARMDecoderEmitter(Records).run(OS);
+ // ARM and Thumb have a CHECK() macro to deal with DecodeStatuses.
+ if (Target.getName() == "ARM" ||
+ Target.getName() == "Thumb") {
+ FixedLenDecoderEmitter(Records,
+ "ARM",
+ "if (!Check(S, ", ")) return MCDisassembler::Fail;",
+ "S", "MCDisassembler::Fail",
+ " MCDisassembler::DecodeStatus S = MCDisassembler::Success;\n(void)S;").run(OS);
return;
- }
+ }
- throw TGError(Target.getTargetRecord()->getLoc(),
- "Unable to generate disassembler for this target");
+ FixedLenDecoderEmitter(Records, Target.getName()).run(OS);
}
diff --git a/src/LLVM/utils/TableGen/DisassemblerEmitter.h b/src/LLVM/utils/TableGen/DisassemblerEmitter.h
index 7229d81..63ee552 100644
--- a/src/LLVM/utils/TableGen/DisassemblerEmitter.h
+++ b/src/LLVM/utils/TableGen/DisassemblerEmitter.h
@@ -10,7 +10,7 @@
#ifndef DISASSEMBLEREMITTER_H
#define DISASSEMBLEREMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
namespace llvm {
diff --git a/src/LLVM/utils/TableGen/EDEmitter.cpp b/src/LLVM/utils/TableGen/EDEmitter.cpp
index 50ff9ea..abef70e 100644
--- a/src/LLVM/utils/TableGen/EDEmitter.cpp
+++ b/src/LLVM/utils/TableGen/EDEmitter.cpp
@@ -17,14 +17,13 @@
#include "AsmWriterInst.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/MC/EDInstInfo.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
-#include <map>
#include <string>
#include <vector>
@@ -35,22 +34,22 @@
///////////////////////////////////////////////////////////
namespace {
-
+
class EnumEmitter {
private:
std::string Name;
std::vector<std::string> Entries;
public:
- EnumEmitter(const char *N) : Name(N) {
+ EnumEmitter(const char *N) : Name(N) {
}
- int addEntry(const char *e) {
+ int addEntry(const char *e) {
Entries.push_back(std::string(e));
- return Entries.size() - 1;
+ return Entries.size() - 1;
}
void emit(raw_ostream &o, unsigned int &i) {
o.indent(i) << "enum " << Name.c_str() << " {" << "\n";
i += 2;
-
+
unsigned int index = 0;
unsigned int numEntries = Entries.size();
for (index = 0; index < numEntries; ++index) {
@@ -59,15 +58,15 @@
o << ",";
o << "\n";
}
-
+
i -= 2;
o.indent(i) << "};" << "\n";
}
-
+
void emitAsFlags(raw_ostream &o, unsigned int &i) {
o.indent(i) << "enum " << Name.c_str() << " {" << "\n";
i += 2;
-
+
unsigned int index = 0;
unsigned int numEntries = Entries.size();
unsigned int flag = 1;
@@ -78,46 +77,18 @@
o << "\n";
flag <<= 1;
}
-
+
i -= 2;
o.indent(i) << "};" << "\n";
}
};
- class StructEmitter {
- private:
- std::string Name;
- typedef std::pair<const char*, const char*> member;
- std::vector< member > Members;
- public:
- StructEmitter(const char *N) : Name(N) {
- }
- void addMember(const char *t, const char *n) {
- member m(t, n);
- Members.push_back(m);
- }
- void emit(raw_ostream &o, unsigned int &i) {
- o.indent(i) << "struct " << Name.c_str() << " {" << "\n";
- i += 2;
-
- unsigned int index = 0;
- unsigned int numMembers = Members.size();
- for (index = 0; index < numMembers; ++index) {
- o.indent(i) << Members[index].first << " ";
- o.indent(i) << Members[index].second << ";" << "\n";
- }
-
- i -= 2;
- o.indent(i) << "};" << "\n";
- }
- };
-
class ConstantEmitter {
public:
virtual ~ConstantEmitter() { }
virtual void emit(raw_ostream &o, unsigned int &i) = 0;
};
-
+
class LiteralConstantEmitter : public ConstantEmitter {
private:
bool IsNumber;
@@ -126,11 +97,7 @@
const char* String;
};
public:
- LiteralConstantEmitter(const char *string) :
- IsNumber(false),
- String(string) {
- }
- LiteralConstantEmitter(int number = 0) :
+ LiteralConstantEmitter(int number = 0) :
IsNumber(true),
Number(number) {
}
@@ -139,11 +106,6 @@
Number = 0;
String = string;
}
- void set(int number) {
- IsNumber = true;
- String = NULL;
- Number = number;
- }
bool is(const char *string) {
return !strcmp(String, string);
}
@@ -154,7 +116,7 @@
o << String;
}
};
-
+
class CompoundConstantEmitter : public ConstantEmitter {
private:
unsigned int Padding;
@@ -164,7 +126,7 @@
}
CompoundConstantEmitter &addEntry(ConstantEmitter *e) {
Entries.push_back(e);
-
+
return *this;
}
~CompoundConstantEmitter() {
@@ -177,12 +139,12 @@
void emit(raw_ostream &o, unsigned int &i) {
o << "{" << "\n";
i += 2;
-
+
unsigned int index;
unsigned int numEntries = Entries.size();
-
+
unsigned int numToPrint;
-
+
if (Padding) {
if (numEntries > Padding) {
fprintf(stderr, "%u entries but %u padding\n", numEntries, Padding);
@@ -192,24 +154,24 @@
} else {
numToPrint = numEntries;
}
-
+
for (index = 0; index < numToPrint; ++index) {
o.indent(i);
if (index < numEntries)
Entries[index]->emit(o, i);
else
o << "-1";
-
+
if (index < (numToPrint - 1))
o << ",";
o << "\n";
}
-
+
i -= 2;
o.indent(i) << "}";
}
};
-
+
class FlagsConstantEmitter : public ConstantEmitter {
private:
std::vector<std::string> Flags;
@@ -225,7 +187,7 @@
unsigned int numFlags = Flags.size();
if (numFlags == 0)
o << "0";
-
+
for (index = 0; index < numFlags; ++index) {
o << Flags[index].c_str();
if (index < (numFlags - 1))
@@ -255,15 +217,15 @@
const CodeGenInstruction &inst,
unsigned syntax) {
unsigned int numArgs = 0;
-
+
AsmWriterInst awInst(inst, syntax, -1, -1);
-
+
std::vector<AsmWriterOperand>::iterator operandIterator;
-
+
for (operandIterator = awInst.Operands.begin();
operandIterator != awInst.Operands.end();
++operandIterator) {
- if (operandIterator->OperandType ==
+ if (operandIterator->OperandType ==
AsmWriterOperand::isMachineInstrOperand) {
operandOrder->addEntry(
new LiteralConstantEmitter(operandIterator->CGIOpNo));
@@ -294,12 +256,15 @@
REG("GR8");
REG("GR8_NOREX");
REG("GR16");
+ REG("GR16_NOAX");
REG("GR32");
+ REG("GR32_NOAX");
REG("GR32_NOREX");
REG("GR32_TC");
REG("FR32");
REG("RFP32");
REG("GR64");
+ REG("GR64_NOAX");
REG("GR64_TC");
REG("FR64");
REG("VR64");
@@ -311,17 +276,18 @@
REG("SEGMENT_REG");
REG("DEBUG_REG");
REG("CONTROL_REG");
-
+
IMM("i8imm");
IMM("i16imm");
IMM("i16i8imm");
IMM("i32imm");
IMM("i32i8imm");
+ IMM("u32u8imm");
IMM("i64imm");
IMM("i64i8imm");
IMM("i64i32imm");
IMM("SSECC");
-
+
// all R, I, R, I, R
MEM("i8mem");
MEM("i8mem_NOREX");
@@ -343,12 +309,12 @@
MEM("f128mem");
MEM("f256mem");
MEM("opaque512mem");
-
+
// all R, I, R, I
LEA("lea32mem");
LEA("lea64_32mem");
LEA("lea64mem");
-
+
// all I
PCR("i16imm_pcrel");
PCR("i32imm_pcrel");
@@ -359,7 +325,12 @@
PCR("offset32");
PCR("offset64");
PCR("brtarget");
-
+ PCR("uncondbrtarget");
+ PCR("bltarget");
+
+ // all I, ARM mode only, conditional/unconditional
+ PCR("br_target");
+ PCR("bl_target");
return 1;
}
@@ -381,19 +352,19 @@
const CodeGenInstruction &inst) {
if (!inst.TheDef->isSubClassOf("X86Inst"))
return;
-
+
unsigned int index;
- unsigned int numOperands = inst.OperandList.size();
-
+ unsigned int numOperands = inst.Operands.size();
+
for (index = 0; index < numOperands; ++index) {
- const CodeGenInstruction::OperandInfo &operandInfo =
- inst.OperandList[index];
+ const CGIOperandList::OperandInfo &operandInfo = inst.Operands[index];
Record &rec = *operandInfo.Rec;
-
- if (X86TypeFromOpName(operandTypes[index], rec.getName())) {
+
+ if (X86TypeFromOpName(operandTypes[index], rec.getName()) &&
+ !rec.isSubClassOf("PointerLikeRegClass")) {
errs() << "Operand type: " << rec.getName().c_str() << "\n";
errs() << "Operand name: " << operandInfo.Name.c_str() << "\n";
- errs() << "Instruction mame: " << inst.TheDef->getName().c_str() << "\n";
+ errs() << "Instruction name: " << inst.TheDef->getName().c_str() << "\n";
llvm_unreachable("Unhandled type");
}
}
@@ -412,9 +383,9 @@
const char *opName,
const char *opFlag) {
unsigned opIndex;
-
- opIndex = inst.getOperandNamed(std::string(opName));
-
+
+ opIndex = inst.Operands.getOperandNamed(std::string(opName));
+
operandFlags[opIndex]->addEntry(opFlag);
}
@@ -451,7 +422,7 @@
}
/// X86ExtractSemantics - Performs various checks on the name of an X86
-/// instruction to determine what sort of an instruction it is and then adds
+/// instruction to determine what sort of an instruction it is and then adds
/// the appropriate flags to the instruction and its operands
///
/// @arg instType - A reference to the type for the instruction as a whole
@@ -462,7 +433,7 @@
FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS],
const CodeGenInstruction &inst) {
const std::string &name = inst.TheDef->getName();
-
+
if (name.find("MOV") != name.npos) {
if (name.find("MOV_V") != name.npos) {
// ignore (this is a pseudoinstruction)
@@ -487,7 +458,7 @@
MOV("src", "dst");
}
}
-
+
if (name.find("JMP") != name.npos ||
name.find("J") == 0) {
if (name.find("FAR") != name.npos && name.find("i") != name.npos) {
@@ -496,10 +467,14 @@
BRANCH("dst");
}
}
-
+
if (name.find("PUSH") != name.npos) {
- if (name.find("FS") != name.npos ||
- name.find("GS") != name.npos) {
+ if (name.find("CS") != name.npos ||
+ name.find("DS") != name.npos ||
+ name.find("ES") != name.npos ||
+ name.find("FS") != name.npos ||
+ name.find("GS") != name.npos ||
+ name.find("SS") != name.npos) {
instType.set("kInstructionTypePush");
// TODO add support for fixed operands
} else if (name.find("F") != name.npos) {
@@ -514,12 +489,16 @@
PUSH("reg");
}
}
-
+
if (name.find("POP") != name.npos) {
if (name.find("POPCNT") != name.npos) {
// ignore (not a real pop)
- } else if (name.find("FS") != name.npos ||
- name.find("GS") != name.npos) {
+ } else if (name.find("CS") != name.npos ||
+ name.find("DS") != name.npos ||
+ name.find("ES") != name.npos ||
+ name.find("FS") != name.npos ||
+ name.find("GS") != name.npos ||
+ name.find("SS") != name.npos) {
instType.set("kInstructionTypePop");
// TODO add support for fixed operands
} else if (name.find("F") != name.npos) {
@@ -532,7 +511,7 @@
POP("reg");
}
}
-
+
if (name.find("CALL") != name.npos) {
if (name.find("ADJ") != name.npos) {
// ignore (not a call)
@@ -546,7 +525,7 @@
CALL("dst");
}
}
-
+
if (name.find("RET") != name.npos) {
RETURN();
}
@@ -579,6 +558,8 @@
const std::string &name) {
REG("GPR");
REG("rGPR");
+ REG("GPRnopc");
+ REG("GPRsp");
REG("tcGPR");
REG("cc_out");
REG("s_cc_out");
@@ -590,68 +571,138 @@
REG("QPR");
REG("QQPR");
REG("QQQQPR");
-
+
IMM("i32imm");
+ IMM("i32imm_hilo16");
IMM("bf_inv_mask_imm");
+ IMM("lsb_pos_imm");
+ IMM("width_imm");
IMM("jtblock_operand");
IMM("nohash_imm");
+ IMM("p_imm");
+ IMM("c_imm");
+ IMM("coproc_option_imm");
+ IMM("imod_op");
+ IMM("iflags_op");
IMM("cpinst_operand");
+ IMM("setend_op");
IMM("cps_opt");
IMM("vfp_f64imm");
IMM("vfp_f32imm");
+ IMM("memb_opt");
IMM("msr_mask");
IMM("neg_zero");
IMM("imm0_31");
+ IMM("imm0_31_m1");
+ IMM("imm1_16");
+ IMM("imm1_32");
IMM("nModImm");
+ IMM("imm0_7");
+ IMM("imm0_15");
+ IMM("imm0_255");
IMM("imm0_4095");
+ IMM("imm0_65535");
+ IMM("imm0_65535_expr");
+ IMM("imm24b");
+ IMM("pkh_lsl_amt");
+ IMM("pkh_asr_amt");
IMM("jt2block_operand");
- IMM("t_imm_s4");
+ IMM("t_imm0_1020s4");
+ IMM("t_imm0_508s4");
IMM("pclabel");
-
+ IMM("adrlabel");
+ IMM("t_adrlabel");
+ IMM("t2adrlabel");
+ IMM("shift_imm");
+ IMM("t2_shift_imm");
+ IMM("neon_vcvt_imm32");
+ IMM("shr_imm8");
+ IMM("shr_imm16");
+ IMM("shr_imm32");
+ IMM("shr_imm64");
+ IMM("t2ldrlabel");
+ IMM("postidx_imm8");
+ IMM("postidx_imm8s4");
+ IMM("imm_sr");
+ IMM("imm1_31");
+ IMM("VectorIndex8");
+ IMM("VectorIndex16");
+ IMM("VectorIndex32");
+
MISC("brtarget", "kOperandTypeARMBranchTarget"); // ?
- MISC("so_reg", "kOperandTypeARMSoReg"); // R, R, I
+ MISC("uncondbrtarget", "kOperandTypeARMBranchTarget"); // ?
+ MISC("t_brtarget", "kOperandTypeARMBranchTarget"); // ?
+ MISC("t_bcctarget", "kOperandTypeARMBranchTarget"); // ?
+ MISC("t_cbtarget", "kOperandTypeARMBranchTarget"); // ?
+ MISC("bltarget", "kOperandTypeARMBranchTarget"); // ?
+
+ MISC("br_target", "kOperandTypeARMBranchTarget"); // ?
+ MISC("bl_target", "kOperandTypeARMBranchTarget"); // ?
+ MISC("blx_target", "kOperandTypeARMBranchTarget"); // ?
+
+ MISC("t_bltarget", "kOperandTypeARMBranchTarget"); // ?
+ MISC("t_blxtarget", "kOperandTypeARMBranchTarget"); // ?
+ MISC("so_reg_imm", "kOperandTypeARMSoRegReg"); // R, R, I
+ MISC("so_reg_reg", "kOperandTypeARMSoRegImm"); // R, R, I
+ MISC("shift_so_reg_reg", "kOperandTypeARMSoRegReg"); // R, R, I
+ MISC("shift_so_reg_imm", "kOperandTypeARMSoRegImm"); // R, R, I
MISC("t2_so_reg", "kOperandTypeThumb2SoReg"); // R, I
MISC("so_imm", "kOperandTypeARMSoImm"); // I
+ MISC("rot_imm", "kOperandTypeARMRotImm"); // I
MISC("t2_so_imm", "kOperandTypeThumb2SoImm"); // I
MISC("so_imm2part", "kOperandTypeARMSoImm2Part"); // I
MISC("pred", "kOperandTypeARMPredicate"); // I, R
MISC("it_pred", "kOperandTypeARMPredicate"); // I
+ MISC("addrmode_imm12", "kOperandTypeAddrModeImm12"); // R, I
+ MISC("ldst_so_reg", "kOperandTypeLdStSOReg"); // R, R, I
+ MISC("postidx_reg", "kOperandTypeARMAddrMode3Offset"); // R, I
MISC("addrmode2", "kOperandTypeARMAddrMode2"); // R, R, I
- MISC("am2offset", "kOperandTypeARMAddrMode2Offset"); // R, I
+ MISC("am2offset_reg", "kOperandTypeARMAddrMode2Offset"); // R, I
+ MISC("am2offset_imm", "kOperandTypeARMAddrMode2Offset"); // R, I
MISC("addrmode3", "kOperandTypeARMAddrMode3"); // R, R, I
MISC("am3offset", "kOperandTypeARMAddrMode3Offset"); // R, I
- MISC("addrmode4", "kOperandTypeARMAddrMode4"); // R, I
+ MISC("ldstm_mode", "kOperandTypeARMLdStmMode"); // I
MISC("addrmode5", "kOperandTypeARMAddrMode5"); // R, I
MISC("addrmode6", "kOperandTypeARMAddrMode6"); // R, R, I, I
MISC("am6offset", "kOperandTypeARMAddrMode6Offset"); // R, I, I
+ MISC("addrmode6dup", "kOperandTypeARMAddrMode6"); // R, R, I, I
+ MISC("addrmode6oneL32", "kOperandTypeARMAddrMode6"); // R, R, I, I
MISC("addrmodepc", "kOperandTypeARMAddrModePC"); // R, I
+ MISC("addr_offset_none", "kOperandTypeARMAddrMode7"); // R
MISC("reglist", "kOperandTypeARMRegisterList"); // I, R, ...
+ MISC("dpr_reglist", "kOperandTypeARMDPRRegisterList"); // I, R, ...
+ MISC("spr_reglist", "kOperandTypeARMSPRRegisterList"); // I, R, ...
MISC("it_mask", "kOperandTypeThumbITMask"); // I
+ MISC("t2addrmode_reg", "kOperandTypeThumb2AddrModeReg"); // R
+ MISC("t2addrmode_posimm8", "kOperandTypeThumb2AddrModeImm8"); // R, I
+ MISC("t2addrmode_negimm8", "kOperandTypeThumb2AddrModeImm8"); // R, I
MISC("t2addrmode_imm8", "kOperandTypeThumb2AddrModeImm8"); // R, I
MISC("t2am_imm8_offset", "kOperandTypeThumb2AddrModeImm8Offset");//I
MISC("t2addrmode_imm12", "kOperandTypeThumb2AddrModeImm12"); // R, I
MISC("t2addrmode_so_reg", "kOperandTypeThumb2AddrModeSoReg"); // R, R, I
MISC("t2addrmode_imm8s4", "kOperandTypeThumb2AddrModeImm8s4"); // R, I
- MISC("t2am_imm8s4_offset", "kOperandTypeThumb2AddrModeImm8s4Offset");
+ MISC("t2addrmode_imm0_1020s4", "kOperandTypeThumb2AddrModeImm8s4"); // R, I
+ MISC("t2am_imm8s4_offset", "kOperandTypeThumb2AddrModeImm8s4Offset");
// R, I
MISC("tb_addrmode", "kOperandTypeARMTBAddrMode"); // I
- MISC("t_addrmode_s1", "kOperandTypeThumbAddrModeS1"); // R, I, R
- MISC("t_addrmode_s2", "kOperandTypeThumbAddrModeS2"); // R, I, R
- MISC("t_addrmode_s4", "kOperandTypeThumbAddrModeS4"); // R, I, R
+ MISC("t_addrmode_rrs1", "kOperandTypeThumbAddrModeRegS1"); // R, R
+ MISC("t_addrmode_rrs2", "kOperandTypeThumbAddrModeRegS2"); // R, R
+ MISC("t_addrmode_rrs4", "kOperandTypeThumbAddrModeRegS4"); // R, R
+ MISC("t_addrmode_is1", "kOperandTypeThumbAddrModeImmS1"); // R, I
+ MISC("t_addrmode_is2", "kOperandTypeThumbAddrModeImmS2"); // R, I
+ MISC("t_addrmode_is4", "kOperandTypeThumbAddrModeImmS4"); // R, I
MISC("t_addrmode_rr", "kOperandTypeThumbAddrModeRR"); // R, R
MISC("t_addrmode_sp", "kOperandTypeThumbAddrModeSP"); // R, I
-
+ MISC("t_addrmode_pc", "kOperandTypeThumbAddrModePC"); // R, I
+ MISC("addrmode_tbb", "kOperandTypeThumbAddrModeRR"); // R, R
+ MISC("addrmode_tbh", "kOperandTypeThumbAddrModeRR"); // R, R
+
return 1;
}
-#undef SOREG
-#undef SOIMM
-#undef PRED
#undef REG
#undef MEM
-#undef LEA
-#undef IMM
-#undef PCR
+#undef MISC
#undef SET
@@ -666,25 +717,24 @@
if (!inst.TheDef->isSubClassOf("InstARM") &&
!inst.TheDef->isSubClassOf("InstThumb"))
return;
-
+
unsigned int index;
- unsigned int numOperands = inst.OperandList.size();
-
+ unsigned int numOperands = inst.Operands.size();
+
if (numOperands > EDIS_MAX_OPERANDS) {
- errs() << "numOperands == " << numOperands << " > " <<
+ errs() << "numOperands == " << numOperands << " > " <<
EDIS_MAX_OPERANDS << '\n';
llvm_unreachable("Too many operands");
}
-
+
for (index = 0; index < numOperands; ++index) {
- const CodeGenInstruction::OperandInfo &operandInfo =
- inst.OperandList[index];
+ const CGIOperandList::OperandInfo &operandInfo = inst.Operands[index];
Record &rec = *operandInfo.Rec;
-
+
if (ARMFlagFromOpName(operandTypes[index], rec.getName())) {
errs() << "Operand type: " << rec.getName() << '\n';
errs() << "Operand name: " << operandInfo.Name << '\n';
- errs() << "Instruction mame: " << inst.TheDef->getName() << '\n';
+ errs() << "Instruction name: " << inst.TheDef->getName() << '\n';
llvm_unreachable("Unhandled type");
}
}
@@ -696,7 +746,7 @@
}
/// ARMExtractSemantics - Performs various checks on the name of an ARM
-/// instruction to determine what sort of an instruction it is and then adds
+/// instruction to determine what sort of an instruction it is and then adds
/// the appropriate flags to the instruction and its operands
///
/// @arg instType - A reference to the type for the instruction as a whole
@@ -709,7 +759,7 @@
FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS],
const CodeGenInstruction &inst) {
const std::string &name = inst.TheDef->getName();
-
+
if (name == "tBcc" ||
name == "tB" ||
name == "t2Bcc" ||
@@ -718,7 +768,7 @@
name == "tCBNZ") {
BRANCH("target");
}
-
+
if (name == "tBLr9" ||
name == "BLr9_pred" ||
name == "tBLXi_r9" ||
@@ -727,9 +777,9 @@
name == "t2BXJ" ||
name == "BXJ") {
BRANCH("func");
-
+
unsigned opIndex;
- opIndex = inst.getOperandNamed("func");
+ opIndex = inst.Operands.getOperandNamed("func");
if (operandTypes[opIndex]->is("kOperandTypeImmediate"))
operandTypes[opIndex]->set("kOperandTypeARMBranchTarget");
}
@@ -737,7 +787,7 @@
#undef BRANCH
-/// populateInstInfo - Fills an array of InstInfos with information about each
+/// populateInstInfo - Fills an array of InstInfos with information about each
/// instruction in a target
///
/// @arg infoArray - The array of InstInfo objects to populate
@@ -746,73 +796,78 @@
CodeGenTarget &target) {
const std::vector<const CodeGenInstruction*> &numberedInstructions =
target.getInstructionsByEnumValue();
-
+
unsigned int index;
unsigned int numInstructions = numberedInstructions.size();
-
+
for (index = 0; index < numInstructions; ++index) {
const CodeGenInstruction& inst = *numberedInstructions[index];
-
+
CompoundConstantEmitter *infoStruct = new CompoundConstantEmitter;
infoArray.addEntry(infoStruct);
-
+
LiteralConstantEmitter *instType = new LiteralConstantEmitter;
infoStruct->addEntry(instType);
-
- LiteralConstantEmitter *numOperandsEmitter =
- new LiteralConstantEmitter(inst.OperandList.size());
+
+ LiteralConstantEmitter *numOperandsEmitter =
+ new LiteralConstantEmitter(inst.Operands.size());
infoStruct->addEntry(numOperandsEmitter);
-
+
CompoundConstantEmitter *operandTypeArray = new CompoundConstantEmitter;
infoStruct->addEntry(operandTypeArray);
-
+
LiteralConstantEmitter *operandTypes[EDIS_MAX_OPERANDS];
-
+
CompoundConstantEmitter *operandFlagArray = new CompoundConstantEmitter;
infoStruct->addEntry(operandFlagArray);
-
+
FlagsConstantEmitter *operandFlags[EDIS_MAX_OPERANDS];
-
- for (unsigned operandIndex = 0;
- operandIndex < EDIS_MAX_OPERANDS;
+
+ for (unsigned operandIndex = 0;
+ operandIndex < EDIS_MAX_OPERANDS;
++operandIndex) {
operandTypes[operandIndex] = new LiteralConstantEmitter;
operandTypeArray->addEntry(operandTypes[operandIndex]);
-
+
operandFlags[operandIndex] = new FlagsConstantEmitter;
operandFlagArray->addEntry(operandFlags[operandIndex]);
}
-
+
unsigned numSyntaxes = 0;
-
- if (target.getName() == "X86") {
- X86PopulateOperands(operandTypes, inst);
- X86ExtractSemantics(*instType, operandFlags, inst);
- numSyntaxes = 2;
+
+ // We don't need to do anything for pseudo-instructions, as we'll never
+ // see them here. We'll only see real instructions.
+ // We still need to emit null initializers for everything.
+ if (!inst.isPseudo) {
+ if (target.getName() == "X86") {
+ X86PopulateOperands(operandTypes, inst);
+ X86ExtractSemantics(*instType, operandFlags, inst);
+ numSyntaxes = 2;
+ }
+ else if (target.getName() == "ARM") {
+ ARMPopulateOperands(operandTypes, inst);
+ ARMExtractSemantics(*instType, operandTypes, operandFlags, inst);
+ numSyntaxes = 1;
+ }
}
- else if (target.getName() == "ARM") {
- ARMPopulateOperands(operandTypes, inst);
- ARMExtractSemantics(*instType, operandTypes, operandFlags, inst);
- numSyntaxes = 1;
- }
-
- CompoundConstantEmitter *operandOrderArray = new CompoundConstantEmitter;
-
+
+ CompoundConstantEmitter *operandOrderArray = new CompoundConstantEmitter;
+
infoStruct->addEntry(operandOrderArray);
-
- for (unsigned syntaxIndex = 0;
- syntaxIndex < EDIS_MAX_SYNTAXES;
+
+ for (unsigned syntaxIndex = 0;
+ syntaxIndex < EDIS_MAX_SYNTAXES;
++syntaxIndex) {
- CompoundConstantEmitter *operandOrder =
+ CompoundConstantEmitter *operandOrder =
new CompoundConstantEmitter(EDIS_MAX_OPERANDS);
-
+
operandOrderArray->addEntry(operandOrder);
-
+
if (syntaxIndex < numSyntaxes) {
populateOperandOrder(operandOrder, inst, syntaxIndex);
}
}
-
+
infoStruct = NULL;
}
}
@@ -826,27 +881,39 @@
operandTypes.addEntry("kOperandTypeX86EffectiveAddress");
operandTypes.addEntry("kOperandTypeX86PCRelative");
operandTypes.addEntry("kOperandTypeARMBranchTarget");
- operandTypes.addEntry("kOperandTypeARMSoReg");
+ operandTypes.addEntry("kOperandTypeARMSoRegReg");
+ operandTypes.addEntry("kOperandTypeARMSoRegImm");
operandTypes.addEntry("kOperandTypeARMSoImm");
+ operandTypes.addEntry("kOperandTypeARMRotImm");
operandTypes.addEntry("kOperandTypeARMSoImm2Part");
operandTypes.addEntry("kOperandTypeARMPredicate");
+ operandTypes.addEntry("kOperandTypeAddrModeImm12");
+ operandTypes.addEntry("kOperandTypeLdStSOReg");
operandTypes.addEntry("kOperandTypeARMAddrMode2");
operandTypes.addEntry("kOperandTypeARMAddrMode2Offset");
operandTypes.addEntry("kOperandTypeARMAddrMode3");
operandTypes.addEntry("kOperandTypeARMAddrMode3Offset");
- operandTypes.addEntry("kOperandTypeARMAddrMode4");
+ operandTypes.addEntry("kOperandTypeARMLdStmMode");
operandTypes.addEntry("kOperandTypeARMAddrMode5");
operandTypes.addEntry("kOperandTypeARMAddrMode6");
operandTypes.addEntry("kOperandTypeARMAddrMode6Offset");
+ operandTypes.addEntry("kOperandTypeARMAddrMode7");
operandTypes.addEntry("kOperandTypeARMAddrModePC");
operandTypes.addEntry("kOperandTypeARMRegisterList");
+ operandTypes.addEntry("kOperandTypeARMDPRRegisterList");
+ operandTypes.addEntry("kOperandTypeARMSPRRegisterList");
operandTypes.addEntry("kOperandTypeARMTBAddrMode");
operandTypes.addEntry("kOperandTypeThumbITMask");
- operandTypes.addEntry("kOperandTypeThumbAddrModeS1");
- operandTypes.addEntry("kOperandTypeThumbAddrModeS2");
- operandTypes.addEntry("kOperandTypeThumbAddrModeS4");
+ operandTypes.addEntry("kOperandTypeThumbAddrModeImmS1");
+ operandTypes.addEntry("kOperandTypeThumbAddrModeImmS2");
+ operandTypes.addEntry("kOperandTypeThumbAddrModeImmS4");
+ operandTypes.addEntry("kOperandTypeThumbAddrModeRegS1");
+ operandTypes.addEntry("kOperandTypeThumbAddrModeRegS2");
+ operandTypes.addEntry("kOperandTypeThumbAddrModeRegS4");
operandTypes.addEntry("kOperandTypeThumbAddrModeRR");
operandTypes.addEntry("kOperandTypeThumbAddrModeSP");
+ operandTypes.addEntry("kOperandTypeThumbAddrModePC");
+ operandTypes.addEntry("kOperandTypeThumb2AddrModeReg");
operandTypes.addEntry("kOperandTypeThumb2SoReg");
operandTypes.addEntry("kOperandTypeThumb2SoImm");
operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8");
@@ -856,16 +923,16 @@
operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8s4");
operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8s4Offset");
operandTypes.emit(o, i);
-
+
o << "\n";
-
+
EnumEmitter operandFlags("OperandFlags");
operandFlags.addEntry("kOperandFlagSource");
operandFlags.addEntry("kOperandFlagTarget");
operandFlags.emitAsFlags(o, i);
-
+
o << "\n";
-
+
EnumEmitter instructionTypes("InstructionTypes");
instructionTypes.addEntry("kInstructionTypeNone");
instructionTypes.addEntry("kInstructionTypeMove");
@@ -875,25 +942,25 @@
instructionTypes.addEntry("kInstructionTypeCall");
instructionTypes.addEntry("kInstructionTypeReturn");
instructionTypes.emit(o, i);
-
+
o << "\n";
}
void EDEmitter::run(raw_ostream &o) {
unsigned int i = 0;
-
+
CompoundConstantEmitter infoArray;
- CodeGenTarget target;
-
+ CodeGenTarget target(Records);
+
populateInstInfo(infoArray, target);
-
+
emitCommonEnums(o, i);
-
+
o << "namespace {\n";
-
+
o << "llvm::EDInstInfo instInfo" << target.getName().c_str() << "[] = ";
infoArray.emit(o, i);
o << ";" << "\n";
-
+
o << "}\n";
}
diff --git a/src/LLVM/utils/TableGen/EDEmitter.h b/src/LLVM/utils/TableGen/EDEmitter.h
index e30373f..f268375 100644
--- a/src/LLVM/utils/TableGen/EDEmitter.h
+++ b/src/LLVM/utils/TableGen/EDEmitter.h
@@ -16,7 +16,7 @@
#ifndef SEMANTIC_INFO_EMITTER_H
#define SEMANTIC_INFO_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
namespace llvm {
diff --git a/src/LLVM/utils/TableGen/FastISelEmitter.cpp b/src/LLVM/utils/TableGen/FastISelEmitter.cpp
index 70448ab..9fdc2e3 100644
--- a/src/LLVM/utils/TableGen/FastISelEmitter.cpp
+++ b/src/LLVM/utils/TableGen/FastISelEmitter.cpp
@@ -18,9 +18,12 @@
//===----------------------------------------------------------------------===//
#include "FastISelEmitter.h"
-#include "Record.h"
-#include "llvm/Support/Debug.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/VectorExtras.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
namespace {
@@ -34,106 +37,252 @@
std::string SubRegNo;
std::vector<std::string>* PhysRegs;
};
+
+/// ImmPredicateSet - This uniques predicates (represented as a string) and
+/// gives them unique (small) integer ID's that start at 0.
+class ImmPredicateSet {
+ DenseMap<TreePattern *, unsigned> ImmIDs;
+ std::vector<TreePredicateFn> PredsByName;
+public:
+
+ unsigned getIDFor(TreePredicateFn Pred) {
+ unsigned &Entry = ImmIDs[Pred.getOrigPatFragRecord()];
+ if (Entry == 0) {
+ PredsByName.push_back(Pred);
+ Entry = PredsByName.size();
+ }
+ return Entry-1;
+ }
+
+ const TreePredicateFn &getPredicate(unsigned i) {
+ assert(i < PredsByName.size());
+ return PredsByName[i];
+ }
+
+ typedef std::vector<TreePredicateFn>::const_iterator iterator;
+ iterator begin() const { return PredsByName.begin(); }
+ iterator end() const { return PredsByName.end(); }
+
+};
/// OperandsSignature - This class holds a description of a list of operand
/// types. It has utility methods for emitting text based on the operands.
///
struct OperandsSignature {
- std::vector<std::string> Operands;
+ class OpKind {
+ enum { OK_Reg, OK_FP, OK_Imm, OK_Invalid = -1 };
+ char Repr;
+ public:
+
+ OpKind() : Repr(OK_Invalid) {}
+
+ bool operator<(OpKind RHS) const { return Repr < RHS.Repr; }
+ bool operator==(OpKind RHS) const { return Repr == RHS.Repr; }
+
+ static OpKind getReg() { OpKind K; K.Repr = OK_Reg; return K; }
+ static OpKind getFP() { OpKind K; K.Repr = OK_FP; return K; }
+ static OpKind getImm(unsigned V) {
+ assert((unsigned)OK_Imm+V < 128 &&
+ "Too many integer predicates for the 'Repr' char");
+ OpKind K; K.Repr = OK_Imm+V; return K;
+ }
+
+ bool isReg() const { return Repr == OK_Reg; }
+ bool isFP() const { return Repr == OK_FP; }
+ bool isImm() const { return Repr >= OK_Imm; }
+
+ unsigned getImmCode() const { assert(isImm()); return Repr-OK_Imm; }
+
+ void printManglingSuffix(raw_ostream &OS, ImmPredicateSet &ImmPredicates,
+ bool StripImmCodes) const {
+ if (isReg())
+ OS << 'r';
+ else if (isFP())
+ OS << 'f';
+ else {
+ OS << 'i';
+ if (!StripImmCodes)
+ if (unsigned Code = getImmCode())
+ OS << "_" << ImmPredicates.getPredicate(Code-1).getFnName();
+ }
+ }
+ };
+
+
+ SmallVector<OpKind, 3> Operands;
bool operator<(const OperandsSignature &O) const {
return Operands < O.Operands;
}
+ bool operator==(const OperandsSignature &O) const {
+ return Operands == O.Operands;
+ }
bool empty() const { return Operands.empty(); }
+ bool hasAnyImmediateCodes() const {
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+ if (Operands[i].isImm() && Operands[i].getImmCode() != 0)
+ return true;
+ return false;
+ }
+
+ /// getWithoutImmCodes - Return a copy of this with any immediate codes forced
+ /// to zero.
+ OperandsSignature getWithoutImmCodes() const {
+ OperandsSignature Result;
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+ if (!Operands[i].isImm())
+ Result.Operands.push_back(Operands[i]);
+ else
+ Result.Operands.push_back(OpKind::getImm(0));
+ return Result;
+ }
+
+ void emitImmediatePredicate(raw_ostream &OS, ImmPredicateSet &ImmPredicates) {
+ bool EmittedAnything = false;
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ if (!Operands[i].isImm()) continue;
+
+ unsigned Code = Operands[i].getImmCode();
+ if (Code == 0) continue;
+
+ if (EmittedAnything)
+ OS << " &&\n ";
+
+ TreePredicateFn PredFn = ImmPredicates.getPredicate(Code-1);
+
+ // Emit the type check.
+ OS << "VT == "
+ << getEnumName(PredFn.getOrigPatFragRecord()->getTree(0)->getType(0))
+ << " && ";
+
+
+ OS << PredFn.getFnName() << "(imm" << i <<')';
+ EmittedAnything = true;
+ }
+ }
+
/// initialize - Examine the given pattern and initialize the contents
/// of the Operands array accordingly. Return true if all the operands
/// are supported, false otherwise.
///
- bool initialize(TreePatternNode *InstPatNode,
- const CodeGenTarget &Target,
- MVT::SimpleValueType VT) {
-
- if (!InstPatNode->isLeaf()) {
- if (InstPatNode->getOperator()->getName() == "imm") {
- Operands.push_back("i");
- return true;
- }
- if (InstPatNode->getOperator()->getName() == "fpimm") {
- Operands.push_back("f");
- return true;
- }
+ bool initialize(TreePatternNode *InstPatNode, const CodeGenTarget &Target,
+ MVT::SimpleValueType VT,
+ ImmPredicateSet &ImmediatePredicates) {
+ if (InstPatNode->isLeaf())
+ return false;
+
+ if (InstPatNode->getOperator()->getName() == "imm") {
+ Operands.push_back(OpKind::getImm(0));
+ return true;
}
+ if (InstPatNode->getOperator()->getName() == "fpimm") {
+ Operands.push_back(OpKind::getFP());
+ return true;
+ }
+
const CodeGenRegisterClass *DstRC = 0;
-
+
for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) {
TreePatternNode *Op = InstPatNode->getChild(i);
+
+ // Handle imm operands specially.
+ if (!Op->isLeaf() && Op->getOperator()->getName() == "imm") {
+ unsigned PredNo = 0;
+ if (!Op->getPredicateFns().empty()) {
+ TreePredicateFn PredFn = Op->getPredicateFns()[0];
+ // If there is more than one predicate weighing in on this operand
+ // then we don't handle it. This doesn't typically happen for
+ // immediates anyway.
+ if (Op->getPredicateFns().size() > 1 ||
+ !PredFn.isImmediatePattern())
+ return false;
+ // Ignore any instruction with 'FastIselShouldIgnore', these are
+ // not needed and just bloat the fast instruction selector. For
+ // example, X86 doesn't need to generate code to match ADD16ri8 since
+ // ADD16ri will do just fine.
+ Record *Rec = PredFn.getOrigPatFragRecord()->getRecord();
+ if (Rec->getValueAsBit("FastIselShouldIgnore"))
+ return false;
+
+ PredNo = ImmediatePredicates.getIDFor(PredFn)+1;
+ }
+
+ // Handle unmatched immediate sizes here.
+ //if (Op->getType(0) != VT)
+ // return false;
+
+ Operands.push_back(OpKind::getImm(PredNo));
+ continue;
+ }
+
// For now, filter out any operand with a predicate.
// For now, filter out any operand with multiple values.
- if (!Op->getPredicateFns().empty() ||
- Op->getNumTypes() != 1)
+ if (!Op->getPredicateFns().empty() || Op->getNumTypes() != 1)
return false;
-
- assert(Op->hasTypeSet(0) && "Type infererence not done?");
- // For now, all the operands must have the same type.
- if (Op->getType(0) != VT)
- return false;
-
+
if (!Op->isLeaf()) {
- if (Op->getOperator()->getName() == "imm") {
- Operands.push_back("i");
- continue;
- }
- if (Op->getOperator()->getName() == "fpimm") {
- Operands.push_back("f");
+ if (Op->getOperator()->getName() == "fpimm") {
+ Operands.push_back(OpKind::getFP());
continue;
}
// For now, ignore other non-leaf nodes.
return false;
}
+
+ assert(Op->hasTypeSet(0) && "Type infererence not done?");
+
+ // For now, all the operands must have the same type (if they aren't
+ // immediates). Note that this causes us to reject variable sized shifts
+ // on X86.
+ if (Op->getType(0) != VT)
+ return false;
+
DefInit *OpDI = dynamic_cast<DefInit*>(Op->getLeafValue());
if (!OpDI)
return false;
Record *OpLeafRec = OpDI->getDef();
+
// For now, the only other thing we accept is register operands.
-
const CodeGenRegisterClass *RC = 0;
+ if (OpLeafRec->isSubClassOf("RegisterOperand"))
+ OpLeafRec = OpLeafRec->getValueAsDef("RegClass");
if (OpLeafRec->isSubClassOf("RegisterClass"))
RC = &Target.getRegisterClass(OpLeafRec);
else if (OpLeafRec->isSubClassOf("Register"))
- RC = Target.getRegisterClassForRegister(OpLeafRec);
+ RC = Target.getRegBank().getRegClassForRegister(OpLeafRec);
else
return false;
-
- // For now, require the register operands' register classes to all
- // be the same.
+
+ // For now, this needs to be a register class of some sort.
if (!RC)
return false;
- // For now, all the operands must have the same register class.
+
+ // For now, all the operands must have the same register class or be
+ // a strict subclass of the destination.
if (DstRC) {
- if (DstRC != RC)
+ if (DstRC != RC && !DstRC->hasSubClass(RC))
return false;
} else
DstRC = RC;
- Operands.push_back("r");
+ Operands.push_back(OpKind::getReg());
}
return true;
}
void PrintParameters(raw_ostream &OS) const {
for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
- if (Operands[i] == "r") {
+ if (Operands[i].isReg()) {
OS << "unsigned Op" << i << ", bool Op" << i << "IsKill";
- } else if (Operands[i] == "i") {
+ } else if (Operands[i].isImm()) {
OS << "uint64_t imm" << i;
- } else if (Operands[i] == "f") {
+ } else if (Operands[i].isFP()) {
OS << "ConstantFP *f" << i;
} else {
- assert("Unknown operand kind!");
- abort();
+ llvm_unreachable("Unknown operand kind!");
}
if (i + 1 != e)
OS << ", ";
@@ -141,7 +290,7 @@
}
void PrintArguments(raw_ostream &OS,
- const std::vector<std::string>& PR) const {
+ const std::vector<std::string> &PR) const {
assert(PR.size() == Operands.size());
bool PrintedArg = false;
for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
@@ -151,33 +300,31 @@
if (PrintedArg)
OS << ", ";
- if (Operands[i] == "r") {
+ if (Operands[i].isReg()) {
OS << "Op" << i << ", Op" << i << "IsKill";
PrintedArg = true;
- } else if (Operands[i] == "i") {
+ } else if (Operands[i].isImm()) {
OS << "imm" << i;
PrintedArg = true;
- } else if (Operands[i] == "f") {
+ } else if (Operands[i].isFP()) {
OS << "f" << i;
PrintedArg = true;
} else {
- assert("Unknown operand kind!");
- abort();
+ llvm_unreachable("Unknown operand kind!");
}
}
}
void PrintArguments(raw_ostream &OS) const {
for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
- if (Operands[i] == "r") {
+ if (Operands[i].isReg()) {
OS << "Op" << i << ", Op" << i << "IsKill";
- } else if (Operands[i] == "i") {
+ } else if (Operands[i].isImm()) {
OS << "imm" << i;
- } else if (Operands[i] == "f") {
+ } else if (Operands[i].isFP()) {
OS << "f" << i;
} else {
- assert("Unknown operand kind!");
- abort();
+ llvm_unreachable("Unknown operand kind!");
}
if (i + 1 != e)
OS << ", ";
@@ -185,8 +332,9 @@
}
- void PrintManglingSuffix(raw_ostream &OS,
- const std::vector<std::string>& PR) const {
+ void PrintManglingSuffix(raw_ostream &OS, const std::vector<std::string> &PR,
+ ImmPredicateSet &ImmPredicates,
+ bool StripImmCodes = false) const {
for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
if (PR[i] != "")
// Implicit physical register operand. e.g. Instruction::Mul expect to
@@ -195,14 +343,14 @@
// like a binary instruction except for the very inner FastEmitInst_*
// call.
continue;
- OS << Operands[i];
+ Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes);
}
}
- void PrintManglingSuffix(raw_ostream &OS) const {
- for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
- OS << Operands[i];
- }
+ void PrintManglingSuffix(raw_ostream &OS, ImmPredicateSet &ImmPredicates,
+ bool StripImmCodes = false) const {
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+ Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes);
}
};
@@ -211,18 +359,22 @@
typedef std::map<MVT::SimpleValueType, PredMap> RetPredMap;
typedef std::map<MVT::SimpleValueType, RetPredMap> TypeRetPredMap;
typedef std::map<std::string, TypeRetPredMap> OpcodeTypeRetPredMap;
- typedef std::map<OperandsSignature, OpcodeTypeRetPredMap>
+ typedef std::map<OperandsSignature, OpcodeTypeRetPredMap>
OperandsOpcodeTypeRetPredMap;
OperandsOpcodeTypeRetPredMap SimplePatterns;
+ std::map<OperandsSignature, std::vector<OperandsSignature> >
+ SignaturesWithConstantForms;
+
std::string InstNS;
-
+ ImmPredicateSet ImmediatePredicates;
public:
explicit FastISelMap(std::string InstNS);
- void CollectPatterns(CodeGenDAGPatterns &CGP);
- void PrintFunctionDefinitions(raw_ostream &OS);
+ void collectPatterns(CodeGenDAGPatterns &CGP);
+ void printImmediatePredicates(raw_ostream &OS);
+ void printFunctionDefinitions(raw_ostream &OS);
};
}
@@ -242,7 +394,26 @@
: InstNS(instns) {
}
-void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) {
+static std::string PhyRegForNode(TreePatternNode *Op,
+ const CodeGenTarget &Target) {
+ std::string PhysReg;
+
+ if (!Op->isLeaf())
+ return PhysReg;
+
+ DefInit *OpDI = dynamic_cast<DefInit*>(Op->getLeafValue());
+ Record *OpLeafRec = OpDI->getDef();
+ if (!OpLeafRec->isSubClassOf("Register"))
+ return PhysReg;
+
+ PhysReg += static_cast<StringInit*>(OpLeafRec->getValue( \
+ "Namespace")->getValue())->getValue();
+ PhysReg += "::";
+ PhysReg += Target.getRegBank().getReg(OpLeafRec)->getName();
+ return PhysReg;
+}
+
+void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
const CodeGenTarget &Target = CGP.getTargetInfo();
// Determine the target's namespace name.
@@ -262,18 +433,9 @@
if (!Op->isSubClassOf("Instruction"))
continue;
CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op);
- if (II.OperandList.empty())
+ if (II.Operands.empty())
continue;
- // For now ignore instructions that have predicate operands.
- bool HasPredicate = false;
- for (unsigned i = 0, e = II.OperandList.size(); i != e; ++i) {
- if(II.OperandList[i].Rec->isSubClassOf("PredicateOperand"))
- HasPredicate = true;
- }
- if (HasPredicate)
- continue;
-
// For now, ignore multi-instruction patterns.
bool MultiInsts = false;
for (unsigned i = 0, e = Dst->getNumChildren(); i != e; ++i) {
@@ -293,7 +455,9 @@
const CodeGenRegisterClass *DstRC = 0;
std::string SubRegNo;
if (Op->getName() != "EXTRACT_SUBREG") {
- Record *Op0Rec = II.OperandList[0].Rec;
+ Record *Op0Rec = II.Operands[0].Rec;
+ if (Op0Rec->isSubClassOf("RegisterOperand"))
+ Op0Rec = Op0Rec->getValueAsDef("RegClass");
if (!Op0Rec->isSubClassOf("RegisterClass"))
continue;
DstRC = &Target.getRegisterClass(Op0Rec);
@@ -303,7 +467,7 @@
// If this isn't a leaf, then continue since the register classes are
// a bit too complicated for now.
if (!Dst->getChild(1)->isLeaf()) continue;
-
+
DefInit *SR = dynamic_cast<DefInit*>(Dst->getChild(1)->getLeafValue());
if (SR)
SubRegNo = getQualifiedName(SR->getDef());
@@ -318,7 +482,7 @@
// Ignore multiple result nodes for now.
if (InstPatNode->getNumTypes() > 1) continue;
-
+
Record *InstPatOp = InstPatNode->getOperator();
std::string OpcodeName = getOpcodeName(InstPatOp, CGP);
MVT::SimpleValueType RetVT = MVT::isVoid;
@@ -329,54 +493,45 @@
VT = InstPatNode->getChild(0)->getType(0);
}
- // For now, filter out instructions which just set a register to
- // an Operand or an immediate, like MOV32ri.
- if (InstPatOp->isSubClassOf("Operand"))
- continue;
-
// For now, filter out any instructions with predicates.
if (!InstPatNode->getPredicateFns().empty())
continue;
// Check all the operands.
OperandsSignature Operands;
- if (!Operands.initialize(InstPatNode, Target, VT))
+ if (!Operands.initialize(InstPatNode, Target, VT, ImmediatePredicates))
continue;
-
+
std::vector<std::string>* PhysRegInputs = new std::vector<std::string>();
- if (!InstPatNode->isLeaf() &&
- (InstPatNode->getOperator()->getName() == "imm" ||
- InstPatNode->getOperator()->getName() == "fpimmm"))
+ if (InstPatNode->getOperator()->getName() == "imm" ||
+ InstPatNode->getOperator()->getName() == "fpimm")
PhysRegInputs->push_back("");
- else if (!InstPatNode->isLeaf()) {
+ else {
+ // Compute the PhysRegs used by the given pattern, and check that
+ // the mapping from the src to dst patterns is simple.
+ bool FoundNonSimplePattern = false;
+ unsigned DstIndex = 0;
for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) {
- TreePatternNode *Op = InstPatNode->getChild(i);
- if (!Op->isLeaf()) {
- PhysRegInputs->push_back("");
- continue;
- }
-
- DefInit *OpDI = dynamic_cast<DefInit*>(Op->getLeafValue());
- Record *OpLeafRec = OpDI->getDef();
- std::string PhysReg;
- if (OpLeafRec->isSubClassOf("Register")) {
- PhysReg += static_cast<StringInit*>(OpLeafRec->getValue( \
- "Namespace")->getValue())->getValue();
- PhysReg += "::";
-
- std::vector<CodeGenRegister> Regs = Target.getRegisters();
- for (unsigned i = 0; i < Regs.size(); ++i) {
- if (Regs[i].TheDef == OpLeafRec) {
- PhysReg += Regs[i].getName();
- break;
- }
+ std::string PhysReg = PhyRegForNode(InstPatNode->getChild(i), Target);
+ if (PhysReg.empty()) {
+ if (DstIndex >= Dst->getNumChildren() ||
+ Dst->getChild(DstIndex)->getName() !=
+ InstPatNode->getChild(i)->getName()) {
+ FoundNonSimplePattern = true;
+ break;
}
+ ++DstIndex;
}
-
+
PhysRegInputs->push_back(PhysReg);
}
- } else
- PhysRegInputs->push_back("");
+
+ if (Op->getName() != "EXTRACT_SUBREG" && DstIndex < Dst->getNumChildren())
+ FoundNonSimplePattern = true;
+
+ if (FoundNonSimplePattern)
+ continue;
+ }
// Get the predicate that guards this pattern.
std::string PredicateCheck = Pattern.getPredicateCheck();
@@ -388,14 +543,39 @@
SubRegNo,
PhysRegInputs
};
- assert(!SimplePatterns[Operands][OpcodeName][VT][RetVT]
- .count(PredicateCheck) &&
- "Duplicate pattern!");
+
+ if (SimplePatterns[Operands][OpcodeName][VT][RetVT].count(PredicateCheck))
+ throw TGError(Pattern.getSrcRecord()->getLoc(),
+ "Duplicate record in FastISel table!");
+
SimplePatterns[Operands][OpcodeName][VT][RetVT][PredicateCheck] = Memo;
+
+ // If any of the operands were immediates with predicates on them, strip
+ // them down to a signature that doesn't have predicates so that we can
+ // associate them with the stripped predicate version.
+ if (Operands.hasAnyImmediateCodes()) {
+ SignaturesWithConstantForms[Operands.getWithoutImmCodes()]
+ .push_back(Operands);
+ }
}
}
-void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) {
+void FastISelMap::printImmediatePredicates(raw_ostream &OS) {
+ if (ImmediatePredicates.begin() == ImmediatePredicates.end())
+ return;
+
+ OS << "\n// FastEmit Immediate Predicate functions.\n";
+ for (ImmPredicateSet::iterator I = ImmediatePredicates.begin(),
+ E = ImmediatePredicates.end(); I != E; ++I) {
+ OS << "static bool " << I->getFnName() << "(int64_t Imm) {\n";
+ OS << I->getImmediatePredicateCode() << "\n}\n";
+ }
+
+ OS << "\n\n";
+}
+
+
+void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
// Now emit code for all the patterns that we collected.
for (OperandsOpcodeTypeRetPredMap::const_iterator OI = SimplePatterns.begin(),
OE = SimplePatterns.end(); OI != OE; ++OI) {
@@ -426,7 +606,7 @@
<< getLegalCName(Opcode)
<< "_" << getLegalCName(getName(VT))
<< "_" << getLegalCName(getName(RetVT)) << "_";
- Operands.PrintManglingSuffix(OS);
+ Operands.PrintManglingSuffix(OS, ImmediatePredicates);
OS << "(";
Operands.PrintParameters(OS);
OS << ") {\n";
@@ -437,7 +617,7 @@
PI != PE; ++PI) {
std::string PredicateCheck = PI->first;
const InstructionMemo &Memo = PI->second;
-
+
if (PredicateCheck.empty()) {
assert(!HasPred &&
"Multiple instructions match, at least one has "
@@ -447,17 +627,18 @@
OS << " ";
HasPred = true;
}
-
+
for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) {
if ((*Memo.PhysRegs)[i] != "")
OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, "
<< "TII.get(TargetOpcode::COPY), "
<< (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n";
}
-
+
OS << " return FastEmitInst_";
if (Memo.SubRegNo.empty()) {
- Operands.PrintManglingSuffix(OS, *Memo.PhysRegs);
+ Operands.PrintManglingSuffix(OS, *Memo.PhysRegs,
+ ImmediatePredicates, true);
OS << "(" << InstNS << Memo.Name << ", ";
OS << InstNS << Memo.RC->getName() << "RegisterClass";
if (!Operands.empty())
@@ -466,14 +647,12 @@
OS << ");\n";
} else {
OS << "extractsubreg(" << getName(RetVT);
- OS << ", Op0, Op0IsKill, ";
- OS << Memo.SubRegNo;
- OS << ");\n";
+ OS << ", Op0, Op0IsKill, " << Memo.SubRegNo << ");\n";
}
-
+
if (HasPred)
OS << " }\n";
-
+
}
// Return 0 if none of the predicates were satisfied.
if (HasPred)
@@ -481,12 +660,12 @@
OS << "}\n";
OS << "\n";
}
-
+
// Emit one function for the type that demultiplexes on return type.
OS << "unsigned FastEmit_"
<< getLegalCName(Opcode) << "_"
<< getLegalCName(getName(VT)) << "_";
- Operands.PrintManglingSuffix(OS);
+ Operands.PrintManglingSuffix(OS, ImmediatePredicates);
OS << "(MVT RetVT";
if (!Operands.empty())
OS << ", ";
@@ -498,31 +677,31 @@
OS << " case " << getName(RetVT) << ": return FastEmit_"
<< getLegalCName(Opcode) << "_" << getLegalCName(getName(VT))
<< "_" << getLegalCName(getName(RetVT)) << "_";
- Operands.PrintManglingSuffix(OS);
+ Operands.PrintManglingSuffix(OS, ImmediatePredicates);
OS << "(";
Operands.PrintArguments(OS);
OS << ");\n";
}
OS << " default: return 0;\n}\n}\n\n";
-
+
} else {
// Non-variadic return type.
OS << "unsigned FastEmit_"
<< getLegalCName(Opcode) << "_"
<< getLegalCName(getName(VT)) << "_";
- Operands.PrintManglingSuffix(OS);
+ Operands.PrintManglingSuffix(OS, ImmediatePredicates);
OS << "(MVT RetVT";
if (!Operands.empty())
OS << ", ";
Operands.PrintParameters(OS);
OS << ") {\n";
-
+
OS << " if (RetVT.SimpleTy != " << getName(RM.begin()->first)
<< ")\n return 0;\n";
-
+
const PredMap &PM = RM.begin()->second;
bool HasPred = false;
-
+
// Emit code for each possible instruction. There may be
// multiple if there are subtarget concerns.
for (PredMap::const_iterator PI = PM.begin(), PE = PM.end(); PI != PE;
@@ -539,18 +718,19 @@
OS << " ";
HasPred = true;
}
-
+
for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) {
if ((*Memo.PhysRegs)[i] != "")
OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, "
<< "TII.get(TargetOpcode::COPY), "
<< (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n";
}
-
+
OS << " return FastEmitInst_";
-
+
if (Memo.SubRegNo.empty()) {
- Operands.PrintManglingSuffix(OS, *Memo.PhysRegs);
+ Operands.PrintManglingSuffix(OS, *Memo.PhysRegs,
+ ImmediatePredicates, true);
OS << "(" << InstNS << Memo.Name << ", ";
OS << InstNS << Memo.RC->getName() << "RegisterClass";
if (!Operands.empty())
@@ -562,11 +742,11 @@
OS << Memo.SubRegNo;
OS << ");\n";
}
-
+
if (HasPred)
OS << " }\n";
}
-
+
// Return 0 if none of the predicates were satisfied.
if (HasPred)
OS << " return 0;\n";
@@ -578,7 +758,7 @@
// Emit one function for the opcode that demultiplexes based on the type.
OS << "unsigned FastEmit_"
<< getLegalCName(Opcode) << "_";
- Operands.PrintManglingSuffix(OS);
+ Operands.PrintManglingSuffix(OS, ImmediatePredicates);
OS << "(MVT VT, MVT RetVT";
if (!Operands.empty())
OS << ", ";
@@ -591,7 +771,7 @@
std::string TypeName = getName(VT);
OS << " case " << TypeName << ": return FastEmit_"
<< getLegalCName(Opcode) << "_" << getLegalCName(TypeName) << "_";
- Operands.PrintManglingSuffix(OS);
+ Operands.PrintManglingSuffix(OS, ImmediatePredicates);
OS << "(RetVT";
if (!Operands.empty())
OS << ", ";
@@ -610,12 +790,44 @@
// Emit one function for the operand signature that demultiplexes based
// on opcode and type.
OS << "unsigned FastEmit_";
- Operands.PrintManglingSuffix(OS);
+ Operands.PrintManglingSuffix(OS, ImmediatePredicates);
OS << "(MVT VT, MVT RetVT, unsigned Opcode";
if (!Operands.empty())
OS << ", ";
Operands.PrintParameters(OS);
OS << ") {\n";
+
+ // If there are any forms of this signature available that operand on
+ // constrained forms of the immediate (e.g. 32-bit sext immediate in a
+ // 64-bit operand), check them first.
+
+ std::map<OperandsSignature, std::vector<OperandsSignature> >::iterator MI
+ = SignaturesWithConstantForms.find(Operands);
+ if (MI != SignaturesWithConstantForms.end()) {
+ // Unique any duplicates out of the list.
+ std::sort(MI->second.begin(), MI->second.end());
+ MI->second.erase(std::unique(MI->second.begin(), MI->second.end()),
+ MI->second.end());
+
+ // Check each in order it was seen. It would be nice to have a good
+ // relative ordering between them, but we're not going for optimality
+ // here.
+ for (unsigned i = 0, e = MI->second.size(); i != e; ++i) {
+ OS << " if (";
+ MI->second[i].emitImmediatePredicate(OS, ImmediatePredicates);
+ OS << ")\n if (unsigned Reg = FastEmit_";
+ MI->second[i].PrintManglingSuffix(OS, ImmediatePredicates);
+ OS << "(VT, RetVT, Opcode";
+ if (!MI->second[i].empty())
+ OS << ", ";
+ MI->second[i].PrintArguments(OS);
+ OS << "))\n return Reg;\n\n";
+ }
+
+ // Done with this, remove it.
+ SignaturesWithConstantForms.erase(MI);
+ }
+
OS << " switch (Opcode) {\n";
for (OpcodeTypeRetPredMap::const_iterator I = OTM.begin(), E = OTM.end();
I != E; ++I) {
@@ -623,7 +835,7 @@
OS << " case " << Opcode << ": return FastEmit_"
<< getLegalCName(Opcode) << "_";
- Operands.PrintManglingSuffix(OS);
+ Operands.PrintManglingSuffix(OS, ImmediatePredicates);
OS << "(VT, RetVT";
if (!Operands.empty())
OS << ", ";
@@ -635,6 +847,8 @@
OS << "}\n";
OS << "\n";
}
+
+ // TODO: SignaturesWithConstantForms should be empty here.
}
void FastISelEmitter::run(raw_ostream &OS) {
@@ -648,12 +862,12 @@
Target.getName() + " target", OS);
FastISelMap F(InstNS);
- F.CollectPatterns(CGP);
- F.PrintFunctionDefinitions(OS);
+ F.collectPatterns(CGP);
+ F.printImmediatePredicates(OS);
+ F.printFunctionDefinitions(OS);
}
FastISelEmitter::FastISelEmitter(RecordKeeper &R)
- : Records(R),
- CGP(R) {
+ : Records(R), CGP(R) {
}
diff --git a/src/LLVM/utils/TableGen/FastISelEmitter.h b/src/LLVM/utils/TableGen/FastISelEmitter.h
index ce4e77e..4f75ac1 100644
--- a/src/LLVM/utils/TableGen/FastISelEmitter.h
+++ b/src/LLVM/utils/TableGen/FastISelEmitter.h
@@ -14,8 +14,8 @@
#ifndef FASTISEL_EMITTER_H
#define FASTISEL_EMITTER_H
-#include "TableGenBackend.h"
#include "CodeGenDAGPatterns.h"
+#include "llvm/TableGen/TableGenBackend.h"
namespace llvm {
diff --git a/src/LLVM/utils/TableGen/FixedLenDecoderEmitter.cpp b/src/LLVM/utils/TableGen/FixedLenDecoderEmitter.cpp
new file mode 100644
index 0000000..02b966a
--- /dev/null
+++ b/src/LLVM/utils/TableGen/FixedLenDecoderEmitter.cpp
@@ -0,0 +1,1489 @@
+//===------------ FixedLenDecoderEmitter.cpp - Decoder Generator ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// It contains the tablegen backend that emits the decoder functions for
+// targets with fixed length instruction set.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "decoder-emitter"
+
+#include "FixedLenDecoderEmitter.h"
+#include "CodeGenTarget.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <vector>
+#include <map>
+#include <string>
+
+using namespace llvm;
+
+// The set (BIT_TRUE, BIT_FALSE, BIT_UNSET) represents a ternary logic system
+// for a bit value.
+//
+// BIT_UNFILTERED is used as the init value for a filter position. It is used
+// only for filter processings.
+typedef enum {
+ BIT_TRUE, // '1'
+ BIT_FALSE, // '0'
+ BIT_UNSET, // '?'
+ BIT_UNFILTERED // unfiltered
+} bit_value_t;
+
+static bool ValueSet(bit_value_t V) {
+ return (V == BIT_TRUE || V == BIT_FALSE);
+}
+static bool ValueNotSet(bit_value_t V) {
+ return (V == BIT_UNSET);
+}
+static int Value(bit_value_t V) {
+ return ValueNotSet(V) ? -1 : (V == BIT_FALSE ? 0 : 1);
+}
+static bit_value_t bitFromBits(BitsInit &bits, unsigned index) {
+ if (BitInit *bit = dynamic_cast<BitInit*>(bits.getBit(index)))
+ return bit->getValue() ? BIT_TRUE : BIT_FALSE;
+
+ // The bit is uninitialized.
+ return BIT_UNSET;
+}
+// Prints the bit value for each position.
+static void dumpBits(raw_ostream &o, BitsInit &bits) {
+ unsigned index;
+
+ for (index = bits.getNumBits(); index > 0; index--) {
+ switch (bitFromBits(bits, index - 1)) {
+ case BIT_TRUE:
+ o << "1";
+ break;
+ case BIT_FALSE:
+ o << "0";
+ break;
+ case BIT_UNSET:
+ o << "_";
+ break;
+ default:
+ assert(0 && "unexpected return value from bitFromBits");
+ }
+ }
+}
+
+static BitsInit &getBitsField(const Record &def, const char *str) {
+ BitsInit *bits = def.getValueAsBitsInit(str);
+ return *bits;
+}
+
+// Forward declaration.
+class FilterChooser;
+
+// Representation of the instruction to work on.
+typedef std::vector<bit_value_t> insn_t;
+
+/// Filter - Filter works with FilterChooser to produce the decoding tree for
+/// the ISA.
+///
+/// It is useful to think of a Filter as governing the switch stmts of the
+/// decoding tree in a certain level. Each case stmt delegates to an inferior
+/// FilterChooser to decide what further decoding logic to employ, or in another
+/// words, what other remaining bits to look at. The FilterChooser eventually
+/// chooses a best Filter to do its job.
+///
+/// This recursive scheme ends when the number of Opcodes assigned to the
+/// FilterChooser becomes 1 or if there is a conflict. A conflict happens when
+/// the Filter/FilterChooser combo does not know how to distinguish among the
+/// Opcodes assigned.
+///
+/// An example of a conflict is
+///
+/// Conflict:
+/// 111101000.00........00010000....
+/// 111101000.00........0001........
+/// 1111010...00........0001........
+/// 1111010...00....................
+/// 1111010.........................
+/// 1111............................
+/// ................................
+/// VST4q8a 111101000_00________00010000____
+/// VST4q8b 111101000_00________00010000____
+///
+/// The Debug output shows the path that the decoding tree follows to reach the
+/// the conclusion that there is a conflict. VST4q8a is a vst4 to double-spaced
+/// even registers, while VST4q8b is a vst4 to double-spaced odd regsisters.
+///
+/// The encoding info in the .td files does not specify this meta information,
+/// which could have been used by the decoder to resolve the conflict. The
+/// decoder could try to decode the even/odd register numbering and assign to
+/// VST4q8a or VST4q8b, but for the time being, the decoder chooses the "a"
+/// version and return the Opcode since the two have the same Asm format string.
+class Filter {
+protected:
+ FilterChooser *Owner; // points to the FilterChooser who owns this filter
+ unsigned StartBit; // the starting bit position
+ unsigned NumBits; // number of bits to filter
+ bool Mixed; // a mixed region contains both set and unset bits
+
+ // Map of well-known segment value to the set of uid's with that value.
+ std::map<uint64_t, std::vector<unsigned> > FilteredInstructions;
+
+ // Set of uid's with non-constant segment values.
+ std::vector<unsigned> VariableInstructions;
+
+ // Map of well-known segment value to its delegate.
+ std::map<unsigned, FilterChooser*> FilterChooserMap;
+
+ // Number of instructions which fall under FilteredInstructions category.
+ unsigned NumFiltered;
+
+ // Keeps track of the last opcode in the filtered bucket.
+ unsigned LastOpcFiltered;
+
+ // Number of instructions which fall under VariableInstructions category.
+ unsigned NumVariable;
+
+public:
+ unsigned getNumFiltered() { return NumFiltered; }
+ unsigned getNumVariable() { return NumVariable; }
+ unsigned getSingletonOpc() {
+ assert(NumFiltered == 1);
+ return LastOpcFiltered;
+ }
+ // Return the filter chooser for the group of instructions without constant
+ // segment values.
+ FilterChooser &getVariableFC() {
+ assert(NumFiltered == 1);
+ assert(FilterChooserMap.size() == 1);
+ return *(FilterChooserMap.find((unsigned)-1)->second);
+ }
+
+ Filter(const Filter &f);
+ Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, bool mixed);
+
+ ~Filter();
+
+ // Divides the decoding task into sub tasks and delegates them to the
+ // inferior FilterChooser's.
+ //
+ // A special case arises when there's only one entry in the filtered
+ // instructions. In order to unambiguously decode the singleton, we need to
+ // match the remaining undecoded encoding bits against the singleton.
+ void recurse();
+
+ // Emit code to decode instructions given a segment or segments of bits.
+ void emit(raw_ostream &o, unsigned &Indentation);
+
+ // Returns the number of fanout produced by the filter. More fanout implies
+ // the filter distinguishes more categories of instructions.
+ unsigned usefulness() const;
+}; // End of class Filter
+
+// These are states of our finite state machines used in FilterChooser's
+// filterProcessor() which produces the filter candidates to use.
+typedef enum {
+ ATTR_NONE,
+ ATTR_FILTERED,
+ ATTR_ALL_SET,
+ ATTR_ALL_UNSET,
+ ATTR_MIXED
+} bitAttr_t;
+
+/// FilterChooser - FilterChooser chooses the best filter among a set of Filters
+/// in order to perform the decoding of instructions at the current level.
+///
+/// Decoding proceeds from the top down. Based on the well-known encoding bits
+/// of instructions available, FilterChooser builds up the possible Filters that
+/// can further the task of decoding by distinguishing among the remaining
+/// candidate instructions.
+///
+/// Once a filter has been chosen, it is called upon to divide the decoding task
+/// into sub-tasks and delegates them to its inferior FilterChoosers for further
+/// processings.
+///
+/// It is useful to think of a Filter as governing the switch stmts of the
+/// decoding tree. And each case is delegated to an inferior FilterChooser to
+/// decide what further remaining bits to look at.
+class FilterChooser {
+protected:
+ friend class Filter;
+
+ // Vector of codegen instructions to choose our filter.
+ const std::vector<const CodeGenInstruction*> &AllInstructions;
+
+ // Vector of uid's for this filter chooser to work on.
+ const std::vector<unsigned> Opcodes;
+
+ // Lookup table for the operand decoding of instructions.
+ std::map<unsigned, std::vector<OperandInfo> > &Operands;
+
+ // Vector of candidate filters.
+ std::vector<Filter> Filters;
+
+ // Array of bit values passed down from our parent.
+ // Set to all BIT_UNFILTERED's for Parent == NULL.
+ std::vector<bit_value_t> FilterBitValues;
+
+ // Links to the FilterChooser above us in the decoding tree.
+ FilterChooser *Parent;
+
+ // Index of the best filter from Filters.
+ int BestIndex;
+
+ // Width of instructions
+ unsigned BitWidth;
+
+ // Parent emitter
+ const FixedLenDecoderEmitter *Emitter;
+
+public:
+ FilterChooser(const FilterChooser &FC) :
+ AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes),
+ Operands(FC.Operands), Filters(FC.Filters),
+ FilterBitValues(FC.FilterBitValues), Parent(FC.Parent),
+ BestIndex(FC.BestIndex), BitWidth(FC.BitWidth),
+ Emitter(FC.Emitter) { }
+
+ FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
+ const std::vector<unsigned> &IDs,
+ std::map<unsigned, std::vector<OperandInfo> > &Ops,
+ unsigned BW,
+ const FixedLenDecoderEmitter *E) :
+ AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(),
+ Parent(NULL), BestIndex(-1), BitWidth(BW), Emitter(E) {
+ for (unsigned i = 0; i < BitWidth; ++i)
+ FilterBitValues.push_back(BIT_UNFILTERED);
+
+ doFilter();
+ }
+
+ FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
+ const std::vector<unsigned> &IDs,
+ std::map<unsigned, std::vector<OperandInfo> > &Ops,
+ std::vector<bit_value_t> &ParentFilterBitValues,
+ FilterChooser &parent) :
+ AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
+ Filters(), FilterBitValues(ParentFilterBitValues),
+ Parent(&parent), BestIndex(-1), BitWidth(parent.BitWidth),
+ Emitter(parent.Emitter) {
+ doFilter();
+ }
+
+ // The top level filter chooser has NULL as its parent.
+ bool isTopLevel() { return Parent == NULL; }
+
+ // Emit the top level typedef and decodeInstruction() function.
+ void emitTop(raw_ostream &o, unsigned Indentation, std::string Namespace);
+
+protected:
+ // Populates the insn given the uid.
+ void insnWithID(insn_t &Insn, unsigned Opcode) const {
+ BitsInit &Bits = getBitsField(*AllInstructions[Opcode]->TheDef, "Inst");
+
+ for (unsigned i = 0; i < BitWidth; ++i)
+ Insn.push_back(bitFromBits(Bits, i));
+ }
+
+ // Returns the record name.
+ const std::string &nameWithID(unsigned Opcode) const {
+ return AllInstructions[Opcode]->TheDef->getName();
+ }
+
+ // Populates the field of the insn given the start position and the number of
+ // consecutive bits to scan for.
+ //
+ // Returns false if there exists any uninitialized bit value in the range.
+ // Returns true, otherwise.
+ bool fieldFromInsn(uint64_t &Field, insn_t &Insn, unsigned StartBit,
+ unsigned NumBits) const;
+
+ /// dumpFilterArray - dumpFilterArray prints out debugging info for the given
+ /// filter array as a series of chars.
+ void dumpFilterArray(raw_ostream &o, std::vector<bit_value_t> & filter);
+
+ /// dumpStack - dumpStack traverses the filter chooser chain and calls
+ /// dumpFilterArray on each filter chooser up to the top level one.
+ void dumpStack(raw_ostream &o, const char *prefix);
+
+ Filter &bestFilter() {
+ assert(BestIndex != -1 && "BestIndex not set");
+ return Filters[BestIndex];
+ }
+
+ // Called from Filter::recurse() when singleton exists. For debug purpose.
+ void SingletonExists(unsigned Opc);
+
+ bool PositionFiltered(unsigned i) {
+ return ValueSet(FilterBitValues[i]);
+ }
+
+ // Calculates the island(s) needed to decode the instruction.
+ // This returns a lit of undecoded bits of an instructions, for example,
+ // Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be
+ // decoded bits in order to verify that the instruction matches the Opcode.
+ unsigned getIslands(std::vector<unsigned> &StartBits,
+ std::vector<unsigned> &EndBits, std::vector<uint64_t> &FieldVals,
+ insn_t &Insn);
+
+ // Emits code to check the Predicates member of an instruction are true.
+ // Returns true if predicate matches were emitted, false otherwise.
+ bool emitPredicateMatch(raw_ostream &o, unsigned &Indentation,unsigned Opc);
+
+ // Emits code to decode the singleton. Return true if we have matched all the
+ // well-known bits.
+ bool emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,unsigned Opc);
+
+ // Emits code to decode the singleton, and then to decode the rest.
+ void emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,Filter &Best);
+
+ void emitBinaryParser(raw_ostream &o , unsigned &Indentation,
+ OperandInfo &OpInfo);
+
+ // Assign a single filter and run with it.
+ void runSingleFilter(FilterChooser &owner, unsigned startBit, unsigned numBit,
+ bool mixed);
+
+ // reportRegion is a helper function for filterProcessor to mark a region as
+ // eligible for use as a filter region.
+ void reportRegion(bitAttr_t RA, unsigned StartBit, unsigned BitIndex,
+ bool AllowMixed);
+
+ // FilterProcessor scans the well-known encoding bits of the instructions and
+ // builds up a list of candidate filters. It chooses the best filter and
+ // recursively descends down the decoding tree.
+ bool filterProcessor(bool AllowMixed, bool Greedy = true);
+
+ // Decides on the best configuration of filter(s) to use in order to decode
+ // the instructions. A conflict of instructions may occur, in which case we
+ // dump the conflict set to the standard error.
+ void doFilter();
+
+ // Emits code to decode our share of instructions. Returns true if the
+ // emitted code causes a return, which occurs if we know how to decode
+ // the instruction at this level or the instruction is not decodeable.
+ bool emit(raw_ostream &o, unsigned &Indentation);
+};
+
+///////////////////////////
+// //
+// Filter Implmenetation //
+// //
+///////////////////////////
+
+Filter::Filter(const Filter &f) :
+ Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits), Mixed(f.Mixed),
+ FilteredInstructions(f.FilteredInstructions),
+ VariableInstructions(f.VariableInstructions),
+ FilterChooserMap(f.FilterChooserMap), NumFiltered(f.NumFiltered),
+ LastOpcFiltered(f.LastOpcFiltered), NumVariable(f.NumVariable) {
+}
+
+Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits,
+ bool mixed) : Owner(&owner), StartBit(startBit), NumBits(numBits),
+ Mixed(mixed) {
+ assert(StartBit + NumBits - 1 < Owner->BitWidth);
+
+ NumFiltered = 0;
+ LastOpcFiltered = 0;
+ NumVariable = 0;
+
+ for (unsigned i = 0, e = Owner->Opcodes.size(); i != e; ++i) {
+ insn_t Insn;
+
+ // Populates the insn given the uid.
+ Owner->insnWithID(Insn, Owner->Opcodes[i]);
+
+ uint64_t Field;
+ // Scans the segment for possibly well-specified encoding bits.
+ bool ok = Owner->fieldFromInsn(Field, Insn, StartBit, NumBits);
+
+ if (ok) {
+ // The encoding bits are well-known. Lets add the uid of the
+ // instruction into the bucket keyed off the constant field value.
+ LastOpcFiltered = Owner->Opcodes[i];
+ FilteredInstructions[Field].push_back(LastOpcFiltered);
+ ++NumFiltered;
+ } else {
+ // Some of the encoding bit(s) are unspecfied. This contributes to
+ // one additional member of "Variable" instructions.
+ VariableInstructions.push_back(Owner->Opcodes[i]);
+ ++NumVariable;
+ }
+ }
+
+ assert((FilteredInstructions.size() + VariableInstructions.size() > 0)
+ && "Filter returns no instruction categories");
+}
+
+Filter::~Filter() {
+ std::map<unsigned, FilterChooser*>::iterator filterIterator;
+ for (filterIterator = FilterChooserMap.begin();
+ filterIterator != FilterChooserMap.end();
+ filterIterator++) {
+ delete filterIterator->second;
+ }
+}
+
+// Divides the decoding task into sub tasks and delegates them to the
+// inferior FilterChooser's.
+//
+// A special case arises when there's only one entry in the filtered
+// instructions. In order to unambiguously decode the singleton, we need to
+// match the remaining undecoded encoding bits against the singleton.
+void Filter::recurse() {
+ std::map<uint64_t, std::vector<unsigned> >::const_iterator mapIterator;
+
+ // Starts by inheriting our parent filter chooser's filter bit values.
+ std::vector<bit_value_t> BitValueArray(Owner->FilterBitValues);
+
+ unsigned bitIndex;
+
+ if (VariableInstructions.size()) {
+ // Conservatively marks each segment position as BIT_UNSET.
+ for (bitIndex = 0; bitIndex < NumBits; bitIndex++)
+ BitValueArray[StartBit + bitIndex] = BIT_UNSET;
+
+ // Delegates to an inferior filter chooser for further processing on this
+ // group of instructions whose segment values are variable.
+ FilterChooserMap.insert(std::pair<unsigned, FilterChooser*>(
+ (unsigned)-1,
+ new FilterChooser(Owner->AllInstructions,
+ VariableInstructions,
+ Owner->Operands,
+ BitValueArray,
+ *Owner)
+ ));
+ }
+
+ // No need to recurse for a singleton filtered instruction.
+ // See also Filter::emit().
+ if (getNumFiltered() == 1) {
+ //Owner->SingletonExists(LastOpcFiltered);
+ assert(FilterChooserMap.size() == 1);
+ return;
+ }
+
+ // Otherwise, create sub choosers.
+ for (mapIterator = FilteredInstructions.begin();
+ mapIterator != FilteredInstructions.end();
+ mapIterator++) {
+
+ // Marks all the segment positions with either BIT_TRUE or BIT_FALSE.
+ for (bitIndex = 0; bitIndex < NumBits; bitIndex++) {
+ if (mapIterator->first & (1ULL << bitIndex))
+ BitValueArray[StartBit + bitIndex] = BIT_TRUE;
+ else
+ BitValueArray[StartBit + bitIndex] = BIT_FALSE;
+ }
+
+ // Delegates to an inferior filter chooser for further processing on this
+ // category of instructions.
+ FilterChooserMap.insert(std::pair<unsigned, FilterChooser*>(
+ mapIterator->first,
+ new FilterChooser(Owner->AllInstructions,
+ mapIterator->second,
+ Owner->Operands,
+ BitValueArray,
+ *Owner)
+ ));
+ }
+}
+
+// Emit code to decode instructions given a segment or segments of bits.
+void Filter::emit(raw_ostream &o, unsigned &Indentation) {
+ o.indent(Indentation) << "// Check Inst{";
+
+ if (NumBits > 1)
+ o << (StartBit + NumBits - 1) << '-';
+
+ o << StartBit << "} ...\n";
+
+ o.indent(Indentation) << "switch (fieldFromInstruction" << Owner->BitWidth
+ << "(insn, " << StartBit << ", "
+ << NumBits << ")) {\n";
+
+ std::map<unsigned, FilterChooser*>::iterator filterIterator;
+
+ bool DefaultCase = false;
+ for (filterIterator = FilterChooserMap.begin();
+ filterIterator != FilterChooserMap.end();
+ filterIterator++) {
+
+ // Field value -1 implies a non-empty set of variable instructions.
+ // See also recurse().
+ if (filterIterator->first == (unsigned)-1) {
+ DefaultCase = true;
+
+ o.indent(Indentation) << "default:\n";
+ o.indent(Indentation) << " break; // fallthrough\n";
+
+ // Closing curly brace for the switch statement.
+ // This is unconventional because we want the default processing to be
+ // performed for the fallthrough cases as well, i.e., when the "cases"
+ // did not prove a decoded instruction.
+ o.indent(Indentation) << "}\n";
+
+ } else
+ o.indent(Indentation) << "case " << filterIterator->first << ":\n";
+
+ // We arrive at a category of instructions with the same segment value.
+ // Now delegate to the sub filter chooser for further decodings.
+ // The case may fallthrough, which happens if the remaining well-known
+ // encoding bits do not match exactly.
+ if (!DefaultCase) { ++Indentation; ++Indentation; }
+
+ bool finished = filterIterator->second->emit(o, Indentation);
+ // For top level default case, there's no need for a break statement.
+ if (Owner->isTopLevel() && DefaultCase)
+ break;
+ if (!finished)
+ o.indent(Indentation) << "break;\n";
+
+ if (!DefaultCase) { --Indentation; --Indentation; }
+ }
+
+ // If there is no default case, we still need to supply a closing brace.
+ if (!DefaultCase) {
+ // Closing curly brace for the switch statement.
+ o.indent(Indentation) << "}\n";
+ }
+}
+
+// Returns the number of fanout produced by the filter. More fanout implies
+// the filter distinguishes more categories of instructions.
+unsigned Filter::usefulness() const {
+ if (VariableInstructions.size())
+ return FilteredInstructions.size();
+ else
+ return FilteredInstructions.size() + 1;
+}
+
+//////////////////////////////////
+// //
+// Filterchooser Implementation //
+// //
+//////////////////////////////////
+
+// Emit the top level typedef and decodeInstruction() function.
+void FilterChooser::emitTop(raw_ostream &o, unsigned Indentation,
+ std::string Namespace) {
+ o.indent(Indentation) <<
+ "static MCDisassembler::DecodeStatus decode" << Namespace << "Instruction" << BitWidth
+ << "(MCInst &MI, uint" << BitWidth << "_t insn, uint64_t Address, "
+ << "const void *Decoder, const MCSubtargetInfo &STI) {\n";
+ o.indent(Indentation) << " unsigned tmp = 0;\n (void)tmp;\n" << Emitter->Locals << "\n";
+ o.indent(Indentation) << " uint64_t Bits = STI.getFeatureBits();\n";
+
+ ++Indentation; ++Indentation;
+ // Emits code to decode the instructions.
+ emit(o, Indentation);
+
+ o << '\n';
+ o.indent(Indentation) << "return " << Emitter->ReturnFail << ";\n";
+ --Indentation; --Indentation;
+
+ o.indent(Indentation) << "}\n";
+
+ o << '\n';
+}
+
+// Populates the field of the insn given the start position and the number of
+// consecutive bits to scan for.
+//
+// Returns false if and on the first uninitialized bit value encountered.
+// Returns true, otherwise.
+bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn,
+ unsigned StartBit, unsigned NumBits) const {
+ Field = 0;
+
+ for (unsigned i = 0; i < NumBits; ++i) {
+ if (Insn[StartBit + i] == BIT_UNSET)
+ return false;
+
+ if (Insn[StartBit + i] == BIT_TRUE)
+ Field = Field | (1ULL << i);
+ }
+
+ return true;
+}
+
+/// dumpFilterArray - dumpFilterArray prints out debugging info for the given
+/// filter array as a series of chars.
+void FilterChooser::dumpFilterArray(raw_ostream &o,
+ std::vector<bit_value_t> &filter) {
+ unsigned bitIndex;
+
+ for (bitIndex = BitWidth; bitIndex > 0; bitIndex--) {
+ switch (filter[bitIndex - 1]) {
+ case BIT_UNFILTERED:
+ o << ".";
+ break;
+ case BIT_UNSET:
+ o << "_";
+ break;
+ case BIT_TRUE:
+ o << "1";
+ break;
+ case BIT_FALSE:
+ o << "0";
+ break;
+ }
+ }
+}
+
+/// dumpStack - dumpStack traverses the filter chooser chain and calls
+/// dumpFilterArray on each filter chooser up to the top level one.
+void FilterChooser::dumpStack(raw_ostream &o, const char *prefix) {
+ FilterChooser *current = this;
+
+ while (current) {
+ o << prefix;
+ dumpFilterArray(o, current->FilterBitValues);
+ o << '\n';
+ current = current->Parent;
+ }
+}
+
+// Called from Filter::recurse() when singleton exists. For debug purpose.
+void FilterChooser::SingletonExists(unsigned Opc) {
+ insn_t Insn0;
+ insnWithID(Insn0, Opc);
+
+ errs() << "Singleton exists: " << nameWithID(Opc)
+ << " with its decoding dominating ";
+ for (unsigned i = 0; i < Opcodes.size(); ++i) {
+ if (Opcodes[i] == Opc) continue;
+ errs() << nameWithID(Opcodes[i]) << ' ';
+ }
+ errs() << '\n';
+
+ dumpStack(errs(), "\t\t");
+ for (unsigned i = 0; i < Opcodes.size(); i++) {
+ const std::string &Name = nameWithID(Opcodes[i]);
+
+ errs() << '\t' << Name << " ";
+ dumpBits(errs(),
+ getBitsField(*AllInstructions[Opcodes[i]]->TheDef, "Inst"));
+ errs() << '\n';
+ }
+}
+
+// Calculates the island(s) needed to decode the instruction.
+// This returns a list of undecoded bits of an instructions, for example,
+// Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be
+// decoded bits in order to verify that the instruction matches the Opcode.
+unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits,
+ std::vector<unsigned> &EndBits, std::vector<uint64_t> &FieldVals,
+ insn_t &Insn) {
+ unsigned Num, BitNo;
+ Num = BitNo = 0;
+
+ uint64_t FieldVal = 0;
+
+ // 0: Init
+ // 1: Water (the bit value does not affect decoding)
+ // 2: Island (well-known bit value needed for decoding)
+ int State = 0;
+ int Val = -1;
+
+ for (unsigned i = 0; i < BitWidth; ++i) {
+ Val = Value(Insn[i]);
+ bool Filtered = PositionFiltered(i);
+ switch (State) {
+ default:
+ assert(0 && "Unreachable code!");
+ break;
+ case 0:
+ case 1:
+ if (Filtered || Val == -1)
+ State = 1; // Still in Water
+ else {
+ State = 2; // Into the Island
+ BitNo = 0;
+ StartBits.push_back(i);
+ FieldVal = Val;
+ }
+ break;
+ case 2:
+ if (Filtered || Val == -1) {
+ State = 1; // Into the Water
+ EndBits.push_back(i - 1);
+ FieldVals.push_back(FieldVal);
+ ++Num;
+ } else {
+ State = 2; // Still in Island
+ ++BitNo;
+ FieldVal = FieldVal | Val << BitNo;
+ }
+ break;
+ }
+ }
+ // If we are still in Island after the loop, do some housekeeping.
+ if (State == 2) {
+ EndBits.push_back(BitWidth - 1);
+ FieldVals.push_back(FieldVal);
+ ++Num;
+ }
+
+ assert(StartBits.size() == Num && EndBits.size() == Num &&
+ FieldVals.size() == Num);
+ return Num;
+}
+
+void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
+ OperandInfo &OpInfo) {
+ std::string &Decoder = OpInfo.Decoder;
+
+ if (OpInfo.numFields() == 1) {
+ OperandInfo::iterator OI = OpInfo.begin();
+ o.indent(Indentation) << " tmp = fieldFromInstruction" << BitWidth
+ << "(insn, " << OI->Base << ", " << OI->Width
+ << ");\n";
+ } else {
+ o.indent(Indentation) << " tmp = 0;\n";
+ for (OperandInfo::iterator OI = OpInfo.begin(), OE = OpInfo.end();
+ OI != OE; ++OI) {
+ o.indent(Indentation) << " tmp |= (fieldFromInstruction" << BitWidth
+ << "(insn, " << OI->Base << ", " << OI->Width
+ << ") << " << OI->Offset << ");\n";
+ }
+ }
+
+ if (Decoder != "")
+ o.indent(Indentation) << " " << Emitter->GuardPrefix << Decoder
+ << "(MI, tmp, Address, Decoder)" << Emitter->GuardPostfix << "\n";
+ else
+ o.indent(Indentation) << " MI.addOperand(MCOperand::CreateImm(tmp));\n";
+
+}
+
+static void emitSinglePredicateMatch(raw_ostream &o, StringRef str,
+ std::string PredicateNamespace) {
+ if (str[0] == '!')
+ o << "!(Bits & " << PredicateNamespace << "::"
+ << str.slice(1,str.size()) << ")";
+ else
+ o << "(Bits & " << PredicateNamespace << "::" << str << ")";
+}
+
+bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
+ unsigned Opc) {
+ ListInit *Predicates = AllInstructions[Opc]->TheDef->getValueAsListInit("Predicates");
+ for (unsigned i = 0; i < Predicates->getSize(); ++i) {
+ Record *Pred = Predicates->getElementAsRecord(i);
+ if (!Pred->getValue("AssemblerMatcherPredicate"))
+ continue;
+
+ std::string P = Pred->getValueAsString("AssemblerCondString");
+
+ if (!P.length())
+ continue;
+
+ if (i != 0)
+ o << " && ";
+
+ StringRef SR(P);
+ std::pair<StringRef, StringRef> pairs = SR.split(',');
+ while (pairs.second.size()) {
+ emitSinglePredicateMatch(o, pairs.first, Emitter->PredicateNamespace);
+ o << " && ";
+ pairs = pairs.second.split(',');
+ }
+ emitSinglePredicateMatch(o, pairs.first, Emitter->PredicateNamespace);
+ }
+ return Predicates->getSize() > 0;
+}
+
+// Emits code to decode the singleton. Return true if we have matched all the
+// well-known bits.
+bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
+ unsigned Opc) {
+ std::vector<unsigned> StartBits;
+ std::vector<unsigned> EndBits;
+ std::vector<uint64_t> FieldVals;
+ insn_t Insn;
+ insnWithID(Insn, Opc);
+
+ // Look for islands of undecoded bits of the singleton.
+ getIslands(StartBits, EndBits, FieldVals, Insn);
+
+ unsigned Size = StartBits.size();
+ unsigned I, NumBits;
+
+ // If we have matched all the well-known bits, just issue a return.
+ if (Size == 0) {
+ o.indent(Indentation) << "if (";
+ if (!emitPredicateMatch(o, Indentation, Opc))
+ o << "1";
+ o << ") {\n";
+ o.indent(Indentation) << " MI.setOpcode(" << Opc << ");\n";
+ std::vector<OperandInfo>& InsnOperands = Operands[Opc];
+ for (std::vector<OperandInfo>::iterator
+ I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) {
+ // If a custom instruction decoder was specified, use that.
+ if (I->numFields() == 0 && I->Decoder.size()) {
+ o.indent(Indentation) << " " << Emitter->GuardPrefix << I->Decoder
+ << "(MI, insn, Address, Decoder)" << Emitter->GuardPostfix << "\n";
+ break;
+ }
+
+ emitBinaryParser(o, Indentation, *I);
+ }
+
+ o.indent(Indentation) << " return " << Emitter->ReturnOK << "; // " << nameWithID(Opc)
+ << '\n';
+ o.indent(Indentation) << "}\n"; // Closing predicate block.
+ return true;
+ }
+
+ // Otherwise, there are more decodings to be done!
+
+ // Emit code to match the island(s) for the singleton.
+ o.indent(Indentation) << "// Check ";
+
+ for (I = Size; I != 0; --I) {
+ o << "Inst{" << EndBits[I-1] << '-' << StartBits[I-1] << "} ";
+ if (I > 1)
+ o << " && ";
+ else
+ o << "for singleton decoding...\n";
+ }
+
+ o.indent(Indentation) << "if (";
+ if (emitPredicateMatch(o, Indentation, Opc)) {
+ o << " &&\n";
+ o.indent(Indentation+4);
+ }
+
+ for (I = Size; I != 0; --I) {
+ NumBits = EndBits[I-1] - StartBits[I-1] + 1;
+ o << "fieldFromInstruction" << BitWidth << "(insn, "
+ << StartBits[I-1] << ", " << NumBits
+ << ") == " << FieldVals[I-1];
+ if (I > 1)
+ o << " && ";
+ else
+ o << ") {\n";
+ }
+ o.indent(Indentation) << " MI.setOpcode(" << Opc << ");\n";
+ std::vector<OperandInfo>& InsnOperands = Operands[Opc];
+ for (std::vector<OperandInfo>::iterator
+ I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) {
+ // If a custom instruction decoder was specified, use that.
+ if (I->numFields() == 0 && I->Decoder.size()) {
+ o.indent(Indentation) << " " << Emitter->GuardPrefix << I->Decoder
+ << "(MI, insn, Address, Decoder)" << Emitter->GuardPostfix << "\n";
+ break;
+ }
+
+ emitBinaryParser(o, Indentation, *I);
+ }
+ o.indent(Indentation) << " return " << Emitter->ReturnOK << "; // " << nameWithID(Opc)
+ << '\n';
+ o.indent(Indentation) << "}\n";
+
+ return false;
+}
+
+// Emits code to decode the singleton, and then to decode the rest.
+void FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation,
+ Filter &Best) {
+
+ unsigned Opc = Best.getSingletonOpc();
+
+ emitSingletonDecoder(o, Indentation, Opc);
+
+ // Emit code for the rest.
+ o.indent(Indentation) << "else\n";
+
+ Indentation += 2;
+ Best.getVariableFC().emit(o, Indentation);
+ Indentation -= 2;
+}
+
+// Assign a single filter and run with it. Top level API client can initialize
+// with a single filter to start the filtering process.
+void FilterChooser::runSingleFilter(FilterChooser &owner, unsigned startBit,
+ unsigned numBit, bool mixed) {
+ Filters.clear();
+ Filter F(*this, startBit, numBit, true);
+ Filters.push_back(F);
+ BestIndex = 0; // Sole Filter instance to choose from.
+ bestFilter().recurse();
+}
+
+// reportRegion is a helper function for filterProcessor to mark a region as
+// eligible for use as a filter region.
+void FilterChooser::reportRegion(bitAttr_t RA, unsigned StartBit,
+ unsigned BitIndex, bool AllowMixed) {
+ if (RA == ATTR_MIXED && AllowMixed)
+ Filters.push_back(Filter(*this, StartBit, BitIndex - StartBit, true));
+ else if (RA == ATTR_ALL_SET && !AllowMixed)
+ Filters.push_back(Filter(*this, StartBit, BitIndex - StartBit, false));
+}
+
+// FilterProcessor scans the well-known encoding bits of the instructions and
+// builds up a list of candidate filters. It chooses the best filter and
+// recursively descends down the decoding tree.
+bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) {
+ Filters.clear();
+ BestIndex = -1;
+ unsigned numInstructions = Opcodes.size();
+
+ assert(numInstructions && "Filter created with no instructions");
+
+ // No further filtering is necessary.
+ if (numInstructions == 1)
+ return true;
+
+ // Heuristics. See also doFilter()'s "Heuristics" comment when num of
+ // instructions is 3.
+ if (AllowMixed && !Greedy) {
+ assert(numInstructions == 3);
+
+ for (unsigned i = 0; i < Opcodes.size(); ++i) {
+ std::vector<unsigned> StartBits;
+ std::vector<unsigned> EndBits;
+ std::vector<uint64_t> FieldVals;
+ insn_t Insn;
+
+ insnWithID(Insn, Opcodes[i]);
+
+ // Look for islands of undecoded bits of any instruction.
+ if (getIslands(StartBits, EndBits, FieldVals, Insn) > 0) {
+ // Found an instruction with island(s). Now just assign a filter.
+ runSingleFilter(*this, StartBits[0], EndBits[0] - StartBits[0] + 1,
+ true);
+ return true;
+ }
+ }
+ }
+
+ unsigned BitIndex, InsnIndex;
+
+ // We maintain BIT_WIDTH copies of the bitAttrs automaton.
+ // The automaton consumes the corresponding bit from each
+ // instruction.
+ //
+ // Input symbols: 0, 1, and _ (unset).
+ // States: NONE, FILTERED, ALL_SET, ALL_UNSET, and MIXED.
+ // Initial state: NONE.
+ //
+ // (NONE) ------- [01] -> (ALL_SET)
+ // (NONE) ------- _ ----> (ALL_UNSET)
+ // (ALL_SET) ---- [01] -> (ALL_SET)
+ // (ALL_SET) ---- _ ----> (MIXED)
+ // (ALL_UNSET) -- [01] -> (MIXED)
+ // (ALL_UNSET) -- _ ----> (ALL_UNSET)
+ // (MIXED) ------ . ----> (MIXED)
+ // (FILTERED)---- . ----> (FILTERED)
+
+ std::vector<bitAttr_t> bitAttrs;
+
+ // FILTERED bit positions provide no entropy and are not worthy of pursuing.
+ // Filter::recurse() set either BIT_TRUE or BIT_FALSE for each position.
+ for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex)
+ if (FilterBitValues[BitIndex] == BIT_TRUE ||
+ FilterBitValues[BitIndex] == BIT_FALSE)
+ bitAttrs.push_back(ATTR_FILTERED);
+ else
+ bitAttrs.push_back(ATTR_NONE);
+
+ for (InsnIndex = 0; InsnIndex < numInstructions; ++InsnIndex) {
+ insn_t insn;
+
+ insnWithID(insn, Opcodes[InsnIndex]);
+
+ for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex) {
+ switch (bitAttrs[BitIndex]) {
+ case ATTR_NONE:
+ if (insn[BitIndex] == BIT_UNSET)
+ bitAttrs[BitIndex] = ATTR_ALL_UNSET;
+ else
+ bitAttrs[BitIndex] = ATTR_ALL_SET;
+ break;
+ case ATTR_ALL_SET:
+ if (insn[BitIndex] == BIT_UNSET)
+ bitAttrs[BitIndex] = ATTR_MIXED;
+ break;
+ case ATTR_ALL_UNSET:
+ if (insn[BitIndex] != BIT_UNSET)
+ bitAttrs[BitIndex] = ATTR_MIXED;
+ break;
+ case ATTR_MIXED:
+ case ATTR_FILTERED:
+ break;
+ }
+ }
+ }
+
+ // The regionAttr automaton consumes the bitAttrs automatons' state,
+ // lowest-to-highest.
+ //
+ // Input symbols: F(iltered), (all_)S(et), (all_)U(nset), M(ixed)
+ // States: NONE, ALL_SET, MIXED
+ // Initial state: NONE
+ //
+ // (NONE) ----- F --> (NONE)
+ // (NONE) ----- S --> (ALL_SET) ; and set region start
+ // (NONE) ----- U --> (NONE)
+ // (NONE) ----- M --> (MIXED) ; and set region start
+ // (ALL_SET) -- F --> (NONE) ; and report an ALL_SET region
+ // (ALL_SET) -- S --> (ALL_SET)
+ // (ALL_SET) -- U --> (NONE) ; and report an ALL_SET region
+ // (ALL_SET) -- M --> (MIXED) ; and report an ALL_SET region
+ // (MIXED) ---- F --> (NONE) ; and report a MIXED region
+ // (MIXED) ---- S --> (ALL_SET) ; and report a MIXED region
+ // (MIXED) ---- U --> (NONE) ; and report a MIXED region
+ // (MIXED) ---- M --> (MIXED)
+
+ bitAttr_t RA = ATTR_NONE;
+ unsigned StartBit = 0;
+
+ for (BitIndex = 0; BitIndex < BitWidth; BitIndex++) {
+ bitAttr_t bitAttr = bitAttrs[BitIndex];
+
+ assert(bitAttr != ATTR_NONE && "Bit without attributes");
+
+ switch (RA) {
+ case ATTR_NONE:
+ switch (bitAttr) {
+ case ATTR_FILTERED:
+ break;
+ case ATTR_ALL_SET:
+ StartBit = BitIndex;
+ RA = ATTR_ALL_SET;
+ break;
+ case ATTR_ALL_UNSET:
+ break;
+ case ATTR_MIXED:
+ StartBit = BitIndex;
+ RA = ATTR_MIXED;
+ break;
+ default:
+ assert(0 && "Unexpected bitAttr!");
+ }
+ break;
+ case ATTR_ALL_SET:
+ switch (bitAttr) {
+ case ATTR_FILTERED:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ RA = ATTR_NONE;
+ break;
+ case ATTR_ALL_SET:
+ break;
+ case ATTR_ALL_UNSET:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ RA = ATTR_NONE;
+ break;
+ case ATTR_MIXED:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ StartBit = BitIndex;
+ RA = ATTR_MIXED;
+ break;
+ default:
+ assert(0 && "Unexpected bitAttr!");
+ }
+ break;
+ case ATTR_MIXED:
+ switch (bitAttr) {
+ case ATTR_FILTERED:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ StartBit = BitIndex;
+ RA = ATTR_NONE;
+ break;
+ case ATTR_ALL_SET:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ StartBit = BitIndex;
+ RA = ATTR_ALL_SET;
+ break;
+ case ATTR_ALL_UNSET:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ RA = ATTR_NONE;
+ break;
+ case ATTR_MIXED:
+ break;
+ default:
+ assert(0 && "Unexpected bitAttr!");
+ }
+ break;
+ case ATTR_ALL_UNSET:
+ assert(0 && "regionAttr state machine has no ATTR_UNSET state");
+ case ATTR_FILTERED:
+ assert(0 && "regionAttr state machine has no ATTR_FILTERED state");
+ }
+ }
+
+ // At the end, if we're still in ALL_SET or MIXED states, report a region
+ switch (RA) {
+ case ATTR_NONE:
+ break;
+ case ATTR_FILTERED:
+ break;
+ case ATTR_ALL_SET:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ break;
+ case ATTR_ALL_UNSET:
+ break;
+ case ATTR_MIXED:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ break;
+ }
+
+ // We have finished with the filter processings. Now it's time to choose
+ // the best performing filter.
+ BestIndex = 0;
+ bool AllUseless = true;
+ unsigned BestScore = 0;
+
+ for (unsigned i = 0, e = Filters.size(); i != e; ++i) {
+ unsigned Usefulness = Filters[i].usefulness();
+
+ if (Usefulness)
+ AllUseless = false;
+
+ if (Usefulness > BestScore) {
+ BestIndex = i;
+ BestScore = Usefulness;
+ }
+ }
+
+ if (!AllUseless)
+ bestFilter().recurse();
+
+ return !AllUseless;
+} // end of FilterChooser::filterProcessor(bool)
+
+// Decides on the best configuration of filter(s) to use in order to decode
+// the instructions. A conflict of instructions may occur, in which case we
+// dump the conflict set to the standard error.
+void FilterChooser::doFilter() {
+ unsigned Num = Opcodes.size();
+ assert(Num && "FilterChooser created with no instructions");
+
+ // Try regions of consecutive known bit values first.
+ if (filterProcessor(false))
+ return;
+
+ // Then regions of mixed bits (both known and unitialized bit values allowed).
+ if (filterProcessor(true))
+ return;
+
+ // Heuristics to cope with conflict set {t2CMPrs, t2SUBSrr, t2SUBSrs} where
+ // no single instruction for the maximum ATTR_MIXED region Inst{14-4} has a
+ // well-known encoding pattern. In such case, we backtrack and scan for the
+ // the very first consecutive ATTR_ALL_SET region and assign a filter to it.
+ if (Num == 3 && filterProcessor(true, false))
+ return;
+
+ // If we come to here, the instruction decoding has failed.
+ // Set the BestIndex to -1 to indicate so.
+ BestIndex = -1;
+}
+
+// Emits code to decode our share of instructions. Returns true if the
+// emitted code causes a return, which occurs if we know how to decode
+// the instruction at this level or the instruction is not decodeable.
+bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) {
+ if (Opcodes.size() == 1)
+ // There is only one instruction in the set, which is great!
+ // Call emitSingletonDecoder() to see whether there are any remaining
+ // encodings bits.
+ return emitSingletonDecoder(o, Indentation, Opcodes[0]);
+
+ // Choose the best filter to do the decodings!
+ if (BestIndex != -1) {
+ Filter &Best = bestFilter();
+ if (Best.getNumFiltered() == 1)
+ emitSingletonDecoder(o, Indentation, Best);
+ else
+ bestFilter().emit(o, Indentation);
+ return false;
+ }
+
+ // We don't know how to decode these instructions! Return 0 and dump the
+ // conflict set!
+ o.indent(Indentation) << "return 0;" << " // Conflict set: ";
+ for (int i = 0, N = Opcodes.size(); i < N; ++i) {
+ o << nameWithID(Opcodes[i]);
+ if (i < (N - 1))
+ o << ", ";
+ else
+ o << '\n';
+ }
+
+ // Print out useful conflict information for postmortem analysis.
+ errs() << "Decoding Conflict:\n";
+
+ dumpStack(errs(), "\t\t");
+
+ for (unsigned i = 0; i < Opcodes.size(); i++) {
+ const std::string &Name = nameWithID(Opcodes[i]);
+
+ errs() << '\t' << Name << " ";
+ dumpBits(errs(),
+ getBitsField(*AllInstructions[Opcodes[i]]->TheDef, "Inst"));
+ errs() << '\n';
+ }
+
+ return true;
+}
+
+static bool populateInstruction(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;
+
+ std::vector<OperandInfo> InsnOperands;
+
+ // If the instruction has specified a custom decoding hook, use that instead
+ // of trying to auto-generate the decoder.
+ std::string InstDecoder = Def.getValueAsString("DecoderMethod");
+ if (InstDecoder != "") {
+ InsnOperands.push_back(OperandInfo(InstDecoder));
+ Operands[Opc] = InsnOperands;
+ return true;
+ }
+
+ // Generate a description of the operand of the instruction that we know
+ // how to decode automatically.
+ // FIXME: We'll need to have a way to manually override this as needed.
+
+ // Gather the outputs/inputs of the instruction, so we can find their
+ // positions in the encoding. This assumes for now that they appear in the
+ // MCInst in the order that they're listed.
+ std::vector<std::pair<Init*, std::string> > InOutOperands;
+ DagInit *Out = Def.getValueAsDag("OutOperandList");
+ DagInit *In = Def.getValueAsDag("InOperandList");
+ for (unsigned i = 0; i < Out->getNumArgs(); ++i)
+ InOutOperands.push_back(std::make_pair(Out->getArg(i), Out->getArgName(i)));
+ for (unsigned i = 0; i < In->getNumArgs(); ++i)
+ InOutOperands.push_back(std::make_pair(In->getArg(i), In->getArgName(i)));
+
+ // Search for tied operands, so that we can correctly instantiate
+ // operands that are not explicitly represented in the encoding.
+ std::map<std::string, std::string> TiedNames;
+ 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;
+ }
+ }
+
+ // For each operand, see if we can figure out where it is encoded.
+ for (std::vector<std::pair<Init*, std::string> >::iterator
+ NI = InOutOperands.begin(), NE = InOutOperands.end(); NI != NE; ++NI) {
+ std::string Decoder = "";
+
+ // At this point, we can locate the field, but we need to know how to
+ // interpret it. As a first step, require the target to provide callbacks
+ // for decoding register classes.
+ // FIXME: This need to be extended to handle instructions with custom
+ // decoder methods, and operands with (simple) MIOperandInfo's.
+ TypedInit *TI = dynamic_cast<TypedInit*>(NI->first);
+ RecordRecTy *Type = dynamic_cast<RecordRecTy*>(TI->getType());
+ Record *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;
+ }
+
+ RecordVal *DecoderString = TypeRecord->getValue("DecoderMethod");
+ StringInit *String = DecoderString ?
+ dynamic_cast<StringInit*>(DecoderString->getValue()) : 0;
+ if (!isReg && String && String->getValue() != "")
+ Decoder = String->getValue();
+
+ OperandInfo OpInfo(Decoder);
+ unsigned Base = ~0U;
+ unsigned Width = 0;
+ unsigned Offset = 0;
+
+ for (unsigned bi = 0; bi < Bits.getNumBits(); ++bi) {
+ VarInit *Var = 0;
+ VarBitInit *BI = dynamic_cast<VarBitInit*>(Bits.getBit(bi));
+ if (BI)
+ Var = dynamic_cast<VarInit*>(BI->getVariable());
+ else
+ Var = dynamic_cast<VarInit*>(Bits.getBit(bi));
+
+ if (!Var) {
+ if (Base != ~0U) {
+ OpInfo.addField(Base, Width, Offset);
+ Base = ~0U;
+ Width = 0;
+ Offset = 0;
+ }
+ continue;
+ }
+
+ if (Var->getName() != NI->second &&
+ Var->getName() != TiedNames[NI->second]) {
+ if (Base != ~0U) {
+ OpInfo.addField(Base, Width, Offset);
+ Base = ~0U;
+ Width = 0;
+ Offset = 0;
+ }
+ continue;
+ }
+
+ if (Base == ~0U) {
+ Base = bi;
+ Width = 1;
+ Offset = BI ? BI->getBitNum() : 0;
+ } else if (BI && BI->getBitNum() != Offset + Width) {
+ OpInfo.addField(Base, Width, Offset);
+ Base = bi;
+ Width = 1;
+ Offset = BI->getBitNum();
+ } else {
+ ++Width;
+ }
+ }
+
+ if (Base != ~0U)
+ OpInfo.addField(Base, Width, Offset);
+
+ if (OpInfo.numFields() > 0)
+ InsnOperands.push_back(OpInfo);
+ }
+
+ Operands[Opc] = InsnOperands;
+
+
+#if 0
+ DEBUG({
+ // Dumps the instruction encoding bits.
+ dumpBits(errs(), Bits);
+
+ errs() << '\n';
+
+ // Dumps the list of operand info.
+ for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) {
+ const CGIOperandList::OperandInfo &Info = CGI.Operands[i];
+ const std::string &OperandName = Info.Name;
+ const Record &OperandDef = *Info.Rec;
+
+ errs() << "\t" << OperandName << " (" << OperandDef.getName() << ")\n";
+ }
+ });
+#endif
+
+ return true;
+}
+
+static void emitHelper(llvm::raw_ostream &o, unsigned BitWidth) {
+ unsigned Indentation = 0;
+ std::string WidthStr = "uint" + utostr(BitWidth) + "_t";
+
+ o << '\n';
+
+ o.indent(Indentation) << "static " << WidthStr <<
+ " fieldFromInstruction" << BitWidth <<
+ "(" << WidthStr <<" insn, unsigned startBit, unsigned numBits)\n";
+
+ o.indent(Indentation) << "{\n";
+
+ ++Indentation; ++Indentation;
+ o.indent(Indentation) << "assert(startBit + numBits <= " << BitWidth
+ << " && \"Instruction field out of bounds!\");\n";
+ o << '\n';
+ o.indent(Indentation) << WidthStr << " fieldMask;\n";
+ o << '\n';
+ o.indent(Indentation) << "if (numBits == " << BitWidth << ")\n";
+
+ ++Indentation; ++Indentation;
+ o.indent(Indentation) << "fieldMask = (" << WidthStr << ")-1;\n";
+ --Indentation; --Indentation;
+
+ o.indent(Indentation) << "else\n";
+
+ ++Indentation; ++Indentation;
+ o.indent(Indentation) << "fieldMask = ((1 << numBits) - 1) << startBit;\n";
+ --Indentation; --Indentation;
+
+ o << '\n';
+ o.indent(Indentation) << "return (insn & fieldMask) >> startBit;\n";
+ --Indentation; --Indentation;
+
+ o.indent(Indentation) << "}\n";
+
+ o << '\n';
+}
+
+// Emits disassembler code for instruction decoding.
+void FixedLenDecoderEmitter::run(raw_ostream &o)
+{
+ o << "#include \"llvm/MC/MCInst.h\"\n";
+ o << "#include \"llvm/Support/DataTypes.h\"\n";
+ o << "#include <assert.h>\n";
+ o << '\n';
+ o << "namespace llvm {\n\n";
+
+ // Parameterize the decoders based on namespace and instruction width.
+ NumberedInstructions = Target.getInstructionsByEnumValue();
+ std::map<std::pair<std::string, unsigned>,
+ std::vector<unsigned> > OpcMap;
+ std::map<unsigned, std::vector<OperandInfo> > Operands;
+
+ for (unsigned i = 0; i < NumberedInstructions.size(); ++i) {
+ const CodeGenInstruction *Inst = NumberedInstructions[i];
+ Record *Def = Inst->TheDef;
+ unsigned Size = Def->getValueAsInt("Size");
+ if (Def->getValueAsString("Namespace") == "TargetOpcode" ||
+ Def->getValueAsBit("isPseudo") ||
+ Def->getValueAsBit("isAsmParserOnly") ||
+ Def->getValueAsBit("isCodeGenOnly"))
+ continue;
+
+ std::string DecoderNamespace = Def->getValueAsString("DecoderNamespace");
+
+ if (Size) {
+ if (populateInstruction(*Inst, i, Operands)) {
+ OpcMap[std::make_pair(DecoderNamespace, Size)].push_back(i);
+ }
+ }
+ }
+
+ std::set<unsigned> Sizes;
+ for (std::map<std::pair<std::string, unsigned>,
+ std::vector<unsigned> >::iterator
+ I = OpcMap.begin(), E = OpcMap.end(); I != E; ++I) {
+ // If we haven't visited this instruction width before, emit the
+ // helper method to extract fields.
+ if (!Sizes.count(I->first.second)) {
+ emitHelper(o, 8*I->first.second);
+ Sizes.insert(I->first.second);
+ }
+
+ // Emit the decoder for this namespace+width combination.
+ FilterChooser FC(NumberedInstructions, I->second, Operands,
+ 8*I->first.second, this);
+ FC.emitTop(o, 0, I->first.first);
+ }
+
+ o << "\n} // End llvm namespace \n";
+}
diff --git a/src/LLVM/utils/TableGen/FixedLenDecoderEmitter.h b/src/LLVM/utils/TableGen/FixedLenDecoderEmitter.h
new file mode 100644
index 0000000..2df5448
--- /dev/null
+++ b/src/LLVM/utils/TableGen/FixedLenDecoderEmitter.h
@@ -0,0 +1,83 @@
+//===------------ FixedLenDecoderEmitter.h - Decoder Generator --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// It contains the tablegen backend that emits the decoder functions for
+// targets with fixed length instruction set.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FixedLenDECODEREMITTER_H
+#define FixedLenDECODEREMITTER_H
+
+#include "CodeGenTarget.h"
+
+#include "llvm/TableGen/TableGenBackend.h"
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+
+struct EncodingField {
+ unsigned Base, Width, Offset;
+ EncodingField(unsigned B, unsigned W, unsigned O)
+ : Base(B), Width(W), Offset(O) { }
+};
+
+struct OperandInfo {
+ std::vector<EncodingField> Fields;
+ std::string Decoder;
+
+ OperandInfo(std::string D)
+ : Decoder(D) { }
+
+ void addField(unsigned Base, unsigned Width, unsigned Offset) {
+ Fields.push_back(EncodingField(Base, Width, Offset));
+ }
+
+ unsigned numFields() { return Fields.size(); }
+
+ typedef std::vector<EncodingField>::iterator iterator;
+
+ iterator begin() { return Fields.begin(); }
+ iterator end() { return Fields.end(); }
+};
+
+class FixedLenDecoderEmitter : public TableGenBackend {
+public:
+ FixedLenDecoderEmitter(RecordKeeper &R,
+ std::string PredicateNamespace,
+ std::string GPrefix = "if (",
+ std::string GPostfix = " == MCDisassembler::Fail) return MCDisassembler::Fail;",
+ std::string ROK = "MCDisassembler::Success",
+ std::string RFail = "MCDisassembler::Fail",
+ std::string L = "") :
+ Records(R), Target(R),
+ NumberedInstructions(Target.getInstructionsByEnumValue()),
+ PredicateNamespace(PredicateNamespace),
+ GuardPrefix(GPrefix), GuardPostfix(GPostfix),
+ ReturnOK(ROK), ReturnFail(RFail), Locals(L) {}
+
+ // run - Output the code emitter
+ void run(raw_ostream &o);
+
+private:
+ RecordKeeper &Records;
+ CodeGenTarget Target;
+ std::vector<const CodeGenInstruction*> NumberedInstructions;
+ std::vector<unsigned> Opcodes;
+ std::map<unsigned, std::vector<OperandInfo> > Operands;
+public:
+ std::string PredicateNamespace;
+ std::string GuardPrefix, GuardPostfix;
+ std::string ReturnOK, ReturnFail;
+ std::string Locals;
+};
+
+} // end llvm namespace
+
+#endif
diff --git a/src/LLVM/utils/TableGen/INSTALL.vcxproj b/src/LLVM/utils/TableGen/INSTALL.vcxproj
new file mode 100644
index 0000000..366e1d9
--- /dev/null
+++ b/src/LLVM/utils/TableGen/INSTALL.vcxproj
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGUID>{048BB775-7681-4EE1-AACF-5A067ACEEEA5}</ProjectGUID>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>INSTALL</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\INSTALL_force.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\generate.stamp</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\ALL_BUILD.vcxproj">
+ <Project>17AECBCF-B2AE-4524-9010-9A175A8F6BFE</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/src/LLVM/utils/TableGen/INSTALL.vcxproj.filters b/src/LLVM/utils/TableGen/INSTALL.vcxproj.filters
new file mode 100644
index 0000000..251dd1d
--- /dev/null
+++ b/src/LLVM/utils/TableGen/INSTALL.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\INSTALL_force.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ <CustomBuild Include="CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{71794486-B3CB-4A48-93CC-DE95557E96E1}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
diff --git a/src/LLVM/utils/TableGen/InstrEnumEmitter.cpp b/src/LLVM/utils/TableGen/InstrEnumEmitter.cpp
index 47a8474..5981afd 100644
--- a/src/LLVM/utils/TableGen/InstrEnumEmitter.cpp
+++ b/src/LLVM/utils/TableGen/InstrEnumEmitter.cpp
@@ -14,7 +14,7 @@
#include "InstrEnumEmitter.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include <cstdio>
using namespace llvm;
@@ -23,7 +23,7 @@
EmitSourceFileHeader("Target Instruction Enum Values", OS);
OS << "namespace llvm {\n\n";
- CodeGenTarget Target;
+ CodeGenTarget Target(Records);
// We must emit the PHI opcode first...
std::string Namespace = Target.getInstNamespace();
diff --git a/src/LLVM/utils/TableGen/InstrEnumEmitter.h b/src/LLVM/utils/TableGen/InstrEnumEmitter.h
index 89f8b65..c29a309 100644
--- a/src/LLVM/utils/TableGen/InstrEnumEmitter.h
+++ b/src/LLVM/utils/TableGen/InstrEnumEmitter.h
@@ -15,7 +15,7 @@
#ifndef INSTRENUM_EMITTER_H
#define INSTRENUM_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
namespace llvm {
diff --git a/src/LLVM/utils/TableGen/InstrInfoEmitter.cpp b/src/LLVM/utils/TableGen/InstrInfoEmitter.cpp
index 4d3aa5e..8341724 100644
--- a/src/LLVM/utils/TableGen/InstrInfoEmitter.cpp
+++ b/src/LLVM/utils/TableGen/InstrInfoEmitter.cpp
@@ -14,7 +14,7 @@
#include "InstrInfoEmitter.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include <algorithm>
using namespace llvm;
@@ -27,14 +27,6 @@
OS << "0 };\n";
}
-static void PrintBarriers(std::vector<Record*> &Barriers,
- unsigned Num, raw_ostream &OS) {
- OS << "static const TargetRegisterClass* Barriers" << Num << "[] = { ";
- for (unsigned i = 0, e = Barriers.size(); i != e; ++i)
- OS << "&" << getQualifiedName(Barriers[i]) << "RegClass, ";
- OS << "NULL };\n";
-}
-
//===----------------------------------------------------------------------===//
// Instruction Itinerary Information.
//===----------------------------------------------------------------------===//
@@ -43,10 +35,10 @@
std::vector<Record*> DefList =
Records.getAllDerivedDefinitions("InstrItinClass");
std::sort(DefList.begin(), DefList.end(), LessRecord());
-
+
for (unsigned i = 0, N = DefList.size(); i < N; i++)
ItinClassMap[DefList[i]->getName()] = i;
-}
+}
unsigned InstrInfoEmitter::getItinClassNumber(const Record *InstRec) {
return ItinClassMap[InstRec->getValueAsDef("Itinerary")->getName()];
@@ -59,24 +51,24 @@
std::vector<std::string>
InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
std::vector<std::string> Result;
-
- for (unsigned i = 0, e = Inst.OperandList.size(); i != e; ++i) {
+
+ for (unsigned i = 0, e = Inst.Operands.size(); i != e; ++i) {
// Handle aggregate operands and normal operands the same way by expanding
// either case into a list of operands for this op.
- std::vector<CodeGenInstruction::OperandInfo> OperandList;
+ std::vector<CGIOperandList::OperandInfo> OperandList;
// This might be a multiple operand thing. Targets like X86 have
// 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.OperandList[i].MIOperandInfo;
-
+ DagInit *MIOI = Inst.Operands[i].MIOperandInfo;
+
if (!MIOI || MIOI->getNumArgs() == 0) {
// Single, anonymous, operand.
- OperandList.push_back(Inst.OperandList[i]);
+ OperandList.push_back(Inst.Operands[i]);
} else {
- for (unsigned j = 0, e = Inst.OperandList[i].MINumOperands; j != e; ++j) {
- OperandList.push_back(Inst.OperandList[i]);
+ for (unsigned j = 0, e = Inst.Operands[i].MINumOperands; j != e; ++j) {
+ OperandList.push_back(Inst.Operands[i]);
Record *OpR = dynamic_cast<DefInit*>(MIOI->getArg(j))->getDef();
OperandList.back().Rec = OpR;
@@ -86,7 +78,9 @@
for (unsigned j = 0, e = OperandList.size(); j != e; ++j) {
Record *OpR = OperandList[j].Rec;
std::string Res;
-
+
+ if (OpR->isSubClassOf("RegisterOperand"))
+ OpR = OpR->getValueAsDef("RegClass");
if (OpR->isSubClassOf("RegisterClass"))
Res += getQualifiedName(OpR) + "RegClassID, ";
else if (OpR->isSubClassOf("PointerLikeRegClass"))
@@ -94,39 +88,44 @@
else
// -1 means the operand does not have a fixed register class.
Res += "-1, ";
-
+
// Fill in applicable flags.
Res += "0";
-
+
// Ptr value whose register class is resolved via callback.
if (OpR->isSubClassOf("PointerLikeRegClass"))
- Res += "|(1<<TOI::LookupPtrRegClass)";
+ Res += "|(1<<MCOI::LookupPtrRegClass)";
// Predicate operands. Check to see if the original unexpanded operand
// was of type PredicateOperand.
- if (Inst.OperandList[i].Rec->isSubClassOf("PredicateOperand"))
- Res += "|(1<<TOI::Predicate)";
-
+ if (Inst.Operands[i].Rec->isSubClassOf("PredicateOperand"))
+ Res += "|(1<<MCOI::Predicate)";
+
// Optional def operands. Check to see if the original unexpanded operand
// was of type OptionalDefOperand.
- if (Inst.OperandList[i].Rec->isSubClassOf("OptionalDefOperand"))
- Res += "|(1<<TOI::OptionalDef)";
+ if (Inst.Operands[i].Rec->isSubClassOf("OptionalDefOperand"))
+ Res += "|(1<<MCOI::OptionalDef)";
// Fill in constraint info.
Res += ", ";
-
- const CodeGenInstruction::ConstraintInfo &Constraint =
- Inst.OperandList[i].Constraints[j];
+
+ const CGIOperandList::ConstraintInfo &Constraint =
+ Inst.Operands[i].Constraints[j];
if (Constraint.isNone())
Res += "0";
else if (Constraint.isEarlyClobber())
- Res += "(1 << TOI::EARLY_CLOBBER)";
+ Res += "(1 << MCOI::EARLY_CLOBBER)";
else {
assert(Constraint.isTied());
Res += "((" + utostr(Constraint.getTiedOperand()) +
- " << 16) | (1 << TOI::TIED_TO))";
+ " << 16) | (1 << MCOI::TIED_TO))";
}
-
+
+ // Fill in operand type.
+ Res += ", MCOI::";
+ assert(!Inst.Operands[i].OperandType.empty() && "Invalid operand type.");
+ Res += Inst.Operands[i].OperandType;
+
Result.push_back(Res);
}
}
@@ -134,12 +133,12 @@
return Result;
}
-void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
+void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
OperandInfoMapTy &OperandInfoIDs) {
// ID #0 is for no operand info.
unsigned OperandListNum = 0;
OperandInfoIDs[std::vector<std::string>()] = ++OperandListNum;
-
+
OS << "\n";
const CodeGenTarget &Target = CDP.getTargetInfo();
for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
@@ -147,65 +146,40 @@
std::vector<std::string> OperandInfo = GetOperandInfo(**II);
unsigned &N = OperandInfoIDs[OperandInfo];
if (N != 0) continue;
-
+
N = ++OperandListNum;
- OS << "static const TargetOperandInfo OperandInfo" << N << "[] = { ";
+ OS << "static const MCOperandInfo OperandInfo" << N << "[] = { ";
for (unsigned i = 0, e = OperandInfo.size(); i != e; ++i)
OS << "{ " << OperandInfo[i] << " }, ";
OS << "};\n";
}
}
-void InstrInfoEmitter::DetectRegisterClassBarriers(std::vector<Record*> &Defs,
- const std::vector<CodeGenRegisterClass> &RCs,
- std::vector<Record*> &Barriers) {
- std::set<Record*> DefSet;
- unsigned NumDefs = Defs.size();
- for (unsigned i = 0; i < NumDefs; ++i)
- DefSet.insert(Defs[i]);
-
- for (unsigned i = 0, e = RCs.size(); i != e; ++i) {
- const CodeGenRegisterClass &RC = RCs[i];
- unsigned NumRegs = RC.Elements.size();
- if (NumRegs > NumDefs)
- continue; // Can't possibly clobber this RC.
-
- bool Clobber = true;
- for (unsigned j = 0; j < NumRegs; ++j) {
- Record *Reg = RC.Elements[j];
- if (!DefSet.count(Reg)) {
- Clobber = false;
- break;
- }
- }
- if (Clobber)
- Barriers.push_back(RC.TheDef);
- }
-}
-
//===----------------------------------------------------------------------===//
// Main Output.
//===----------------------------------------------------------------------===//
// run - Emit the main instruction description records for the target...
void InstrInfoEmitter::run(raw_ostream &OS) {
+ emitEnums(OS);
+
GatherItinClasses();
EmitSourceFileHeader("Target Instruction Descriptors", OS);
+
+ OS << "\n#ifdef GET_INSTRINFO_MC_DESC\n";
+ OS << "#undef GET_INSTRINFO_MC_DESC\n";
+
OS << "namespace llvm {\n\n";
CodeGenTarget &Target = CDP.getTargetInfo();
const std::string &TargetName = Target.getName();
Record *InstrInfo = Target.getInstructionSet();
- const std::vector<CodeGenRegisterClass> &RCs = Target.getRegisterClasses();
// Keep track of all of the def lists we have emitted already.
std::map<std::vector<Record*>, unsigned> EmittedLists;
unsigned ListNumber = 0;
- std::map<std::vector<Record*>, unsigned> EmittedBarriers;
- unsigned BarrierNumber = 0;
- std::map<Record*, unsigned> BarriersMap;
-
+
// 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) {
@@ -217,79 +191,110 @@
}
std::vector<Record*> Defs = Inst->getValueAsListOfDefs("Defs");
if (!Defs.empty()) {
- std::vector<Record*> RCBarriers;
- DetectRegisterClassBarriers(Defs, RCs, RCBarriers);
- if (!RCBarriers.empty()) {
- unsigned &IB = EmittedBarriers[RCBarriers];
- if (!IB) PrintBarriers(RCBarriers, IB = ++BarrierNumber, OS);
- BarriersMap.insert(std::make_pair(Inst, IB));
- }
-
unsigned &IL = EmittedLists[Defs];
if (!IL) PrintDefList(Defs, IL = ++ListNumber, OS);
}
}
OperandInfoMapTy OperandInfoIDs;
-
+
// Emit all of the operand info records.
EmitOperandInfo(OS, OperandInfoIDs);
-
- // Emit all of the TargetInstrDesc records in their ENUM ordering.
+
+ // Emit all of the MCInstrDesc records in their ENUM ordering.
//
- OS << "\nstatic const TargetInstrDesc " << TargetName
- << "Insts[] = {\n";
+ OS << "\nMCInstrDesc " << TargetName << "Insts[] = {\n";
const std::vector<const CodeGenInstruction*> &NumberedInstructions =
Target.getInstructionsByEnumValue();
for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i)
emitRecord(*NumberedInstructions[i], i, InstrInfo, EmittedLists,
- BarriersMap, OperandInfoIDs, OS);
- OS << "};\n";
+ OperandInfoIDs, OS);
+ OS << "};\n\n";
+
+ // MCInstrInfo initialization routine.
+ OS << "static inline void Init" << TargetName
+ << "MCInstrInfo(MCInstrInfo *II) {\n";
+ OS << " II->InitMCInstrInfo(" << TargetName << "Insts, "
+ << NumberedInstructions.size() << ");\n}\n\n";
+
OS << "} // End llvm namespace \n";
+
+ OS << "#endif // GET_INSTRINFO_MC_DESC\n\n";
+
+ // Create a TargetInstrInfo subclass to hide the MC layer initialization.
+ OS << "\n#ifdef GET_INSTRINFO_HEADER\n";
+ OS << "#undef GET_INSTRINFO_HEADER\n";
+
+ std::string ClassName = TargetName + "GenInstrInfo";
+ OS << "namespace llvm {\n";
+ OS << "struct " << ClassName << " : public TargetInstrInfoImpl {\n"
+ << " explicit " << ClassName << "(int SO = -1, int DO = -1);\n"
+ << "};\n";
+ OS << "} // End llvm namespace \n";
+
+ OS << "#endif // GET_INSTRINFO_HEADER\n\n";
+
+ OS << "\n#ifdef GET_INSTRINFO_CTOR\n";
+ OS << "#undef GET_INSTRINFO_CTOR\n";
+
+ OS << "namespace llvm {\n";
+ OS << "extern MCInstrDesc " << TargetName << "Insts[];\n";
+ OS << ClassName << "::" << ClassName << "(int SO, int DO)\n"
+ << " : TargetInstrInfoImpl(SO, DO) {\n"
+ << " InitMCInstrInfo(" << TargetName << "Insts, "
+ << NumberedInstructions.size() << ");\n}\n";
+ OS << "} // End llvm namespace \n";
+
+ OS << "#endif // GET_INSTRINFO_CTOR\n\n";
}
void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
Record *InstrInfo,
std::map<std::vector<Record*>, unsigned> &EmittedLists,
- std::map<Record*, unsigned> &BarriersMap,
const OperandInfoMapTy &OpInfo,
raw_ostream &OS) {
int MinOperands = 0;
- if (!Inst.OperandList.empty())
+ if (!Inst.Operands.size() == 0)
// Each logical operand can be multiple MI operands.
- MinOperands = Inst.OperandList.back().MIOperandNo +
- Inst.OperandList.back().MINumOperands;
+ MinOperands = Inst.Operands.back().MIOperandNo +
+ Inst.Operands.back().MINumOperands;
OS << " { ";
OS << Num << ",\t" << MinOperands << ",\t"
- << Inst.NumDefs << ",\t" << getItinClassNumber(Inst.TheDef)
- << ",\t\"" << Inst.TheDef->getName() << "\", 0";
+ << Inst.Operands.NumDefs << ",\t"
+ << getItinClassNumber(Inst.TheDef) << ",\t"
+ << Inst.TheDef->getValueAsInt("Size") << ",\t\""
+ << Inst.TheDef->getName() << "\", 0";
// Emit all of the target indepedent flags...
- if (Inst.isReturn) OS << "|(1<<TID::Return)";
- if (Inst.isBranch) OS << "|(1<<TID::Branch)";
- if (Inst.isIndirectBranch) OS << "|(1<<TID::IndirectBranch)";
- if (Inst.isCompare) OS << "|(1<<TID::Compare)";
- if (Inst.isBarrier) OS << "|(1<<TID::Barrier)";
- if (Inst.hasDelaySlot) OS << "|(1<<TID::DelaySlot)";
- if (Inst.isCall) OS << "|(1<<TID::Call)";
- if (Inst.canFoldAsLoad) OS << "|(1<<TID::FoldableAsLoad)";
- if (Inst.mayLoad) OS << "|(1<<TID::MayLoad)";
- if (Inst.mayStore) OS << "|(1<<TID::MayStore)";
- if (Inst.isPredicable) OS << "|(1<<TID::Predicable)";
- if (Inst.isConvertibleToThreeAddress) OS << "|(1<<TID::ConvertibleTo3Addr)";
- if (Inst.isCommutable) OS << "|(1<<TID::Commutable)";
- if (Inst.isTerminator) OS << "|(1<<TID::Terminator)";
- if (Inst.isReMaterializable) OS << "|(1<<TID::Rematerializable)";
- if (Inst.isNotDuplicable) OS << "|(1<<TID::NotDuplicable)";
- if (Inst.hasOptionalDef) OS << "|(1<<TID::HasOptionalDef)";
- if (Inst.usesCustomInserter) OS << "|(1<<TID::UsesCustomInserter)";
- if (Inst.isVariadic) OS << "|(1<<TID::Variadic)";
- if (Inst.hasSideEffects) OS << "|(1<<TID::UnmodeledSideEffects)";
- if (Inst.isAsCheapAsAMove) OS << "|(1<<TID::CheapAsAMove)";
- if (Inst.hasExtraSrcRegAllocReq) OS << "|(1<<TID::ExtraSrcRegAllocReq)";
- if (Inst.hasExtraDefRegAllocReq) OS << "|(1<<TID::ExtraDefRegAllocReq)";
+ if (Inst.isPseudo) OS << "|(1<<MCID::Pseudo)";
+ if (Inst.isReturn) OS << "|(1<<MCID::Return)";
+ if (Inst.isBranch) OS << "|(1<<MCID::Branch)";
+ if (Inst.isIndirectBranch) OS << "|(1<<MCID::IndirectBranch)";
+ if (Inst.isCompare) OS << "|(1<<MCID::Compare)";
+ if (Inst.isMoveImm) OS << "|(1<<MCID::MoveImm)";
+ if (Inst.isBitcast) OS << "|(1<<MCID::Bitcast)";
+ if (Inst.isBarrier) OS << "|(1<<MCID::Barrier)";
+ if (Inst.hasDelaySlot) OS << "|(1<<MCID::DelaySlot)";
+ if (Inst.isCall) OS << "|(1<<MCID::Call)";
+ if (Inst.canFoldAsLoad) OS << "|(1<<MCID::FoldableAsLoad)";
+ if (Inst.mayLoad) OS << "|(1<<MCID::MayLoad)";
+ if (Inst.mayStore) OS << "|(1<<MCID::MayStore)";
+ if (Inst.isPredicable) OS << "|(1<<MCID::Predicable)";
+ if (Inst.isConvertibleToThreeAddress) OS << "|(1<<MCID::ConvertibleTo3Addr)";
+ if (Inst.isCommutable) OS << "|(1<<MCID::Commutable)";
+ if (Inst.isTerminator) OS << "|(1<<MCID::Terminator)";
+ if (Inst.isReMaterializable) OS << "|(1<<MCID::Rematerializable)";
+ if (Inst.isNotDuplicable) OS << "|(1<<MCID::NotDuplicable)";
+ if (Inst.Operands.hasOptionalDef) OS << "|(1<<MCID::HasOptionalDef)";
+ if (Inst.usesCustomInserter) OS << "|(1<<MCID::UsesCustomInserter)";
+ if (Inst.hasPostISelHook) OS << "|(1<<MCID::HasPostISelHook)";
+ if (Inst.Operands.isVariadic)OS << "|(1<<MCID::Variadic)";
+ if (Inst.hasSideEffects) OS << "|(1<<MCID::UnmodeledSideEffects)";
+ if (Inst.isAsCheapAsAMove) OS << "|(1<<MCID::CheapAsAMove)";
+ if (Inst.hasExtraSrcRegAllocReq) OS << "|(1<<MCID::ExtraSrcRegAllocReq)";
+ if (Inst.hasExtraDefRegAllocReq) OS << "|(1<<MCID::ExtraDefRegAllocReq)";
// Emit all of the target-specific flags...
BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags");
@@ -318,12 +323,6 @@
else
OS << "ImplicitList" << EmittedLists[DefList] << ", ";
- std::map<Record*, unsigned>::iterator BI = BarriersMap.find(Inst.TheDef);
- if (BI == BarriersMap.end())
- OS << "NULL, ";
- else
- OS << "Barriers" << BI->second << ", ";
-
// Emit the operand info.
std::vector<std::string> OperandInfo = GetOperandInfo(Inst);
if (OperandInfo.empty())
@@ -333,3 +332,38 @@
OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";
}
+
+// emitEnums - Print out enum values for all of the instructions.
+void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
+ EmitSourceFileHeader("Target Instruction Enum Values", OS);
+
+ OS << "\n#ifdef GET_INSTRINFO_ENUM\n";
+ OS << "#undef GET_INSTRINFO_ENUM\n";
+
+ OS << "namespace llvm {\n\n";
+
+ CodeGenTarget Target(Records);
+
+ // We must emit the PHI opcode first...
+ std::string Namespace = Target.getInstNamespace();
+
+ if (Namespace.empty()) {
+ fprintf(stderr, "No instructions defined!\n");
+ exit(1);
+ }
+
+ const std::vector<const CodeGenInstruction*> &NumberedInstructions =
+ Target.getInstructionsByEnumValue();
+
+ 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";
+ }
+ OS << " INSTRUCTION_LIST_END = " << NumberedInstructions.size() << "\n";
+ OS << " };\n}\n";
+ OS << "} // End llvm namespace \n";
+
+ OS << "#endif // GET_INSTRINFO_ENUM\n\n";
+}
diff --git a/src/LLVM/utils/TableGen/InstrInfoEmitter.h b/src/LLVM/utils/TableGen/InstrInfoEmitter.h
index abb1c6b..1461e2c 100644
--- a/src/LLVM/utils/TableGen/InstrInfoEmitter.h
+++ b/src/LLVM/utils/TableGen/InstrInfoEmitter.h
@@ -15,8 +15,8 @@
#ifndef INSTRINFO_EMITTER_H
#define INSTRINFO_EMITTER_H
-#include "TableGenBackend.h"
#include "CodeGenDAGPatterns.h"
+#include "llvm/TableGen/TableGenBackend.h"
#include <vector>
#include <map>
@@ -39,12 +39,12 @@
void run(raw_ostream &OS);
private:
- typedef std::map<std::vector<std::string>, unsigned> OperandInfoMapTy;
-
+ void emitEnums(raw_ostream &OS);
+
+ typedef std::map<std::vector<std::string>, unsigned> OperandInfoMapTy;
void emitRecord(const CodeGenInstruction &Inst, unsigned Num,
Record *InstrInfo,
std::map<std::vector<Record*>, unsigned> &EL,
- std::map<Record*, unsigned> &BM,
const OperandInfoMapTy &OpInfo,
raw_ostream &OS);
@@ -55,10 +55,6 @@
// Operand information.
void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs);
std::vector<std::string> GetOperandInfo(const CodeGenInstruction &Inst);
-
- void DetectRegisterClassBarriers(std::vector<Record*> &Defs,
- const std::vector<CodeGenRegisterClass> &RCs,
- std::vector<Record*> &Barriers);
};
} // End llvm namespace
diff --git a/src/LLVM/utils/TableGen/IntrinsicEmitter.cpp b/src/LLVM/utils/TableGen/IntrinsicEmitter.cpp
index ba30d97..782b89e 100644
--- a/src/LLVM/utils/TableGen/IntrinsicEmitter.cpp
+++ b/src/LLVM/utils/TableGen/IntrinsicEmitter.cpp
@@ -13,7 +13,8 @@
#include "CodeGenTarget.h"
#include "IntrinsicEmitter.h"
-#include "Record.h"
+#include "StringMatcher.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include <algorithm>
using namespace llvm;
@@ -67,16 +68,19 @@
void IntrinsicEmitter::EmitPrefix(raw_ostream &OS) {
OS << "// VisualStudio defines setjmp as _setjmp\n"
- "#if defined(_MSC_VER) && defined(setjmp)\n"
- "#define setjmp_undefined_for_visual_studio\n"
- "#undef setjmp\n"
+ "#if defined(_MSC_VER) && defined(setjmp) && \\\n"
+ " !defined(setjmp_undefined_for_msvc)\n"
+ "# pragma push_macro(\"setjmp\")\n"
+ "# undef setjmp\n"
+ "# define setjmp_undefined_for_msvc\n"
"#endif\n\n";
}
void IntrinsicEmitter::EmitSuffix(raw_ostream &OS) {
- OS << "#if defined(_MSC_VER) && defined(setjmp_undefined_for_visual_studio)\n"
+ OS << "#if defined(_MSC_VER) && defined(setjmp_undefined_for_msvc)\n"
"// let's return it to _setjmp state\n"
- "#define setjmp _setjmp\n"
+ "# pragma pop_macro(\"setjmp\")\n"
+ "# undef setjmp_undefined_for_msvc\n"
"#endif\n\n";
}
@@ -96,37 +100,48 @@
void IntrinsicEmitter::
EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
raw_ostream &OS) {
- // Build a function name -> intrinsic name mapping.
- std::map<std::string, unsigned> IntMapping;
+ // Build a 'first character of function name' -> intrinsic # mapping.
+ std::map<char, std::vector<unsigned> > IntMapping;
for (unsigned i = 0, e = Ints.size(); i != e; ++i)
- IntMapping[Ints[i].Name] = i;
-
+ IntMapping[Ints[i].Name[5]].push_back(i);
+
OS << "// Function name -> enum value recognizer code.\n";
OS << "#ifdef GET_FUNCTION_RECOGNIZER\n";
- OS << " switch (Name[5]) {\n";
- OS << " default:\n";
- // Emit the intrinsics in sorted order.
- char LastChar = 0;
- for (std::map<std::string, unsigned>::iterator I = IntMapping.begin(),
+ OS << " StringRef NameR(Name+6, Len-6); // Skip over 'llvm.'\n";
+ OS << " switch (Name[5]) { // Dispatch on first letter.\n";
+ OS << " default: break;\n";
+ // 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) {
- if (I->first[5] != LastChar) {
- LastChar = I->first[5];
- OS << " break;\n";
- OS << " case '" << LastChar << "':\n";
+ OS << " case '" << I->first << "':\n";
+ std::vector<unsigned> &IntList = I->second;
+
+ // Emit all the overloaded intrinsics first, build a table of the
+ // non-overloaded ones.
+ std::vector<StringMatcher::StringPair> MatchTable;
+
+ for (unsigned i = 0, e = IntList.size(); i != e; ++i) {
+ unsigned IntNo = IntList[i];
+ std::string Result = "return " + TargetPrefix + "Intrinsic::" +
+ Ints[IntNo].EnumName + ";";
+
+ if (!Ints[IntNo].isOverloaded) {
+ MatchTable.push_back(std::make_pair(Ints[IntNo].Name.substr(6),Result));
+ continue;
+ }
+
+ // For overloaded intrinsics, only the prefix needs to match
+ std::string TheStr = Ints[IntNo].Name.substr(6);
+ TheStr += '.'; // Require "bswap." instead of bswap.
+ OS << " if (NameR.startswith(\"" << TheStr << "\")) "
+ << Result << '\n';
}
- // For overloaded intrinsics, only the prefix needs to match
- if (Ints[I->second].isOverloaded)
- OS << " if (Len > " << I->first.size()
- << " && !memcmp(Name, \"" << I->first << ".\", "
- << (I->first.size() + 1) << ")) return " << TargetPrefix << "Intrinsic::"
- << Ints[I->second].EnumName << ";\n";
- else
- OS << " if (Len == " << I->first.size()
- << " && !memcmp(Name, \"" << I->first << "\", "
- << I->first.size() << ")) return " << TargetPrefix << "Intrinsic::"
- << Ints[I->second].EnumName << ";\n";
+ // Emit the matcher logic for the fixed length strings.
+ StringMatcher("NameR", MatchTable, OS).Emit(1);
+ OS << " break; // end of '" << I->first << "' case.\n";
}
+
OS << " }\n";
OS << "#endif\n\n";
}
@@ -180,6 +195,8 @@
OS << "Type::getVoidTy(Context)";
} else if (VT == MVT::Metadata) {
OS << "Type::getMetadataTy(Context)";
+ } else if (VT == MVT::x86mmx) {
+ OS << "Type::getX86_MMXTy(Context)";
} else {
assert(false && "Unsupported ValueType!");
}
@@ -197,7 +214,7 @@
if (ArgTypes.size() == 1)
return EmitTypeGenerate(OS, ArgTypes.front(), ArgNo);
- OS << "StructType::get(Context, ";
+ OS << "StructType::get(";
for (std::vector<Record*>::const_iterator
I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I) {
@@ -242,7 +259,7 @@
} else if (VT == MVT::iPTRAny) {
// Make sure the user has passed us an argument type to overload. If not,
// treat it as an ordinary (not overloaded) intrinsic.
- OS << "(" << ArgNo << " < numTys) ? Tys[" << ArgNo
+ OS << "(" << ArgNo << " < Tys.size()) ? Tys[" << ArgNo
<< "] : PointerType::getUnqual(";
EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
OS << ")";
@@ -448,6 +465,46 @@
OS << "#endif\n\n";
}
+namespace {
+ enum ModRefKind {
+ MRK_none,
+ MRK_readonly,
+ MRK_readnone
+ };
+
+ ModRefKind getModRefKind(const CodeGenIntrinsic &intrinsic) {
+ switch (intrinsic.ModRef) {
+ case CodeGenIntrinsic::NoMem:
+ return MRK_readnone;
+ case CodeGenIntrinsic::ReadArgMem:
+ case CodeGenIntrinsic::ReadMem:
+ return MRK_readonly;
+ case CodeGenIntrinsic::ReadWriteArgMem:
+ case CodeGenIntrinsic::ReadWriteMem:
+ return MRK_none;
+ }
+ assert(0 && "bad mod-ref kind");
+ return MRK_none;
+ }
+
+ struct AttributeComparator {
+ bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const {
+ // Sort throwing intrinsics after non-throwing intrinsics.
+ if (L->canThrow != R->canThrow)
+ return R->canThrow;
+
+ // Try to order by readonly/readnone attribute.
+ ModRefKind LK = getModRefKind(*L);
+ ModRefKind RK = getModRefKind(*R);
+ if (LK != RK) return (LK > RK);
+
+ // Order by argument attributes.
+ // This is reliable because each side is already sorted internally.
+ return (L->ArgumentAttributes < R->ArgumentAttributes);
+ }
+ };
+}
+
/// EmitAttributes - This emits the Intrinsic::getAttributes method.
void IntrinsicEmitter::
EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
@@ -455,84 +512,96 @@
OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n";
if (TargetOnly)
OS << "static AttrListPtr getAttributes(" << TargetPrefix
- << "Intrinsic::ID id) {";
+ << "Intrinsic::ID id) {\n";
else
- OS << "AttrListPtr Intrinsic::getAttributes(ID id) {";
- OS << " // No intrinsic can throw exceptions.\n";
- OS << " Attributes Attr = Attribute::NoUnwind;\n";
- OS << " switch (id) {\n";
- OS << " default: break;\n";
- unsigned MaxArgAttrs = 0;
+ OS << "AttrListPtr Intrinsic::getAttributes(ID id) {\n";
+
+ // Compute the maximum number of attribute arguments.
+ std::vector<const CodeGenIntrinsic*> sortedIntrinsics(Ints.size());
+ unsigned maxArgAttrs = 0;
for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
- MaxArgAttrs =
- std::max(MaxArgAttrs, unsigned(Ints[i].ArgumentAttributes.size()));
- switch (Ints[i].ModRef) {
- default: break;
- case CodeGenIntrinsic::NoMem:
- OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
- << ":\n";
- break;
- }
+ const CodeGenIntrinsic &intrinsic = Ints[i];
+ sortedIntrinsics[i] = &intrinsic;
+ maxArgAttrs =
+ std::max(maxArgAttrs, unsigned(intrinsic.ArgumentAttributes.size()));
}
- OS << " Attr |= Attribute::ReadNone; // These do not access memory.\n";
- OS << " break;\n";
- for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
- switch (Ints[i].ModRef) {
- default: break;
- case CodeGenIntrinsic::ReadArgMem:
- case CodeGenIntrinsic::ReadMem:
- OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
- << ":\n";
- break;
- }
- }
- OS << " Attr |= Attribute::ReadOnly; // These do not write memory.\n";
- OS << " break;\n";
- OS << " }\n";
- OS << " AttributeWithIndex AWI[" << MaxArgAttrs+1 << "];\n";
+
+ // Emit an array of AttributeWithIndex. Most intrinsics will have
+ // at least one entry, for the function itself (index ~1), which is
+ // usually nounwind.
+ OS << " AttributeWithIndex AWI[" << maxArgAttrs+1 << "];\n";
OS << " unsigned NumAttrs = 0;\n";
OS << " switch (id) {\n";
- OS << " default: break;\n";
-
- // Add argument attributes for any intrinsics that have them.
- for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
- if (Ints[i].ArgumentAttributes.empty()) continue;
-
- OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
- << ":\n";
+ OS << " default: break;\n";
- std::vector<std::pair<unsigned, CodeGenIntrinsic::ArgAttribute> > ArgAttrs =
- Ints[i].ArgumentAttributes;
- // Sort by argument index.
- std::sort(ArgAttrs.begin(), ArgAttrs.end());
+ AttributeComparator precedes;
- unsigned NumArgsWithAttrs = 0;
+ std::stable_sort(sortedIntrinsics.begin(), sortedIntrinsics.end(), precedes);
- while (!ArgAttrs.empty()) {
- unsigned ArgNo = ArgAttrs[0].first;
+ for (unsigned i = 0, e = sortedIntrinsics.size(); i != e; ++i) {
+ const CodeGenIntrinsic &intrinsic = *sortedIntrinsics[i];
+ OS << " case " << TargetPrefix << "Intrinsic::"
+ << intrinsic.EnumName << ":\n";
+
+ // Fill out the case if this is the last case for this range of
+ // intrinsics.
+ if (i + 1 != e && !precedes(&intrinsic, sortedIntrinsics[i + 1]))
+ continue;
+
+ // Keep track of the number of attributes we're writing out.
+ unsigned numAttrs = 0;
+
+ // The argument attributes are alreadys sorted by argument index.
+ for (unsigned ai = 0, ae = intrinsic.ArgumentAttributes.size(); ai != ae;) {
+ unsigned argNo = intrinsic.ArgumentAttributes[ai].first;
- OS << " AWI[" << NumArgsWithAttrs++ << "] = AttributeWithIndex::get("
- << ArgNo+1 << ", 0";
+ OS << " AWI[" << numAttrs++ << "] = AttributeWithIndex::get("
+ << argNo+1 << ", ";
- while (!ArgAttrs.empty() && ArgAttrs[0].first == ArgNo) {
- switch (ArgAttrs[0].second) {
- default: assert(0 && "Unknown arg attribute");
+ bool moreThanOne = false;
+
+ do {
+ if (moreThanOne) OS << '|';
+
+ switch (intrinsic.ArgumentAttributes[ai].second) {
case CodeGenIntrinsic::NoCapture:
- OS << "|Attribute::NoCapture";
+ OS << "Attribute::NoCapture";
break;
}
- ArgAttrs.erase(ArgAttrs.begin());
+
+ ++ai;
+ moreThanOne = true;
+ } while (ai != ae && intrinsic.ArgumentAttributes[ai].first == argNo);
+
+ OS << ");\n";
+ }
+
+ ModRefKind modRef = getModRefKind(intrinsic);
+
+ if (!intrinsic.canThrow || modRef) {
+ OS << " AWI[" << numAttrs++ << "] = AttributeWithIndex::get(~0, ";
+ if (!intrinsic.canThrow) {
+ OS << "Attribute::NoUnwind";
+ if (modRef) OS << '|';
+ }
+ switch (modRef) {
+ case MRK_none: break;
+ case MRK_readonly: OS << "Attribute::ReadOnly"; break;
+ case MRK_readnone: OS << "Attribute::ReadNone"; break;
}
OS << ");\n";
}
-
- OS << " NumAttrs = " << NumArgsWithAttrs << ";\n";
- OS << " break;\n";
+
+ if (numAttrs) {
+ OS << " NumAttrs = " << numAttrs << ";\n";
+ OS << " break;\n";
+ } else {
+ OS << " return AttrListPtr();\n";
+ }
}
OS << " }\n";
- OS << " AWI[NumAttrs] = AttributeWithIndex::get(~0, Attr);\n";
- OS << " return AttrListPtr::get(AWI, NumAttrs+1);\n";
+ OS << " return AttrListPtr::get(AWI, NumAttrs);\n";
OS << "}\n";
OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n";
}
@@ -556,11 +625,13 @@
OS << " return DoesNotAccessMemory;\n";
break;
case CodeGenIntrinsic::ReadArgMem:
+ OS << " return OnlyReadsArgumentPointees;\n";
+ break;
case CodeGenIntrinsic::ReadMem:
OS << " return OnlyReadsMemory;\n";
break;
case CodeGenIntrinsic::ReadWriteArgMem:
- OS << " return AccessesArguments;\n";
+ OS << " return OnlyAccessesArgumentPointees;\n";
break;
}
}
@@ -584,112 +655,22 @@
OS << "#endif\n\n";
}
-/// EmitBuiltinComparisons - Emit comparisons to determine whether the specified
-/// sorted range of builtin names is equal to the current builtin. This breaks
-/// it down into a simple tree.
-///
-/// At this point, we know that all the builtins in the range have the same name
-/// for the first 'CharStart' characters. Only the end of the name needs to be
-/// discriminated.
-typedef std::map<std::string, std::string>::const_iterator StrMapIterator;
-static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End,
- unsigned CharStart, unsigned Indent,
- std::string TargetPrefix, raw_ostream &OS) {
- if (Start == End) return; // empty range.
-
- // Determine what, if anything, is the same about all these strings.
- std::string CommonString = Start->first;
- unsigned NumInRange = 0;
- for (StrMapIterator I = Start; I != End; ++I, ++NumInRange) {
- // Find the first character that doesn't match.
- const std::string &ThisStr = I->first;
- unsigned NonMatchChar = CharStart;
- while (NonMatchChar < CommonString.size() &&
- NonMatchChar < ThisStr.size() &&
- CommonString[NonMatchChar] == ThisStr[NonMatchChar])
- ++NonMatchChar;
- // Truncate off pieces that don't match.
- CommonString.resize(NonMatchChar);
- }
-
- // Just compare the rest of the string.
- if (NumInRange == 1) {
- if (CharStart != CommonString.size()) {
- OS << std::string(Indent*2, ' ') << "if (!memcmp(BuiltinName";
- if (CharStart) OS << "+" << CharStart;
- OS << ", \"" << (CommonString.c_str()+CharStart) << "\", ";
- OS << CommonString.size() - CharStart << "))\n";
- ++Indent;
- }
- OS << std::string(Indent*2, ' ') << "IntrinsicID = " << TargetPrefix
- << "Intrinsic::";
- OS << Start->second << ";\n";
- return;
- }
-
- // At this point, we potentially have a common prefix for these builtins, emit
- // a check for this common prefix.
- if (CommonString.size() != CharStart) {
- OS << std::string(Indent*2, ' ') << "if (!memcmp(BuiltinName";
- if (CharStart) OS << "+" << CharStart;
- OS << ", \"" << (CommonString.c_str()+CharStart) << "\", ";
- OS << CommonString.size()-CharStart << ")) {\n";
-
- EmitBuiltinComparisons(Start, End, CommonString.size(), Indent+1,
- TargetPrefix, OS);
- OS << std::string(Indent*2, ' ') << "}\n";
- return;
- }
-
- // Output a switch on the character that differs across the set.
- OS << std::string(Indent*2, ' ') << "switch (BuiltinName[" << CharStart
- << "]) {";
- if (CharStart)
- OS << " // \"" << std::string(Start->first.begin(),
- Start->first.begin()+CharStart) << "\"";
- OS << "\n";
-
- for (StrMapIterator I = Start; I != End; ) {
- char ThisChar = I->first[CharStart];
- OS << std::string(Indent*2, ' ') << "case '" << ThisChar << "':\n";
- // Figure out the range that has this common character.
- StrMapIterator NextChar = I;
- for (++NextChar; NextChar != End && NextChar->first[CharStart] == ThisChar;
- ++NextChar)
- /*empty*/;
- EmitBuiltinComparisons(I, NextChar, CharStart+1, Indent+1, TargetPrefix,OS);
- OS << std::string(Indent*2, ' ') << " break;\n";
- I = NextChar;
- }
- OS << std::string(Indent*2, ' ') << "}\n";
-}
-
/// EmitTargetBuiltins - All of the builtins in the specified map are for the
/// same target, and we already checked it.
static void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM,
const std::string &TargetPrefix,
raw_ostream &OS) {
- // Rearrange the builtins by length.
- std::vector<std::map<std::string, std::string> > BuiltinsByLen;
- BuiltinsByLen.reserve(100);
- for (StrMapIterator I = BIM.begin(), E = BIM.end(); I != E; ++I) {
- if (I->first.size() >= BuiltinsByLen.size())
- BuiltinsByLen.resize(I->first.size()+1);
- BuiltinsByLen[I->first.size()].insert(*I);
- }
+ std::vector<StringMatcher::StringPair> Results;
- // Now that we have all the builtins by their length, emit a switch stmt.
- OS << " switch (strlen(BuiltinName)) {\n";
- OS << " default: break;\n";
- for (unsigned i = 0, e = BuiltinsByLen.size(); i != e; ++i) {
- if (BuiltinsByLen[i].empty()) continue;
- OS << " case " << i << ":\n";
- EmitBuiltinComparisons(BuiltinsByLen[i].begin(), BuiltinsByLen[i].end(),
- 0, 3, TargetPrefix, OS);
- OS << " break;\n";
+ for (std::map<std::string, std::string>::const_iterator I = BIM.begin(),
+ E = BIM.end(); I != E; ++I) {
+ std::string ResultCode =
+ "return " + TargetPrefix + "Intrinsic::" + I->second + ";";
+ Results.push_back(StringMatcher::StringPair(I->first, ResultCode));
}
- OS << " }\n";
+
+ StringMatcher("BuiltinName", Results, OS).Emit();
}
@@ -719,24 +700,20 @@
if (TargetOnly) {
OS << "static " << TargetPrefix << "Intrinsic::ID "
<< "getIntrinsicForGCCBuiltin(const char "
- << "*TargetPrefix, const char *BuiltinName) {\n";
- OS << " " << TargetPrefix << "Intrinsic::ID IntrinsicID = ";
+ << "*TargetPrefixStr, const char *BuiltinNameStr) {\n";
} else {
OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char "
- << "*TargetPrefix, const char *BuiltinName) {\n";
- OS << " Intrinsic::ID IntrinsicID = ";
+ << "*TargetPrefixStr, const char *BuiltinNameStr) {\n";
}
- if (TargetOnly)
- OS << "(" << TargetPrefix<< "Intrinsic::ID)";
-
- OS << "Intrinsic::not_intrinsic;\n";
+ OS << " StringRef BuiltinName(BuiltinNameStr);\n";
+ OS << " StringRef TargetPrefix(TargetPrefixStr);\n\n";
// Note: this could emit significantly better code if we cared.
for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){
OS << " ";
if (!I->first.empty())
- OS << "if (!strcmp(TargetPrefix, \"" << I->first << "\")) ";
+ OS << "if (TargetPrefix == \"" << I->first << "\") ";
else
OS << "/* Target Independent Builtins */ ";
OS << "{\n";
@@ -745,7 +722,10 @@
EmitTargetBuiltins(I->second, TargetPrefix, OS);
OS << " }\n";
}
- OS << " return IntrinsicID;\n";
+ OS << " return ";
+ if (!TargetPrefix.empty())
+ OS << "(" << TargetPrefix << "Intrinsic::ID)";
+ OS << "Intrinsic::not_intrinsic;\n";
OS << "}\n";
OS << "#endif\n\n";
}
diff --git a/src/LLVM/utils/TableGen/IntrinsicEmitter.h b/src/LLVM/utils/TableGen/IntrinsicEmitter.h
index b1efecb..eb6379c 100644
--- a/src/LLVM/utils/TableGen/IntrinsicEmitter.h
+++ b/src/LLVM/utils/TableGen/IntrinsicEmitter.h
@@ -15,7 +15,7 @@
#define INTRINSIC_EMITTER_H
#include "CodeGenIntrinsics.h"
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
namespace llvm {
class IntrinsicEmitter : public TableGenBackend {
diff --git a/src/LLVM/utils/TableGen/Makefile b/src/LLVM/utils/TableGen/Makefile
index f27cd99..0c4619d 100644
--- a/src/LLVM/utils/TableGen/Makefile
+++ b/src/LLVM/utils/TableGen/Makefile
@@ -8,8 +8,8 @@
##===----------------------------------------------------------------------===##
LEVEL = ../..
-TOOLNAME = tblgen
-USEDLIBS = LLVMSupport.a LLVMSystem.a
+TOOLNAME = llvm-tblgen
+USEDLIBS = LLVMTableGen.a LLVMSupport.a
REQUIRES_EH := 1
REQUIRES_RTTI := 1
diff --git a/src/LLVM/utils/TableGen/PACKAGE.vcxproj b/src/LLVM/utils/TableGen/PACKAGE.vcxproj
new file mode 100644
index 0000000..74af67e
--- /dev/null
+++ b/src/LLVM/utils/TableGen/PACKAGE.vcxproj
@@ -0,0 +1,277 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGUID>{1B050569-3318-48D9-8BB0-4DE9EF58B202}</ProjectGUID>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>PACKAGE</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\PACKAGE_force.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\generate.stamp</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\ALL_BUILD.vcxproj">
+ <Project>17AECBCF-B2AE-4524-9010-9A175A8F6BFE</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/src/LLVM/utils/TableGen/PACKAGE.vcxproj.filters b/src/LLVM/utils/TableGen/PACKAGE.vcxproj.filters
new file mode 100644
index 0000000..a570359
--- /dev/null
+++ b/src/LLVM/utils/TableGen/PACKAGE.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\PACKAGE_force.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ <CustomBuild Include="CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{71794486-B3CB-4A48-93CC-DE95557E96E1}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
diff --git a/src/LLVM/utils/TableGen/PseudoLoweringEmitter.cpp b/src/LLVM/utils/TableGen/PseudoLoweringEmitter.cpp
new file mode 100644
index 0000000..c685527
--- /dev/null
+++ b/src/LLVM/utils/TableGen/PseudoLoweringEmitter.cpp
@@ -0,0 +1,243 @@
+//===- PseudoLoweringEmitter.cpp - PseudoLowering Generator -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "pseudo-lowering"
+#include "CodeGenInstruction.h"
+#include "PseudoLoweringEmitter.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/ADT/IndexedMap.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Debug.h"
+#include <vector>
+using namespace llvm;
+
+// FIXME: This pass currently can only expand a pseudo to a single instruction.
+// The pseudo expansion really should take a list of dags, not just
+// a single dag, so we can do fancier things.
+
+unsigned PseudoLoweringEmitter::
+addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Insn,
+ IndexedMap<OpData> &OperandMap, unsigned BaseIdx) {
+ unsigned OpsAdded = 0;
+ for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
+ if (DefInit *DI = dynamic_cast<DefInit*>(Dag->getArg(i))) {
+ // Physical register reference. Explicit check for the special case
+ // "zero_reg" definition.
+ if (DI->getDef()->isSubClassOf("Register") ||
+ DI->getDef()->getName() == "zero_reg") {
+ OperandMap[BaseIdx + i].Kind = OpData::Reg;
+ OperandMap[BaseIdx + i].Data.Reg = DI->getDef();
+ ++OpsAdded;
+ continue;
+ }
+
+ // Normal operands should always have the same type, or we have a
+ // problem.
+ // FIXME: We probably shouldn't ever get a non-zero BaseIdx here.
+ assert(BaseIdx == 0 && "Named subargument in pseudo expansion?!");
+ if (DI->getDef() != Insn.Operands[BaseIdx + i].Rec)
+ throw TGError(Rec->getLoc(),
+ "Pseudo operand type '" + DI->getDef()->getName() +
+ "' does not match expansion operand type '" +
+ Insn.Operands[BaseIdx + i].Rec->getName() + "'");
+ // Source operand maps to destination operand. The Data element
+ // will be filled in later, just set the Kind for now. Do it
+ // for each corresponding MachineInstr operand, not just the first.
+ for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I)
+ OperandMap[BaseIdx + i + I].Kind = OpData::Operand;
+ OpsAdded += Insn.Operands[i].MINumOperands;
+ } else if (IntInit *II = dynamic_cast<IntInit*>(Dag->getArg(i))) {
+ OperandMap[BaseIdx + i].Kind = OpData::Imm;
+ OperandMap[BaseIdx + i].Data.Imm = II->getValue();
+ ++OpsAdded;
+ } else if (DagInit *SubDag = dynamic_cast<DagInit*>(Dag->getArg(i))) {
+ // Just add the operands recursively. This is almost certainly
+ // a constant value for a complex operand (> 1 MI operand).
+ unsigned NewOps =
+ addDagOperandMapping(Rec, SubDag, Insn, OperandMap, BaseIdx + i);
+ OpsAdded += NewOps;
+ // Since we added more than one, we also need to adjust the base.
+ BaseIdx += NewOps - 1;
+ } else
+ assert(0 && "Unhandled pseudo-expansion argument type!");
+ }
+ return OpsAdded;
+}
+
+void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) {
+ DEBUG(dbgs() << "Pseudo definition: " << Rec->getName() << "\n");
+
+ // Validate that the result pattern has the corrent number and types
+ // of arguments for the instruction it references.
+ DagInit *Dag = Rec->getValueAsDag("ResultInst");
+ assert(Dag && "Missing result instruction in pseudo expansion!");
+ DEBUG(dbgs() << " Result: " << *Dag << "\n");
+
+ DefInit *OpDef = dynamic_cast<DefInit*>(Dag->getOperator());
+ if (!OpDef)
+ throw TGError(Rec->getLoc(), Rec->getName() +
+ " has unexpected operator type!");
+ Record *Operator = OpDef->getDef();
+ if (!Operator->isSubClassOf("Instruction"))
+ throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
+ "' is not an instruction!");
+
+ CodeGenInstruction Insn(Operator);
+
+ if (Insn.isCodeGenOnly || Insn.isPseudo)
+ throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
+ "' cannot be another pseudo instruction!");
+
+ if (Insn.Operands.size() != Dag->getNumArgs())
+ throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
+ "' operand count mismatch");
+
+ IndexedMap<OpData> OperandMap;
+ OperandMap.grow(Insn.Operands.size());
+
+ addDagOperandMapping(Rec, Dag, Insn, OperandMap, 0);
+
+ // 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,
+ // PredicateOperand and OptionalDefOperand both 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.
+ // Also check that the type of the arguments match.
+ //
+ // Record the mapping of the source to result arguments for use by
+ // the lowering emitter.
+ CodeGenInstruction SourceInsn(Rec);
+ StringMap<unsigned> SourceOperands;
+ for (unsigned i = 0, e = SourceInsn.Operands.size(); i != e; ++i)
+ SourceOperands[SourceInsn.Operands[i].Name] = i;
+
+ DEBUG(dbgs() << " Operand mapping:\n");
+ for (unsigned i = 0, e = Insn.Operands.size(); i != e; ++i) {
+ // We've already handled constant values. Just map instruction operands
+ // here.
+ if (OperandMap[Insn.Operands[i].MIOperandNo].Kind != OpData::Operand)
+ continue;
+ StringMap<unsigned>::iterator SourceOp =
+ SourceOperands.find(Dag->getArgName(i));
+ if (SourceOp == SourceOperands.end())
+ throw TGError(Rec->getLoc(),
+ "Pseudo output operand '" + Dag->getArgName(i) +
+ "' has no matching source operand.");
+ // Map the source operand to the destination operand index for each
+ // MachineInstr operand.
+ for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I)
+ OperandMap[Insn.Operands[i].MIOperandNo + I].Data.Operand =
+ SourceOp->getValue();
+
+ DEBUG(dbgs() << " " << SourceOp->getValue() << " ==> " << i << "\n");
+ }
+
+ Expansions.push_back(PseudoExpansion(SourceInsn, Insn, OperandMap));
+}
+
+void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) {
+ // Emit file header.
+ EmitSourceFileHeader("Pseudo-instruction MC lowering Source Fragment", 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) {
+ default:
+ llvm_unreachable("Unknown operand type?!");
+ 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 += Dest.Operands[OpNo].MINumOperands;
+ }
+ if (Dest.Operands.isVariadic) {
+ 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 << " OutStreamer.EmitInstruction(TmpInst);\n"
+ << " break;\n"
+ << " }\n";
+ }
+ o << " }\n return true;\n}\n\n";
+}
+
+void PseudoLoweringEmitter::run(raw_ostream &o) {
+ Record *ExpansionClass = Records.getClass("PseudoInstExpansion");
+ Record *InstructionClass = Records.getClass("PseudoInstExpansion");
+ assert(ExpansionClass && "PseudoInstExpansion class definition missing!");
+ assert(InstructionClass && "Instruction class definition missing!");
+
+ std::vector<Record*> Insts;
+ for (std::map<std::string, Record*>::const_iterator I =
+ Records.getDefs().begin(), E = Records.getDefs().end(); I != E; ++I) {
+ if (I->second->isSubClassOf(ExpansionClass) &&
+ I->second->isSubClassOf(InstructionClass))
+ Insts.push_back(I->second);
+ }
+
+ // Process the pseudo expansion definitions, validating them as we do so.
+ for (unsigned i = 0, e = Insts.size(); i != e; ++i)
+ evaluateExpansion(Insts[i]);
+
+ // Generate expansion code to lower the pseudo to an MCInst of the real
+ // instruction.
+ emitLoweringEmitter(o);
+}
+
diff --git a/src/LLVM/utils/TableGen/PseudoLoweringEmitter.h b/src/LLVM/utils/TableGen/PseudoLoweringEmitter.h
new file mode 100644
index 0000000..325bc8b
--- /dev/null
+++ b/src/LLVM/utils/TableGen/PseudoLoweringEmitter.h
@@ -0,0 +1,65 @@
+//===- PseudoLoweringEmitter.h - PseudoLowering Generator -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PSEUDOLOWERINGEMITTER_H
+#define PSEUDOLOWERINGEMITTER_H
+
+#include "CodeGenInstruction.h"
+#include "CodeGenTarget.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include "llvm/ADT/IndexedMap.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm {
+
+class PseudoLoweringEmitter : public TableGenBackend {
+ struct OpData {
+ enum MapKind { Operand, Imm, Reg };
+ MapKind Kind;
+ union {
+ unsigned Operand; // Operand number mapped to.
+ uint64_t Imm; // Integer immedate value.
+ Record *Reg; // Physical register.
+ } Data;
+ };
+ struct PseudoExpansion {
+ CodeGenInstruction Source; // The source pseudo instruction definition.
+ CodeGenInstruction Dest; // The destination instruction to lower to.
+ IndexedMap<OpData> OperandMap;
+
+ PseudoExpansion(CodeGenInstruction &s, CodeGenInstruction &d,
+ IndexedMap<OpData> &m) :
+ Source(s), Dest(d), OperandMap(m) {}
+ };
+
+ RecordKeeper &Records;
+
+ // It's overkill to have an instance of the full CodeGenTarget object,
+ // but it loads everything on demand, not in the constructor, so it's
+ // lightweight in performance, so it works out OK.
+ CodeGenTarget Target;
+
+ SmallVector<PseudoExpansion, 64> Expansions;
+
+ unsigned addDagOperandMapping(Record *Rec, DagInit *Dag,
+ CodeGenInstruction &Insn,
+ IndexedMap<OpData> &OperandMap,
+ unsigned BaseIdx);
+ void evaluateExpansion(Record *Pseudo);
+ void emitLoweringEmitter(raw_ostream &o);
+public:
+ PseudoLoweringEmitter(RecordKeeper &R) : Records(R), Target(R) {}
+
+ /// run - Output the pseudo-lowerings.
+ void run(raw_ostream &o);
+};
+
+} // end llvm namespace
+
+#endif
diff --git a/src/LLVM/utils/TableGen/RegisterInfoEmitter.cpp b/src/LLVM/utils/TableGen/RegisterInfoEmitter.cpp
index a3ca0bc..b0f4ffc 100644
--- a/src/LLVM/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/src/LLVM/utils/TableGen/RegisterInfoEmitter.cpp
@@ -16,54 +16,400 @@
#include "RegisterInfoEmitter.h"
#include "CodeGenTarget.h"
#include "CodeGenRegisters.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Format.h"
#include <algorithm>
#include <set>
using namespace llvm;
// runEnums - Print out enum values for all of the registers.
-void RegisterInfoEmitter::runEnums(raw_ostream &OS) {
- CodeGenTarget Target;
- const std::vector<CodeGenRegister> &Registers = Target.getRegisters();
+void
+RegisterInfoEmitter::runEnums(raw_ostream &OS,
+ CodeGenTarget &Target, CodeGenRegBank &Bank) {
+ const std::vector<CodeGenRegister*> &Registers = Bank.getRegisters();
- std::string Namespace = Registers[0].TheDef->getValueAsString("Namespace");
+ std::string Namespace = Registers[0]->TheDef->getValueAsString("Namespace");
EmitSourceFileHeader("Target Register Enum Values", OS);
+
+ OS << "\n#ifdef GET_REGINFO_ENUM\n";
+ OS << "#undef GET_REGINFO_ENUM\n";
+
OS << "namespace llvm {\n\n";
+ OS << "class MCRegisterClass;\n"
+ << "extern MCRegisterClass " << Namespace << "MCRegisterClasses[];\n\n";
+
if (!Namespace.empty())
OS << "namespace " << Namespace << " {\n";
OS << "enum {\n NoRegister,\n";
for (unsigned i = 0, e = Registers.size(); i != e; ++i)
- OS << " " << Registers[i].getName() << ", \t// " << i+1 << "\n";
+ OS << " " << Registers[i]->getName() << " = " <<
+ Registers[i]->EnumValue << ",\n";
+ assert(Registers.size() == Registers[Registers.size()-1]->EnumValue &&
+ "Register enum value mismatch!");
OS << " NUM_TARGET_REGS \t// " << Registers.size()+1 << "\n";
OS << "};\n";
if (!Namespace.empty())
OS << "}\n";
- const std::vector<Record*> SubRegIndices = Target.getSubRegIndices();
- if (!SubRegIndices.empty()) {
- OS << "\n// Subregister indices\n";
- Namespace = SubRegIndices[0]->getValueAsString("Namespace");
+ ArrayRef<CodeGenRegisterClass*> RegisterClasses = Bank.getRegClasses();
+ if (!RegisterClasses.empty()) {
+ OS << "\n// Register classes\n";
if (!Namespace.empty())
OS << "namespace " << Namespace << " {\n";
- OS << "enum {\n NoSubRegister,\n";
- for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i)
- OS << " " << SubRegIndices[i]->getName() << ",\t// " << i+1 << "\n";
- OS << " NUM_TARGET_SUBREGS = " << SubRegIndices.size()+1 << "\n";
+ OS << "enum {\n";
+ for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
+ if (i) OS << ",\n";
+ OS << " " << RegisterClasses[i]->getName() << "RegClassID";
+ OS << " = " << i;
+ }
+ OS << "\n };\n";
+ if (!Namespace.empty())
+ OS << "}\n";
+ }
+
+ const std::vector<Record*> RegAltNameIndices = Target.getRegAltNameIndices();
+ // If the only definition is the default NoRegAltName, we don't need to
+ // emit anything.
+ if (RegAltNameIndices.size() > 1) {
+ OS << "\n// Register alternate name indices\n";
+ if (!Namespace.empty())
+ OS << "namespace " << Namespace << " {\n";
+ OS << "enum {\n";
+ for (unsigned i = 0, e = RegAltNameIndices.size(); i != e; ++i)
+ OS << " " << RegAltNameIndices[i]->getName() << ",\t// " << i << "\n";
+ OS << " NUM_TARGET_REG_ALT_NAMES = " << RegAltNameIndices.size() << "\n";
OS << "};\n";
if (!Namespace.empty())
OS << "}\n";
}
+
+
OS << "} // End llvm namespace \n";
+ OS << "#endif // GET_REGINFO_ENUM\n\n";
}
-void RegisterInfoEmitter::runHeader(raw_ostream &OS) {
+void
+RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS,
+ const std::vector<CodeGenRegister*> &Regs,
+ bool isCtor) {
+
+ // Collect all information about dwarf register numbers
+ typedef std::map<Record*, std::vector<int64_t>, LessRecord> DwarfRegNumsMapTy;
+ DwarfRegNumsMapTy DwarfRegNums;
+
+ // First, just pull all provided information to the map
+ unsigned maxLength = 0;
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ Record *Reg = Regs[i]->TheDef;
+ std::vector<int64_t> RegNums = Reg->getValueAsListOfInts("DwarfNumbers");
+ maxLength = std::max((size_t)maxLength, RegNums.size());
+ if (DwarfRegNums.count(Reg))
+ errs() << "Warning: DWARF numbers for register " << getQualifiedName(Reg)
+ << "specified multiple times\n";
+ DwarfRegNums[Reg] = RegNums;
+ }
+
+ if (!maxLength)
+ return;
+
+ // Now we know maximal length of number list. Append -1's, where needed
+ for (DwarfRegNumsMapTy::iterator
+ I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I)
+ for (unsigned i = I->second.size(), e = maxLength; i != e; ++i)
+ I->second.push_back(-1);
+
+ // Emit reverse information about the dwarf register numbers.
+ for (unsigned j = 0; j < 2; ++j) {
+ OS << " switch (";
+ if (j == 0)
+ OS << "DwarfFlavour";
+ else
+ OS << "EHFlavour";
+ OS << ") {\n"
+ << " default:\n"
+ << " assert(0 && \"Unknown DWARF flavour\");\n"
+ << " break;\n";
+
+ for (unsigned i = 0, e = maxLength; i != e; ++i) {
+ OS << " case " << i << ":\n";
+ for (DwarfRegNumsMapTy::iterator
+ I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
+ int DwarfRegNo = I->second[i];
+ if (DwarfRegNo < 0)
+ continue;
+ OS << " ";
+ if (!isCtor)
+ OS << "RI->";
+ OS << "mapDwarfRegToLLVMReg(" << DwarfRegNo << ", "
+ << getQualifiedName(I->first) << ", ";
+ if (j == 0)
+ OS << "false";
+ else
+ OS << "true";
+ OS << " );\n";
+ }
+ OS << " break;\n";
+ }
+ OS << " }\n";
+ }
+
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ Record *Reg = Regs[i]->TheDef;
+ const RecordVal *V = Reg->getValue("DwarfAlias");
+ if (!V || !V->getValue())
+ continue;
+
+ DefInit *DI = dynamic_cast<DefInit*>(V->getValue());
+ Record *Alias = DI->getDef();
+ DwarfRegNums[Reg] = DwarfRegNums[Alias];
+ }
+
+ // Emit information about the dwarf register numbers.
+ for (unsigned j = 0; j < 2; ++j) {
+ OS << " switch (";
+ if (j == 0)
+ OS << "DwarfFlavour";
+ else
+ OS << "EHFlavour";
+ OS << ") {\n"
+ << " default:\n"
+ << " assert(0 && \"Unknown DWARF flavour\");\n"
+ << " break;\n";
+
+ for (unsigned i = 0, e = maxLength; i != e; ++i) {
+ OS << " case " << i << ":\n";
+ // Sort by name to get a stable order.
+ for (DwarfRegNumsMapTy::iterator
+ I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
+ int RegNo = I->second[i];
+ OS << " ";
+ if (!isCtor)
+ OS << "RI->";
+ OS << "mapLLVMRegToDwarfReg(" << getQualifiedName(I->first) << ", "
+ << RegNo << ", ";
+ if (j == 0)
+ OS << "false";
+ else
+ OS << "true";
+ OS << " );\n";
+ }
+ OS << " break;\n";
+ }
+ OS << " }\n";
+ }
+}
+
+// Print a BitVector as a sequence of hex numbers using a little-endian mapping.
+// Width is the number of bits per hex number.
+static void printBitVectorAsHex(raw_ostream &OS,
+ const BitVector &Bits,
+ unsigned Width) {
+ assert(Width <= 32 && "Width too large");
+ unsigned Digits = (Width + 3) / 4;
+ for (unsigned i = 0, e = Bits.size(); i < e; i += Width) {
+ unsigned Value = 0;
+ for (unsigned j = 0; j != Width && i + j != e; ++j)
+ Value |= Bits.test(i + j) << j;
+ OS << format("0x%0*x, ", Digits, Value);
+ }
+}
+
+// Helper to emit a set of bits into a constant byte array.
+class BitVectorEmitter {
+ BitVector Values;
+public:
+ void add(unsigned v) {
+ if (v >= Values.size())
+ Values.resize(((v/8)+1)*8); // Round up to the next byte.
+ Values[v] = true;
+ }
+
+ void print(raw_ostream &OS) {
+ printBitVectorAsHex(OS, Values, 8);
+ }
+};
+
+//
+// runMCDesc - Print out MC register descriptions.
+//
+void
+RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
+ CodeGenRegBank &RegBank) {
+ EmitSourceFileHeader("MC Register Information", OS);
+
+ OS << "\n#ifdef GET_REGINFO_MC_DESC\n";
+ OS << "#undef GET_REGINFO_MC_DESC\n";
+
+ std::map<const CodeGenRegister*, CodeGenRegister::Set> Overlaps;
+ RegBank.computeOverlaps(Overlaps);
+
+ OS << "namespace llvm {\n\n";
+
+ const std::string &TargetName = Target.getName();
+ std::string ClassName = TargetName + "GenMCRegisterInfo";
+ OS << "struct " << ClassName << " : public MCRegisterInfo {\n"
+ << " explicit " << ClassName << "(const MCRegisterDesc *D);\n";
+ OS << "};\n";
+
+ OS << "\nnamespace {\n";
+
+ const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters();
+
+ // Emit an overlap list for all registers.
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ const CodeGenRegister *Reg = Regs[i];
+ const CodeGenRegister::Set &O = Overlaps[Reg];
+ // Move Reg to the front so TRI::getAliasSet can share the list.
+ OS << " const unsigned " << Reg->getName() << "_Overlaps[] = { "
+ << getQualifiedName(Reg->TheDef) << ", ";
+ for (CodeGenRegister::Set::const_iterator I = O.begin(), E = O.end();
+ I != E; ++I)
+ if (*I != Reg)
+ OS << getQualifiedName((*I)->TheDef) << ", ";
+ OS << "0 };\n";
+ }
+
+ // Emit the empty sub-registers list
+ OS << " const unsigned Empty_SubRegsSet[] = { 0 };\n";
+ // Loop over all of the registers which have sub-registers, emitting the
+ // sub-registers list to memory.
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ const CodeGenRegister &Reg = *Regs[i];
+ if (Reg.getSubRegs().empty())
+ continue;
+ // getSubRegs() orders by SubRegIndex. We want a topological order.
+ SetVector<CodeGenRegister*> SR;
+ Reg.addSubRegsPreOrder(SR);
+ OS << " const unsigned " << Reg.getName() << "_SubRegsSet[] = { ";
+ for (unsigned j = 0, je = SR.size(); j != je; ++j)
+ OS << getQualifiedName(SR[j]->TheDef) << ", ";
+ OS << "0 };\n";
+ }
+
+ // Emit the empty super-registers list
+ OS << " const unsigned Empty_SuperRegsSet[] = { 0 };\n";
+ // Loop over all of the registers which have super-registers, emitting the
+ // super-registers list to memory.
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ const CodeGenRegister &Reg = *Regs[i];
+ const CodeGenRegister::SuperRegList &SR = Reg.getSuperRegs();
+ if (SR.empty())
+ continue;
+ OS << " const unsigned " << Reg.getName() << "_SuperRegsSet[] = { ";
+ for (unsigned j = 0, je = SR.size(); j != je; ++j)
+ OS << getQualifiedName(SR[j]->TheDef) << ", ";
+ OS << "0 };\n";
+ }
+ OS << "}\n"; // End of anonymous namespace...
+
+ OS << "\nMCRegisterDesc " << TargetName
+ << "RegDesc[] = { // Descriptors\n";
+ OS << " { \"NOREG\",\t0,\t0,\t0 },\n";
+
+ // Now that register alias and sub-registers sets have been emitted, emit the
+ // register descriptors now.
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ const CodeGenRegister &Reg = *Regs[i];
+ OS << " { \"";
+ OS << Reg.getName() << "\",\t" << Reg.getName() << "_Overlaps,\t";
+ if (!Reg.getSubRegs().empty())
+ OS << Reg.getName() << "_SubRegsSet,\t";
+ else
+ OS << "Empty_SubRegsSet,\t";
+ if (!Reg.getSuperRegs().empty())
+ OS << Reg.getName() << "_SuperRegsSet";
+ else
+ OS << "Empty_SuperRegsSet";
+ OS << " },\n";
+ }
+ OS << "};\n\n"; // End of register descriptors...
+
+ ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses();
+
+ // Loop over all of the register classes... emitting each one.
+ OS << "namespace { // Register classes...\n";
+
+ // Emit the register enum value arrays for each RegisterClass
+ for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
+ ArrayRef<Record*> Order = RC.getOrder();
+
+ // Give the register class a legal C name if it's anonymous.
+ std::string Name = RC.getName();
+
+ // Emit the register list now.
+ OS << " // " << Name << " Register Class...\n"
+ << " static const unsigned " << Name
+ << "[] = {\n ";
+ for (unsigned i = 0, e = Order.size(); i != e; ++i) {
+ Record *Reg = Order[i];
+ OS << getQualifiedName(Reg) << ", ";
+ }
+ OS << "\n };\n\n";
+
+ OS << " // " << Name << " Bit set.\n"
+ << " static const unsigned char " << Name
+ << "Bits[] = {\n ";
+ BitVectorEmitter BVE;
+ for (unsigned i = 0, e = Order.size(); i != e; ++i) {
+ Record *Reg = Order[i];
+ BVE.add(Target.getRegBank().getReg(Reg)->EnumValue);
+ }
+ BVE.print(OS);
+ OS << "\n };\n\n";
+
+ }
+ OS << "}\n\n";
+
+ OS << "MCRegisterClass " << TargetName << "MCRegisterClasses[] = {\n";
+
+ for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
+ OS << " MCRegisterClass(" << RC.getQualifiedName() + "RegClassID" << ", "
+ << '\"' << RC.getName() << "\", "
+ << RC.SpillSize/8 << ", "
+ << RC.SpillAlignment/8 << ", "
+ << RC.CopyCost << ", "
+ << RC.Allocatable << ", "
+ << RC.getName() << ", " << RC.getName() << " + "
+ << RC.getOrder().size() << ", "
+ << RC.getName() << "Bits, sizeof(" << RC.getName() << "Bits)"
+ << "),\n";
+ }
+
+ OS << "};\n\n";
+
+ // MCRegisterInfo initialization routine.
+ OS << "static inline void Init" << TargetName
+ << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, "
+ << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0) {\n";
+ OS << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, "
+ << Regs.size()+1 << ", RA, " << TargetName << "MCRegisterClasses, "
+ << RegisterClasses.size() << ");\n\n";
+
+ EmitRegMapping(OS, Regs, false);
+
+ OS << "}\n\n";
+
+
+ OS << "} // End llvm namespace \n";
+ OS << "#endif // GET_REGINFO_MC_DESC\n\n";
+}
+
+void
+RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
+ CodeGenRegBank &RegBank) {
EmitSourceFileHeader("Register Information Header Fragment", OS);
- CodeGenTarget Target;
+
+ OS << "\n#ifdef GET_REGINFO_HEADER\n";
+ OS << "#undef GET_REGINFO_HEADER\n";
+
const std::string &TargetName = Target.getName();
std::string ClassName = TargetName + "GenRegisterInfo";
@@ -74,39 +420,48 @@
OS << "struct " << ClassName << " : public TargetRegisterInfo {\n"
<< " explicit " << ClassName
- << "(int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1);\n"
- << " virtual int getDwarfRegNumFull(unsigned RegNum, "
- << "unsigned Flavour) const;\n"
- << " virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const = 0;\n"
+ << "(unsigned RA, unsigned D = 0, unsigned E = 0);\n"
<< " virtual bool needsStackRealignment(const MachineFunction &) const\n"
<< " { return false; }\n"
<< " unsigned getSubReg(unsigned RegNo, unsigned Index) const;\n"
<< " unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const;\n"
<< " unsigned composeSubRegIndices(unsigned, unsigned) const;\n"
+ << " const TargetRegisterClass *"
+ "getSubClassWithSubReg(const TargetRegisterClass*, unsigned) const;\n"
<< "};\n\n";
- const std::vector<CodeGenRegisterClass> &RegisterClasses =
- Target.getRegisterClasses();
+ const std::vector<Record*> &SubRegIndices = RegBank.getSubRegIndices();
+ if (!SubRegIndices.empty()) {
+ OS << "\n// Subregister indices\n";
+ std::string Namespace = SubRegIndices[0]->getValueAsString("Namespace");
+ if (!Namespace.empty())
+ OS << "namespace " << Namespace << " {\n";
+ OS << "enum {\n NoSubRegister,\n";
+ for (unsigned i = 0, e = RegBank.getNumNamedIndices(); i != e; ++i)
+ OS << " " << SubRegIndices[i]->getName() << ",\t// " << i+1 << "\n";
+ OS << " NUM_TARGET_NAMED_SUBREGS = " << SubRegIndices.size()+1 << "\n";
+ OS << "};\n";
+ if (!Namespace.empty())
+ OS << "}\n";
+ }
+
+ ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses();
if (!RegisterClasses.empty()) {
- OS << "namespace " << RegisterClasses[0].Namespace
+ OS << "namespace " << RegisterClasses[0]->Namespace
<< " { // Register classes\n";
-
- OS << " enum {\n";
- for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
- if (i) OS << ",\n";
- OS << " " << RegisterClasses[i].getName() << "RegClassID";
- OS << " = " << i;
- }
- OS << "\n };\n\n";
for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
- const std::string &Name = RegisterClasses[i].getName();
+ const CodeGenRegisterClass &RC = *RegisterClasses[i];
+ const std::string &Name = RC.getName();
// Output the register class definition.
OS << " struct " << Name << "Class : public TargetRegisterClass {\n"
- << " " << Name << "Class();\n"
- << RegisterClasses[i].MethodProtos << " };\n";
+ << " " << Name << "Class();\n";
+ if (!RC.AltOrderSelect.empty())
+ OS << " ArrayRef<unsigned> "
+ "getRawAllocationOrder(const MachineFunction&) const;\n";
+ OS << " };\n";
// Output the extern for the instance.
OS << " extern " << Name << "Class\t" << Name << "RegClass;\n";
@@ -117,281 +472,52 @@
OS << "} // end of namespace " << TargetName << "\n\n";
}
OS << "} // End llvm namespace \n";
+ OS << "#endif // GET_REGINFO_HEADER\n\n";
}
-bool isSubRegisterClass(const CodeGenRegisterClass &RC,
- std::set<Record*> &RegSet) {
- for (unsigned i = 0, e = RC.Elements.size(); i != e; ++i) {
- Record *Reg = RC.Elements[i];
- if (!RegSet.count(Reg))
- return false;
- }
- return true;
-}
-
-static void addSuperReg(Record *R, Record *S,
- std::map<Record*, std::set<Record*>, LessRecord> &SubRegs,
- std::map<Record*, std::set<Record*>, LessRecord> &SuperRegs,
- std::map<Record*, std::set<Record*>, LessRecord> &Aliases) {
- if (R == S) {
- errs() << "Error: recursive sub-register relationship between"
- << " register " << getQualifiedName(R)
- << " and its sub-registers?\n";
- abort();
- }
- if (!SuperRegs[R].insert(S).second)
- return;
- SubRegs[S].insert(R);
- Aliases[R].insert(S);
- Aliases[S].insert(R);
- if (SuperRegs.count(S))
- for (std::set<Record*>::iterator I = SuperRegs[S].begin(),
- E = SuperRegs[S].end(); I != E; ++I)
- addSuperReg(R, *I, SubRegs, SuperRegs, Aliases);
-}
-
-static void addSubSuperReg(Record *R, Record *S,
- std::map<Record*, std::set<Record*>, LessRecord> &SubRegs,
- std::map<Record*, std::set<Record*>, LessRecord> &SuperRegs,
- std::map<Record*, std::set<Record*>, LessRecord> &Aliases) {
- if (R == S) {
- errs() << "Error: recursive sub-register relationship between"
- << " register " << getQualifiedName(R)
- << " and its sub-registers?\n";
- abort();
- }
-
- if (!SubRegs[R].insert(S).second)
- return;
- addSuperReg(S, R, SubRegs, SuperRegs, Aliases);
- Aliases[R].insert(S);
- Aliases[S].insert(R);
- if (SubRegs.count(S))
- for (std::set<Record*>::iterator I = SubRegs[S].begin(),
- E = SubRegs[S].end(); I != E; ++I)
- addSubSuperReg(R, *I, SubRegs, SuperRegs, Aliases);
-}
-
-struct RegisterMaps {
- // Map SubRegIndex -> Register
- typedef std::map<Record*, Record*, LessRecord> SubRegMap;
- // Map Register -> SubRegMap
- typedef std::map<Record*, SubRegMap> SubRegMaps;
-
- SubRegMaps SubReg;
- SubRegMap &inferSubRegIndices(Record *Reg);
-
- // Composite SubRegIndex instances.
- // Map (SubRegIndex,SubRegIndex) -> SubRegIndex
- typedef DenseMap<std::pair<Record*,Record*>,Record*> CompositeMap;
- CompositeMap Composite;
-
- // Compute SubRegIndex compositions after inferSubRegIndices has run on all
- // registers.
- void computeComposites();
-};
-
-// Calculate all subregindices for Reg. Loopy subregs cause infinite recursion.
-RegisterMaps::SubRegMap &RegisterMaps::inferSubRegIndices(Record *Reg) {
- SubRegMap &SRM = SubReg[Reg];
- if (!SRM.empty())
- return SRM;
- std::vector<Record*> SubRegs = Reg->getValueAsListOfDefs("SubRegs");
- std::vector<Record*> Indices = Reg->getValueAsListOfDefs("SubRegIndices");
- if (SubRegs.size() != Indices.size())
- throw "Register " + Reg->getName() + " SubRegIndices doesn't match SubRegs";
-
- // First insert the direct subregs and make sure they are fully indexed.
- for (unsigned i = 0, e = SubRegs.size(); i != e; ++i) {
- if (!SRM.insert(std::make_pair(Indices[i], SubRegs[i])).second)
- throw "SubRegIndex " + Indices[i]->getName()
- + " appears twice in Register " + Reg->getName();
- inferSubRegIndices(SubRegs[i]);
- }
-
- // Keep track of inherited subregs and how they can be reached.
- // Register -> (SubRegIndex, SubRegIndex)
- typedef std::map<Record*, std::pair<Record*,Record*>, LessRecord> OrphanMap;
- OrphanMap Orphans;
-
- // Clone inherited subregs. Here the order is important - earlier subregs take
- // precedence.
- for (unsigned i = 0, e = SubRegs.size(); i != e; ++i) {
- SubRegMap &M = SubReg[SubRegs[i]];
- for (SubRegMap::iterator si = M.begin(), se = M.end(); si != se; ++si)
- if (!SRM.insert(*si).second)
- Orphans[si->second] = std::make_pair(Indices[i], si->first);
- }
-
- // Finally process the composites.
- ListInit *Comps = Reg->getValueAsListInit("CompositeIndices");
- for (unsigned i = 0, e = Comps->size(); i != e; ++i) {
- DagInit *Pat = dynamic_cast<DagInit*>(Comps->getElement(i));
- if (!Pat)
- throw "Invalid dag '" + Comps->getElement(i)->getAsString()
- + "' in CompositeIndices";
- DefInit *BaseIdxInit = dynamic_cast<DefInit*>(Pat->getOperator());
- if (!BaseIdxInit || !BaseIdxInit->getDef()->isSubClassOf("SubRegIndex"))
- throw "Invalid SubClassIndex in " + Pat->getAsString();
-
- // Resolve list of subreg indices into R2.
- Record *R2 = Reg;
- for (DagInit::const_arg_iterator di = Pat->arg_begin(),
- de = Pat->arg_end(); di != de; ++di) {
- DefInit *IdxInit = dynamic_cast<DefInit*>(*di);
- if (!IdxInit || !IdxInit->getDef()->isSubClassOf("SubRegIndex"))
- throw "Invalid SubClassIndex in " + Pat->getAsString();
- SubRegMap::const_iterator ni = SubReg[R2].find(IdxInit->getDef());
- if (ni == SubReg[R2].end())
- throw "Composite " + Pat->getAsString() + " refers to bad index in "
- + R2->getName();
- R2 = ni->second;
- }
-
- // Insert composite index. Allow overriding inherited indices etc.
- SRM[BaseIdxInit->getDef()] = R2;
-
- // R2 is now directly addressable, no longer an orphan.
- Orphans.erase(R2);
- }
-
- // Now, Orphans contains the inherited subregisters without a direct index.
- if (!Orphans.empty()) {
- errs() << "Error: Register " << getQualifiedName(Reg)
- << " inherited subregisters without an index:\n";
- for (OrphanMap::iterator i = Orphans.begin(), e = Orphans.end(); i != e;
- ++i) {
- errs() << " " << getQualifiedName(i->first)
- << " = " << i->second.first->getName()
- << ", " << i->second.second->getName() << "\n";
- }
- abort();
- }
- return SRM;
-}
-
-void RegisterMaps::computeComposites() {
- for (SubRegMaps::const_iterator sri = SubReg.begin(), sre = SubReg.end();
- sri != sre; ++sri) {
- Record *Reg1 = sri->first;
- const SubRegMap &SRM1 = sri->second;
- for (SubRegMap::const_iterator i1 = SRM1.begin(), e1 = SRM1.end();
- i1 != e1; ++i1) {
- Record *Idx1 = i1->first;
- Record *Reg2 = i1->second;
- // Ignore identity compositions.
- if (Reg1 == Reg2)
- continue;
- // If Reg2 has no subregs, Idx1 doesn't compose.
- if (!SubReg.count(Reg2))
- continue;
- const SubRegMap &SRM2 = SubReg[Reg2];
- // Try composing Idx1 with another SubRegIndex.
- for (SubRegMap::const_iterator i2 = SRM2.begin(), e2 = SRM2.end();
- i2 != e2; ++i2) {
- std::pair<Record*,Record*> IdxPair(Idx1, i2->first);
- Record *Reg3 = i2->second;
- // OK Reg1:IdxPair == Reg3. Find the index with Reg:Idx == Reg3.
- for (SubRegMap::const_iterator i1d = SRM1.begin(), e1d = SRM1.end();
- i1d != e1d; ++i1d) {
- // Ignore identity compositions.
- if (Reg2 == Reg3)
- continue;
- if (i1d->second == Reg3) {
- std::pair<CompositeMap::iterator,bool> Ins =
- Composite.insert(std::make_pair(IdxPair, i1d->first));
- // Conflicting composition?
- if (!Ins.second && Ins.first->second != i1d->first) {
- errs() << "Error: SubRegIndex " << getQualifiedName(Idx1)
- << " and " << getQualifiedName(IdxPair.second)
- << " compose ambiguously as "
- << getQualifiedName(Ins.first->second) << " or "
- << getQualifiedName(i1d->first) << "\n";
- abort();
- }
- }
- }
- }
- }
- }
-
- // We don't care about the difference between (Idx1, Idx2) -> Idx2 and invalid
- // compositions, so remove any mappings of that form.
- for (CompositeMap::iterator i = Composite.begin(), e = Composite.end();
- i != e;) {
- CompositeMap::iterator j = i;
- ++i;
- if (j->first.second == j->second)
- Composite.erase(j);
- }
-}
-
-class RegisterSorter {
-private:
- std::map<Record*, std::set<Record*>, LessRecord> &RegisterSubRegs;
-
-public:
- RegisterSorter(std::map<Record*, std::set<Record*>, LessRecord> &RS)
- : RegisterSubRegs(RS) {}
-
- bool operator()(Record *RegA, Record *RegB) {
- // B is sub-register of A.
- return RegisterSubRegs.count(RegA) && RegisterSubRegs[RegA].count(RegB);
- }
-};
-
-// RegisterInfoEmitter::run - Main register file description emitter.
//
-void RegisterInfoEmitter::run(raw_ostream &OS) {
- CodeGenTarget Target;
- EmitSourceFileHeader("Register Information Source Fragment", OS);
+// runTargetDesc - Output the target register and register file descriptions.
+//
+void
+RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
+ CodeGenRegBank &RegBank){
+ EmitSourceFileHeader("Target Register and Register Classes Information", OS);
+
+ OS << "\n#ifdef GET_REGINFO_TARGET_DESC\n";
+ OS << "#undef GET_REGINFO_TARGET_DESC\n";
OS << "namespace llvm {\n\n";
- // Start out by emitting each of the register classes... to do this, we build
- // a set of registers which belong to a register class, this is to ensure that
- // each register is only in a single register class.
- //
- const std::vector<CodeGenRegisterClass> &RegisterClasses =
- Target.getRegisterClasses();
+ // Get access to MCRegisterClass data.
+ OS << "extern MCRegisterClass " << Target.getName()
+ << "MCRegisterClasses[];\n";
- // Loop over all of the register classes... emitting each one.
- OS << "namespace { // Register classes...\n";
+ // Start out by emitting each of the register classes.
+ ArrayRef<CodeGenRegisterClass*> RegisterClasses = RegBank.getRegClasses();
- // RegClassesBelongedTo - Keep track of which register classes each reg
- // belongs to.
- std::multimap<Record*, const CodeGenRegisterClass*> RegClassesBelongedTo;
+ // Collect all registers belonging to any allocatable class.
+ std::set<Record*> AllocatableRegs;
- // Emit the register enum value arrays for each RegisterClass
+ // Collect allocatable registers.
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RegisterClasses[rc];
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
+ ArrayRef<Record*> Order = RC.getOrder();
- // Give the register class a legal C name if it's anonymous.
- std::string Name = RC.TheDef->getName();
-
- // Emit the register list now.
- OS << " // " << Name << " Register Class...\n"
- << " static const unsigned " << Name
- << "[] = {\n ";
- for (unsigned i = 0, e = RC.Elements.size(); i != e; ++i) {
- Record *Reg = RC.Elements[i];
- OS << getQualifiedName(Reg) << ", ";
-
- // Keep track of which regclasses this register is in.
- RegClassesBelongedTo.insert(std::make_pair(Reg, &RC));
- }
- OS << "\n };\n\n";
+ if (RC.Allocatable)
+ AllocatableRegs.insert(Order.begin(), Order.end());
}
+ OS << "namespace { // Register classes...\n";
+
// Emit the ValueType arrays for each RegisterClass
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RegisterClasses[rc];
-
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
+
// Give the register class a legal C name if it's anonymous.
- std::string Name = RC.TheDef->getName() + "VTs";
-
+ std::string Name = RC.getName() + "VTs";
+
// Emit the register list now.
- OS << " // " << Name
+ OS << " // " << Name
<< " Register Class Value Types...\n"
<< " static const EVT " << Name
<< "[] = {\n ";
@@ -400,68 +526,42 @@
OS << "MVT::Other\n };\n\n";
}
OS << "} // end anonymous namespace\n\n";
-
+
// Now that all of the structs have been emitted, emit the instances.
if (!RegisterClasses.empty()) {
- OS << "namespace " << RegisterClasses[0].Namespace
+ OS << "namespace " << RegisterClasses[0]->Namespace
<< " { // Register class instances\n";
for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i)
- OS << " " << RegisterClasses[i].getName() << "Class\t"
- << RegisterClasses[i].getName() << "RegClass;\n";
-
- std::map<unsigned, std::set<unsigned> > SuperClassMap;
- std::map<unsigned, std::set<unsigned> > SuperRegClassMap;
- OS << "\n";
+ OS << " " << RegisterClasses[i]->getName() << "Class\t"
+ << RegisterClasses[i]->getName() << "RegClass;\n";
- unsigned NumSubRegIndices = Target.getSubRegIndices().size();
+ std::map<unsigned, std::set<unsigned> > SuperRegClassMap;
+
+ OS << "\n static const TargetRegisterClass* const "
+ << "NullRegClasses[] = { NULL };\n\n";
+
+ unsigned NumSubRegIndices = RegBank.getSubRegIndices().size();
if (NumSubRegIndices) {
- // Emit the sub-register classes for each RegisterClass
+ // Compute the super-register classes for each RegisterClass
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RegisterClasses[rc];
- std::vector<Record*> SRC(NumSubRegIndices);
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
for (DenseMap<Record*,Record*>::const_iterator
i = RC.SubRegClasses.begin(),
e = RC.SubRegClasses.end(); i != e; ++i) {
- // Build SRC array.
- unsigned idx = Target.getSubRegIndexNo(i->first);
- SRC.at(idx-1) = i->second;
-
// Find the register class number of i->second for SuperRegClassMap.
- for (unsigned rc2 = 0, e2 = RegisterClasses.size(); rc2 != e2; ++rc2) {
- const CodeGenRegisterClass &RC2 = RegisterClasses[rc2];
- if (RC2.TheDef == i->second) {
- SuperRegClassMap[rc2].insert(rc);
- break;
- }
- }
+ const CodeGenRegisterClass *RC2 = RegBank.getRegClass(i->second);
+ assert(RC2 && "Invalid register class in SubRegClasses");
+ SuperRegClassMap[RC2->EnumValue].insert(rc);
}
-
- // Give the register class a legal C name if it's anonymous.
- std::string Name = RC.TheDef->getName();
-
- OS << " // " << Name
- << " Sub-register Classes...\n"
- << " static const TargetRegisterClass* const "
- << Name << "SubRegClasses[] = {\n ";
-
- for (unsigned idx = 0; idx != NumSubRegIndices; ++idx) {
- if (idx)
- OS << ", ";
- if (SRC[idx])
- OS << "&" << getQualifiedName(SRC[idx]) << "RegClass";
- else
- OS << "0";
- }
- OS << "\n };\n\n";
}
// Emit the super-register classes for each RegisterClass
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RegisterClasses[rc];
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
// Give the register class a legal C name if it's anonymous.
- std::string Name = RC.TheDef->getName();
+ std::string Name = RC.getName();
OS << " // " << Name
<< " Super-register Classes...\n"
@@ -474,10 +574,10 @@
if (I != SuperRegClassMap.end()) {
for (std::set<unsigned>::iterator II = I->second.begin(),
EE = I->second.end(); II != EE; ++II) {
- const CodeGenRegisterClass &RC2 = RegisterClasses[*II];
+ const CodeGenRegisterClass &RC2 = *RegisterClasses[*II];
if (!Empty)
OS << ", ";
- OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
+ OS << "&" << RC2.getQualifiedName() << "RegClass";
Empty = false;
}
}
@@ -485,430 +585,134 @@
OS << (!Empty ? ", " : "") << "NULL";
OS << "\n };\n\n";
}
- } else {
- // No subregindices in this target
- OS << " static const TargetRegisterClass* const "
- << "NullRegClasses[] = { NULL };\n\n";
}
// Emit the sub-classes array for each RegisterClass
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RegisterClasses[rc];
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
// Give the register class a legal C name if it's anonymous.
- std::string Name = RC.TheDef->getName();
+ std::string Name = RC.getName();
- std::set<Record*> RegSet;
- for (unsigned i = 0, e = RC.Elements.size(); i != e; ++i) {
- Record *Reg = RC.Elements[i];
- RegSet.insert(Reg);
- }
-
- OS << " // " << Name
- << " Register Class sub-classes...\n"
- << " static const TargetRegisterClass* const "
- << Name << "Subclasses[] = {\n ";
-
- bool Empty = true;
- for (unsigned rc2 = 0, e2 = RegisterClasses.size(); rc2 != e2; ++rc2) {
- const CodeGenRegisterClass &RC2 = RegisterClasses[rc2];
-
- // RC2 is a sub-class of RC if it is a valid replacement for any
- // instruction operand where an RC register is required. It must satisfy
- // these conditions:
- //
- // 1. All RC2 registers are also in RC.
- // 2. The RC2 spill size must not be smaller that the RC spill size.
- // 3. RC2 spill alignment must be compatible with RC.
- //
- // Sub-classes are used to determine if a virtual register can be used
- // as an instruction operand, or if it must be copied first.
-
- if (rc == rc2 || RC2.Elements.size() > RC.Elements.size() ||
- (RC.SpillAlignment && RC2.SpillAlignment % RC.SpillAlignment) ||
- RC.SpillSize > RC2.SpillSize || !isSubRegisterClass(RC2, RegSet))
- continue;
-
- if (!Empty) OS << ", ";
- OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
- Empty = false;
-
- std::map<unsigned, std::set<unsigned> >::iterator SCMI =
- SuperClassMap.find(rc2);
- if (SCMI == SuperClassMap.end()) {
- SuperClassMap.insert(std::make_pair(rc2, std::set<unsigned>()));
- SCMI = SuperClassMap.find(rc2);
- }
- SCMI->second.insert(rc);
- }
-
- OS << (!Empty ? ", " : "") << "NULL";
- OS << "\n };\n\n";
+ OS << " static const unsigned " << Name << "SubclassMask[] = { ";
+ printBitVectorAsHex(OS, RC.getSubClasses(), 32);
+ OS << "};\n\n";
}
+ // Emit NULL terminated super-class lists.
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RegisterClasses[rc];
+ const CodeGenRegisterClass &RC = *RegisterClasses[rc];
+ ArrayRef<CodeGenRegisterClass*> Supers = RC.getSuperClasses();
- // Give the register class a legal C name if it's anonymous.
- std::string Name = RC.TheDef->getName();
+ // Skip classes without supers. We can reuse NullRegClasses.
+ if (Supers.empty())
+ continue;
- OS << " // " << Name
- << " Register Class super-classes...\n"
- << " static const TargetRegisterClass* const "
- << Name << "Superclasses[] = {\n ";
-
- bool Empty = true;
- std::map<unsigned, std::set<unsigned> >::iterator I =
- SuperClassMap.find(rc);
- if (I != SuperClassMap.end()) {
- for (std::set<unsigned>::iterator II = I->second.begin(),
- EE = I->second.end(); II != EE; ++II) {
- const CodeGenRegisterClass &RC2 = RegisterClasses[*II];
- if (!Empty) OS << ", ";
- OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
- Empty = false;
- }
- }
-
- OS << (!Empty ? ", " : "") << "NULL";
- OS << "\n };\n\n";
+ OS << " static const TargetRegisterClass* const "
+ << RC.getName() << "Superclasses[] = {\n";
+ for (unsigned i = 0; i != Supers.size(); ++i)
+ OS << " &" << Supers[i]->getQualifiedName() << "RegClass,\n";
+ OS << " NULL\n };\n\n";
}
-
+ // Emit methods.
for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) {
- const CodeGenRegisterClass &RC = RegisterClasses[i];
- OS << RC.MethodBodies << "\n";
- OS << RC.getName() << "Class::" << RC.getName()
- << "Class() : TargetRegisterClass("
- << RC.getName() + "RegClassID" << ", "
- << '\"' << RC.getName() << "\", "
+ const CodeGenRegisterClass &RC = *RegisterClasses[i];
+ OS << RC.getName() << "Class::" << RC.getName()
+ << "Class() : TargetRegisterClass(&"
+ << Target.getName() << "MCRegisterClasses["
+ << RC.getName() + "RegClassID" << "], "
<< RC.getName() + "VTs" << ", "
- << RC.getName() + "Subclasses" << ", "
- << RC.getName() + "Superclasses" << ", "
- << (NumSubRegIndices ? RC.getName() + "Sub" : std::string("Null"))
- << "RegClasses, "
- << (NumSubRegIndices ? RC.getName() + "Super" : std::string("Null"))
- << "RegClasses, "
- << RC.SpillSize/8 << ", "
- << RC.SpillAlignment/8 << ", "
- << RC.CopyCost << ", "
- << RC.getName() << ", " << RC.getName() << " + " << RC.Elements.size()
+ << RC.getName() + "SubclassMask" << ", ";
+ if (RC.getSuperClasses().empty())
+ OS << "NullRegClasses, ";
+ else
+ OS << RC.getName() + "Superclasses, ";
+ OS << (NumSubRegIndices ? RC.getName() + "Super" : std::string("Null"))
+ << "RegClasses"
<< ") {}\n";
+ if (!RC.AltOrderSelect.empty()) {
+ OS << "\nstatic inline unsigned " << RC.getName()
+ << "AltOrderSelect(const MachineFunction &MF) {"
+ << RC.AltOrderSelect << "}\n\nArrayRef<unsigned> "
+ << RC.getName() << "Class::"
+ << "getRawAllocationOrder(const MachineFunction &MF) const {\n";
+ for (unsigned oi = 1 , oe = RC.getNumOrders(); oi != oe; ++oi) {
+ ArrayRef<Record*> Elems = RC.getOrder(oi);
+ OS << " static const unsigned AltOrder" << oi << "[] = {";
+ for (unsigned elem = 0; elem != Elems.size(); ++elem)
+ OS << (elem ? ", " : " ") << getQualifiedName(Elems[elem]);
+ OS << " };\n";
+ }
+ OS << " const MCRegisterClass &MCR = " << Target.getName()
+ << "MCRegisterClasses[" << RC.getQualifiedName() + "RegClassID];"
+ << " static const ArrayRef<unsigned> Order[] = {\n"
+ << " makeArrayRef(MCR.begin(), MCR.getNumRegs()";
+ for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi)
+ OS << "),\n makeArrayRef(AltOrder" << oi;
+ OS << ")\n };\n const unsigned Select = " << RC.getName()
+ << "AltOrderSelect(MF);\n assert(Select < " << RC.getNumOrders()
+ << ");\n return Order[Select];\n}\n";
+ }
}
-
+
OS << "}\n";
}
OS << "\nnamespace {\n";
OS << " const TargetRegisterClass* const RegisterClasses[] = {\n";
for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i)
- OS << " &" << getQualifiedName(RegisterClasses[i].TheDef)
+ OS << " &" << RegisterClasses[i]->getQualifiedName()
<< "RegClass,\n";
OS << " };\n";
+ OS << "}\n"; // End of anonymous namespace...
- // Emit register sub-registers / super-registers, aliases...
- std::map<Record*, std::set<Record*>, LessRecord> RegisterSubRegs;
- std::map<Record*, std::set<Record*>, LessRecord> RegisterSuperRegs;
- std::map<Record*, std::set<Record*>, LessRecord> RegisterAliases;
- typedef std::map<Record*, std::vector<int64_t>, LessRecord> DwarfRegNumsMapTy;
- DwarfRegNumsMapTy DwarfRegNums;
-
- const std::vector<CodeGenRegister> &Regs = Target.getRegisters();
+ // Emit extra information about registers.
+ const std::string &TargetName = Target.getName();
+ OS << "\n static const TargetRegisterInfoDesc "
+ << TargetName << "RegInfoDesc[] = "
+ << "{ // Extra Descriptors\n";
+ OS << " { 0, 0 },\n";
+ const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters();
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- Record *R = Regs[i].TheDef;
- std::vector<Record*> LI = Regs[i].TheDef->getValueAsListOfDefs("Aliases");
- // Add information that R aliases all of the elements in the list... and
- // that everything in the list aliases R.
- for (unsigned j = 0, e = LI.size(); j != e; ++j) {
- Record *Reg = LI[j];
- if (RegisterAliases[R].count(Reg))
- errs() << "Warning: register alias between " << getQualifiedName(R)
- << " and " << getQualifiedName(Reg)
- << " specified multiple times!\n";
- RegisterAliases[R].insert(Reg);
-
- if (RegisterAliases[Reg].count(R))
- errs() << "Warning: register alias between " << getQualifiedName(R)
- << " and " << getQualifiedName(Reg)
- << " specified multiple times!\n";
- RegisterAliases[Reg].insert(R);
- }
- }
-
- // Process sub-register sets.
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- Record *R = Regs[i].TheDef;
- std::vector<Record*> LI = Regs[i].TheDef->getValueAsListOfDefs("SubRegs");
- // Process sub-register set and add aliases information.
- for (unsigned j = 0, e = LI.size(); j != e; ++j) {
- Record *SubReg = LI[j];
- if (RegisterSubRegs[R].count(SubReg))
- errs() << "Warning: register " << getQualifiedName(SubReg)
- << " specified as a sub-register of " << getQualifiedName(R)
- << " multiple times!\n";
- addSubSuperReg(R, SubReg, RegisterSubRegs, RegisterSuperRegs,
- RegisterAliases);
- }
- }
-
- // Print the SubregHashTable, a simple quadratically probed
- // hash table for determining if a register is a subregister
- // of another register.
- unsigned NumSubRegs = 0;
- std::map<Record*, unsigned> RegNo;
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- RegNo[Regs[i].TheDef] = i;
- NumSubRegs += RegisterSubRegs[Regs[i].TheDef].size();
- }
-
- unsigned SubregHashTableSize = 2 * NextPowerOf2(2 * NumSubRegs);
- unsigned* SubregHashTable = new unsigned[2 * SubregHashTableSize];
- std::fill(SubregHashTable, SubregHashTable + 2 * SubregHashTableSize, ~0U);
-
- unsigned hashMisses = 0;
-
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- Record* R = Regs[i].TheDef;
- for (std::set<Record*>::iterator I = RegisterSubRegs[R].begin(),
- E = RegisterSubRegs[R].end(); I != E; ++I) {
- Record* RJ = *I;
- // We have to increase the indices of both registers by one when
- // computing the hash because, in the generated code, there
- // will be an extra empty slot at register 0.
- size_t index = ((i+1) + (RegNo[RJ]+1) * 37) & (SubregHashTableSize-1);
- unsigned ProbeAmt = 2;
- while (SubregHashTable[index*2] != ~0U &&
- SubregHashTable[index*2+1] != ~0U) {
- index = (index + ProbeAmt) & (SubregHashTableSize-1);
- ProbeAmt += 2;
-
- hashMisses++;
- }
-
- SubregHashTable[index*2] = i;
- SubregHashTable[index*2+1] = RegNo[RJ];
- }
- }
-
- OS << "\n\n // Number of hash collisions: " << hashMisses << "\n";
-
- if (SubregHashTableSize) {
- std::string Namespace = Regs[0].TheDef->getValueAsString("Namespace");
-
- OS << " const unsigned SubregHashTable[] = { ";
- for (unsigned i = 0; i < SubregHashTableSize - 1; ++i) {
- if (i != 0)
- // Insert spaces for nice formatting.
- OS << " ";
-
- if (SubregHashTable[2*i] != ~0U) {
- OS << getQualifiedName(Regs[SubregHashTable[2*i]].TheDef) << ", "
- << getQualifiedName(Regs[SubregHashTable[2*i+1]].TheDef) << ", \n";
- } else {
- OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister, \n";
- }
- }
-
- unsigned Idx = SubregHashTableSize*2-2;
- if (SubregHashTable[Idx] != ~0U) {
- OS << " "
- << getQualifiedName(Regs[SubregHashTable[Idx]].TheDef) << ", "
- << getQualifiedName(Regs[SubregHashTable[Idx+1]].TheDef) << " };\n";
- } else {
- OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister };\n";
- }
-
- OS << " const unsigned SubregHashTableSize = "
- << SubregHashTableSize << ";\n";
- } else {
- OS << " const unsigned SubregHashTable[] = { ~0U, ~0U };\n"
- << " const unsigned SubregHashTableSize = 1;\n";
- }
-
- delete [] SubregHashTable;
-
-
- // Print the AliasHashTable, a simple quadratically probed
- // hash table for determining if a register aliases another register.
- unsigned NumAliases = 0;
- RegNo.clear();
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- RegNo[Regs[i].TheDef] = i;
- NumAliases += RegisterAliases[Regs[i].TheDef].size();
- }
-
- unsigned AliasesHashTableSize = 2 * NextPowerOf2(2 * NumAliases);
- unsigned* AliasesHashTable = new unsigned[2 * AliasesHashTableSize];
- std::fill(AliasesHashTable, AliasesHashTable + 2 * AliasesHashTableSize, ~0U);
-
- hashMisses = 0;
-
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- Record* R = Regs[i].TheDef;
- for (std::set<Record*>::iterator I = RegisterAliases[R].begin(),
- E = RegisterAliases[R].end(); I != E; ++I) {
- Record* RJ = *I;
- // We have to increase the indices of both registers by one when
- // computing the hash because, in the generated code, there
- // will be an extra empty slot at register 0.
- size_t index = ((i+1) + (RegNo[RJ]+1) * 37) & (AliasesHashTableSize-1);
- unsigned ProbeAmt = 2;
- while (AliasesHashTable[index*2] != ~0U &&
- AliasesHashTable[index*2+1] != ~0U) {
- index = (index + ProbeAmt) & (AliasesHashTableSize-1);
- ProbeAmt += 2;
-
- hashMisses++;
- }
-
- AliasesHashTable[index*2] = i;
- AliasesHashTable[index*2+1] = RegNo[RJ];
- }
- }
-
- OS << "\n\n // Number of hash collisions: " << hashMisses << "\n";
-
- if (AliasesHashTableSize) {
- std::string Namespace = Regs[0].TheDef->getValueAsString("Namespace");
-
- OS << " const unsigned AliasesHashTable[] = { ";
- for (unsigned i = 0; i < AliasesHashTableSize - 1; ++i) {
- if (i != 0)
- // Insert spaces for nice formatting.
- OS << " ";
-
- if (AliasesHashTable[2*i] != ~0U) {
- OS << getQualifiedName(Regs[AliasesHashTable[2*i]].TheDef) << ", "
- << getQualifiedName(Regs[AliasesHashTable[2*i+1]].TheDef) << ", \n";
- } else {
- OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister, \n";
- }
- }
-
- unsigned Idx = AliasesHashTableSize*2-2;
- if (AliasesHashTable[Idx] != ~0U) {
- OS << " "
- << getQualifiedName(Regs[AliasesHashTable[Idx]].TheDef) << ", "
- << getQualifiedName(Regs[AliasesHashTable[Idx+1]].TheDef) << " };\n";
- } else {
- OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister };\n";
- }
-
- OS << " const unsigned AliasesHashTableSize = "
- << AliasesHashTableSize << ";\n";
- } else {
- OS << " const unsigned AliasesHashTable[] = { ~0U, ~0U };\n"
- << " const unsigned AliasesHashTableSize = 1;\n";
- }
-
- delete [] AliasesHashTable;
-
- if (!RegisterAliases.empty())
- OS << "\n\n // Register Alias Sets...\n";
-
- // Emit the empty alias list
- OS << " const unsigned Empty_AliasSet[] = { 0 };\n";
- // Loop over all of the registers which have aliases, emitting the alias list
- // to memory.
- for (std::map<Record*, std::set<Record*>, LessRecord >::iterator
- I = RegisterAliases.begin(), E = RegisterAliases.end(); I != E; ++I) {
- if (I->second.empty())
- continue;
- OS << " const unsigned " << I->first->getName() << "_AliasSet[] = { ";
- for (std::set<Record*>::iterator ASI = I->second.begin(),
- E = I->second.end(); ASI != E; ++ASI)
- OS << getQualifiedName(*ASI) << ", ";
- OS << "0 };\n";
- }
-
- if (!RegisterSubRegs.empty())
- OS << "\n\n // Register Sub-registers Sets...\n";
-
- // Emit the empty sub-registers list
- OS << " const unsigned Empty_SubRegsSet[] = { 0 };\n";
- // Loop over all of the registers which have sub-registers, emitting the
- // sub-registers list to memory.
- for (std::map<Record*, std::set<Record*>, LessRecord>::iterator
- I = RegisterSubRegs.begin(), E = RegisterSubRegs.end(); I != E; ++I) {
- if (I->second.empty())
- continue;
- OS << " const unsigned " << I->first->getName() << "_SubRegsSet[] = { ";
- std::vector<Record*> SubRegsVector;
- for (std::set<Record*>::iterator ASI = I->second.begin(),
- E = I->second.end(); ASI != E; ++ASI)
- SubRegsVector.push_back(*ASI);
- RegisterSorter RS(RegisterSubRegs);
- std::stable_sort(SubRegsVector.begin(), SubRegsVector.end(), RS);
- for (unsigned i = 0, e = SubRegsVector.size(); i != e; ++i)
- OS << getQualifiedName(SubRegsVector[i]) << ", ";
- OS << "0 };\n";
- }
-
- if (!RegisterSuperRegs.empty())
- OS << "\n\n // Register Super-registers Sets...\n";
-
- // Emit the empty super-registers list
- OS << " const unsigned Empty_SuperRegsSet[] = { 0 };\n";
- // Loop over all of the registers which have super-registers, emitting the
- // super-registers list to memory.
- for (std::map<Record*, std::set<Record*>, LessRecord >::iterator
- I = RegisterSuperRegs.begin(), E = RegisterSuperRegs.end(); I != E; ++I) {
- if (I->second.empty())
- continue;
- OS << " const unsigned " << I->first->getName() << "_SuperRegsSet[] = { ";
-
- std::vector<Record*> SuperRegsVector;
- for (std::set<Record*>::iterator ASI = I->second.begin(),
- E = I->second.end(); ASI != E; ++ASI)
- SuperRegsVector.push_back(*ASI);
- RegisterSorter RS(RegisterSubRegs);
- std::stable_sort(SuperRegsVector.begin(), SuperRegsVector.end(), RS);
- for (unsigned i = 0, e = SuperRegsVector.size(); i != e; ++i)
- OS << getQualifiedName(SuperRegsVector[i]) << ", ";
- OS << "0 };\n";
- }
-
- OS<<"\n const TargetRegisterDesc RegisterDescriptors[] = { // Descriptors\n";
- OS << " { \"NOREG\",\t0,\t0,\t0 },\n";
-
- // Now that register alias and sub-registers sets have been emitted, emit the
- // register descriptors now.
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- const CodeGenRegister &Reg = Regs[i];
- OS << " { \"";
- OS << Reg.getName() << "\",\t";
- if (!RegisterAliases[Reg.TheDef].empty())
- OS << Reg.getName() << "_AliasSet,\t";
- else
- OS << "Empty_AliasSet,\t";
- if (!RegisterSubRegs[Reg.TheDef].empty())
- OS << Reg.getName() << "_SubRegsSet,\t";
- else
- OS << "Empty_SubRegsSet,\t";
- if (!RegisterSuperRegs[Reg.TheDef].empty())
- OS << Reg.getName() << "_SuperRegsSet },\n";
- else
- OS << "Empty_SuperRegsSet },\n";
+ const CodeGenRegister &Reg = *Regs[i];
+ OS << " { ";
+ OS << Reg.CostPerUse << ", "
+ << int(AllocatableRegs.count(Reg.TheDef)) << " },\n";
}
OS << " };\n"; // End of register descriptors...
+
+ // Calculate the mapping of subregister+index pairs to physical registers.
+ // This will also create further anonymous indexes.
+ unsigned NamedIndices = RegBank.getNumNamedIndices();
+
// Emit SubRegIndex names, skipping 0
- const std::vector<Record*> SubRegIndices = Target.getSubRegIndices();
- OS << "\n const char *const SubRegIndexTable[] = { \"";
+ const std::vector<Record*> &SubRegIndices = RegBank.getSubRegIndices();
+ OS << "\n static const char *const " << TargetName
+ << "SubRegIndexTable[] = { \"";
for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) {
OS << SubRegIndices[i]->getName();
if (i+1 != e)
OS << "\", \"";
}
OS << "\" };\n\n";
- OS << "}\n\n"; // End of anonymous namespace...
+
+ // Emit names of the anonymus subreg indexes.
+ if (SubRegIndices.size() > NamedIndices) {
+ OS << " enum {";
+ for (unsigned i = NamedIndices, e = SubRegIndices.size(); i != e; ++i) {
+ OS << "\n " << SubRegIndices[i]->getName() << " = " << i+1;
+ if (i+1 != e)
+ OS << ',';
+ }
+ OS << "\n };\n\n";
+ }
+ OS << "\n";
std::string ClassName = Target.getName() + "GenRegisterInfo";
- // Calculate the mapping of subregister+index pairs to physical registers.
- RegisterMaps RegMaps;
-
// Emit the subregister + index mapping function based on the information
// calculated above.
OS << "unsigned " << ClassName
@@ -916,16 +720,16 @@
<< " switch (RegNo) {\n"
<< " default:\n return 0;\n";
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- RegisterMaps::SubRegMap &SRM = RegMaps.inferSubRegIndices(Regs[i].TheDef);
+ const CodeGenRegister::SubRegMap &SRM = Regs[i]->getSubRegs();
if (SRM.empty())
continue;
- OS << " case " << getQualifiedName(Regs[i].TheDef) << ":\n";
+ OS << " case " << getQualifiedName(Regs[i]->TheDef) << ":\n";
OS << " switch (Index) {\n";
OS << " default: return 0;\n";
- for (RegisterMaps::SubRegMap::const_iterator ii = SRM.begin(),
+ for (CodeGenRegister::SubRegMap::const_iterator ii = SRM.begin(),
ie = SRM.end(); ii != ie; ++ii)
OS << " case " << getQualifiedName(ii->first)
- << ": return " << getQualifiedName(ii->second) << ";\n";
+ << ": return " << getQualifiedName(ii->second->TheDef) << ";\n";
OS << " };\n" << " break;\n";
}
OS << " };\n";
@@ -937,13 +741,13 @@
<< " switch (RegNo) {\n"
<< " default:\n return 0;\n";
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- RegisterMaps::SubRegMap &SRM = RegMaps.SubReg[Regs[i].TheDef];
+ const CodeGenRegister::SubRegMap &SRM = Regs[i]->getSubRegs();
if (SRM.empty())
continue;
- OS << " case " << getQualifiedName(Regs[i].TheDef) << ":\n";
- for (RegisterMaps::SubRegMap::const_iterator ii = SRM.begin(),
+ OS << " case " << getQualifiedName(Regs[i]->TheDef) << ":\n";
+ for (CodeGenRegister::SubRegMap::const_iterator ii = SRM.begin(),
ie = SRM.end(); ii != ie; ++ii)
- OS << " if (SubRegNo == " << getQualifiedName(ii->second)
+ OS << " if (SubRegNo == " << getQualifiedName(ii->second->TheDef)
<< ") return " << getQualifiedName(ii->first) << ";\n";
OS << " return 0;\n";
}
@@ -952,7 +756,6 @@
OS << "}\n\n";
// Emit composeSubRegIndices
- RegMaps.computeComposites();
OS << "unsigned " << ClassName
<< "::composeSubRegIndices(unsigned IdxA, unsigned IdxB) const {\n"
<< " switch (IdxA) {\n"
@@ -960,8 +763,8 @@
for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) {
bool Open = false;
for (unsigned j = 0; j != e; ++j) {
- if (Record *Comp = RegMaps.Composite.lookup(
- std::make_pair(SubRegIndices[i], SubRegIndices[j]))) {
+ if (Record *Comp = RegBank.getCompositeSubRegIndex(SubRegIndices[i],
+ SubRegIndices[j])) {
if (!Open) {
OS << " case " << getQualifiedName(SubRegIndices[i])
<< ": switch(IdxB) {\n default: return IdxB;\n";
@@ -976,70 +779,71 @@
}
OS << " }\n}\n\n";
- // Emit the constructor of the class...
- OS << ClassName << "::" << ClassName
- << "(int CallFrameSetupOpcode, int CallFrameDestroyOpcode)\n"
- << " : TargetRegisterInfo(RegisterDescriptors, " << Regs.size()+1
- << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n"
- << " SubRegIndexTable,\n"
- << " CallFrameSetupOpcode, CallFrameDestroyOpcode,\n"
- << " SubregHashTable, SubregHashTableSize,\n"
- << " AliasesHashTable, AliasesHashTableSize) {\n"
- << "}\n\n";
-
- // Collect all information about dwarf register numbers
-
- // First, just pull all provided information to the map
- unsigned maxLength = 0;
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- Record *Reg = Regs[i].TheDef;
- std::vector<int64_t> RegNums = Reg->getValueAsListOfInts("DwarfNumbers");
- maxLength = std::max((size_t)maxLength, RegNums.size());
- if (DwarfRegNums.count(Reg))
- errs() << "Warning: DWARF numbers for register " << getQualifiedName(Reg)
- << "specified multiple times\n";
- DwarfRegNums[Reg] = RegNums;
- }
-
- // Now we know maximal length of number list. Append -1's, where needed
- for (DwarfRegNumsMapTy::iterator
- I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I)
- for (unsigned i = I->second.size(), e = maxLength; i != e; ++i)
- I->second.push_back(-1);
-
- // Emit information about the dwarf register numbers.
- OS << "int " << ClassName << "::getDwarfRegNumFull(unsigned RegNum, "
- << "unsigned Flavour) const {\n"
- << " switch (Flavour) {\n"
- << " default:\n"
- << " assert(0 && \"Unknown DWARF flavour\");\n"
- << " return -1;\n";
-
- for (unsigned i = 0, e = maxLength; i != e; ++i) {
- OS << " case " << i << ":\n"
- << " switch (RegNum) {\n"
- << " default:\n"
- << " assert(0 && \"Invalid RegNum\");\n"
- << " return -1;\n";
-
- // Sort by name to get a stable order.
-
-
- for (DwarfRegNumsMapTy::iterator
- I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
- int RegNo = I->second[i];
- if (RegNo != -2)
- OS << " case " << getQualifiedName(I->first) << ":\n"
- << " return " << RegNo << ";\n";
- else
- OS << " case " << getQualifiedName(I->first) << ":\n"
- << " assert(0 && \"Invalid register for this mode\");\n"
- << " return -1;\n";
+ // Emit getSubClassWithSubReg.
+ OS << "const TargetRegisterClass *" << ClassName
+ << "::getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx)"
+ " const {\n";
+ if (SubRegIndices.empty()) {
+ OS << " assert(Idx == 0 && \"Target has no sub-registers\");\n"
+ << " return RC;\n";
+ } else {
+ // Use the smallest type that can hold a regclass ID with room for a
+ // sentinel.
+ if (RegisterClasses.size() < UINT8_MAX)
+ OS << " static const uint8_t Table[";
+ else if (RegisterClasses.size() < UINT16_MAX)
+ OS << " static const uint16_t Table[";
+ else
+ throw "Too many register classes.";
+ OS << RegisterClasses.size() << "][" << SubRegIndices.size() << "] = {\n";
+ for (unsigned rci = 0, rce = RegisterClasses.size(); rci != rce; ++rci) {
+ const CodeGenRegisterClass &RC = *RegisterClasses[rci];
+ OS << " {\t// " << RC.getName() << "\n";
+ for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) {
+ Record *Idx = SubRegIndices[sri];
+ if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(Idx))
+ OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx->getName()
+ << " -> " << SRC->getName() << "\n";
+ else
+ OS << " 0,\t// " << Idx->getName() << "\n";
+ }
+ OS << " },\n";
}
- OS << " };\n";
+ OS << " };\n assert(RC && \"Missing regclass\");\n"
+ << " 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";
}
-
- OS << " };\n}\n\n";
+ OS << "}\n\n";
+
+ // Emit the constructor of the class...
+ OS << "extern MCRegisterDesc " << TargetName << "RegDesc[];\n";
+
+ OS << ClassName << "::" << ClassName
+ << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour)\n"
+ << " : TargetRegisterInfo(" << TargetName << "RegInfoDesc"
+ << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n"
+ << " " << TargetName << "SubRegIndexTable) {\n"
+ << " InitMCRegisterInfo(" << TargetName << "RegDesc, "
+ << Regs.size()+1 << ", RA, " << TargetName << "MCRegisterClasses, "
+ << RegisterClasses.size() << ");\n\n";
+
+ EmitRegMapping(OS, Regs, true);
+
+ OS << "}\n\n";
OS << "} // End llvm namespace \n";
+ OS << "#endif // GET_REGINFO_TARGET_DESC\n\n";
+}
+
+void RegisterInfoEmitter::run(raw_ostream &OS) {
+ CodeGenTarget Target(Records);
+ CodeGenRegBank &RegBank = Target.getRegBank();
+ RegBank.computeDerivedInfo();
+
+ runEnums(OS, Target, RegBank);
+ runMCDesc(OS, Target, RegBank);
+ runTargetHeader(OS, Target, RegBank);
+ runTargetDesc(OS, Target, RegBank);
}
diff --git a/src/LLVM/utils/TableGen/RegisterInfoEmitter.h b/src/LLVM/utils/TableGen/RegisterInfoEmitter.h
index 1456b4f..0fd4d07 100644
--- a/src/LLVM/utils/TableGen/RegisterInfoEmitter.h
+++ b/src/LLVM/utils/TableGen/RegisterInfoEmitter.h
@@ -16,23 +16,41 @@
#ifndef REGISTER_INFO_EMITTER_H
#define REGISTER_INFO_EMITTER_H
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <vector>
namespace llvm {
+class CodeGenRegBank;
+struct CodeGenRegister;
+class CodeGenTarget;
+
class RegisterInfoEmitter : public TableGenBackend {
RecordKeeper &Records;
public:
RegisterInfoEmitter(RecordKeeper &R) : Records(R) {}
- // run - Output the register file description, returning true on failure.
+ // runEnums - Print out enum values for all of the registers.
+ void runEnums(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank);
+
+ // runMCDesc - Print out MC register descriptions.
+ void runMCDesc(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank);
+
+ // runTargetHeader - Emit a header fragment for the register info emitter.
+ void runTargetHeader(raw_ostream &o, CodeGenTarget &Target,
+ CodeGenRegBank &Bank);
+
+ // runTargetDesc - Output the target register and register file descriptions.
+ void runTargetDesc(raw_ostream &o, CodeGenTarget &Target,
+ CodeGenRegBank &Bank);
+
+ // run - Output the register file description.
void run(raw_ostream &o);
- // runHeader - Emit a header fragment for the register info emitter.
- void runHeader(raw_ostream &o);
-
- // runEnums - Print out enum values for all of the registers.
- void runEnums(raw_ostream &o);
+private:
+ void EmitRegMapping(raw_ostream &o,
+ const std::vector<CodeGenRegister*> &Regs, bool isCtor);
+ void EmitRegClasses(raw_ostream &OS, CodeGenTarget &Target);
};
} // End llvm namespace
diff --git a/src/LLVM/utils/TableGen/SetTheory.cpp b/src/LLVM/utils/TableGen/SetTheory.cpp
new file mode 100644
index 0000000..bef73f3
--- /dev/null
+++ b/src/LLVM/utils/TableGen/SetTheory.cpp
@@ -0,0 +1,276 @@
+//===- 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/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/Support/Format.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 {
+ void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) {
+ ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts);
+ }
+};
+
+// (sub Add, Sub, ...) Set difference.
+struct SubOp : public SetTheory::Operator {
+ void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) {
+ if (Expr->arg_size() < 2)
+ throw "Set difference needs at least two arguments: " +
+ Expr->getAsString();
+ RecSet Add, Sub;
+ ST.evaluate(*Expr->arg_begin(), Add);
+ ST.evaluate(Expr->arg_begin() + 1, Expr->arg_end(), Sub);
+ 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 {
+ void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) {
+ if (Expr->arg_size() != 2)
+ throw "Set intersection requires two arguments: " + Expr->getAsString();
+ RecSet S1, S2;
+ ST.evaluate(Expr->arg_begin()[0], S1);
+ ST.evaluate(Expr->arg_begin()[1], S2);
+ 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) =0;
+
+ void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) {
+ if (Expr->arg_size() != 2)
+ throw "Operator requires (Op Set, Int) arguments: " + Expr->getAsString();
+ RecSet Set;
+ ST.evaluate(Expr->arg_begin()[0], Set);
+ IntInit *II = dynamic_cast<IntInit*>(Expr->arg_begin()[1]);
+ if (!II)
+ throw "Second argument must be an integer: " + Expr->getAsString();
+ apply2(ST, Expr, Set, II->getValue(), Elts);
+ }
+};
+
+// (shl S, N) Shift left, remove the first N elements.
+struct ShlOp : public SetIntBinOp {
+ void apply2(SetTheory &ST, DagInit *Expr,
+ RecSet &Set, int64_t N,
+ RecSet &Elts) {
+ if (N < 0)
+ throw "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 {
+ void apply2(SetTheory &ST, DagInit *Expr,
+ RecSet &Set, int64_t N,
+ RecSet &Elts) {
+ if (N < 0)
+ throw "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) {}
+
+ void apply2(SetTheory &ST, DagInit *Expr,
+ RecSet &Set, int64_t N,
+ RecSet &Elts) {
+ 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 {
+ void apply2(SetTheory &ST, DagInit *Expr,
+ RecSet &Set, int64_t N,
+ RecSet &Elts) {
+ if (N <= 0)
+ throw "Positive stride required: " + Expr->getAsString();
+ for (unsigned I = 0; I < Set.size(); I += N)
+ Elts.insert(Set[I]);
+ }
+};
+
+// (sequence "Format", From, To) Generate a sequence of records by name.
+struct SequenceOp : public SetTheory::Operator {
+ void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts) {
+ if (Expr->arg_size() != 3)
+ throw "Bad args to (sequence \"Format\", From, To): " +
+ Expr->getAsString();
+ std::string Format;
+ if (StringInit *SI = dynamic_cast<StringInit*>(Expr->arg_begin()[0]))
+ Format = SI->getValue();
+ else
+ throw "Format must be a string: " + Expr->getAsString();
+
+ int64_t From, To;
+ if (IntInit *II = dynamic_cast<IntInit*>(Expr->arg_begin()[1]))
+ From = II->getValue();
+ else
+ throw "From must be an integer: " + Expr->getAsString();
+ if (From < 0 || From >= (1 << 30))
+ throw "From out of range";
+
+ if (IntInit *II = dynamic_cast<IntInit*>(Expr->arg_begin()[2]))
+ To = II->getValue();
+ else
+ throw "From must be an integer: " + Expr->getAsString();
+ if (To < 0 || To >= (1 << 30))
+ throw "To out of range";
+
+ RecordKeeper &Records =
+ dynamic_cast<DefInit&>(*Expr->getOperator()).getDef()->getRecords();
+
+ int Step = From <= To ? 1 : -1;
+ for (To += Step; From != To; From += Step) {
+ std::string Name;
+ raw_string_ostream OS(Name);
+ OS << format(Format.c_str(), unsigned(From));
+ Record *Rec = Records.getDef(OS.str());
+ if (!Rec)
+ throw "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);
+ }
+ }
+};
+
+// Expand a Def into a set by evaluating one of its fields.
+struct FieldExpander : public SetTheory::Expander {
+ StringRef FieldName;
+
+ FieldExpander(StringRef fn) : FieldName(fn) {}
+
+ void expand(SetTheory &ST, Record *Def, RecSet &Elts) {
+ ST.evaluate(Def->getValueInit(FieldName), Elts);
+ }
+};
+} // end anonymous namespace
+
+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("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) {
+ // A def in a list can be a just an element, or it may expand.
+ if (DefInit *Def = dynamic_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 = dynamic_cast<ListInit*>(Expr))
+ return evaluate(LI->begin(), LI->end(), Elts);
+
+ // Anything else must be a DAG.
+ DagInit *DagExpr = dynamic_cast<DagInit*>(Expr);
+ if (!DagExpr)
+ throw "Invalid set element: " + Expr->getAsString();
+ DefInit *OpInit = dynamic_cast<DefInit*>(DagExpr->getOperator());
+ if (!OpInit)
+ throw "Bad set expression: " + Expr->getAsString();
+ Operator *Op = Operators.lookup(OpInit->getDef()->getName());
+ if (!Op)
+ throw "Unknown set operator: " + Expr->getAsString();
+ Op->apply(*this, DagExpr, Elts);
+}
+
+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.
+ try {
+ const std::vector<Record*> &SC = Set->getSuperClasses();
+ for (unsigned i = 0, e = SC.size(); i != e; ++i)
+ 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;
+ }
+ } catch (const std::string &Error) {
+ throw TGError(Set->getLoc(), Error);
+ }
+
+ // Set is not expandable.
+ return 0;
+}
+
diff --git a/src/LLVM/utils/TableGen/SetTheory.h b/src/LLVM/utils/TableGen/SetTheory.h
new file mode 100644
index 0000000..6e8313b
--- /dev/null
+++ b/src/LLVM/utils/TableGen/SetTheory.h
@@ -0,0 +1,136 @@
+//===- 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/StringMap.h"
+#include "llvm/ADT/SetVector.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.
+ struct Operator {
+ virtual ~Operator() {}
+
+ /// apply - Apply this operator to Expr's arguments and insert the result
+ /// in Elts.
+ virtual void apply(SetTheory&, DagInit *Expr, RecSet &Elts) =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.
+ struct Expander {
+ 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);
+
+ /// evaluate - Evaluate a sequence of Inits and append to Elts.
+ template<typename Iter>
+ void evaluate(Iter begin, Iter end, RecSet &Elts) {
+ while (begin != end)
+ evaluate(*begin++, Elts);
+ }
+
+ /// 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/src/LLVM/utils/TableGen/StringMatcher.cpp b/src/LLVM/utils/TableGen/StringMatcher.cpp
new file mode 100644
index 0000000..6aedcbf
--- /dev/null
+++ b/src/LLVM/utils/TableGen/StringMatcher.cpp
@@ -0,0 +1,149 @@
+//===- StringMatcher.cpp - Generate a matcher for input strings -----------===//
+//
+// 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 StringMatcher class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "StringMatcher.h"
+#include "llvm/Support/raw_ostream.h"
+#include <map>
+using namespace llvm;
+
+/// FindFirstNonCommonLetter - Find the first character in the keys of the
+/// string pairs that is not shared across the whole set of strings. All
+/// strings are assumed to have the same length.
+static unsigned
+FindFirstNonCommonLetter(const std::vector<const
+ StringMatcher::StringPair*> &Matches) {
+ assert(!Matches.empty());
+ for (unsigned i = 0, e = Matches[0]->first.size(); i != e; ++i) {
+ // Check to see if letter i is the same across the set.
+ char Letter = Matches[0]->first[i];
+
+ for (unsigned str = 0, e = Matches.size(); str != e; ++str)
+ if (Matches[str]->first[i] != Letter)
+ return i;
+ }
+
+ return Matches[0]->first.size();
+}
+
+/// EmitStringMatcherForChar - Given a set of strings that are known to be the
+/// same length and whose characters leading up to CharNo are the same, emit
+/// code to verify that CharNo and later are the same.
+///
+/// \return - True if control can leave the emitted code fragment.
+bool StringMatcher::
+EmitStringMatcherForChar(const std::vector<const StringPair*> &Matches,
+ unsigned CharNo, unsigned IndentCount) const {
+ assert(!Matches.empty() && "Must have at least one string to match!");
+ std::string Indent(IndentCount*2+4, ' ');
+
+ // If we have verified that the entire string matches, we're done: output the
+ // matching code.
+ if (CharNo == Matches[0]->first.size()) {
+ assert(Matches.size() == 1 && "Had duplicate keys to match on");
+
+ // If the to-execute code has \n's in it, indent each subsequent line.
+ StringRef Code = Matches[0]->second;
+
+ std::pair<StringRef, StringRef> Split = Code.split('\n');
+ OS << Indent << Split.first << "\t // \"" << Matches[0]->first << "\"\n";
+
+ Code = Split.second;
+ while (!Code.empty()) {
+ Split = Code.split('\n');
+ OS << Indent << Split.first << "\n";
+ Code = Split.second;
+ }
+ return false;
+ }
+
+ // Bucket the matches by the character we are comparing.
+ std::map<char, std::vector<const StringPair*> > MatchesByLetter;
+
+ for (unsigned i = 0, e = Matches.size(); i != e; ++i)
+ MatchesByLetter[Matches[i]->first[CharNo]].push_back(Matches[i]);
+
+
+ // If we have exactly one bucket to match, see how many characters are common
+ // across the whole set and match all of them at once.
+ if (MatchesByLetter.size() == 1) {
+ unsigned FirstNonCommonLetter = FindFirstNonCommonLetter(Matches);
+ unsigned NumChars = FirstNonCommonLetter-CharNo;
+
+ // Emit code to break out if the prefix doesn't match.
+ if (NumChars == 1) {
+ // Do the comparison with if (Str[1] != 'f')
+ // FIXME: Need to escape general characters.
+ OS << Indent << "if (" << StrVariableName << "[" << CharNo << "] != '"
+ << Matches[0]->first[CharNo] << "')\n";
+ OS << Indent << " break;\n";
+ } else {
+ // Do the comparison with if (Str.substr(1, 3) != "foo").
+ // FIXME: Need to escape general strings.
+ OS << Indent << "if (" << StrVariableName << ".substr(" << CharNo << ", "
+ << NumChars << ") != \"";
+ OS << Matches[0]->first.substr(CharNo, NumChars) << "\")\n";
+ OS << Indent << " break;\n";
+ }
+
+ return EmitStringMatcherForChar(Matches, FirstNonCommonLetter, IndentCount);
+ }
+
+ // Otherwise, we have multiple possible things, emit a switch on the
+ // character.
+ OS << Indent << "switch (" << StrVariableName << "[" << CharNo << "]) {\n";
+ OS << Indent << "default: break;\n";
+
+ for (std::map<char, std::vector<const StringPair*> >::iterator LI =
+ MatchesByLetter.begin(), E = MatchesByLetter.end(); LI != E; ++LI) {
+ // TODO: escape hard stuff (like \n) if we ever care about it.
+ OS << Indent << "case '" << LI->first << "':\t // "
+ << LI->second.size() << " string";
+ if (LI->second.size() != 1) OS << 's';
+ OS << " to match.\n";
+ if (EmitStringMatcherForChar(LI->second, CharNo+1, IndentCount+1))
+ OS << Indent << " break;\n";
+ }
+
+ OS << Indent << "}\n";
+ return true;
+}
+
+
+/// Emit - Top level entry point.
+///
+void StringMatcher::Emit(unsigned Indent) const {
+ // If nothing to match, just fall through.
+ if (Matches.empty()) return;
+
+ // First level categorization: group strings by length.
+ std::map<unsigned, std::vector<const StringPair*> > MatchesByLength;
+
+ for (unsigned i = 0, e = Matches.size(); i != e; ++i)
+ MatchesByLength[Matches[i].first.size()].push_back(&Matches[i]);
+
+ // Output a switch statement on length and categorize the elements within each
+ // bin.
+ OS.indent(Indent*2+2) << "switch (" << StrVariableName << ".size()) {\n";
+ OS.indent(Indent*2+2) << "default: break;\n";
+
+ for (std::map<unsigned, std::vector<const StringPair*> >::iterator LI =
+ MatchesByLength.begin(), E = MatchesByLength.end(); LI != E; ++LI) {
+ OS.indent(Indent*2+2) << "case " << LI->first << ":\t // "
+ << LI->second.size()
+ << " string" << (LI->second.size() == 1 ? "" : "s") << " to match.\n";
+ if (EmitStringMatcherForChar(LI->second, 0, Indent))
+ OS.indent(Indent*2+4) << "break;\n";
+ }
+
+ OS.indent(Indent*2+2) << "}\n";
+}
diff --git a/src/LLVM/utils/TableGen/StringMatcher.h b/src/LLVM/utils/TableGen/StringMatcher.h
new file mode 100644
index 0000000..1dadc76
--- /dev/null
+++ b/src/LLVM/utils/TableGen/StringMatcher.h
@@ -0,0 +1,54 @@
+//===- StringMatcher.h - Generate a matcher for input strings ---*- 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 StringMatcher class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef STRINGMATCHER_H
+#define STRINGMATCHER_H
+
+#include <vector>
+#include <string>
+#include <utility>
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+ class raw_ostream;
+
+/// StringMatcher - Given a list of strings and code to execute when they match,
+/// output a simple switch tree to classify the input string.
+///
+/// If a match is found, the code in Vals[i].second is executed; control must
+/// not exit this code fragment. If nothing matches, execution falls through.
+///
+class StringMatcher {
+public:
+ typedef std::pair<std::string, std::string> StringPair;
+private:
+ StringRef StrVariableName;
+ const std::vector<StringPair> &Matches;
+ raw_ostream &OS;
+
+public:
+ StringMatcher(StringRef strVariableName,
+ const std::vector<StringPair> &matches, raw_ostream &os)
+ : StrVariableName(strVariableName), Matches(matches), OS(os) {}
+
+ void Emit(unsigned Indent = 0) const;
+
+
+private:
+ bool EmitStringMatcherForChar(const std::vector<const StringPair*> &Matches,
+ unsigned CharNo, unsigned IndentCount) const;
+};
+
+} // end llvm namespace.
+
+#endif
diff --git a/src/LLVM/utils/TableGen/SubtargetEmitter.cpp b/src/LLVM/utils/TableGen/SubtargetEmitter.cpp
index b04eaf8..103a403 100644
--- a/src/LLVM/utils/TableGen/SubtargetEmitter.cpp
+++ b/src/LLVM/utils/TableGen/SubtargetEmitter.cpp
@@ -13,7 +13,7 @@
#include "SubtargetEmitter.h"
#include "CodeGenTarget.h"
-#include "Record.h"
+#include "llvm/TableGen/Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/Debug.h"
#include <algorithm>
@@ -29,45 +29,62 @@
std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
std::sort(DefList.begin(), DefList.end(), LessRecord());
+ unsigned N = DefList.size();
+ if (N == 0)
+ return;
+ if (N > 64) {
+ errs() << "Too many (> 64) subtarget features!\n";
+ exit(1);
+ }
+
+ OS << "namespace " << Target << " {\n";
+
// Open enumeration
OS << "enum {\n";
-
+
// For each record
- for (unsigned i = 0, N = DefList.size(); i < N;) {
+ for (unsigned i = 0; i < N;) {
// Next record
Record *Def = DefList[i];
-
+
// Get and emit name
OS << " " << Def->getName();
-
+
// If bit flags then emit expression (1 << i)
- if (isBits) OS << " = " << " 1 << " << i;
+ if (isBits) OS << " = " << " 1ULL << " << i;
// Depending on 'if more in the list' emit comma
if (++i < N) OS << ",";
-
+
OS << "\n";
}
-
+
// Close enumeration
OS << "};\n";
+
+ OS << "}\n";
}
//
// FeatureKeyValues - Emit data of all the subtarget features. Used by the
// command line.
//
-void SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
+unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
// Gather and sort all the features
std::vector<Record*> FeatureList =
Records.getAllDerivedDefinitions("SubtargetFeature");
+
+ if (FeatureList.empty())
+ return 0;
+
std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName());
// Begin feature table
OS << "// Sorted (by key) array of values for CPU features.\n"
- << "static const llvm::SubtargetFeatureKV FeatureKV[] = {\n";
-
+ << "llvm::SubtargetFeatureKV " << Target << "FeatureKV[] = {\n";
+
// For each feature
+ unsigned NumFeatures = 0;
for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) {
// Next feature
Record *Feature = FeatureList[i];
@@ -75,49 +92,47 @@
const std::string &Name = Feature->getName();
const std::string &CommandLineName = Feature->getValueAsString("Name");
const std::string &Desc = Feature->getValueAsString("Desc");
-
+
if (CommandLineName.empty()) continue;
-
+
// Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in }
OS << " { "
<< "\"" << CommandLineName << "\", "
<< "\"" << Desc << "\", "
- << Name << ", ";
+ << Target << "::" << Name << ", ";
- const std::vector<Record*> &ImpliesList =
+ const std::vector<Record*> &ImpliesList =
Feature->getValueAsListOfDefs("Implies");
-
+
if (ImpliesList.empty()) {
- OS << "0";
+ OS << "0ULL";
} else {
for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
- OS << ImpliesList[j]->getName();
+ OS << Target << "::" << ImpliesList[j]->getName();
if (++j < M) OS << " | ";
}
}
OS << " }";
-
+ ++NumFeatures;
+
// Depending on 'if more in the list' emit comma
if ((i + 1) < N) OS << ",";
-
+
OS << "\n";
}
-
+
// End feature table
OS << "};\n";
- // Emit size of table
- OS<<"\nenum {\n";
- OS<<" FeatureKVSize = sizeof(FeatureKV)/sizeof(llvm::SubtargetFeatureKV)\n";
- OS<<"};\n";
+ return NumFeatures;
}
//
// CPUKeyValues - Emit data of all the subtarget processors. Used by command
// line.
//
-void SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
+unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
// Gather and sort processor information
std::vector<Record*> ProcessorList =
Records.getAllDerivedDefinitions("Processor");
@@ -125,60 +140,54 @@
// Begin processor table
OS << "// Sorted (by key) array of values for CPU subtype.\n"
- << "static const llvm::SubtargetFeatureKV SubTypeKV[] = {\n";
-
+ << "llvm::SubtargetFeatureKV " << Target << "SubTypeKV[] = {\n";
+
// For each processor
for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
// Next processor
Record *Processor = ProcessorList[i];
const std::string &Name = Processor->getValueAsString("Name");
- const std::vector<Record*> &FeatureList =
+ const std::vector<Record*> &FeatureList =
Processor->getValueAsListOfDefs("Features");
-
+
// Emit as { "cpu", "description", f1 | f2 | ... fn },
OS << " { "
<< "\"" << Name << "\", "
<< "\"Select the " << Name << " processor\", ";
-
+
if (FeatureList.empty()) {
- OS << "0";
+ OS << "0ULL";
} else {
for (unsigned j = 0, M = FeatureList.size(); j < M;) {
- OS << FeatureList[j]->getName();
+ OS << Target << "::" << FeatureList[j]->getName();
if (++j < M) OS << " | ";
}
}
-
+
// The "0" is for the "implies" section of this data structure.
- OS << ", 0 }";
-
+ OS << ", 0ULL }";
+
// Depending on 'if more in the list' emit comma
if (++i < N) OS << ",";
-
+
OS << "\n";
}
-
+
// End processor table
OS << "};\n";
- // Emit size of table
- OS<<"\nenum {\n";
- OS<<" SubTypeKVSize = sizeof(SubTypeKV)/sizeof(llvm::SubtargetFeatureKV)\n";
- OS<<"};\n";
+ return ProcessorList.size();
}
//
// CollectAllItinClasses - Gathers and enumerates all the itinerary classes.
// Returns itinerary class count.
//
-unsigned SubtargetEmitter::CollectAllItinClasses(raw_ostream &OS,
- std::map<std::string, unsigned> &ItinClassesMap) {
- // Gather and sort all itinerary classes
- std::vector<Record*> ItinClassList =
- Records.getAllDerivedDefinitions("InstrItinClass");
- std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord());
-
+unsigned SubtargetEmitter::
+CollectAllItinClasses(raw_ostream &OS,
+ std::map<std::string, unsigned> &ItinClassesMap,
+ std::vector<Record*> &ItinClassList) {
// For each itinerary class
unsigned N = ItinClassList.size();
for (unsigned i = 0; i < N; i++) {
@@ -188,11 +197,6 @@
// Assign itinerary class a unique number
ItinClassesMap[ItinClass->getName()] = i;
}
-
- // Emit size of table
- OS<<"\nenum {\n";
- OS<<" ItinClassesSize = " << N << "\n";
- OS<<"};\n";
// Return itinerary class count
return N;
@@ -216,21 +220,21 @@
for (unsigned i = 0; i < N;) {
// Next stage
const Record *Stage = StageList[i];
-
+
// Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind }
int Cycles = Stage->getValueAsInt("Cycles");
ItinString += " { " + itostr(Cycles) + ", ";
-
+
// Get unit list
const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units");
-
+
// For each unit
for (unsigned j = 0, M = UnitList.size(); j < M;) {
// Add name and bitwise or
ItinString += Name + "FU::" + UnitList[j]->getName();
if (++j < M) ItinString += " | ";
}
-
+
int TimeInc = Stage->getValueAsInt("TimeInc");
ItinString += ", " + itostr(TimeInc);
@@ -259,24 +263,43 @@
for (unsigned i = 0; i < N;) {
// Next operand cycle
const int OCycle = OperandCycleList[i];
-
+
ItinString += " " + itostr(OCycle);
if (++i < N) ItinString += ", ";
}
}
+void SubtargetEmitter::FormItineraryBypassString(const std::string &Name,
+ Record *ItinData,
+ std::string &ItinString,
+ unsigned NOperandCycles) {
+ const std::vector<Record*> &BypassList =
+ ItinData->getValueAsListOfDefs("Bypasses");
+ unsigned N = BypassList.size();
+ unsigned i = 0;
+ for (; i < N;) {
+ ItinString += Name + "Bypass::" + BypassList[i]->getName();
+ if (++i < NOperandCycles) ItinString += ", ";
+ }
+ for (; i < NOperandCycles;) {
+ ItinString += " 0";
+ if (++i < NOperandCycles) ItinString += ", ";
+ }
+}
+
//
// EmitStageAndOperandCycleData - Generate unique itinerary stages and
// operand cycle tables. Record itineraries for processors.
//
void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS,
unsigned NItinClasses,
- std::map<std::string, unsigned> &ItinClassesMap,
+ std::map<std::string, unsigned> &ItinClassesMap,
+ std::vector<Record*> &ItinClassList,
std::vector<std::vector<InstrItinerary> > &ProcList) {
// Gather processor iteraries
std::vector<Record*> ProcItinList =
Records.getAllDerivedDefinitions("ProcessorItineraries");
-
+
// If just no itinerary then don't bother
if (ProcItinList.size() < 2) return;
@@ -298,41 +321,59 @@
<< " = 1 << " << j << ";\n";
OS << "}\n";
+
+ std::vector<Record*> BPs = Proc->getValueAsListOfDefs("BP");
+ if (BPs.size()) {
+ OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
+ << "\"\n" << "namespace " << Name << "Bypass {\n";
+
+ OS << " unsigned NoBypass = 0;\n";
+ for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j)
+ OS << " unsigned " << BPs[j]->getName()
+ << " = 1 << " << j << ";\n";
+
+ OS << "}\n";
+ }
}
// Begin stages table
- std::string StageTable = "\nstatic const llvm::InstrStage Stages[] = {\n";
+ std::string StageTable = "\nllvm::InstrStage " + Target + "Stages[] = {\n";
StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
-
+
// Begin operand cycle table
- std::string OperandCycleTable = "static const unsigned OperandCycles[] = {\n";
+ std::string OperandCycleTable = "unsigned " + Target +
+ "OperandCycles[] = {\n";
OperandCycleTable += " 0, // No itinerary\n";
-
+
+ // Begin pipeline bypass table
+ std::string BypassTable = "unsigned " + Target +
+ "ForwardingPathes[] = {\n";
+ BypassTable += " 0, // No itinerary\n";
+
unsigned StageCount = 1, OperandCycleCount = 1;
- unsigned ItinStageEnum = 1, ItinOperandCycleEnum = 1;
- std::map<std::string, unsigned> ItinStageMap, ItinOperandCycleMap;
+ std::map<std::string, unsigned> ItinStageMap, ItinOperandMap;
for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) {
// Next record
Record *Proc = ProcItinList[i];
-
+
// Get processor itinerary name
const std::string &Name = Proc->getName();
-
+
// Skip default
if (Name == "NoItineraries") continue;
-
+
// Create and expand processor itinerary to cover all itinerary classes
std::vector<InstrItinerary> ItinList;
ItinList.resize(NItinClasses);
-
+
// Get itinerary data list
std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID");
-
+
// For each itinerary data
for (unsigned j = 0, M = ItinDataList.size(); j < M; j++) {
// Next itinerary data
Record *ItinData = ItinDataList[j];
-
+
// Get string and stage count
std::string ItinStageString;
unsigned NStages;
@@ -344,52 +385,66 @@
FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
NOperandCycles);
+ std::string ItinBypassString;
+ FormItineraryBypassString(Name, ItinData, ItinBypassString,
+ NOperandCycles);
+
// Check to see if stage already exists and create if it doesn't
unsigned FindStage = 0;
if (NStages > 0) {
FindStage = ItinStageMap[ItinStageString];
if (FindStage == 0) {
- // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // index
- StageTable += ItinStageString + ", // " + itostr(ItinStageEnum) + "\n";
+ // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices
+ StageTable += ItinStageString + ", // " + itostr(StageCount);
+ if (NStages > 1)
+ StageTable += "-" + itostr(StageCount + NStages - 1);
+ StageTable += "\n";
// Record Itin class number.
ItinStageMap[ItinStageString] = FindStage = StageCount;
StageCount += NStages;
- ItinStageEnum++;
}
}
-
+
// Check to see if operand cycle already exists and create if it doesn't
unsigned FindOperandCycle = 0;
if (NOperandCycles > 0) {
- FindOperandCycle = ItinOperandCycleMap[ItinOperandCycleString];
+ std::string ItinOperandString = ItinOperandCycleString+ItinBypassString;
+ FindOperandCycle = ItinOperandMap[ItinOperandString];
if (FindOperandCycle == 0) {
// Emit as cycle, // index
- OperandCycleTable += ItinOperandCycleString + ", // " +
- itostr(ItinOperandCycleEnum) + "\n";
+ OperandCycleTable += ItinOperandCycleString + ", // ";
+ std::string OperandIdxComment = itostr(OperandCycleCount);
+ if (NOperandCycles > 1)
+ OperandIdxComment += "-"
+ + itostr(OperandCycleCount + NOperandCycles - 1);
+ OperandCycleTable += OperandIdxComment + "\n";
// Record Itin class number.
- ItinOperandCycleMap[ItinOperandCycleString] =
+ ItinOperandMap[ItinOperandCycleString] =
FindOperandCycle = OperandCycleCount;
+ // Emit as bypass, // index
+ BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n";
OperandCycleCount += NOperandCycles;
- ItinOperandCycleEnum++;
}
}
-
- // Set up itinerary as location and location + stage count
- InstrItinerary Intinerary = { FindStage, FindStage + NStages,
- FindOperandCycle, FindOperandCycle + NOperandCycles};
// Locate where to inject into processor itinerary table
const std::string &Name = ItinData->getValueAsDef("TheClass")->getName();
unsigned Find = ItinClassesMap[Name];
-
+
+ // Set up itinerary as location and location + stage count
+ unsigned NumUOps = ItinClassList[Find]->getValueAsInt("NumMicroOps");
+ InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages,
+ FindOperandCycle,
+ FindOperandCycle + NOperandCycles};
+
// Inject - empty slots will be 0, 0
ItinList[Find] = Intinerary;
}
-
+
// Add process itinerary to list
ProcList.push_back(ItinList);
}
-
+
// Closing stage
StageTable += " { 0, 0, 0, llvm::InstrStage::Required } // End itinerary\n";
StageTable += "};\n";
@@ -398,26 +453,26 @@
OperandCycleTable += " 0 // End itinerary\n";
OperandCycleTable += "};\n";
+ BypassTable += " 0 // End itinerary\n";
+ BypassTable += "};\n";
+
// Emit tables.
OS << StageTable;
OS << OperandCycleTable;
-
- // Emit size of tables
- OS<<"\nenum {\n";
- OS<<" StagesSize = sizeof(Stages)/sizeof(llvm::InstrStage),\n";
- OS<<" OperandCyclesSize = sizeof(OperandCycles)/sizeof(unsigned)\n";
- OS<<"};\n";
+ OS << BypassTable;
}
//
// EmitProcessorData - Generate data for processor itineraries.
//
-void SubtargetEmitter::EmitProcessorData(raw_ostream &OS,
- std::vector<std::vector<InstrItinerary> > &ProcList) {
+void SubtargetEmitter::
+EmitProcessorData(raw_ostream &OS,
+ std::vector<Record*> &ItinClassList,
+ std::vector<std::vector<InstrItinerary> > &ProcList) {
// Get an iterator for processor itinerary stages
std::vector<std::vector<InstrItinerary> >::iterator
ProcListIter = ProcList.begin();
-
+
// For each processor itinerary
std::vector<Record*> Itins =
Records.getAllDerivedDefinitions("ProcessorItineraries");
@@ -427,35 +482,38 @@
// Get processor itinerary name
const std::string &Name = Itin->getName();
-
+
// Skip default
if (Name == "NoItineraries") continue;
// Begin processor itinerary table
OS << "\n";
- OS << "static const llvm::InstrItinerary " << Name << "[] = {\n";
-
+ OS << "llvm::InstrItinerary " << Name << "[] = {\n";
+
// For each itinerary class
std::vector<InstrItinerary> &ItinList = *ProcListIter++;
+ assert(ItinList.size() == ItinClassList.size() && "bad itinerary");
for (unsigned j = 0, M = ItinList.size(); j < M; ++j) {
InstrItinerary &Intinerary = ItinList[j];
-
- // Emit in the form of
+
+ // Emit in the form of
// { firstStage, lastStage, firstCycle, lastCycle } // index
if (Intinerary.FirstStage == 0) {
- OS << " { 0, 0, 0, 0 }";
+ OS << " { 1, 0, 0, 0, 0 }";
} else {
- OS << " { " << Intinerary.FirstStage << ", " <<
- Intinerary.LastStage << ", " <<
- Intinerary.FirstOperandCycle << ", " <<
+ OS << " { " <<
+ Intinerary.NumMicroOps << ", " <<
+ Intinerary.FirstStage << ", " <<
+ Intinerary.LastStage << ", " <<
+ Intinerary.FirstOperandCycle << ", " <<
Intinerary.LastOperandCycle << " }";
}
-
- OS << ", // " << j << "\n";
+
+ OS << ", // " << j << " " << ItinClassList[j]->getName() << "\n";
}
-
+
// End processor itinerary table
- OS << " { ~0U, ~0U, ~0U, ~0U } // end marker\n";
+ OS << " { 1, ~0U, ~0U, ~0U, ~0U } // end marker\n";
OS << "};\n";
}
}
@@ -472,8 +530,9 @@
// Begin processor table
OS << "\n";
OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
- << "static const llvm::SubtargetInfoKV ProcItinKV[] = {\n";
-
+ << "llvm::SubtargetInfoKV "
+ << Target << "ProcItinKV[] = {\n";
+
// For each processor
for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
// Next processor
@@ -482,28 +541,22 @@
const std::string &Name = Processor->getValueAsString("Name");
const std::string &ProcItin =
Processor->getValueAsDef("ProcItin")->getName();
-
+
// Emit as { "cpu", procinit },
OS << " { "
<< "\"" << Name << "\", "
<< "(void *)&" << ProcItin;
-
+
OS << " }";
-
+
// Depending on ''if more in the list'' emit comma
if (++i < N) OS << ",";
-
+
OS << "\n";
}
-
+
// End processor table
OS << "};\n";
-
- // Emit size of table
- OS<<"\nenum {\n";
- OS<<" ProcItinKVSize = sizeof(ProcItinKV)/"
- "sizeof(llvm::SubtargetInfoKV)\n";
- OS<<"};\n";
}
//
@@ -511,18 +564,24 @@
//
void SubtargetEmitter::EmitData(raw_ostream &OS) {
std::map<std::string, unsigned> ItinClassesMap;
- std::vector<std::vector<InstrItinerary> > ProcList;
-
+ // Gather and sort all itinerary classes
+ std::vector<Record*> ItinClassList =
+ Records.getAllDerivedDefinitions("InstrItinClass");
+ std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord());
+
// Enumerate all the itinerary classes
- unsigned NItinClasses = CollectAllItinClasses(OS, ItinClassesMap);
+ unsigned NItinClasses = CollectAllItinClasses(OS, ItinClassesMap,
+ ItinClassList);
// Make sure the rest is worth the effort
HasItineraries = NItinClasses != 1; // Ignore NoItinerary.
-
+
if (HasItineraries) {
+ std::vector<std::vector<InstrItinerary> > ProcList;
// Emit the stage data
- EmitStageAndOperandCycleData(OS, NItinClasses, ItinClassesMap, ProcList);
+ EmitStageAndOperandCycleData(OS, NItinClasses, ItinClassesMap,
+ ItinClassList, ProcList);
// Emit the processor itinerary data
- EmitProcessorData(OS, ProcList);
+ EmitProcessorData(OS, ItinClassList, ProcList);
// Emit the processor lookup data
EmitProcessorLookup(OS);
}
@@ -532,23 +591,27 @@
// ParseFeaturesFunction - Produces a subtarget specific function for parsing
// the subtarget features string.
//
-void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) {
+void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
+ unsigned NumFeatures,
+ unsigned NumProcs) {
std::vector<Record*> Features =
Records.getAllDerivedDefinitions("SubtargetFeature");
std::sort(Features.begin(), Features.end(), LessRecord());
- OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
- << "// subtarget options.\n"
- << "std::string llvm::";
+ OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
+ << "// subtarget options.\n"
+ << "void llvm::";
OS << Target;
- OS << "Subtarget::ParseSubtargetFeatures(const std::string &FS,\n"
- << " const std::string &CPU) {\n"
+ OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n"
<< " DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n"
- << " DEBUG(dbgs() << \"\\nCPU:\" << CPU);\n"
- << " SubtargetFeatures Features(FS);\n"
- << " Features.setCPUIfNone(CPU);\n"
- << " uint32_t Bits = Features.getBits(SubTypeKV, SubTypeKVSize,\n"
- << " FeatureKV, FeatureKVSize);\n";
+ << " DEBUG(dbgs() << \"\\nCPU:\" << CPU);\n";
+
+ if (Features.empty()) {
+ OS << "}\n";
+ return;
+ }
+
+ OS << " uint64_t Bits = ReInitMCSubtargetInfo(CPU, FS);\n";
for (unsigned i = 0; i < Features.size(); i++) {
// Next record
@@ -558,48 +621,135 @@
const std::string &Attribute = R->getValueAsString("Attribute");
if (Value=="true" || Value=="false")
- OS << " if ((Bits & " << Instance << ") != 0) "
+ OS << " if ((Bits & " << Target << "::"
+ << Instance << ") != 0) "
<< Attribute << " = " << Value << ";\n";
else
- OS << " if ((Bits & " << Instance << ") != 0 && " << Attribute <<
- " < " << Value << ") " << Attribute << " = " << Value << ";\n";
+ OS << " if ((Bits & " << Target << "::"
+ << Instance << ") != 0 && "
+ << Attribute << " < " << Value << ") "
+ << Attribute << " = " << Value << ";\n";
}
- if (HasItineraries) {
- OS << "\n"
- << " InstrItinerary *Itinerary = (InstrItinerary *)"
- << "Features.getInfo(ProcItinKV, ProcItinKVSize);\n"
- << " InstrItins = InstrItineraryData(Stages, OperandCycles, Itinerary);\n";
- }
-
- OS << " return Features.getCPU();\n"
- << "}\n";
+ OS << "}\n";
}
//
// SubtargetEmitter::run - Main subtarget enumeration emitter.
//
void SubtargetEmitter::run(raw_ostream &OS) {
- Target = CodeGenTarget().getName();
+ Target = CodeGenTarget(Records).getName();
EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
+ OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
+ OS << "#undef GET_SUBTARGETINFO_ENUM\n";
+
+ OS << "namespace llvm {\n";
+ Enumeration(OS, "SubtargetFeature", true);
+ OS << "} // End llvm namespace \n";
+ OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
+
+ OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
+ OS << "#undef GET_SUBTARGETINFO_MC_DESC\n";
+
+ OS << "namespace llvm {\n";
+#if 0
+ OS << "namespace {\n";
+#endif
+ unsigned NumFeatures = FeatureKeyValues(OS);
+ OS << "\n";
+ unsigned NumProcs = CPUKeyValues(OS);
+ OS << "\n";
+ EmitData(OS);
+ OS << "\n";
+#if 0
+ OS << "}\n";
+#endif
+
+ // MCInstrInfo initialization routine.
+ OS << "static inline void Init" << Target
+ << "MCSubtargetInfo(MCSubtargetInfo *II, "
+ << "StringRef TT, StringRef CPU, StringRef FS) {\n";
+ OS << " II->InitMCSubtargetInfo(TT, CPU, FS, ";
+ if (NumFeatures)
+ OS << Target << "FeatureKV, ";
+ else
+ OS << "0, ";
+ if (NumProcs)
+ OS << Target << "SubTypeKV, ";
+ else
+ OS << "0, ";
+ if (HasItineraries) {
+ OS << Target << "ProcItinKV, "
+ << Target << "Stages, "
+ << Target << "OperandCycles, "
+ << Target << "ForwardingPathes, ";
+ } else
+ OS << "0, 0, 0, 0, ";
+ OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
+
+ OS << "} // End llvm namespace \n";
+
+ OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n";
+
+ OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n";
+ OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n";
+
OS << "#include \"llvm/Support/Debug.h\"\n";
OS << "#include \"llvm/Support/raw_ostream.h\"\n";
- OS << "#include \"llvm/Target/SubtargetFeature.h\"\n";
- OS << "#include \"llvm/Target/TargetInstrItineraries.h\"\n\n";
+ ParseFeaturesFunction(OS, NumFeatures, NumProcs);
-// Enumeration(OS, "FuncUnit", true);
-// OS<<"\n";
-// Enumeration(OS, "InstrItinClass", false);
-// OS<<"\n";
- Enumeration(OS, "SubtargetFeature", true);
- OS<<"\n";
- FeatureKeyValues(OS);
- OS<<"\n";
- CPUKeyValues(OS);
- OS<<"\n";
- EmitData(OS);
- OS<<"\n";
- ParseFeaturesFunction(OS);
+ OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n";
+
+ // Create a TargetSubtargetInfo subclass to hide the MC layer initialization.
+ OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n";
+ OS << "#undef GET_SUBTARGETINFO_HEADER\n";
+
+ std::string ClassName = Target + "GenSubtargetInfo";
+ OS << "namespace llvm {\n";
+ OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n"
+ << " explicit " << ClassName << "(StringRef TT, StringRef CPU, "
+ << "StringRef FS);\n"
+ << "};\n";
+ OS << "} // End llvm namespace \n";
+
+ OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n";
+
+ OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n";
+ OS << "#undef GET_SUBTARGETINFO_CTOR\n";
+
+ OS << "namespace llvm {\n";
+ OS << "extern llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
+ OS << "extern llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n";
+ if (HasItineraries) {
+ OS << "extern llvm::SubtargetInfoKV " << Target << "ProcItinKV[];\n";
+ OS << "extern llvm::InstrStage " << Target << "Stages[];\n";
+ OS << "extern unsigned " << Target << "OperandCycles[];\n";
+ OS << "extern unsigned " << Target << "ForwardingPathes[];\n";
+ }
+
+ OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, "
+ << "StringRef FS)\n"
+ << " : TargetSubtargetInfo() {\n"
+ << " InitMCSubtargetInfo(TT, CPU, FS, ";
+ if (NumFeatures)
+ OS << Target << "FeatureKV, ";
+ else
+ OS << "0, ";
+ if (NumProcs)
+ OS << Target << "SubTypeKV, ";
+ else
+ OS << "0, ";
+ if (HasItineraries) {
+ OS << Target << "ProcItinKV, "
+ << Target << "Stages, "
+ << Target << "OperandCycles, "
+ << Target << "ForwardingPathes, ";
+ } else
+ OS << "0, 0, 0, 0, ";
+ OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
+ OS << "} // End llvm namespace \n";
+
+ OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
}
diff --git a/src/LLVM/utils/TableGen/SubtargetEmitter.h b/src/LLVM/utils/TableGen/SubtargetEmitter.h
index f43a443..ff01274 100644
--- a/src/LLVM/utils/TableGen/SubtargetEmitter.h
+++ b/src/LLVM/utils/TableGen/SubtargetEmitter.h
@@ -14,8 +14,8 @@
#ifndef SUBTARGET_EMITTER_H
#define SUBTARGET_EMITTER_H
-#include "TableGenBackend.h"
-#include "llvm/Target/TargetInstrItineraries.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include "llvm/MC/MCInstrItineraries.h"
#include <vector>
#include <map>
#include <string>
@@ -24,30 +24,37 @@
namespace llvm {
class SubtargetEmitter : public TableGenBackend {
-
+
RecordKeeper &Records;
std::string Target;
bool HasItineraries;
-
+
void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits);
- void FeatureKeyValues(raw_ostream &OS);
- void CPUKeyValues(raw_ostream &OS);
+ unsigned FeatureKeyValues(raw_ostream &OS);
+ unsigned CPUKeyValues(raw_ostream &OS);
unsigned CollectAllItinClasses(raw_ostream &OS,
- std::map<std::string, unsigned> &ItinClassesMap);
+ std::map<std::string,unsigned> &ItinClassesMap,
+ std::vector<Record*> &ItinClassList);
void FormItineraryStageString(const std::string &Names,
Record *ItinData, std::string &ItinString,
unsigned &NStages);
void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString,
unsigned &NOperandCycles);
+ void FormItineraryBypassString(const std::string &Names,
+ Record *ItinData,
+ std::string &ItinString, unsigned NOperandCycles);
void EmitStageAndOperandCycleData(raw_ostream &OS, unsigned NItinClasses,
std::map<std::string, unsigned> &ItinClassesMap,
+ std::vector<Record*> &ItinClassList,
std::vector<std::vector<InstrItinerary> > &ProcList);
void EmitProcessorData(raw_ostream &OS,
- std::vector<std::vector<InstrItinerary> > &ProcList);
+ std::vector<Record*> &ItinClassList,
+ std::vector<std::vector<InstrItinerary> > &ProcList);
void EmitProcessorLookup(raw_ostream &OS);
void EmitData(raw_ostream &OS);
- void ParseFeaturesFunction(raw_ostream &OS);
-
+ void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures,
+ unsigned NumProcs);
+
public:
SubtargetEmitter(RecordKeeper &R) : Records(R), HasItineraries(false) {}
diff --git a/src/LLVM/utils/TableGen/TGValueTypes.cpp b/src/LLVM/utils/TableGen/TGValueTypes.cpp
index 122d085..af0d9f4 100644
--- a/src/LLVM/utils/TableGen/TGValueTypes.cpp
+++ b/src/LLVM/utils/TableGen/TGValueTypes.cpp
@@ -16,7 +16,6 @@
#include "llvm/CodeGen/ValueTypes.h"
#include <map>
-#include <vector>
using namespace llvm;
namespace llvm {
diff --git a/src/LLVM/utils/TableGen/TableGen.cpp b/src/LLVM/utils/TableGen/TableGen.cpp
index ebd163d..eacfdf6 100644
--- a/src/LLVM/utils/TableGen/TableGen.cpp
+++ b/src/LLVM/utils/TableGen/TableGen.cpp
@@ -1,4 +1,4 @@
-//===- TableGen.cpp - Top-Level TableGen implementation -------------------===//
+//===- TableGen.cpp - Top-Level TableGen implementation for LLVM ----------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,70 +7,55 @@
//
//===----------------------------------------------------------------------===//
//
-// TableGen is a tool which can be used to build up a description of something,
-// then invoke one or more "tablegen backends" to emit information about the
-// description in some predefined format. In practice, this is used by the LLVM
-// code generators to automate generation of a code generator through a
-// high-level description of the target.
+// This file contains the main function for LLVM's TableGen.
//
//===----------------------------------------------------------------------===//
#include "AsmMatcherEmitter.h"
#include "AsmWriterEmitter.h"
#include "CallingConvEmitter.h"
-#include "ClangASTNodesEmitter.h"
-#include "ClangAttrEmitter.h"
-#include "ClangDiagnosticsEmitter.h"
#include "CodeEmitterGen.h"
#include "DAGISelEmitter.h"
#include "DisassemblerEmitter.h"
#include "EDEmitter.h"
#include "FastISelEmitter.h"
-#include "InstrEnumEmitter.h"
#include "InstrInfoEmitter.h"
#include "IntrinsicEmitter.h"
-#include "LLVMCConfigurationEmitter.h"
-#include "NeonEmitter.h"
-#include "OptParserEmitter.h"
-#include "Record.h"
+#include "PseudoLoweringEmitter.h"
#include "RegisterInfoEmitter.h"
#include "ARMDecoderEmitter.h"
#include "SubtargetEmitter.h"
-#include "TGParser.h"
+#include "SetTheory.h"
+
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/System/Signals.h"
-#include <algorithm>
-#include <cstdio>
+#include "llvm/Support/Signals.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Main.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenAction.h"
+
using namespace llvm;
enum ActionType {
PrintRecords,
GenEmitter,
- GenRegisterEnums, GenRegister, GenRegisterHeader,
- GenInstrEnums, GenInstrs, GenAsmWriter, GenAsmMatcher,
+ GenRegisterInfo,
+ GenInstrInfo,
+ GenAsmWriter,
+ GenAsmMatcher,
GenARMDecoder,
GenDisassembler,
+ GenPseudoLowering,
GenCallingConv,
- GenClangAttrClasses,
- GenClangAttrList,
- GenClangDiagsDefs,
- GenClangDiagGroups,
- GenClangDeclNodes,
- GenClangStmtNodes,
GenDAGISel,
GenFastISel,
- GenOptParserDefs, GenOptParserImpl,
GenSubtarget,
GenIntrinsic,
GenTgtIntrinsic,
- GenLLVMCConf,
GenEDInfo,
- GenArmNeon,
- GenArmNeonSema,
- PrintEnums
+ PrintEnums,
+ PrintSets
};
namespace {
@@ -80,15 +65,9 @@
"Print all records to stdout (default)"),
clEnumValN(GenEmitter, "gen-emitter",
"Generate machine code emitter"),
- clEnumValN(GenRegisterEnums, "gen-register-enums",
- "Generate enum values for registers"),
- clEnumValN(GenRegister, "gen-register-desc",
- "Generate a register info description"),
- clEnumValN(GenRegisterHeader, "gen-register-desc-header",
- "Generate a register info description header"),
- clEnumValN(GenInstrEnums, "gen-instr-enums",
- "Generate enum values for instructions"),
- clEnumValN(GenInstrs, "gen-instr-desc",
+ clEnumValN(GenRegisterInfo, "gen-register-info",
+ "Generate registers and register classes info"),
+ clEnumValN(GenInstrInfo, "gen-instr-info",
"Generate instruction descriptions"),
clEnumValN(GenCallingConv, "gen-callingconv",
"Generate calling convention descriptions"),
@@ -98,244 +77,122 @@
"Generate decoders for ARM/Thumb"),
clEnumValN(GenDisassembler, "gen-disassembler",
"Generate disassembler"),
+ clEnumValN(GenPseudoLowering, "gen-pseudo-lowering",
+ "Generate pseudo instruction lowering"),
clEnumValN(GenAsmMatcher, "gen-asm-matcher",
"Generate assembly instruction matcher"),
clEnumValN(GenDAGISel, "gen-dag-isel",
"Generate a DAG instruction selector"),
clEnumValN(GenFastISel, "gen-fast-isel",
"Generate a \"fast\" instruction selector"),
- clEnumValN(GenOptParserDefs, "gen-opt-parser-defs",
- "Generate option definitions"),
- clEnumValN(GenOptParserImpl, "gen-opt-parser-impl",
- "Generate option parser implementation"),
clEnumValN(GenSubtarget, "gen-subtarget",
"Generate subtarget enumerations"),
clEnumValN(GenIntrinsic, "gen-intrinsic",
"Generate intrinsic information"),
clEnumValN(GenTgtIntrinsic, "gen-tgt-intrinsic",
"Generate target intrinsic information"),
- clEnumValN(GenClangAttrClasses, "gen-clang-attr-classes",
- "Generate clang attribute clases"),
- clEnumValN(GenClangAttrList, "gen-clang-attr-list",
- "Generate a clang attribute list"),
- clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
- "Generate Clang diagnostics definitions"),
- clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups",
- "Generate Clang diagnostic groups"),
- clEnumValN(GenClangDeclNodes, "gen-clang-decl-nodes",
- "Generate Clang AST statement nodes"),
- clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes",
- "Generate Clang AST statement nodes"),
- clEnumValN(GenLLVMCConf, "gen-llvmc",
- "Generate LLVMC configuration library"),
clEnumValN(GenEDInfo, "gen-enhanced-disassembly-info",
"Generate enhanced disassembly info"),
- clEnumValN(GenArmNeon, "gen-arm-neon",
- "Generate arm_neon.h for clang"),
- clEnumValN(GenArmNeonSema, "gen-arm-neon-sema",
- "Generate ARM NEON sema support for clang"),
clEnumValN(PrintEnums, "print-enums",
"Print enum values for a class"),
+ clEnumValN(PrintSets, "print-sets",
+ "Print expanded sets for testing DAG exprs"),
clEnumValEnd));
cl::opt<std::string>
Class("class", cl::desc("Print Enum list for this class"),
cl::value_desc("class name"));
-
- cl::opt<std::string>
- OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"),
- cl::init("-"));
-
- cl::opt<std::string>
- InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-"));
-
- cl::list<std::string>
- IncludeDirs("I", cl::desc("Directory of include files"),
- cl::value_desc("directory"), cl::Prefix);
-
- cl::opt<std::string>
- ClangComponent("clang-component",
- cl::desc("Only use warnings from specified component"),
- cl::value_desc("component"), cl::Hidden);
}
+class LLVMTableGenAction : public TableGenAction {
+public:
+ bool operator()(raw_ostream &OS, RecordKeeper &Records) {
+ switch (Action) {
+ case PrintRecords:
+ OS << Records; // No argument, dump all contents
+ break;
+ case GenEmitter:
+ CodeEmitterGen(Records).run(OS);
+ break;
+ case GenRegisterInfo:
+ RegisterInfoEmitter(Records).run(OS);
+ break;
+ case GenInstrInfo:
+ InstrInfoEmitter(Records).run(OS);
+ break;
+ case GenCallingConv:
+ CallingConvEmitter(Records).run(OS);
+ break;
+ case GenAsmWriter:
+ AsmWriterEmitter(Records).run(OS);
+ break;
+ case GenARMDecoder:
+ ARMDecoderEmitter(Records).run(OS);
+ break;
+ case GenAsmMatcher:
+ AsmMatcherEmitter(Records).run(OS);
+ break;
+ case GenDisassembler:
+ DisassemblerEmitter(Records).run(OS);
+ break;
+ case GenPseudoLowering:
+ PseudoLoweringEmitter(Records).run(OS);
+ break;
+ case GenDAGISel:
+ DAGISelEmitter(Records).run(OS);
+ break;
+ case GenFastISel:
+ FastISelEmitter(Records).run(OS);
+ break;
+ case GenSubtarget:
+ SubtargetEmitter(Records).run(OS);
+ break;
+ case GenIntrinsic:
+ IntrinsicEmitter(Records).run(OS);
+ break;
+ case GenTgtIntrinsic:
+ IntrinsicEmitter(Records, true).run(OS);
+ break;
+ case GenEDInfo:
+ EDEmitter(Records).run(OS);
+ break;
+ case PrintEnums:
+ {
+ std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
+ for (unsigned i = 0, e = Recs.size(); i != e; ++i)
+ OS << Recs[i]->getName() << ", ";
+ OS << "\n";
+ break;
+ }
+ case PrintSets:
+ {
+ SetTheory Sets;
+ Sets.addFieldExpander("Set", "Elements");
+ std::vector<Record*> Recs = Records.getAllDerivedDefinitions("Set");
+ for (unsigned i = 0, e = Recs.size(); i != e; ++i) {
+ OS << Recs[i]->getName() << " = [";
+ const std::vector<Record*> *Elts = Sets.expand(Recs[i]);
+ assert(Elts && "Couldn't expand Set instance");
+ for (unsigned ei = 0, ee = Elts->size(); ei != ee; ++ei)
+ OS << ' ' << (*Elts)[ei]->getName();
+ OS << " ]\n";
+ }
+ break;
+ }
+ default:
+ assert(1 && "Invalid Action");
+ return true;
+ }
-// FIXME: Eliminate globals from tblgen.
-RecordKeeper llvm::Records;
-
-static SourceMgr SrcMgr;
-
-void llvm::PrintError(SMLoc ErrorLoc, const std::string &Msg) {
- SrcMgr.PrintMessage(ErrorLoc, Msg, "error");
-}
-
-
-
-/// ParseFile - this function begins the parsing of the specified tablegen
-/// file.
-static bool ParseFile(const std::string &Filename,
- const std::vector<std::string> &IncludeDirs,
- SourceMgr &SrcMgr) {
- std::string ErrorStr;
- MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrorStr);
- if (F == 0) {
- errs() << "Could not open input file '" << Filename << "': "
- << ErrorStr <<"\n";
- return true;
+ return false;
}
-
- // Tell SrcMgr about this buffer, which is what TGParser will pick up.
- SrcMgr.AddNewSourceBuffer(F, SMLoc());
-
- // Record the location of the include directory so that the lexer can find
- // it later.
- SrcMgr.setIncludeDirs(IncludeDirs);
-
- TGParser Parser(SrcMgr);
-
- return Parser.ParseFile();
-}
+};
int main(int argc, char **argv) {
sys::PrintStackTraceOnErrorSignal();
PrettyStackTraceProgram X(argc, argv);
cl::ParseCommandLineOptions(argc, argv);
-
- // Parse the input file.
- if (ParseFile(InputFilename, IncludeDirs, SrcMgr))
- return 1;
-
- std::string Error;
- raw_fd_ostream Out(OutputFilename.c_str(), Error);
- if (!Error.empty()) {
- errs() << argv[0] << ": error opening " << OutputFilename
- << ":" << Error << "\n";
- return 1;
- }
-
- // Make sure the file gets removed if *gasp* tablegen crashes...
- sys::RemoveFileOnSignal(sys::Path(OutputFilename));
-
- try {
- switch (Action) {
- case PrintRecords:
- Out << Records; // No argument, dump all contents
- break;
- case GenEmitter:
- CodeEmitterGen(Records).run(Out);
- break;
-
- case GenRegisterEnums:
- RegisterInfoEmitter(Records).runEnums(Out);
- break;
- case GenRegister:
- RegisterInfoEmitter(Records).run(Out);
- break;
- case GenRegisterHeader:
- RegisterInfoEmitter(Records).runHeader(Out);
- break;
- case GenInstrEnums:
- InstrEnumEmitter(Records).run(Out);
- break;
- case GenInstrs:
- InstrInfoEmitter(Records).run(Out);
- break;
- case GenCallingConv:
- CallingConvEmitter(Records).run(Out);
- break;
- case GenAsmWriter:
- AsmWriterEmitter(Records).run(Out);
- break;
- case GenARMDecoder:
- ARMDecoderEmitter(Records).run(Out);
- break;
- case GenAsmMatcher:
- AsmMatcherEmitter(Records).run(Out);
- break;
- case GenClangAttrClasses:
- ClangAttrClassEmitter(Records).run(Out);
- break;
- case GenClangAttrList:
- ClangAttrListEmitter(Records).run(Out);
- break;
- case GenClangDiagsDefs:
- ClangDiagsDefsEmitter(Records, ClangComponent).run(Out);
- break;
- case GenClangDiagGroups:
- ClangDiagGroupsEmitter(Records).run(Out);
- break;
- case GenClangDeclNodes:
- ClangASTNodesEmitter(Records, "Decl", "Decl").run(Out);
- ClangDeclContextEmitter(Records).run(Out);
- break;
- case GenClangStmtNodes:
- ClangASTNodesEmitter(Records, "Stmt", "").run(Out);
- break;
- case GenDisassembler:
- DisassemblerEmitter(Records).run(Out);
- break;
- case GenOptParserDefs:
- OptParserEmitter(Records, true).run(Out);
- break;
- case GenOptParserImpl:
- OptParserEmitter(Records, false).run(Out);
- break;
- case GenDAGISel:
- DAGISelEmitter(Records).run(Out);
- break;
- case GenFastISel:
- FastISelEmitter(Records).run(Out);
- break;
- case GenSubtarget:
- SubtargetEmitter(Records).run(Out);
- break;
- case GenIntrinsic:
- IntrinsicEmitter(Records).run(Out);
- break;
- case GenTgtIntrinsic:
- IntrinsicEmitter(Records, true).run(Out);
- break;
- case GenLLVMCConf:
- LLVMCConfigurationEmitter(Records).run(Out);
- break;
- case GenEDInfo:
- EDEmitter(Records).run(Out);
- break;
- case GenArmNeon:
- NeonEmitter(Records).run(Out);
- break;
- case GenArmNeonSema:
- NeonEmitter(Records).runHeader(Out);
- break;
- case PrintEnums:
- {
- std::vector<Record*> Recs = Records.getAllDerivedDefinitions(Class);
- for (unsigned i = 0, e = Recs.size(); i != e; ++i)
- Out << Recs[i]->getName() << ", ";
- Out << "\n";
- break;
- }
- default:
- assert(1 && "Invalid Action");
- return 1;
- }
-
- return 0;
-
- } catch (const TGError &Error) {
- errs() << argv[0] << ": error:\n";
- PrintError(Error.getLoc(), Error.getMessage());
-
- } catch (const std::string &Error) {
- errs() << argv[0] << ": " << Error << "\n";
- } catch (const char *Error) {
- errs() << argv[0] << ": " << Error << "\n";
- } catch (...) {
- errs() << argv[0] << ": Unknown unexpected exception occurred.\n";
- }
-
- if (OutputFilename != "-")
- std::remove(OutputFilename.c_str()); // Remove the file, it's broken
- return 1;
+ LLVMTableGenAction Action;
+ return TableGenMain(argv[0], Action);
}
diff --git a/src/LLVM/utils/TableGen/X86DisassemblerTables.cpp b/src/LLVM/utils/TableGen/X86DisassemblerTables.cpp
index 2176224..e8c9a48 100644
--- a/src/LLVM/utils/TableGen/X86DisassemblerTables.cpp
+++ b/src/LLVM/utils/TableGen/X86DisassemblerTables.cpp
@@ -17,7 +17,8 @@
#include "X86DisassemblerShared.h"
#include "X86DisassemblerTables.h"
-#include "TableGenBackend.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
@@ -31,24 +32,32 @@
/// @param parent - The class that may be the superset
/// @return - True if child is a subset of parent, false otherwise.
static inline bool inheritsFrom(InstructionContext child,
- InstructionContext parent) {
+ InstructionContext parent,
+ bool VEX_LIG = false) {
if (child == parent)
return true;
switch (parent) {
case IC:
- return true;
+ return(inheritsFrom(child, IC_64BIT) ||
+ inheritsFrom(child, IC_OPSIZE) ||
+ inheritsFrom(child, IC_XD) ||
+ inheritsFrom(child, IC_XS));
case IC_64BIT:
return(inheritsFrom(child, IC_64BIT_REXW) ||
inheritsFrom(child, IC_64BIT_OPSIZE) ||
inheritsFrom(child, IC_64BIT_XD) ||
inheritsFrom(child, IC_64BIT_XS));
case IC_OPSIZE:
- return(inheritsFrom(child, IC_64BIT_OPSIZE));
+ return inheritsFrom(child, IC_64BIT_OPSIZE);
case IC_XD:
- return(inheritsFrom(child, IC_64BIT_XD));
+ return inheritsFrom(child, IC_64BIT_XD);
case IC_XS:
- return(inheritsFrom(child, IC_64BIT_XS));
+ return inheritsFrom(child, IC_64BIT_XS);
+ case IC_XD_OPSIZE:
+ return inheritsFrom(child, IC_64BIT_XD_OPSIZE);
+ case IC_XS_OPSIZE:
+ return inheritsFrom(child, IC_64BIT_XS_OPSIZE);
case IC_64BIT_REXW:
return(inheritsFrom(child, IC_64BIT_REXW_XS) ||
inheritsFrom(child, IC_64BIT_REXW_XD) ||
@@ -59,13 +68,37 @@
return(inheritsFrom(child, IC_64BIT_REXW_XD));
case IC_64BIT_XS:
return(inheritsFrom(child, IC_64BIT_REXW_XS));
+ case IC_64BIT_XD_OPSIZE:
+ case IC_64BIT_XS_OPSIZE:
+ return false;
case IC_64BIT_REXW_XD:
- return false;
case IC_64BIT_REXW_XS:
- return false;
case IC_64BIT_REXW_OPSIZE:
return false;
+ case IC_VEX:
+ return inheritsFrom(child, IC_VEX_W) ||
+ (VEX_LIG && inheritsFrom(child, IC_VEX_L));
+ case IC_VEX_XS:
+ return inheritsFrom(child, IC_VEX_W_XS) ||
+ (VEX_LIG && inheritsFrom(child, IC_VEX_L_XS));
+ case IC_VEX_XD:
+ return inheritsFrom(child, IC_VEX_W_XD) ||
+ (VEX_LIG && inheritsFrom(child, IC_VEX_L_XD));
+ case IC_VEX_OPSIZE:
+ return inheritsFrom(child, IC_VEX_W_OPSIZE) ||
+ (VEX_LIG && inheritsFrom(child, IC_VEX_L_OPSIZE));
+ case IC_VEX_W:
+ case IC_VEX_W_XS:
+ case IC_VEX_W_XD:
+ case IC_VEX_W_OPSIZE:
+ return false;
+ case IC_VEX_L:
+ case IC_VEX_L_XS:
+ case IC_VEX_L_XD:
+ case IC_VEX_L_OPSIZE:
+ return false;
default:
+ llvm_unreachable("Unknown instruction class");
return false;
}
}
@@ -161,7 +194,7 @@
/// @param i - The indentation level for that output stream.
static void emitEmptyTable(raw_ostream &o, uint32_t &i)
{
- o.indent(i * 2) << "static InstrUID modRMEmptyTable[1] = { 0 };" << "\n";
+ o.indent(i * 2) << "static const InstrUID modRMEmptyTable[1] = { 0 };\n";
o << "\n";
}
@@ -236,7 +269,7 @@
DisassemblerTables::DisassemblerTables() {
unsigned i;
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < array_lengthof(Tables); i++) {
Tables[i] = new ContextDecision;
memset(Tables[i], 0, sizeof(ContextDecision));
}
@@ -247,7 +280,7 @@
DisassemblerTables::~DisassemblerTables() {
unsigned i;
- for (i = 0; i < 4; i++)
+ for (i = 0; i < array_lengthof(Tables); i++)
delete Tables[i];
}
@@ -275,7 +308,7 @@
return;
}
- o1.indent(i1) << "static InstrUID modRMTable" << thisTableNumber;
+ o1.indent(i1) << "static const InstrUID modRMTable" << thisTableNumber;
switch (dt) {
default:
@@ -365,7 +398,7 @@
uint32_t &i2,
ContextDecision &decision,
const char* name) const {
- o2.indent(i2) << "struct ContextDecision " << name << " = {" << "\n";
+ o2.indent(i2) << "static const struct ContextDecision " << name << " = {\n";
i2++;
o2.indent(i2) << "{ /* opcodeDecisions */" << "\n";
i2++;
@@ -392,10 +425,8 @@
void DisassemblerTables::emitInstructionInfo(raw_ostream &o, uint32_t &i)
const {
- o.indent(i * 2) << "struct InstructionSpecifier ";
- o << INSTRUCTIONS_STR << "[";
- o << InstructionSpecifiers.size();
- o << "] = {" << "\n";
+ o.indent(i * 2) << "static const struct InstructionSpecifier ";
+ o << INSTRUCTIONS_STR "[" << InstructionSpecifiers.size() << "] = {\n";
i++;
@@ -456,20 +487,48 @@
void DisassemblerTables::emitContextTable(raw_ostream &o, uint32_t &i) const {
uint16_t index;
- o.indent(i * 2) << "InstructionContext ";
- o << CONTEXTS_STR << "[256] = {" << "\n";
+ o.indent(i * 2) << "static const InstructionContext " CONTEXTS_STR
+ "[256] = {\n";
i++;
for (index = 0; index < 256; ++index) {
o.indent(i * 2);
- if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS))
+ if ((index & ATTR_VEXL) && (index & ATTR_OPSIZE))
+ o << "IC_VEX_L_OPSIZE";
+ else if ((index & ATTR_VEXL) && (index & ATTR_XD))
+ o << "IC_VEX_L_XD";
+ else if ((index & ATTR_VEXL) && (index & ATTR_XS))
+ o << "IC_VEX_L_XS";
+ else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_OPSIZE))
+ o << "IC_VEX_W_OPSIZE";
+ else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XD))
+ o << "IC_VEX_W_XD";
+ else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XS))
+ o << "IC_VEX_W_XS";
+ else if (index & ATTR_VEXL)
+ o << "IC_VEX_L";
+ else if ((index & ATTR_VEX) && (index & ATTR_REXW))
+ o << "IC_VEX_W";
+ else if ((index & ATTR_VEX) && (index & ATTR_OPSIZE))
+ o << "IC_VEX_OPSIZE";
+ else if ((index & ATTR_VEX) && (index & ATTR_XD))
+ o << "IC_VEX_XD";
+ else if ((index & ATTR_VEX) && (index & ATTR_XS))
+ o << "IC_VEX_XS";
+ else if (index & ATTR_VEX)
+ o << "IC_VEX";
+ else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS))
o << "IC_64BIT_REXW_XS";
else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XD))
o << "IC_64BIT_REXW_XD";
else if ((index & ATTR_64BIT) && (index & ATTR_REXW) &&
(index & ATTR_OPSIZE))
o << "IC_64BIT_REXW_OPSIZE";
+ else if ((index & ATTR_64BIT) && (index & ATTR_XD) && (index & ATTR_OPSIZE))
+ o << "IC_64BIT_XD_OPSIZE";
+ else if ((index & ATTR_64BIT) && (index & ATTR_XS) && (index & ATTR_OPSIZE))
+ o << "IC_64BIT_XS_OPSIZE";
else if ((index & ATTR_64BIT) && (index & ATTR_XS))
o << "IC_64BIT_XS";
else if ((index & ATTR_64BIT) && (index & ATTR_XD))
@@ -480,6 +539,10 @@
o << "IC_64BIT_REXW";
else if ((index & ATTR_64BIT))
o << "IC_64BIT";
+ else if ((index & ATTR_XS) && (index & ATTR_OPSIZE))
+ o << "IC_XS_OPSIZE";
+ else if ((index & ATTR_XD) && (index & ATTR_OPSIZE))
+ o << "IC_XD_OPSIZE";
else if (index & ATTR_XS)
o << "IC_XS";
else if (index & ATTR_XD)
@@ -512,6 +575,8 @@
emitContextDecision(o1, o2, i1, i2, *Tables[1], TWOBYTE_STR);
emitContextDecision(o1, o2, i1, i2, *Tables[2], THREEBYTE38_STR);
emitContextDecision(o1, o2, i1, i2, *Tables[3], THREEBYTE3A_STR);
+ emitContextDecision(o1, o2, i1, i2, *Tables[4], THREEBYTEA6_STR);
+ emitContextDecision(o1, o2, i1, i2, *Tables[5], THREEBYTEA7_STR);
}
void DisassemblerTables::emit(raw_ostream &o) const {
@@ -560,8 +625,11 @@
if(newInfo.filtered)
continue; // filtered instructions get lowest priority
- if(previousInfo.name == "NOOP")
- continue; // special case for XCHG32ar and NOOP
+ if(previousInfo.name == "NOOP" && (newInfo.name == "XCHG16ar" ||
+ newInfo.name == "XCHG32ar" ||
+ newInfo.name == "XCHG32ar64" ||
+ newInfo.name == "XCHG64ar"))
+ continue; // special case for XCHG*ar and NOOP
if (outranks(previousInfo.insnContext, newInfo.insnContext))
continue;
@@ -587,14 +655,19 @@
InstructionContext insnContext,
uint8_t opcode,
const ModRMFilter &filter,
- InstrUID uid) {
+ InstrUID uid,
+ bool is32bit,
+ bool ignoresVEX_L) {
unsigned index;
ContextDecision &decision = *Tables[type];
for (index = 0; index < IC_max; ++index) {
+ if (is32bit && inheritsFrom((InstructionContext)index, IC_64BIT))
+ continue;
+
if (inheritsFrom((InstructionContext)index,
- InstructionSpecifiers[uid].insnContext))
+ InstructionSpecifiers[uid].insnContext, ignoresVEX_L))
setTableFields(decision.opcodeDecisions[index].modRMDecisions[opcode],
filter,
uid,
diff --git a/src/LLVM/utils/TableGen/X86DisassemblerTables.h b/src/LLVM/utils/TableGen/X86DisassemblerTables.h
index 08eba01..e148cd2 100644
--- a/src/LLVM/utils/TableGen/X86DisassemblerTables.h
+++ b/src/LLVM/utils/TableGen/X86DisassemblerTables.h
@@ -39,7 +39,9 @@
/// [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 __
- ContextDecision* Tables[4];
+ /// [4] three-byte opcodes of the form 0f a6 __
+ /// [5] three-byte opcodes of the form 0f a7 __
+ ContextDecision* Tables[6];
/// The instruction information table
std::vector<InstructionSpecifier> InstructionSpecifiers;
@@ -77,7 +79,7 @@
/// regardless of ModR/M byte, two entries - one for bytes 0x00-0xbf and one
/// for bytes 0xc0-0xff -, or 256 entries, one for each possible byte.
/// nnnn is the number of a table for looking up these values. The tables
- /// are writen separately so that tables consisting entirely of zeros will
+ /// are written separately so that tables consisting entirely of zeros will
/// not be duplicated. (These all have the name modRMEmptyTable.) A table
/// is printed as:
///
@@ -141,8 +143,9 @@
/// }
/// }
///
- /// NAME is the name of the ContextDecision (typically one of the four names
- /// ONEBYTE_SYM, TWOBYTE_SYM, THREEBYTE38_SYM, and THREEBYTE3A_SYM from
+ /// 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
/// X86DisassemblerDecoderCommon.h).
/// IC is one of the contexts in InstructionContext. There is an opcode
/// decision for each possible context.
@@ -257,11 +260,15 @@
/// @param filter - The ModRMFilter that decides which ModR/M byte values
/// correspond to the desired instruction.
/// @param uid - The unique ID of the instruction.
+ /// @param is32bit - Instructon is only 32-bit
+ /// @param ignoresVEX_L - Instruction ignores VEX.L
void setTableFields(OpcodeType type,
InstructionContext insnContext,
uint8_t opcode,
const ModRMFilter &filter,
- InstrUID uid);
+ InstrUID uid,
+ bool is32bit,
+ bool ignoresVEX_L);
/// specForUID - Returns the instruction specifier for a given unique
/// instruction ID. Used when resolving collisions.
diff --git a/src/LLVM/utils/TableGen/X86ModRMFilters.h b/src/LLVM/utils/TableGen/X86ModRMFilters.h
index 45cb07a..199040b 100644
--- a/src/LLVM/utils/TableGen/X86ModRMFilters.h
+++ b/src/LLVM/utils/TableGen/X86ModRMFilters.h
@@ -18,7 +18,7 @@
#ifndef X86MODRMFILTERS_H
#define X86MODRMFILTERS_H
-#include "llvm/System/DataTypes.h"
+#include "llvm/Support/DataTypes.h"
namespace llvm {
diff --git a/src/LLVM/utils/TableGen/X86RecognizableInstr.cpp b/src/LLVM/utils/TableGen/X86RecognizableInstr.cpp
index 4dba85b..cae8237 100644
--- a/src/LLVM/utils/TableGen/X86RecognizableInstr.cpp
+++ b/src/LLVM/utils/TableGen/X86RecognizableInstr.cpp
@@ -34,7 +34,9 @@
MAP(E8, 39) \
MAP(F0, 40) \
MAP(F8, 41) \
- MAP(F9, 42)
+ MAP(F9, 42) \
+ MAP(D0, 45) \
+ MAP(D1, 46)
// A clone of X86 since we can't depend on something that is generated.
namespace X86Local {
@@ -51,10 +53,11 @@
MRM0m = 24, MRM1m = 25, MRM2m = 26, MRM3m = 27,
MRM4m = 28, MRM5m = 29, MRM6m = 30, MRM7m = 31,
MRMInitReg = 32,
-
#define MAP(from, to) MRM_##from = to,
MRM_MAPPING
#undef MAP
+ RawFrmImm8 = 43,
+ RawFrmImm16 = 44,
lastMRM
};
@@ -65,7 +68,7 @@
DC = 7, DD = 8, DE = 9, DF = 10,
XD = 11, XS = 12,
T8 = 13, P_TA = 14,
- P_0F_AE = 16, P_0F_01 = 17
+ A6 = 15, A7 = 16, TF = 17
};
}
@@ -113,7 +116,6 @@
EXTENSION_TABLE(72) \
EXTENSION_TABLE(73) \
EXTENSION_TABLE(ae) \
- EXTENSION_TABLE(b9) \
EXTENSION_TABLE(ba) \
EXTENSION_TABLE(c7)
@@ -212,23 +214,59 @@
HasOpSizePrefix = Rec->getValueAsBit("hasOpSizePrefix");
HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix");
+ HasVEXPrefix = Rec->getValueAsBit("hasVEXPrefix");
HasVEX_4VPrefix = Rec->getValueAsBit("hasVEX_4VPrefix");
+ HasVEX_WPrefix = Rec->getValueAsBit("hasVEX_WPrefix");
+ IgnoresVEX_L = Rec->getValueAsBit("ignoresVEX_L");
HasLockPrefix = Rec->getValueAsBit("hasLockPrefix");
IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly");
Name = Rec->getName();
AsmString = Rec->getValueAsString("AsmString");
- Operands = &insn.OperandList;
+ Operands = &insn.Operands.OperandList;
- IsSSE = HasOpSizePrefix && (Name.find("16") == Name.npos);
- HasFROperands = false;
+ IsSSE = (HasOpSizePrefix && (Name.find("16") == Name.npos)) ||
+ (Name.find("CRC32") != Name.npos);
+ HasFROperands = hasFROperands();
+ HasVEX_LPrefix = has256BitOperands() || Rec->getValueAsBit("hasVEX_L");
+ // Check for 64-bit inst which does not require REX
+ Is32Bit = false;
+ Is64Bit = false;
+ // 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) {
+ Is32Bit = true;
+ break;
+ }
+ if (Predicates[i]->getName().find("64Bit") != 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("VMREAD64") != Name.npos ||
+ Rec->getName().find("VMWRITE64") != Name.npos ||
+ Rec->getName().find("INVEPT64") != Name.npos ||
+ Rec->getName().find("INVVPID64") != Name.npos ||
+ Rec->getName().find("MOV64") != Name.npos ||
+ Rec->getName().find("PUSH64") != Name.npos ||
+ Rec->getName().find("POP64") != Name.npos;
+
ShouldBeEmitted = true;
}
void RecognizableInstr::processInstr(DisassemblerTables &tables,
- const CodeGenInstruction &insn,
+ const CodeGenInstruction &insn,
InstrUID uid)
{
// Ignore "asm parser only" instructions.
@@ -246,16 +284,49 @@
InstructionContext RecognizableInstr::insnContext() const {
InstructionContext insnContext;
- if (Name.find("64") != Name.npos || HasREX_WPrefix) {
+ if (HasVEX_4VPrefix || HasVEXPrefix) {
+ if (HasVEX_LPrefix && HasVEX_WPrefix)
+ llvm_unreachable("Don't support VEX.L and VEX.W together");
+ else if (HasOpSizePrefix && HasVEX_LPrefix)
+ insnContext = IC_VEX_L_OPSIZE;
+ else if (HasOpSizePrefix && HasVEX_WPrefix)
+ insnContext = IC_VEX_W_OPSIZE;
+ else if (HasOpSizePrefix)
+ insnContext = IC_VEX_OPSIZE;
+ else if (HasVEX_LPrefix && Prefix == X86Local::XS)
+ insnContext = IC_VEX_L_XS;
+ else if (HasVEX_LPrefix && Prefix == X86Local::XD)
+ insnContext = IC_VEX_L_XD;
+ else if (HasVEX_WPrefix && Prefix == X86Local::XS)
+ insnContext = IC_VEX_W_XS;
+ else if (HasVEX_WPrefix && Prefix == X86Local::XD)
+ insnContext = IC_VEX_W_XD;
+ else if (HasVEX_WPrefix)
+ insnContext = IC_VEX_W;
+ else if (HasVEX_LPrefix)
+ insnContext = IC_VEX_L;
+ else if (Prefix == X86Local::XD)
+ insnContext = IC_VEX_XD;
+ else if (Prefix == X86Local::XS)
+ insnContext = IC_VEX_XS;
+ else
+ insnContext = IC_VEX;
+ } else if (Is64Bit || HasREX_WPrefix) {
if (HasREX_WPrefix && HasOpSizePrefix)
insnContext = IC_64BIT_REXW_OPSIZE;
+ else if (HasOpSizePrefix &&
+ (Prefix == X86Local::XD || Prefix == X86Local::TF))
+ insnContext = IC_64BIT_XD_OPSIZE;
+ else if (HasOpSizePrefix && Prefix == X86Local::XS)
+ insnContext = IC_64BIT_XS_OPSIZE;
else if (HasOpSizePrefix)
insnContext = IC_64BIT_OPSIZE;
else if (HasREX_WPrefix && Prefix == X86Local::XS)
insnContext = IC_64BIT_REXW_XS;
- else if (HasREX_WPrefix && Prefix == X86Local::XD)
+ else if (HasREX_WPrefix &&
+ (Prefix == X86Local::XD || Prefix == X86Local::TF))
insnContext = IC_64BIT_REXW_XD;
- else if (Prefix == X86Local::XD)
+ else if (Prefix == X86Local::XD || Prefix == X86Local::TF)
insnContext = IC_64BIT_XD;
else if (Prefix == X86Local::XS)
insnContext = IC_64BIT_XS;
@@ -264,11 +335,16 @@
else
insnContext = IC_64BIT;
} else {
- if (HasOpSizePrefix)
+ if (HasOpSizePrefix &&
+ (Prefix == X86Local::XD || Prefix == X86Local::TF))
+ insnContext = IC_XD_OPSIZE;
+ else if (HasOpSizePrefix && Prefix == X86Local::XS)
+ insnContext = IC_XS_OPSIZE;
+ else if (HasOpSizePrefix)
insnContext = IC_OPSIZE;
- else if (Prefix == X86Local::XD)
+ else if (Prefix == X86Local::XD || Prefix == X86Local::TF)
insnContext = IC_XD;
- else if (Prefix == X86Local::XS)
+ else if (Prefix == X86Local::XS || Prefix == X86Local::REP)
insnContext = IC_XS;
else
insnContext = IC;
@@ -278,40 +354,82 @@
}
RecognizableInstr::filter_ret RecognizableInstr::filter() const {
+ ///////////////////
+ // FILTER_STRONG
+ //
+
// Filter out intrinsics
if (!Rec->isSubClassOf("X86Inst"))
return FILTER_STRONG;
if (Form == X86Local::Pseudo ||
- IsCodeGenOnly)
+ (IsCodeGenOnly && Name.find("_REV") == Name.npos))
return FILTER_STRONG;
if (Form == X86Local::MRMInitReg)
return FILTER_STRONG;
+
+
+ // Filter out artificial instructions
+
+ if (Name.find("TAILJMP") != Name.npos ||
+ Name.find("_Int") != Name.npos ||
+ Name.find("_int") != Name.npos ||
+ Name.find("Int_") != Name.npos ||
+ Name.find("_NOREX") != Name.npos ||
+ Name.find("_TC") != Name.npos ||
+ Name.find("EH_RETURN") != Name.npos ||
+ Name.find("V_SET") != Name.npos ||
+ Name.find("LOCK_") != Name.npos ||
+ Name.find("WIN") != Name.npos ||
+ Name.find("_AVX") != Name.npos ||
+ Name.find("2SDL") != 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 out instructions that can't be printed.
+
+ if (AsmString.size() == 0)
+ return FILTER_STRONG;
+
+ // Filter out instructions with subreg operands.
+
+ if (AsmString.find("subreg") != AsmString.npos)
+ 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 artificial instructions
- if (Name.find("TAILJMP") != Name.npos ||
- Name.find("_Int") != Name.npos ||
- Name.find("_int") != Name.npos ||
- Name.find("Int_") != Name.npos ||
- Name.find("_NOREX") != Name.npos ||
- Name.find("_TC") != Name.npos ||
- Name.find("EH_RETURN") != Name.npos ||
- Name.find("V_SET") != Name.npos ||
- Name.find("LOCK_") != Name.npos ||
- Name.find("WIN") != Name.npos)
- return FILTER_STRONG;
+ // Filter out alternate forms of AVX instructions
+ if (Name.find("_alt") != Name.npos ||
+ Name.find("XrYr") != Name.npos ||
+ (Name.find("r64r") != Name.npos && Name.find("r64r64") == Name.npos) ||
+ Name.find("_64mr") != Name.npos ||
+ Name.find("Xrr") != Name.npos ||
+ Name.find("rr64") != Name.npos)
+ return FILTER_WEAK;
+
+ if (Name == "VMASKMOVDQU64" ||
+ Name == "VEXTRACTPSrr64" ||
+ Name == "VMOVQd64rr" ||
+ Name == "VMOVQs64rr")
+ return FILTER_WEAK;
// Special cases.
-
+
if (Name.find("PCMPISTRI") != Name.npos && Name != "PCMPISTRI")
return FILTER_WEAK;
if (Name.find("PCMPESTRI") != Name.npos && Name != "PCMPESTRI")
@@ -337,6 +455,7 @@
Name == "PUSH32i16" ||
Name == "PUSH64i16" ||
Name == "MOVPQI2QImr" ||
+ Name == "VMOVPQI2QImr" ||
Name == "MOVSDmr" ||
Name == "MOVSDrm" ||
Name == "MOVSSmr" ||
@@ -347,22 +466,6 @@
Name == "CRC32r16")
return FILTER_WEAK;
- // 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 out instructions that can't be printed.
-
- if (AsmString.size() == 0)
- return FILTER_STRONG;
-
- // Filter out instructions with subreg operands.
-
- if (AsmString.find("subreg") != AsmString.npos)
- return FILTER_STRONG;
-
if (HasFROperands && Name.find("MOV") != Name.npos &&
((Name.find("2") != Name.npos && Name.find("32") == Name.npos) ||
(Name.find("to") != Name.npos)))
@@ -370,6 +473,33 @@
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;
+}
+
+bool RecognizableInstr::has256BitOperands() 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.compare("VR256") || !recName.compare("f256mem")) {
+ return true;
+ }
+ }
+ return false;
+}
void RecognizableInstr::handleOperand(
bool optional,
@@ -393,13 +523,13 @@
}
const std::string &typeName = (*Operands)[operandIndex].Rec->getName();
-
+
Spec->operands[operandIndex].encoding = encodingFromString(typeName,
HasOpSizePrefix);
Spec->operands[operandIndex].type = typeFromString(typeName,
- IsSSE,
- HasREX_WPrefix,
- HasOpSizePrefix);
+ IsSSE,
+ HasREX_WPrefix,
+ HasOpSizePrefix);
++operandIndex;
++physicalOperandIndex;
@@ -424,7 +554,7 @@
Spec->insnContext = insnContext();
- const std::vector<CodeGenInstruction::OperandInfo> &OperandList = *Operands;
+ const std::vector<CGIOperandList::OperandInfo> &OperandList = *Operands;
unsigned operandIndex;
unsigned numOperands = OperandList.size();
@@ -440,7 +570,7 @@
for (operandIndex = 0; operandIndex < numOperands; ++operandIndex) {
if (OperandList[operandIndex].Constraints.size()) {
- const CodeGenInstruction::ConstraintInfo &Constraint =
+ const CGIOperandList::ConstraintInfo &Constraint =
OperandList[operandIndex].Constraints[0];
if (Constraint.isTied()) {
operandMapping[operandIndex] = Constraint.getTiedOperand();
@@ -508,51 +638,88 @@
case X86Local::MRMDestReg:
// Operand 1 is a register operand in the R/M field.
// 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.
- assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
- "Unexpected number of operands for MRMDestRegFrm");
+ if (HasVEX_4VPrefix)
+ assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 &&
+ "Unexpected number of operands for MRMDestRegFrm with VEX_4V");
+ else
+ assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
+ "Unexpected number of operands for MRMDestRegFrm");
+
HANDLE_OPERAND(rmRegister)
+
+ if (HasVEX_4VPrefix)
+ // 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)
+
HANDLE_OPERAND(roRegister)
HANDLE_OPTIONAL(immediate)
break;
case X86Local::MRMDestMem:
// Operand 1 is a memory operand (possibly SIB-extended)
// 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.
- assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
- "Unexpected number of operands for MRMDestMemFrm");
+ if (HasVEX_4VPrefix)
+ assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 &&
+ "Unexpected number of operands for MRMDestMemFrm with VEX_4V");
+ else
+ assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
+ "Unexpected number of operands for MRMDestMemFrm");
HANDLE_OPERAND(memory)
+
+ if (HasVEX_4VPrefix)
+ // 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)
+
HANDLE_OPERAND(roRegister)
HANDLE_OPTIONAL(immediate)
break;
case X86Local::MRMSrcReg:
// Operand 1 is a register operand in the Reg/Opcode field.
// Operand 2 is a register operand in the R/M field.
+ // - In AVX, there is a register operand in the VEX.vvvv field here -
// Operand 3 (optional) is an immediate.
- assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
- "Unexpected number of operands for MRMSrcRegFrm");
- HANDLE_OPERAND(roRegister)
- HANDLE_OPERAND(rmRegister)
if (HasVEX_4VPrefix)
+ assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 &&
+ "Unexpected number of operands for MRMSrcRegFrm with VEX_4V");
+ else
+ assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
+ "Unexpected number of operands for MRMSrcRegFrm");
+
+ HANDLE_OPERAND(roRegister)
+
+ if (HasVEX_4VPrefix)
// FIXME: In AVX, the register below becomes the one encoded
// in ModRMVEX and the one above the one in the VEX.VVVV field
- HANDLE_OPTIONAL(rmRegister)
- else
- HANDLE_OPTIONAL(immediate)
+ HANDLE_OPERAND(vvvvRegister)
+
+ HANDLE_OPERAND(rmRegister)
+ HANDLE_OPTIONAL(immediate)
break;
case X86Local::MRMSrcMem:
// Operand 1 is a register operand in the Reg/Opcode field.
// Operand 2 is a memory operand (possibly SIB-extended)
+ // - In AVX, there is a register operand in the VEX.vvvv field here -
// Operand 3 (optional) is an immediate.
- assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
- "Unexpected number of operands for MRMSrcMemFrm");
+
+ if (HasVEX_4VPrefix)
+ assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 &&
+ "Unexpected number of operands for MRMSrcMemFrm with VEX_4V");
+ else
+ assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
+ "Unexpected number of operands for MRMSrcMemFrm");
+
HANDLE_OPERAND(roRegister)
if (HasVEX_4VPrefix)
// FIXME: In AVX, the register below becomes the one encoded
// in ModRMVEX and the one above the one in the VEX.VVVV field
- HANDLE_OPTIONAL(rmRegister)
+ HANDLE_OPERAND(vvvvRegister)
HANDLE_OPERAND(memory)
HANDLE_OPTIONAL(immediate)
@@ -567,8 +734,14 @@
case X86Local::MRM7r:
// Operand 1 is a register operand in the R/M field.
// Operand 2 (optional) is an immediate or relocation.
- assert(numPhysicalOperands <= 2 &&
- "Unexpected number of operands for MRMnRFrm");
+ if (HasVEX_4VPrefix)
+ assert(numPhysicalOperands <= 3 &&
+ "Unexpected number of operands for MRMSrcMemFrm with VEX_4V");
+ else
+ assert(numPhysicalOperands <= 2 &&
+ "Unexpected number of operands for MRMnRFrm");
+ if (HasVEX_4VPrefix)
+ HANDLE_OPERAND(vvvvRegister);
HANDLE_OPTIONAL(rmRegister)
HANDLE_OPTIONAL(relocation)
break;
@@ -587,6 +760,20 @@
HANDLE_OPERAND(memory)
HANDLE_OPTIONAL(relocation)
break;
+ case X86Local::RawFrmImm8:
+ // operand 1 is a 16-bit immediate
+ // operand 2 is an 8-bit immediate
+ assert(numPhysicalOperands == 2 &&
+ "Unexpected number of operands for X86Local::RawFrmImm8");
+ HANDLE_OPERAND(immediate)
+ HANDLE_OPERAND(immediate)
+ break;
+ case X86Local::RawFrmImm16:
+ // operand 1 is a 16-bit immediate
+ // operand 2 is a 16-bit immediate
+ HANDLE_OPERAND(immediate)
+ HANDLE_OPERAND(immediate)
+ break;
case X86Local::MRMInitReg:
// Ignored.
break;
@@ -656,6 +843,7 @@
opcodeToSet = Opcode;
break;
case X86Local::T8:
+ case X86Local::TF:
opcodeType = THREEBYTE_38;
if (needsModRMForDecode(Form))
filter = new ModFilter(isRegFormat(Form));
@@ -671,6 +859,22 @@
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::D8:
case X86Local::D9:
case X86Local::DA:
@@ -690,6 +894,7 @@
}
opcodeToSet = 0xd8 + (Prefix - X86Local::D8);
break;
+ case X86Local::REP:
default:
opcodeType = ONEBYTE;
switch (Opcode) {
@@ -761,7 +966,7 @@
insnContext(),
currentOpcode,
*filter,
- UID);
+ UID, Is32Bit, IgnoresVEX_L);
Spec->modifierType = MODIFIER_OPCODE;
Spec->modifierBase = opcodeToSet;
@@ -771,14 +976,14 @@
insnContext(),
opcodeToSet,
*filter,
- UID);
+ UID, Is32Bit, IgnoresVEX_L);
}
} else {
tables.setTableFields(opcodeType,
insnContext(),
opcodeToSet,
*filter,
- UID);
+ UID, Is32Bit, IgnoresVEX_L);
Spec->modifierType = MODIFIER_NONE;
Spec->modifierBase = opcodeToSet;
@@ -819,6 +1024,7 @@
TYPE("i32mem", TYPE_Mv)
TYPE("i32imm", TYPE_IMMv)
TYPE("i32i8imm", TYPE_IMM32)
+ TYPE("u32u8imm", TYPE_IMM32)
TYPE("GR32", TYPE_Rv)
TYPE("i64mem", TYPE_Mv)
TYPE("i64i32imm", TYPE_IMM64)
@@ -829,17 +1035,22 @@
TYPE("GR8", TYPE_R8)
TYPE("VR128", TYPE_XMM128)
TYPE("f128mem", TYPE_M128)
+ TYPE("f256mem", TYPE_M256)
TYPE("FR64", TYPE_XMM64)
TYPE("f64mem", TYPE_M64FP)
+ TYPE("sdmem", TYPE_M64FP)
TYPE("FR32", TYPE_XMM32)
TYPE("f32mem", TYPE_M32FP)
+ TYPE("ssmem", TYPE_M32FP)
TYPE("RST", TYPE_ST)
TYPE("i128mem", TYPE_M128)
+ TYPE("i256mem", TYPE_M256)
TYPE("i64i32imm_pcrel", TYPE_REL64)
TYPE("i16imm_pcrel", TYPE_REL16)
TYPE("i32imm_pcrel", TYPE_REL32)
TYPE("SSECC", TYPE_IMM3)
TYPE("brtarget", TYPE_RELv)
+ TYPE("uncondbrtarget", TYPE_RELv)
TYPE("brtarget8", TYPE_REL8)
TYPE("f80mem", TYPE_M80FP)
TYPE("lea32mem", TYPE_LEA)
@@ -858,6 +1069,10 @@
TYPE("offset16", TYPE_MOFFS16)
TYPE("offset32", TYPE_MOFFS32)
TYPE("offset64", TYPE_MOFFS64)
+ TYPE("VR256", TYPE_XMM256)
+ TYPE("GR16_NOAX", TYPE_Rv)
+ TYPE("GR32_NOAX", TYPE_Rv)
+ TYPE("GR64_NOAX", TYPE_R64)
errs() << "Unhandled type string " << s << "\n";
llvm_unreachable("Unhandled type string");
}
@@ -873,6 +1088,7 @@
ENCODING("i16imm", ENCODING_IW)
}
ENCODING("i32i8imm", ENCODING_IB)
+ ENCODING("u32u8imm", ENCODING_IB)
ENCODING("SSECC", ENCODING_IB)
ENCODING("i16imm", ENCODING_Iv)
ENCODING("i16i8imm", ENCODING_IB)
@@ -880,6 +1096,10 @@
ENCODING("i64i32imm", ENCODING_ID)
ENCODING("i64i8imm", ENCODING_IB)
ENCODING("i8imm", ENCODING_IB)
+ // This is not a typo. Instructions like BLENDVPD put
+ // register IDs in 8-bit immediates nowadays.
+ ENCODING("VR256", ENCODING_IB)
+ ENCODING("VR128", ENCODING_IB)
errs() << "Unhandled immediate encoding " << s << "\n";
llvm_unreachable("Unhandled immediate encoding");
}
@@ -895,6 +1115,7 @@
ENCODING("FR64", ENCODING_RM)
ENCODING("FR32", ENCODING_RM)
ENCODING("VR64", ENCODING_RM)
+ ENCODING("VR256", ENCODING_RM)
errs() << "Unhandled R/M register encoding " << s << "\n";
llvm_unreachable("Unhandled R/M register encoding");
}
@@ -913,10 +1134,24 @@
ENCODING("SEGMENT_REG", ENCODING_REG)
ENCODING("DEBUG_REG", ENCODING_REG)
ENCODING("CONTROL_REG", ENCODING_REG)
+ ENCODING("VR256", 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) {
+ ENCODING("GR32", ENCODING_VVVV)
+ ENCODING("GR64", ENCODING_VVVV)
+ ENCODING("FR32", ENCODING_VVVV)
+ ENCODING("FR64", ENCODING_VVVV)
+ ENCODING("VR128", ENCODING_VVVV)
+ ENCODING("VR256", ENCODING_VVVV)
+ errs() << "Unhandled VEX.vvvv register encoding " << s << "\n";
+ llvm_unreachable("Unhandled VEX.vvvv register encoding");
+}
+
OperandEncoding RecognizableInstr::memoryEncodingFromString
(const std::string &s,
bool hasOpSizePrefix) {
@@ -924,10 +1159,14 @@
ENCODING("i32mem", ENCODING_RM)
ENCODING("i64mem", ENCODING_RM)
ENCODING("i8mem", ENCODING_RM)
+ ENCODING("ssmem", ENCODING_RM)
+ ENCODING("sdmem", ENCODING_RM)
ENCODING("f128mem", ENCODING_RM)
+ ENCODING("f256mem", ENCODING_RM)
ENCODING("f64mem", ENCODING_RM)
ENCODING("f32mem", ENCODING_RM)
ENCODING("i128mem", ENCODING_RM)
+ ENCODING("i256mem", ENCODING_RM)
ENCODING("f80mem", ENCODING_RM)
ENCODING("lea32mem", ENCODING_RM)
ENCODING("lea64_32mem", ENCODING_RM)
@@ -977,6 +1216,9 @@
ENCODING("GR64", ENCODING_RO)
ENCODING("GR16", ENCODING_Rv)
ENCODING("GR8", ENCODING_RB)
+ ENCODING("GR16_NOAX", ENCODING_Rv)
+ ENCODING("GR32_NOAX", ENCODING_Rv)
+ ENCODING("GR64_NOAX", ENCODING_RO)
errs() << "Unhandled opcode modifier encoding " << s << "\n";
llvm_unreachable("Unhandled opcode modifier encoding");
}
diff --git a/src/LLVM/utils/TableGen/X86RecognizableInstr.h b/src/LLVM/utils/TableGen/X86RecognizableInstr.h
index db4d96d..4441597 100644
--- a/src/LLVM/utils/TableGen/X86RecognizableInstr.h
+++ b/src/LLVM/utils/TableGen/X86RecognizableInstr.h
@@ -20,9 +20,9 @@
#include "X86DisassemblerTables.h"
#include "CodeGenTarget.h"
-#include "Record.h"
-#include "llvm/System/DataTypes.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/Support/DataTypes.h"
#include "llvm/ADT/SmallVector.h"
namespace llvm {
@@ -52,12 +52,24 @@
bool HasOpSizePrefix;
/// 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_WPrefix field from the record
+ bool HasVEX_WPrefix;
+ /// Inferred from the operands; indicates whether the L bit in the VEX prefix is set
+ bool HasVEX_LPrefix;
+ // The ignoreVEX_L field from the record
+ bool IgnoresVEX_L;
/// The hasLockPrefix field from the record
bool HasLockPrefix;
/// The isCodeGenOnly filed from the record
bool IsCodeGenOnly;
+ // Whether the instruction has the predicate "In64BitMode"
+ bool Is64Bit;
+ // Whether the instruction has the predicate "In32BitMode"
+ bool Is32Bit;
/// The instruction name as listed in the tables
std::string Name;
@@ -76,7 +88,8 @@
/// The operands of the instruction, as listed in the CodeGenInstruction.
/// They are not one-to-one with operands listed in the MCInst; for example,
/// memory operands expand to 5 operands in the MCInst
- const std::vector<CodeGenInstruction::OperandInfo>* Operands;
+ const std::vector<CGIOperandList::OperandInfo>* Operands;
+
/// The description of the instruction that is emitted into the instruction
/// info table
InstructionSpecifier* Spec;
@@ -95,7 +108,7 @@
// 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
@@ -105,6 +118,12 @@
///
/// @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;
+
+ /// has256BitOperands - Returns true if any operand is a 256-bit SSE operand.
+ bool has256BitOperands() const;
/// typeFromString - Translates an operand type from the string provided in
/// the LLVM tables to an OperandType for use in the operand specifier.
@@ -154,6 +173,8 @@
bool hasOpSizePrefix);
static OperandEncoding opcodeModifierEncodingFromString(const std::string &s,
bool hasOpSizePrefix);
+ static OperandEncoding vvvvRegisterEncodingFromString(const std::string &s,
+ bool HasOpSizePrefix);
/// handleOperand - Converts a single operand from the LLVM table format to
/// the emitted table format, handling any duplicate operands it encounters
diff --git a/src/LLVM/utils/TableGen/llvm-tblgen.vcxproj b/src/LLVM/utils/TableGen/llvm-tblgen.vcxproj
new file mode 100644
index 0000000..3572d30
--- /dev/null
+++ b/src/LLVM/utils/TableGen/llvm-tblgen.vcxproj
@@ -0,0 +1,476 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Profile|Win32">
+ <Configuration>Profile</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Profile|x64">
+ <Configuration>Profile</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGUID>{1F8587CB-0779-44BB-AFA4-03DD8A036D75}</ProjectGUID>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>llvm-tblgen</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Profile|x64'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectName)</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.exe</TargetExt>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</GenerateManifest>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</GenerateManifest>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(Platform)\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</OutDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Profile|x64'">$(Platform)\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(Platform)\$(Configuration)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Profile|x64'">$(Platform)\$(Configuration)\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectName)</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Profile|x64'">$(ProjectName)</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.exe</TargetExt>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">.exe</TargetExt>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.exe</TargetExt>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Profile|x64'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Profile|x64'">false</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</GenerateManifest>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">true</GenerateManifest>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</GenerateManifest>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Profile|x64'">true</GenerateManifest>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>Disabled</Optimization>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>Debug</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/Debug/llvm-tblgen.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalOptions> /machine:X86 /debug %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/Debug/llvm-tblgen.lib</ImportLibrary>
+ <LinkIncremental>true</LinkIncremental>
+ <ProgramDataBaseFileName>..\..\bin/Debug/llvm-tblgen.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>true</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>Disabled</Optimization>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>Debug</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/Debug/llvm-tblgen.pdb</ProgramDataBaseFileName>
+ <OmitFramePointers>false</OmitFramePointers>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalOptions>/debug %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/Debug/llvm-tblgen.lib</ImportLibrary>
+ <LinkIncremental>true</LinkIncremental>
+ <ProgramDataBaseFileName>..\..\bin/Debug/llvm-tblgen.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>true</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>MaxSpeed</Optimization>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>Release</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/Release/llvm-tblgen.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalOptions> /machine:X86 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/Release/llvm-tblgen.lib</ImportLibrary>
+ <ProgramDataBaseFileName>..\..\bin/Release/llvm-tblgen.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>true</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>MaxSpeed</Optimization>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>Release</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/Release/llvm-tblgen.pdb</ProgramDataBaseFileName>
+ <OmitFramePointers>false</OmitFramePointers>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalOptions> /machine:X86 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/Release/llvm-tblgen.lib</ImportLibrary>
+ <ProgramDataBaseFileName>..\..\bin/Release/llvm-tblgen.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>true</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>MaxSpeed</Optimization>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>Release</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/Release/llvm-tblgen.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/Release/llvm-tblgen.lib</ImportLibrary>
+ <ProgramDataBaseFileName>..\..\bin/Release/llvm-tblgen.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>true</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Profile|x64'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>MaxSpeed</Optimization>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>true</RuntimeTypeInfo>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;CMAKE_INTDIR="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>Release</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/Release/llvm-tblgen.pdb</ProgramDataBaseFileName>
+ <OmitFramePointers>false</OmitFramePointers>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\TableGen;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/Release/llvm-tblgen.lib</ImportLibrary>
+ <ProgramDataBaseFileName>..\..\bin/Release/llvm-tblgen.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>true</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="ARMDecoderEmitter.cpp" />
+ <ClCompile Include="AsmMatcherEmitter.cpp" />
+ <ClCompile Include="AsmWriterEmitter.cpp" />
+ <ClCompile Include="AsmWriterInst.cpp" />
+ <ClCompile Include="CallingConvEmitter.cpp" />
+ <ClCompile Include="CodeEmitterGen.cpp" />
+ <ClCompile Include="CodeGenDAGPatterns.cpp" />
+ <ClCompile Include="CodeGenInstruction.cpp" />
+ <ClCompile Include="CodeGenRegisters.cpp" />
+ <ClCompile Include="CodeGenTarget.cpp" />
+ <ClCompile Include="DAGISelEmitter.cpp" />
+ <ClCompile Include="DAGISelMatcherEmitter.cpp" />
+ <ClCompile Include="DAGISelMatcherGen.cpp" />
+ <ClCompile Include="DAGISelMatcherOpt.cpp" />
+ <ClCompile Include="DAGISelMatcher.cpp" />
+ <ClCompile Include="DisassemblerEmitter.cpp" />
+ <ClCompile Include="EDEmitter.cpp" />
+ <ClCompile Include="FastISelEmitter.cpp" />
+ <ClCompile Include="FixedLenDecoderEmitter.cpp" />
+ <ClCompile Include="InstrEnumEmitter.cpp" />
+ <ClCompile Include="InstrInfoEmitter.cpp" />
+ <ClCompile Include="IntrinsicEmitter.cpp" />
+ <ClCompile Include="PseudoLoweringEmitter.cpp" />
+ <ClCompile Include="RegisterInfoEmitter.cpp" />
+ <ClCompile Include="SetTheory.cpp" />
+ <ClCompile Include="StringMatcher.cpp" />
+ <ClCompile Include="SubtargetEmitter.cpp" />
+ <ClCompile Include="TGValueTypes.cpp" />
+ <ClCompile Include="TableGen.cpp" />
+ <ClCompile Include="X86DisassemblerTables.cpp" />
+ <ClCompile Include="X86RecognizableInstr.cpp" />
+ <ClInclude Include="ARMDecoderEmitter.h" />
+ <ClInclude Include="AsmMatcherEmitter.h" />
+ <ClInclude Include="AsmWriterEmitter.h" />
+ <ClInclude Include="AsmWriterInst.h" />
+ <ClInclude Include="CallingConvEmitter.h" />
+ <ClInclude Include="CodeEmitterGen.h" />
+ <ClInclude Include="CodeGenDAGPatterns.h" />
+ <ClInclude Include="CodeGenInstruction.h" />
+ <ClInclude Include="CodeGenIntrinsics.h" />
+ <ClInclude Include="CodeGenRegisters.h" />
+ <ClInclude Include="CodeGenTarget.h" />
+ <ClInclude Include="DAGISelEmitter.h" />
+ <ClInclude Include="DAGISelMatcher.h" />
+ <ClInclude Include="DisassemblerEmitter.h" />
+ <ClInclude Include="EDEmitter.h" />
+ <ClInclude Include="FastISelEmitter.h" />
+ <ClInclude Include="FixedLenDecoderEmitter.h" />
+ <ClInclude Include="InstrEnumEmitter.h" />
+ <ClInclude Include="InstrInfoEmitter.h" />
+ <ClInclude Include="IntrinsicEmitter.h" />
+ <ClInclude Include="PseudoLoweringEmitter.h" />
+ <ClInclude Include="RegisterInfoEmitter.h" />
+ <ClInclude Include="SetTheory.h" />
+ <ClInclude Include="StringMatcher.h" />
+ <ClInclude Include="StringToOffsetTable.h" />
+ <ClInclude Include="SubtargetEmitter.h" />
+ <ClInclude Include="X86DisassemblerShared.h" />
+ <ClInclude Include="X86DisassemblerTables.h" />
+ <ClInclude Include="X86ModRMFilters.h" />
+ <ClInclude Include="X86RecognizableInstr.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\lib/Support/LLVMSupport.vcxproj">
+ <Project>C688DD59-C6CB-4B33-B56F-A7D6F3761524</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\..\lib/TableGen/LLVMTableGen.vcxproj">
+ <Project>BD8EE868-0D68-4A92-B277-3C9EBDC5EC3C</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/src/LLVM/utils/TableGen/llvm-tblgen.vcxproj.filters b/src/LLVM/utils/TableGen/llvm-tblgen.vcxproj.filters
new file mode 100644
index 0000000..82d29fa
--- /dev/null
+++ b/src/LLVM/utils/TableGen/llvm-tblgen.vcxproj.filters
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="ARMDecoderEmitter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="AsmMatcherEmitter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="AsmWriterEmitter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="AsmWriterInst.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="CallingConvEmitter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="CodeEmitterGen.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="CodeGenDAGPatterns.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="CodeGenInstruction.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="CodeGenRegisters.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="CodeGenTarget.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="DAGISelEmitter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="DAGISelMatcherEmitter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="DAGISelMatcherGen.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="DAGISelMatcherOpt.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="DAGISelMatcher.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="DisassemblerEmitter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="EDEmitter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="FastISelEmitter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="FixedLenDecoderEmitter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="InstrEnumEmitter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="InstrInfoEmitter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="IntrinsicEmitter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="PseudoLoweringEmitter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="RegisterInfoEmitter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="SetTheory.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="StringMatcher.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="SubtargetEmitter.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="TGValueTypes.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="TableGen.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="X86DisassemblerTables.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="X86RecognizableInstr.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="ARMDecoderEmitter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="AsmMatcherEmitter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="AsmWriterEmitter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="AsmWriterInst.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="CallingConvEmitter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="CodeEmitterGen.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="CodeGenDAGPatterns.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="CodeGenInstruction.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="CodeGenIntrinsics.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="CodeGenRegisters.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="CodeGenTarget.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="DAGISelEmitter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="DAGISelMatcher.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="DisassemblerEmitter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="EDEmitter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="FastISelEmitter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="FixedLenDecoderEmitter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="InstrEnumEmitter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="InstrInfoEmitter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="IntrinsicEmitter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="PseudoLoweringEmitter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="RegisterInfoEmitter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="SetTheory.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="StringMatcher.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="StringToOffsetTable.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="SubtargetEmitter.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="X86DisassemblerShared.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="X86DisassemblerTables.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="X86ModRMFilters.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="X86RecognizableInstr.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{1733179C-6FE4-462E-9EA5-4A29A1ACFE25}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{CFA0CD99-0550-4E94-A4D9-080C3F5D695C}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/src/LLVM/utils/Target/ARM/analyze-match-table.py b/src/LLVM/utils/Target/ARM/analyze-match-table.py
new file mode 100644
index 0000000..aa952d4
--- /dev/null
+++ b/src/LLVM/utils/Target/ARM/analyze-match-table.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+
+def analyze_match_table(path):
+ # Extract the instruction table.
+ data = open(path).read()
+ start = data.index("static const MatchEntry MatchTable")
+ end = data.index("\n};\n", start)
+ lines = data[start:end].split("\n")[1:]
+
+ # Parse the instructions.
+ insns = []
+ for ln in lines:
+ ln = ln.split("{", 1)[1]
+ ln = ln.rsplit("}", 1)[0]
+ a,bc = ln.split("{", 1)
+ b,c = bc.split("}", 1)
+ code, string, converter, _ = [s.strip()
+ for s in a.split(",")]
+ items = [s.strip() for s in b.split(",")]
+ _,features = [s.strip() for s in c.split(",")]
+ assert string[0] == string[-1] == '"'
+ string = string[1:-1]
+ insns.append((code,string,converter,items,features))
+
+ # For every mnemonic, compute whether or not it can have a carry setting
+ # operand and whether or not it can have a predication code.
+ mnemonic_flags = {}
+ for insn in insns:
+ mnemonic = insn[1]
+ items = insn[3]
+ flags = mnemonic_flags[mnemonic] = mnemonic_flags.get(mnemonic, set())
+ flags.update(items)
+
+ mnemonics = set(mnemonic_flags)
+ ccout_mnemonics = set(m for m in mnemonics
+ if 'MCK_CCOut' in mnemonic_flags[m])
+ condcode_mnemonics = set(m for m in mnemonics
+ if 'MCK_CondCode' in mnemonic_flags[m])
+ noncondcode_mnemonics = mnemonics - condcode_mnemonics
+ print ' || '.join('Mnemonic == "%s"' % m
+ for m in ccout_mnemonics)
+ print ' || '.join('Mnemonic == "%s"' % m
+ for m in noncondcode_mnemonics)
+
+def main():
+ import sys
+ if len(sys.argv) == 1:
+ import os
+ from lit.Util import capture
+ llvm_obj_root = capture(["llvm-config", "--obj-root"])
+ file = os.path.join(llvm_obj_root,
+ "lib/Target/ARM/ARMGenAsmMatcher.inc")
+ elif len(sys.argv) == 2:
+ file = sys.argv[1]
+ else:
+ raise NotImplementedError
+
+ analyze_match_table(file)
+
+if __name__ == '__main__':
+ main()
diff --git a/src/LLVM/utils/buildit/GNUmakefile b/src/LLVM/utils/buildit/GNUmakefile
index 08904e6..470ee76 100644
--- a/src/LLVM/utils/buildit/GNUmakefile
+++ b/src/LLVM/utils/buildit/GNUmakefile
@@ -6,7 +6,7 @@
#
# You can specify TARGETS=ppc (or i386) on the buildit command line to limit the
# build to just one target. The default is for ppc and i386. The compiler
-# targetted at this host gets built anyway, but not installed unless it's listed
+# targeted at this host gets built anyway, but not installed unless it's listed
# in TARGETS.
# Include the set of standard Apple makefile definitions.
@@ -71,14 +71,18 @@
$(RC_ProjectSourceVersion) $(RC_ProjectSourceSubversion)
EmbeddedHosted:
- $(MAKE) ARM_HOSTED_BUILD=yes PREFIX=/usr install
+ $(MAKE) ARM_HOSTED_BUILD=yes PREFIX=/usr/local install
# When building for the iOS simulator, MACOSX_DEPLOYMENT_TARGET is not set
# by default, but it needs to be set when building tools that run on the host
# (e.g., tblgen), so set it here.
EmbeddedSim:
export MACOSX_DEPLOYMENT_TARGET=`sw_vers -productVersion`; \
- $(MAKE) IOS_SIM_BUILD=yes PREFIX=$(SDKROOT)/usr install
+ $(MAKE) IOS_SIM_BUILD=yes PREFIX=$(SDKROOT)/usr/local install
+
+Embedded:
+ ARM_PLATFORM=`xcodebuild -version -sdk iphoneos PlatformPath` && \
+ $(MAKE) DSTROOT=$(DSTROOT)$$ARM_PLATFORM install
# installhdrs does nothing, because the headers aren't useful until
# the compiler is installed.
@@ -128,4 +132,4 @@
$(OBJROOT) $(SYMROOT) $(DSTROOT):
mkdir -p $@
-.PHONY: install installsrc clean EmbeddedHosted EmbeddedSim
+.PHONY: install installsrc clean EmbeddedHosted EmbeddedSim Embedded
diff --git a/src/LLVM/utils/buildit/build_llvm b/src/LLVM/utils/buildit/build_llvm
index 39ec1cc..0ffbc19 100644
--- a/src/LLVM/utils/buildit/build_llvm
+++ b/src/LLVM/utils/buildit/build_llvm
@@ -97,31 +97,16 @@
echo 'exec '$T' "$@"' >> $P || exit 1
chmod a+x $P || exit 1
done
- # Try to use the platform llvm-gcc. Fall back to gcc if it's not available.
- for prog in gcc g++ ; do
+ # Set up the links for clang.
+ for prog in clang clang++ ; do
P=$DIR/bin/arm-apple-darwin$DARWIN_VERS-${prog}
- T=`xcrun -sdk $SDKROOT -find llvm-${prog}`
- if [ "x$T" = "x" ] ; then
- T=`xcrun -sdk $SDKROOT -find ${prog}`
- fi
+ T=`xcrun -sdk $SDKROOT -find ${prog}`
echo '#!/bin/sh' > $P || exit 1
- echo 'exec '$T' -arch armv6 -isysroot '${SDKROOT}' "$@"' >> $P || exit 1
+ echo 'exec '$T' -arch armv7 -isysroot '${SDKROOT}' "$@"' >> $P || exit 1
chmod a+x $P || exit 1
done
PATH=$DIR/bin:$PATH
-# otherwise, try to use llvm-gcc if it's available
-elif [ $DARWIN_VERS -gt 9 ]; then
- # If the user has set CC or CXX, respect their wishes. If not,
- # compile with LLVM-GCC/LLVM-G++ if available; if LLVM is not
- # available, fall back to usual GCC/G++ default.
- savedPATH=$PATH ; PATH="/Developer/usr/bin:$PATH"
- XTMPCC=$(which llvm-gcc)
- if [ x$CC = x -a x$XTMPCC != x ] ; then export CC=$XTMPCC ; fi
- XTMPCC=$(which llvm-g++)
- if [ x$CXX = x -a x$XTMPCC != x ] ; then export CXX=$XTMPCC ; fi
- PATH=$savedPATH
- unset XTMPCC savedPATH
fi
if [ "$ARM_HOSTED_BUILD" = yes ]; then
@@ -132,7 +117,7 @@
configure_opts="--enable-targets=x86 --host=i686-apple-darwin_sim \
--build=i686-apple-darwin10"
else
- configure_opts="--enable-targets=arm,x86,powerpc,cbe"
+ configure_opts="--enable-targets=arm,x86,cbe"
fi
if [ \! -f Makefile.config ]; then
@@ -157,37 +142,15 @@
LLVM_VERSION="$LLVM_SUBMIT_VERSION-$LLVM_SUBMIT_SUBVERSION"
fi
-GCC_VER=`cc --version 2>/dev/null | sed 1q`
-
-if echo "$GCC_VER" | grep GCC > /dev/null; then
- GCC_VER=`echo $GCC_VER | sed -e 's/.*(GCC) \([0-9.][0-9.]*\).*/\1/'`
- MAJ_VER=`echo $GCC_VER | sed 's/\..*//'`
- MIN_VER=`echo $GCC_VER | sed 's/[^.]*\.\([0-9]*\).*/\1/'`
+# 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.
+# Builders can default to 2, since even if they are single processor,
+# nothing else is running on the machine.
+if [ -z "$SYSCTL" ]; then
+ SYSCTL=2
fi
-
-JOBS_FLAG=""
-
-# Note: If compiling with GCC 4.0, don't pass the -jN flag. Building universal
-# already has parallelism and we don't want to make the builders hit swap by
-# firing off too many gccs at the same time.
-if [ "x$MAJ_VER" != "x4" -o "x$MIN_VER" != "x0" ]; then
- # Figure out how many make processes to run.
- SYSCTL=`sysctl -n hw.activecpu`
-
- # hw.activecpu only available in 10.2.6 and later
- if [ -z "$SYSCTL" ]; then
- SYSCTL=`sysctl -n hw.ncpu`
- fi
-
- # sysctl -n hw.* does not work when invoked via B&I chroot /BuildRoot.
- # Builders can default to 2, since even if they are single processor,
- # nothing else is running on the machine.
- if [ -z "$SYSCTL" ]; then
- SYSCTL=2
- fi
-
- JOBS_FLAG="-j $SYSCTL"
-fi
+JOBS_FLAG="-j $SYSCTL"
make $JOBS_FLAG $OPTIMIZE_OPTS UNIVERSAL=1 UNIVERSAL_ARCH="$HOSTS" \
UNIVERSAL_SDK_PATH=$SDKROOT \
@@ -238,14 +201,20 @@
echo "#define LLVM_VERSION ${RC_ProjectSourceVersion}" > $DEST_DIR$DEST_ROOT/include/llvm/Version.h
echo "#define LLVM_MINOR_VERSION ${RC_ProjectSourceSubversion}" >> $DEST_DIR$DEST_ROOT/include/llvm/Version.h
+# Find the right version of strip to use.
+STRIP=strip
+if [ -n "$SDKROOT" ]; then
+ STRIP=`xcrun -sdk $SDKROOT -find strip`
+fi
+
if [ "x$LLVM_DEBUG" != "x1" ]; then
# Strip local symbols from llvm libraries.
#
# Use '-l' to strip i386 modules. N.B. that flag doesn't work with kext or
# PPC objects!
- strip -Sl $DEST_DIR$DEST_ROOT/lib/*.[oa]
+ $STRIP -Sl $DEST_DIR$DEST_ROOT/lib/*.[oa]
for f in `ls $DEST_DIR$DEST_ROOT/lib/*.so`; do
- strip -Sxl $f
+ $STRIP -Sxl $f
done
fi
@@ -266,11 +235,15 @@
-exec lipo -extract ppc7400 -extract i386 {} -output {} \;
else
find . -perm 755 -type f \! \( -name '*gccas' -o -name '*gccld' -o -name llvm-config \) \
- -exec lipo -extract ppc7400 -extract i386 -extract x86_64 {} -output {} \;
+ -exec lipo -extract i386 -extract x86_64 {} -output {} \;
fi
-# The Hello dylib is an example of how to build a pass. No need to install it.
-rm $DEST_DIR$DEST_ROOT/lib/LLVMHello.dylib
+# The Hello dylib is an example of how to build a pass.
+# The BugpointPasses module is only used to test bugpoint.
+# These unversioned dylibs cause verification failures, so do not install them.
+# (The wildcards are used to match a "lib" prefix if it is present.)
+rm $DEST_DIR$DEST_ROOT/lib/*LLVMHello.dylib
+rm $DEST_DIR$DEST_ROOT/lib/*BugpointPasses.dylib
# Compress manpages
MDIR=$DEST_DIR$DEST_ROOT/share/man/man1
@@ -330,7 +303,7 @@
# Use '-l' to strip i386 modules. N.B. that flag doesn't work with kext or
# PPC objects!
- strip -arch all -Sl $DT_HOME/lib/libLTO.dylib
+ $STRIP -arch all -Sl $DT_HOME/lib/libLTO.dylib
if [ "x$DISABLE_USR_LINKS" == "x" ]; then
# Add a symlink in /usr/lib for B&I.
@@ -343,6 +316,9 @@
fi
rm -f lib/libLTO.a lib/libLTO.la
+# Omit lto.h from the result. Clang will supply.
+find $DEST_DIR$DEST_ROOT -name lto.h -delete
+
################################################################################
# Remove debugging information from DEST_DIR.
@@ -357,7 +333,7 @@
# PPC objects!
find $DEST_DIR -perm -0111 -type f \
! \( -name '*.la' -o -name gccas -o -name gccld -o -name llvm-config \) \
- -print | xargs -n 1 -P ${SYSCTL} strip -arch all -Sl
+ -print | xargs -n 1 -P ${SYSCTL} $STRIP -arch all -Sl
chgrp -h -R wheel $DEST_DIR
chgrp -R wheel $DEST_DIR
diff --git a/src/LLVM/utils/count/INSTALL.vcxproj b/src/LLVM/utils/count/INSTALL.vcxproj
new file mode 100644
index 0000000..af6d5fd
--- /dev/null
+++ b/src/LLVM/utils/count/INSTALL.vcxproj
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGUID>{048BB775-7681-4EE1-AACF-5A067ACEEEA5}</ProjectGUID>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>INSTALL</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\count;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\count;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\count;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\count;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\INSTALL_force.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\generate.stamp</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\ALL_BUILD.vcxproj">
+ <Project>17AECBCF-B2AE-4524-9010-9A175A8F6BFE</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/src/LLVM/utils/count/INSTALL.vcxproj.filters b/src/LLVM/utils/count/INSTALL.vcxproj.filters
new file mode 100644
index 0000000..251dd1d
--- /dev/null
+++ b/src/LLVM/utils/count/INSTALL.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\INSTALL_force.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ <CustomBuild Include="CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{71794486-B3CB-4A48-93CC-DE95557E96E1}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
diff --git a/src/LLVM/utils/count/PACKAGE.vcxproj b/src/LLVM/utils/count/PACKAGE.vcxproj
new file mode 100644
index 0000000..cc7a80b
--- /dev/null
+++ b/src/LLVM/utils/count/PACKAGE.vcxproj
@@ -0,0 +1,277 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGUID>{1B050569-3318-48D9-8BB0-4DE9EF58B202}</ProjectGUID>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>PACKAGE</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\count;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\count;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\count;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\count;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\PACKAGE_force.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\generate.stamp</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\ALL_BUILD.vcxproj">
+ <Project>17AECBCF-B2AE-4524-9010-9A175A8F6BFE</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/src/LLVM/utils/count/PACKAGE.vcxproj.filters b/src/LLVM/utils/count/PACKAGE.vcxproj.filters
new file mode 100644
index 0000000..a570359
--- /dev/null
+++ b/src/LLVM/utils/count/PACKAGE.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\PACKAGE_force.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ <CustomBuild Include="CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{71794486-B3CB-4A48-93CC-DE95557E96E1}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
diff --git a/src/LLVM/utils/count/count.vcxproj b/src/LLVM/utils/count/count.vcxproj
new file mode 100644
index 0000000..226cfcb
--- /dev/null
+++ b/src/LLVM/utils/count/count.vcxproj
@@ -0,0 +1,338 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGUID>{D65DD481-0042-44B3-B31C-92D19078BAAE}</ProjectGUID>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>count</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\bin\Debug\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">count.dir\Debug\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">count</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</GenerateManifest>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\bin\Release\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">count.dir\Release\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">count</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</GenerateManifest>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">..\..\bin\MinSizeRel\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">count.dir\MinSizeRel\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">count</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">true</GenerateManifest>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">..\..\bin\RelWithDebInfo\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">count.dir\RelWithDebInfo\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">count</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">true</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">true</GenerateManifest>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\count;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <CompileAs>CompileAsC</CompileAs>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>Disabled</Optimization>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>Debug</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/Debug/count.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\count;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\count;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalOptions> /machine:X86 /debug %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/Debug/count.lib</ImportLibrary>
+ <LinkIncremental>true</LinkIncremental>
+ <ProgramDataBaseFileName>..\..\bin/Debug/count.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\count;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>MaxSpeed</Optimization>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>Release</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/Release/count.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\count;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\count;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalOptions> /machine:X86 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/Release/count.lib</ImportLibrary>
+ <ProgramDataBaseFileName>..\..\bin/Release/count.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\count;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>MinSpace</Optimization>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>MinSizeRel</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/MinSizeRel/count.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\count;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\count;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalOptions> /machine:X86 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/MinSizeRel/count.lib</ImportLibrary>
+ <ProgramDataBaseFileName>..\..\bin/MinSizeRel/count.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\count;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>MaxSpeed</Optimization>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>RelWithDebInfo</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/RelWithDebInfo/count.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\count;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\count;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalOptions> /machine:X86 /debug %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/RelWithDebInfo/count.lib</ImportLibrary>
+ <LinkIncremental>true</LinkIncremental>
+ <ProgramDataBaseFileName>..\..\bin/RelWithDebInfo/count.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\generate.stamp</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="count.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\include/llvm/intrinsics_gen.vcxproj">
+ <Project>E9B87B46-1EB0-4D95-9049-41B148FBADCD</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/src/LLVM/utils/count/count.vcxproj.filters b/src/LLVM/utils/count/count.vcxproj.filters
new file mode 100644
index 0000000..d79a3d3
--- /dev/null
+++ b/src/LLVM/utils/count/count.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="count.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{1733179C-6FE4-462E-9EA5-4A29A1ACFE25}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
diff --git a/src/LLVM/utils/emacs/llvm-mode.el b/src/LLVM/utils/emacs/llvm-mode.el
index 56b60bb..2652910 100644
--- a/src/LLVM/utils/emacs/llvm-mode.el
+++ b/src/LLVM/utils/emacs/llvm-mode.el
@@ -19,7 +19,7 @@
;; Unnamed variable slots
'("%[-]?[0-9]+" . font-lock-variable-name-face)
;; Types
- '("\\bvoid\\b\\|\\bi[0-9]+\\b\\|\\float\\b\\|\\bdouble\\b\\|\\btype\\b\\|\\blabel\\b\\|\\bopaque\\b" . font-lock-type-face)
+ `(,(regexp-opt '("void" "i[0-9]+" "float" "double" "type" "label" "opaque") 'words) . font-lock-type-face)
;; Integer literals
'("\\b[-]?[0-9]+\\b" . font-lock-preprocessor-face)
;; Floating point constants
@@ -27,15 +27,20 @@
;; Hex constants
'("\\b0x[0-9A-Fa-f]+\\b" . font-lock-preprocessor-face)
;; Keywords
- '("\\bbegin\\b\\|\\bend\\b\\|\\btrue\\b\\|\\bfalse\\b\\|\\bzeroinitializer\\b\\|\\bdeclare\\b\\|\\bdefine\\b\\|\\bglobal\\b\\|\\bconstant\\b\\|\\bconst\\b\\|\\binternal\\b\\|\\blinkonce\\b\\|\\blinkonce_odr\\b\\|\\bweak\\b\\|\\bweak_odr\\b\\|\\bappending\\b\\|\\buninitialized\\b\\|\\bimplementation\\b\\|\\b\\.\\.\\.\\b\\|\\bnull\\b\\|\\bundef\\b\\|\\bto\\b\\|\\bexcept\\b\\|\\bnot\\b\\|\\btarget\\b\\|\\bendian\\b\\|\\blittle\\b\\|\\bbig\\b\\|\\bpointersize\\b\\|\\bdeplibs\\b\\|\\bvolatile\\b\\|\\bfastcc\\b\\|\\bcoldcc\\b\\|\\bcc\\b" . font-lock-keyword-face)
+ `(,(regexp-opt '("begin" "end" "true" "false" "zeroinitializer" "declare"
+ "define" "global" "constant" "const" "internal" "linkonce" "linkonce_odr"
+ "weak" "weak_odr" "appending" "uninitialized" "implementation" "..."
+ "null" "undef" "to" "except" "not" "target" "endian" "little" "big"
+ "pointersize" "deplibs" "volatile" "fastcc" "coldcc" "cc") 'words) . font-lock-keyword-face)
;; Arithmetic and Logical Operators
- '("\\badd\\b\\|\\bsub\\b\\|\\bmul\\b\\|\\bdiv\\b\\|\\brem\\b\\|\\band\\b\\|\\bor\\b\\|\\bxor\\b\\|\\bset\\(ne\\b\\|\\beq\\b\\|\\blt\\b\\|\\bgt\\b\\|\\ble\\b\\|\\bge\\b\\)" . font-lock-keyword-face)
+ `(,(regexp-opt '("add" "sub" "mul" "div" "rem" "and" "or" "xor"
+ "setne" "seteq" "setlt" "setgt" "setle" "setge") 'words) . font-lock-keyword-face)
;; Special instructions
- '("\\bphi\\b\\|\\btail\\b\\|\\bcall\\b\\|\\bcast\\b\\|\\bselect\\b\\|\\bto\\b\\|\\bshl\\b\\|\\bshr\\b\\|\\bvaarg\\b\\|\\bvanext\\b" . font-lock-keyword-face)
+ `(,(regexp-opt '("phi" "tail" "call" "cast" "select" "to" "shl" "shr" "vaarg" "vanext") 'words) . font-lock-keyword-face)
;; Control instructions
- '("\\bret\\b\\|\\bbr\\b\\|\\bswitch\\b\\|\\binvoke\\b\\|\\bunwind\\b\\|\\bunreachable\\b" . font-lock-keyword-face)
+ `(,(regexp-opt '("ret" "br" "switch" "invoke" "unwind" "unreachable") 'words) . font-lock-keyword-face)
;; Memory operators
- '("\\bmalloc\\b\\|\\balloca\\b\\|\\bfree\\b\\|\\bload\\b\\|\\bstore\\b\\|\\bgetelementptr\\b" . font-lock-keyword-face)
+ `(,(regexp-opt '("malloc" "alloca" "free" "load" "store" "getelementptr") 'words) . font-lock-keyword-face)
)
"Syntax highlighting for LLVM"
)
diff --git a/src/LLVM/utils/emacs/tablegen-mode.el b/src/LLVM/utils/emacs/tablegen-mode.el
index 7989acf..a78f3e7 100644
--- a/src/LLVM/utils/emacs/tablegen-mode.el
+++ b/src/LLVM/utils/emacs/tablegen-mode.el
@@ -12,13 +12,11 @@
(make-face 'td-decorators-face)
(defvar tablegen-font-lock-keywords
- (let ((kw (mapconcat 'identity
- '("class" "defm" "def" "field" "include" "in"
+ (let ((kw (regexp-opt '("class" "defm" "def" "field" "include" "in"
"let" "multiclass")
- "\\|"))
- (type-kw (mapconcat 'identity
- '("bit" "bits" "code" "dag" "int" "list" "string")
- "\\|"))
+ 'words))
+ (type-kw (regexp-opt '("bit" "bits" "code" "dag" "int" "list" "string")
+ 'words))
)
(list
;; Comments
@@ -36,10 +34,10 @@
'("^[ \t]*\\(@.+\\)" 1 'td-decorators-face)
;; Keywords
- (cons (concat "\\<\\(" kw "\\)\\>[ \n\t(]") 1)
+ (cons (concat kw "[ \n\t(]") 1)
;; Type keywords
- (cons (concat "\\<\\(" type-kw "\\)[ \n\t(]") 1)
+ (cons (concat type-kw "[ \n\t(]") 1)
))
"Additional expressions to highlight in TableGen mode.")
(put 'tablegen-mode 'font-lock-defaults '(tablegen-font-lock-keywords))
diff --git a/src/LLVM/utils/findmisopt b/src/LLVM/utils/findmisopt
index 817004d..60f223b 100644
--- a/src/LLVM/utils/findmisopt
+++ b/src/LLVM/utils/findmisopt
@@ -7,7 +7,7 @@
# it from finding a problem unless the set of failing optimizations are
# known and given to it on the command line.
#
-# Given a bytecode file that produces correct output (or return code),
+# Given a bitcode file that produces correct output (or return code),
# this script will run through all the optimizations passes that gccas
# uses (in the same order) and will narrow down which optimizations
# cause the program either generate different output or return a
@@ -21,7 +21,7 @@
#
# Where:
# bcfile
-# is the bytecode file input (the unoptimized working case)
+# is the bitcode file input (the unoptimized working case)
# outdir
# is a directory into which intermediate results are placed
# progargs
diff --git a/src/LLVM/utils/findoptdiff b/src/LLVM/utils/findoptdiff
index e59dd3b..95badc1 100644
--- a/src/LLVM/utils/findoptdiff
+++ b/src/LLVM/utils/findoptdiff
@@ -14,7 +14,7 @@
# second build contains some experimental optimization features that
# are suspected of producing a misoptimization.
#
-# The script takes two bytecode files, one from each build. They are
+# The script takes two bitcode files, one from each build. They are
# presumed to be a compilation of the same program or program fragment
# with the only difference being the builds.
#
@@ -39,9 +39,9 @@
# llvm2
# is the path to the second llvm build dir
# bc1
-# is the bytecode file for the first llvm environment
+# is the bitcode file for the first llvm environment
# bc2
-# is the bytecode file for the second llvm environment
+# is the bitcode file for the second llvm environment
# filter1
# is an optional filter for filtering the llvm1 generated assembly
# filter2
diff --git a/src/LLVM/utils/fpcmp/Makefile b/src/LLVM/utils/fpcmp/Makefile
index fd2f747..81db3b9 100644
--- a/src/LLVM/utils/fpcmp/Makefile
+++ b/src/LLVM/utils/fpcmp/Makefile
@@ -1,15 +1,15 @@
##===- utils/fpcmp/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 = fpcmp
-USEDLIBS = LLVMSupport.a LLVMSystem.a
+USEDLIBS = LLVMSupport.a
NO_INSTALL = 1
include $(LEVEL)/Makefile.common
diff --git a/src/LLVM/utils/git/find-rev b/src/LLVM/utils/git/find-rev
new file mode 100644
index 0000000..a6161db
--- /dev/null
+++ b/src/LLVM/utils/git/find-rev
@@ -0,0 +1,50 @@
+#!/usr/bin/python
+
+import os, sys, subprocess
+
+def main():
+ from optparse import OptionParser, OptionGroup
+ parser = OptionParser("usage: %prog [options] <repo> <revision>")
+ parser.add_option("", "--dump-section-data", dest="dumpSectionData",
+ help="Dump the contents of sections",
+ action="store_true", default=False)
+ (opts, args) = parser.parse_args()
+
+ if len(args) != 2:
+ parser.error("invalid number of arguments")
+
+ repo,rev = args
+
+ try:
+ rev = int(rev)
+ except:
+ parser.error("invalid revision argument (not an integer)")
+
+ os.chdir(repo)
+ p = subprocess.Popen(['git', 'rev-list', 'git-svn', '--pretty'],
+ stdout=subprocess.PIPE)
+
+ bestRev = bestCommit = None
+ lastCommit = None
+ for ln in p.stdout:
+ if ln.startswith('commit '):
+ lastCommit = ln.split(' ',2)[1]
+ elif ln.startswith(' git-svn-id: '):
+ _,repo,_ = ln.strip().split(' ')
+ _,lrev = repo.rsplit('@',1)
+ lrev = int(lrev)
+ if lrev<=rev:
+ if bestRev is None or lrev>bestRev:
+ assert lastCommit
+ bestCommit = lastCommit
+ bestRev = lrev
+ if lrev == rev:
+ break
+
+ if bestCommit is not None:
+ print bestCommit
+ sys.exit(0)
+ sys.exit(1)
+
+if __name__=='__main__':
+ main()
diff --git a/src/LLVM/utils/kate/README b/src/LLVM/utils/kate/README
new file mode 100644
index 0000000..efe53b7
--- /dev/null
+++ b/src/LLVM/utils/kate/README
@@ -0,0 +1,12 @@
+-*- llvm/utils/kate/README -*-
+
+These are syntax highlighting files for the Kate editor. Included are:
+
+* llvm.xml
+
+ Syntax Highlighting Mode for the KDE Kate editor. To install just copy
+ this file to ~/.kde/share/apps/katepart/syntax (or better yet, symlink it).
+
+Note: If you notice missing or incorrect syntax highlighting, please contact
+<llvmbugs [at] cs.uiuc.edu>; if you wish to provide a patch to improve the
+functionality, it will be most appreciated. Thank you.
diff --git a/src/LLVM/utils/kate/llvm.xml b/src/LLVM/utils/kate/llvm.xml
new file mode 100644
index 0000000..074fa16
--- /dev/null
+++ b/src/LLVM/utils/kate/llvm.xml
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE language SYSTEM "language.dtd">
+<language name="LLVM" section="Sources"
+ version="1.00" kateversion="3.4.4"
+ extensions="*.ll"
+ mimetype=""
+ author="LLVM Team"
+ license="LLVM Release License">
+ <highlighting>
+ <list name="keywords">
+ <item> begin </item>
+ <item> end </item>
+ <item> true </item>
+ <item> false </item>
+ <item> declare </item>
+ <item> define </item>
+ <item> global </item>
+ <item> constant </item>
+ <item> gc </item>
+ <item> module </item>
+ <item> asm </item>
+ <item> target </item>
+ <item> datalayout </item>
+ <item> null </item>
+ <item> undef </item>
+ <item> blockaddress </item>
+ <item> sideeffect </item>
+ <item> alignstack </item>
+ <item> to </item>
+ <item> unwind </item>
+ <item> nuw </item>
+ <item> nsw </item>
+ <item> inbounds </item>
+ <item> tail </item>
+ <item> triple </item>
+ <item> type </item>
+ <item> align </item>
+ <item> alias </item>
+ </list>
+ <list name="linkage-types">
+ <item> private </item>
+ <item> linker_private </item>
+ <item> linker_private_weak </item>
+ <item> linker_private_weak_def_auto </item>
+ <item> internal </item>
+ <item> available_externally </item>
+ <item> linkonce </item>
+ <item> weak </item>
+ <item> common </item>
+ <item> appending </item>
+ <item> extern_weak </item>
+ <item> linkonce_odr </item>
+ <item> weak_odr </item>
+ <item> dllimport </item>
+ <item> dllexport </item>
+ </list>
+ <list name="calling-conventions">
+ <item> ccc </item>
+ <item> fastcc </item>
+ <item> coldcc </item>
+ <item> cc </item>
+ </list>
+ <list name="visibility-styles">
+ <item> default </item>
+ <item> hidden </item>
+ <item> protected </item>
+ </list>
+ <list name="parameter-attributes">
+ <item> zeroext </item>
+ <item> signext </item>
+ <item> inreg </item>
+ <item> byval </item>
+ <item> sret </item>
+ <item> noalias </item>
+ <item> nocapture </item>
+ <item> nest </item>
+ </list>
+ <list name="function-attributes">
+ <item> alignstack </item>
+ <item> alwaysinline </item>
+ <item> inlinehint </item>
+ <item> naked </item>
+ <item> noimplicitfloat </item>
+ <item> noinline </item>
+ <item> noredzone </item>
+ <item> noreturn </item>
+ <item> nounwind </item>
+ <item> optsize </item>
+ <item> readnone </item>
+ <item> readonly </item>
+ <item> ssp </item>
+ <item> sspreq </item>
+ </list>
+ <list name="types">
+ <item> float </item>
+ <item> double </item>
+ <item> fp128 </item>
+ <item> x86_fp80 </item>
+ <item> ppc_fp128 </item>
+ <item> x86mmx </item>
+ <item> void </item>
+ <item> label </item>
+ <item> metadata </item>
+ <item> opaque </item>
+ </list>
+ <list name="intrinsic-global-variables">
+ <item> llvm.used </item>
+ <item> llvm.compiler.used </item>
+ <item> llvm.global_ctors </item>
+ <item> llvm.global_dtors </item>
+ </list>
+ <list name="instructions">
+ <item> ret </item>
+ <item> br </item>
+ <item> switch </item>
+ <item> indirectbr </item>
+ <item> invoke </item>
+ <item> unwind </item>
+ <item> unreachable </item>
+ <item> add </item>
+ <item> fadd </item>
+ <item> sub </item>
+ <item> fsub </item>
+ <item> mul </item>
+ <item> fmul </item>
+ <item> udiv </item>
+ <item> sdiv </item>
+ <item> fdiv </item>
+ <item> urem </item>
+ <item> srem </item>
+ <item> frem </item>
+ <item> shl </item>
+ <item> lshr </item>
+ <item> ashr </item>
+ <item> and </item>
+ <item> or </item>
+ <item> xor </item>
+ <item> extractelement </item>
+ <item> insertelement </item>
+ <item> shufflevector </item>
+ <item> extractvalue </item>
+ <item> insertvalue </item>
+ <item> alloca </item>
+ <item> load </item>
+ <item> store </item>
+ <item> getelementptr </item>
+ <item> trunc </item>
+ <item> zext </item>
+ <item> sext </item>
+ <item> fptrunc </item>
+ <item> fpext </item>
+ <item> fptoui </item>
+ <item> fptosi </item>
+ <item> uitofp </item>
+ <item> sitofp </item>
+ <item> ptrtoint </item>
+ <item> inttoptr </item>
+ <item> bitcast </item>
+ <item> icmp </item>
+ <item> fcmp </item>
+ <item> phi </item>
+ <item> select </item>
+ <item> call </item>
+ <item> va_arg </item>
+ </list>
+ <list name="conditions">
+ <item> eq </item>
+ <item> ne </item>
+ <item> ugt </item>
+ <item> uge </item>
+ <item> ult </item>
+ <item> ule </item>
+ <item> sgt </item>
+ <item> sge </item>
+ <item> slt </item>
+ <item> sle </item>
+ <item> oeq </item>
+ <item> ogt </item>
+ <item> oge </item>
+ <item> olt </item>
+ <item> ole </item>
+ <item> one </item>
+ <item> ord </item>
+ <item> ueq </item>
+ <item> une </item>
+ <item> uno </item>
+ </list>
+ <contexts>
+ <context name="llvm" attribute="Normal Text" lineEndContext="#stay">
+ <DetectSpaces />
+ <AnyChar String="@%" attribute="Symbol" context="symbol" />
+
+ <DetectChar char="{" beginRegion="Brace1" />
+ <DetectChar char="}" endRegion="Brace1" />
+ <DetectChar char=";" attribute="Comment" context="comment" />
+ <DetectChar attribute="String" context="string" char=""" />
+ <RegExpr String="i[0-9]+" attribute="Data Type" context="#stay" />
+ <RegExpr attribute="Symbol" String="[-a-zA-Z$._][-a-zA-Z$._0-9]*:" context="#stay" />
+ <Int attribute="Int" context="#stay" />
+
+ <keyword attribute="Keyword" String="keywords" />
+ <keyword attribute="Keyword" String="linkage-types" />
+ <keyword attribute="Keyword" String="calling-conventions" />
+ <keyword attribute="Keyword" String="visibility-styles" />
+ <keyword attribute="Keyword" String="parameter-attributes" />
+ <keyword attribute="Keyword" String="function-attributes" />
+ <keyword attribute="Data Type" String="types" />
+ <keyword attribute="Keyword" String="intrinsic-global-variables" />
+ <keyword attribute="Keyword" String="instructions" />
+ <keyword attribute="Keyword" String="conditions" />
+ </context>
+
+ <context name="symbol" attribute="Symbol" lineEndContext="#pop">
+ <DetectChar attribute="Symbol" context="symbol-string" char=""" />
+ <RegExpr attribute="Symbol" String="([-a-zA-Z$._][-a-zA-Z$._0-9]*|[0-9]+)" context="#pop" />
+ </context>
+
+ <context name="symbol-string" attribute="Symbol" lineEndContext="#stay">
+ <DetectChar attribute="Symbol" context="#pop#pop" char=""" />
+ </context>
+
+ <context name="string" attribute="String" lineEndContext="#stay">
+ <DetectChar attribute="String" context="#pop" char=""" />
+ </context>
+
+ <context name="comment" attribute="Comment" lineEndContext="#pop">
+ <DetectSpaces />
+ <!-- TODO: Add FileCheck syntax highlighting -->
+ <IncludeRules context="##Alerts" />
+ <DetectIdentifier />
+ </context>
+ </contexts>
+ <itemDatas>
+ <itemData name="Normal Text" defStyleNum="dsNormal" />
+ <itemData name="Keyword" defStyleNum="dsKeyword" />
+ <itemData name="Data Type" defStyleNum="dsDataType" />
+ <itemData name="Int" defStyleNum="dsDecVal" />
+ <itemData name="Hex" defStyleNum="dsBaseN" />
+ <itemData name="Float" defStyleNum="dsFloat" />
+ <itemData name="String" defStyleNum="dsString" />
+ <itemData name="Comment" defStyleNum="dsComment" />
+ <itemData name="Function" defStyleNum="dsFunction" />
+ <itemData name="Symbol" defStyleNum="dsFunction" />
+ </itemDatas>
+ </highlighting>
+ <general>
+ <comments>
+ <comment name="singleLine" start=";" />
+ </comments>
+ <keywords casesensitive="1" weakDeliminator="." />
+ </general>
+</language>
+<!--
+// kate: space-indent on; indent-width 2; replace-tabs on;
+-->
diff --git a/src/LLVM/utils/lit/ShUtil.py b/src/LLVM/utils/lit/ShUtil.py
deleted file mode 100644
index c8f9332..0000000
--- a/src/LLVM/utils/lit/ShUtil.py
+++ /dev/null
@@ -1,346 +0,0 @@
-import itertools
-
-import Util
-from ShCommands import Command, Pipeline, Seq
-
-class ShLexer:
- def __init__(self, data, win32Escapes = False):
- self.data = data
- self.pos = 0
- self.end = len(data)
- self.win32Escapes = win32Escapes
-
- def eat(self):
- c = self.data[self.pos]
- self.pos += 1
- return c
-
- def look(self):
- return self.data[self.pos]
-
- def maybe_eat(self, c):
- """
- maybe_eat(c) - Consume the character c if it is the next character,
- returning True if a character was consumed. """
- if self.data[self.pos] == c:
- self.pos += 1
- return True
- return False
-
- def lex_arg_fast(self, c):
- # Get the leading whitespace free section.
- chunk = self.data[self.pos - 1:].split(None, 1)[0]
-
- # If it has special characters, the fast path failed.
- if ('|' in chunk or '&' in chunk or
- '<' in chunk or '>' in chunk or
- "'" in chunk or '"' in chunk or
- '\\' in chunk):
- return None
-
- self.pos = self.pos - 1 + len(chunk)
- return chunk
-
- def lex_arg_slow(self, c):
- if c in "'\"":
- str = self.lex_arg_quoted(c)
- else:
- str = c
- while self.pos != self.end:
- c = self.look()
- if c.isspace() or c in "|&":
- break
- elif c in '><':
- # This is an annoying case; we treat '2>' as a single token so
- # we don't have to track whitespace tokens.
-
- # If the parse string isn't an integer, do the usual thing.
- if not str.isdigit():
- break
-
- # Otherwise, lex the operator and convert to a redirection
- # token.
- num = int(str)
- tok = self.lex_one_token()
- assert isinstance(tok, tuple) and len(tok) == 1
- return (tok[0], num)
- elif c == '"':
- self.eat()
- str += self.lex_arg_quoted('"')
- elif not self.win32Escapes and c == '\\':
- # Outside of a string, '\\' escapes everything.
- self.eat()
- if self.pos == self.end:
- Util.warning("escape at end of quoted argument in: %r" %
- self.data)
- return str
- str += self.eat()
- else:
- str += self.eat()
- return str
-
- def lex_arg_quoted(self, delim):
- str = ''
- while self.pos != self.end:
- c = self.eat()
- if c == delim:
- return str
- elif c == '\\' and delim == '"':
- # Inside a '"' quoted string, '\\' only escapes the quote
- # character and backslash, otherwise it is preserved.
- if self.pos == self.end:
- Util.warning("escape at end of quoted argument in: %r" %
- self.data)
- return str
- c = self.eat()
- if c == '"': #
- str += '"'
- elif c == '\\':
- str += '\\'
- else:
- str += '\\' + c
- else:
- str += c
- Util.warning("missing quote character in %r" % self.data)
- return str
-
- def lex_arg_checked(self, c):
- pos = self.pos
- res = self.lex_arg_fast(c)
- end = self.pos
-
- self.pos = pos
- reference = self.lex_arg_slow(c)
- if res is not None:
- if res != reference:
- raise ValueError,"Fast path failure: %r != %r" % (res, reference)
- if self.pos != end:
- raise ValueError,"Fast path failure: %r != %r" % (self.pos, end)
- return reference
-
- def lex_arg(self, c):
- return self.lex_arg_fast(c) or self.lex_arg_slow(c)
-
- def lex_one_token(self):
- """
- lex_one_token - Lex a single 'sh' token. """
-
- c = self.eat()
- if c in ';!':
- return (c,)
- if c == '|':
- if self.maybe_eat('|'):
- return ('||',)
- return (c,)
- if c == '&':
- if self.maybe_eat('&'):
- return ('&&',)
- if self.maybe_eat('>'):
- return ('&>',)
- return (c,)
- if c == '>':
- if self.maybe_eat('&'):
- return ('>&',)
- if self.maybe_eat('>'):
- return ('>>',)
- return (c,)
- if c == '<':
- if self.maybe_eat('&'):
- return ('<&',)
- if self.maybe_eat('>'):
- return ('<<',)
- return (c,)
-
- return self.lex_arg(c)
-
- def lex(self):
- while self.pos != self.end:
- if self.look().isspace():
- self.eat()
- else:
- yield self.lex_one_token()
-
-###
-
-class ShParser:
- def __init__(self, data, win32Escapes = False):
- self.data = data
- self.tokens = ShLexer(data, win32Escapes = win32Escapes).lex()
-
- def lex(self):
- try:
- return self.tokens.next()
- except StopIteration:
- return None
-
- def look(self):
- next = self.lex()
- if next is not None:
- self.tokens = itertools.chain([next], self.tokens)
- return next
-
- def parse_command(self):
- tok = self.lex()
- if not tok:
- raise ValueError,"empty command!"
- if isinstance(tok, tuple):
- raise ValueError,"syntax error near unexpected token %r" % tok[0]
-
- args = [tok]
- redirects = []
- while 1:
- tok = self.look()
-
- # EOF?
- if tok is None:
- break
-
- # If this is an argument, just add it to the current command.
- if isinstance(tok, str):
- args.append(self.lex())
- continue
-
- # Otherwise see if it is a terminator.
- assert isinstance(tok, tuple)
- if tok[0] in ('|',';','&','||','&&'):
- break
-
- # Otherwise it must be a redirection.
- op = self.lex()
- arg = self.lex()
- if not arg:
- raise ValueError,"syntax error near token %r" % op[0]
- redirects.append((op, arg))
-
- return Command(args, redirects)
-
- def parse_pipeline(self):
- negate = False
- if self.look() == ('!',):
- self.lex()
- negate = True
-
- commands = [self.parse_command()]
- while self.look() == ('|',):
- self.lex()
- commands.append(self.parse_command())
- return Pipeline(commands, negate)
-
- def parse(self):
- lhs = self.parse_pipeline()
-
- while self.look():
- operator = self.lex()
- assert isinstance(operator, tuple) and len(operator) == 1
-
- if not self.look():
- raise ValueError, "missing argument to operator %r" % operator[0]
-
- # FIXME: Operator precedence!!
- lhs = Seq(lhs, operator[0], self.parse_pipeline())
-
- return lhs
-
-###
-
-import unittest
-
-class TestShLexer(unittest.TestCase):
- def lex(self, str, *args, **kwargs):
- return list(ShLexer(str, *args, **kwargs).lex())
-
- def test_basic(self):
- self.assertEqual(self.lex('a|b>c&d<e'),
- ['a', ('|',), 'b', ('>',), 'c', ('&',), 'd',
- ('<',), 'e'])
-
- def test_redirection_tokens(self):
- self.assertEqual(self.lex('a2>c'),
- ['a2', ('>',), 'c'])
- self.assertEqual(self.lex('a 2>c'),
- ['a', ('>',2), 'c'])
-
- def test_quoting(self):
- self.assertEqual(self.lex(""" 'a' """),
- ['a'])
- self.assertEqual(self.lex(""" "hello\\"world" """),
- ['hello"world'])
- self.assertEqual(self.lex(""" "hello\\'world" """),
- ["hello\\'world"])
- self.assertEqual(self.lex(""" "hello\\\\world" """),
- ["hello\\world"])
- self.assertEqual(self.lex(""" he"llo wo"rld """),
- ["hello world"])
- self.assertEqual(self.lex(""" a\\ b a\\\\b """),
- ["a b", "a\\b"])
- self.assertEqual(self.lex(""" "" "" """),
- ["", ""])
- self.assertEqual(self.lex(""" a\\ b """, win32Escapes = True),
- ['a\\', 'b'])
-
-class TestShParse(unittest.TestCase):
- def parse(self, str):
- return ShParser(str).parse()
-
- def test_basic(self):
- self.assertEqual(self.parse('echo hello'),
- Pipeline([Command(['echo', 'hello'], [])], False))
- self.assertEqual(self.parse('echo ""'),
- Pipeline([Command(['echo', ''], [])], False))
-
- def test_redirection(self):
- self.assertEqual(self.parse('echo hello > c'),
- Pipeline([Command(['echo', 'hello'],
- [((('>'),), 'c')])], False))
- self.assertEqual(self.parse('echo hello > c >> d'),
- Pipeline([Command(['echo', 'hello'], [(('>',), 'c'),
- (('>>',), 'd')])], False))
- self.assertEqual(self.parse('a 2>&1'),
- Pipeline([Command(['a'], [(('>&',2), '1')])], False))
-
- def test_pipeline(self):
- self.assertEqual(self.parse('a | b'),
- Pipeline([Command(['a'], []),
- Command(['b'], [])],
- False))
-
- self.assertEqual(self.parse('a | b | c'),
- Pipeline([Command(['a'], []),
- Command(['b'], []),
- Command(['c'], [])],
- False))
-
- self.assertEqual(self.parse('! a'),
- Pipeline([Command(['a'], [])],
- True))
-
- def test_list(self):
- self.assertEqual(self.parse('a ; b'),
- Seq(Pipeline([Command(['a'], [])], False),
- ';',
- Pipeline([Command(['b'], [])], False)))
-
- self.assertEqual(self.parse('a & b'),
- Seq(Pipeline([Command(['a'], [])], False),
- '&',
- Pipeline([Command(['b'], [])], False)))
-
- self.assertEqual(self.parse('a && b'),
- Seq(Pipeline([Command(['a'], [])], False),
- '&&',
- Pipeline([Command(['b'], [])], False)))
-
- self.assertEqual(self.parse('a || b'),
- Seq(Pipeline([Command(['a'], [])], False),
- '||',
- Pipeline([Command(['b'], [])], False)))
-
- self.assertEqual(self.parse('a && b || c'),
- Seq(Seq(Pipeline([Command(['a'], [])], False),
- '&&',
- Pipeline([Command(['b'], [])], False)),
- '||',
- Pipeline([Command(['c'], [])], False)))
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/src/LLVM/utils/lit/ShUtil.py.bak b/src/LLVM/utils/lit/ShUtil.py.bak
deleted file mode 100644
index c4bbb3d..0000000
--- a/src/LLVM/utils/lit/ShUtil.py.bak
+++ /dev/null
@@ -1,346 +0,0 @@
-import itertools
-
-import Util
-from ShCommands import Command, Pipeline, Seq
-
-class ShLexer:
- def __init__(self, data, win32Escapes = False):
- self.data = data
- self.pos = 0
- self.end = len(data)
- self.win32Escapes = win32Escapes
-
- def eat(self):
- c = self.data[self.pos]
- self.pos += 1
- return c
-
- def look(self):
- return self.data[self.pos]
-
- def maybe_eat(self, c):
- """
- maybe_eat(c) - Consume the character c if it is the next character,
- returning True if a character was consumed. """
- if self.data[self.pos] == c:
- self.pos += 1
- return True
- return False
-
- def lex_arg_fast(self, c):
- # Get the leading whitespace free section.
- chunk = self.data[self.pos - 1:].split(None, 1)[0]
-
- # If it has special characters, the fast path failed.
- if ('|' in chunk or '&' in chunk or
- '<' in chunk or '>' in chunk or
- "'" in chunk or '"' in chunk or
- '\\' in chunk):
- return None
-
- self.pos = self.pos - 1 + len(chunk)
- return chunk
-
- def lex_arg_slow(self, c):
- if c in "'\"":
- str = self.lex_arg_quoted(c)
- else:
- str = c
- while self.pos != self.end:
- c = self.look()
- if c.isspace() or c in "|&":
- break
- elif c in '><':
- # This is an annoying case; we treat '2>' as a single token so
- # we don't have to track whitespace tokens.
-
- # If the parse string isn't an integer, do the usual thing.
- if not str.isdigit():
- break
-
- # Otherwise, lex the operator and convert to a redirection
- # token.
- num = int(str)
- tok = self.lex_one_token()
- assert isinstance(tok, tuple) and len(tok) == 1
- return (tok[0], num)
- elif c == '"':
- self.eat()
- str += self.lex_arg_quoted('"')
- elif not self.win32Escapes and c == '\\':
- # Outside of a string, '\\' escapes everything.
- self.eat()
- if self.pos == self.end:
- Util.warning("escape at end of quoted argument in: %r" %
- self.data)
- return str
- str += self.eat()
- else:
- str += self.eat()
- return str
-
- def lex_arg_quoted(self, delim):
- str = ''
- while self.pos != self.end:
- c = self.eat()
- if c == delim:
- return str
- elif c == '\\' and delim == '"':
- # Inside a '"' quoted string, '\\' only escapes the quote
- # character and backslash, otherwise it is preserved.
- if self.pos == self.end:
- Util.warning("escape at end of quoted argument in: %r" %
- self.data)
- return str
- c = self.eat()
- if c == '"': #
- str += '"'
- elif c == '\\':
- str += '\\'
- else:
- str += '\\' + c
- else:
- str += c
- Util.warning("missing quote character in %r" % self.data)
- return str
-
- def lex_arg_checked(self, c):
- pos = self.pos
- res = self.lex_arg_fast(c)
- end = self.pos
-
- self.pos = pos
- reference = self.lex_arg_slow(c)
- if res is not None:
- if res != reference:
- raise ValueError,"Fast path failure: %r != %r" % (res, reference)
- if self.pos != end:
- raise ValueError,"Fast path failure: %r != %r" % (self.pos, end)
- return reference
-
- def lex_arg(self, c):
- return self.lex_arg_fast(c) or self.lex_arg_slow(c)
-
- def lex_one_token(self):
- """
- lex_one_token - Lex a single 'sh' token. """
-
- c = self.eat()
- if c in ';!':
- return (c,)
- if c == '|':
- if self.maybe_eat('|'):
- return ('||',)
- return (c,)
- if c == '&':
- if self.maybe_eat('&'):
- return ('&&',)
- if self.maybe_eat('>'):
- return ('&>',)
- return (c,)
- if c == '>':
- if self.maybe_eat('&'):
- return ('>&',)
- if self.maybe_eat('>'):
- return ('>>',)
- return (c,)
- if c == '<':
- if self.maybe_eat('&'):
- return ('<&',)
- if self.maybe_eat('>'):
- return ('<<',)
- return (c,)
-
- return self.lex_arg(c)
-
- def lex(self):
- while self.pos != self.end:
- if self.look().isspace():
- self.eat()
- else:
- yield self.lex_one_token()
-
-###
-
-class ShParser:
- def __init__(self, data, win32Escapes = False):
- self.data = data
- self.tokens = ShLexer(data, win32Escapes = win32Escapes).lex()
-
- def lex(self):
- try:
- return self.tokens.next()
- except StopIteration:
- return None
-
- def look(self):
- next = self.lex()
- if next is not None:
- self.tokens = itertools.chain([next], self.tokens)
- return next
-
- def parse_command(self):
- tok = self.lex()
- if not tok:
- raise ValueError,"empty command!"
- if isinstance(tok, tuple):
- raise ValueError,"syntax error near unexpected token %r" % tok[0]
-
- args = [tok]
- redirects = []
- while 1:
- tok = self.look()
-
- # EOF?
- if tok is None:
- break
-
- # If this is an argument, just add it to the current command.
- if isinstance(tok, str):
- args.append(self.lex())
- continue
-
- # Otherwise see if it is a terminator.
- assert isinstance(tok, tuple)
- if tok[0] in ('|',';','&','||','&&'):
- break
-
- # Otherwise it must be a redirection.
- op = self.lex()
- arg = self.lex()
- if not arg:
- raise ValueError,"syntax error near token %r" % op[0]
- redirects.append((op, arg))
-
- return Command(args, redirects)
-
- def parse_pipeline(self):
- negate = False
- if self.look() == ('!',):
- self.lex()
- negate = True
-
- commands = [self.parse_command()]
- while self.look() == ('|',):
- self.lex()
- commands.append(self.parse_command())
- return Pipeline(commands, negate)
-
- def parse(self):
- lhs = self.parse_pipeline()
-
- while self.look():
- operator = self.lex()
- assert isinstance(operator, tuple) and len(operator) == 1
-
- if not self.look():
- raise ValueError, "missing argument to operator %r" % operator[0]
-
- # FIXME: Operator precedence!!
- lhs = Seq(lhs, operator[0], self.parse_pipeline())
-
- return lhs
-
-###
-
-import unittest
-
-class TestShLexer(unittest.TestCase):
- def lex(self, str, *args, **kwargs):
- return list(ShLexer(str, *args, **kwargs).lex())
-
- def test_basic(self):
- self.assertEqual(self.lex('a|b>c&d<e'),
- ['a', ('|',), 'b', ('>',), 'c', ('&',), 'd',
- ('<',), 'e'])
-
- def test_redirection_tokens(self):
- self.assertEqual(self.lex('a2>c'),
- ['a2', ('>',), 'c'])
- self.assertEqual(self.lex('a 2>c'),
- ['a', ('>',2), 'c'])
-
- def test_quoting(self):
- self.assertEqual(self.lex(""" 'a' """),
- ['a'])
- self.assertEqual(self.lex(""" "hello\\"world" """),
- ['hello"world'])
- self.assertEqual(self.lex(""" "hello\\'world" """),
- ["hello\\'world"])
- self.assertEqual(self.lex(""" "hello\\\\world" """),
- ["hello\\world"])
- self.assertEqual(self.lex(""" he"llo wo"rld """),
- ["hello world"])
- self.assertEqual(self.lex(""" a\\ b a\\\\b """),
- ["a b", "a\\b"])
- self.assertEqual(self.lex(""" "" "" """),
- ["", ""])
- self.assertEqual(self.lex(""" a\\ b """, win32Escapes = True),
- ['a\\', 'b'])
-
-class TestShParse(unittest.TestCase):
- def parse(self, str):
- return ShParser(str).parse()
-
- def test_basic(self):
- self.assertEqual(self.parse('echo hello'),
- Pipeline([Command(['echo', 'hello'], [])], False))
- self.assertEqual(self.parse('echo ""'),
- Pipeline([Command(['echo', ''], [])], False))
-
- def test_redirection(self):
- self.assertEqual(self.parse('echo hello > c'),
- Pipeline([Command(['echo', 'hello'],
- [((('>'),), 'c')])], False))
- self.assertEqual(self.parse('echo hello > c >> d'),
- Pipeline([Command(['echo', 'hello'], [(('>',), 'c'),
- (('>>',), 'd')])], False))
- self.assertEqual(self.parse('a 2>&1'),
- Pipeline([Command(['a'], [(('>&',2), '1')])], False))
-
- def test_pipeline(self):
- self.assertEqual(self.parse('a | b'),
- Pipeline([Command(['a'], []),
- Command(['b'], [])],
- False))
-
- self.assertEqual(self.parse('a | b | c'),
- Pipeline([Command(['a'], []),
- Command(['b'], []),
- Command(['c'], [])],
- False))
-
- self.assertEqual(self.parse('! a'),
- Pipeline([Command(['a'], [])],
- True))
-
- def test_list(self):
- self.assertEqual(self.parse('a ; b'),
- Seq(Pipeline([Command(['a'], [])], False),
- ';',
- Pipeline([Command(['b'], [])], False)))
-
- self.assertEqual(self.parse('a & b'),
- Seq(Pipeline([Command(['a'], [])], False),
- '&',
- Pipeline([Command(['b'], [])], False)))
-
- self.assertEqual(self.parse('a && b'),
- Seq(Pipeline([Command(['a'], [])], False),
- '&&',
- Pipeline([Command(['b'], [])], False)))
-
- self.assertEqual(self.parse('a || b'),
- Seq(Pipeline([Command(['a'], [])], False),
- '||',
- Pipeline([Command(['b'], [])], False)))
-
- self.assertEqual(self.parse('a && b || c'),
- Seq(Seq(Pipeline([Command(['a'], [])], False),
- '&&',
- Pipeline([Command(['b'], [])], False)),
- '||',
- Pipeline([Command(['c'], [])], False)))
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/src/LLVM/utils/lit/TODO b/src/LLVM/utils/lit/TODO
index 4d00d2c..6d7f7ea 100644
--- a/src/LLVM/utils/lit/TODO
+++ b/src/LLVM/utils/lit/TODO
@@ -2,18 +2,8 @@
- Add --show-unsupported, don't show by default?
- - Finish documentation.
-
- Optionally use multiprocessing.
- - Support llvmc and ocaml tests.
-
- Support valgrind in all configs, and LLVM style valgrind.
- - Provide test suite config for running unit tests.
-
- Support a timeout / ulimit.
-
- - Support "disabling" tests? The advantage of making this distinct from XFAIL
- is it makes it more obvious that it is a temporary measure (and lit can put
- in a separate category).
diff --git a/src/LLVM/utils/lit/lit/ExampleTests.ObjDir/lit.site.cfg b/src/LLVM/utils/lit/lit/ExampleTests.ObjDir/lit.site.cfg
new file mode 100644
index 0000000..14b6e01
--- /dev/null
+++ b/src/LLVM/utils/lit/lit/ExampleTests.ObjDir/lit.site.cfg
@@ -0,0 +1,15 @@
+# -*- Python -*-
+
+# Site specific configuration file.
+#
+# Typically this will be generated by the build system to automatically set
+# certain configuration variables which cannot be autodetected, so that 'lit'
+# can easily be used on the command line.
+
+import os
+
+# Preserve the obj_root, for use by the main lit.cfg.
+config.example_obj_root = os.path.dirname(__file__)
+
+lit.load_config(config, os.path.join(config.test_source_root,
+ 'lit.cfg'))
diff --git a/src/LLVM/utils/lit/lit/ExampleTests/Clang/fsyntax-only.c b/src/LLVM/utils/lit/lit/ExampleTests/Clang/fsyntax-only.c
new file mode 100644
index 0000000..a4a064b
--- /dev/null
+++ b/src/LLVM/utils/lit/lit/ExampleTests/Clang/fsyntax-only.c
@@ -0,0 +1,4 @@
+// RUN: clang -fsyntax-only -Xclang -verify %s
+
+int f0(void) {} // expected-warning {{control reaches end of non-void function}}
+
diff --git a/src/LLVM/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/bar-test.ll b/src/LLVM/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/bar-test.ll
new file mode 100644
index 0000000..3017b13
--- /dev/null
+++ b/src/LLVM/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/bar-test.ll
@@ -0,0 +1,3 @@
+; RUN: true
+; XFAIL: *
+; XTARGET: darwin
diff --git a/src/LLVM/utils/lit/lit/ExampleTests/LLVM.OutOfTree/lit.local.cfg b/src/LLVM/utils/lit/lit/ExampleTests/LLVM.OutOfTree/lit.local.cfg
new file mode 100644
index 0000000..80d0c7e
--- /dev/null
+++ b/src/LLVM/utils/lit/lit/ExampleTests/LLVM.OutOfTree/lit.local.cfg
@@ -0,0 +1 @@
+config.excludes = ['src']
diff --git a/src/LLVM/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/Foo/lit.local.cfg b/src/LLVM/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/Foo/lit.local.cfg
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/LLVM/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/Foo/lit.local.cfg
diff --git a/src/LLVM/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/lit.site.cfg b/src/LLVM/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/lit.site.cfg
new file mode 100644
index 0000000..bdcc35e
--- /dev/null
+++ b/src/LLVM/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/lit.site.cfg
@@ -0,0 +1,11 @@
+# -*- Python -*-
+
+## Autogenerated by Makefile ##
+# Do not edit!
+
+# Preserve some key paths for use by main LLVM test suite config.
+config.llvm_obj_root = os.path.dirname(os.path.dirname(__file__))
+
+# Let the main config do the real work.
+lit.load_config(config, os.path.join(config.llvm_obj_root,
+ '../src/test/lit.cfg'))
diff --git a/src/LLVM/utils/lit/lit/ExampleTests/ShExternal/lit.local.cfg b/src/LLVM/utils/lit/lit/ExampleTests/ShExternal/lit.local.cfg
new file mode 100644
index 0000000..1061da6
--- /dev/null
+++ b/src/LLVM/utils/lit/lit/ExampleTests/ShExternal/lit.local.cfg
@@ -0,0 +1,6 @@
+# -*- Python -*-
+
+config.test_format = lit.formats.ShTest(execute_external = True)
+
+config.suffixes = ['.c']
+
diff --git a/src/LLVM/utils/lit/lit/ExampleTests/ShInternal/lit.local.cfg b/src/LLVM/utils/lit/lit/ExampleTests/ShInternal/lit.local.cfg
new file mode 100644
index 0000000..448eaa4
--- /dev/null
+++ b/src/LLVM/utils/lit/lit/ExampleTests/ShInternal/lit.local.cfg
@@ -0,0 +1,6 @@
+# -*- Python -*-
+
+config.test_format = lit.formats.ShTest(execute_external = False)
+
+config.suffixes = ['.c']
+
diff --git a/src/LLVM/utils/lit/lit/ExampleTests/TclTest/lit.local.cfg b/src/LLVM/utils/lit/lit/ExampleTests/TclTest/lit.local.cfg
new file mode 100644
index 0000000..6a37129
--- /dev/null
+++ b/src/LLVM/utils/lit/lit/ExampleTests/TclTest/lit.local.cfg
@@ -0,0 +1,5 @@
+# -*- Python -*-
+
+config.test_format = lit.formats.TclTest()
+
+config.suffixes = ['.ll']
diff --git a/src/LLVM/utils/lit/lit/ExampleTests/TclTest/tcl-redir-1.ll b/src/LLVM/utils/lit/lit/ExampleTests/TclTest/tcl-redir-1.ll
new file mode 100644
index 0000000..61240ba
--- /dev/null
+++ b/src/LLVM/utils/lit/lit/ExampleTests/TclTest/tcl-redir-1.ll
@@ -0,0 +1,7 @@
+; RUN: echo 'hi' > %t.1 | echo 'hello' > %t.2
+; RUN: not grep 'hi' %t.1
+; RUN: grep 'hello' %t.2
+
+
+
+
diff --git a/src/LLVM/utils/lit/lit/ExampleTests/required-and-missing.c b/src/LLVM/utils/lit/lit/ExampleTests/required-and-missing.c
new file mode 100644
index 0000000..47ba72e
--- /dev/null
+++ b/src/LLVM/utils/lit/lit/ExampleTests/required-and-missing.c
@@ -0,0 +1,4 @@
+// This test shouldn't be run, the required feature is missing.
+//
+// RUN: false
+// REQUIRES: some-missing-feature-name
diff --git a/src/LLVM/utils/lit/lit/ExampleTests/required-and-present.c b/src/LLVM/utils/lit/lit/ExampleTests/required-and-present.c
new file mode 100644
index 0000000..2a09e08
--- /dev/null
+++ b/src/LLVM/utils/lit/lit/ExampleTests/required-and-present.c
@@ -0,0 +1,2 @@
+// RUN: true
+// REQUIRES: some-feature-name
diff --git a/src/LLVM/utils/lit/lit/LitConfig.py b/src/LLVM/utils/lit/lit/LitConfig.py
index ac48591..2cc2781 100644
--- a/src/LLVM/utils/lit/lit/LitConfig.py
+++ b/src/LLVM/utils/lit/lit/LitConfig.py
@@ -8,6 +8,9 @@
easily.
"""
+ # Provide access to Test module.
+ import Test
+
# Provide access to built-in formats.
import LitFormats as formats
@@ -17,7 +20,7 @@
def __init__(self, progname, path, quiet,
useValgrind, valgrindLeakCheck, valgrindArgs,
useTclAsSh,
- noExecute, debug, isWindows,
+ noExecute, ignoreStdErr, debug, isWindows,
params):
# The name of the test runner.
self.progname = progname
@@ -29,6 +32,7 @@
self.valgrindUserArgs = list(valgrindArgs)
self.useTclAsSh = bool(useTclAsSh)
self.noExecute = noExecute
+ self.ignoreStdErr = ignoreStdErr
self.debug = debug
self.isWindows = bool(isWindows)
self.params = dict(params)
@@ -82,6 +86,22 @@
return self.bashPath
+ def getToolsPath(self, dir, paths, tools):
+ import os, Util
+ if dir is not None and os.path.isabs(dir) and os.path.isdir(dir):
+ if not Util.checkToolsPath(dir, tools):
+ return None
+ else:
+ dir = Util.whichTools(tools, paths)
+
+ # bash
+ self.bashPath = Util.which('bash', dir)
+ if self.bashPath is None:
+ self.note("Unable to find 'bash.exe'.")
+ self.bashPath = ''
+
+ return dir
+
def _write_message(self, kind, message):
import inspect, os, sys
diff --git a/src/LLVM/utils/lit/lit/LitFormats.py b/src/LLVM/utils/lit/lit/LitFormats.py
index e86f103..931d107 100644
--- a/src/LLVM/utils/lit/lit/LitFormats.py
+++ b/src/LLVM/utils/lit/lit/LitFormats.py
@@ -1,2 +1,3 @@
+from TestFormats import FileBasedTest
from TestFormats import GoogleTest, ShTest, TclTest
from TestFormats import SyntaxCheckTest, OneCommandPerFileTest
diff --git a/src/LLVM/utils/lit/lit/ProgressBar.py b/src/LLVM/utils/lit/lit/ProgressBar.py
index 85c95f5..5c85a17 100644
--- a/src/LLVM/utils/lit/lit/ProgressBar.py
+++ b/src/LLVM/utils/lit/lit/ProgressBar.py
@@ -105,6 +105,7 @@
# Look up numeric capabilities.
self.COLS = curses.tigetnum('cols')
self.LINES = curses.tigetnum('lines')
+ self.XN = curses.tigetflag('xenl')
# Look up string capabilities.
for capability in self._STRING_CAPABILITIES:
@@ -205,7 +206,7 @@
The progress bar is colored, if the terminal supports color
output; and adjusts to the width of the terminal.
"""
- BAR = '%s${GREEN}[${BOLD}%s%s${NORMAL}${GREEN}]${NORMAL}%s\n'
+ BAR = '%s${GREEN}[${BOLD}%s%s${NORMAL}${GREEN}]${NORMAL}%s'
HEADER = '${BOLD}${CYAN}%s${NORMAL}\n\n'
def __init__(self, term, header, useETA=True):
@@ -213,7 +214,15 @@
if not (self.term.CLEAR_EOL and self.term.UP and self.term.BOL):
raise ValueError("Terminal isn't capable enough -- you "
"should use a simpler progress dispaly.")
- self.width = self.term.COLS or 75
+ self.BOL = self.term.BOL # BoL from col#79
+ self.XNL = "\n" # Newline from col#79
+ if self.term.COLS:
+ self.width = self.term.COLS
+ if not self.term.XN:
+ self.BOL = self.term.UP + self.term.BOL
+ self.XNL = "" # Cursor must be fed to the next line
+ else:
+ self.width = 75
self.bar = term.render(self.BAR)
self.header = self.term.render(self.HEADER % header.center(self.width))
self.cleared = 1 #: true if we haven't drawn the bar yet.
@@ -244,15 +253,19 @@
else:
message = '... ' + message[-(self.width-4):]
sys.stdout.write(
- self.term.BOL + self.term.UP + self.term.CLEAR_EOL +
+ self.BOL + self.term.UP + self.term.CLEAR_EOL +
(self.bar % (prefix, '='*n, '-'*(barWidth-n), suffix)) +
+ self.XNL +
self.term.CLEAR_EOL + message)
+ if not self.term.XN:
+ sys.stdout.flush()
def clear(self):
if not self.cleared:
- sys.stdout.write(self.term.BOL + self.term.CLEAR_EOL +
+ sys.stdout.write(self.BOL + self.term.CLEAR_EOL +
self.term.UP + self.term.CLEAR_EOL +
self.term.UP + self.term.CLEAR_EOL)
+ sys.stdout.flush()
self.cleared = 1
def test():
diff --git a/src/LLVM/utils/lit/lit/TestFormats.py b/src/LLVM/utils/lit/lit/TestFormats.py
index e52d0e4..d1c0558 100644
--- a/src/LLVM/utils/lit/lit/TestFormats.py
+++ b/src/LLVM/utils/lit/lit/TestFormats.py
@@ -1,14 +1,21 @@
import os
+import sys
import Test
import TestRunner
import Util
+kIsWindows = sys.platform in ['win32', 'cygwin']
+
class GoogleTest(object):
def __init__(self, test_sub_dir, test_suffix):
- self.test_sub_dir = str(test_sub_dir)
+ self.test_sub_dir = os.path.normcase(str(test_sub_dir)).split(';')
self.test_suffix = str(test_suffix)
+ # On Windows, assume tests will also end in '.exe'.
+ if kIsWindows:
+ self.test_suffix += '.exe'
+
def getGTestTests(self, path, litConfig, localConfig):
"""getGTestTests(path) - [name]
@@ -21,7 +28,10 @@
try:
lines = Util.capture([path, '--gtest_list_tests'],
- env=localConfig.environment).split('\n')
+ env=localConfig.environment)
+ if kIsWindows:
+ lines = lines.replace('\r', '')
+ lines = lines.split('\n')
except:
litConfig.error("unable to discover google-tests in %r" % path)
raise StopIteration
@@ -37,7 +47,7 @@
index += 1
while len(nested_tests) > index:
nested_tests.pop()
-
+
ln = ln[index*2:]
if ln.endswith('.'):
nested_tests.append(ln)
@@ -49,10 +59,14 @@
source_path = testSuite.getSourcePath(path_in_suite)
for filename in os.listdir(source_path):
# Check for the one subdirectory (build directory) tests will be in.
- if filename != self.test_sub_dir:
- continue
+ if not '.' in self.test_sub_dir:
+ if not os.path.normcase(filename) in self.test_sub_dir:
+ continue
filepath = os.path.join(source_path, filename)
+ if not os.path.isdir(filepath):
+ continue
+
for subfilename in os.listdir(filepath):
if subfilename.endswith(self.test_suffix):
execpath = os.path.join(filepath, subfilename)
@@ -77,7 +91,7 @@
out, err, exitCode = TestRunner.executeCommand(
cmd, env=test.config.environment)
-
+
if not exitCode:
return Test.PASS,''
@@ -111,7 +125,11 @@
self.execute_external)
class TclTest(FileBasedTest):
+ def __init__(self, ignoreStdErr=False):
+ self.ignoreStdErr = ignoreStdErr
+
def execute(self, test, litConfig):
+ litConfig.ignoreStdErr = self.ignoreStdErr
return TestRunner.executeTclTest(test, litConfig)
###
diff --git a/src/LLVM/utils/lit/lit/TestRunner.py b/src/LLVM/utils/lit/lit/TestRunner.py
index 0eb51a8..f5f7c19 100644
--- a/src/LLVM/utils/lit/lit/TestRunner.py
+++ b/src/LLVM/utils/lit/lit/TestRunner.py
@@ -8,6 +8,8 @@
import platform
import tempfile
+import re
+
class InternalShellError(Exception):
def __init__(self, command, message):
self.command = command
@@ -178,6 +180,13 @@
else:
input = subprocess.PIPE
+ # Explicitly close any redirected files. We need to do this now because we
+ # need to release any handles we may have on the temporary files (important
+ # on Win32, for example). Since we have already spawned the subprocess, our
+ # handles have already been transferred so we do not need them anymore.
+ for f in opened_files:
+ f.close()
+
# FIXME: There is probably still deadlock potential here. Yawn.
procData = [None] * len(procs)
procData[-1] = procs[-1].communicate()
@@ -215,10 +224,6 @@
else:
exitCode = res
- # Explicitly close any redirected files.
- for f in opened_files:
- f.close()
-
# Remove any named temporary files we created.
for f in named_temp_files:
try:
@@ -332,23 +337,28 @@
return out, err, exitCode
def executeScript(test, litConfig, tmpBase, commands, cwd):
+ bashPath = litConfig.getBashPath();
+ isWin32CMDEXE = (litConfig.isWindows and not bashPath)
script = tmpBase + '.script'
- if litConfig.isWindows:
+ if isWin32CMDEXE:
script += '.bat'
# Write script file
f = open(script,'w')
- if litConfig.isWindows:
+ if isWin32CMDEXE:
f.write('\nif %ERRORLEVEL% NEQ 0 EXIT\n'.join(commands))
else:
f.write(' &&\n'.join(commands))
f.write('\n')
f.close()
- if litConfig.isWindows:
+ if isWin32CMDEXE:
command = ['cmd','/c', script]
else:
- command = ['/bin/sh', script]
+ if bashPath:
+ command = [bashPath, script]
+ else:
+ command = ['/bin/sh', script]
if litConfig.useValgrind:
# FIXME: Running valgrind on sh is overkill. We probably could just
# run on clang with no real loss.
@@ -387,7 +397,8 @@
sourcedir = os.path.dirname(sourcepath)
execpath = test.getExecPath()
execdir,execbase = os.path.split(execpath)
- tmpBase = os.path.join(execdir, 'Output', execbase)
+ tmpDir = os.path.join(execdir, 'Output')
+ tmpBase = os.path.join(tmpDir, execbase)
if test.index is not None:
tmpBase += '_%d' % test.index
@@ -395,6 +406,7 @@
if normalize_slashes:
sourcepath = sourcepath.replace('\\', '/')
sourcedir = sourcedir.replace('\\', '/')
+ tmpDir = tmpDir.replace('\\', '/')
tmpBase = tmpBase.replace('\\', '/')
# We use #_MARKER_# to hide %% while we do the other substitutions.
@@ -404,6 +416,7 @@
('%S', sourcedir),
('%p', sourcedir),
('%t', tmpBase + '.tmp'),
+ ('%T', tmpDir),
# FIXME: Remove this once we kill DejaGNU.
('%abs_tmp', tmpBase + '.tmp'),
('#_MARKER_#', '%')])
@@ -441,11 +454,15 @@
if ln[ln.index('END.'):].strip() == 'END.':
break
- # Apply substitutions to the script.
+ # Apply substitutions to the script. Allow full regular
+ # expression syntax. Replace each matching occurrence of regular
+ # expression pattern a with substitution b in line ln.
def processLine(ln):
# Apply substitutions
for a,b in substitutions:
- ln = ln.replace(a,b)
+ if kIsWindows:
+ b = b.replace("\\","\\\\")
+ ln = re.sub(a, b, ln)
# Strip the trailing newline and any extra whitespace.
return ln.strip()
@@ -519,13 +536,13 @@
# considered to fail if there is any standard error output.
out,err,exitCode = res
if isXFail:
- ok = exitCode != 0 or err
+ ok = exitCode != 0 or err and not litConfig.ignoreStdErr
if ok:
status = Test.XFAIL
else:
status = Test.XPASS
else:
- ok = exitCode == 0 and not err
+ ok = exitCode == 0 and (not err or litConfig.ignoreStdErr)
if ok:
status = Test.PASS
else:
@@ -536,7 +553,7 @@
# Set a flag for formatTestOutput so it can explain why the test was
# considered to have failed, despite having an exit code of 0.
- failDueToStderr = exitCode == 0 and err
+ failDueToStderr = exitCode == 0 and err and not litConfig.ignoreStdErr
return formatTestOutput(status, out, err, exitCode, failDueToStderr, script)
@@ -544,7 +561,7 @@
if test.config.unsupported:
return (Test.UNSUPPORTED, 'Test is unsupported')
- res = parseIntegratedTestScript(test)
+ res = parseIntegratedTestScript(test, useExternalSh)
if len(res) == 2:
return res
diff --git a/src/LLVM/utils/lit/lit/TestingConfig.py b/src/LLVM/utils/lit/lit/TestingConfig.py
index 5c1b273..a92dca8 100644
--- a/src/LLVM/utils/lit/lit/TestingConfig.py
+++ b/src/LLVM/utils/lit/lit/TestingConfig.py
@@ -1,4 +1,5 @@
import os
+import sys
class TestingConfig:
""""
@@ -10,14 +11,22 @@
if config is None:
# Set the environment based on the command line arguments.
environment = {
+ 'LIBRARY_PATH' : os.environ.get('LIBRARY_PATH',''),
'LD_LIBRARY_PATH' : os.environ.get('LD_LIBRARY_PATH',''),
'PATH' : os.pathsep.join(litConfig.path +
[os.environ.get('PATH','')]),
- 'PATHEXT' : os.environ.get('PATHEXT',''),
'SYSTEMROOT' : os.environ.get('SYSTEMROOT',''),
- 'LLVM_DISABLE_CRT_DEBUG' : '1',
}
+ if sys.platform == 'win32':
+ environment.update({
+ 'LLVM_DISABLE_CRT_DEBUG' : '1',
+ 'PATHEXT' : os.environ.get('PATHEXT',''),
+ 'PYTHONUNBUFFERED' : '1',
+ 'TEMP' : os.environ.get('TEMP',''),
+ 'TMP' : os.environ.get('TMP',''),
+ })
+
config = TestingConfig(parent,
name = '<unnamed>',
suffixes = set(),
diff --git a/src/LLVM/utils/lit/lit/Util.py b/src/LLVM/utils/lit/lit/Util.py
index 414b714..226e453 100644
--- a/src/LLVM/utils/lit/lit/Util.py
+++ b/src/LLVM/utils/lit/lit/Util.py
@@ -12,7 +12,7 @@
if isinstance(ncpus, int) and ncpus > 0:
return ncpus
else: # OSX:
- return int(os.popen2("sysctl -n hw.ncpu")[1].read())
+ return int(capture(['sysctl', '-n', 'hw.ncpu']))
# Windows:
if os.environ.has_key("NUMBER_OF_PROCESSORS"):
ncpus = int(os.environ["NUMBER_OF_PROCESSORS"])
@@ -64,7 +64,11 @@
paths = os.defpath
# Get suffixes to search.
- pathext = os.environ.get('PATHEXT', '').split(os.pathsep)
+ # On Cygwin, 'PATHEXT' may exist but it should not be used.
+ if os.pathsep == ';':
+ pathext = os.environ.get('PATHEXT', '').split(';')
+ else:
+ pathext = ['']
# Search the paths...
for path in paths.split(os.pathsep):
@@ -75,6 +79,18 @@
return None
+def checkToolsPath(dir, tools):
+ for tool in tools:
+ if not os.path.exists(os.path.join(dir, tool)):
+ return False;
+ return True;
+
+def whichTools(tools, paths):
+ for path in paths.split(os.pathsep):
+ if checkToolsPath(path, tools):
+ return path
+ return None
+
def printHistogram(items, title = 'Items'):
import itertools, math
diff --git a/src/LLVM/utils/lit/lit/__init__.py b/src/LLVM/utils/lit/lit/__init__.py
new file mode 100644
index 0000000..f3fbb1c
--- /dev/null
+++ b/src/LLVM/utils/lit/lit/__init__.py
@@ -0,0 +1,10 @@
+"""'lit' Testing Tool"""
+
+from main import main
+
+__author__ = 'Daniel Dunbar'
+__email__ = 'daniel@zuster.org'
+__versioninfo__ = (0, 2, 0)
+__version__ = '.'.join(map(str, __versioninfo__)) + 'dev'
+
+__all__ = []
diff --git a/src/LLVM/utils/lit/lit/main.py b/src/LLVM/utils/lit/lit/main.py
new file mode 100644
index 0000000..e1a380c
--- /dev/null
+++ b/src/LLVM/utils/lit/lit/main.py
@@ -0,0 +1,650 @@
+#!/usr/bin/env python
+
+"""
+lit - LLVM Integrated Tester.
+
+See lit.pod for more information.
+"""
+
+import math, os, platform, random, re, sys, time, threading, traceback
+
+import ProgressBar
+import TestRunner
+import Util
+
+from TestingConfig import TestingConfig
+import LitConfig
+import Test
+
+# Configuration files to look for when discovering test suites. These can be
+# overridden with --config-prefix.
+#
+# FIXME: Rename to 'config.lit', 'site.lit', and 'local.lit' ?
+gConfigName = 'lit.cfg'
+gSiteConfigName = 'lit.site.cfg'
+
+kLocalConfigName = 'lit.local.cfg'
+
+class TestingProgressDisplay:
+ def __init__(self, opts, numTests, progressBar=None):
+ self.opts = opts
+ self.numTests = numTests
+ self.current = None
+ self.lock = threading.Lock()
+ self.progressBar = progressBar
+ self.completed = 0
+
+ def update(self, test):
+ # Avoid locking overhead in quiet mode
+ if self.opts.quiet and not test.result.isFailure:
+ self.completed += 1
+ return
+
+ # Output lock.
+ self.lock.acquire()
+ try:
+ self.handleUpdate(test)
+ finally:
+ self.lock.release()
+
+ def finish(self):
+ if self.progressBar:
+ self.progressBar.clear()
+ elif self.opts.quiet:
+ pass
+ elif self.opts.succinct:
+ sys.stdout.write('\n')
+
+ def handleUpdate(self, test):
+ self.completed += 1
+ if self.progressBar:
+ self.progressBar.update(float(self.completed)/self.numTests,
+ test.getFullName())
+
+ if self.opts.succinct and not test.result.isFailure:
+ return
+
+ if self.progressBar:
+ self.progressBar.clear()
+
+ print '%s: %s (%d of %d)' % (test.result.name, test.getFullName(),
+ self.completed, self.numTests)
+
+ if test.result.isFailure and self.opts.showOutput:
+ print "%s TEST '%s' FAILED %s" % ('*'*20, test.getFullName(),
+ '*'*20)
+ print test.output
+ print "*" * 20
+
+ sys.stdout.flush()
+
+class TestProvider:
+ def __init__(self, tests, maxTime):
+ self.maxTime = maxTime
+ self.iter = iter(tests)
+ self.lock = threading.Lock()
+ self.startTime = time.time()
+
+ def get(self):
+ # Check if we have run out of time.
+ if self.maxTime is not None:
+ if time.time() - self.startTime > self.maxTime:
+ return None
+
+ # Otherwise take the next test.
+ self.lock.acquire()
+ try:
+ item = self.iter.next()
+ except StopIteration:
+ item = None
+ self.lock.release()
+ return item
+
+class Tester(threading.Thread):
+ def __init__(self, litConfig, provider, display):
+ threading.Thread.__init__(self)
+ self.litConfig = litConfig
+ self.provider = provider
+ self.display = display
+
+ def run(self):
+ while 1:
+ item = self.provider.get()
+ if item is None:
+ break
+ self.runTest(item)
+
+ def runTest(self, test):
+ result = None
+ startTime = time.time()
+ try:
+ result, output = test.config.test_format.execute(test,
+ self.litConfig)
+ except KeyboardInterrupt:
+ # This is a sad hack. Unfortunately subprocess goes
+ # bonkers with ctrl-c and we start forking merrily.
+ print '\nCtrl-C detected, goodbye.'
+ os.kill(0,9)
+ except:
+ if self.litConfig.debug:
+ raise
+ result = Test.UNRESOLVED
+ output = 'Exception during script execution:\n'
+ output += traceback.format_exc()
+ output += '\n'
+ elapsed = time.time() - startTime
+
+ test.setResult(result, output, elapsed)
+ self.display.update(test)
+
+def dirContainsTestSuite(path):
+ cfgpath = os.path.join(path, gSiteConfigName)
+ if os.path.exists(cfgpath):
+ return cfgpath
+ cfgpath = os.path.join(path, gConfigName)
+ if os.path.exists(cfgpath):
+ return cfgpath
+
+def getTestSuite(item, litConfig, cache):
+ """getTestSuite(item, litConfig, cache) -> (suite, relative_path)
+
+ Find the test suite containing @arg item.
+
+ @retval (None, ...) - Indicates no test suite contains @arg item.
+ @retval (suite, relative_path) - The suite that @arg item is in, and its
+ relative path inside that suite.
+ """
+ def search1(path):
+ # Check for a site config or a lit config.
+ cfgpath = dirContainsTestSuite(path)
+
+ # If we didn't find a config file, keep looking.
+ if not cfgpath:
+ parent,base = os.path.split(path)
+ if parent == path:
+ return (None, ())
+
+ ts, relative = search(parent)
+ return (ts, relative + (base,))
+
+ # We found a config file, load it.
+ if litConfig.debug:
+ litConfig.note('loading suite config %r' % cfgpath)
+
+ cfg = TestingConfig.frompath(cfgpath, None, litConfig, mustExist = True)
+ source_root = os.path.realpath(cfg.test_source_root or path)
+ exec_root = os.path.realpath(cfg.test_exec_root or path)
+ return Test.TestSuite(cfg.name, source_root, exec_root, cfg), ()
+
+ def search(path):
+ # Check for an already instantiated test suite.
+ res = cache.get(path)
+ if res is None:
+ cache[path] = res = search1(path)
+ return res
+
+ # Canonicalize the path.
+ item = os.path.realpath(item)
+
+ # Skip files and virtual components.
+ components = []
+ while not os.path.isdir(item):
+ parent,base = os.path.split(item)
+ if parent == item:
+ return (None, ())
+ components.append(base)
+ item = parent
+ components.reverse()
+
+ ts, relative = search(item)
+ return ts, tuple(relative + tuple(components))
+
+def getLocalConfig(ts, path_in_suite, litConfig, cache):
+ def search1(path_in_suite):
+ # Get the parent config.
+ if not path_in_suite:
+ parent = ts.config
+ else:
+ parent = search(path_in_suite[:-1])
+
+ # Load the local configuration.
+ source_path = ts.getSourcePath(path_in_suite)
+ cfgpath = os.path.join(source_path, kLocalConfigName)
+ if litConfig.debug:
+ litConfig.note('loading local config %r' % cfgpath)
+ return TestingConfig.frompath(cfgpath, parent, litConfig,
+ mustExist = False,
+ config = parent.clone(cfgpath))
+
+ def search(path_in_suite):
+ key = (ts, path_in_suite)
+ res = cache.get(key)
+ if res is None:
+ cache[key] = res = search1(path_in_suite)
+ return res
+
+ return search(path_in_suite)
+
+def getTests(path, litConfig, testSuiteCache, localConfigCache):
+ # Find the test suite for this input and its relative path.
+ ts,path_in_suite = getTestSuite(path, litConfig, testSuiteCache)
+ if ts is None:
+ litConfig.warning('unable to find test suite for %r' % path)
+ return (),()
+
+ if litConfig.debug:
+ litConfig.note('resolved input %r to %r::%r' % (path, ts.name,
+ path_in_suite))
+
+ return ts, getTestsInSuite(ts, path_in_suite, litConfig,
+ testSuiteCache, localConfigCache)
+
+def getTestsInSuite(ts, path_in_suite, litConfig,
+ testSuiteCache, localConfigCache):
+ # Check that the source path exists (errors here are reported by the
+ # caller).
+ source_path = ts.getSourcePath(path_in_suite)
+ if not os.path.exists(source_path):
+ return
+
+ # Check if the user named a test directly.
+ if not os.path.isdir(source_path):
+ lc = getLocalConfig(ts, path_in_suite[:-1], litConfig, localConfigCache)
+ yield Test.Test(ts, path_in_suite, lc)
+ return
+
+ # Otherwise we have a directory to search for tests, start by getting the
+ # local configuration.
+ lc = getLocalConfig(ts, path_in_suite, litConfig, localConfigCache)
+
+ # Search for tests.
+ if lc.test_format is not None:
+ for res in lc.test_format.getTestsInDirectory(ts, path_in_suite,
+ litConfig, lc):
+ yield res
+
+ # Search subdirectories.
+ for filename in os.listdir(source_path):
+ # FIXME: This doesn't belong here?
+ if filename in ('Output', '.svn') or filename in lc.excludes:
+ continue
+
+ # Ignore non-directories.
+ file_sourcepath = os.path.join(source_path, filename)
+ if not os.path.isdir(file_sourcepath):
+ continue
+
+ # Check for nested test suites, first in the execpath in case there is a
+ # site configuration and then in the source path.
+ file_execpath = ts.getExecPath(path_in_suite + (filename,))
+ if dirContainsTestSuite(file_execpath):
+ sub_ts, subiter = getTests(file_execpath, litConfig,
+ testSuiteCache, localConfigCache)
+ elif dirContainsTestSuite(file_sourcepath):
+ sub_ts, subiter = getTests(file_sourcepath, litConfig,
+ testSuiteCache, localConfigCache)
+ else:
+ # Otherwise, continue loading from inside this test suite.
+ subiter = getTestsInSuite(ts, path_in_suite + (filename,),
+ litConfig, testSuiteCache,
+ localConfigCache)
+ sub_ts = None
+
+ N = 0
+ for res in subiter:
+ N += 1
+ yield res
+ if sub_ts and not N:
+ litConfig.warning('test suite %r contained no tests' % sub_ts.name)
+
+def runTests(numThreads, litConfig, provider, display):
+ # If only using one testing thread, don't use threads at all; this lets us
+ # profile, among other things.
+ if numThreads == 1:
+ t = Tester(litConfig, provider, display)
+ t.run()
+ return
+
+ # Otherwise spin up the testing threads and wait for them to finish.
+ testers = [Tester(litConfig, provider, display)
+ for i in range(numThreads)]
+ for t in testers:
+ t.start()
+ try:
+ for t in testers:
+ t.join()
+ except KeyboardInterrupt:
+ sys.exit(2)
+
+def load_test_suite(inputs):
+ import unittest
+
+ # Create the global config object.
+ litConfig = LitConfig.LitConfig(progname = 'lit',
+ path = [],
+ quiet = False,
+ useValgrind = False,
+ valgrindLeakCheck = False,
+ valgrindArgs = [],
+ useTclAsSh = False,
+ noExecute = False,
+ ignoreStdErr = False,
+ debug = False,
+ isWindows = (platform.system()=='Windows'),
+ params = {})
+
+ # Load the tests from the inputs.
+ tests = []
+ testSuiteCache = {}
+ localConfigCache = {}
+ for input in inputs:
+ prev = len(tests)
+ tests.extend(getTests(input, litConfig,
+ testSuiteCache, localConfigCache)[1])
+ if prev == len(tests):
+ litConfig.warning('input %r contained no tests' % input)
+
+ # If there were any errors during test discovery, exit now.
+ if litConfig.numErrors:
+ print >>sys.stderr, '%d errors, exiting.' % litConfig.numErrors
+ sys.exit(2)
+
+ # Return a unittest test suite which just runs the tests in order.
+ def get_test_fn(test):
+ return unittest.FunctionTestCase(
+ lambda: test.config.test_format.execute(
+ test, litConfig),
+ description = test.getFullName())
+
+ from LitTestCase import LitTestCase
+ return unittest.TestSuite([LitTestCase(test, litConfig) for test in tests])
+
+def main(builtinParameters = {}): # Bump the GIL check interval, its more important to get any one thread to a
+ # blocking operation (hopefully exec) than to try and unblock other threads.
+ #
+ # FIXME: This is a hack.
+ import sys
+ sys.setcheckinterval(1000)
+
+ global options
+ from optparse import OptionParser, OptionGroup
+ parser = OptionParser("usage: %prog [options] {file-or-path}")
+
+ parser.add_option("-j", "--threads", dest="numThreads", metavar="N",
+ help="Number of testing threads",
+ type=int, action="store", default=None)
+ parser.add_option("", "--config-prefix", dest="configPrefix",
+ metavar="NAME", help="Prefix for 'lit' config files",
+ action="store", default=None)
+ parser.add_option("", "--param", dest="userParameters",
+ metavar="NAME=VAL",
+ help="Add 'NAME' = 'VAL' to the user defined parameters",
+ type=str, action="append", default=[])
+
+ group = OptionGroup(parser, "Output Format")
+ # FIXME: I find these names very confusing, although I like the
+ # functionality.
+ group.add_option("-q", "--quiet", dest="quiet",
+ help="Suppress no error output",
+ action="store_true", default=False)
+ group.add_option("-s", "--succinct", dest="succinct",
+ help="Reduce amount of output",
+ action="store_true", default=False)
+ group.add_option("-v", "--verbose", dest="showOutput",
+ help="Show all test output",
+ action="store_true", default=False)
+ group.add_option("", "--no-progress-bar", dest="useProgressBar",
+ help="Do not use curses based progress bar",
+ action="store_false", default=True)
+ parser.add_option_group(group)
+
+ group = OptionGroup(parser, "Test Execution")
+ group.add_option("", "--path", dest="path",
+ help="Additional paths to add to testing environment",
+ action="append", type=str, default=[])
+ group.add_option("", "--vg", dest="useValgrind",
+ help="Run tests under valgrind",
+ action="store_true", default=False)
+ group.add_option("", "--vg-leak", dest="valgrindLeakCheck",
+ help="Check for memory leaks under valgrind",
+ action="store_true", default=False)
+ group.add_option("", "--vg-arg", dest="valgrindArgs", metavar="ARG",
+ help="Specify an extra argument for valgrind",
+ type=str, action="append", default=[])
+ group.add_option("", "--time-tests", dest="timeTests",
+ help="Track elapsed wall time for each test",
+ action="store_true", default=False)
+ group.add_option("", "--no-execute", dest="noExecute",
+ help="Don't execute any tests (assume PASS)",
+ action="store_true", default=False)
+ parser.add_option_group(group)
+
+ group = OptionGroup(parser, "Test Selection")
+ group.add_option("", "--max-tests", dest="maxTests", metavar="N",
+ help="Maximum number of tests to run",
+ action="store", type=int, default=None)
+ group.add_option("", "--max-time", dest="maxTime", metavar="N",
+ help="Maximum time to spend testing (in seconds)",
+ action="store", type=float, default=None)
+ group.add_option("", "--shuffle", dest="shuffle",
+ help="Run tests in random order",
+ action="store_true", default=False)
+ parser.add_option_group(group)
+
+ group = OptionGroup(parser, "Debug and Experimental Options")
+ group.add_option("", "--debug", dest="debug",
+ help="Enable debugging (for 'lit' development)",
+ action="store_true", default=False)
+ group.add_option("", "--show-suites", dest="showSuites",
+ help="Show discovered test suites",
+ action="store_true", default=False)
+ group.add_option("", "--no-tcl-as-sh", dest="useTclAsSh",
+ help="Don't run Tcl scripts using 'sh'",
+ action="store_false", default=True)
+ group.add_option("", "--repeat", dest="repeatTests", metavar="N",
+ help="Repeat tests N times (for timing)",
+ action="store", default=None, type=int)
+ parser.add_option_group(group)
+
+ (opts, args) = parser.parse_args()
+
+ if not args:
+ parser.error('No inputs specified')
+
+ if opts.configPrefix is not None:
+ global gConfigName, gSiteConfigName
+ gConfigName = '%s.cfg' % opts.configPrefix
+ gSiteConfigName = '%s.site.cfg' % opts.configPrefix
+
+ if opts.numThreads is None:
+# Python <2.5 has a race condition causing lit to always fail with numThreads>1
+# http://bugs.python.org/issue1731717
+# I haven't seen this bug occur with 2.5.2 and later, so only enable multiple
+# threads by default there.
+ if sys.hexversion >= 0x2050200:
+ opts.numThreads = Util.detectCPUs()
+ else:
+ opts.numThreads = 1
+
+ inputs = args
+
+ # Create the user defined parameters.
+ userParams = dict(builtinParameters)
+ for entry in opts.userParameters:
+ if '=' not in entry:
+ name,val = entry,''
+ else:
+ name,val = entry.split('=', 1)
+ userParams[name] = val
+
+ # Create the global config object.
+ litConfig = LitConfig.LitConfig(progname = os.path.basename(sys.argv[0]),
+ path = opts.path,
+ quiet = opts.quiet,
+ useValgrind = opts.useValgrind,
+ valgrindLeakCheck = opts.valgrindLeakCheck,
+ valgrindArgs = opts.valgrindArgs,
+ useTclAsSh = opts.useTclAsSh,
+ noExecute = opts.noExecute,
+ ignoreStdErr = False,
+ debug = opts.debug,
+ isWindows = (platform.system()=='Windows'),
+ params = userParams)
+
+ # Expand '@...' form in inputs.
+ actual_inputs = []
+ for input in inputs:
+ if os.path.exists(input) or not input.startswith('@'):
+ actual_inputs.append(input)
+ else:
+ f = open(input[1:])
+ try:
+ for ln in f:
+ ln = ln.strip()
+ if ln:
+ actual_inputs.append(ln)
+ finally:
+ f.close()
+
+
+ # Load the tests from the inputs.
+ tests = []
+ testSuiteCache = {}
+ localConfigCache = {}
+ for input in actual_inputs:
+ prev = len(tests)
+ tests.extend(getTests(input, litConfig,
+ testSuiteCache, localConfigCache)[1])
+ if prev == len(tests):
+ litConfig.warning('input %r contained no tests' % input)
+
+ # If there were any errors during test discovery, exit now.
+ if litConfig.numErrors:
+ print >>sys.stderr, '%d errors, exiting.' % litConfig.numErrors
+ sys.exit(2)
+
+ if opts.showSuites:
+ suitesAndTests = dict([(ts,[])
+ for ts,_ in testSuiteCache.values()
+ if ts])
+ for t in tests:
+ suitesAndTests[t.suite].append(t)
+
+ print '-- Test Suites --'
+ suitesAndTests = suitesAndTests.items()
+ suitesAndTests.sort(key = lambda (ts,_): ts.name)
+ for ts,ts_tests in suitesAndTests:
+ print ' %s - %d tests' %(ts.name, len(ts_tests))
+ print ' Source Root: %s' % ts.source_root
+ print ' Exec Root : %s' % ts.exec_root
+
+ # Select and order the tests.
+ numTotalTests = len(tests)
+ if opts.shuffle:
+ random.shuffle(tests)
+ else:
+ tests.sort(key = lambda t: t.getFullName())
+ if opts.maxTests is not None:
+ tests = tests[:opts.maxTests]
+
+ extra = ''
+ if len(tests) != numTotalTests:
+ extra = ' of %d' % numTotalTests
+ header = '-- Testing: %d%s tests, %d threads --'%(len(tests),extra,
+ opts.numThreads)
+
+ if opts.repeatTests:
+ tests = [t.copyWithIndex(i)
+ for t in tests
+ for i in range(opts.repeatTests)]
+
+ progressBar = None
+ if not opts.quiet:
+ if opts.succinct and opts.useProgressBar:
+ try:
+ tc = ProgressBar.TerminalController()
+ progressBar = ProgressBar.ProgressBar(tc, header)
+ except ValueError:
+ print header
+ progressBar = ProgressBar.SimpleProgressBar('Testing: ')
+ else:
+ print header
+
+ # Don't create more threads than tests.
+ opts.numThreads = min(len(tests), opts.numThreads)
+
+ startTime = time.time()
+ display = TestingProgressDisplay(opts, len(tests), progressBar)
+ provider = TestProvider(tests, opts.maxTime)
+ runTests(opts.numThreads, litConfig, provider, display)
+ display.finish()
+
+ if not opts.quiet:
+ print 'Testing Time: %.2fs'%(time.time() - startTime)
+
+ # Update results for any tests which weren't run.
+ for t in tests:
+ if t.result is None:
+ t.setResult(Test.UNRESOLVED, '', 0.0)
+
+ # List test results organized by kind.
+ hasFailures = False
+ byCode = {}
+ for t in tests:
+ if t.result not in byCode:
+ byCode[t.result] = []
+ byCode[t.result].append(t)
+ if t.result.isFailure:
+ hasFailures = True
+
+ # FIXME: Show unresolved and (optionally) unsupported tests.
+ for title,code in (('Unexpected Passing Tests', Test.XPASS),
+ ('Failing Tests', Test.FAIL)):
+ elts = byCode.get(code)
+ if not elts:
+ continue
+ print '*'*20
+ print '%s (%d):' % (title, len(elts))
+ for t in elts:
+ print ' %s' % t.getFullName()
+ print
+
+ if opts.timeTests:
+ # Collate, in case we repeated tests.
+ times = {}
+ for t in tests:
+ key = t.getFullName()
+ times[key] = times.get(key, 0.) + t.elapsed
+
+ byTime = list(times.items())
+ byTime.sort(key = lambda (name,elapsed): elapsed)
+ if byTime:
+ Util.printHistogram(byTime, title='Tests')
+
+ for name,code in (('Expected Passes ', Test.PASS),
+ ('Expected Failures ', Test.XFAIL),
+ ('Unsupported Tests ', Test.UNSUPPORTED),
+ ('Unresolved Tests ', Test.UNRESOLVED),
+ ('Unexpected Passes ', Test.XPASS),
+ ('Unexpected Failures', Test.FAIL),):
+ if opts.quiet and not code.isFailure:
+ continue
+ N = len(byCode.get(code,[]))
+ if N:
+ print ' %s: %d' % (name,N)
+
+ # If we encountered any additional errors, exit abnormally.
+ if litConfig.numErrors:
+ print >>sys.stderr, '\n%d error(s), exiting.' % litConfig.numErrors
+ sys.exit(2)
+
+ # Warn about warnings.
+ if litConfig.numWarnings:
+ print >>sys.stderr, '\n%d warning(s) in tests.' % litConfig.numWarnings
+
+ if hasFailures:
+ sys.exit(1)
+ sys.exit(0)
+
+if __name__=='__main__':
+ main()
diff --git a/src/LLVM/utils/lit/setup.py b/src/LLVM/utils/lit/setup.py
index e6ae3d8..a94e6ea 100644
--- a/src/LLVM/utils/lit/setup.py
+++ b/src/LLVM/utils/lit/setup.py
@@ -3,7 +3,7 @@
# FIXME: Support distutils?
from setuptools import setup, find_packages
setup(
- name = "Lit",
+ name = "lit",
version = lit.__version__,
author = lit.__author__,
@@ -14,15 +14,16 @@
description = "A Software Testing Tool",
keywords = 'test C++ automatic discovery',
long_description = """\
-Lit
-+++
+*lit*
++++++
About
=====
-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.
+*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.
Features
@@ -37,15 +38,15 @@
Documentation
=============
-The offical Lit documentation is in the man page, available online in the `LLVM
-Command Guide http://llvm.org/cmds/lit.html`_.
+The official *lit* documentation is in the man page, available online at the LLVM
+Command Guide: http://llvm.org/cmds/lit.html.
Source
======
-The Lit source is available as part of LLVM, in the `LLVM SVN repository
-<http://llvm.org/svn/llvm-project/llvm/trunk/utils/lit`_.
+The *lit* source is available as part of LLVM, in the LLVM SVN repository:
+http://llvm.org/svn/llvm-project/llvm/trunk/utils/lit.
""",
classifiers=[
@@ -55,7 +56,7 @@
'License :: OSI Approved :: University of Illinois/NCSA Open Source License',
'Natural Language :: English',
'Operating System :: OS Independent',
- 'Progamming Language :: Python',
+ 'Programming Language :: Python',
'Topic :: Software Development :: Testing',
],
diff --git a/src/LLVM/utils/llvm-lit/INSTALL.vcxproj b/src/LLVM/utils/llvm-lit/INSTALL.vcxproj
new file mode 100644
index 0000000..d24593d
--- /dev/null
+++ b/src/LLVM/utils/llvm-lit/INSTALL.vcxproj
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGUID>{048BB775-7681-4EE1-AACF-5A067ACEEEA5}</ProjectGUID>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>INSTALL</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\llvm-lit;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\llvm-lit;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\llvm-lit;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\llvm-lit;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\INSTALL_force.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeLists.txt;CMakeLists.txt;llvm-lit.in;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeLists.txt;CMakeLists.txt;llvm-lit.in;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeLists.txt;CMakeLists.txt;llvm-lit.in;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeLists.txt;CMakeLists.txt;llvm-lit.in;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\generate.stamp</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\ALL_BUILD.vcxproj">
+ <Project>17AECBCF-B2AE-4524-9010-9A175A8F6BFE</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/src/LLVM/utils/llvm-lit/INSTALL.vcxproj.filters b/src/LLVM/utils/llvm-lit/INSTALL.vcxproj.filters
new file mode 100644
index 0000000..251dd1d
--- /dev/null
+++ b/src/LLVM/utils/llvm-lit/INSTALL.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\INSTALL_force.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ <CustomBuild Include="CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{71794486-B3CB-4A48-93CC-DE95557E96E1}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
diff --git a/src/LLVM/utils/llvm-lit/Makefile b/src/LLVM/utils/llvm-lit/Makefile
new file mode 100644
index 0000000..77021bb
--- /dev/null
+++ b/src/LLVM/utils/llvm-lit/Makefile
@@ -0,0 +1,22 @@
+##===- utils/llvm-lit/Makefile -----------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+
+include $(LEVEL)/Makefile.common
+
+all:: $(ToolDir)/llvm-lit
+
+$(ToolDir)/llvm-lit: 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
+ $(Verb)sed -f lit.tmp $< > $@
+ $(Verb)chmod +x $@
+ $(Verb)rm -f lit.tmp
diff --git a/src/LLVM/utils/llvm-lit/PACKAGE.vcxproj b/src/LLVM/utils/llvm-lit/PACKAGE.vcxproj
new file mode 100644
index 0000000..a96e4a4
--- /dev/null
+++ b/src/LLVM/utils/llvm-lit/PACKAGE.vcxproj
@@ -0,0 +1,277 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGUID>{1B050569-3318-48D9-8BB0-4DE9EF58B202}</ProjectGUID>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>PACKAGE</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\llvm-lit;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\llvm-lit;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\llvm-lit;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\llvm-lit;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\PACKAGE_force.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeLists.txt;CMakeLists.txt;llvm-lit.in;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeLists.txt;CMakeLists.txt;llvm-lit.in;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeLists.txt;CMakeLists.txt;llvm-lit.in;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeLists.txt;CMakeLists.txt;llvm-lit.in;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\generate.stamp</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\ALL_BUILD.vcxproj">
+ <Project>17AECBCF-B2AE-4524-9010-9A175A8F6BFE</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/src/LLVM/utils/llvm-lit/PACKAGE.vcxproj.filters b/src/LLVM/utils/llvm-lit/PACKAGE.vcxproj.filters
new file mode 100644
index 0000000..a570359
--- /dev/null
+++ b/src/LLVM/utils/llvm-lit/PACKAGE.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\PACKAGE_force.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ <CustomBuild Include="CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{71794486-B3CB-4A48-93CC-DE95557E96E1}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
diff --git a/src/LLVM/utils/llvm-lit/llvm-lit.in b/src/LLVM/utils/llvm-lit/llvm-lit.in
new file mode 100644
index 0000000..1df1747
--- /dev/null
+++ b/src/LLVM/utils/llvm-lit/llvm-lit.in
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+
+import os
+import sys
+
+# Variables configured at build time.
+llvm_source_root = "@LLVM_SOURCE_DIR@"
+llvm_obj_root = "@LLVM_BINARY_DIR@"
+
+# Make sure we can find the lit package.
+sys.path.append(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_config' : "@CMAKE_CFG_INTDIR@",
+ 'build_mode' : "@RUNTIME_BUILD_MODE@",
+ 'llvm_site_config' : os.path.join(llvm_obj_root, 'test', 'lit.site.cfg')
+ }
+
+clang_site_config = os.path.join(llvm_obj_root, 'tools', 'clang', 'test', 'lit.site.cfg')
+if os.path.exists(clang_site_config):
+ builtin_parameters['clang_site_config'] = clang_site_config
+
+if __name__=='__main__':
+ import lit
+ lit.main(builtin_parameters)
diff --git a/src/LLVM/utils/llvm-native-gcc b/src/LLVM/utils/llvm-native-gcc
index f34e02d..a6f29a74 100644
--- a/src/LLVM/utils/llvm-native-gcc
+++ b/src/LLVM/utils/llvm-native-gcc
@@ -193,10 +193,10 @@
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 bytecode, and then
+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 bytecode to native code, and takes
+If called as "native-build", it compiles bitcode to native code, and takes
different options.
=head1 OPTIONS
diff --git a/src/LLVM/utils/llvm-native-gxx b/src/LLVM/utils/llvm-native-gxx
index 1e9b0c0..ba406ac 100644
--- a/src/LLVM/utils/llvm-native-gxx
+++ b/src/LLVM/utils/llvm-native-gxx
@@ -193,10 +193,10 @@
llvm-native-g++ is a wrapper around the LLVM command-line tools which generates
a native object (.o) file by compiling FILE with llvm-g++, and then running
-an LLVM back-end (CBE by default) over the resulting bytecode, and then
+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 bytecode to native code, and takes
+If called as "native-build", it compiles bitcode to native code, and takes
different options.
=head1 OPTIONS
diff --git a/src/LLVM/utils/llvm.grm b/src/LLVM/utils/llvm.grm
index f97c0d1..fb26dbb 100644
--- a/src/LLVM/utils/llvm.grm
+++ b/src/LLVM/utils/llvm.grm
@@ -9,7 +9,6 @@
pass the Verifier.
TODO: Metadata, in all its forms
-TODO: Union types
*)
@@ -173,6 +172,8 @@
| optsize
| ssp
| sspreq
+ | returns_twice
+ | nonlazybind
;
OptFuncAttrs ::= + _ | OptFuncAttrs FuncAttr ;
diff --git a/src/LLVM/utils/llvmbuild b/src/LLVM/utils/llvmbuild
new file mode 100644
index 0000000..b623d32
--- /dev/null
+++ b/src/LLVM/utils/llvmbuild
@@ -0,0 +1,778 @@
+#!/usr/bin/python3
+##===- utils/llvmbuild - Build the LLVM project ----------------*-python-*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+#
+# This script builds many different flavors of the LLVM ecosystem. It
+# will build LLVM, Clang, llvm-gcc, and dragonegg as well as run tests
+# on them. This script is convenient to use to check builds and tests
+# before committing changes to the upstream repository
+#
+# A typical source setup uses three trees and looks like this:
+#
+# official
+# dragonegg
+# trunk
+# gcc
+# trunk
+# llvm
+# trunk
+# tools
+# clang
+# tags
+# RELEASE_28
+# tools
+# clang
+# llvm-gcc
+# trunk
+# tags
+# RELEASE_28
+# staging
+# dragonegg
+# trunk
+# gcc
+# trunk
+# llvm
+# trunk
+# tools
+# clang
+# tags
+# RELEASE_28
+# tools
+# clang
+# llvm-gcc
+# trunk
+# tags
+# RELEASE_28
+# commit
+# dragonegg
+# trunk
+# gcc
+# trunk
+# llvm
+# trunk
+# tools
+# clang
+# tags
+# RELEASE_28
+# tools
+# clang
+# llvm-gcc
+# trunk
+# tags
+# RELEASE_28
+#
+# "gcc" above is the upstream FSF gcc and "gcc/trunk" refers to the
+# 4.5 branch as discussed in the dragonegg build guide.
+#
+# In a typical workflow, the "official" tree always contains unchanged
+# sources from the main LLVM project repositories. The "staging" tree
+# is where local work is done. A set of changes resides there waiting
+# to be moved upstream. The "commit" tree is where changes from
+# "staging" make their way upstream. Individual incremental changes
+# from "staging" are applied to "commit" and committed upstream after
+# a successful build and test run. A successful build is one in which
+# testing results in no more failures than seen in the testing of the
+# "official" tree.
+#
+# A build may be invoked as such:
+#
+# llvmbuild --src=~/llvm/commit --src=~/llvm/staging
+# --src=~/llvm/official --branch=trunk --branch=tags/RELEASE_28
+# --build=debug --build=release --build=paranoid
+# --prefix=/home/greened/install --builddir=/home/greened/build
+#
+# This will build the LLVM ecosystem, including LLVM, Clang, llvm-gcc,
+# gcc 4.5 and dragonegg, putting build results in ~/build and
+# installing tools in ~/install. llvmbuild creates separate build and
+# install directories for each source/branch/build flavor. In the
+# above example, llvmbuild will build debug, release and paranoid
+# (debug+checks) flavors of the trunk and RELEASE_28 branches from
+# each source tree (official, staging and commit) for a total of
+# eighteen builds. All builds will be run in parallel.
+#
+# The user may control parallelism via the --jobs and --threads
+# switches. --jobs tells llvmbuild the maximum total number of builds
+# to activate in parallel. The user may think of it as equivalent to
+# the GNU make -j switch. --threads tells llvmbuild how many worker
+# threads to use to accomplish those builds. If --threads is less
+# than --jobs, --threads workers will be launched and each one will
+# pick a source/branch/flavor combination to build. Then llvmbuild
+# will invoke GNU make with -j (--jobs / --threads) to use up the
+# remaining job capacity. Once a worker is finished with a build, it
+# will pick another combination off the list and start building it.
+#
+##===----------------------------------------------------------------------===##
+
+import optparse
+import os
+import sys
+import threading
+import queue
+import logging
+import traceback
+import subprocess
+import re
+
+# TODO: Use shutil.which when it is available (3.2 or later)
+def find_executable(executable, path=None):
+ """Try to find 'executable' in the directories listed in 'path' (a
+ string listing directories separated by 'os.pathsep'; defaults to
+ os.environ['PATH']). Returns the complete filename or None if not
+ found
+ """
+ if path is None:
+ path = os.environ['PATH']
+ paths = path.split(os.pathsep)
+ extlist = ['']
+ if os.name == 'os2':
+ (base, ext) = os.path.splitext(executable)
+ # executable files on OS/2 can have an arbitrary extension, but
+ # .exe is automatically appended if no dot is present in the name
+ if not ext:
+ executable = executable + ".exe"
+ elif sys.platform == 'win32':
+ pathext = os.environ['PATHEXT'].lower().split(os.pathsep)
+ (base, ext) = os.path.splitext(executable)
+ if ext.lower() not in pathext:
+ extlist = pathext
+ for ext in extlist:
+ execname = executable + ext
+ if os.path.isfile(execname):
+ return execname
+ else:
+ for p in paths:
+ f = os.path.join(p, execname)
+ if os.path.isfile(f):
+ return f
+ else:
+ return None
+
+def is_executable(fpath):
+ return os.path.exists(fpath) and os.access(fpath, os.X_OK)
+
+def add_options(parser):
+ parser.add_option("-v", "--verbose", action="store_true",
+ default=False,
+ help=("Output informational messages"
+ " [default: %default]"))
+ parser.add_option("--src", action="append",
+ help=("Top-level source directory [default: %default]"))
+ parser.add_option("--build", action="append",
+ help=("Build types to run [default: %default]"))
+ parser.add_option("--branch", action="append",
+ help=("Source branch to build [default: %default]"))
+ parser.add_option("--cc", default=find_executable("cc"),
+ help=("The C compiler to use [default: %default]"))
+ parser.add_option("--cxx", default=find_executable("c++"),
+ help=("The C++ compiler to use [default: %default]"))
+ parser.add_option("--threads", default=4, type="int",
+ help=("The number of worker threads to use "
+ "[default: %default]"))
+ parser.add_option("--jobs", "-j", default=8, type="int",
+ help=("The number of simultaneous build jobs "
+ "[default: %default]"))
+ parser.add_option("--prefix",
+ help=("Root install directory [default: %default]"))
+ parser.add_option("--builddir",
+ help=("Root build directory [default: %default]"))
+ parser.add_option("--extra-llvm-config-flags", default="",
+ help=("Extra flags to pass to llvm configure [default: %default]"))
+ parser.add_option("--extra-llvm-gcc-config-flags", default="",
+ help=("Extra flags to pass to llvm-gcc configure [default: %default]"))
+ parser.add_option("--extra-gcc-config-flags", default="",
+ help=("Extra flags to pass to gcc configure [default: %default]"))
+ parser.add_option("--force-configure", default=False, action="store_true",
+ help=("Force reconfigure of all components"))
+ parser.add_option("--no-gcc", default=False, action="store_true",
+ help=("Do not build dragonegg and gcc"))
+ parser.add_option("--no-install", default=False, action="store_true",
+ help=("Do not do installs"))
+ return
+
+def check_options(parser, options, valid_builds):
+ # See if we're building valid flavors.
+ for build in options.build:
+ if (build not in valid_builds):
+ parser.error("'" + build + "' is not a valid build flavor "
+ + str(valid_builds))
+
+ # See if we can find source directories.
+ for src in options.src:
+ for component in components:
+ component = component.rstrip("2")
+ compsrc = src + "/" + component
+ if (not os.path.isdir(compsrc)):
+ parser.error("'" + compsrc + "' does not exist")
+ if (options.branch is not None):
+ for branch in options.branch:
+ if (not os.path.isdir(os.path.join(compsrc, branch))):
+ parser.error("'" + os.path.join(compsrc, branch)
+ + "' does not exist")
+
+ # See if we can find the compilers
+ options.cc = find_executable(options.cc)
+ options.cxx = find_executable(options.cxx)
+
+ return
+
+# Find a unique short name for the given set of paths. This searches
+# back through path components until it finds unique component names
+# among all given paths.
+def get_path_abbrevs(paths):
+ # Find the number of common starting characters in the last component
+ # of the paths.
+ unique_paths = list(paths)
+
+ class NotFoundException(Exception): pass
+
+ # Find a unique component of each path.
+ unique_bases = unique_paths[:]
+ found = 0
+ while len(unique_paths) > 0:
+ bases = [os.path.basename(src) for src in unique_paths]
+ components = { c for c in bases }
+ # Account for single entry in paths.
+ if len(components) > 1 or len(components) == len(bases):
+ # We found something unique.
+ for c in components:
+ if bases.count(c) == 1:
+ index = bases.index(c)
+ unique_bases[index] = c
+ # Remove the corresponding path from the set under
+ # consideration.
+ unique_paths[index] = None
+ unique_paths = [ p for p in unique_paths if p is not None ]
+ unique_paths = [os.path.dirname(src) for src in unique_paths]
+
+ if len(unique_paths) > 0:
+ raise NotFoundException()
+
+ abbrevs = dict(zip(paths, [base for base in unique_bases]))
+
+ return abbrevs
+
+# Given a set of unique names, find a short character sequence that
+# uniquely identifies them.
+def get_short_abbrevs(unique_bases):
+ # Find a unique start character for each path base.
+ my_unique_bases = unique_bases[:]
+ unique_char_starts = unique_bases[:]
+ while len(my_unique_bases) > 0:
+ for start, char_tuple in enumerate(zip(*[base
+ for base in my_unique_bases])):
+ chars = { c for c in char_tuple }
+ # Account for single path.
+ if len(chars) > 1 or len(chars) == len(char_tuple):
+ # We found something unique.
+ for c in chars:
+ if char_tuple.count(c) == 1:
+ index = char_tuple.index(c)
+ unique_char_starts[index] = start
+ # Remove the corresponding path from the set under
+ # consideration.
+ my_unique_bases[index] = None
+ my_unique_bases = [ b for b in my_unique_bases
+ if b is not None ]
+ break
+
+ if len(my_unique_bases) > 0:
+ raise NotFoundException()
+
+ abbrevs = [abbrev[start_index:start_index+3]
+ for abbrev, start_index
+ in zip([base for base in unique_bases],
+ [index for index in unique_char_starts])]
+
+ abbrevs = dict(zip(unique_bases, abbrevs))
+
+ return abbrevs
+
+class Builder(threading.Thread):
+ class ExecutableNotFound(Exception): pass
+ class FileNotExecutable(Exception): pass
+
+ def __init__(self, work_queue, jobs,
+ build_abbrev, source_abbrev, branch_abbrev,
+ options):
+ super().__init__()
+ self.work_queue = work_queue
+ self.jobs = jobs
+ self.cc = options.cc
+ self.cxx = options.cxx
+ self.build_abbrev = build_abbrev
+ self.source_abbrev = source_abbrev
+ self.branch_abbrev = branch_abbrev
+ self.build_prefix = options.builddir
+ self.install_prefix = options.prefix
+ self.options = options
+ self.component_abbrev = dict(
+ llvm="llvm",
+ llvm_gcc="lgcc",
+ llvm2="llv2",
+ gcc="ugcc",
+ dagonegg="degg")
+ def run(self):
+ while True:
+ try:
+ source, branch, build = self.work_queue.get()
+ self.dobuild(source, branch, build)
+ except:
+ traceback.print_exc()
+ finally:
+ self.work_queue.task_done()
+
+ def execute(self, command, execdir, env, component):
+ prefix = self.component_abbrev[component.replace("-", "_")]
+ pwd = os.getcwd()
+ if not os.path.exists(execdir):
+ os.makedirs(execdir)
+
+ execenv = os.environ.copy()
+
+ for key, value in env.items():
+ execenv[key] = value
+
+ self.logger.debug("[" + prefix + "] " + "env " + str(env) + " "
+ + " ".join(command));
+
+ try:
+ proc = subprocess.Popen(command,
+ cwd=execdir,
+ env=execenv,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+
+ line = proc.stdout.readline()
+ while line:
+ self.logger.info("[" + prefix + "] "
+ + str(line, "utf-8").rstrip())
+ line = proc.stdout.readline()
+
+ except:
+ traceback.print_exc()
+
+ # Get a list of C++ include directories to pass to clang.
+ def get_includes(self):
+ # Assume we're building with g++ for now.
+ command = [self.cxx]
+ command += ["-v", "-x", "c++", "/dev/null", "-fsyntax-only"]
+ includes = []
+ self.logger.debug(command)
+ try:
+ proc = subprocess.Popen(command,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+
+ gather = False
+ line = proc.stdout.readline()
+ while line:
+ self.logger.debug(line)
+ if re.search("End of search list", str(line)) is not None:
+ self.logger.debug("Stop Gather")
+ gather = False
+ if gather:
+ includes.append(str(line, "utf-8").strip())
+ if re.search("#include <...> search starts", str(line)) is not None:
+ self.logger.debug("Start Gather")
+ gather = True
+ line = proc.stdout.readline()
+ except:
+ traceback.print_exc()
+ self.logger.debug(includes)
+ return includes
+
+ def dobuild(self, source, branch, build):
+ build_suffix = ""
+
+ ssabbrev = get_short_abbrevs([ab for ab in self.source_abbrev.values()])
+
+ if branch is not None:
+ sbabbrev = get_short_abbrevs([ab for ab in self.branch_abbrev.values()])
+
+ prefix = "[" + ssabbrev[self.source_abbrev[source]] + "-" + sbabbrev[self.branch_abbrev[branch]] + "-" + self.build_abbrev[build] + "]"
+ self.install_prefix += "/" + self.source_abbrev[source] + "/" + branch + "/" + build
+ build_suffix += self.source_abbrev[source] + "/" + branch + "/" + build
+ else:
+ prefix = "[" + ssabbrev[self.source_abbrev[source]] + "-" + self.build_abbrev[build] + "]"
+ self.install_prefix += "/" + self.source_abbrev[source] + "/" + build
+ build_suffix += "/" + self.source_abbrev[source] + "/" + build
+
+ self.logger = logging.getLogger(prefix)
+
+ self.logger.debug(self.install_prefix)
+
+ # Assume we're building with gcc for now.
+ cxxincludes = self.get_includes()
+ cxxroot = cxxincludes[0]
+ cxxarch = os.path.basename(cxxincludes[1])
+
+ configure_flags = dict(
+ llvm=dict(debug=["--prefix=" + self.install_prefix,
+ "--with-extra-options=-Werror",
+ "--enable-assertions",
+ "--disable-optimized",
+ "--with-cxx-include-root=" + cxxroot,
+ "--with-cxx-include-arch=" + cxxarch],
+ release=["--prefix=" + self.install_prefix,
+ "--with-extra-options=-Werror",
+ "--enable-optimized",
+ "--with-cxx-include-root=" + cxxroot,
+ "--with-cxx-include-arch=" + cxxarch],
+ paranoid=["--prefix=" + self.install_prefix,
+ "--with-extra-options=-Werror",
+ "--enable-assertions",
+ "--enable-expensive-checks",
+ "--disable-optimized",
+ "--with-cxx-include-root=" + cxxroot,
+ "--with-cxx-include-arch=" + cxxarch]),
+ llvm_gcc=dict(debug=["--prefix=" + self.install_prefix,
+ "--enable-checking",
+ "--program-prefix=llvm-",
+ "--enable-llvm=" + self.build_prefix + "/llvm/" + build_suffix,
+# Fortran install seems to be broken.
+# "--enable-languages=c,c++,fortran"],
+ "--enable-languages=c,c++"],
+ release=["--prefix=" + self.install_prefix,
+ "--program-prefix=llvm-",
+ "--enable-llvm=" + self.build_prefix + "/llvm/" + build_suffix,
+# Fortran install seems to be broken.
+# "--enable-languages=c,c++,fortran"],
+ "--enable-languages=c,c++"],
+ paranoid=["--prefix=" + self.install_prefix,
+ "--enable-checking",
+ "--program-prefix=llvm-",
+ "--enable-llvm=" + self.build_prefix + "/llvm/" + build_suffix,
+# Fortran install seems to be broken.
+# "--enable-languages=c,c++,fortran"]),
+ "--enable-languages=c,c++"]),
+ llvm2=dict(debug=["--prefix=" + self.install_prefix,
+ "--with-extra-options=-Werror",
+ "--enable-assertions",
+ "--disable-optimized",
+ "--with-llvmgccdir=" + self.install_prefix + "/bin",
+ "--with-cxx-include-root=" + cxxroot,
+ "--with-cxx-include-arch=" + cxxarch],
+ release=["--prefix=" + self.install_prefix,
+ "--with-extra-options=-Werror",
+ "--enable-optimized",
+ "--with-llvmgccdir=" + self.install_prefix + "/bin",
+ "--with-cxx-include-root=" + cxxroot,
+ "--with-cxx-include-arch=" + cxxarch],
+ paranoid=["--prefix=" + self.install_prefix,
+ "--with-extra-options=-Werror",
+ "--enable-assertions",
+ "--enable-expensive-checks",
+ "--disable-optimized",
+ "--with-llvmgccdir=" + self.install_prefix + "/bin",
+ "--with-cxx-include-root=" + cxxroot,
+ "--with-cxx-include-arch=" + cxxarch]),
+ gcc=dict(debug=["--prefix=" + self.install_prefix,
+ "--enable-checking"],
+ release=["--prefix=" + self.install_prefix],
+ paranoid=["--prefix=" + self.install_prefix,
+ "--enable-checking"]),
+ dragonegg=dict(debug=[],
+ release=[],
+ paranoid=[]))
+
+ configure_env = dict(
+ llvm=dict(debug=dict(CC=self.cc,
+ CXX=self.cxx),
+ release=dict(CC=self.cc,
+ CXX=self.cxx),
+ paranoid=dict(CC=self.cc,
+ CXX=self.cxx)),
+ llvm_gcc=dict(debug=dict(CC=self.cc,
+ CXX=self.cxx),
+ release=dict(CC=self.cc,
+ CXX=self.cxx),
+ paranoid=dict(CC=self.cc,
+ CXX=self.cxx)),
+ llvm2=dict(debug=dict(CC=self.cc,
+ CXX=self.cxx),
+ release=dict(CC=self.cc,
+ CXX=self.cxx),
+ paranoid=dict(CC=self.cc,
+ CXX=self.cxx)),
+ gcc=dict(debug=dict(CC=self.cc,
+ CXX=self.cxx),
+ release=dict(CC=self.cc,
+ CXX=self.cxx),
+ paranoid=dict(CC=self.cc,
+ CXX=self.cxx)),
+ dragonegg=dict(debug=dict(CC=self.cc,
+ CXX=self.cxx),
+ release=dict(CC=self.cc,
+ CXX=self.cxx),
+ paranoid=dict(CC=self.cc,
+ CXX=self.cxx)))
+
+ make_flags = dict(
+ llvm=dict(debug=["-j" + str(self.jobs)],
+ release=["-j" + str(self.jobs)],
+ paranoid=["-j" + str(self.jobs)]),
+ llvm_gcc=dict(debug=["-j" + str(self.jobs),
+ "bootstrap"],
+ release=["-j" + str(self.jobs),
+ "bootstrap"],
+ paranoid=["-j" + str(self.jobs),
+ "bootstrap"]),
+ llvm2=dict(debug=["-j" + str(self.jobs)],
+ release=["-j" + str(self.jobs)],
+ paranoid=["-j" + str(self.jobs)]),
+ gcc=dict(debug=["-j" + str(self.jobs),
+ "bootstrap"],
+ release=["-j" + str(self.jobs),
+ "bootstrap"],
+ paranoid=["-j" + str(self.jobs),
+ "bootstrap"]),
+ dragonegg=dict(debug=["-j" + str(self.jobs)],
+ release=["-j" + str(self.jobs)],
+ paranoid=["-j" + str(self.jobs)]))
+
+ make_env = dict(
+ llvm=dict(debug=dict(),
+ release=dict(),
+ paranoid=dict()),
+ llvm_gcc=dict(debug=dict(),
+ release=dict(),
+ paranoid=dict()),
+ llvm2=dict(debug=dict(),
+ release=dict(),
+ paranoid=dict()),
+ gcc=dict(debug=dict(),
+ release=dict(),
+ paranoid=dict()),
+ dragonegg=dict(debug=dict(GCC=self.install_prefix + "/bin/gcc",
+ LLVM_CONFIG=self.install_prefix + "/bin/llvm-config"),
+ release=dict(GCC=self.install_prefix + "/bin/gcc",
+ LLVM_CONFIG=self.install_prefix + "/bin/llvm-config"),
+ paranoid=dict(GCC=self.install_prefix + "/bin/gcc",
+ LLVM_CONFIG=self.install_prefix + "/bin/llvm-config")))
+
+ make_install_flags = dict(
+ llvm=dict(debug=["install"],
+ release=["install"],
+ paranoid=["install"]),
+ llvm_gcc=dict(debug=["install"],
+ release=["install"],
+ paranoid=["install"]),
+ llvm2=dict(debug=["install"],
+ release=["install"],
+ paranoid=["install"]),
+ gcc=dict(debug=["install"],
+ release=["install"],
+ paranoid=["install"]),
+ dragonegg=dict(debug=["install"],
+ release=["install"],
+ paranoid=["install"]))
+
+ make_install_env = dict(
+ llvm=dict(debug=dict(),
+ release=dict(),
+ paranoid=dict()),
+ llvm_gcc=dict(debug=dict(),
+ release=dict(),
+ paranoid=dict()),
+ llvm2=dict(debug=dict(),
+ release=dict(),
+ paranoid=dict()),
+ gcc=dict(debug=dict(),
+ release=dict(),
+ paranoid=dict()),
+ dragonegg=dict(debug=dict(),
+ release=dict(),
+ paranoid=dict()))
+
+ make_check_flags = dict(
+ llvm=dict(debug=["check"],
+ release=["check"],
+ paranoid=["check"]),
+ llvm_gcc=dict(debug=["check"],
+ release=["check"],
+ paranoid=["check"]),
+ llvm2=dict(debug=["check"],
+ release=["check"],
+ paranoid=["check"]),
+ gcc=dict(debug=["check"],
+ release=["check"],
+ paranoid=["check"]),
+ dragonegg=dict(debug=["check"],
+ release=["check"],
+ paranoid=["check"]))
+
+ make_check_env = dict(
+ llvm=dict(debug=dict(),
+ release=dict(),
+ paranoid=dict()),
+ llvm_gcc=dict(debug=dict(),
+ release=dict(),
+ paranoid=dict()),
+ llvm2=dict(debug=dict(),
+ release=dict(),
+ paranoid=dict()),
+ gcc=dict(debug=dict(),
+ release=dict(),
+ paranoid=dict()),
+ dragonegg=dict(debug=dict(),
+ release=dict(),
+ paranoid=dict()))
+
+ for component in components:
+ comp = component[:]
+
+ if (self.options.no_gcc):
+ if (comp == 'gcc' or comp == 'dragonegg' or comp == 'llvm2'):
+ self.logger.info("Skipping " + component + " in "
+ + builddir)
+ continue
+
+ srcdir = source + "/" + comp.rstrip("2")
+ builddir = self.build_prefix + "/" + comp + "/" + build_suffix
+ installdir = self.install_prefix
+
+ if (branch is not None):
+ srcdir += "/" + branch
+
+ comp_key = comp.replace("-", "_")
+
+ config_args = configure_flags[comp_key][build][:]
+ config_args.extend(getattr(self.options,
+ "extra_" + comp_key.rstrip("2")
+ + "_config_flags").split())
+
+ self.logger.info("Configuring " + component + " in " + builddir)
+ self.configure(component, srcdir, builddir,
+ config_args,
+ configure_env[comp_key][build])
+
+ self.logger.info("Building " + component + " in " + builddir)
+ self.logger.info("Build: make " + str(make_flags[comp_key][build]))
+ self.make(component, srcdir, builddir,
+ make_flags[comp_key][build],
+ make_env[comp_key][build])
+
+ if (not self.options.no_install):
+ self.logger.info("Installing " + component + " in " + installdir)
+ self.make(component, srcdir, builddir,
+ make_install_flags[comp_key][build],
+ make_install_env[comp_key][build])
+
+ self.logger.info("Testing " + component + " in " + builddir)
+ self.logger.info("Test: make "
+ + str(make_check_flags[comp_key][build]))
+ self.make(component, srcdir, builddir,
+ make_check_flags[comp_key][build],
+ make_check_env[comp_key][build])
+
+
+ def configure(self, component, srcdir, builddir, flags, env):
+ self.logger.debug("Configure " + str(flags) + " " + str(srcdir) + " -> "
+ + str(builddir))
+
+ configure_files = dict(
+ llvm=[(srcdir + "/configure", builddir + "/Makefile")],
+ llvm_gcc=[(srcdir + "/configure", builddir + "/Makefile"),
+ (srcdir + "/gcc/configure", builddir + "/gcc/Makefile")],
+ llvm2=[(srcdir + "/configure", builddir + "/Makefile")],
+ gcc=[(srcdir + "/configure", builddir + "/Makefile"),
+ (srcdir + "/gcc/configure", builddir + "/gcc/Makefile")],
+ dragonegg=[()])
+
+
+ doconfig = False
+ for conf, mf in configure_files[component.replace("-", "_")]:
+ if not os.path.exists(conf):
+ return
+ if os.path.exists(conf) and os.path.exists(mf):
+ confstat = os.stat(conf)
+ makestat = os.stat(mf)
+ if confstat.st_mtime > makestat.st_mtime:
+ doconfig = True
+ break
+ else:
+ doconfig = True
+ break
+
+ if not doconfig and not self.options.force_configure:
+ return
+
+ program = srcdir + "/configure"
+ if not is_executable(program):
+ return
+
+ args = [program]
+ args += ["--verbose"]
+ args += flags
+ self.execute(args, builddir, env, component)
+
+ def make(self, component, srcdir, builddir, flags, env):
+ program = find_executable("make")
+ if program is None:
+ raise ExecutableNotFound
+
+ if not is_executable(program):
+ raise FileNotExecutable
+
+ args = [program]
+ args += flags
+ self.execute(args, builddir, env, component)
+
+# Global constants
+build_abbrev = dict(debug="dbg", release="opt", paranoid="par")
+#components = ["llvm", "llvm-gcc", "llvm2", "gcc", "dragonegg"]
+components = ["llvm", "llvm2", "gcc", "dragonegg"]
+
+# Parse options
+parser = optparse.OptionParser(version="%prog 1.0")
+add_options(parser)
+(options, args) = parser.parse_args()
+check_options(parser, options, build_abbrev.keys());
+
+if options.verbose:
+ logging.basicConfig(level=logging.DEBUG,
+ format='%(name)-13s: %(message)s')
+else:
+ logging.basicConfig(level=logging.INFO,
+ format='%(name)-13s: %(message)s')
+
+source_abbrev = get_path_abbrevs(set(options.src))
+
+branch_abbrev = None
+if options.branch is not None:
+ branch_abbrev = get_path_abbrevs(set(options.branch))
+
+work_queue = queue.Queue()
+
+jobs = options.jobs // options.threads
+if jobs == 0:
+ jobs = 1
+
+numthreads = options.threads
+
+logging.getLogger().info("Building with " + str(options.jobs) + " jobs and "
+ + str(numthreads) + " threads using " + str(jobs)
+ + " make jobs")
+
+for t in range(numthreads):
+ builder = Builder(work_queue, jobs,
+ build_abbrev, source_abbrev, branch_abbrev,
+ options)
+ builder.daemon = True
+ builder.start()
+
+for build in set(options.build):
+ for source in set(options.src):
+ if options.branch is not None:
+ for branch in set(options.branch):
+ work_queue.put((source, branch, build))
+ else:
+ work_queue.put((source, None, build))
+
+work_queue.join()
diff --git a/src/LLVM/utils/not/INSTALL.vcxproj b/src/LLVM/utils/not/INSTALL.vcxproj
new file mode 100644
index 0000000..e678da1
--- /dev/null
+++ b/src/LLVM/utils/not/INSTALL.vcxproj
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGUID>{048BB775-7681-4EE1-AACF-5A067ACEEEA5}</ProjectGUID>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>INSTALL</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\not;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\not;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\not;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\not;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -DBUILD_TYPE=$(Configuration) -P cmake_install.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\INSTALL_force.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles/INSTALL_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\INSTALL_force</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\generate.stamp</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\ALL_BUILD.vcxproj">
+ <Project>17AECBCF-B2AE-4524-9010-9A175A8F6BFE</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/src/LLVM/utils/not/INSTALL.vcxproj.filters b/src/LLVM/utils/not/INSTALL.vcxproj.filters
new file mode 100644
index 0000000..251dd1d
--- /dev/null
+++ b/src/LLVM/utils/not/INSTALL.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\INSTALL_force.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ <CustomBuild Include="CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{71794486-B3CB-4A48-93CC-DE95557E96E1}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
diff --git a/src/LLVM/utils/not/Makefile b/src/LLVM/utils/not/Makefile
index fef4802..f37f166 100644
--- a/src/LLVM/utils/not/Makefile
+++ b/src/LLVM/utils/not/Makefile
@@ -1,15 +1,15 @@
##===- utils/not/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 = not
-USEDLIBS = LLVMSupport.a LLVMSystem.a
+USEDLIBS = LLVMSupport.a
# This tool has no plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
diff --git a/src/LLVM/utils/not/PACKAGE.vcxproj b/src/LLVM/utils/not/PACKAGE.vcxproj
new file mode 100644
index 0000000..47b87e1
--- /dev/null
+++ b/src/LLVM/utils/not/PACKAGE.vcxproj
@@ -0,0 +1,277 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGUID>{1B050569-3318-48D9-8BB0-4DE9EF58B202}</ProjectGUID>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>PACKAGE</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType></ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">$(Platform)\$(Configuration)\$(ProjectName)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\not;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\not;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\not;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <Midl>
+ <AdditionalIncludeDirectories>..\not;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <PostBuildEvent>
+ <Message></Message>
+ <Command>setlocal
+cd ..\..\..\LLVM
+if %errorlevel% neq 0 goto :cmEnd
+D:
+if %errorlevel% neq 0 goto :cmEnd
+"C:\Program Files (x86)\CMake 2.8\bin\cpack.exe" -C $(Configuration) --config ./CPackConfig.cmake
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ </PostBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\PACKAGE_force.rule">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'"> </Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+cd .
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles/PACKAGE_force.rule;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\PACKAGE_force</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\generate.stamp</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\ALL_BUILD.vcxproj">
+ <Project>17AECBCF-B2AE-4524-9010-9A175A8F6BFE</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/src/LLVM/utils/not/PACKAGE.vcxproj.filters b/src/LLVM/utils/not/PACKAGE.vcxproj.filters
new file mode 100644
index 0000000..a570359
--- /dev/null
+++ b/src/LLVM/utils/not/PACKAGE.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeFiles\PACKAGE_force.rule">
+ <Filter>CMake Rules</Filter>
+ </CustomBuild>
+ <CustomBuild Include="CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="CMake Rules">
+ <UniqueIdentifier>{71794486-B3CB-4A48-93CC-DE95557E96E1}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
diff --git a/src/LLVM/utils/not/not.cpp b/src/LLVM/utils/not/not.cpp
index dd89b8f..9a924b5 100644
--- a/src/LLVM/utils/not/not.cpp
+++ b/src/LLVM/utils/not/not.cpp
@@ -7,11 +7,21 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/System/Path.h"
-#include "llvm/System/Program.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
int main(int argc, const char **argv) {
sys::Path Program = sys::Program::FindProgramByName(argv[1]);
- return !sys::Program::ExecuteAndWait(Program, argv + 1);
+
+ std::string ErrMsg;
+ int Result = sys::Program::ExecuteAndWait(Program, argv + 1, 0, 0, 0, 0,
+ &ErrMsg);
+ if (Result < 0) {
+ errs() << "Error: " << ErrMsg << "\n";
+ return 1;
+ }
+
+ return Result == 0;
}
diff --git a/src/LLVM/utils/not/not.vcxproj b/src/LLVM/utils/not/not.vcxproj
new file mode 100644
index 0000000..0ff5a15
--- /dev/null
+++ b/src/LLVM/utils/not/not.vcxproj
@@ -0,0 +1,345 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="MinSizeRel|Win32">
+ <Configuration>MinSizeRel</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="RelWithDebInfo|Win32">
+ <Configuration>RelWithDebInfo</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGUID>{84B72A06-2281-4CCA-8F1A-5BD60C0236E9}</ProjectGUID>
+ <Keyword>Win32Proj</Keyword>
+ <Platform>Win32</Platform>
+ <ProjectName>not</ProjectName>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\bin\Debug\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">not.dir\Debug\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">not</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</GenerateManifest>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\bin\Release\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">not.dir\Release\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">not</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</GenerateManifest>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">..\..\bin\MinSizeRel\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">not.dir\MinSizeRel\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">not</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">false</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">true</GenerateManifest>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">..\..\bin\RelWithDebInfo\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">not.dir\RelWithDebInfo\</IntDir>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">not</TargetName>
+ <TargetExt Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">.exe</TargetExt>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">true</LinkIncremental>
+ <GenerateManifest Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">true</GenerateManifest>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 /EHs-c- -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\not;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>Disabled</Optimization>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>Debug</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/Debug/not.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\not;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\not;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalOptions> /machine:X86 /debug %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;..\..\lib\Debug\LLVMSupport.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/Debug/not.lib</ImportLibrary>
+ <LinkIncremental>true</LinkIncremental>
+ <ProgramDataBaseFileName>..\..\bin/Debug/not.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 /EHs-c- -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\not;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>MaxSpeed</Optimization>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>Release</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/Release/not.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\not;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\not;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalOptions> /machine:X86 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;..\..\lib\Release\LLVMSupport.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/Release/not.lib</ImportLibrary>
+ <ProgramDataBaseFileName>..\..\bin/Release/not.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 /EHs-c- -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\not;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>MinSpace</Optimization>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>
+ </DebugInformationFormat>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR="MinSizeRel";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>MinSizeRel</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/MinSizeRel/not.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR=\"MinSizeRel\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\not;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\not;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalOptions> /machine:X86 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;..\..\lib\MinSizeRel\LLVMSupport.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/MinSizeRel/not.lib</ImportLibrary>
+ <ProgramDataBaseFileName>..\..\bin/MinSizeRel/not.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
+ <ClCompile>
+ <AdditionalOptions> /Zm1000 /EHs-c- -w14062 %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalIncludeDirectories>..\not;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsCpp</CompileAs>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4146;4180;4224;4244;4267;4275;4291;4345;4351;4355;4503;4551;4624;4715;4800;4065;4181</DisableSpecificWarnings>
+ <ExceptionHandling>
+ </ExceptionHandling>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <Optimization>MaxSpeed</Optimization>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <RuntimeTypeInfo>false</RuntimeTypeInfo>
+ <WarningLevel>Level3</WarningLevel>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AssemblerListingLocation>RelWithDebInfo</AssemblerListingLocation>
+ <ObjectFileName>$(IntDir)</ObjectFileName>
+ <ProgramDataBaseFileName>..\..\bin/RelWithDebInfo/not.pdb</ProgramDataBaseFileName>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_SCL_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;__STDC_FORMAT_MACROS;__STDC_LIMIT_MACROS;_HAS_EXCEPTIONS=0;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <AdditionalIncludeDirectories>..\not;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ </ResourceCompile>
+ <Midl>
+ <AdditionalIncludeDirectories>..\not;..\..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <OutputDirectory>$(IntDir)</OutputDirectory>
+ <HeaderFileName>%(Filename).h</HeaderFileName>
+ <TypeLibraryName>%(Filename).tlb</TypeLibraryName>
+ <InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
+ <ProxyFileName>%(Filename)_p.c</ProxyFileName>
+ </Midl>
+ <Link>
+ <AdditionalOptions> /machine:X86 /debug %(AdditionalOptions)</AdditionalOptions>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;comdlg32.lib;advapi32.lib;..\..\lib\RelWithDebInfo\LLVMSupport.lib</AdditionalDependencies>
+ <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ImportLibrary>..\..\lib/RelWithDebInfo/not.lib</ImportLibrary>
+ <LinkIncremental>true</LinkIncremental>
+ <ProgramDataBaseFileName>..\..\bin/RelWithDebInfo/not.pdb</ProgramDataBaseFileName>
+ <StackReserveSize>10000000</StackReserveSize>
+ <SubSystem>Console</SubSystem>
+ <Version>
+ </Version>
+ </Link>
+ <ProjectReference>
+ <LinkLibraryDependencies>false</LinkLibraryDependencies>
+ </ProjectReference>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeLists.txt">
+ <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">CMakeFiles\generate.stamp</Outputs>
+ <Message Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">Building Custom Rule CMakeLists.txt</Message>
+ <Command Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">setlocal
+"C:\Program Files (x86)\CMake 2.8\bin\cmake.exe" -H../.. -B../.. --check-stamp-file CMakeFiles\generate.stamp
+if %errorlevel% neq 0 goto :cmEnd
+:cmEnd
+endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
+:cmErrorLevel
+exit /b %1
+:cmDone
+if %errorlevel% neq 0 goto :VCEnd</Command>
+ <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeLists.txt;CMakeLists.txt;CMakeLists.txt;%(AdditionalInputs)</AdditionalInputs>
+ <Outputs Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">CMakeFiles\generate.stamp</Outputs>
+ </CustomBuild>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="not.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\lib/Support/LLVMSupport.vcxproj">
+ <Project>C688DD59-C6CB-4B33-B56F-A7D6F3761524</Project>
+ </ProjectReference>
+ <ProjectReference Include="..\..\include/llvm/intrinsics_gen.vcxproj">
+ <Project>E9B87B46-1EB0-4D95-9049-41B148FBADCD</Project>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/src/LLVM/utils/not/not.vcxproj.filters b/src/LLVM/utils/not/not.vcxproj.filters
new file mode 100644
index 0000000..3a80139
--- /dev/null
+++ b/src/LLVM/utils/not/not.vcxproj.filters
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="not.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+ <ItemGroup>
+ <CustomBuild Include="CMakeLists.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{1733179C-6FE4-462E-9EA5-4A29A1ACFE25}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ </ItemGroup>
+</Project>
diff --git a/src/LLVM/utils/profile.pl b/src/LLVM/utils/profile.pl
index f9950f9..782e5dc 100644
--- a/src/LLVM/utils/profile.pl
+++ b/src/LLVM/utils/profile.pl
@@ -5,7 +5,7 @@
# Synopsis: Insert instrumentation code into a program, run it with the JIT,
# then print out a profile report.
#
-# Syntax: profile.pl [OPTIONS] bytecodefile <arguments>
+# Syntax: profile.pl [OPTIONS] bitcodefile <arguments>
#
# OPTIONS may include one or more of the following:
# -block - Enable basicblock profiling
@@ -56,7 +56,7 @@
$LLVMProfOpts .= " " . $_;
}
-die "Must specify LLVM bytecode file as first argument!" if (@ARGV == 0);
+die "Must specify LLVM bitcode file as first argument!" if (@ARGV == 0);
my $BytecodeFile = $ARGV[0];
@@ -65,7 +65,7 @@
my $libdir = `llvm-config --libdir`;
chomp $libdir;
-my $LibProfPath = $libdir . "/profile_rt.so";
+my $LibProfPath = $libdir . "/libprofile_rt.so";
system "opt -q -f $ProfilePass $BytecodeFile -o $BytecodeFile.inst";
system "lli -fake-argv0 '$BytecodeFile' -load $LibProfPath " .
diff --git a/src/LLVM/utils/release/findRegressions.py b/src/LLVM/utils/release/findRegressions.py
new file mode 100644
index 0000000..7629c8b
--- /dev/null
+++ b/src/LLVM/utils/release/findRegressions.py
@@ -0,0 +1,123 @@
+#!/usr/bin/python
+import re, string, sys, os, time, math
+
+DEBUG = 0
+
+(tp, exp) = ('compile', 'exec')
+
+def parse(file):
+ f = open(file, 'r')
+ d = f.read()
+
+ # Cleanup weird stuff
+ d = re.sub(r',\d+:\d', '', d)
+
+ r = re.findall(r'TEST-(PASS|FAIL|RESULT.*?):\s+(.*?)\s+(.*?)\r*\n', d)
+
+ test = {}
+ fname = ''
+ for t in r:
+ if DEBUG:
+ print t
+
+ if t[0] == 'PASS' or t[0] == 'FAIL' :
+ tmp = t[2].split('llvm-test/')
+
+ if DEBUG:
+ print tmp
+
+ if len(tmp) == 2:
+ fname = tmp[1].strip('\r\n')
+ else:
+ fname = tmp[0].strip('\r\n')
+
+ if not test.has_key(fname):
+ test[fname] = {}
+
+ test[fname][t[1] + ' state'] = t[0]
+ test[fname][t[1] + ' time'] = float('nan')
+ else :
+ try:
+ n = t[0].split('RESULT-')[1]
+
+ if DEBUG:
+ print "n == ", n;
+
+ if n == 'compile-success':
+ test[fname]['compile time'] = float(t[2].split('program')[1].strip('\r\n'))
+
+ elif n == 'exec-success':
+ test[fname]['exec time'] = float(t[2].split('program')[1].strip('\r\n'))
+ if DEBUG:
+ print test[fname][string.replace(n, '-success', '')]
+
+ else :
+ # print "ERROR!"
+ sys.exit(1)
+
+ except:
+ continue
+
+ return test
+
+# Diff results and look for regressions.
+def diffResults(d_old, d_new):
+
+ for t in sorted(d_old.keys()) :
+ if d_new.has_key(t):
+
+ # Check if the test passed or failed.
+ for x in ['compile state', 'compile time', 'exec state', 'exec time']:
+
+ if not d_old[t].has_key(x) and not d_new[t].has_key(x):
+ continue
+
+ if d_old[t].has_key(x):
+ if d_new[t].has_key(x):
+
+ if d_old[t][x] == 'PASS':
+ if d_new[t][x] != 'PASS':
+ print t + " *** REGRESSION (" + x + " now fails)"
+ else:
+ if d_new[t][x] == 'PASS':
+ print t + " * NEW PASS (" + x + " now fails)"
+
+ else :
+ print t + "*** REGRESSION (" + x + " now fails)"
+
+ if x == 'compile state' or x == 'exec state':
+ continue
+
+ # For execution time, if there is no result it's a fail.
+ if not d_old[t].has_key(x) and not d_new[t].has_key(x):
+ continue
+ elif not d_new[t].has_key(x):
+ print t + " *** REGRESSION (" + x + ")"
+ elif not d_old[t].has_key(x):
+ print t + " * NEW PASS (" + x + ")"
+
+ if math.isnan(d_old[t][x]) and math.isnan(d_new[t][x]):
+ continue
+
+ elif math.isnan(d_old[t][x]) and not math.isnan(d_new[t][x]):
+ print t + " * NEW PASS (" + x + ")"
+
+ elif not math.isnan(d_old[t][x]) and math.isnan(d_new[t][x]):
+ print t + " *** REGRESSION (" + x + ")"
+
+ if d_new[t][x] > d_old[t][x] and \
+ (d_new[t][x] - d_old[t][x]) / d_new[t][x] > .05:
+ print t + " *** REGRESSION (" + x + ")"
+
+ else :
+ print t + ": Removed from test-suite."
+
+# Main
+if len(sys.argv) < 3 :
+ print 'Usage:', sys.argv[0], '<old log> <new log>'
+ sys.exit(-1)
+
+d_old = parse(sys.argv[1])
+d_new = parse(sys.argv[2])
+
+diffResults(d_old, d_new)
diff --git a/src/LLVM/utils/release/test-release.sh b/src/LLVM/utils/release/test-release.sh
new file mode 100644
index 0000000..94217e5
--- /dev/null
+++ b/src/LLVM/utils/release/test-release.sh
@@ -0,0 +1,364 @@
+#!/usr/bin/env bash
+#===-- test-release.sh - Test the LLVM release candidates ------------------===#
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License.
+#
+#===------------------------------------------------------------------------===#
+#
+# Download, build, and test the release candidate for an LLVM release.
+#
+#===------------------------------------------------------------------------===#
+
+if [ `uname -s` = "FreeBSD" ]; then
+ MAKE=gmake
+else
+ MAKE=make
+fi
+
+projects="llvm cfe dragonegg test-suite"
+
+# Base SVN URL for the sources.
+Base_url="http://llvm.org/svn/llvm-project"
+
+Release=""
+Release_no_dot=""
+RC=""
+do_checkout="yes"
+do_ada="no"
+do_objc="yes"
+do_fortran="no"
+do_64bit="yes"
+do_debug="no"
+do_asserts="no"
+BuildDir="`pwd`"
+
+function usage() {
+ echo "usage: `basename $0` -release X.Y -rc NUM [OPTIONS]"
+ echo ""
+ echo " -release X.Y The release number to test."
+ echo " -rc NUM The pre-release candidate number."
+ echo " -j NUM Number of compile jobs to run. [default: 3]"
+ echo " -build-dir DIR Directory to perform testing in. [default: pwd]"
+ echo " -no-checkout Don't checkout the sources from SVN."
+ echo " -no-64bit Don't test the 64-bit version. [default: yes]"
+ echo " -enable-ada Build Ada. [default: disable]"
+ echo " -enable-fortran Enable Fortran build. [default: disable]"
+ echo " -disable-objc Disable ObjC build. [default: enable]"
+ echo " -test-debug Test the debug build. [default: no]"
+ echo " -test-asserts Test with asserts on. [default: no]"
+}
+
+while [ $# -gt 0 ]; do
+ case $1 in
+ -release | --release )
+ shift
+ Release="$1"
+ Release_no_dot="`echo $1 | sed -e 's,\.,,'`"
+ ;;
+ -rc | --rc | -RC | --RC )
+ shift
+ RC=$1
+ ;;
+ -j* )
+ NumJobs="`echo $1 | sed -e 's,-j\([0-9]*\),\1,g'`"
+ if [ -z "$NumJobs" ]; then
+ shift
+ NumJobs="$1"
+ fi
+ ;;
+ -build-dir | --build-dir | -builddir | --builddir )
+ shift
+ BuildDir="$1"
+ ;;
+ -no-checkout | --no-checkout )
+ do_checkout="no"
+ ;;
+ -no-64bit | --no-64bit )
+ do_64bit="no"
+ ;;
+ -enable-ada | --enable-ada )
+ do_ada="yes"
+ ;;
+ -enable-fortran | --enable-fortran )
+ do_fortran="yes"
+ ;;
+ -disable-objc | --disable-objc )
+ do_objc="no"
+ ;;
+ -test-debug | --test-debug )
+ do_debug="yes"
+ ;;
+ -test-asserts | --test-asserts )
+ do_asserts="yes"
+ ;;
+ -help | --help | -h | --h | -\? )
+ usage
+ exit 0
+ ;;
+ * )
+ echo "unknown option: $1"
+ usage
+ exit 1
+ ;;
+ esac
+ shift
+done
+
+# Check required arguments.
+if [ -z "$Release" ]; then
+ echo "error: no release number specified"
+ exit 1
+fi
+if [ -z "$RC" ]; then
+ echo "error: no release candidate number specified"
+ exit 1
+fi
+
+# Figure out how many make processes to run.
+if [ -z "$NumJobs" ]; then
+ NumJobs=`sysctl -n hw.activecpu 2> /dev/null || true`
+fi
+if [ -z "$NumJobs" ]; then
+ NumJobs=`sysctl -n hw.ncpu 2> /dev/null || true`
+fi
+if [ -z "$NumJobs" ]; then
+ NumJobs=`grep -c processor /proc/cpuinfo 2> /dev/null || true`
+fi
+if [ -z "$NumJobs" ]; then
+ NumJobs=3
+fi
+
+# Go to the build directory (may be different from CWD)
+BuildDir=$BuildDir/rc$RC
+mkdir -p $BuildDir
+cd $BuildDir
+
+# Location of log files.
+LogDir=$BuildDir/logs
+mkdir -p $LogDir
+
+# Find a compilers.
+c_compiler="$CC"
+cxx_compiler="$CXX"
+
+# Make sure that the URLs are valid.
+function check_valid_urls() {
+ for proj in $projects ; do
+ echo "# Validating $proj SVN URL"
+
+ if ! svn ls $Base_url/$proj/tags/RELEASE_$Release_no_dot/rc$RC > /dev/null 2>&1 ; then
+ echo "llvm $Release release candidate $RC doesn't exist!"
+ exit 1
+ fi
+ done
+}
+
+# Export sources to the the build directory.
+function export_sources() {
+ check_valid_urls
+
+ for proj in $projects ; do
+ echo "# Exporting $proj $Release-RC$RC sources"
+ if ! svn export -q $Base_url/$proj/tags/RELEASE_$Release_no_dot/rc$RC $proj.src ; then
+ echo "error: failed to export $proj project"
+ exit 1
+ fi
+ done
+
+ echo "# Creating symlinks"
+ cd $BuildDir/llvm.src/tools
+ if [ ! -h clang ]; then
+ ln -s ../../cfe.src clang
+ fi
+ cd $BuildDir/llvm.src/projects
+ if [ ! -h llvm-test ]; then
+ ln -s ../../test-suite.src llvm-test
+ fi
+ cd $BuildDir
+}
+
+function configure_llvmCore() {
+ Phase="$1"
+ Flavor="$2"
+ ObjDir="$3"
+ InstallDir="$4"
+
+ case $Flavor in
+ Release | Release-64 )
+ Optimized="yes"
+ Assertions="no"
+ ;;
+ Release+Asserts )
+ Optimized="yes"
+ Assertions="yes"
+ ;;
+ Debug )
+ Optimized="no"
+ Assertions="yes"
+ ;;
+ * )
+ echo "# Invalid flavor '$Flavor'"
+ echo ""
+ return
+ ;;
+ esac
+
+ echo "# Using C compiler: $c_compiler"
+ echo "# Using C++ compiler: $cxx_compiler"
+
+ cd $ObjDir
+ echo "# Configuring llvm $Release-rc$RC $Flavor"
+ echo "# $BuildDir/llvm.src/configure --prefix=$InstallDir \
+ --enable-optimized=$Optimized \
+ --enable-assertions=$Assertions"
+ env CC=$c_compiler CXX=$cxx_compiler \
+ $BuildDir/llvm.src/configure --prefix=$InstallDir \
+ --enable-optimized=$Optimized \
+ --enable-assertions=$Assertions \
+ 2>&1 | tee $LogDir/llvm.configure-Phase$Phase-$Flavor.log
+ cd $BuildDir
+}
+
+function build_llvmCore() {
+ Phase="$1"
+ Flavor="$2"
+ ObjDir="$3"
+ ExtraOpts=""
+
+ if [ "$Flavor" = "Release-64" ]; then
+ ExtraOpts="EXTRA_OPTIONS=-m64"
+ fi
+
+ cd $ObjDir
+ echo "# Compiling llvm $Release-rc$RC $Flavor"
+ echo "# ${MAKE} -j $NumJobs VERBOSE=1 $ExtraOpts"
+ ${MAKE} -j $NumJobs VERBOSE=1 $ExtraOpts \
+ 2>&1 | tee $LogDir/llvm.make-Phase$Phase-$Flavor.log
+
+ echo "# Installing llvm $Release-rc$RC $Flavor"
+ echo "# ${MAKE} install"
+ ${MAKE} install \
+ 2>&1 | tee $LogDir/llvm.install-Phase$Phase-$Flavor.log
+ cd $BuildDir
+}
+
+function test_llvmCore() {
+ Phase="$1"
+ Flavor="$2"
+ ObjDir="$3"
+
+ cd $ObjDir
+ ${MAKE} -k check-all \
+ 2>&1 | tee $LogDir/llvm.check-Phase$Phase-$Flavor.log
+ ${MAKE} -k unittests \
+ 2>&1 | tee $LogDir/llvm.unittests-Phase$Phase-$Flavor.log
+ cd $BuildDir
+}
+
+set -e # Exit if any command fails
+
+if [ "$do_checkout" = "yes" ]; then
+ export_sources
+fi
+
+(
+Flavors="Release"
+if [ "$do_debug" = "yes" ]; then
+ Flavors="Debug $Flavors"
+fi
+if [ "$do_asserts" = "yes" ]; then
+ Flavors="$Flavors Release+Asserts"
+fi
+if [ "$do_64bit" = "yes" ]; then
+ Flavors="$Flavors Release-64"
+fi
+
+for Flavor in $Flavors ; do
+ echo ""
+ echo ""
+ echo "********************************************************************************"
+ echo " Release: $Release-rc$RC"
+ echo " Build: $Flavor"
+ echo " System Info: "
+ echo " `uname -a`"
+ echo "********************************************************************************"
+ echo ""
+
+ llvmCore_phase1_objdir=$BuildDir/Phase1/$Flavor/llvmCore-$Release-rc$RC.obj
+ llvmCore_phase1_installdir=$BuildDir/Phase1/$Flavor/llvmCore-$Release-rc$RC.install
+
+ llvmCore_phase2_objdir=$BuildDir/Phase2/$Flavor/llvmCore-$Release-rc$RC.obj
+ llvmCore_phase2_installdir=$BuildDir/Phase2/$Flavor/llvmCore-$Release-rc$RC.install
+
+ llvmCore_phase3_objdir=$BuildDir/Phase3/$Flavor/llvmCore-$Release-rc$RC.obj
+ llvmCore_phase3_installdir=$BuildDir/Phase3/$Flavor/llvmCore-$Release-rc$RC.install
+
+ rm -rf $llvmCore_phase1_objdir
+ rm -rf $llvmCore_phase1_installdir
+ rm -rf $llvmCore_phase2_objdir
+ rm -rf $llvmCore_phase2_installdir
+ rm -rf $llvmCore_phase3_objdir
+ rm -rf $llvmCore_phase3_installdir
+
+ mkdir -p $llvmCore_phase1_objdir
+ mkdir -p $llvmCore_phase1_installdir
+ mkdir -p $llvmCore_phase2_objdir
+ mkdir -p $llvmCore_phase2_installdir
+ mkdir -p $llvmCore_phase3_objdir
+ mkdir -p $llvmCore_phase3_installdir
+
+ ############################################################################
+ # Phase 1: Build llvmCore and llvmgcc42
+ echo "# Phase 1: Building llvmCore"
+ configure_llvmCore 1 $Flavor \
+ $llvmCore_phase1_objdir $llvmCore_phase1_installdir
+ build_llvmCore 1 $Flavor \
+ $llvmCore_phase1_objdir
+
+ ############################################################################
+ # Phase 2: Build llvmCore with newly built clang from phase 1.
+ c_compiler=$llvmCore_phase1_installdir/bin/clang
+ cxx_compiler=$llvmCore_phase1_installdir/bin/clang++
+ echo "# Phase 2: Building llvmCore"
+ configure_llvmCore 2 $Flavor \
+ $llvmCore_phase2_objdir $llvmCore_phase2_installdir
+ build_llvmCore 2 $Flavor \
+ $llvmCore_phase2_objdir
+
+ ############################################################################
+ # Phase 3: Build llvmCore with newly built clang from phase 2.
+ c_compiler=$llvmCore_phase2_installdir/bin/clang
+ cxx_compiler=$llvmCore_phase2_installdir/bin/clang++
+ echo "# Phase 3: Building llvmCore"
+ configure_llvmCore 3 $Flavor \
+ $llvmCore_phase3_objdir $llvmCore_phase3_installdir
+ build_llvmCore 3 $Flavor \
+ $llvmCore_phase3_objdir
+
+ ############################################################################
+ # Testing: Test phase 3
+ echo "# Testing - built with clang"
+ test_llvmCore 3 $Flavor $llvmCore_phase3_objdir
+
+ ############################################################################
+ # Compare .o files between Phase2 and Phase3 and report which ones differ.
+ echo
+ echo "# Comparing Phase 2 and Phase 3 files"
+ for o in `find $llvmCore_phase2_objdir -name '*.o'` ; do
+ p3=`echo $o | sed -e 's,Phase2,Phase3,'`
+ if ! cmp --ignore-initial=16 $o $p3 > /dev/null 2>&1 ; then
+ echo "file `basename $o` differs between phase 2 and phase 3"
+ fi
+ done
+done
+) 2>&1 | tee $LogDir/testing.$Release-rc$RC.log
+
+set +e
+
+# Woo hoo!
+echo "### Testing Finished ###"
+echo "### Logs: $LogDir"
+exit 0
diff --git a/src/LLVM/utils/show-diagnostics b/src/LLVM/utils/show-diagnostics
new file mode 100644
index 0000000..3a69793
--- /dev/null
+++ b/src/LLVM/utils/show-diagnostics
@@ -0,0 +1,52 @@
+#!/usr/bin/env python
+
+import plistlib
+
+def main():
+ from optparse import OptionParser, OptionGroup
+ parser = OptionParser("""\
+usage: %prog [options] <path>
+
+Utility for dumping Clang-style logged diagnostics.\
+""")
+ (opts, args) = parser.parse_args()
+
+ if len(args) != 1:
+ parser.error("invalid number of arguments")
+
+ path, = args
+
+ # Read the diagnostics log.
+ f = open(path)
+ try:
+ data = f.read()
+ finally:
+ f.close()
+
+ # Complete the plist (the log itself is just the chunks).
+ data = """\
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" \
+ "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<array>
+%s
+</array>
+</plist>""" % data
+
+ # Load the diagnostics.
+ diags = plistlib.readPlistFromString(data)
+
+ # Print out the diagnostics.
+ print
+ print "**** BUILD DIAGNOSTICS ****"
+ for i, file_diags in enumerate(diags):
+ file = file_diags.get('main-file')
+ print "*** %s ***" % file
+ for d in file_diags.get('diagnostics', ()):
+ print "%s:%s:%s: %s: %s" % (
+ d.get('filename'), d.get('line'), d.get('column'),
+ d.get('level'), d.get('message'))
+
+if __name__ == "__main__":
+ main()
diff --git a/src/LLVM/utils/test_debuginfo.pl b/src/LLVM/utils/test_debuginfo.pl
new file mode 100644
index 0000000..fb61fb0
--- /dev/null
+++ b/src/LLVM/utils/test_debuginfo.pl
@@ -0,0 +1,61 @@
+#!/usr/bin/perl
+#
+# This script tests debugging information generated by a compiler.
+# Input arguments
+# - Input source program. Usually this source file is decorated using
+# special comments to communicate debugger commands.
+# - Executable file. This file is generated by the compiler.
+#
+# This perl script extracts debugger commands from input source program
+# comments in a script. A debugger is used to load the executable file
+# and run the script generated from source program comments. Finally,
+# the debugger output is checked, using FileCheck, to validate
+# debugging information.
+
+use File::Basename;
+
+my $testcase_file = $ARGV[0];
+my $executable_file = $ARGV[1];
+
+my $input_filename = basename $testcase_file;
+my $output_dir = dirname $executable_file;
+
+my $debugger_script_file = "$output_dir/$input_filename.debugger.script";
+my $output_file = "$output_dir/$input_filename.gdb.output";
+
+# Extract debugger commands from testcase. They are marked with DEBUGGER:
+# at the beginnign of a comment line.
+open(INPUT, $testcase_file);
+open(OUTPUT, ">$debugger_script_file");
+while(<INPUT>) {
+ my($line) = $_;
+ $i = index($line, "DEBUGGER:");
+ if ( $i >= 0) {
+ $l = length("DEBUGGER:");
+ $s = substr($line, $i + $l);
+ print OUTPUT "$s";
+ }
+}
+print OUTPUT "\n";
+print OUTPUT "quit\n";
+close(INPUT);
+close(OUTPUT);
+
+# setup debugger and debugger options to run a script.
+my $my_debugger = $ENV{'DEBUGGER'};
+if (!$my_debugger) {
+ $my_debugger = "gdb";
+}
+my $debugger_options = "-q -batch -n -x";
+
+# run debugger and capture output.
+system("$my_debugger $debugger_options $debugger_script_file $executable_file >& $output_file");
+
+# validate output.
+system("FileCheck", "-input-file", "$output_file", "$testcase_file");
+if ($?>>8 == 1) {
+ exit 1;
+}
+else {
+ exit 0;
+}
diff --git a/src/LLVM/utils/unittest/UnitTestMain/Makefile b/src/LLVM/utils/unittest/UnitTestMain/Makefile
index cec654f..3082779 100644
--- a/src/LLVM/utils/unittest/UnitTestMain/Makefile
+++ b/src/LLVM/utils/unittest/UnitTestMain/Makefile
@@ -27,4 +27,6 @@
CPP.Flags += -DGTEST_HAS_PTHREAD=0
endif
+NO_INSTALL = 1
+
include $(LEVEL)/Makefile.common
diff --git a/src/LLVM/utils/unittest/UnitTestMain/TestMain.cpp b/src/LLVM/utils/unittest/UnitTestMain/TestMain.cpp
index d97dca8..b35bae5 100644
--- a/src/LLVM/utils/unittest/UnitTestMain/TestMain.cpp
+++ b/src/LLVM/utils/unittest/UnitTestMain/TestMain.cpp
@@ -7,9 +7,36 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/Config/config.h"
+#include "llvm/Support/Signals.h"
#include "gtest/gtest.h"
+
+#if defined(LLVM_ON_WIN32)
+# include <windows.h>
+# if defined(_MSC_VER)
+# include <crtdbg.h>
+# endif
+#endif
+
int main(int argc, char **argv) {
+ llvm::sys::PrintStackTraceOnErrorSignal();
testing::InitGoogleTest(&argc, argv);
+
+# if defined(LLVM_ON_WIN32)
+ // Disable all of the possible ways Windows conspires to make automated
+ // testing impossible.
+ ::SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
+# if defined(_MSC_VER)
+ ::_set_error_mode(_OUT_TO_STDERR);
+ _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+ _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
+ _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+ _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
+ _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
+ _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
+# endif
+# endif
+
return RUN_ALL_TESTS();
}
diff --git a/src/LLVM/utils/unittest/googletest/README.LLVM b/src/LLVM/utils/unittest/googletest/README.LLVM
index d6e6f98..51340e9 100644
--- a/src/LLVM/utils/unittest/googletest/README.LLVM
+++ b/src/LLVM/utils/unittest/googletest/README.LLVM
@@ -1,14 +1,14 @@
LLVM notes
----------
-This directory contains Google Test 1.5.0, with all elements removed except for
+This directory contains Google Test 1.6.0, with all elements removed except for
the actual source code, to minimize the addition to the LLVM distribution.
Cleaned up as follows:
# Remove all the unnecessary files and directories
$ rm -f aclocal* CMakeLists.txt configure* Makefile* CHANGES CONTRIBUTORS README
-$ rm -rf build-aux codegear fused-src m4 make msvc samples scripts test xcode
+$ rm -rf build-aux cmake codegear fused-src m4 make msvc samples scripts test xcode
$ rm -f `find . -name \*\.pump`
# Move all the source files to the current directory
@@ -21,6 +21,8 @@
# Update paths to the included files
$ perl -pi -e 's|^#include "src/|#include "gtest/internal/|' *.cc
+$ rm -f gtest-all.cc gtest_main.cc
+
$ mv COPYING LICENSE.TXT
diff --git a/src/LLVM/utils/unittest/googletest/gtest-death-test.cc b/src/LLVM/utils/unittest/googletest/gtest-death-test.cc
index e4199de..6589385 100644
--- a/src/LLVM/utils/unittest/googletest/gtest-death-test.cc
+++ b/src/LLVM/utils/unittest/googletest/gtest-death-test.cc
@@ -31,31 +31,31 @@
//
// This file implements death tests.
-#include <gtest/gtest-death-test.h>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/gtest-death-test.h"
+#include "gtest/internal/gtest-port.h"
#if GTEST_HAS_DEATH_TEST
-#if GTEST_OS_MAC
-#include <crt_externs.h>
-#endif // GTEST_OS_MAC
+# if GTEST_OS_MAC
+# include <crt_externs.h>
+# endif // GTEST_OS_MAC
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdarg.h>
+# include <errno.h>
+# include <fcntl.h>
+# include <limits.h>
+# include <stdarg.h>
-#if GTEST_OS_WINDOWS
-#include <windows.h>
-#else
-#include <sys/mman.h>
-#include <sys/wait.h>
-#endif // GTEST_OS_WINDOWS
+# if GTEST_OS_WINDOWS
+# include <windows.h>
+# else
+# include <sys/mman.h>
+# include <sys/wait.h>
+# endif // GTEST_OS_WINDOWS
#endif // GTEST_HAS_DEATH_TEST
-#include <gtest/gtest-message.h>
-#include <gtest/internal/gtest-string.h>
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-string.h"
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
@@ -113,14 +113,18 @@
// ExitedWithCode function-call operator.
bool ExitedWithCode::operator()(int exit_status) const {
-#if GTEST_OS_WINDOWS
+# if GTEST_OS_WINDOWS
+
return exit_status == exit_code_;
-#else
+
+# else
+
return WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == exit_code_;
-#endif // GTEST_OS_WINDOWS
+
+# endif // GTEST_OS_WINDOWS
}
-#if !GTEST_OS_WINDOWS
+# if !GTEST_OS_WINDOWS
// KilledBySignal constructor.
KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
}
@@ -129,7 +133,7 @@
bool KilledBySignal::operator()(int exit_status) const {
return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
}
-#endif // !GTEST_OS_WINDOWS
+# endif // !GTEST_OS_WINDOWS
namespace internal {
@@ -139,20 +143,25 @@
// specified by wait(2).
static String ExitSummary(int exit_code) {
Message m;
-#if GTEST_OS_WINDOWS
+
+# if GTEST_OS_WINDOWS
+
m << "Exited with exit status " << exit_code;
-#else
+
+# else
+
if (WIFEXITED(exit_code)) {
m << "Exited with exit status " << WEXITSTATUS(exit_code);
} else if (WIFSIGNALED(exit_code)) {
m << "Terminated by signal " << WTERMSIG(exit_code);
}
-#ifdef WCOREDUMP
+# ifdef WCOREDUMP
if (WCOREDUMP(exit_code)) {
m << " (core dumped)";
}
-#endif
-#endif // GTEST_OS_WINDOWS
+# endif
+# endif // GTEST_OS_WINDOWS
+
return m.GetString();
}
@@ -162,7 +171,7 @@
return !ExitedWithCode(0)(exit_status);
}
-#if !GTEST_OS_WINDOWS
+# if !GTEST_OS_WINDOWS
// Generates a textual failure message when a death test finds more than
// one thread running, or cannot determine the number of threads, prior
// to executing the given statement. It is the responsibility of the
@@ -177,20 +186,24 @@
msg << "detected " << thread_count << " threads.";
return msg.GetString();
}
-#endif // !GTEST_OS_WINDOWS
+# endif // !GTEST_OS_WINDOWS
// Flag characters for reporting a death test that did not die.
static const char kDeathTestLived = 'L';
static const char kDeathTestReturned = 'R';
+static const char kDeathTestThrew = 'T';
static const char kDeathTestInternalError = 'I';
-// An enumeration describing all of the possible ways that a death test
-// can conclude. DIED means that the process died while executing the
-// test code; LIVED means that process lived beyond the end of the test
-// code; and RETURNED means that the test statement attempted a "return,"
-// which is not allowed. IN_PROGRESS means the test has not yet
-// concluded.
-enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED };
+// An enumeration describing all of the possible ways that a death test can
+// conclude. DIED means that the process died while executing the test
+// code; LIVED means that process lived beyond the end of the test code;
+// RETURNED means that the test statement attempted to execute a return
+// statement, which is not allowed; THREW means that the test statement
+// returned control by throwing an exception. IN_PROGRESS means the test
+// has not yet concluded.
+// TODO(vladl@google.com): Unify names and possibly values for
+// AbortReason, DeathTestOutcome, and flag characters above.
+enum DeathTestOutcome { IN_PROGRESS, DIED, LIVED, RETURNED, THREW };
// Routine for aborting the program which is safe to call from an
// exec-style death test child process, in which case the error
@@ -212,13 +225,13 @@
} else {
fprintf(stderr, "%s", message.c_str());
fflush(stderr);
- abort();
+ posix::Abort();
}
}
// A replacement for CHECK that calls DeathTestAbort if the assertion
// fails.
-#define GTEST_DEATH_TEST_CHECK_(expression) \
+# define GTEST_DEATH_TEST_CHECK_(expression) \
do { \
if (!::testing::internal::IsTrue(expression)) { \
DeathTestAbort(::testing::internal::String::Format( \
@@ -234,7 +247,7 @@
// evaluates the expression as long as it evaluates to -1 and sets
// errno to EINTR. If the expression evaluates to -1 but errno is
// something other than EINTR, DeathTestAbort is called.
-#define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
+# define GTEST_DEATH_TEST_CHECK_SYSCALL_(expression) \
do { \
int gtest_retval; \
do { \
@@ -388,6 +401,9 @@
case kDeathTestReturned:
set_outcome(RETURNED);
break;
+ case kDeathTestThrew:
+ set_outcome(THREW);
+ break;
case kDeathTestLived:
set_outcome(LIVED);
break;
@@ -416,19 +432,46 @@
// it finds any data in our pipe. So, here we write a single flag byte
// to the pipe, then exit.
const char status_ch =
- reason == TEST_DID_NOT_DIE ? kDeathTestLived : kDeathTestReturned;
+ reason == TEST_DID_NOT_DIE ? kDeathTestLived :
+ reason == TEST_THREW_EXCEPTION ? kDeathTestThrew : kDeathTestReturned;
+
GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Write(write_fd(), &status_ch, 1));
- GTEST_DEATH_TEST_CHECK_SYSCALL_(posix::Close(write_fd()));
+ // We are leaking the descriptor here because on some platforms (i.e.,
+ // when built as Windows DLL), destructors of global objects will still
+ // run after calling _exit(). On such systems, write_fd_ will be
+ // indirectly closed from the destructor of UnitTestImpl, causing double
+ // close if it is also closed here. On debug configurations, double close
+ // may assert. As there are no in-process buffers to flush here, we are
+ // relying on the OS to close the descriptor after the process terminates
+ // when the destructors are not run.
_exit(1); // Exits w/o any normal exit hooks (we were supposed to crash)
}
+// Returns an indented copy of stderr output for a death test.
+// This makes distinguishing death test output lines from regular log lines
+// much easier.
+static ::std::string FormatDeathTestOutput(const ::std::string& output) {
+ ::std::string ret;
+ for (size_t at = 0; ; ) {
+ const size_t line_end = output.find('\n', at);
+ ret += "[ DEATH ] ";
+ if (line_end == ::std::string::npos) {
+ ret += output.substr(at);
+ break;
+ }
+ ret += output.substr(at, line_end + 1 - at);
+ at = line_end + 1;
+ }
+ return ret;
+}
+
// Assesses the success or failure of a death test, using both private
// members which have previously been set, and one argument:
//
// Private data members:
// outcome: An enumeration describing how the death test
-// concluded: DIED, LIVED, or RETURNED. The death test fails
-// in the latter two cases.
+// concluded: DIED, LIVED, THREW, or RETURNED. The death test
+// fails in the latter three cases.
// status: The exit status of the child process. On *nix, it is in the
// in the format specified by wait(2). On Windows, this is the
// value supplied to the ExitProcess() API or a numeric code
@@ -457,11 +500,15 @@
switch (outcome()) {
case LIVED:
buffer << " Result: failed to die.\n"
- << " Error msg: " << error_message;
+ << " Error msg:\n" << FormatDeathTestOutput(error_message);
+ break;
+ case THREW:
+ buffer << " Result: threw an exception.\n"
+ << " Error msg:\n" << FormatDeathTestOutput(error_message);
break;
case RETURNED:
buffer << " Result: illegal return in test statement.\n"
- << " Error msg: " << error_message;
+ << " Error msg:\n" << FormatDeathTestOutput(error_message);
break;
case DIED:
if (status_ok) {
@@ -471,11 +518,12 @@
} else {
buffer << " Result: died but not with expected error.\n"
<< " Expected: " << regex()->pattern() << "\n"
- << "Actual msg: " << error_message;
+ << "Actual msg:\n" << FormatDeathTestOutput(error_message);
}
} else {
buffer << " Result: died but not with expected exit code:\n"
- << " " << ExitSummary(status()) << "\n";
+ << " " << ExitSummary(status()) << "\n"
+ << "Actual msg:\n" << FormatDeathTestOutput(error_message);
}
break;
case IN_PROGRESS:
@@ -488,7 +536,7 @@
return success;
}
-#if GTEST_OS_WINDOWS
+# if GTEST_OS_WINDOWS
// WindowsDeathTest implements death tests on Windows. Due to the
// specifics of starting new processes on Windows, death tests there are
// always threadsafe, and Google Test considers the
@@ -519,11 +567,11 @@
//
class WindowsDeathTest : public DeathTestImpl {
public:
- WindowsDeathTest(const char* statement,
- const RE* regex,
+ WindowsDeathTest(const char* a_statement,
+ const RE* a_regex,
const char* file,
int line)
- : DeathTestImpl(statement, regex), file_(file), line_(line) {}
+ : DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {}
// All of these virtual functions are inherited from DeathTest.
virtual int Wait();
@@ -580,12 +628,12 @@
GTEST_DEATH_TEST_CHECK_(
WAIT_OBJECT_0 == ::WaitForSingleObject(child_handle_.Get(),
INFINITE));
- DWORD status;
- GTEST_DEATH_TEST_CHECK_(::GetExitCodeProcess(child_handle_.Get(), &status)
- != FALSE);
+ DWORD status_code;
+ GTEST_DEATH_TEST_CHECK_(
+ ::GetExitCodeProcess(child_handle_.Get(), &status_code) != FALSE);
child_handle_.Reset();
- set_status(static_cast<int>(status));
- return this->status();
+ set_status(static_cast<int>(status_code));
+ return status();
}
// The AssumeRole process for a Windows death test. It creates a child
@@ -684,7 +732,7 @@
set_spawned(true);
return OVERSEE_TEST;
}
-#else // We are not on Windows.
+# else // We are not on Windows.
// ForkingDeathTest provides implementations for most of the abstract
// methods of the DeathTest interface. Only the AssumeRole method is
@@ -832,19 +880,19 @@
int close_fd; // File descriptor to close; the read end of a pipe
};
-#if GTEST_OS_MAC
+# if GTEST_OS_MAC
inline char** GetEnviron() {
// When Google Test is built as a framework on MacOS X, the environ variable
// is unavailable. Apple's documentation (man environ) recommends using
// _NSGetEnviron() instead.
return *_NSGetEnviron();
}
-#else
+# else
// Some POSIX platforms expect you to declare environ. extern "C" makes
// it reside in the global namespace.
extern "C" char** environ;
inline char** GetEnviron() { return environ; }
-#endif // GTEST_OS_MAC
+# endif // GTEST_OS_MAC
// The main function for a threadsafe-style death test child process.
// This function is called in a clone()-ed process and thus must avoid
@@ -884,6 +932,11 @@
// This could be accomplished more elegantly by a single recursive
// function, but we want to guard against the unlikely possibility of
// a smart compiler optimizing the recursion away.
+//
+// GTEST_NO_INLINE_ is required to prevent GCC 4.6 from inlining
+// StackLowerThanAddress into StackGrowsDown, which then doesn't give
+// correct answer.
+bool StackLowerThanAddress(const void* ptr) GTEST_NO_INLINE_;
bool StackLowerThanAddress(const void* ptr) {
int dummy;
return &dummy < ptr;
@@ -901,7 +954,7 @@
ExecDeathTestArgs args = { argv, close_fd };
pid_t child_pid = -1;
-#if GTEST_HAS_CLONE
+# if GTEST_HAS_CLONE
const bool use_fork = GTEST_FLAG(death_test_use_fork);
if (!use_fork) {
@@ -918,9 +971,9 @@
GTEST_DEATH_TEST_CHECK_(munmap(stack, stack_size) != -1);
}
-#else
+# else
const bool use_fork = true;
-#endif // GTEST_HAS_CLONE
+# endif // GTEST_HAS_CLONE
if (use_fork && (child_pid = fork()) == 0) {
ExecDeathTestChildMain(&args);
@@ -981,7 +1034,7 @@
return OVERSEE_TEST;
}
-#endif // !GTEST_OS_WINDOWS
+# endif // !GTEST_OS_WINDOWS
// Creates a concrete DeathTest-derived class that depends on the
// --gtest_death_test_style flag, and sets the pointer pointed to
@@ -1012,18 +1065,23 @@
}
}
-#if GTEST_OS_WINDOWS
+# if GTEST_OS_WINDOWS
+
if (GTEST_FLAG(death_test_style) == "threadsafe" ||
GTEST_FLAG(death_test_style) == "fast") {
*test = new WindowsDeathTest(statement, regex, file, line);
}
-#else
+
+# else
+
if (GTEST_FLAG(death_test_style) == "threadsafe") {
*test = new ExecDeathTest(statement, regex, file, line);
} else if (GTEST_FLAG(death_test_style) == "fast") {
*test = new NoExecDeathTest(statement, regex);
}
-#endif // GTEST_OS_WINDOWS
+
+# endif // GTEST_OS_WINDOWS
+
else { // NOLINT - this is more readable than unbalanced brackets inside #if.
DeathTest::set_last_death_test_message(String::Format(
"Unknown death test style \"%s\" encountered",
@@ -1054,7 +1112,7 @@
dest->swap(parsed);
}
-#if GTEST_OS_WINDOWS
+# if GTEST_OS_WINDOWS
// Recreates the pipe and event handles from the provided parameters,
// signals the event, and returns a file descriptor wrapped around the pipe
// handle. This function is called in the child process only.
@@ -1118,7 +1176,7 @@
return write_fd;
}
-#endif // GTEST_OS_WINDOWS
+# endif // GTEST_OS_WINDOWS
// Returns a newly created InternalRunDeathTestFlag object with fields
// initialized from the GTEST_FLAG(internal_run_death_test) flag if
@@ -1134,7 +1192,8 @@
SplitString(GTEST_FLAG(internal_run_death_test).c_str(), '|', &fields);
int write_fd = -1;
-#if GTEST_OS_WINDOWS
+# if GTEST_OS_WINDOWS
+
unsigned int parent_process_id = 0;
size_t write_handle_as_size_t = 0;
size_t event_handle_as_size_t = 0;
@@ -1152,7 +1211,8 @@
write_fd = GetStatusFileDescriptor(parent_process_id,
write_handle_as_size_t,
event_handle_as_size_t);
-#else
+# else
+
if (fields.size() != 4
|| !ParseNaturalNumber(fields[1], &line)
|| !ParseNaturalNumber(fields[2], &index)
@@ -1161,7 +1221,9 @@
"Bad --gtest_internal_run_death_test flag: %s",
GTEST_FLAG(internal_run_death_test).c_str()));
}
-#endif // GTEST_OS_WINDOWS
+
+# endif // GTEST_OS_WINDOWS
+
return new InternalRunDeathTestFlag(fields[0], line, index, write_fd);
}
diff --git a/src/LLVM/utils/unittest/googletest/gtest-filepath.cc b/src/LLVM/utils/unittest/googletest/gtest-filepath.cc
index c1ef918..bc61009 100644
--- a/src/LLVM/utils/unittest/googletest/gtest-filepath.cc
+++ b/src/LLVM/utils/unittest/googletest/gtest-filepath.cc
@@ -29,35 +29,35 @@
//
// Authors: keith.ray@gmail.com (Keith Ray)
-#include <gtest/internal/gtest-filepath.h>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/internal/gtest-port.h"
#include <stdlib.h>
#if GTEST_OS_WINDOWS_MOBILE
-#include <windows.h>
+# include <windows.h>
#elif GTEST_OS_WINDOWS
-#include <direct.h>
-#include <io.h>
-#elif GTEST_OS_SYMBIAN
-// Symbian OpenC has PATH_MAX in sys/syslimits.h
-#include <sys/syslimits.h>
+# include <direct.h>
+# include <io.h>
+#elif GTEST_OS_SYMBIAN || GTEST_OS_NACL
+// Symbian OpenC and NaCl have PATH_MAX in sys/syslimits.h
+# include <sys/syslimits.h>
#else
-#include <limits.h>
-#include <climits> // Some Linux distributions define PATH_MAX here.
+# include <limits.h>
+# include <climits> // Some Linux distributions define PATH_MAX here.
#endif // GTEST_OS_WINDOWS_MOBILE
#if GTEST_OS_WINDOWS
-#define GTEST_PATH_MAX_ _MAX_PATH
+# define GTEST_PATH_MAX_ _MAX_PATH
#elif defined(PATH_MAX)
-#define GTEST_PATH_MAX_ PATH_MAX
+# define GTEST_PATH_MAX_ PATH_MAX
#elif defined(_XOPEN_PATH_MAX)
-#define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
+# define GTEST_PATH_MAX_ _XOPEN_PATH_MAX
#else
-#define GTEST_PATH_MAX_ _POSIX_PATH_MAX
+# define GTEST_PATH_MAX_ _POSIX_PATH_MAX
#endif // GTEST_OS_WINDOWS
-#include <gtest/internal/gtest-string.h>
+#include "gtest/internal/gtest-string.h"
namespace testing {
namespace internal {
@@ -71,16 +71,16 @@
const char kAlternatePathSeparator = '/';
const char kPathSeparatorString[] = "\\";
const char kAlternatePathSeparatorString[] = "/";
-#if GTEST_OS_WINDOWS_MOBILE
+# if GTEST_OS_WINDOWS_MOBILE
// Windows CE doesn't have a current directory. You should not use
// the current directory in tests on Windows CE, but this at least
// provides a reasonable fallback.
const char kCurrentDirectoryString[] = "\\";
// Windows CE doesn't define INVALID_FILE_ATTRIBUTES
const DWORD kInvalidFileAttributes = 0xffffffff;
-#else
+# else
const char kCurrentDirectoryString[] = ".\\";
-#endif // GTEST_OS_WINDOWS_MOBILE
+# endif // GTEST_OS_WINDOWS_MOBILE
#else
const char kPathSeparator = '/';
const char kPathSeparatorString[] = "/";
@@ -123,7 +123,7 @@
return *this;
}
-// Returns a pointer to the last occurence of a valid path separator in
+// Returns a pointer to the last occurrence of a valid path separator in
// the FilePath. On Windows, for example, both '/' and '\' are valid path
// separators. Returns NULL if no path separator was found.
const char* FilePath::FindLastPathSeparator() const {
diff --git a/src/LLVM/utils/unittest/googletest/gtest-port.cc b/src/LLVM/utils/unittest/googletest/gtest-port.cc
index 5609599..07e5bb3 100644
--- a/src/LLVM/utils/unittest/googletest/gtest-port.cc
+++ b/src/LLVM/utils/unittest/googletest/gtest-port.cc
@@ -29,30 +29,32 @@
//
// Author: wan@google.com (Zhanyong Wan)
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-port.h"
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#if GTEST_OS_WINDOWS_MOBILE
-#include <windows.h> // For TerminateProcess()
+# include <windows.h> // For TerminateProcess()
#elif GTEST_OS_WINDOWS
-#include <io.h>
-#include <sys/stat.h>
+# include <io.h>
+# include <sys/stat.h>
#else
-#include <unistd.h>
+# include <unistd.h>
#endif // GTEST_OS_WINDOWS_MOBILE
#if GTEST_OS_MAC
-#include <mach/mach_init.h>
-#include <mach/task.h>
-#include <mach/vm_map.h>
+# include <mach/mach_init.h>
+# include <mach/task.h>
+# include <mach/vm_map.h>
#endif // GTEST_OS_MAC
-#include <gtest/gtest-spi.h>
-#include <gtest/gtest-message.h>
-#include <gtest/internal/gtest-string.h>
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest-message.h"
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
@@ -180,20 +182,20 @@
// Returns true iff ch belongs to the given classification. Unlike
// similar functions in <ctype.h>, these aren't affected by the
// current locale.
-bool IsDigit(char ch) { return '0' <= ch && ch <= '9'; }
-bool IsPunct(char ch) {
+bool IsAsciiDigit(char ch) { return '0' <= ch && ch <= '9'; }
+bool IsAsciiPunct(char ch) {
return IsInSet(ch, "^-!\"#$%&'()*+,./:;<=>?@[\\]_`{|}~");
}
bool IsRepeat(char ch) { return IsInSet(ch, "?*+"); }
-bool IsWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
-bool IsWordChar(char ch) {
+bool IsAsciiWhiteSpace(char ch) { return IsInSet(ch, " \f\n\r\t\v"); }
+bool IsAsciiWordChar(char ch) {
return ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') ||
('0' <= ch && ch <= '9') || ch == '_';
}
// Returns true iff "\\c" is a supported escape sequence.
bool IsValidEscape(char c) {
- return (IsPunct(c) || IsInSet(c, "dDfnrsStvwW"));
+ return (IsAsciiPunct(c) || IsInSet(c, "dDfnrsStvwW"));
}
// Returns true iff the given atom (specified by escaped and pattern)
@@ -201,19 +203,19 @@
bool AtomMatchesChar(bool escaped, char pattern_char, char ch) {
if (escaped) { // "\\p" where p is pattern_char.
switch (pattern_char) {
- case 'd': return IsDigit(ch);
- case 'D': return !IsDigit(ch);
+ case 'd': return IsAsciiDigit(ch);
+ case 'D': return !IsAsciiDigit(ch);
case 'f': return ch == '\f';
case 'n': return ch == '\n';
case 'r': return ch == '\r';
- case 's': return IsWhiteSpace(ch);
- case 'S': return !IsWhiteSpace(ch);
+ case 's': return IsAsciiWhiteSpace(ch);
+ case 'S': return !IsAsciiWhiteSpace(ch);
case 't': return ch == '\t';
case 'v': return ch == '\v';
- case 'w': return IsWordChar(ch);
- case 'W': return !IsWordChar(ch);
+ case 'w': return IsAsciiWordChar(ch);
+ case 'W': return !IsAsciiWordChar(ch);
}
- return IsPunct(pattern_char) && pattern_char == ch;
+ return IsAsciiPunct(pattern_char) && pattern_char == ch;
}
return (pattern_char == '.' && ch != '\n') || pattern_char == ch;
@@ -422,6 +424,38 @@
#endif // GTEST_USES_POSIX_RE
+const char kUnknownFile[] = "unknown file";
+
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line) {
+ const char* const file_name = file == NULL ? kUnknownFile : file;
+
+ if (line < 0) {
+ return String::Format("%s:", file_name).c_str();
+ }
+#ifdef _MSC_VER
+ return String::Format("%s(%d):", file_name, line).c_str();
+#else
+ return String::Format("%s:%d:", file_name, line).c_str();
+#endif // _MSC_VER
+}
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+// Note that FormatCompilerIndependentFileLocation() does NOT append colon
+// to the file location it produces, unlike FormatFileLocation().
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
+ const char* file, int line) {
+ const char* const file_name = file == NULL ? kUnknownFile : file;
+
+ if (line < 0)
+ return file_name;
+ else
+ return String::Format("%s:%d", file_name, line).c_str();
+}
+
GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
: severity_(severity) {
@@ -444,18 +478,19 @@
// Disable Microsoft deprecation warnings for POSIX functions called from
// this class (creat, dup, dup2, and close)
#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable: 4996)
+# pragma warning(push)
+# pragma warning(disable: 4996)
#endif // _MSC_VER
-#if GTEST_HAS_STREAM_REDIRECTION_
+#if GTEST_HAS_STREAM_REDIRECTION
// Object that captures an output stream (stdout/stderr).
class CapturedStream {
public:
// The ctor redirects the stream to a temporary file.
CapturedStream(int fd) : fd_(fd), uncaptured_fd_(dup(fd)) {
-#if GTEST_OS_WINDOWS
+
+# if GTEST_OS_WINDOWS
char temp_dir_path[MAX_PATH + 1] = { '\0' }; // NOLINT
char temp_file_path[MAX_PATH + 1] = { '\0' }; // NOLINT
@@ -470,14 +505,14 @@
GTEST_CHECK_(captured_fd != -1) << "Unable to open temporary file "
<< temp_file_path;
filename_ = temp_file_path;
-#else
+# else
// There's no guarantee that a test has write access to the
// current directory, so we create the temporary file in the /tmp
// directory instead.
char name_template[] = "/tmp/captured_stream.XXXXXX";
const int captured_fd = mkstemp(name_template);
filename_ = name_template;
-#endif // GTEST_OS_WINDOWS
+# endif // GTEST_OS_WINDOWS
fflush(NULL);
dup2(captured_fd, fd_);
close(captured_fd);
@@ -546,9 +581,9 @@
return content;
}
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif // _MSC_VER
+# ifdef _MSC_VER
+# pragma warning(pop)
+# endif // _MSC_VER
static CapturedStream* g_captured_stderr = NULL;
static CapturedStream* g_captured_stdout = NULL;
@@ -588,7 +623,7 @@
// Stops capturing stderr and returns the captured string.
String GetCapturedStderr() { return GetCapturedStream(&g_captured_stderr); }
-#endif // GTEST_HAS_STREAM_REDIRECTION_
+#endif // GTEST_HAS_STREAM_REDIRECTION
#if GTEST_HAS_DEATH_TEST
@@ -618,7 +653,7 @@
Message env_var;
for (size_t i = 0; i != full_flag.length(); i++) {
- env_var << static_cast<char>(toupper(full_flag.c_str()[i]));
+ env_var << ToUpper(full_flag.c_str()[i]);
}
return env_var.GetString();
diff --git a/src/LLVM/utils/unittest/googletest/gtest-printers.cc b/src/LLVM/utils/unittest/googletest/gtest-printers.cc
new file mode 100644
index 0000000..ed63c7b
--- /dev/null
+++ b/src/LLVM/utils/unittest/googletest/gtest-printers.cc
@@ -0,0 +1,356 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Test - The Google C++ Testing Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+// void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// It uses the << operator when possible, and prints the bytes in the
+// object otherwise. A user can override its behavior for a class
+// type Foo by defining either operator<<(::std::ostream&, const Foo&)
+// or void PrintTo(const Foo&, ::std::ostream*) in the namespace that
+// defines Foo.
+
+#include "gtest/gtest-printers.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <ostream> // NOLINT
+#include <string>
+#include "gtest/internal/gtest-port.h"
+
+namespace testing {
+
+namespace {
+
+using ::std::ostream;
+
+#if GTEST_OS_WINDOWS_MOBILE // Windows CE does not define _snprintf_s.
+# define snprintf _snprintf
+#elif _MSC_VER >= 1400 // VC 8.0 and later deprecate snprintf and _snprintf.
+# define snprintf _snprintf_s
+#elif _MSC_VER
+# define snprintf _snprintf
+#endif // GTEST_OS_WINDOWS_MOBILE
+
+// Prints a segment of bytes in the given object.
+void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
+ size_t count, ostream* os) {
+ char text[5] = "";
+ for (size_t i = 0; i != count; i++) {
+ const size_t j = start + i;
+ if (i != 0) {
+ // Organizes the bytes into groups of 2 for easy parsing by
+ // human.
+ if ((j % 2) == 0)
+ *os << ' ';
+ else
+ *os << '-';
+ }
+ snprintf(text, sizeof(text), "%02X", obj_bytes[j]);
+ *os << text;
+ }
+}
+
+// Prints the bytes in the given value to the given ostream.
+void PrintBytesInObjectToImpl(const unsigned char* obj_bytes, size_t count,
+ ostream* os) {
+ // Tells the user how big the object is.
+ *os << count << "-byte object <";
+
+ const size_t kThreshold = 132;
+ const size_t kChunkSize = 64;
+ // If the object size is bigger than kThreshold, we'll have to omit
+ // some details by printing only the first and the last kChunkSize
+ // bytes.
+ // TODO(wan): let the user control the threshold using a flag.
+ if (count < kThreshold) {
+ PrintByteSegmentInObjectTo(obj_bytes, 0, count, os);
+ } else {
+ PrintByteSegmentInObjectTo(obj_bytes, 0, kChunkSize, os);
+ *os << " ... ";
+ // Rounds up to 2-byte boundary.
+ const size_t resume_pos = (count - kChunkSize + 1)/2*2;
+ PrintByteSegmentInObjectTo(obj_bytes, resume_pos, count - resume_pos, os);
+ }
+ *os << ">";
+}
+
+} // namespace
+
+namespace internal2 {
+
+// Delegates to PrintBytesInObjectToImpl() to print the bytes in the
+// given object. The delegation simplifies the implementation, which
+// uses the << operator and thus is easier done outside of the
+// ::testing::internal namespace, which contains a << operator that
+// sometimes conflicts with the one in STL.
+void PrintBytesInObjectTo(const unsigned char* obj_bytes, size_t count,
+ ostream* os) {
+ PrintBytesInObjectToImpl(obj_bytes, count, os);
+}
+
+} // namespace internal2
+
+namespace internal {
+
+// Depending on the value of a char (or wchar_t), we print it in one
+// of three formats:
+// - as is if it's a printable ASCII (e.g. 'a', '2', ' '),
+// - as a hexidecimal escape sequence (e.g. '\x7F'), or
+// - as a special escape sequence (e.g. '\r', '\n').
+enum CharFormat {
+ kAsIs,
+ kHexEscape,
+ kSpecialEscape
+};
+
+// Returns true if c is a printable ASCII character. We test the
+// value of c directly instead of calling isprint(), which is buggy on
+// Windows Mobile.
+inline bool IsPrintableAscii(wchar_t c) {
+ return 0x20 <= c && c <= 0x7E;
+}
+
+// Prints a wide or narrow char c as a character literal without the
+// quotes, escaping it when necessary; returns how c was formatted.
+// The template argument UnsignedChar is the unsigned version of Char,
+// which is the type of c.
+template <typename UnsignedChar, typename Char>
+static CharFormat PrintAsCharLiteralTo(Char c, ostream* os) {
+ switch (static_cast<wchar_t>(c)) {
+ case L'\0':
+ *os << "\\0";
+ break;
+ case L'\'':
+ *os << "\\'";
+ break;
+ case L'\\':
+ *os << "\\\\";
+ break;
+ case L'\a':
+ *os << "\\a";
+ break;
+ case L'\b':
+ *os << "\\b";
+ break;
+ case L'\f':
+ *os << "\\f";
+ break;
+ case L'\n':
+ *os << "\\n";
+ break;
+ case L'\r':
+ *os << "\\r";
+ break;
+ case L'\t':
+ *os << "\\t";
+ break;
+ case L'\v':
+ *os << "\\v";
+ break;
+ default:
+ if (IsPrintableAscii(c)) {
+ *os << static_cast<char>(c);
+ return kAsIs;
+ } else {
+ *os << String::Format("\\x%X", static_cast<UnsignedChar>(c));
+ return kHexEscape;
+ }
+ }
+ return kSpecialEscape;
+}
+
+// Prints a char c as if it's part of a string literal, escaping it when
+// necessary; returns how c was formatted.
+static CharFormat PrintAsWideStringLiteralTo(wchar_t c, ostream* os) {
+ switch (c) {
+ case L'\'':
+ *os << "'";
+ return kAsIs;
+ case L'"':
+ *os << "\\\"";
+ return kSpecialEscape;
+ default:
+ return PrintAsCharLiteralTo<wchar_t>(c, os);
+ }
+}
+
+// Prints a char c as if it's part of a string literal, escaping it when
+// necessary; returns how c was formatted.
+static CharFormat PrintAsNarrowStringLiteralTo(char c, ostream* os) {
+ return PrintAsWideStringLiteralTo(static_cast<unsigned char>(c), os);
+}
+
+// Prints a wide or narrow character c and its code. '\0' is printed
+// as "'\\0'", other unprintable characters are also properly escaped
+// using the standard C++ escape sequence. The template argument
+// UnsignedChar is the unsigned version of Char, which is the type of c.
+template <typename UnsignedChar, typename Char>
+void PrintCharAndCodeTo(Char c, ostream* os) {
+ // First, print c as a literal in the most readable form we can find.
+ *os << ((sizeof(c) > 1) ? "L'" : "'");
+ const CharFormat format = PrintAsCharLiteralTo<UnsignedChar>(c, os);
+ *os << "'";
+
+ // To aid user debugging, we also print c's code in decimal, unless
+ // it's 0 (in which case c was printed as '\\0', making the code
+ // obvious).
+ if (c == 0)
+ return;
+ *os << " (" << String::Format("%d", c).c_str();
+
+ // For more convenience, we print c's code again in hexidecimal,
+ // unless c was already printed in the form '\x##' or the code is in
+ // [1, 9].
+ if (format == kHexEscape || (1 <= c && c <= 9)) {
+ // Do nothing.
+ } else {
+ *os << String::Format(", 0x%X",
+ static_cast<UnsignedChar>(c)).c_str();
+ }
+ *os << ")";
+}
+
+void PrintTo(unsigned char c, ::std::ostream* os) {
+ PrintCharAndCodeTo<unsigned char>(c, os);
+}
+void PrintTo(signed char c, ::std::ostream* os) {
+ PrintCharAndCodeTo<unsigned char>(c, os);
+}
+
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its code. L'\0' is printed as "L'\\0'".
+void PrintTo(wchar_t wc, ostream* os) {
+ PrintCharAndCodeTo<wchar_t>(wc, os);
+}
+
+// Prints the given array of characters to the ostream.
+// The array starts at *begin, the length is len, it may include '\0' characters
+// and may not be null-terminated.
+static void PrintCharsAsStringTo(const char* begin, size_t len, ostream* os) {
+ *os << "\"";
+ bool is_previous_hex = false;
+ for (size_t index = 0; index < len; ++index) {
+ const char cur = begin[index];
+ if (is_previous_hex && IsXDigit(cur)) {
+ // Previous character is of '\x..' form and this character can be
+ // interpreted as another hexadecimal digit in its number. Break string to
+ // disambiguate.
+ *os << "\" \"";
+ }
+ is_previous_hex = PrintAsNarrowStringLiteralTo(cur, os) == kHexEscape;
+ }
+ *os << "\"";
+}
+
+// Prints a (const) char array of 'len' elements, starting at address 'begin'.
+void UniversalPrintArray(const char* begin, size_t len, ostream* os) {
+ PrintCharsAsStringTo(begin, len, os);
+}
+
+// Prints the given array of wide characters to the ostream.
+// The array starts at *begin, the length is len, it may include L'\0'
+// characters and may not be null-terminated.
+static void PrintWideCharsAsStringTo(const wchar_t* begin, size_t len,
+ ostream* os) {
+ *os << "L\"";
+ bool is_previous_hex = false;
+ for (size_t index = 0; index < len; ++index) {
+ const wchar_t cur = begin[index];
+ if (is_previous_hex && isascii(cur) && IsXDigit(static_cast<char>(cur))) {
+ // Previous character is of '\x..' form and this character can be
+ // interpreted as another hexadecimal digit in its number. Break string to
+ // disambiguate.
+ *os << "\" L\"";
+ }
+ is_previous_hex = PrintAsWideStringLiteralTo(cur, os) == kHexEscape;
+ }
+ *os << "\"";
+}
+
+// Prints the given C string to the ostream.
+void PrintTo(const char* s, ostream* os) {
+ if (s == NULL) {
+ *os << "NULL";
+ } else {
+ *os << ImplicitCast_<const void*>(s) << " pointing to ";
+ PrintCharsAsStringTo(s, strlen(s), os);
+ }
+}
+
+// MSVC compiler can be configured to define whar_t as a typedef
+// of unsigned short. Defining an overload for const wchar_t* in that case
+// would cause pointers to unsigned shorts be printed as wide strings,
+// possibly accessing more memory than intended and causing invalid
+// memory accesses. MSVC defines _NATIVE_WCHAR_T_DEFINED symbol when
+// wchar_t is implemented as a native type.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Prints the given wide C string to the ostream.
+void PrintTo(const wchar_t* s, ostream* os) {
+ if (s == NULL) {
+ *os << "NULL";
+ } else {
+ *os << ImplicitCast_<const void*>(s) << " pointing to ";
+ PrintWideCharsAsStringTo(s, wcslen(s), os);
+ }
+}
+#endif // wchar_t is native
+
+// Prints a ::string object.
+#if GTEST_HAS_GLOBAL_STRING
+void PrintStringTo(const ::string& s, ostream* os) {
+ PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif // GTEST_HAS_GLOBAL_STRING
+
+void PrintStringTo(const ::std::string& s, ostream* os) {
+ PrintCharsAsStringTo(s.data(), s.size(), os);
+}
+
+// Prints a ::wstring object.
+#if GTEST_HAS_GLOBAL_WSTRING
+void PrintWideStringTo(const ::wstring& s, ostream* os) {
+ PrintWideCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif // GTEST_HAS_GLOBAL_WSTRING
+
+#if GTEST_HAS_STD_WSTRING
+void PrintWideStringTo(const ::std::wstring& s, ostream* os) {
+ PrintWideCharsAsStringTo(s.data(), s.size(), os);
+}
+#endif // GTEST_HAS_STD_WSTRING
+
+} // namespace internal
+
+} // namespace testing
diff --git a/src/LLVM/utils/unittest/googletest/gtest-test-part.cc b/src/LLVM/utils/unittest/googletest/gtest-test-part.cc
index 8249afe..1612780 100644
--- a/src/LLVM/utils/unittest/googletest/gtest-test-part.cc
+++ b/src/LLVM/utils/unittest/googletest/gtest-test-part.cc
@@ -31,7 +31,7 @@
//
// The Google C++ Testing Framework (Google Test)
-#include <gtest/gtest-test-part.h>
+#include "gtest/gtest-test-part.h"
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
diff --git a/src/LLVM/utils/unittest/googletest/gtest-typed-test.cc b/src/LLVM/utils/unittest/googletest/gtest-typed-test.cc
index 3cc4b5d..a5cc88f 100644
--- a/src/LLVM/utils/unittest/googletest/gtest-typed-test.cc
+++ b/src/LLVM/utils/unittest/googletest/gtest-typed-test.cc
@@ -29,8 +29,8 @@
//
// Author: wan@google.com (Zhanyong Wan)
-#include <gtest/gtest-typed-test.h>
-#include <gtest/gtest.h>
+#include "gtest/gtest-typed-test.h"
+#include "gtest/gtest.h"
namespace testing {
namespace internal {
@@ -40,7 +40,7 @@
// Skips to the first non-space char in str. Returns an empty string if str
// contains only whitespace characters.
static const char* SkipSpaces(const char* str) {
- while (isspace(*str))
+ while (IsSpace(*str))
str++;
return str;
}
diff --git a/src/LLVM/utils/unittest/googletest/gtest.cc b/src/LLVM/utils/unittest/googletest/gtest.cc
index aa2d5bb..7624497 100644
--- a/src/LLVM/utils/unittest/googletest/gtest.cc
+++ b/src/LLVM/utils/unittest/googletest/gtest.cc
@@ -31,8 +31,8 @@
//
// The Google C++ Testing Framework (Google Test)
-#include <gtest/gtest.h>
-#include <gtest/gtest-spi.h>
+#include "gtest/gtest.h"
+#include "gtest/gtest-spi.h"
#include <ctype.h>
#include <math.h>
@@ -43,7 +43,7 @@
#include <wctype.h>
#include <algorithm>
-#include <ostream>
+#include <ostream> // NOLINT
#include <sstream>
#include <vector>
@@ -51,72 +51,76 @@
// TODO(kenton@google.com): Use autoconf to detect availability of
// gettimeofday().
-#define GTEST_HAS_GETTIMEOFDAY_ 1
+# define GTEST_HAS_GETTIMEOFDAY_ 1
-#include <fcntl.h>
-#include <limits.h>
-#include <sched.h>
+# include <fcntl.h> // NOLINT
+# include <limits.h> // NOLINT
+# include <sched.h> // NOLINT
// Declares vsnprintf(). This header is not available on Windows.
-#include <strings.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <string>
-#include <vector>
+# include <strings.h> // NOLINT
+# include <sys/mman.h> // NOLINT
+# include <sys/time.h> // NOLINT
+# include <unistd.h> // NOLINT
+# include <string>
#elif GTEST_OS_SYMBIAN
-#define GTEST_HAS_GETTIMEOFDAY_ 1
-#include <sys/time.h> // NOLINT
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h> // NOLINT
#elif GTEST_OS_ZOS
-#define GTEST_HAS_GETTIMEOFDAY_ 1
-#include <sys/time.h> // NOLINT
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h> // NOLINT
// On z/OS we additionally need strings.h for strcasecmp.
-#include <strings.h> // NOLINT
+# include <strings.h> // NOLINT
#elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE.
-#include <windows.h> // NOLINT
+# include <windows.h> // NOLINT
#elif GTEST_OS_WINDOWS // We are on Windows proper.
-#include <io.h> // NOLINT
-#include <sys/timeb.h> // NOLINT
-#include <sys/types.h> // NOLINT
-#include <sys/stat.h> // NOLINT
+# include <io.h> // NOLINT
+# include <sys/timeb.h> // NOLINT
+# include <sys/types.h> // NOLINT
+# include <sys/stat.h> // NOLINT
-#if GTEST_OS_WINDOWS_MINGW
+# if GTEST_OS_WINDOWS_MINGW
// MinGW has gettimeofday() but not _ftime64().
// TODO(kenton@google.com): Use autoconf to detect availability of
// gettimeofday().
// TODO(kenton@google.com): There are other ways to get the time on
// Windows, like GetTickCount() or GetSystemTimeAsFileTime(). MinGW
// supports these. consider using them instead.
-#define GTEST_HAS_GETTIMEOFDAY_ 1
-#include <sys/time.h> // NOLINT
-#endif // GTEST_OS_WINDOWS_MINGW
+# define GTEST_HAS_GETTIMEOFDAY_ 1
+# include <sys/time.h> // NOLINT
+# endif // GTEST_OS_WINDOWS_MINGW
// cpplint thinks that the header is already included, so we want to
// silence it.
-#include <windows.h> // NOLINT
+# include <windows.h> // NOLINT
#else
// Assume other platforms have gettimeofday().
// TODO(kenton@google.com): Use autoconf to detect availability of
// gettimeofday().
-#define GTEST_HAS_GETTIMEOFDAY_ 1
+# define GTEST_HAS_GETTIMEOFDAY_ 1
// cpplint thinks that the header is already included, so we want to
// silence it.
-#include <sys/time.h> // NOLINT
-#include <unistd.h> // NOLINT
+# include <sys/time.h> // NOLINT
+# include <unistd.h> // NOLINT
#endif // GTEST_OS_LINUX
#if GTEST_HAS_EXCEPTIONS
-#include <stdexcept>
+# include <stdexcept>
+#endif
+
+#if GTEST_CAN_STREAM_RESULTS_
+# include <arpa/inet.h> // NOLINT
+# include <netdb.h> // NOLINT
#endif
// Indicates that this translation unit is part of Google Test's
@@ -129,7 +133,7 @@
#undef GTEST_IMPLEMENTATION_
#if GTEST_OS_WINDOWS
-#define vsnprintf _vsnprintf
+# define vsnprintf _vsnprintf
#endif // GTEST_OS_WINDOWS
namespace testing {
@@ -187,7 +191,7 @@
GTEST_DEFINE_bool_(
catch_exceptions,
- internal::BoolFromGTestEnv("catch_exceptions", false),
+ internal::BoolFromGTestEnv("catch_exceptions", true),
"True iff " GTEST_NAME_
" should catch exceptions and treat them as test failures.");
@@ -258,6 +262,13 @@
"The maximum number of stack frames to print when an "
"assertion fails. The valid range is 0 through 100, inclusive.");
+GTEST_DEFINE_string_(
+ stream_result_to,
+ internal::StringFromGTestEnv("stream_result_to", ""),
+ "This flag specifies the host name and the port number on which to stream "
+ "test results. Example: \"localhost:555\". The flag is effective only on "
+ "Linux.");
+
GTEST_DEFINE_bool_(
throw_on_failure,
internal::BoolFromGTestEnv("throw_on_failure", false),
@@ -490,20 +501,33 @@
!MatchesFilter(full_name, negative.c_str()));
}
-#if GTEST_OS_WINDOWS
+#if GTEST_HAS_SEH
// Returns EXCEPTION_EXECUTE_HANDLER if Google Test should handle the
// given SEH exception, or EXCEPTION_CONTINUE_SEARCH otherwise.
// This function is useful as an __except condition.
int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) {
- // Google Test should handle an exception if:
+ // Google Test should handle a SEH exception if:
// 1. the user wants it to, AND
- // 2. this is not a breakpoint exception.
- return (GTEST_FLAG(catch_exceptions) &&
- exception_code != EXCEPTION_BREAKPOINT) ?
- EXCEPTION_EXECUTE_HANDLER :
- EXCEPTION_CONTINUE_SEARCH;
+ // 2. this is not a breakpoint exception, AND
+ // 3. this is not a C++ exception (VC++ implements them via SEH,
+ // apparently).
+ //
+ // SEH exception code for C++ exceptions.
+ // (see http://support.microsoft.com/kb/185294 for more information).
+ const DWORD kCxxExceptionCode = 0xe06d7363;
+
+ bool should_handle = true;
+
+ if (!GTEST_FLAG(catch_exceptions))
+ should_handle = false;
+ else if (exception_code == EXCEPTION_BREAKPOINT)
+ should_handle = false;
+ else if (exception_code == kCxxExceptionCode)
+ should_handle = false;
+
+ return should_handle ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
}
-#endif // GTEST_OS_WINDOWS
+#endif // GTEST_HAS_SEH
} // namespace internal
@@ -583,7 +607,7 @@
const char* /* substr_expr */,
const TestPartResultArray& results,
TestPartResult::Type type,
- const char* substr) {
+ const string& substr) {
const String expected(type == TestPartResult::kFatalFailure ?
"1 fatal failure" :
"1 non-fatal failure");
@@ -594,23 +618,21 @@
for (int i = 0; i < results.size(); i++) {
msg << "\n" << results.GetTestPartResult(i);
}
- return AssertionFailure(msg);
+ return AssertionFailure() << msg;
}
const TestPartResult& r = results.GetTestPartResult(0);
if (r.type() != type) {
- msg << "Expected: " << expected << "\n"
- << " Actual:\n"
- << r;
- return AssertionFailure(msg);
+ return AssertionFailure() << "Expected: " << expected << "\n"
+ << " Actual:\n"
+ << r;
}
- if (strstr(r.message(), substr) == NULL) {
- msg << "Expected: " << expected << " containing \""
- << substr << "\"\n"
- << " Actual:\n"
- << r;
- return AssertionFailure(msg);
+ if (strstr(r.message(), substr.c_str()) == NULL) {
+ return AssertionFailure() << "Expected: " << expected << " containing \""
+ << substr << "\"\n"
+ << " Actual:\n"
+ << r;
}
return AssertionSuccess();
@@ -622,7 +644,7 @@
SingleFailureChecker:: SingleFailureChecker(
const TestPartResultArray* results,
TestPartResult::Type type,
- const char* substr)
+ const string& substr)
: results_(results),
type_(type),
substr_(substr) {}
@@ -632,7 +654,7 @@
// type and contains the given substring. If that's not the case, a
// non-fatal failure will be generated.
SingleFailureChecker::~SingleFailureChecker() {
- EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_.c_str());
+ EXPECT_PRED_FORMAT3(HasOneFailure, *results_, type_, substr_);
}
DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter(
@@ -764,25 +786,30 @@
return 0;
#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_
__timeb64 now;
-#ifdef _MSC_VER
+
+# ifdef _MSC_VER
+
// MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996
// (deprecated function) there.
// TODO(kenton@google.com): Use GetTickCount()? Or use
// SystemTimeToFileTime()
-#pragma warning(push) // Saves the current warning state.
-#pragma warning(disable:4996) // Temporarily disables warning 4996.
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4996) // Temporarily disables warning 4996.
_ftime64(&now);
-#pragma warning(pop) // Restores the warning state.
-#else
+# pragma warning(pop) // Restores the warning state.
+# else
+
_ftime64(&now);
-#endif // _MSC_VER
+
+# endif // _MSC_VER
+
return static_cast<TimeInMillis>(now.time) * 1000 + now.millitm;
#elif GTEST_HAS_GETTIMEOFDAY_
struct timeval now;
gettimeofday(&now, NULL);
return static_cast<TimeInMillis>(now.tv_sec) * 1000 + now.tv_usec / 1000;
#else
-#error "Don't know how to get the current time on your system."
+# error "Don't know how to get the current time on your system."
#endif
}
@@ -918,55 +945,13 @@
}
#endif // GTEST_HAS_GLOBAL_WSTRING
-namespace internal {
-
-// Formats a value to be used in a failure message.
-
-// For a char value, we print it as a C++ char literal and as an
-// unsigned integer (both in decimal and in hexadecimal).
-String FormatForFailureMessage(char ch) {
- const unsigned int ch_as_uint = ch;
- // A String object cannot contain '\0', so we print "\\0" when ch is
- // '\0'.
- return String::Format("'%s' (%u, 0x%X)",
- ch ? String::Format("%c", ch).c_str() : "\\0",
- ch_as_uint, ch_as_uint);
-}
-
-// For a wchar_t value, we print it as a C++ wchar_t literal and as an
-// unsigned integer (both in decimal and in hexidecimal).
-String FormatForFailureMessage(wchar_t wchar) {
- // The C++ standard doesn't specify the exact size of the wchar_t
- // type. It just says that it shall have the same size as another
- // integral type, called its underlying type.
- //
- // Therefore, in order to print a wchar_t value in the numeric form,
- // we first convert it to the largest integral type (UInt64) and
- // then print the converted value.
- //
- // We use streaming to print the value as "%llu" doesn't work
- // correctly with MSVC 7.1.
- const UInt64 wchar_as_uint64 = wchar;
- Message msg;
- // A String object cannot contain '\0', so we print "\\0" when wchar is
- // L'\0'.
- char buffer[32]; // CodePointToUtf8 requires a buffer that big.
- msg << "L'"
- << (wchar ? CodePointToUtf8(static_cast<UInt32>(wchar), buffer) : "\\0")
- << "' (" << wchar_as_uint64 << ", 0x" << ::std::setbase(16)
- << wchar_as_uint64 << ")";
- return msg.GetString();
-}
-
-} // namespace internal
-
// AssertionResult constructors.
// Used in EXPECT_TRUE/FALSE(assertion_result).
AssertionResult::AssertionResult(const AssertionResult& other)
: success_(other.success_),
message_(other.message_.get() != NULL ?
- new internal::String(*other.message_) :
- static_cast<internal::String*>(NULL)) {
+ new ::std::string(*other.message_) :
+ static_cast< ::std::string*>(NULL)) {
}
// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
@@ -1029,7 +1014,7 @@
msg << "\nWhich is: " << expected_value;
}
- return AssertionFailure(msg);
+ return AssertionFailure() << msg;
}
// Constructs a failure message for Boolean assertions such as EXPECT_TRUE.
@@ -1059,13 +1044,12 @@
// TODO(wan): do not print the value of an expression if it's
// already a literal.
- Message msg;
- msg << "The difference between " << expr1 << " and " << expr2
+ return AssertionFailure()
+ << "The difference between " << expr1 << " and " << expr2
<< " is " << diff << ", which exceeds " << abs_error_expr << ", where\n"
<< expr1 << " evaluates to " << val1 << ",\n"
<< expr2 << " evaluates to " << val2 << ", and\n"
<< abs_error_expr << " evaluates to " << abs_error << ".";
- return AssertionFailure(msg);
}
@@ -1090,20 +1074,18 @@
// val2 is NaN, as the IEEE floating-point standard requires that
// any predicate involving a NaN must return false.
- StrStream val1_ss;
+ ::std::stringstream val1_ss;
val1_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
<< val1;
- StrStream val2_ss;
+ ::std::stringstream val2_ss;
val2_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
<< val2;
- Message msg;
- msg << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n"
- << " Actual: " << StrStreamToString(&val1_ss) << " vs "
- << StrStreamToString(&val2_ss);
-
- return AssertionFailure(msg);
+ return AssertionFailure()
+ << "Expected: (" << expr1 << ") <= (" << expr2 << ")\n"
+ << " Actual: " << StringStreamToString(&val1_ss) << " vs "
+ << StringStreamToString(&val2_ss);
}
} // namespace internal
@@ -1150,11 +1132,10 @@
if (val1 op val2) {\
return AssertionSuccess();\
} else {\
- Message msg;\
- msg << "Expected: (" << expr1 << ") " #op " (" << expr2\
+ return AssertionFailure() \
+ << "Expected: (" << expr1 << ") " #op " (" << expr2\
<< "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
<< " vs " << FormatForComparisonFailureMessage(val2, val1);\
- return AssertionFailure(msg);\
}\
}
@@ -1216,11 +1197,9 @@
if (!String::CStringEquals(s1, s2)) {
return AssertionSuccess();
} else {
- Message msg;
- msg << "Expected: (" << s1_expression << ") != ("
- << s2_expression << "), actual: \""
- << s1 << "\" vs \"" << s2 << "\"";
- return AssertionFailure(msg);
+ return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+ << s2_expression << "), actual: \""
+ << s1 << "\" vs \"" << s2 << "\"";
}
}
@@ -1232,11 +1211,10 @@
if (!String::CaseInsensitiveCStringEquals(s1, s2)) {
return AssertionSuccess();
} else {
- Message msg;
- msg << "Expected: (" << s1_expression << ") != ("
+ return AssertionFailure()
+ << "Expected: (" << s1_expression << ") != ("
<< s2_expression << ") (ignoring case), actual: \""
<< s1 << "\" vs \"" << s2 << "\"";
- return AssertionFailure(msg);
}
}
@@ -1285,13 +1263,12 @@
const bool is_wide_string = sizeof(needle[0]) > 1;
const char* const begin_string_quote = is_wide_string ? "L\"" : "\"";
- return AssertionFailure(
- Message()
+ return AssertionFailure()
<< "Value of: " << needle_expr << "\n"
<< " Actual: " << begin_string_quote << needle << "\"\n"
<< "Expected: " << (expected_to_be_substring ? "" : "not ")
<< "a substring of " << haystack_expr << "\n"
- << "Which is: " << begin_string_quote << haystack << "\"");
+ << "Which is: " << begin_string_quote << haystack << "\"";
}
} // namespace
@@ -1360,10 +1337,13 @@
AssertionResult HRESULTFailureHelper(const char* expr,
const char* expected,
long hr) { // NOLINT
-#if GTEST_OS_WINDOWS_MOBILE
+# if GTEST_OS_WINDOWS_MOBILE
+
// Windows CE doesn't support FormatMessage.
const char error_text[] = "";
-#else
+
+# else
+
// Looks up the human-readable system message for the HRESULT code
// and since we're not passing any params to FormatMessage, we don't
// want inserts expanded.
@@ -1380,18 +1360,17 @@
kBufSize, // buf size
NULL); // no arguments for inserts
// Trims tailing white space (FormatMessage leaves a trailing cr-lf)
- for (; message_length && isspace(error_text[message_length - 1]);
+ for (; message_length && IsSpace(error_text[message_length - 1]);
--message_length) {
error_text[message_length - 1] = '\0';
}
-#endif // GTEST_OS_WINDOWS_MOBILE
+
+# endif // GTEST_OS_WINDOWS_MOBILE
const String error_hex(String::Format("0x%08X ", hr));
- Message msg;
- msg << "Expected: " << expr << " " << expected << ".\n"
+ return ::testing::AssertionFailure()
+ << "Expected: " << expr << " " << expected << ".\n"
<< " Actual: " << error_hex << error_text << "\n";
-
- return ::testing::AssertionFailure(msg);
}
} // namespace
@@ -1415,7 +1394,7 @@
// Utility functions for encoding Unicode text (wide strings) in
// UTF-8.
-// A Unicode code-point can have upto 21 bits, and is encoded in UTF-8
+// A Unicode code-point can have up to 21 bits, and is encoded in UTF-8
// like this:
//
// Code-point length Encoding
@@ -1526,7 +1505,7 @@
if (num_chars == -1)
num_chars = static_cast<int>(wcslen(str));
- StrStream stream;
+ ::std::stringstream stream;
for (int i = 0; i < num_chars; ++i) {
UInt32 unicode_code_point;
@@ -1543,7 +1522,7 @@
char buffer[32]; // CodePointToUtf8 requires a buffer this big.
stream << CodePointToUtf8(unicode_code_point, buffer);
}
- return StrStreamToString(&stream);
+ return StringStreamToString(&stream);
}
// Converts a wide C string to a String using the UTF-8 encoding.
@@ -1602,12 +1581,10 @@
return AssertionSuccess();
}
- Message msg;
- msg << "Expected: (" << s1_expression << ") != ("
- << s2_expression << "), actual: "
- << String::ShowWideCStringQuoted(s1)
- << " vs " << String::ShowWideCStringQuoted(s2);
- return AssertionFailure(msg);
+ return AssertionFailure() << "Expected: (" << s1_expression << ") != ("
+ << s2_expression << "), actual: "
+ << String::ShowWideCStringQuoted(s1)
+ << " vs " << String::ShowWideCStringQuoted(s2);
}
// Compares two C strings, ignoring case. Returns true iff they have
@@ -1638,17 +1615,17 @@
// current locale.
bool String::CaseInsensitiveWideCStringEquals(const wchar_t* lhs,
const wchar_t* rhs) {
- if ( lhs == NULL ) return rhs == NULL;
+ if (lhs == NULL) return rhs == NULL;
- if ( rhs == NULL ) return false;
+ if (rhs == NULL) return false;
#if GTEST_OS_WINDOWS
return _wcsicmp(lhs, rhs) == 0;
-#elif GTEST_OS_LINUX
+#elif GTEST_OS_LINUX && !GTEST_OS_LINUX_ANDROID
return wcscasecmp(lhs, rhs) == 0;
#else
- // Mac OS X and Cygwin don't define wcscasecmp. Other unknown OSes
- // may not define it either.
+ // Android, Mac OS X and Cygwin don't define wcscasecmp.
+ // Other unknown OSes may not define it either.
wint_t left, right;
do {
left = towlower(*lhs++);
@@ -1730,10 +1707,12 @@
// MSVC 8 deprecates vsnprintf(), so we want to suppress warning
// 4996 (deprecated function) there.
#ifdef _MSC_VER // We are using MSVC.
-#pragma warning(push) // Saves the current warning state.
-#pragma warning(disable:4996) // Temporarily disables warning 4996.
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4996) // Temporarily disables warning 4996.
+
const int size = vsnprintf(buffer, kBufferSize, format, args);
-#pragma warning(pop) // Restores the warning state.
+
+# pragma warning(pop) // Restores the warning state.
#else // We are not using MSVC.
const int size = vsnprintf(buffer, kBufferSize, format, args);
#endif // _MSC_VER
@@ -1751,16 +1730,16 @@
}
}
-// Converts the buffer in a StrStream to a String, converting NUL
+// Converts the buffer in a stringstream to a String, converting NUL
// bytes to "\\0" along the way.
-String StrStreamToString(StrStream* ss) {
+String StringStreamToString(::std::stringstream* ss) {
const ::std::string& str = ss->str();
const char* const start = str.c_str();
const char* const end = start + str.length();
- // We need to use a helper StrStream to do this transformation
+ // We need to use a helper stringstream to do this transformation
// because String doesn't support push_back().
- StrStream helper;
+ ::std::stringstream helper;
for (const char* ch = start; ch != end; ++ch) {
if (*ch == '\0') {
helper << "\\0"; // Replaces NUL with "\\0";
@@ -1964,22 +1943,6 @@
} // namespace internal
-#if GTEST_OS_WINDOWS
-// We are on Windows.
-
-// Adds an "exception thrown" fatal failure to the current test.
-static void AddExceptionThrownFailure(DWORD exception_code,
- const char* location) {
- Message message;
- message << "Exception thrown with code 0x" << std::setbase(16) <<
- exception_code << std::setbase(10) << " in " << location << ".";
-
- internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,
- message.GetString());
-}
-
-#endif // GTEST_OS_WINDOWS
-
// Google Test requires all tests in the same test case to use the same test
// fixture class. This function checks if the current test has the
// same fixture class as the first test in the current test case. If
@@ -1990,15 +1953,13 @@
const TestCase* const test_case = impl->current_test_case();
// Info about the first test in the current test case.
- const internal::TestInfoImpl* const first_test_info =
- test_case->test_info_list()[0]->impl();
- const internal::TypeId first_fixture_id = first_test_info->fixture_class_id();
+ const TestInfo* const first_test_info = test_case->test_info_list()[0];
+ const internal::TypeId first_fixture_id = first_test_info->fixture_class_id_;
const char* const first_test_name = first_test_info->name();
// Info about the current test.
- const internal::TestInfoImpl* const this_test_info =
- impl->current_test_info()->impl();
- const internal::TypeId this_fixture_id = this_test_info->fixture_class_id();
+ const TestInfo* const this_test_info = impl->current_test_info();
+ const internal::TypeId this_fixture_id = this_test_info->fixture_class_id_;
const char* const this_test_name = this_test_info->name();
if (this_fixture_id != first_fixture_id) {
@@ -2048,62 +2009,167 @@
return true;
}
+#if GTEST_HAS_SEH
+
+// Adds an "exception thrown" fatal failure to the current test. This
+// function returns its result via an output parameter pointer because VC++
+// prohibits creation of objects with destructors on stack in functions
+// using __try (see error C2712).
+static internal::String* FormatSehExceptionMessage(DWORD exception_code,
+ const char* location) {
+ Message message;
+ message << "SEH exception with code 0x" << std::setbase(16) <<
+ exception_code << std::setbase(10) << " thrown in " << location << ".";
+
+ return new internal::String(message.GetString());
+}
+
+#endif // GTEST_HAS_SEH
+
+#if GTEST_HAS_EXCEPTIONS
+
+// Adds an "exception thrown" fatal failure to the current test.
+static internal::String FormatCxxExceptionMessage(const char* description,
+ const char* location) {
+ Message message;
+ if (description != NULL) {
+ message << "C++ exception with description \"" << description << "\"";
+ } else {
+ message << "Unknown C++ exception";
+ }
+ message << " thrown in " << location << ".";
+
+ return message.GetString();
+}
+
+static internal::String PrintTestPartResultToString(
+ const TestPartResult& test_part_result);
+
+// A failed Google Test assertion will throw an exception of this type when
+// GTEST_FLAG(throw_on_failure) is true (if exceptions are enabled). We
+// derive it from std::runtime_error, which is for errors presumably
+// detectable only at run time. Since std::runtime_error inherits from
+// std::exception, many testing frameworks know how to extract and print the
+// message inside it.
+class GoogleTestFailureException : public ::std::runtime_error {
+ public:
+ explicit GoogleTestFailureException(const TestPartResult& failure)
+ : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {}
+};
+#endif // GTEST_HAS_EXCEPTIONS
+
+namespace internal {
+// We put these helper functions in the internal namespace as IBM's xlC
+// compiler rejects the code if they were declared static.
+
+// Runs the given method and handles SEH exceptions it throws, when
+// SEH is supported; returns the 0-value for type Result in case of an
+// SEH exception. (Microsoft compilers cannot handle SEH and C++
+// exceptions in the same function. Therefore, we provide a separate
+// wrapper function for handling SEH exceptions.)
+template <class T, typename Result>
+Result HandleSehExceptionsInMethodIfSupported(
+ T* object, Result (T::*method)(), const char* location) {
+#if GTEST_HAS_SEH
+ __try {
+ return (object->*method)();
+ } __except (internal::UnitTestOptions::GTestShouldProcessSEH( // NOLINT
+ GetExceptionCode())) {
+ // We create the exception message on the heap because VC++ prohibits
+ // creation of objects with destructors on stack in functions using __try
+ // (see error C2712).
+ internal::String* exception_message = FormatSehExceptionMessage(
+ GetExceptionCode(), location);
+ internal::ReportFailureInUnknownLocation(TestPartResult::kFatalFailure,
+ *exception_message);
+ delete exception_message;
+ return static_cast<Result>(0);
+ }
+#else
+ (void)location;
+ return (object->*method)();
+#endif // GTEST_HAS_SEH
+}
+
+// Runs the given method and catches and reports C++ and/or SEH-style
+// exceptions, if they are supported; returns the 0-value for type
+// Result in case of an SEH exception.
+template <class T, typename Result>
+Result HandleExceptionsInMethodIfSupported(
+ T* object, Result (T::*method)(), const char* location) {
+ // NOTE: The user code can affect the way in which Google Test handles
+ // exceptions by setting GTEST_FLAG(catch_exceptions), but only before
+ // RUN_ALL_TESTS() starts. It is technically possible to check the flag
+ // after the exception is caught and either report or re-throw the
+ // exception based on the flag's value:
+ //
+ // try {
+ // // Perform the test method.
+ // } catch (...) {
+ // if (GTEST_FLAG(catch_exceptions))
+ // // Report the exception as failure.
+ // else
+ // throw; // Re-throws the original exception.
+ // }
+ //
+ // However, the purpose of this flag is to allow the program to drop into
+ // the debugger when the exception is thrown. On most platforms, once the
+ // control enters the catch block, the exception origin information is
+ // lost and the debugger will stop the program at the point of the
+ // re-throw in this function -- instead of at the point of the original
+ // throw statement in the code under test. For this reason, we perform
+ // the check early, sacrificing the ability to affect Google Test's
+ // exception handling in the method where the exception is thrown.
+ if (internal::GetUnitTestImpl()->catch_exceptions()) {
+#if GTEST_HAS_EXCEPTIONS
+ try {
+ return HandleSehExceptionsInMethodIfSupported(object, method, location);
+ } catch (const GoogleTestFailureException&) { // NOLINT
+ // This exception doesn't originate in code under test. It makes no
+ // sense to report it as a test failure.
+ throw;
+ } catch (const std::exception& e) { // NOLINT
+ internal::ReportFailureInUnknownLocation(
+ TestPartResult::kFatalFailure,
+ FormatCxxExceptionMessage(e.what(), location));
+ } catch (...) { // NOLINT
+ internal::ReportFailureInUnknownLocation(
+ TestPartResult::kFatalFailure,
+ FormatCxxExceptionMessage(NULL, location));
+ }
+ return static_cast<Result>(0);
+#else
+ return HandleSehExceptionsInMethodIfSupported(object, method, location);
+#endif // GTEST_HAS_EXCEPTIONS
+ } else {
+ return (object->*method)();
+ }
+}
+
+} // namespace internal
+
// Runs the test and updates the test result.
void Test::Run() {
if (!HasSameFixtureClass()) return;
internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
-#if GTEST_HAS_SEH
- // Catch SEH-style exceptions.
impl->os_stack_trace_getter()->UponLeavingGTest();
- __try {
- SetUp();
- } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
- GetExceptionCode())) {
- AddExceptionThrownFailure(GetExceptionCode(), "SetUp()");
- }
-
- // We will run the test only if SetUp() had no fatal failure.
- if (!HasFatalFailure()) {
- impl->os_stack_trace_getter()->UponLeavingGTest();
- __try {
- TestBody();
- } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
- GetExceptionCode())) {
- AddExceptionThrownFailure(GetExceptionCode(), "the test body");
- }
- }
-
- // However, we want to clean up as much as possible. Hence we will
- // always call TearDown(), even if SetUp() or the test body has
- // failed.
- impl->os_stack_trace_getter()->UponLeavingGTest();
- __try {
- TearDown();
- } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
- GetExceptionCode())) {
- AddExceptionThrownFailure(GetExceptionCode(), "TearDown()");
- }
-
-#else // We are on a compiler or platform that doesn't support SEH.
- impl->os_stack_trace_getter()->UponLeavingGTest();
- SetUp();
-
+ internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()");
// We will run the test only if SetUp() was successful.
if (!HasFatalFailure()) {
impl->os_stack_trace_getter()->UponLeavingGTest();
- TestBody();
+ internal::HandleExceptionsInMethodIfSupported(
+ this, &Test::TestBody, "the test body");
}
// However, we want to clean up as much as possible. Hence we will
// always call TearDown(), even if SetUp() or the test body has
// failed.
impl->os_stack_trace_getter()->UponLeavingGTest();
- TearDown();
-#endif // GTEST_HAS_SEH
+ internal::HandleExceptionsInMethodIfSupported(
+ this, &Test::TearDown, "TearDown()");
}
-
// Returns true iff the current test has a fatal failure.
bool Test::HasFatalFailure() {
return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure();
@@ -2118,22 +2184,28 @@
// class TestInfo
// Constructs a TestInfo object. It assumes ownership of the test factory
-// object via impl_.
+// object.
+// TODO(vladl@google.com): Make a_test_case_name and a_name const string&'s
+// to signify they cannot be NULLs.
TestInfo::TestInfo(const char* a_test_case_name,
const char* a_name,
- const char* a_test_case_comment,
- const char* a_comment,
+ const char* a_type_param,
+ const char* a_value_param,
internal::TypeId fixture_class_id,
- internal::TestFactoryBase* factory) {
- impl_ = new internal::TestInfoImpl(this, a_test_case_name, a_name,
- a_test_case_comment, a_comment,
- fixture_class_id, factory);
-}
+ internal::TestFactoryBase* factory)
+ : test_case_name_(a_test_case_name),
+ name_(a_name),
+ type_param_(a_type_param ? new std::string(a_type_param) : NULL),
+ value_param_(a_value_param ? new std::string(a_value_param) : NULL),
+ fixture_class_id_(fixture_class_id),
+ should_run_(false),
+ is_disabled_(false),
+ matches_filter_(false),
+ factory_(factory),
+ result_() {}
// Destructs a TestInfo object.
-TestInfo::~TestInfo() {
- delete impl_;
-}
+TestInfo::~TestInfo() { delete factory_; }
namespace internal {
@@ -2144,10 +2216,10 @@
//
// test_case_name: name of the test case
// name: name of the test
-// test_case_comment: a comment on the test case that will be included in
-// the test output
-// comment: a comment on the test that will be included in the
-// test output
+// type_param: the name of the test's type parameter, or NULL if
+// this is not a typed or a type-parameterized test.
+// value_param: text representation of the test's value parameter,
+// or NULL if this is not a value-parameterized test.
// fixture_class_id: ID of the test fixture class
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
@@ -2156,13 +2228,14 @@
// ownership of the factory object.
TestInfo* MakeAndRegisterTestInfo(
const char* test_case_name, const char* name,
- const char* test_case_comment, const char* comment,
+ const char* type_param,
+ const char* value_param,
TypeId fixture_class_id,
SetUpTestCaseFunc set_up_tc,
TearDownTestCaseFunc tear_down_tc,
TestFactoryBase* factory) {
TestInfo* const test_info =
- new TestInfo(test_case_name, name, test_case_comment, comment,
+ new TestInfo(test_case_name, name, type_param, value_param,
fixture_class_id, factory);
GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
return test_info;
@@ -2189,70 +2262,6 @@
} // namespace internal
-// Returns the test case name.
-const char* TestInfo::test_case_name() const {
- return impl_->test_case_name();
-}
-
-// Returns the test name.
-const char* TestInfo::name() const {
- return impl_->name();
-}
-
-// Returns the test case comment.
-const char* TestInfo::test_case_comment() const {
- return impl_->test_case_comment();
-}
-
-// Returns the test comment.
-const char* TestInfo::comment() const {
- return impl_->comment();
-}
-
-// Returns true if this test should run.
-bool TestInfo::should_run() const { return impl_->should_run(); }
-
-// Returns true if this test matches the user-specified filter.
-bool TestInfo::matches_filter() const { return impl_->matches_filter(); }
-
-// Returns the result of the test.
-const TestResult* TestInfo::result() const { return impl_->result(); }
-
-// Increments the number of death tests encountered in this test so
-// far.
-int TestInfo::increment_death_test_count() {
- return impl_->result()->increment_death_test_count();
-}
-
-namespace {
-
-// A predicate that checks the test name of a TestInfo against a known
-// value.
-//
-// This is used for implementation of the TestCase class only. We put
-// it in the anonymous namespace to prevent polluting the outer
-// namespace.
-//
-// TestNameIs is copyable.
-class TestNameIs {
- public:
- // Constructor.
- //
- // TestNameIs has NO default constructor.
- explicit TestNameIs(const char* name)
- : name_(name) {}
-
- // Returns true iff the test name of test_info matches name_.
- bool operator()(const TestInfo * test_info) const {
- return test_info && internal::String(test_info->name()).Compare(name_) == 0;
- }
-
- private:
- internal::String name_;
-};
-
-} // namespace
-
namespace internal {
// This method expands all parameterized tests registered with macros TEST_P
@@ -2267,70 +2276,54 @@
#endif
}
+} // namespace internal
+
// Creates the test object, runs it, records its result, and then
// deletes it.
-void TestInfoImpl::Run() {
+void TestInfo::Run() {
if (!should_run_) return;
// Tells UnitTest where to store test result.
- UnitTestImpl* const impl = internal::GetUnitTestImpl();
- impl->set_current_test_info(parent_);
+ internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
+ impl->set_current_test_info(this);
TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
// Notifies the unit test event listeners that a test is about to start.
- repeater->OnTestStart(*parent_);
+ repeater->OnTestStart(*this);
- const TimeInMillis start = GetTimeInMillis();
+ const TimeInMillis start = internal::GetTimeInMillis();
impl->os_stack_trace_getter()->UponLeavingGTest();
-#if GTEST_HAS_SEH
- // Catch SEH-style exceptions.
- Test* test = NULL;
-
- __try {
- // Creates the test object.
- test = factory_->CreateTest();
- } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
- GetExceptionCode())) {
- AddExceptionThrownFailure(GetExceptionCode(),
- "the test fixture's constructor");
- return;
- }
-#else // We are on a compiler or platform that doesn't support SEH.
-
- // TODO(wan): If test->Run() throws, test won't be deleted. This is
- // not a problem now as we don't use exceptions. If we were to
- // enable exceptions, we should revise the following to be
- // exception-safe.
// Creates the test object.
- Test* test = factory_->CreateTest();
-#endif // GTEST_HAS_SEH
+ Test* const test = internal::HandleExceptionsInMethodIfSupported(
+ factory_, &internal::TestFactoryBase::CreateTest,
+ "the test fixture's constructor");
- // Runs the test only if the constructor of the test fixture didn't
- // generate a fatal failure.
- if (!Test::HasFatalFailure()) {
+ // Runs the test only if the test object was created and its
+ // constructor didn't generate a fatal failure.
+ if ((test != NULL) && !Test::HasFatalFailure()) {
+ // This doesn't throw as all user code that can throw are wrapped into
+ // exception handling code.
test->Run();
}
// Deletes the test object.
impl->os_stack_trace_getter()->UponLeavingGTest();
- delete test;
- test = NULL;
+ internal::HandleExceptionsInMethodIfSupported(
+ test, &Test::DeleteSelf_, "the test fixture's destructor");
- result_.set_elapsed_time(GetTimeInMillis() - start);
+ result_.set_elapsed_time(internal::GetTimeInMillis() - start);
// Notifies the unit test event listener that a test has just finished.
- repeater->OnTestEnd(*parent_);
+ repeater->OnTestEnd(*this);
// Tells UnitTest to stop associating assertion results to this
// test.
impl->set_current_test_info(NULL);
}
-} // namespace internal
-
// class TestCase
// Gets the number of successful tests in this test case.
@@ -2362,13 +2355,15 @@
// Arguments:
//
// name: name of the test case
+// a_type_param: the name of the test case's type parameter, or NULL if
+// this is not a typed or a type-parameterized test case.
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
-TestCase::TestCase(const char* a_name, const char* a_comment,
+TestCase::TestCase(const char* a_name, const char* a_type_param,
Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc)
: name_(a_name),
- comment_(a_comment),
+ type_param_(a_type_param ? new std::string(a_type_param) : NULL),
set_up_tc_(set_up_tc),
tear_down_tc_(tear_down_tc),
should_run_(false),
@@ -2413,45 +2408,26 @@
repeater->OnTestCaseStart(*this);
impl->os_stack_trace_getter()->UponLeavingGTest();
- set_up_tc_();
+ internal::HandleExceptionsInMethodIfSupported(
+ this, &TestCase::RunSetUpTestCase, "SetUpTestCase()");
const internal::TimeInMillis start = internal::GetTimeInMillis();
for (int i = 0; i < total_test_count(); i++) {
- GetMutableTestInfo(i)->impl()->Run();
+ GetMutableTestInfo(i)->Run();
}
elapsed_time_ = internal::GetTimeInMillis() - start;
impl->os_stack_trace_getter()->UponLeavingGTest();
- tear_down_tc_();
+ internal::HandleExceptionsInMethodIfSupported(
+ this, &TestCase::RunTearDownTestCase, "TearDownTestCase()");
+
repeater->OnTestCaseEnd(*this);
impl->set_current_test_case(NULL);
}
// Clears the results of all tests in this test case.
void TestCase::ClearResult() {
- ForEach(test_info_list_, internal::TestInfoImpl::ClearTestResult);
-}
-
-// Returns true iff test passed.
-bool TestCase::TestPassed(const TestInfo * test_info) {
- const internal::TestInfoImpl* const impl = test_info->impl();
- return impl->should_run() && impl->result()->Passed();
-}
-
-// Returns true iff test failed.
-bool TestCase::TestFailed(const TestInfo * test_info) {
- const internal::TestInfoImpl* const impl = test_info->impl();
- return impl->should_run() && impl->result()->Failed();
-}
-
-// Returns true iff test is disabled.
-bool TestCase::TestDisabled(const TestInfo * test_info) {
- return test_info->impl()->is_disabled();
-}
-
-// Returns true if the given test should run.
-bool TestCase::ShouldRunTest(const TestInfo *test_info) {
- return test_info->impl()->should_run();
+ ForEach(test_info_list_, TestInfo::ClearTestResult);
}
// Shuffles the tests in this test case.
@@ -2504,9 +2480,9 @@
#else
return "Failure\n";
#endif
+ default:
+ return "Unknown result type";
}
-
- return "Unknown result type";
}
// Prints a TestPartResult to a String.
@@ -2592,6 +2568,7 @@
String::CStringEquals(term, "xterm") ||
String::CStringEquals(term, "xterm-color") ||
String::CStringEquals(term, "xterm-256color") ||
+ String::CStringEquals(term, "screen") ||
String::CStringEquals(term, "linux") ||
String::CStringEquals(term, "cygwin");
return stdout_is_tty && term_supports_color;
@@ -2657,6 +2634,23 @@
va_end(args);
}
+void PrintFullTestCommentIfPresent(const TestInfo& test_info) {
+ const char* const type_param = test_info.type_param();
+ const char* const value_param = test_info.value_param();
+
+ if (type_param != NULL || value_param != NULL) {
+ printf(", where ");
+ if (type_param != NULL) {
+ printf("TypeParam = %s", type_param);
+ if (value_param != NULL)
+ printf(" and ");
+ }
+ if (value_param != NULL) {
+ printf("GetParam() = %s", value_param);
+ }
+ }
+}
+
// This class implements the TestEventListener interface.
//
// Class PrettyUnitTestResultPrinter is copyable.
@@ -2704,9 +2698,10 @@
}
if (internal::ShouldShard(kTestTotalShards, kTestShardIndex, false)) {
+ const Int32 shard_index = Int32FromEnvOrDie(kTestShardIndex, -1);
ColoredPrintf(COLOR_YELLOW,
- "Note: This is test shard %s of %s.\n",
- internal::posix::GetEnv(kTestShardIndex),
+ "Note: This is test shard %d of %s.\n",
+ static_cast<int>(shard_index) + 1,
internal::posix::GetEnv(kTestTotalShards));
}
@@ -2736,10 +2731,10 @@
FormatCountableNoun(test_case.test_to_run_count(), "test", "tests");
ColoredPrintf(COLOR_GREEN, "[----------] ");
printf("%s from %s", counts.c_str(), test_case_name_.c_str());
- if (test_case.comment()[0] == '\0') {
+ if (test_case.type_param() == NULL) {
printf("\n");
} else {
- printf(", where %s\n", test_case.comment());
+ printf(", where TypeParam = %s\n", test_case.type_param());
}
fflush(stdout);
}
@@ -2747,11 +2742,7 @@
void PrettyUnitTestResultPrinter::OnTestStart(const TestInfo& test_info) {
ColoredPrintf(COLOR_GREEN, "[ RUN ] ");
PrintTestName(test_case_name_.c_str(), test_info.name());
- if (test_info.comment()[0] == '\0') {
- printf("\n");
- } else {
- printf(", where %s\n", test_info.comment());
- }
+ printf("\n");
fflush(stdout);
}
@@ -2774,6 +2765,9 @@
ColoredPrintf(COLOR_RED, "[ FAILED ] ");
}
PrintTestName(test_case_name_.c_str(), test_info.name());
+ if (test_info.result()->Failed())
+ PrintFullTestCommentIfPresent(test_info);
+
if (GTEST_FLAG(print_time)) {
printf(" (%s ms)\n", internal::StreamableToString(
test_info.result()->elapsed_time()).c_str());
@@ -2822,21 +2816,14 @@
}
ColoredPrintf(COLOR_RED, "[ FAILED ] ");
printf("%s.%s", test_case.name(), test_info.name());
- if (test_case.comment()[0] != '\0' ||
- test_info.comment()[0] != '\0') {
- printf(", where %s", test_case.comment());
- if (test_case.comment()[0] != '\0' &&
- test_info.comment()[0] != '\0') {
- printf(" and ");
- }
- }
- printf("%s\n", test_info.comment());
+ PrintFullTestCommentIfPresent(test_info);
+ printf("\n");
}
}
}
- void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
- int /*iteration*/) {
+void PrettyUnitTestResultPrinter::OnTestIterationEnd(const UnitTest& unit_test,
+ int /*iteration*/) {
ColoredPrintf(COLOR_GREEN, "[==========] ");
printf("%s from %s ran.",
FormatTestCount(unit_test.test_to_run_count()).c_str(),
@@ -3016,7 +3003,7 @@
static String EscapeXml(const char* str, bool is_attribute);
// Returns the given string with all characters invalid in XML removed.
- static String RemoveInvalidXmlCharacters(const char* str);
+ static string RemoveInvalidXmlCharacters(const string& str);
// Convenience wrapper around EscapeXml when str is an attribute value.
static String EscapeXmlAttribute(const char* str) {
@@ -3150,17 +3137,14 @@
// Returns the given string with all characters invalid in XML removed.
// Currently invalid characters are dropped from the string. An
// alternative is to replace them with certain characters such as . or ?.
-String XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(const char* str) {
- char* const output = new char[strlen(str) + 1];
- char* appender = output;
- for (char ch = *str; ch != '\0'; ch = *++str)
- if (IsValidXmlCharacter(ch))
- *appender++ = ch;
- *appender = '\0';
+string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(const string& str) {
+ string output;
+ output.reserve(str.size());
+ for (string::const_iterator it = str.begin(); it != str.end(); ++it)
+ if (IsValidXmlCharacter(*it))
+ output.push_back(*it);
- String ret_value(output);
- delete[] output;
- return ret_value;
+ return output;
}
// The following routines generate an XML representation of a UnitTest
@@ -3213,8 +3197,18 @@
const TestInfo& test_info) {
const TestResult& result = *test_info.result();
*stream << " <testcase name=\""
- << EscapeXmlAttribute(test_info.name()).c_str()
- << "\" status=\""
+ << EscapeXmlAttribute(test_info.name()).c_str() << "\"";
+
+ if (test_info.value_param() != NULL) {
+ *stream << " value_param=\"" << EscapeXmlAttribute(test_info.value_param())
+ << "\"";
+ }
+ if (test_info.type_param() != NULL) {
+ *stream << " type_param=\"" << EscapeXmlAttribute(test_info.type_param())
+ << "\"";
+ }
+
+ *stream << " status=\""
<< (test_info.should_run() ? "run" : "notrun")
<< "\" time=\""
<< FormatTimeInMillisAsSeconds(result.elapsed_time())
@@ -3230,11 +3224,11 @@
*stream << " <failure message=\""
<< EscapeXmlAttribute(part.summary()).c_str()
<< "\" type=\"\">";
- const String message = RemoveInvalidXmlCharacters(String::Format(
- "%s:%d\n%s",
- part.file_name(), part.line_number(),
- part.message()).c_str());
- OutputXmlCDataSection(stream, message.c_str());
+ const string location = internal::FormatCompilerIndependentFileLocation(
+ part.file_name(), part.line_number());
+ const string message = location + "\n" + part.message();
+ OutputXmlCDataSection(stream,
+ RemoveInvalidXmlCharacters(message).c_str());
*stream << "</failure>\n";
}
}
@@ -3259,9 +3253,9 @@
"errors=\"0\" time=\"%s\">\n",
FormatTimeInMillisAsSeconds(test_case.elapsed_time()).c_str());
for (int i = 0; i < test_case.total_test_count(); ++i) {
- StrStream stream;
+ ::std::stringstream stream;
OutputXmlTestInfo(&stream, test_case.name(), *test_case.GetTestInfo(i));
- fprintf(out, "%s", StrStreamToString(&stream).c_str());
+ fprintf(out, "%s", StringStreamToString(&stream).c_str());
}
fprintf(out, " </testsuite>\n");
}
@@ -3301,6 +3295,182 @@
// End XmlUnitTestResultPrinter
+#if GTEST_CAN_STREAM_RESULTS_
+
+// Streams test results to the given port on the given host machine.
+class StreamingListener : public EmptyTestEventListener {
+ public:
+ // Escapes '=', '&', '%', and '\n' characters in str as "%xx".
+ static string UrlEncode(const char* str);
+
+ StreamingListener(const string& host, const string& port)
+ : sockfd_(-1), host_name_(host), port_num_(port) {
+ MakeConnection();
+ Send("gtest_streaming_protocol_version=1.0\n");
+ }
+
+ virtual ~StreamingListener() {
+ if (sockfd_ != -1)
+ CloseConnection();
+ }
+
+ void OnTestProgramStart(const UnitTest& /* unit_test */) {
+ Send("event=TestProgramStart\n");
+ }
+
+ void OnTestProgramEnd(const UnitTest& unit_test) {
+ // Note that Google Test current only report elapsed time for each
+ // test iteration, not for the entire test program.
+ Send(String::Format("event=TestProgramEnd&passed=%d\n",
+ unit_test.Passed()));
+
+ // Notify the streaming server to stop.
+ CloseConnection();
+ }
+
+ void OnTestIterationStart(const UnitTest& /* unit_test */, int iteration) {
+ Send(String::Format("event=TestIterationStart&iteration=%d\n",
+ iteration));
+ }
+
+ void OnTestIterationEnd(const UnitTest& unit_test, int /* iteration */) {
+ Send(String::Format("event=TestIterationEnd&passed=%d&elapsed_time=%sms\n",
+ unit_test.Passed(),
+ StreamableToString(unit_test.elapsed_time()).c_str()));
+ }
+
+ void OnTestCaseStart(const TestCase& test_case) {
+ Send(String::Format("event=TestCaseStart&name=%s\n", test_case.name()));
+ }
+
+ void OnTestCaseEnd(const TestCase& test_case) {
+ Send(String::Format("event=TestCaseEnd&passed=%d&elapsed_time=%sms\n",
+ test_case.Passed(),
+ StreamableToString(test_case.elapsed_time()).c_str()));
+ }
+
+ void OnTestStart(const TestInfo& test_info) {
+ Send(String::Format("event=TestStart&name=%s\n", test_info.name()));
+ }
+
+ void OnTestEnd(const TestInfo& test_info) {
+ Send(String::Format(
+ "event=TestEnd&passed=%d&elapsed_time=%sms\n",
+ (test_info.result())->Passed(),
+ StreamableToString((test_info.result())->elapsed_time()).c_str()));
+ }
+
+ void OnTestPartResult(const TestPartResult& test_part_result) {
+ const char* file_name = test_part_result.file_name();
+ if (file_name == NULL)
+ file_name = "";
+ Send(String::Format("event=TestPartResult&file=%s&line=%d&message=",
+ UrlEncode(file_name).c_str(),
+ test_part_result.line_number()));
+ Send(UrlEncode(test_part_result.message()) + "\n");
+ }
+
+ private:
+ // Creates a client socket and connects to the server.
+ void MakeConnection();
+
+ // Closes the socket.
+ void CloseConnection() {
+ GTEST_CHECK_(sockfd_ != -1)
+ << "CloseConnection() can be called only when there is a connection.";
+
+ close(sockfd_);
+ sockfd_ = -1;
+ }
+
+ // Sends a string to the socket.
+ void Send(const string& message) {
+ GTEST_CHECK_(sockfd_ != -1)
+ << "Send() can be called only when there is a connection.";
+
+ const int len = static_cast<int>(message.length());
+ if (write(sockfd_, message.c_str(), len) != len) {
+ GTEST_LOG_(WARNING)
+ << "stream_result_to: failed to stream to "
+ << host_name_ << ":" << port_num_;
+ }
+ }
+
+ int sockfd_; // socket file descriptor
+ const string host_name_;
+ const string port_num_;
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamingListener);
+}; // class StreamingListener
+
+// Checks if str contains '=', '&', '%' or '\n' characters. If yes,
+// replaces them by "%xx" where xx is their hexadecimal value. For
+// example, replaces "=" with "%3D". This algorithm is O(strlen(str))
+// in both time and space -- important as the input str may contain an
+// arbitrarily long test failure message and stack trace.
+string StreamingListener::UrlEncode(const char* str) {
+ string result;
+ result.reserve(strlen(str) + 1);
+ for (char ch = *str; ch != '\0'; ch = *++str) {
+ switch (ch) {
+ case '%':
+ case '=':
+ case '&':
+ case '\n':
+ result.append(String::Format("%%%02x", static_cast<unsigned char>(ch)));
+ break;
+ default:
+ result.push_back(ch);
+ break;
+ }
+ }
+ return result;
+}
+
+void StreamingListener::MakeConnection() {
+ GTEST_CHECK_(sockfd_ == -1)
+ << "MakeConnection() can't be called when there is already a connection.";
+
+ addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC; // To allow both IPv4 and IPv6 addresses.
+ hints.ai_socktype = SOCK_STREAM;
+ addrinfo* servinfo = NULL;
+
+ // Use the getaddrinfo() to get a linked list of IP addresses for
+ // the given host name.
+ const int error_num = getaddrinfo(
+ host_name_.c_str(), port_num_.c_str(), &hints, &servinfo);
+ if (error_num != 0) {
+ GTEST_LOG_(WARNING) << "stream_result_to: getaddrinfo() failed: "
+ << gai_strerror(error_num);
+ }
+
+ // Loop through all the results and connect to the first we can.
+ for (addrinfo* cur_addr = servinfo; sockfd_ == -1 && cur_addr != NULL;
+ cur_addr = cur_addr->ai_next) {
+ sockfd_ = socket(
+ cur_addr->ai_family, cur_addr->ai_socktype, cur_addr->ai_protocol);
+ if (sockfd_ != -1) {
+ // Connect the client socket to the server socket.
+ if (connect(sockfd_, cur_addr->ai_addr, cur_addr->ai_addrlen) == -1) {
+ close(sockfd_);
+ sockfd_ = -1;
+ }
+ }
+ }
+
+ freeaddrinfo(servinfo); // all done with this structure
+
+ if (sockfd_ == -1) {
+ GTEST_LOG_(WARNING) << "stream_result_to: failed to connect to "
+ << host_name_ << ":" << port_num_;
+ }
+}
+
+// End of class Streaming Listener
+#endif // GTEST_CAN_STREAM_RESULTS__
+
// Class ScopedTrace
// Pushes the given source file location and message onto a per-thread
@@ -3541,19 +3711,6 @@
return env;
}
-#if GTEST_HAS_EXCEPTIONS
-// A failed Google Test assertion will throw an exception of this type
-// when exceptions are enabled. We derive it from std::runtime_error,
-// which is for errors presumably detectable only at run time. Since
-// std::runtime_error inherits from std::exception, many testing
-// frameworks know how to extract and print the message inside it.
-class GoogleTestFailureException : public ::std::runtime_error {
- public:
- explicit GoogleTestFailureException(const TestPartResult& failure)
- : ::std::runtime_error(PrintTestPartResultToString(failure).c_str()) {}
-};
-#endif
-
// Adds a TestPartResult to the current TestResult object. All Google Test
// assertion macros (e.g. ASSERT_TRUE, EXPECT_EQ, etc) eventually call
// this to report their results. The user code should use the
@@ -3630,31 +3787,34 @@
// We don't protect this under mutex_, as we only support calling it
// from the main thread.
int UnitTest::Run() {
-#if GTEST_HAS_SEH
- // Catch SEH-style exceptions.
+ // Captures the value of GTEST_FLAG(catch_exceptions). This value will be
+ // used for the duration of the program.
+ impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions));
+#if GTEST_HAS_SEH
const bool in_death_test_child_process =
internal::GTEST_FLAG(internal_run_death_test).length() > 0;
// Either the user wants Google Test to catch exceptions thrown by the
// tests or this is executing in the context of death test child
// process. In either case the user does not want to see pop-up dialogs
- // about crashes - they are expected..
- if (GTEST_FLAG(catch_exceptions) || in_death_test_child_process) {
-#if !GTEST_OS_WINDOWS_MOBILE
+ // about crashes - they are expected.
+ if (impl()->catch_exceptions() || in_death_test_child_process) {
+
+# if !GTEST_OS_WINDOWS_MOBILE
// SetErrorMode doesn't exist on CE.
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
-#endif // !GTEST_OS_WINDOWS_MOBILE
+# endif // !GTEST_OS_WINDOWS_MOBILE
-#if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE
+# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE
// Death test children can be terminated with _abort(). On Windows,
// _abort() can show a dialog with a warning message. This forces the
// abort message to go to stderr instead.
_set_error_mode(_OUT_TO_STDERR);
-#endif
+# endif
-#if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE
+# if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE
// In the debug version, Visual Studio pops up a separate dialog
// offering a choice to debug the aborted program. We need to suppress
// this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement
@@ -3670,22 +3830,15 @@
_set_abort_behavior(
0x0, // Clear the following flags:
_WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump.
-#endif
+# endif
+
}
-
- __try {
- return impl_->RunAllTests();
- } __except(internal::UnitTestOptions::GTestShouldProcessSEH(
- GetExceptionCode())) {
- printf("Exception thrown with code 0x%x.\nFAIL\n", GetExceptionCode());
- fflush(stdout);
- return 1;
- }
-
-#else // We are on a compiler or platform that doesn't support SEH.
-
- return impl_->RunAllTests();
#endif // GTEST_HAS_SEH
+
+ return internal::HandleExceptionsInMethodIfSupported(
+ impl(),
+ &internal::UnitTestImpl::RunAllTests,
+ "auxiliary test code (environments or event listeners)") ? 0 : 1;
}
// Returns the working directory when the first TEST() or TEST_F() was
@@ -3753,12 +3906,12 @@
UnitTestImpl::UnitTestImpl(UnitTest* parent)
: parent_(parent),
#ifdef _MSC_VER
-#pragma warning(push) // Saves the current warning state.
-#pragma warning(disable:4355) // Temporarily disables warning 4355
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4355) // Temporarily disables warning 4355
// (using this in initializer).
default_global_test_part_result_reporter_(this),
default_per_thread_test_part_result_reporter_(this),
-#pragma warning(pop) // Restores the warning state again.
+# pragma warning(pop) // Restores the warning state again.
#else
default_global_test_part_result_reporter_(this),
default_per_thread_test_part_result_reporter_(this),
@@ -3779,13 +3932,13 @@
post_flag_parse_init_performed_(false),
random_seed_(0), // Will be overridden by the flag before first use.
random_(0), // Will be reseeded before first use.
-#if GTEST_HAS_DEATH_TEST
elapsed_time_(0),
+#if GTEST_HAS_DEATH_TEST
internal_run_death_test_flag_(NULL),
- death_test_factory_(new DefaultDeathTestFactory) {
-#else
- elapsed_time_(0) {
-#endif // GTEST_HAS_DEATH_TEST
+ death_test_factory_(new DefaultDeathTestFactory),
+#endif
+ // Will be overridden by the flag before first use.
+ catch_exceptions_(false) {
listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter);
}
@@ -3822,6 +3975,25 @@
}
}
+#if GTEST_CAN_STREAM_RESULTS_
+// Initializes event listeners for streaming test results in String form.
+// Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureStreamingOutput() {
+ const string& target = GTEST_FLAG(stream_result_to);
+ if (!target.empty()) {
+ const size_t pos = target.find(':');
+ if (pos != string::npos) {
+ listeners()->Append(new StreamingListener(target.substr(0, pos),
+ target.substr(pos+1)));
+ } else {
+ printf("WARNING: unrecognized streaming target \"%s\" ignored.\n",
+ target.c_str());
+ fflush(stdout);
+ }
+ }
+}
+#endif // GTEST_CAN_STREAM_RESULTS_
+
// Performs initialization dependent upon flag values obtained in
// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to
// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest
@@ -3845,6 +4017,11 @@
// Configures listeners for XML output. This makes it possible for users
// to shut down the default XML output before invoking RUN_ALL_TESTS.
ConfigureXmlOutput();
+
+#if GTEST_CAN_STREAM_RESULTS_
+ // Configures listeners for streaming test results to the specified server.
+ ConfigureStreamingOutput();
+#endif // GTEST_CAN_STREAM_RESULTS_
}
}
@@ -3879,10 +4056,12 @@
// Arguments:
//
// test_case_name: name of the test case
+// type_param: the name of the test case's type parameter, or NULL if
+// this is not a typed or a type-parameterized test case.
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
TestCase* UnitTestImpl::GetTestCase(const char* test_case_name,
- const char* comment,
+ const char* type_param,
Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc) {
// Can we find a TestCase with the given name?
@@ -3895,7 +4074,7 @@
// No. Let's create one.
TestCase* const new_test_case =
- new TestCase(test_case_name, comment, set_up_tc, tear_down_tc);
+ new TestCase(test_case_name, type_param, set_up_tc, tear_down_tc);
// Is this a death test case?
if (internal::UnitTestOptions::MatchesFilter(String(test_case_name),
@@ -3922,27 +4101,26 @@
static void TearDownEnvironment(Environment* env) { env->TearDown(); }
// Runs all tests in this UnitTest object, prints the result, and
-// returns 0 if all tests are successful, or 1 otherwise. If any
-// exception is thrown during a test on Windows, this test is
-// considered to be failed, but the rest of the tests will still be
-// run. (We disable exceptions on Linux and Mac OS X, so the issue
-// doesn't apply there.)
+// returns true if all tests are successful. If any exception is
+// thrown during a test, the test is considered to be failed, but the
+// rest of the tests will still be run.
+//
// When parameterized tests are enabled, it expands and registers
// parameterized tests first in RegisterParameterizedTests().
// All other functions called from RunAllTests() may safely assume that
// parameterized tests are ready to be counted and run.
-int UnitTestImpl::RunAllTests() {
+bool UnitTestImpl::RunAllTests() {
// Makes sure InitGoogleTest() was called.
if (!GTestIsInitialized()) {
printf("%s",
"\nThis test program did NOT call ::testing::InitGoogleTest "
"before calling RUN_ALL_TESTS(). Please fix it.\n");
- return 1;
+ return false;
}
// Do not run any test if the --help flag was specified.
if (g_help_flag)
- return 0;
+ return true;
// Repeats the call to the post-flag parsing initialization in case the
// user didn't call InitGoogleTest.
@@ -3974,7 +4152,7 @@
if (GTEST_FLAG(list_tests)) {
// This must be called *after* FilterTests() has been called.
ListTestsMatchingFilter();
- return 0;
+ return true;
}
random_seed_ = GTEST_FLAG(shuffle) ?
@@ -3993,7 +4171,9 @@
// Repeats forever if the repeat count is negative.
const bool forever = repeat < 0;
for (int i = 0; forever || i != repeat; i++) {
- ClearResult();
+ // We want to preserve failures generated by ad-hoc test
+ // assertions executed before RUN_ALL_TESTS().
+ ClearNonAdHocTestResult();
const TimeInMillis start = GetTimeInMillis();
@@ -4058,8 +4238,7 @@
repeater->OnTestProgramEnd(*parent_);
- // Returns 0 if all tests passed, or 1 other wise.
- return failed ? 1 : 0;
+ return !failed;
}
// Reads the GTEST_SHARD_STATUS_FILE environment variable, and creates the file
@@ -4133,7 +4312,7 @@
// Parses the environment variable var as an Int32. If it is unset,
// returns default_val. If it is not an Int32, prints an error
// and aborts.
-Int32 Int32FromEnvOrDie(const char* const var, Int32 default_val) {
+Int32 Int32FromEnvOrDie(const char* var, Int32 default_val) {
const char* str_val = posix::GetEnv(var);
if (str_val == NULL) {
return default_val;
@@ -4189,12 +4368,12 @@
kDisableTestFilter) ||
internal::UnitTestOptions::MatchesFilter(test_name,
kDisableTestFilter);
- test_info->impl()->set_is_disabled(is_disabled);
+ test_info->is_disabled_ = is_disabled;
const bool matches_filter =
internal::UnitTestOptions::FilterMatchesTest(test_case_name,
test_name);
- test_info->impl()->set_matches_filter(matches_filter);
+ test_info->matches_filter_ = matches_filter;
const bool is_runnable =
(GTEST_FLAG(also_run_disabled_tests) || !is_disabled) &&
@@ -4208,7 +4387,7 @@
num_runnable_tests += is_runnable;
num_selected_tests += is_selected;
- test_info->impl()->set_should_run(is_selected);
+ test_info->should_run_ = is_selected;
test_case->set_should_run(test_case->should_run() || is_selected);
}
}
@@ -4224,7 +4403,7 @@
for (size_t j = 0; j < test_case->test_info_list().size(); j++) {
const TestInfo* const test_info =
test_case->test_info_list()[j];
- if (test_info->matches_filter()) {
+ if (test_info->matches_filter_) {
if (!printed_test_case_name) {
printed_test_case_name = true;
printf("%s.\n", test_case->name());
@@ -4264,7 +4443,7 @@
// the TestResult for the ad hoc test if no test is running.
TestResult* UnitTestImpl::current_test_result() {
return current_test_info_ ?
- current_test_info_->impl()->result() : &ad_hoc_test_result_;
+ &(current_test_info_->result_) : &ad_hoc_test_result_;
}
// Shuffles all test cases, and the tests within each test case,
@@ -4293,32 +4472,6 @@
}
}
-// TestInfoImpl constructor. The new instance assumes ownership of the test
-// factory object.
-TestInfoImpl::TestInfoImpl(TestInfo* parent,
- const char* a_test_case_name,
- const char* a_name,
- const char* a_test_case_comment,
- const char* a_comment,
- TypeId a_fixture_class_id,
- internal::TestFactoryBase* factory) :
- parent_(parent),
- test_case_name_(String(a_test_case_name)),
- name_(String(a_name)),
- test_case_comment_(String(a_test_case_comment)),
- comment_(String(a_comment)),
- fixture_class_id_(a_fixture_class_id),
- should_run_(false),
- is_disabled_(false),
- matches_filter_(false),
- factory_(factory) {
-}
-
-// TestInfoImpl destructor.
-TestInfoImpl::~TestInfoImpl() {
- delete factory_;
-}
-
// Returns the current OS stack trace as a String.
//
// The maximum number of stack frames to be included is specified by
@@ -4336,8 +4489,8 @@
return GetUnitTestImpl()->CurrentOsStackTraceExceptTop(skip_count + 1);
}
-// Used by the GTEST_HIDE_UNREACHABLE_CODE_ macro to suppress unreachable
-// code warnings.
+// Used by the GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_ macro to
+// suppress unreachable code warnings.
namespace {
class ClassUniqueToAlwaysTrue {};
}
@@ -4549,6 +4702,10 @@
GTEST_PATH_SEP_ "@Y|@G:@YFILE_PATH]@D\n"
" Generate an XML report in the given directory or with the given file\n"
" name. @YFILE_PATH@D defaults to @Gtest_details.xml@D.\n"
+#if GTEST_CAN_STREAM_RESULTS_
+" @G--" GTEST_FLAG_PREFIX_ "stream_result_to=@YHOST@G:@YPORT@D\n"
+" Stream test results to the given server.\n"
+#endif // GTEST_CAN_STREAM_RESULTS_
"\n"
"Assertion Behavior:\n"
#if GTEST_HAS_DEATH_TEST && !GTEST_OS_WINDOWS
@@ -4559,10 +4716,9 @@
" Turn assertion failures into debugger break-points.\n"
" @G--" GTEST_FLAG_PREFIX_ "throw_on_failure@D\n"
" Turn assertion failures into C++ exceptions.\n"
-#if GTEST_OS_WINDOWS
-" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions@D\n"
-" Suppress pop-ups caused by exceptions.\n"
-#endif // GTEST_OS_WINDOWS
+" @G--" GTEST_FLAG_PREFIX_ "catch_exceptions=0@D\n"
+" Do not report exceptions as test failures. Instead, allow them\n"
+" to crash the program or throw a pop-up (on Windows).\n"
"\n"
"Except for @G--" GTEST_FLAG_PREFIX_ "list_tests@D, you can alternatively set "
"the corresponding\n"
@@ -4612,7 +4768,10 @@
ParseBoolFlag(arg, kShuffleFlag, >EST_FLAG(shuffle)) ||
ParseInt32Flag(arg, kStackTraceDepthFlag,
>EST_FLAG(stack_trace_depth)) ||
- ParseBoolFlag(arg, kThrowOnFailureFlag, >EST_FLAG(throw_on_failure))
+ ParseStringFlag(arg, kStreamResultToFlag,
+ >EST_FLAG(stream_result_to)) ||
+ ParseBoolFlag(arg, kThrowOnFailureFlag,
+ >EST_FLAG(throw_on_failure))
) {
// Yes. Shift the remainder of the argv list left by one. Note
// that argv has (*argc + 1) elements, the last one always being
@@ -4670,10 +4829,12 @@
internal::g_executable_path = internal::StreamableToString(argv[0]);
#if GTEST_HAS_DEATH_TEST
+
g_argvs.clear();
for (int i = 0; i != *argc; i++) {
g_argvs.push_back(StreamableToString(argv[i]));
}
+
#endif // GTEST_HAS_DEATH_TEST
ParseGoogleTestFlagsOnly(argc, argv);
diff --git a/src/LLVM/utils/unittest/googletest/include/gtest/gtest-death-test.h b/src/LLVM/utils/unittest/googletest/include/gtest/gtest-death-test.h
index 121dc1f..a27883f 100644
--- a/src/LLVM/utils/unittest/googletest/include/gtest/gtest-death-test.h
+++ b/src/LLVM/utils/unittest/googletest/include/gtest/gtest-death-test.h
@@ -38,7 +38,7 @@
#ifndef GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
#define GTEST_INCLUDE_GTEST_GTEST_DEATH_TEST_H_
-#include <gtest/internal/gtest-death-test-internal.h>
+#include "gtest/internal/gtest-death-test-internal.h"
namespace testing {
@@ -154,24 +154,24 @@
// Asserts that a given statement causes the program to exit, with an
// integer exit status that satisfies predicate, and emitting error output
// that matches regex.
-#define ASSERT_EXIT(statement, predicate, regex) \
- GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
+# define ASSERT_EXIT(statement, predicate, regex) \
+ GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_FATAL_FAILURE_)
// Like ASSERT_EXIT, but continues on to successive tests in the
// test case, if any:
-#define EXPECT_EXIT(statement, predicate, regex) \
- GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
+# define EXPECT_EXIT(statement, predicate, regex) \
+ GTEST_DEATH_TEST_(statement, predicate, regex, GTEST_NONFATAL_FAILURE_)
// Asserts that a given statement causes the program to exit, either by
// explicitly exiting with a nonzero exit code or being killed by a
// signal, and emitting error output that matches regex.
-#define ASSERT_DEATH(statement, regex) \
- ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
+# define ASSERT_DEATH(statement, regex) \
+ ASSERT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
// Like ASSERT_DEATH, but continues on to successive tests in the
// test case, if any:
-#define EXPECT_DEATH(statement, regex) \
- EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
+# define EXPECT_DEATH(statement, regex) \
+ EXPECT_EXIT(statement, ::testing::internal::ExitedUnsuccessfully, regex)
// Two predicate classes that can be used in {ASSERT,EXPECT}_EXIT*:
@@ -187,7 +187,7 @@
const int exit_code_;
};
-#if !GTEST_OS_WINDOWS
+# if !GTEST_OS_WINDOWS
// Tests that an exit code describes an exit due to termination by a
// given signal.
class GTEST_API_ KilledBySignal {
@@ -197,7 +197,7 @@
private:
const int signum_;
};
-#endif // !GTEST_OS_WINDOWS
+# endif // !GTEST_OS_WINDOWS
// EXPECT_DEBUG_DEATH asserts that the given statements die in debug mode.
// The death testing framework causes this to have interesting semantics,
@@ -242,23 +242,23 @@
// EXPECT_EQ(12, DieInDebugOr12(&sideeffect));
// }, "death");
//
-#ifdef NDEBUG
+# ifdef NDEBUG
-#define EXPECT_DEBUG_DEATH(statement, regex) \
+# define EXPECT_DEBUG_DEATH(statement, regex) \
do { statement; } while (::testing::internal::AlwaysFalse())
-#define ASSERT_DEBUG_DEATH(statement, regex) \
+# define ASSERT_DEBUG_DEATH(statement, regex) \
do { statement; } while (::testing::internal::AlwaysFalse())
-#else
+# else
-#define EXPECT_DEBUG_DEATH(statement, regex) \
+# define EXPECT_DEBUG_DEATH(statement, regex) \
EXPECT_DEATH(statement, regex)
-#define ASSERT_DEBUG_DEATH(statement, regex) \
+# define ASSERT_DEBUG_DEATH(statement, regex) \
ASSERT_DEATH(statement, regex)
-#endif // NDEBUG for EXPECT_DEBUG_DEATH
+# endif // NDEBUG for EXPECT_DEBUG_DEATH
#endif // GTEST_HAS_DEATH_TEST
// EXPECT_DEATH_IF_SUPPORTED(statement, regex) and
@@ -267,14 +267,14 @@
// useful when you are combining death test assertions with normal test
// assertions in one test.
#if GTEST_HAS_DEATH_TEST
-#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
EXPECT_DEATH(statement, regex)
-#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
ASSERT_DEATH(statement, regex)
#else
-#define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+# define EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, )
-#define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
+# define ASSERT_DEATH_IF_SUPPORTED(statement, regex) \
GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, return)
#endif
diff --git a/src/LLVM/utils/unittest/googletest/include/gtest/gtest-message.h b/src/LLVM/utils/unittest/googletest/include/gtest/gtest-message.h
index f135b69..9b7142f 100644
--- a/src/LLVM/utils/unittest/googletest/include/gtest/gtest-message.h
+++ b/src/LLVM/utils/unittest/googletest/include/gtest/gtest-message.h
@@ -48,8 +48,8 @@
#include <limits>
-#include <gtest/internal/gtest-string.h>
-#include <gtest/internal/gtest-internal.h>
+#include "gtest/internal/gtest-string.h"
+#include "gtest/internal/gtest-internal.h"
namespace testing {
@@ -58,7 +58,7 @@
// Typical usage:
//
// 1. You stream a bunch of values to a Message object.
-// It will remember the text in a StrStream.
+// It will remember the text in a stringstream.
// 2. Then you stream the Message object to an ostream.
// This causes the text in the Message to be streamed
// to the ostream.
@@ -74,7 +74,7 @@
// Message is not intended to be inherited from. In particular, its
// destructor is not virtual.
//
-// Note that StrStream behaves differently in gcc and in MSVC. You
+// Note that stringstream behaves differently in gcc and in MSVC. You
// can stream a NULL char pointer to it in the former, but not in the
// latter (it causes an access violation if you do). The Message
// class hides this difference by treating a NULL char pointer as
@@ -87,27 +87,26 @@
public:
// Constructs an empty Message.
- // We allocate the StrStream separately because it otherwise each use of
+ // We allocate the stringstream separately because otherwise each use of
// ASSERT/EXPECT in a procedure adds over 200 bytes to the procedure's
// stack frame leading to huge stack frames in some cases; gcc does not reuse
// the stack space.
- Message() : ss_(new internal::StrStream) {
+ Message() : ss_(new ::std::stringstream) {
// By default, we want there to be enough precision when printing
// a double to a Message.
*ss_ << std::setprecision(std::numeric_limits<double>::digits10 + 2);
}
// Copy constructor.
- Message(const Message& msg) : ss_(new internal::StrStream) { // NOLINT
+ Message(const Message& msg) : ss_(new ::std::stringstream) { // NOLINT
*ss_ << msg.GetString();
}
// Constructs a Message from a C-string.
- explicit Message(const char* str) : ss_(new internal::StrStream) {
+ explicit Message(const char* str) : ss_(new ::std::stringstream) {
*ss_ << str;
}
- ~Message() { delete ss_; }
#if GTEST_OS_SYMBIAN
// Streams a value (either a pointer or not) to this object.
template <typename T>
@@ -119,7 +118,7 @@
// Streams a non-pointer value to this object.
template <typename T>
inline Message& operator <<(const T& val) {
- ::GTestStreamToHelper(ss_, val);
+ ::GTestStreamToHelper(ss_.get(), val);
return *this;
}
@@ -141,7 +140,7 @@
if (pointer == NULL) {
*ss_ << "(null)";
} else {
- ::GTestStreamToHelper(ss_, pointer);
+ ::GTestStreamToHelper(ss_.get(), pointer);
}
return *this;
}
@@ -189,10 +188,11 @@
//
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
internal::String GetString() const {
- return internal::StrStreamToString(ss_);
+ return internal::StringStreamToString(ss_.get());
}
private:
+
#if GTEST_OS_SYMBIAN
// These are needed as the Nokia Symbian Compiler cannot decide between
// const T& and const T* in a function template. The Nokia compiler _can_
@@ -203,17 +203,17 @@
if (pointer == NULL) {
*ss_ << "(null)";
} else {
- ::GTestStreamToHelper(ss_, pointer);
+ ::GTestStreamToHelper(ss_.get(), pointer);
}
}
template <typename T>
inline void StreamHelper(internal::false_type /*dummy*/, const T& value) {
- ::GTestStreamToHelper(ss_, value);
+ ::GTestStreamToHelper(ss_.get(), value);
}
#endif // GTEST_OS_SYMBIAN
// We'll hold the text streamed to this object here.
- internal::StrStream* const ss_;
+ const internal::scoped_ptr< ::std::stringstream> ss_;
// We declare (but don't implement) this to prevent the compiler
// from implementing the assignment operator.
diff --git a/src/LLVM/utils/unittest/googletest/include/gtest/gtest-param-test.h b/src/LLVM/utils/unittest/googletest/include/gtest/gtest-param-test.h
index 3184d07..b1f8bb9 100644
--- a/src/LLVM/utils/unittest/googletest/include/gtest/gtest-param-test.h
+++ b/src/LLVM/utils/unittest/googletest/include/gtest/gtest-param-test.h
@@ -1,4 +1,6 @@
-// This file was GENERATED by a script. DO NOT EDIT BY HAND!!!
+// This file was GENERATED by command:
+// pump.py gtest-param-test.h.pump
+// DO NOT EDIT BY HAND!!!
// Copyright 2008, Google Inc.
// All rights reserved.
@@ -48,10 +50,12 @@
#if 0
// To write value-parameterized tests, first you should define a fixture
-// class. It must be derived from testing::TestWithParam<T>, where T is
-// the type of your parameter values. TestWithParam<T> is itself derived
-// from testing::Test. T can be any copyable type. If it's a raw pointer,
-// you are responsible for managing the lifespan of the pointed values.
+// class. It is usually derived from testing::TestWithParam<T> (see below for
+// another inheritance scheme that's sometimes useful in more complicated
+// class hierarchies), where the type of your parameter values.
+// TestWithParam<T> is itself derived from testing::Test. T can be any
+// copyable type. If it's a raw pointer, you are responsible for managing the
+// lifespan of the pointed values.
class FooTest : public ::testing::TestWithParam<const char*> {
// You can implement all the usual class fixture members here.
@@ -146,20 +150,46 @@
// In the future, we plan to publish the API for defining new parameter
// generators. But for now this interface remains part of the internal
// implementation and is subject to change.
+//
+//
+// A parameterized test fixture must be derived from testing::Test and from
+// testing::WithParamInterface<T>, where T is the type of the parameter
+// values. Inheriting from TestWithParam<T> satisfies that requirement because
+// TestWithParam<T> inherits from both Test and WithParamInterface. In more
+// complicated hierarchies, however, it is occasionally useful to inherit
+// separately from Test and WithParamInterface. For example:
+
+class BaseTest : public ::testing::Test {
+ // You can inherit all the usual members for a non-parameterized test
+ // fixture here.
+};
+
+class DerivedTest : public BaseTest, public ::testing::WithParamInterface<int> {
+ // The usual test fixture members go here too.
+};
+
+TEST_F(BaseTest, HasFoo) {
+ // This is an ordinary non-parameterized test.
+}
+
+TEST_P(DerivedTest, DoesBlah) {
+ // GetParam works just the same here as if you inherit from TestWithParam.
+ EXPECT_TRUE(foo.Blah(GetParam()));
+}
#endif // 0
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-port.h"
#if !GTEST_OS_SYMBIAN
-#include <utility>
+# include <utility>
#endif
// scripts/fuse_gtest.py depends on gtest's own header being #included
// *unconditionally*. Therefore these #includes cannot be moved
// inside #if GTEST_HAS_PARAM_TEST.
-#include <gtest/internal/gtest-internal.h>
-#include <gtest/internal/gtest-param-util.h>
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-param-util.h"
#if GTEST_HAS_PARAM_TEST
@@ -275,11 +305,10 @@
//
template <typename ForwardIterator>
internal::ParamGenerator<
- typename ::std::iterator_traits<ForwardIterator>::value_type> ValuesIn(
- ForwardIterator begin,
- ForwardIterator end) {
- typedef typename ::std::iterator_traits<ForwardIterator>::value_type
- ParamType;
+ typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end) {
+ typedef typename ::testing::internal::IteratorTraits<ForwardIterator>
+ ::value_type ParamType;
return internal::ParamGenerator<ParamType>(
new internal::ValuesInIteratorRangeGenerator<ParamType>(begin, end));
}
@@ -1197,7 +1226,7 @@
return Values(false, true);
}
-#if GTEST_HAS_COMBINE
+# if GTEST_HAS_COMBINE
// Combine() allows the user to combine two or more sequences to produce
// values of a Cartesian product of those sequences' elements.
//
@@ -1349,11 +1378,11 @@
Generator10>(
g1, g2, g3, g4, g5, g6, g7, g8, g9, g10);
}
-#endif // GTEST_HAS_COMBINE
+# endif // GTEST_HAS_COMBINE
-#define TEST_P(test_case_name, test_name) \
+# define TEST_P(test_case_name, test_name) \
class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
: public test_case_name { \
public: \
@@ -1379,7 +1408,7 @@
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::AddToRegistry(); \
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
-#define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
+# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
::testing::internal::ParamGenerator<test_case_name::ParamType> \
gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
int gtest_##prefix##test_case_name##_dummy_ = \
diff --git a/src/LLVM/utils/unittest/googletest/include/gtest/gtest-printers.h b/src/LLVM/utils/unittest/googletest/include/gtest/gtest-printers.h
new file mode 100644
index 0000000..9cbab3f
--- /dev/null
+++ b/src/LLVM/utils/unittest/googletest/include/gtest/gtest-printers.h
@@ -0,0 +1,796 @@
+// Copyright 2007, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: wan@google.com (Zhanyong Wan)
+
+// Google Test - The Google C++ Testing Framework
+//
+// This file implements a universal value printer that can print a
+// value of any type T:
+//
+// void ::testing::internal::UniversalPrinter<T>::Print(value, ostream_ptr);
+//
+// A user can teach this function how to print a class type T by
+// defining either operator<<() or PrintTo() in the namespace that
+// defines T. More specifically, the FIRST defined function in the
+// following list will be used (assuming T is defined in namespace
+// foo):
+//
+// 1. foo::PrintTo(const T&, ostream*)
+// 2. operator<<(ostream&, const T&) defined in either foo or the
+// global namespace.
+//
+// If none of the above is defined, it will print the debug string of
+// the value if it is a protocol buffer, or print the raw bytes in the
+// value otherwise.
+//
+// To aid debugging: when T is a reference type, the address of the
+// value is also printed; when T is a (const) char pointer, both the
+// pointer value and the NUL-terminated string it points to are
+// printed.
+//
+// We also provide some convenient wrappers:
+//
+// // Prints a value to a string. For a (const or not) char
+// // pointer, the NUL-terminated string (but not the pointer) is
+// // printed.
+// std::string ::testing::PrintToString(const T& value);
+//
+// // Prints a value tersely: for a reference type, the referenced
+// // value (but not the address) is printed; for a (const or not) char
+// // pointer, the NUL-terminated string (but not the pointer) is
+// // printed.
+// void ::testing::internal::UniversalTersePrint(const T& value, ostream*);
+//
+// // Prints value using the type inferred by the compiler. The difference
+// // from UniversalTersePrint() is that this function prints both the
+// // pointer and the NUL-terminated string for a (const or not) char pointer.
+// void ::testing::internal::UniversalPrint(const T& value, ostream*);
+//
+// // Prints the fields of a tuple tersely to a string vector, one
+// // element for each field. Tuple support must be enabled in
+// // gtest-port.h.
+// std::vector<string> UniversalTersePrintTupleFieldsToStrings(
+// const Tuple& value);
+//
+// Known limitation:
+//
+// The print primitives print the elements of an STL-style container
+// using the compiler-inferred type of *iter where iter is a
+// const_iterator of the container. When const_iterator is an input
+// iterator but not a forward iterator, this inferred type may not
+// match value_type, and the print output may be incorrect. In
+// practice, this is rarely a problem as for most containers
+// const_iterator is a forward iterator. We'll fix this if there's an
+// actual need for it. Note that this fix cannot rely on value_type
+// being defined as many user-defined container types don't have
+// value_type.
+
+#ifndef GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+#define GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
+
+#include <ostream> // NOLINT
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-internal.h"
+
+namespace testing {
+
+// Definitions in the 'internal' and 'internal2' name spaces are
+// subject to change without notice. DO NOT USE THEM IN USER CODE!
+namespace internal2 {
+
+// Prints the given number of bytes in the given object to the given
+// ostream.
+GTEST_API_ void PrintBytesInObjectTo(const unsigned char* obj_bytes,
+ size_t count,
+ ::std::ostream* os);
+
+// For selecting which printer to use when a given type has neither <<
+// nor PrintTo().
+enum TypeKind {
+ kProtobuf, // a protobuf type
+ kConvertibleToInteger, // a type implicitly convertible to BiggestInt
+ // (e.g. a named or unnamed enum type)
+ kOtherType // anything else
+};
+
+// TypeWithoutFormatter<T, kTypeKind>::PrintValue(value, os) is called
+// by the universal printer to print a value of type T when neither
+// operator<< nor PrintTo() is defined for T, where kTypeKind is the
+// "kind" of T as defined by enum TypeKind.
+template <typename T, TypeKind kTypeKind>
+class TypeWithoutFormatter {
+ public:
+ // This default version is called when kTypeKind is kOtherType.
+ static void PrintValue(const T& value, ::std::ostream* os) {
+ PrintBytesInObjectTo(reinterpret_cast<const unsigned char*>(&value),
+ sizeof(value), os);
+ }
+};
+
+// We print a protobuf using its ShortDebugString() when the string
+// doesn't exceed this many characters; otherwise we print it using
+// DebugString() for better readability.
+const size_t kProtobufOneLinerMaxLength = 50;
+
+template <typename T>
+class TypeWithoutFormatter<T, kProtobuf> {
+ public:
+ static void PrintValue(const T& value, ::std::ostream* os) {
+ const ::testing::internal::string short_str = value.ShortDebugString();
+ const ::testing::internal::string pretty_str =
+ short_str.length() <= kProtobufOneLinerMaxLength ?
+ short_str : ("\n" + value.DebugString());
+ *os << ("<" + pretty_str + ">");
+ }
+};
+
+template <typename T>
+class TypeWithoutFormatter<T, kConvertibleToInteger> {
+ public:
+ // Since T has no << operator or PrintTo() but can be implicitly
+ // converted to BiggestInt, we print it as a BiggestInt.
+ //
+ // Most likely T is an enum type (either named or unnamed), in which
+ // case printing it as an integer is the desired behavior. In case
+ // T is not an enum, printing it as an integer is the best we can do
+ // given that it has no user-defined printer.
+ static void PrintValue(const T& value, ::std::ostream* os) {
+ const internal::BiggestInt kBigInt = value;
+ *os << kBigInt;
+ }
+};
+
+// Prints the given value to the given ostream. If the value is a
+// protocol message, its debug string is printed; if it's an enum or
+// of a type implicitly convertible to BiggestInt, it's printed as an
+// integer; otherwise the bytes in the value are printed. This is
+// what UniversalPrinter<T>::Print() does when it knows nothing about
+// type T and T has neither << operator nor PrintTo().
+//
+// A user can override this behavior for a class type Foo by defining
+// a << operator in the namespace where Foo is defined.
+//
+// We put this operator in namespace 'internal2' instead of 'internal'
+// to simplify the implementation, as much code in 'internal' needs to
+// use << in STL, which would conflict with our own << were it defined
+// in 'internal'.
+//
+// Note that this operator<< takes a generic std::basic_ostream<Char,
+// CharTraits> type instead of the more restricted std::ostream. If
+// we define it to take an std::ostream instead, we'll get an
+// "ambiguous overloads" compiler error when trying to print a type
+// Foo that supports streaming to std::basic_ostream<Char,
+// CharTraits>, as the compiler cannot tell whether
+// operator<<(std::ostream&, const T&) or
+// operator<<(std::basic_stream<Char, CharTraits>, const Foo&) is more
+// specific.
+template <typename Char, typename CharTraits, typename T>
+::std::basic_ostream<Char, CharTraits>& operator<<(
+ ::std::basic_ostream<Char, CharTraits>& os, const T& x) {
+ TypeWithoutFormatter<T,
+ (internal::IsAProtocolMessage<T>::value ? kProtobuf :
+ internal::ImplicitlyConvertible<const T&, internal::BiggestInt>::value ?
+ kConvertibleToInteger : kOtherType)>::PrintValue(x, &os);
+ return os;
+}
+
+} // namespace internal2
+} // namespace testing
+
+// This namespace MUST NOT BE NESTED IN ::testing, or the name look-up
+// magic needed for implementing UniversalPrinter won't work.
+namespace testing_internal {
+
+// Used to print a value that is not an STL-style container when the
+// user doesn't define PrintTo() for it.
+template <typename T>
+void DefaultPrintNonContainerTo(const T& value, ::std::ostream* os) {
+ // With the following statement, during unqualified name lookup,
+ // testing::internal2::operator<< appears as if it was declared in
+ // the nearest enclosing namespace that contains both
+ // ::testing_internal and ::testing::internal2, i.e. the global
+ // namespace. For more details, refer to the C++ Standard section
+ // 7.3.4-1 [namespace.udir]. This allows us to fall back onto
+ // testing::internal2::operator<< in case T doesn't come with a <<
+ // operator.
+ //
+ // We cannot write 'using ::testing::internal2::operator<<;', which
+ // gcc 3.3 fails to compile due to a compiler bug.
+ using namespace ::testing::internal2; // NOLINT
+
+ // Assuming T is defined in namespace foo, in the next statement,
+ // the compiler will consider all of:
+ //
+ // 1. foo::operator<< (thanks to Koenig look-up),
+ // 2. ::operator<< (as the current namespace is enclosed in ::),
+ // 3. testing::internal2::operator<< (thanks to the using statement above).
+ //
+ // The operator<< whose type matches T best will be picked.
+ //
+ // We deliberately allow #2 to be a candidate, as sometimes it's
+ // impossible to define #1 (e.g. when foo is ::std, defining
+ // anything in it is undefined behavior unless you are a compiler
+ // vendor.).
+ *os << value;
+}
+
+} // namespace testing_internal
+
+namespace testing {
+namespace internal {
+
+// UniversalPrinter<T>::Print(value, ostream_ptr) prints the given
+// value to the given ostream. The caller must ensure that
+// 'ostream_ptr' is not NULL, or the behavior is undefined.
+//
+// We define UniversalPrinter as a class template (as opposed to a
+// function template), as we need to partially specialize it for
+// reference types, which cannot be done with function templates.
+template <typename T>
+class UniversalPrinter;
+
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os);
+
+// Used to print an STL-style container when the user doesn't define
+// a PrintTo() for it.
+template <typename C>
+void DefaultPrintTo(IsContainer /* dummy */,
+ false_type /* is not a pointer */,
+ const C& container, ::std::ostream* os) {
+ const size_t kMaxCount = 32; // The maximum number of elements to print.
+ *os << '{';
+ size_t count = 0;
+ for (typename C::const_iterator it = container.begin();
+ it != container.end(); ++it, ++count) {
+ if (count > 0) {
+ *os << ',';
+ if (count == kMaxCount) { // Enough has been printed.
+ *os << " ...";
+ break;
+ }
+ }
+ *os << ' ';
+ // We cannot call PrintTo(*it, os) here as PrintTo() doesn't
+ // handle *it being a native array.
+ internal::UniversalPrint(*it, os);
+ }
+
+ if (count > 0) {
+ *os << ' ';
+ }
+ *os << '}';
+}
+
+// Used to print a pointer that is neither a char pointer nor a member
+// pointer, when the user doesn't define PrintTo() for it. (A member
+// variable pointer or member function pointer doesn't really point to
+// a location in the address space. Their representation is
+// implementation-defined. Therefore they will be printed as raw
+// bytes.)
+template <typename T>
+void DefaultPrintTo(IsNotContainer /* dummy */,
+ true_type /* is a pointer */,
+ T* p, ::std::ostream* os) {
+ if (p == NULL) {
+ *os << "NULL";
+ } else {
+ // C++ doesn't allow casting from a function pointer to any object
+ // pointer.
+ //
+ // IsTrue() silences warnings: "Condition is always true",
+ // "unreachable code".
+ if (IsTrue(ImplicitlyConvertible<T*, const void*>::value)) {
+ // T is not a function type. We just call << to print p,
+ // relying on ADL to pick up user-defined << for their pointer
+ // types, if any.
+ *os << p;
+ } else {
+ // T is a function type, so '*os << p' doesn't do what we want
+ // (it just prints p as bool). We want to print p as a const
+ // void*. However, we cannot cast it to const void* directly,
+ // even using reinterpret_cast, as earlier versions of gcc
+ // (e.g. 3.4.5) cannot compile the cast when p is a function
+ // pointer. Casting to UInt64 first solves the problem.
+ *os << reinterpret_cast<const void*>(
+ reinterpret_cast<internal::UInt64>(p));
+ }
+ }
+}
+
+// Used to print a non-container, non-pointer value when the user
+// doesn't define PrintTo() for it.
+template <typename T>
+void DefaultPrintTo(IsNotContainer /* dummy */,
+ false_type /* is not a pointer */,
+ const T& value, ::std::ostream* os) {
+ ::testing_internal::DefaultPrintNonContainerTo(value, os);
+}
+
+// Prints the given value using the << operator if it has one;
+// otherwise prints the bytes in it. This is what
+// UniversalPrinter<T>::Print() does when PrintTo() is not specialized
+// or overloaded for type T.
+//
+// A user can override this behavior for a class type Foo by defining
+// an overload of PrintTo() in the namespace where Foo is defined. We
+// give the user this option as sometimes defining a << operator for
+// Foo is not desirable (e.g. the coding style may prevent doing it,
+// or there is already a << operator but it doesn't do what the user
+// wants).
+template <typename T>
+void PrintTo(const T& value, ::std::ostream* os) {
+ // DefaultPrintTo() is overloaded. The type of its first two
+ // arguments determine which version will be picked. If T is an
+ // STL-style container, the version for container will be called; if
+ // T is a pointer, the pointer version will be called; otherwise the
+ // generic version will be called.
+ //
+ // Note that we check for container types here, prior to we check
+ // for protocol message types in our operator<<. The rationale is:
+ //
+ // For protocol messages, we want to give people a chance to
+ // override Google Mock's format by defining a PrintTo() or
+ // operator<<. For STL containers, other formats can be
+ // incompatible with Google Mock's format for the container
+ // elements; therefore we check for container types here to ensure
+ // that our format is used.
+ //
+ // The second argument of DefaultPrintTo() is needed to bypass a bug
+ // in Symbian's C++ compiler that prevents it from picking the right
+ // overload between:
+ //
+ // PrintTo(const T& x, ...);
+ // PrintTo(T* x, ...);
+ DefaultPrintTo(IsContainerTest<T>(0), is_pointer<T>(), value, os);
+}
+
+// The following list of PrintTo() overloads tells
+// UniversalPrinter<T>::Print() how to print standard types (built-in
+// types, strings, plain arrays, and pointers).
+
+// Overloads for various char types.
+GTEST_API_ void PrintTo(unsigned char c, ::std::ostream* os);
+GTEST_API_ void PrintTo(signed char c, ::std::ostream* os);
+inline void PrintTo(char c, ::std::ostream* os) {
+ // When printing a plain char, we always treat it as unsigned. This
+ // way, the output won't be affected by whether the compiler thinks
+ // char is signed or not.
+ PrintTo(static_cast<unsigned char>(c), os);
+}
+
+// Overloads for other simple built-in types.
+inline void PrintTo(bool x, ::std::ostream* os) {
+ *os << (x ? "true" : "false");
+}
+
+// Overload for wchar_t type.
+// Prints a wchar_t as a symbol if it is printable or as its internal
+// code otherwise and also as its decimal code (except for L'\0').
+// The L'\0' char is printed as "L'\\0'". The decimal code is printed
+// as signed integer when wchar_t is implemented by the compiler
+// as a signed type and is printed as an unsigned integer when wchar_t
+// is implemented as an unsigned type.
+GTEST_API_ void PrintTo(wchar_t wc, ::std::ostream* os);
+
+// Overloads for C strings.
+GTEST_API_ void PrintTo(const char* s, ::std::ostream* os);
+inline void PrintTo(char* s, ::std::ostream* os) {
+ PrintTo(ImplicitCast_<const char*>(s), os);
+}
+
+// signed/unsigned char is often used for representing binary data, so
+// we print pointers to it as void* to be safe.
+inline void PrintTo(const signed char* s, ::std::ostream* os) {
+ PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(signed char* s, ::std::ostream* os) {
+ PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(const unsigned char* s, ::std::ostream* os) {
+ PrintTo(ImplicitCast_<const void*>(s), os);
+}
+inline void PrintTo(unsigned char* s, ::std::ostream* os) {
+ PrintTo(ImplicitCast_<const void*>(s), os);
+}
+
+// MSVC can be configured to define wchar_t as a typedef of unsigned
+// short. It defines _NATIVE_WCHAR_T_DEFINED when wchar_t is a native
+// type. When wchar_t is a typedef, defining an overload for const
+// wchar_t* would cause unsigned short* be printed as a wide string,
+// possibly causing invalid memory accesses.
+#if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED)
+// Overloads for wide C strings
+GTEST_API_ void PrintTo(const wchar_t* s, ::std::ostream* os);
+inline void PrintTo(wchar_t* s, ::std::ostream* os) {
+ PrintTo(ImplicitCast_<const wchar_t*>(s), os);
+}
+#endif
+
+// Overload for C arrays. Multi-dimensional arrays are printed
+// properly.
+
+// Prints the given number of elements in an array, without printing
+// the curly braces.
+template <typename T>
+void PrintRawArrayTo(const T a[], size_t count, ::std::ostream* os) {
+ UniversalPrint(a[0], os);
+ for (size_t i = 1; i != count; i++) {
+ *os << ", ";
+ UniversalPrint(a[i], os);
+ }
+}
+
+// Overloads for ::string and ::std::string.
+#if GTEST_HAS_GLOBAL_STRING
+GTEST_API_ void PrintStringTo(const ::string&s, ::std::ostream* os);
+inline void PrintTo(const ::string& s, ::std::ostream* os) {
+ PrintStringTo(s, os);
+}
+#endif // GTEST_HAS_GLOBAL_STRING
+
+GTEST_API_ void PrintStringTo(const ::std::string&s, ::std::ostream* os);
+inline void PrintTo(const ::std::string& s, ::std::ostream* os) {
+ PrintStringTo(s, os);
+}
+
+// Overloads for ::wstring and ::std::wstring.
+#if GTEST_HAS_GLOBAL_WSTRING
+GTEST_API_ void PrintWideStringTo(const ::wstring&s, ::std::ostream* os);
+inline void PrintTo(const ::wstring& s, ::std::ostream* os) {
+ PrintWideStringTo(s, os);
+}
+#endif // GTEST_HAS_GLOBAL_WSTRING
+
+#if GTEST_HAS_STD_WSTRING
+GTEST_API_ void PrintWideStringTo(const ::std::wstring&s, ::std::ostream* os);
+inline void PrintTo(const ::std::wstring& s, ::std::ostream* os) {
+ PrintWideStringTo(s, os);
+}
+#endif // GTEST_HAS_STD_WSTRING
+
+#if GTEST_HAS_TR1_TUPLE
+// Overload for ::std::tr1::tuple. Needed for printing function arguments,
+// which are packed as tuples.
+
+// Helper function for printing a tuple. T must be instantiated with
+// a tuple type.
+template <typename T>
+void PrintTupleTo(const T& t, ::std::ostream* os);
+
+// Overloaded PrintTo() for tuples of various arities. We support
+// tuples of up-to 10 fields. The following implementation works
+// regardless of whether tr1::tuple is implemented using the
+// non-standard variadic template feature or not.
+
+inline void PrintTo(const ::std::tr1::tuple<>& t, ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1>
+void PrintTo(const ::std::tr1::tuple<T1>& t, ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2>
+void PrintTo(const ::std::tr1::tuple<T1, T2>& t, ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3>& t, ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4>& t, ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5>& t,
+ ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6>& t,
+ ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7>& t,
+ ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8>& t,
+ ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9>
+void PrintTo(const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>& t,
+ ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+
+template <typename T1, typename T2, typename T3, typename T4, typename T5,
+ typename T6, typename T7, typename T8, typename T9, typename T10>
+void PrintTo(
+ const ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>& t,
+ ::std::ostream* os) {
+ PrintTupleTo(t, os);
+}
+#endif // GTEST_HAS_TR1_TUPLE
+
+// Overload for std::pair.
+template <typename T1, typename T2>
+void PrintTo(const ::std::pair<T1, T2>& value, ::std::ostream* os) {
+ *os << '(';
+ // We cannot use UniversalPrint(value.first, os) here, as T1 may be
+ // a reference type. The same for printing value.second.
+ UniversalPrinter<T1>::Print(value.first, os);
+ *os << ", ";
+ UniversalPrinter<T2>::Print(value.second, os);
+ *os << ')';
+}
+
+// Implements printing a non-reference type T by letting the compiler
+// pick the right overload of PrintTo() for T.
+template <typename T>
+class UniversalPrinter {
+ public:
+ // MSVC warns about adding const to a function type, so we want to
+ // disable the warning.
+#ifdef _MSC_VER
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4180) // Temporarily disables warning 4180.
+#endif // _MSC_VER
+
+ // Note: we deliberately don't call this PrintTo(), as that name
+ // conflicts with ::testing::internal::PrintTo in the body of the
+ // function.
+ static void Print(const T& value, ::std::ostream* os) {
+ // By default, ::testing::internal::PrintTo() is used for printing
+ // the value.
+ //
+ // Thanks to Koenig look-up, if T is a class and has its own
+ // PrintTo() function defined in its namespace, that function will
+ // be visible here. Since it is more specific than the generic ones
+ // in ::testing::internal, it will be picked by the compiler in the
+ // following statement - exactly what we want.
+ PrintTo(value, os);
+ }
+
+#ifdef _MSC_VER
+# pragma warning(pop) // Restores the warning state.
+#endif // _MSC_VER
+};
+
+// UniversalPrintArray(begin, len, os) prints an array of 'len'
+// elements, starting at address 'begin'.
+template <typename T>
+void UniversalPrintArray(const T* begin, size_t len, ::std::ostream* os) {
+ if (len == 0) {
+ *os << "{}";
+ } else {
+ *os << "{ ";
+ const size_t kThreshold = 18;
+ const size_t kChunkSize = 8;
+ // If the array has more than kThreshold elements, we'll have to
+ // omit some details by printing only the first and the last
+ // kChunkSize elements.
+ // TODO(wan@google.com): let the user control the threshold using a flag.
+ if (len <= kThreshold) {
+ PrintRawArrayTo(begin, len, os);
+ } else {
+ PrintRawArrayTo(begin, kChunkSize, os);
+ *os << ", ..., ";
+ PrintRawArrayTo(begin + len - kChunkSize, kChunkSize, os);
+ }
+ *os << " }";
+ }
+}
+// This overload prints a (const) char array compactly.
+GTEST_API_ void UniversalPrintArray(const char* begin,
+ size_t len,
+ ::std::ostream* os);
+
+// Implements printing an array type T[N].
+template <typename T, size_t N>
+class UniversalPrinter<T[N]> {
+ public:
+ // Prints the given array, omitting some elements when there are too
+ // many.
+ static void Print(const T (&a)[N], ::std::ostream* os) {
+ UniversalPrintArray(a, N, os);
+ }
+};
+
+// Implements printing a reference type T&.
+template <typename T>
+class UniversalPrinter<T&> {
+ public:
+ // MSVC warns about adding const to a function type, so we want to
+ // disable the warning.
+#ifdef _MSC_VER
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4180) // Temporarily disables warning 4180.
+#endif // _MSC_VER
+
+ static void Print(const T& value, ::std::ostream* os) {
+ // Prints the address of the value. We use reinterpret_cast here
+ // as static_cast doesn't compile when T is a function type.
+ *os << "@" << reinterpret_cast<const void*>(&value) << " ";
+
+ // Then prints the value itself.
+ UniversalPrint(value, os);
+ }
+
+#ifdef _MSC_VER
+# pragma warning(pop) // Restores the warning state.
+#endif // _MSC_VER
+};
+
+// Prints a value tersely: for a reference type, the referenced value
+// (but not the address) is printed; for a (const) char pointer, the
+// NUL-terminated string (but not the pointer) is printed.
+template <typename T>
+void UniversalTersePrint(const T& value, ::std::ostream* os) {
+ UniversalPrint(value, os);
+}
+inline void UniversalTersePrint(const char* str, ::std::ostream* os) {
+ if (str == NULL) {
+ *os << "NULL";
+ } else {
+ UniversalPrint(string(str), os);
+ }
+}
+inline void UniversalTersePrint(char* str, ::std::ostream* os) {
+ UniversalTersePrint(static_cast<const char*>(str), os);
+}
+
+// Prints a value using the type inferred by the compiler. The
+// difference between this and UniversalTersePrint() is that for a
+// (const) char pointer, this prints both the pointer and the
+// NUL-terminated string.
+template <typename T>
+void UniversalPrint(const T& value, ::std::ostream* os) {
+ UniversalPrinter<T>::Print(value, os);
+}
+
+#if GTEST_HAS_TR1_TUPLE
+typedef ::std::vector<string> Strings;
+
+// This helper template allows PrintTo() for tuples and
+// UniversalTersePrintTupleFieldsToStrings() to be defined by
+// induction on the number of tuple fields. The idea is that
+// TuplePrefixPrinter<N>::PrintPrefixTo(t, os) prints the first N
+// fields in tuple t, and can be defined in terms of
+// TuplePrefixPrinter<N - 1>.
+
+// The inductive case.
+template <size_t N>
+struct TuplePrefixPrinter {
+ // Prints the first N fields of a tuple.
+ template <typename Tuple>
+ static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
+ TuplePrefixPrinter<N - 1>::PrintPrefixTo(t, os);
+ *os << ", ";
+ UniversalPrinter<typename ::std::tr1::tuple_element<N - 1, Tuple>::type>
+ ::Print(::std::tr1::get<N - 1>(t), os);
+ }
+
+ // Tersely prints the first N fields of a tuple to a string vector,
+ // one element for each field.
+ template <typename Tuple>
+ static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
+ TuplePrefixPrinter<N - 1>::TersePrintPrefixToStrings(t, strings);
+ ::std::stringstream ss;
+ UniversalTersePrint(::std::tr1::get<N - 1>(t), &ss);
+ strings->push_back(ss.str());
+ }
+};
+
+// Base cases.
+template <>
+struct TuplePrefixPrinter<0> {
+ template <typename Tuple>
+ static void PrintPrefixTo(const Tuple&, ::std::ostream*) {}
+
+ template <typename Tuple>
+ static void TersePrintPrefixToStrings(const Tuple&, Strings*) {}
+};
+// We have to specialize the entire TuplePrefixPrinter<> class
+// template here, even though the definition of
+// TersePrintPrefixToStrings() is the same as the generic version, as
+// Embarcadero (formerly CodeGear, formerly Borland) C++ doesn't
+// support specializing a method template of a class template.
+template <>
+struct TuplePrefixPrinter<1> {
+ template <typename Tuple>
+ static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
+ UniversalPrinter<typename ::std::tr1::tuple_element<0, Tuple>::type>::
+ Print(::std::tr1::get<0>(t), os);
+ }
+
+ template <typename Tuple>
+ static void TersePrintPrefixToStrings(const Tuple& t, Strings* strings) {
+ ::std::stringstream ss;
+ UniversalTersePrint(::std::tr1::get<0>(t), &ss);
+ strings->push_back(ss.str());
+ }
+};
+
+// Helper function for printing a tuple. T must be instantiated with
+// a tuple type.
+template <typename T>
+void PrintTupleTo(const T& t, ::std::ostream* os) {
+ *os << "(";
+ TuplePrefixPrinter< ::std::tr1::tuple_size<T>::value>::
+ PrintPrefixTo(t, os);
+ *os << ")";
+}
+
+// Prints the fields of a tuple tersely to a string vector, one
+// element for each field. See the comment before
+// UniversalTersePrint() for how we define "tersely".
+template <typename Tuple>
+Strings UniversalTersePrintTupleFieldsToStrings(const Tuple& value) {
+ Strings result;
+ TuplePrefixPrinter< ::std::tr1::tuple_size<Tuple>::value>::
+ TersePrintPrefixToStrings(value, &result);
+ return result;
+}
+#endif // GTEST_HAS_TR1_TUPLE
+
+} // namespace internal
+
+template <typename T>
+::std::string PrintToString(const T& value) {
+ ::std::stringstream ss;
+ internal::UniversalTersePrint(value, &ss);
+ return ss.str();
+}
+
+} // namespace testing
+
+#endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_
diff --git a/src/LLVM/utils/unittest/googletest/include/gtest/gtest-spi.h b/src/LLVM/utils/unittest/googletest/include/gtest/gtest-spi.h
index c41da48..b226e55 100644
--- a/src/LLVM/utils/unittest/googletest/include/gtest/gtest-spi.h
+++ b/src/LLVM/utils/unittest/googletest/include/gtest/gtest-spi.h
@@ -35,7 +35,7 @@
#ifndef GTEST_INCLUDE_GTEST_GTEST_SPI_H_
#define GTEST_INCLUDE_GTEST_GTEST_SPI_H_
-#include <gtest/gtest.h>
+#include "gtest/gtest.h"
namespace testing {
@@ -98,12 +98,12 @@
// The constructor remembers the arguments.
SingleFailureChecker(const TestPartResultArray* results,
TestPartResult::Type type,
- const char* substr);
+ const string& substr);
~SingleFailureChecker();
private:
const TestPartResultArray* const results_;
const TestPartResult::Type type_;
- const String substr_;
+ const string substr_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(SingleFailureChecker);
};
diff --git a/src/LLVM/utils/unittest/googletest/include/gtest/gtest-test-part.h b/src/LLVM/utils/unittest/googletest/include/gtest/gtest-test-part.h
index f714759..8aeea14 100644
--- a/src/LLVM/utils/unittest/googletest/include/gtest/gtest-test-part.h
+++ b/src/LLVM/utils/unittest/googletest/include/gtest/gtest-test-part.h
@@ -35,8 +35,8 @@
#include <iosfwd>
#include <vector>
-#include <gtest/internal/gtest-internal.h>
-#include <gtest/internal/gtest-string.h>
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
namespace testing {
diff --git a/src/LLVM/utils/unittest/googletest/include/gtest/gtest-typed-test.h b/src/LLVM/utils/unittest/googletest/include/gtest/gtest-typed-test.h
index 1ec8eb8..fe1e83b 100644
--- a/src/LLVM/utils/unittest/googletest/include/gtest/gtest-typed-test.h
+++ b/src/LLVM/utils/unittest/googletest/include/gtest/gtest-typed-test.h
@@ -146,8 +146,8 @@
#endif // 0
-#include <gtest/internal/gtest-port.h>
-#include <gtest/internal/gtest-type-util.h>
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-type-util.h"
// Implements typed tests.
@@ -157,16 +157,16 @@
//
// Expands to the name of the typedef for the type parameters of the
// given test case.
-#define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
+# define GTEST_TYPE_PARAMS_(TestCaseName) gtest_type_params_##TestCaseName##_
// The 'Types' template argument below must have spaces around it
// since some compilers may choke on '>>' when passing a template
// instance (e.g. Types<int>)
-#define TYPED_TEST_CASE(CaseName, Types) \
+# define TYPED_TEST_CASE(CaseName, Types) \
typedef ::testing::internal::TypeList< Types >::type \
GTEST_TYPE_PARAMS_(CaseName)
-#define TYPED_TEST(CaseName, TestName) \
+# define TYPED_TEST(CaseName, TestName) \
template <typename gtest_TypeParam_> \
class GTEST_TEST_CLASS_NAME_(CaseName, TestName) \
: public CaseName<gtest_TypeParam_> { \
@@ -175,7 +175,7 @@
typedef gtest_TypeParam_ TypeParam; \
virtual void TestBody(); \
}; \
- bool gtest_##CaseName##_##TestName##_registered_ = \
+ bool gtest_##CaseName##_##TestName##_registered_ GTEST_ATTRIBUTE_UNUSED_ = \
::testing::internal::TypeParameterizedTest< \
CaseName, \
::testing::internal::TemplateSel< \
@@ -196,31 +196,31 @@
// Expands to the namespace name that the type-parameterized tests for
// the given type-parameterized test case are defined in. The exact
// name of the namespace is subject to change without notice.
-#define GTEST_CASE_NAMESPACE_(TestCaseName) \
+# define GTEST_CASE_NAMESPACE_(TestCaseName) \
gtest_case_##TestCaseName##_
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Expands to the name of the variable used to remember the names of
// the defined tests in the given test case.
-#define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \
+# define GTEST_TYPED_TEST_CASE_P_STATE_(TestCaseName) \
gtest_typed_test_case_p_state_##TestCaseName##_
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE DIRECTLY.
//
// Expands to the name of the variable used to remember the names of
// the registered tests in the given test case.
-#define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \
+# define GTEST_REGISTERED_TEST_NAMES_(TestCaseName) \
gtest_registered_test_names_##TestCaseName##_
// The variables defined in the type-parameterized test macros are
// static as typically these macros are used in a .h file that can be
// #included in multiple translation units linked together.
-#define TYPED_TEST_CASE_P(CaseName) \
+# define TYPED_TEST_CASE_P(CaseName) \
static ::testing::internal::TypedTestCasePState \
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName)
-#define TYPED_TEST_P(CaseName, TestName) \
+# define TYPED_TEST_P(CaseName, TestName) \
namespace GTEST_CASE_NAMESPACE_(CaseName) { \
template <typename gtest_TypeParam_> \
class TestName : public CaseName<gtest_TypeParam_> { \
@@ -229,14 +229,14 @@
typedef gtest_TypeParam_ TypeParam; \
virtual void TestBody(); \
}; \
- static bool gtest_##TestName##_defined_ = \
+ static bool gtest_##TestName##_defined_ GTEST_ATTRIBUTE_UNUSED_ = \
GTEST_TYPED_TEST_CASE_P_STATE_(CaseName).AddTestName(\
__FILE__, __LINE__, #CaseName, #TestName); \
} \
template <typename gtest_TypeParam_> \
void GTEST_CASE_NAMESPACE_(CaseName)::TestName<gtest_TypeParam_>::TestBody()
-#define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \
+# define REGISTER_TYPED_TEST_CASE_P(CaseName, ...) \
namespace GTEST_CASE_NAMESPACE_(CaseName) { \
typedef ::testing::internal::Templates<__VA_ARGS__>::type gtest_AllTests_; \
} \
@@ -247,8 +247,8 @@
// The 'Types' template argument below must have spaces around it
// since some compilers may choke on '>>' when passing a template
// instance (e.g. Types<int>)
-#define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \
- bool gtest_##Prefix##_##CaseName = \
+# define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, CaseName, Types) \
+ bool gtest_##Prefix##_##CaseName GTEST_ATTRIBUTE_UNUSED_ = \
::testing::internal::TypeParameterizedTestCase<CaseName, \
GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \
::testing::internal::TypeList< Types >::type>::Register(\
diff --git a/src/LLVM/utils/unittest/googletest/include/gtest/gtest.h b/src/LLVM/utils/unittest/googletest/include/gtest/gtest.h
index 921fad1..1734c44 100644
--- a/src/LLVM/utils/unittest/googletest/include/gtest/gtest.h
+++ b/src/LLVM/utils/unittest/googletest/include/gtest/gtest.h
@@ -54,14 +54,15 @@
#include <limits>
#include <vector>
-#include <gtest/internal/gtest-internal.h>
-#include <gtest/internal/gtest-string.h>
-#include <gtest/gtest-death-test.h>
-#include <gtest/gtest-message.h>
-#include <gtest/gtest-param-test.h>
-#include <gtest/gtest_prod.h>
-#include <gtest/gtest-test-part.h>
-#include <gtest/gtest-typed-test.h>
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-string.h"
+#include "gtest/gtest-death-test.h"
+#include "gtest/gtest-message.h"
+#include "gtest/gtest-param-test.h"
+#include "gtest/gtest-printers.h"
+#include "gtest/gtest_prod.h"
+#include "gtest/gtest-test-part.h"
+#include "gtest/gtest-typed-test.h"
// Depending on the platform, different string classes are available.
// On Linux, in addition to ::std::string, Google also makes use of
@@ -136,6 +137,11 @@
// non-zero code otherwise.
GTEST_DECLARE_bool_(throw_on_failure);
+// When this flag is set with a "host:port" string, on supported
+// platforms test results are streamed to the specified port on
+// the specified host machine.
+GTEST_DECLARE_string_(stream_result_to);
+
// The upper limit for valid stack trace depths.
const int kMaxStackTraceDepth = 100;
@@ -147,7 +153,6 @@
class NoExecDeathTest;
class FinalSuccessChecker;
class GTestFlagSaver;
-class TestInfoImpl;
class TestResultAccessor;
class TestEventListenersAccessor;
class TestEventRepeater;
@@ -155,8 +160,6 @@
class UnitTestImpl* GetUnitTestImpl();
void ReportFailureInUnknownLocation(TestPartResult::Type result_type,
const String& message);
-class PrettyUnitTestResultPrinter;
-class XmlUnitTestResultPrinter;
// Converts a streamable value to a String. A NULL pointer is
// converted to "(null)". When the input value is a ::string,
@@ -172,6 +175,14 @@
} // namespace internal
+// The friend relationship of some of these classes is cyclic.
+// If we don't forward declare them the compiler might confuse the classes
+// in friendship clauses with same named classes on the scope.
+class Test;
+class TestCase;
+class TestInfo;
+class UnitTest;
+
// A class for indicating whether an assertion was successful. When
// the assertion wasn't successful, the AssertionResult object
// remembers a non-empty message that describes how it failed.
@@ -270,20 +281,33 @@
// assertion's expectation). When nothing has been streamed into the
// object, returns an empty string.
const char* message() const {
- return message_.get() != NULL && message_->c_str() != NULL ?
- message_->c_str() : "";
+ return message_.get() != NULL ? message_->c_str() : "";
}
// TODO(vladl@google.com): Remove this after making sure no clients use it.
// Deprecated; please use message() instead.
const char* failure_message() const { return message(); }
// Streams a custom failure message into this object.
- template <typename T> AssertionResult& operator<<(const T& value);
+ template <typename T> AssertionResult& operator<<(const T& value) {
+ AppendMessage(Message() << value);
+ return *this;
+ }
+
+ // Allows streaming basic output manipulators such as endl or flush into
+ // this object.
+ AssertionResult& operator<<(
+ ::std::ostream& (*basic_manipulator)(::std::ostream& stream)) {
+ AppendMessage(Message() << basic_manipulator);
+ return *this;
+ }
private:
- // No implementation - we want AssertionResult to be
- // copy-constructible but not assignable.
- void operator=(const AssertionResult& other);
+ // Appends the contents of message to message_.
+ void AppendMessage(const Message& a_message) {
+ if (message_.get() == NULL)
+ message_.reset(new ::std::string);
+ message_->append(a_message.GetString().c_str());
+ }
// Stores result of the assertion predicate.
bool success_;
@@ -291,19 +315,10 @@
// construct is not satisfied with the predicate's outcome.
// Referenced via a pointer to avoid taking too much stack frame space
// with test assertions.
- internal::scoped_ptr<internal::String> message_;
-}; // class AssertionResult
+ internal::scoped_ptr< ::std::string> message_;
-// Streams a custom failure message into this object.
-template <typename T>
-AssertionResult& AssertionResult::operator<<(const T& value) {
- Message msg;
- if (message_.get() != NULL)
- msg << *message_;
- msg << value;
- message_.reset(new internal::String(msg.GetString()));
- return *this;
-}
+ GTEST_DISALLOW_ASSIGN_(AssertionResult);
+};
// Makes a successful assertion result.
GTEST_API_ AssertionResult AssertionSuccess();
@@ -340,7 +355,7 @@
// Test is not copyable.
class GTEST_API_ Test {
public:
- friend class internal::TestInfoImpl;
+ friend class TestInfo;
// Defines types for pointers to functions that set up and tear down
// a test case.
@@ -417,6 +432,10 @@
// Sets up, executes, and tears down the test.
void Run();
+ // Deletes self. We deliberately pick an unusual name for this
+ // internal method to avoid clashing with names used in user TESTs.
+ void DeleteSelf_() { delete this; }
+
// Uses a GTestFlagSaver to save and restore all Google Test flags.
const internal::GTestFlagSaver* const gtest_flag_saver_;
@@ -531,7 +550,6 @@
friend class UnitTest;
friend class internal::DefaultGlobalTestPartResultReporter;
friend class internal::ExecDeathTest;
- friend class internal::TestInfoImpl;
friend class internal::TestResultAccessor;
friend class internal::UnitTestImpl;
friend class internal::WindowsDeathTest;
@@ -611,16 +629,26 @@
~TestInfo();
// Returns the test case name.
- const char* test_case_name() const;
+ const char* test_case_name() const { return test_case_name_.c_str(); }
// Returns the test name.
- const char* name() const;
+ const char* name() const { return name_.c_str(); }
- // Returns the test case comment.
- const char* test_case_comment() const;
+ // Returns the name of the parameter type, or NULL if this is not a typed
+ // or a type-parameterized test.
+ const char* type_param() const {
+ if (type_param_.get() != NULL)
+ return type_param_->c_str();
+ return NULL;
+ }
- // Returns the test comment.
- const char* comment() const;
+ // Returns the text representation of the value parameter, or NULL if this
+ // is not a value-parameterized test.
+ const char* value_param() const {
+ if (value_param_.get() != NULL)
+ return value_param_->c_str();
+ return NULL;
+ }
// Returns true if this test should run, that is if the test is not disabled
// (or it is disabled but the also_run_disabled_tests flag has been specified)
@@ -638,47 +666,70 @@
//
// For example, *A*:Foo.* is a filter that matches any string that
// contains the character 'A' or starts with "Foo.".
- bool should_run() const;
+ bool should_run() const { return should_run_; }
// Returns the result of the test.
- const TestResult* result() const;
+ const TestResult* result() const { return &result_; }
private:
+
#if GTEST_HAS_DEATH_TEST
friend class internal::DefaultDeathTestFactory;
#endif // GTEST_HAS_DEATH_TEST
friend class Test;
friend class TestCase;
- friend class internal::TestInfoImpl;
friend class internal::UnitTestImpl;
friend TestInfo* internal::MakeAndRegisterTestInfo(
const char* test_case_name, const char* name,
- const char* test_case_comment, const char* comment,
+ const char* type_param,
+ const char* value_param,
internal::TypeId fixture_class_id,
Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc,
internal::TestFactoryBase* factory);
- // Returns true if this test matches the user-specified filter.
- bool matches_filter() const;
-
- // Increments the number of death tests encountered in this test so
- // far.
- int increment_death_test_count();
-
- // Accessors for the implementation object.
- internal::TestInfoImpl* impl() { return impl_; }
- const internal::TestInfoImpl* impl() const { return impl_; }
-
// Constructs a TestInfo object. The newly constructed instance assumes
// ownership of the factory object.
TestInfo(const char* test_case_name, const char* name,
- const char* test_case_comment, const char* comment,
+ const char* a_type_param,
+ const char* a_value_param,
internal::TypeId fixture_class_id,
internal::TestFactoryBase* factory);
- // An opaque implementation object.
- internal::TestInfoImpl* impl_;
+ // Increments the number of death tests encountered in this test so
+ // far.
+ int increment_death_test_count() {
+ return result_.increment_death_test_count();
+ }
+
+ // Creates the test object, runs it, records its result, and then
+ // deletes it.
+ void Run();
+
+ static void ClearTestResult(TestInfo* test_info) {
+ test_info->result_.Clear();
+ }
+
+ // These fields are immutable properties of the test.
+ const std::string test_case_name_; // Test case name
+ const std::string name_; // Test name
+ // Name of the parameter type, or NULL if this is not a typed or a
+ // type-parameterized test.
+ const internal::scoped_ptr<const ::std::string> type_param_;
+ // Text representation of the value parameter, or NULL if this is not a
+ // value-parameterized test.
+ const internal::scoped_ptr<const ::std::string> value_param_;
+ const internal::TypeId fixture_class_id_; // ID of the test fixture class
+ bool should_run_; // True iff this test should run
+ bool is_disabled_; // True iff this test is disabled
+ bool matches_filter_; // True if this test matches the
+ // user-specified filter.
+ internal::TestFactoryBase* const factory_; // The factory that creates
+ // the test object
+
+ // This field is mutable and needs to be reset before running the
+ // test for the second time.
+ TestResult result_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfo);
};
@@ -696,9 +747,11 @@
// Arguments:
//
// name: name of the test case
+ // a_type_param: the name of the test's type parameter, or NULL if
+ // this is not a type-parameterized test.
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
- TestCase(const char* name, const char* comment,
+ TestCase(const char* name, const char* a_type_param,
Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc);
@@ -708,8 +761,13 @@
// Gets the name of the TestCase.
const char* name() const { return name_.c_str(); }
- // Returns the test case comment.
- const char* comment() const { return comment_.c_str(); }
+ // Returns the name of the parameter type, or NULL if this is not a
+ // type-parameterized test case.
+ const char* type_param() const {
+ if (type_param_.get() != NULL)
+ return type_param_->c_str();
+ return NULL;
+ }
// Returns true if any test in this test case should run.
bool should_run() const { return should_run_; }
@@ -776,17 +834,33 @@
// Runs every test in this TestCase.
void Run();
+ // Runs SetUpTestCase() for this TestCase. This wrapper is needed
+ // for catching exceptions thrown from SetUpTestCase().
+ void RunSetUpTestCase() { (*set_up_tc_)(); }
+
+ // Runs TearDownTestCase() for this TestCase. This wrapper is
+ // needed for catching exceptions thrown from TearDownTestCase().
+ void RunTearDownTestCase() { (*tear_down_tc_)(); }
+
// Returns true iff test passed.
- static bool TestPassed(const TestInfo * test_info);
+ static bool TestPassed(const TestInfo* test_info) {
+ return test_info->should_run() && test_info->result()->Passed();
+ }
// Returns true iff test failed.
- static bool TestFailed(const TestInfo * test_info);
+ static bool TestFailed(const TestInfo* test_info) {
+ return test_info->should_run() && test_info->result()->Failed();
+ }
// Returns true iff test is disabled.
- static bool TestDisabled(const TestInfo * test_info);
+ static bool TestDisabled(const TestInfo* test_info) {
+ return test_info->is_disabled_;
+ }
// Returns true if the given test should run.
- static bool ShouldRunTest(const TestInfo *test_info);
+ static bool ShouldRunTest(const TestInfo* test_info) {
+ return test_info->should_run();
+ }
// Shuffles the tests in this test case.
void ShuffleTests(internal::Random* random);
@@ -796,8 +870,9 @@
// Name of the test case.
internal::String name_;
- // Comment on the test case.
- internal::String comment_;
+ // Name of the parameter type, or NULL if this is not a typed or a
+ // type-parameterized test.
+ const internal::scoped_ptr<const ::std::string> type_param_;
// The vector of TestInfos in their original order. It owns the
// elements in the vector.
std::vector<TestInfo*> test_info_list_;
@@ -876,7 +951,7 @@
// Fired before the test starts.
virtual void OnTestStart(const TestInfo& test_info) = 0;
- // Fired after a failed assertion or a SUCCESS().
+ // Fired after a failed assertion or a SUCCEED() invocation.
virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0;
// Fired after the test ends.
@@ -961,10 +1036,10 @@
private:
friend class TestCase;
+ friend class TestInfo;
friend class internal::DefaultGlobalTestPartResultReporter;
friend class internal::NoExecDeathTest;
friend class internal::TestEventListenersAccessor;
- friend class internal::TestInfoImpl;
friend class internal::UnitTestImpl;
// Returns repeater that broadcasts the TestEventListener events to all
@@ -1206,30 +1281,6 @@
namespace internal {
-// These overloaded versions handle ::std::string and ::std::wstring.
-GTEST_API_ inline String FormatForFailureMessage(const ::std::string& str) {
- return (Message() << '"' << str << '"').GetString();
-}
-
-#if GTEST_HAS_STD_WSTRING
-GTEST_API_ inline String FormatForFailureMessage(const ::std::wstring& wstr) {
- return (Message() << "L\"" << wstr << '"').GetString();
-}
-#endif // GTEST_HAS_STD_WSTRING
-
-// These overloaded versions handle ::string and ::wstring.
-#if GTEST_HAS_GLOBAL_STRING
-GTEST_API_ inline String FormatForFailureMessage(const ::string& str) {
- return (Message() << '"' << str << '"').GetString();
-}
-#endif // GTEST_HAS_GLOBAL_STRING
-
-#if GTEST_HAS_GLOBAL_WSTRING
-GTEST_API_ inline String FormatForFailureMessage(const ::wstring& wstr) {
- return (Message() << "L\"" << wstr << '"').GetString();
-}
-#endif // GTEST_HAS_GLOBAL_WSTRING
-
// Formats a comparison assertion (e.g. ASSERT_EQ, EXPECT_LT, and etc)
// operand to be used in a failure message. The type (but not value)
// of the other operand may affect the format. This allows us to
@@ -1245,7 +1296,9 @@
template <typename T1, typename T2>
String FormatForComparisonFailureMessage(const T1& value,
const T2& /* other_operand */) {
- return FormatForFailureMessage(value);
+ // C++Builder compiles this incorrectly if the namespace isn't explicitly
+ // given.
+ return ::testing::PrintToString(value);
}
// The helper function for {ASSERT|EXPECT}_EQ.
@@ -1255,9 +1308,11 @@
const T1& expected,
const T2& actual) {
#ifdef _MSC_VER
-#pragma warning(push) // Saves the current warning state.
-#pragma warning(disable:4389) // Temporarily disables warning on
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4389) // Temporarily disables warning on
// signed/unsigned mismatch.
+#pragma warning(disable:4805) // Temporarily disables warning on
+ // unsafe mix of types
#endif
if (expected == actual) {
@@ -1265,7 +1320,7 @@
}
#ifdef _MSC_VER
-#pragma warning(pop) // Restores the warning state.
+# pragma warning(pop) // Restores the warning state.
#endif
return EqFailure(expected_expression,
@@ -1316,7 +1371,7 @@
};
// This specialization is used when the first argument to ASSERT_EQ()
-// is a null pointer literal.
+// is a null pointer literal, like NULL, false, or 0.
template <>
class EqHelper<true> {
public:
@@ -1325,24 +1380,38 @@
// NOT a pointer, e.g. ASSERT_EQ(0, AnIntFunction()) or
// EXPECT_EQ(false, a_bool).
template <typename T1, typename T2>
- static AssertionResult Compare(const char* expected_expression,
- const char* actual_expression,
- const T1& expected,
- const T2& actual) {
+ static AssertionResult Compare(
+ const char* expected_expression,
+ const char* actual_expression,
+ const T1& expected,
+ const T2& actual,
+ // The following line prevents this overload from being considered if T2
+ // is not a pointer type. We need this because ASSERT_EQ(NULL, my_ptr)
+ // expands to Compare("", "", NULL, my_ptr), which requires a conversion
+ // to match the Secret* in the other overload, which would otherwise make
+ // this template match better.
+ typename EnableIf<!is_pointer<T2>::value>::type* = 0) {
return CmpHelperEQ(expected_expression, actual_expression, expected,
actual);
}
- // This version will be picked when the second argument to
- // ASSERT_EQ() is a pointer, e.g. ASSERT_EQ(NULL, a_pointer).
- template <typename T1, typename T2>
- static AssertionResult Compare(const char* expected_expression,
- const char* actual_expression,
- const T1& /* expected */,
- T2* actual) {
+ // This version will be picked when the second argument to ASSERT_EQ() is a
+ // pointer, e.g. ASSERT_EQ(NULL, a_pointer).
+ template <typename T>
+ static AssertionResult Compare(
+ const char* expected_expression,
+ const char* actual_expression,
+ // We used to have a second template parameter instead of Secret*. That
+ // template parameter would deduce to 'long', making this a better match
+ // than the first overload even without the first overload's EnableIf.
+ // Unfortunately, gcc with -Wconversion-null warns when "passing NULL to
+ // non-pointer argument" (even a deduced integral argument), so the old
+ // implementation caused warnings in user code.
+ Secret* /* expected (NULL) */,
+ T* actual) {
// We already know that 'expected' is a null pointer.
return CmpHelperEQ(expected_expression, actual_expression,
- static_cast<T2*>(NULL), actual);
+ static_cast<T*>(NULL), actual);
}
};
@@ -1363,11 +1432,10 @@
if (val1 op val2) {\
return AssertionSuccess();\
} else {\
- Message msg;\
- msg << "Expected: (" << expr1 << ") " #op " (" << expr2\
+ return AssertionFailure() \
+ << "Expected: (" << expr1 << ") " #op " (" << expr2\
<< "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
<< " vs " << FormatForComparisonFailureMessage(val2, val1);\
- return AssertionFailure(msg);\
}\
}\
GTEST_API_ AssertionResult CmpHelper##op_name(\
@@ -1495,18 +1563,18 @@
return AssertionSuccess();
}
- StrStream expected_ss;
+ ::std::stringstream expected_ss;
expected_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
<< expected;
- StrStream actual_ss;
+ ::std::stringstream actual_ss;
actual_ss << std::setprecision(std::numeric_limits<RawType>::digits10 + 2)
<< actual;
return EqFailure(expected_expression,
actual_expression,
- StrStreamToString(&expected_ss),
- StrStreamToString(&actual_ss),
+ StringStreamToString(&expected_ss),
+ StringStreamToString(&actual_ss),
false);
}
@@ -1564,9 +1632,13 @@
} // namespace internal
#if GTEST_HAS_PARAM_TEST
-// The abstract base class that all value-parameterized tests inherit from.
+// The pure interface class that all value-parameterized tests inherit from.
+// A value-parameterized class must inherit from both ::testing::Test and
+// ::testing::WithParamInterface. In most cases that just means inheriting
+// from ::testing::TestWithParam, but more complicated test hierarchies
+// may need to inherit from Test and WithParamInterface at different levels.
//
-// This class adds support for accessing the test parameter value via
+// This interface has support for accessing the test parameter value via
// the GetParam() method.
//
// Use it with one of the parameter generator defining functions, like Range(),
@@ -1595,12 +1667,16 @@
// INSTANTIATE_TEST_CASE_P(OneToTenRange, FooTest, ::testing::Range(1, 10));
template <typename T>
-class TestWithParam : public Test {
+class WithParamInterface {
public:
typedef T ParamType;
+ virtual ~WithParamInterface() {}
// The current parameter value. Is also available in the test fixture's
- // constructor.
+ // constructor. This member function is non-static, even though it only
+ // references static data, to reduce the opportunity for incorrect uses
+ // like writing 'WithParamInterface<bool>::GetParam()' for a test that
+ // uses a fixture whose parameter type is int.
const ParamType& GetParam() const { return *parameter_; }
private:
@@ -1613,12 +1689,19 @@
// Static value used for accessing parameter during a test lifetime.
static const ParamType* parameter_;
- // TestClass must be a subclass of TestWithParam<T>.
+ // TestClass must be a subclass of WithParamInterface<T> and Test.
template <class TestClass> friend class internal::ParameterizedTestFactory;
};
template <typename T>
-const T* TestWithParam<T>::parameter_ = NULL;
+const T* WithParamInterface<T>::parameter_ = NULL;
+
+// Most value-parameterized classes can ignore the existence of
+// WithParamInterface, and can just inherit from ::testing::TestWithParam.
+
+template <typename T>
+class TestWithParam : public Test, public WithParamInterface<T> {
+};
#endif // GTEST_HAS_PARAM_TEST
@@ -1650,13 +1733,19 @@
// Generates a nonfatal failure with a generic message.
#define ADD_FAILURE() GTEST_NONFATAL_FAILURE_("Failed")
+// Generates a nonfatal failure at the given source file location with
+// a generic message.
+#define ADD_FAILURE_AT(file, line) \
+ GTEST_MESSAGE_AT_(file, line, "Failed", \
+ ::testing::TestPartResult::kNonFatalFailure)
+
// Generates a fatal failure with a generic message.
#define GTEST_FAIL() GTEST_FATAL_FAILURE_("Failed")
// Define this macro to 1 to omit the definition of FAIL(), which is a
// generic name and clashes with some other libraries.
#if !GTEST_DONT_DEFINE_FAIL
-#define FAIL() GTEST_FAIL()
+# define FAIL() GTEST_FAIL()
#endif
// Generates a success with a generic message.
@@ -1665,7 +1754,7 @@
// Define this macro to 1 to omit the definition of SUCCEED(), which
// is a generic name and clashes with some other libraries.
#if !GTEST_DONT_DEFINE_SUCCEED
-#define SUCCEED() GTEST_SUCCEED()
+# define SUCCEED() GTEST_SUCCEED()
#endif
// Macros for testing exceptions.
@@ -1708,7 +1797,7 @@
// Includes the auto-generated header that implements a family of
// generic predicate assertion macros.
-#include <gtest/gtest_pred_impl.h>
+#include "gtest/gtest_pred_impl.h"
// Macros for testing equalities and inequalities.
//
@@ -1771,21 +1860,48 @@
#define EXPECT_GT(val1, val2) \
EXPECT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
-#define ASSERT_EQ(expected, actual) \
+#define GTEST_ASSERT_EQ(expected, actual) \
ASSERT_PRED_FORMAT2(::testing::internal:: \
EqHelper<GTEST_IS_NULL_LITERAL_(expected)>::Compare, \
expected, actual)
-#define ASSERT_NE(val1, val2) \
+#define GTEST_ASSERT_NE(val1, val2) \
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperNE, val1, val2)
-#define ASSERT_LE(val1, val2) \
+#define GTEST_ASSERT_LE(val1, val2) \
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLE, val1, val2)
-#define ASSERT_LT(val1, val2) \
+#define GTEST_ASSERT_LT(val1, val2) \
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperLT, val1, val2)
-#define ASSERT_GE(val1, val2) \
+#define GTEST_ASSERT_GE(val1, val2) \
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGE, val1, val2)
-#define ASSERT_GT(val1, val2) \
+#define GTEST_ASSERT_GT(val1, val2) \
ASSERT_PRED_FORMAT2(::testing::internal::CmpHelperGT, val1, val2)
+// Define macro GTEST_DONT_DEFINE_ASSERT_XY to 1 to omit the definition of
+// ASSERT_XY(), which clashes with some users' own code.
+
+#if !GTEST_DONT_DEFINE_ASSERT_EQ
+# define ASSERT_EQ(val1, val2) GTEST_ASSERT_EQ(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_NE
+# define ASSERT_NE(val1, val2) GTEST_ASSERT_NE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LE
+# define ASSERT_LE(val1, val2) GTEST_ASSERT_LE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_LT
+# define ASSERT_LT(val1, val2) GTEST_ASSERT_LT(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GE
+# define ASSERT_GE(val1, val2) GTEST_ASSERT_GE(val1, val2)
+#endif
+
+#if !GTEST_DONT_DEFINE_ASSERT_GT
+# define ASSERT_GT(val1, val2) GTEST_ASSERT_GT(val1, val2)
+#endif
+
// C String Comparisons. All tests treat NULL and any non-NULL string
// as different. Two NULLs are equal.
//
@@ -1882,16 +1998,16 @@
// expected result and the actual result with both a human-readable
// string representation of the error, if available, as well as the
// hex result code.
-#define EXPECT_HRESULT_SUCCEEDED(expr) \
+# define EXPECT_HRESULT_SUCCEEDED(expr) \
EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
-#define ASSERT_HRESULT_SUCCEEDED(expr) \
+# define ASSERT_HRESULT_SUCCEEDED(expr) \
ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTSuccess, (expr))
-#define EXPECT_HRESULT_FAILED(expr) \
+# define EXPECT_HRESULT_FAILED(expr) \
EXPECT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
-#define ASSERT_HRESULT_FAILED(expr) \
+# define ASSERT_HRESULT_FAILED(expr) \
ASSERT_PRED_FORMAT1(::testing::internal::IsHRESULTFailure, (expr))
#endif // GTEST_OS_WINDOWS
@@ -1926,17 +2042,6 @@
::testing::internal::ScopedTrace GTEST_CONCAT_TOKEN_(gtest_trace_, __LINE__)(\
__FILE__, __LINE__, ::testing::Message() << (message))
-namespace internal {
-
-// This template is declared, but intentionally undefined.
-template <typename T1, typename T2>
-struct StaticAssertTypeEqHelper;
-
-template <typename T>
-struct StaticAssertTypeEqHelper<T, T> {};
-
-} // namespace internal
-
// Compile-time assertion for type equality.
// StaticAssertTypeEq<type1, type2>() compiles iff type1 and type2 are
// the same type. The value it returns is not interesting.
@@ -1969,7 +2074,7 @@
// to cause a compiler error.
template <typename T1, typename T2>
bool StaticAssertTypeEq() {
- internal::StaticAssertTypeEqHelper<T1, T2>();
+ (void)internal::StaticAssertTypeEqHelper<T1, T2>();
return true;
}
@@ -2005,7 +2110,7 @@
// Define this macro to 1 to omit the definition of TEST(), which
// is a generic name and clashes with some other libraries.
#if !GTEST_DONT_DEFINE_TEST
-#define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name)
+# define TEST(test_case_name, test_name) GTEST_TEST(test_case_name, test_name)
#endif
// Defines a test that uses a test fixture.
diff --git a/src/LLVM/utils/unittest/googletest/include/gtest/gtest_pred_impl.h b/src/LLVM/utils/unittest/googletest/include/gtest/gtest_pred_impl.h
index e1e2f8c..3805f85 100644
--- a/src/LLVM/utils/unittest/googletest/include/gtest/gtest_pred_impl.h
+++ b/src/LLVM/utils/unittest/googletest/include/gtest/gtest_pred_impl.h
@@ -27,7 +27,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// This file is AUTOMATICALLY GENERATED on 10/02/2008 by command
+// This file is AUTOMATICALLY GENERATED on 09/24/2010 by command
// 'gen_gtest_pred_impl.py 5'. DO NOT EDIT BY HAND!
//
// Implements a family of generic predicate assertion macros.
@@ -37,7 +37,7 @@
// Makes sure this header is not included before gtest.h.
#ifndef GTEST_INCLUDE_GTEST_GTEST_H_
-#error Do not include gtest_pred_impl.h directly. Include gtest.h instead.
+# error Do not include gtest_pred_impl.h directly. Include gtest.h instead.
#endif // GTEST_INCLUDE_GTEST_GTEST_H_
// This header implements a family of generic predicate assertion
@@ -90,11 +90,9 @@
const T1& v1) {
if (pred(v1)) return AssertionSuccess();
- Message msg;
- msg << pred_text << "("
- << e1 << ") evaluates to false, where"
- << "\n" << e1 << " evaluates to " << v1;
- return AssertionFailure(msg);
+ return AssertionFailure() << pred_text << "("
+ << e1 << ") evaluates to false, where"
+ << "\n" << e1 << " evaluates to " << v1;
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT1.
@@ -136,13 +134,11 @@
const T2& v2) {
if (pred(v1, v2)) return AssertionSuccess();
- Message msg;
- msg << pred_text << "("
- << e1 << ", "
- << e2 << ") evaluates to false, where"
- << "\n" << e1 << " evaluates to " << v1
- << "\n" << e2 << " evaluates to " << v2;
- return AssertionFailure(msg);
+ return AssertionFailure() << pred_text << "("
+ << e1 << ", "
+ << e2 << ") evaluates to false, where"
+ << "\n" << e1 << " evaluates to " << v1
+ << "\n" << e2 << " evaluates to " << v2;
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT2.
@@ -189,15 +185,13 @@
const T3& v3) {
if (pred(v1, v2, v3)) return AssertionSuccess();
- Message msg;
- msg << pred_text << "("
- << e1 << ", "
- << e2 << ", "
- << e3 << ") evaluates to false, where"
- << "\n" << e1 << " evaluates to " << v1
- << "\n" << e2 << " evaluates to " << v2
- << "\n" << e3 << " evaluates to " << v3;
- return AssertionFailure(msg);
+ return AssertionFailure() << pred_text << "("
+ << e1 << ", "
+ << e2 << ", "
+ << e3 << ") evaluates to false, where"
+ << "\n" << e1 << " evaluates to " << v1
+ << "\n" << e2 << " evaluates to " << v2
+ << "\n" << e3 << " evaluates to " << v3;
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT3.
@@ -249,17 +243,15 @@
const T4& v4) {
if (pred(v1, v2, v3, v4)) return AssertionSuccess();
- Message msg;
- msg << pred_text << "("
- << e1 << ", "
- << e2 << ", "
- << e3 << ", "
- << e4 << ") evaluates to false, where"
- << "\n" << e1 << " evaluates to " << v1
- << "\n" << e2 << " evaluates to " << v2
- << "\n" << e3 << " evaluates to " << v3
- << "\n" << e4 << " evaluates to " << v4;
- return AssertionFailure(msg);
+ return AssertionFailure() << pred_text << "("
+ << e1 << ", "
+ << e2 << ", "
+ << e3 << ", "
+ << e4 << ") evaluates to false, where"
+ << "\n" << e1 << " evaluates to " << v1
+ << "\n" << e2 << " evaluates to " << v2
+ << "\n" << e3 << " evaluates to " << v3
+ << "\n" << e4 << " evaluates to " << v4;
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT4.
@@ -316,19 +308,17 @@
const T5& v5) {
if (pred(v1, v2, v3, v4, v5)) return AssertionSuccess();
- Message msg;
- msg << pred_text << "("
- << e1 << ", "
- << e2 << ", "
- << e3 << ", "
- << e4 << ", "
- << e5 << ") evaluates to false, where"
- << "\n" << e1 << " evaluates to " << v1
- << "\n" << e2 << " evaluates to " << v2
- << "\n" << e3 << " evaluates to " << v3
- << "\n" << e4 << " evaluates to " << v4
- << "\n" << e5 << " evaluates to " << v5;
- return AssertionFailure(msg);
+ return AssertionFailure() << pred_text << "("
+ << e1 << ", "
+ << e2 << ", "
+ << e3 << ", "
+ << e4 << ", "
+ << e5 << ") evaluates to false, where"
+ << "\n" << e1 << " evaluates to " << v1
+ << "\n" << e2 << " evaluates to " << v2
+ << "\n" << e3 << " evaluates to " << v3
+ << "\n" << e4 << " evaluates to " << v4
+ << "\n" << e5 << " evaluates to " << v5;
}
// Internal macro for implementing {EXPECT|ASSERT}_PRED_FORMAT5.
diff --git a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h
index e433084..1d9f83b 100644
--- a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h
+++ b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-death-test-internal.h
@@ -37,7 +37,9 @@
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
-#include <gtest/internal/gtest-internal.h>
+#include "gtest/internal/gtest-internal.h"
+
+#include <stdio.h>
namespace testing {
namespace internal {
@@ -96,8 +98,12 @@
// test, then wait for it to complete.
enum TestRole { OVERSEE_TEST, EXECUTE_TEST };
- // An enumeration of the two reasons that a test might be aborted.
- enum AbortReason { TEST_ENCOUNTERED_RETURN_STATEMENT, TEST_DID_NOT_DIE };
+ // An enumeration of the three reasons that a test might be aborted.
+ enum AbortReason {
+ TEST_ENCOUNTERED_RETURN_STATEMENT,
+ TEST_THREW_EXCEPTION,
+ TEST_DID_NOT_DIE
+ };
// Assumes one of the above roles.
virtual TestRole AssumeRole() = 0;
@@ -149,9 +155,34 @@
// by a signal, or exited normally with a nonzero exit code.
GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
+// Traps C++ exceptions escaping statement and reports them as test
+// failures. Note that trapping SEH exceptions is not implemented here.
+# if GTEST_HAS_EXCEPTIONS
+# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+ try { \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+ } catch (const ::std::exception& gtest_exception) { \
+ fprintf(\
+ stderr, \
+ "\n%s: Caught std::exception-derived exception escaping the " \
+ "death test statement. Exception message: %s\n", \
+ ::testing::internal::FormatFileLocation(__FILE__, __LINE__).c_str(), \
+ gtest_exception.what()); \
+ fflush(stderr); \
+ death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+ } catch (...) { \
+ death_test->Abort(::testing::internal::DeathTest::TEST_THREW_EXCEPTION); \
+ }
+
+# else
+# define GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, death_test) \
+ GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement)
+
+# endif
+
// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
// ASSERT_EXIT*, and EXPECT_EXIT*.
-#define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
+# define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \
const ::testing::internal::RE& gtest_regex = (regex); \
@@ -172,10 +203,12 @@
case ::testing::internal::DeathTest::EXECUTE_TEST: { \
::testing::internal::DeathTest::ReturnSentinel \
gtest_sentinel(gtest_dt); \
- GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
+ GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
break; \
} \
+ default: \
+ break; \
} \
} \
} else \
@@ -254,7 +287,7 @@
// statement unconditionally returns or throws. The Message constructor at
// the end allows the syntax of streaming additional messages into the
// macro, for compilational compatibility with EXPECT_DEATH/ASSERT_DEATH.
-#define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \
+# define GTEST_UNSUPPORTED_DEATH_TEST_(statement, regex, terminator) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \
GTEST_LOG_(WARNING) \
diff --git a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h
index 4b76d79..823c6bd 100644
--- a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h
+++ b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h
@@ -40,7 +40,7 @@
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_FILEPATH_H_
-#include <gtest/internal/gtest-string.h>
+#include "gtest/internal/gtest-string.h"
namespace testing {
namespace internal {
@@ -196,7 +196,7 @@
void Normalize();
- // Returns a pointer to the last occurence of a valid path separator in
+ // Returns a pointer to the last occurrence of a valid path separator in
// the FilePath. On Windows, for example, both '/' and '\' are valid path
// separators. Returns NULL if no path separator was found.
const char* FindLastPathSeparator() const;
diff --git a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h
index 855b215..65a2101 100644
--- a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h
+++ b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-internal-inl.h
@@ -41,12 +41,12 @@
// part of Google Test's implementation; otherwise it's undefined.
#if !GTEST_IMPLEMENTATION_
// A user is trying to include this from his code - just say no.
-#error "gtest-internal-inl.h is part of Google Test's internal implementation."
-#error "It must not be included except by Google Test itself."
+# error "gtest-internal-inl.h is part of Google Test's internal implementation."
+# error "It must not be included except by Google Test itself."
#endif // GTEST_IMPLEMENTATION_
#ifndef _WIN32_WCE
-#include <errno.h>
+# include <errno.h>
#endif // !_WIN32_WCE
#include <stddef.h>
#include <stdlib.h> // For strtoll/_strtoul64/malloc/free.
@@ -56,14 +56,14 @@
#include <string>
#include <vector>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-port.h"
#if GTEST_OS_WINDOWS
-#include <windows.h> // For DWORD.
+# include <windows.h> // NOLINT
#endif // GTEST_OS_WINDOWS
-#include <gtest/gtest.h> // NOLINT
-#include <gtest/gtest-spi.h>
+#include "gtest/gtest.h" // NOLINT
+#include "gtest/gtest-spi.h"
namespace testing {
@@ -93,6 +93,7 @@
const char kRepeatFlag[] = "repeat";
const char kShuffleFlag[] = "shuffle";
const char kStackTraceDepthFlag[] = "stack_trace_depth";
+const char kStreamResultToFlag[] = "stream_result_to";
const char kThrowOnFailureFlag[] = "throw_on_failure";
// A valid random seed must be in [1, kMaxRandomSeed].
@@ -165,6 +166,7 @@
repeat_ = GTEST_FLAG(repeat);
shuffle_ = GTEST_FLAG(shuffle);
stack_trace_depth_ = GTEST_FLAG(stack_trace_depth);
+ stream_result_to_ = GTEST_FLAG(stream_result_to);
throw_on_failure_ = GTEST_FLAG(throw_on_failure);
}
@@ -185,6 +187,7 @@
GTEST_FLAG(repeat) = repeat_;
GTEST_FLAG(shuffle) = shuffle_;
GTEST_FLAG(stack_trace_depth) = stack_trace_depth_;
+ GTEST_FLAG(stream_result_to) = stream_result_to_;
GTEST_FLAG(throw_on_failure) = throw_on_failure_;
}
private:
@@ -205,6 +208,7 @@
internal::Int32 repeat_;
bool shuffle_;
internal::Int32 stack_trace_depth_;
+ String stream_result_to_;
bool throw_on_failure_;
} GTEST_ATTRIBUTE_UNUSED_;
@@ -267,7 +271,14 @@
// the given predicate.
template <class Container, typename Predicate>
inline int CountIf(const Container& c, Predicate predicate) {
- return static_cast<int>(std::count_if(c.begin(), c.end(), predicate));
+ // Implemented as an explicit loop since std::count_if() in libCstd on
+ // Solaris has a non-standard signature.
+ int count = 0;
+ for (typename Container::const_iterator it = c.begin(); it != c.end(); ++it) {
+ if (predicate(*it))
+ ++count;
+ }
+ return count;
}
// Applies a function/functor to each element in the container.
@@ -340,85 +351,6 @@
String key_;
};
-class TestInfoImpl {
- public:
- TestInfoImpl(TestInfo* parent, const char* test_case_name,
- const char* name, const char* test_case_comment,
- const char* comment, TypeId fixture_class_id,
- internal::TestFactoryBase* factory);
- ~TestInfoImpl();
-
- // Returns true if this test should run.
- bool should_run() const { return should_run_; }
-
- // Sets the should_run member.
- void set_should_run(bool should) { should_run_ = should; }
-
- // Returns true if this test is disabled. Disabled tests are not run.
- bool is_disabled() const { return is_disabled_; }
-
- // Sets the is_disabled member.
- void set_is_disabled(bool is) { is_disabled_ = is; }
-
- // Returns true if this test matches the filter specified by the user.
- bool matches_filter() const { return matches_filter_; }
-
- // Sets the matches_filter member.
- void set_matches_filter(bool matches) { matches_filter_ = matches; }
-
- // Returns the test case name.
- const char* test_case_name() const { return test_case_name_.c_str(); }
-
- // Returns the test name.
- const char* name() const { return name_.c_str(); }
-
- // Returns the test case comment.
- const char* test_case_comment() const { return test_case_comment_.c_str(); }
-
- // Returns the test comment.
- const char* comment() const { return comment_.c_str(); }
-
- // Returns the ID of the test fixture class.
- TypeId fixture_class_id() const { return fixture_class_id_; }
-
- // Returns the test result.
- TestResult* result() { return &result_; }
- const TestResult* result() const { return &result_; }
-
- // Creates the test object, runs it, records its result, and then
- // deletes it.
- void Run();
-
- // Clears the test result.
- void ClearResult() { result_.Clear(); }
-
- // Clears the test result in the given TestInfo object.
- static void ClearTestResult(TestInfo * test_info) {
- test_info->impl()->ClearResult();
- }
-
- private:
- // These fields are immutable properties of the test.
- TestInfo* const parent_; // The owner of this object
- const String test_case_name_; // Test case name
- const String name_; // Test name
- const String test_case_comment_; // Test case comment
- const String comment_; // Test comment
- const TypeId fixture_class_id_; // ID of the test fixture class
- bool should_run_; // True iff this test should run
- bool is_disabled_; // True iff this test is disabled
- bool matches_filter_; // True if this test matches the
- // user-specified filter.
- internal::TestFactoryBase* const factory_; // The factory that creates
- // the test object
-
- // This field is mutable and needs to be reset before running the
- // test for the second time.
- TestResult result_;
-
- GTEST_DISALLOW_COPY_AND_ASSIGN_(TestInfoImpl);
-};
-
// Class UnitTestOptions.
//
// This class contains functions for processing options the user
@@ -682,10 +614,12 @@
// Arguments:
//
// test_case_name: name of the test case
+ // type_param: the name of the test's type parameter, or NULL if
+ // this is not a typed or a type-parameterized test.
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
TestCase* GetTestCase(const char* test_case_name,
- const char* comment,
+ const char* type_param,
Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc);
@@ -698,7 +632,7 @@
// test_info: the TestInfo object
void AddTestInfo(Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc,
- TestInfo * test_info) {
+ TestInfo* test_info) {
// In order to support thread-safe death tests, we need to
// remember the original working directory when the test program
// was first invoked. We cannot do this in RUN_ALL_TESTS(), as
@@ -713,7 +647,7 @@
}
GetTestCase(test_info->test_case_name(),
- test_info->test_case_comment(),
+ test_info->type_param(),
set_up_tc,
tear_down_tc)->AddTestInfo(test_info);
}
@@ -739,24 +673,26 @@
}
// Registers all parameterized tests defined using TEST_P and
- // INSTANTIATE_TEST_P, creating regular tests for each test/parameter
- // combination. This method can be called more then once; it has
- // guards protecting from registering the tests more then once.
- // If value-parameterized tests are disabled, RegisterParameterizedTests
- // is present but does nothing.
+ // INSTANTIATE_TEST_CASE_P, creating regular tests for each test/parameter
+ // combination. This method can be called more then once; it has guards
+ // protecting from registering the tests more then once. If
+ // value-parameterized tests are disabled, RegisterParameterizedTests is
+ // present but does nothing.
void RegisterParameterizedTests();
// Runs all tests in this UnitTest object, prints the result, and
- // returns 0 if all tests are successful, or 1 otherwise. If any
- // exception is thrown during a test on Windows, this test is
- // considered to be failed, but the rest of the tests will still be
- // run. (We disable exceptions on Linux and Mac OS X, so the issue
- // doesn't apply there.)
- int RunAllTests();
+ // returns true if all tests are successful. If any exception is
+ // thrown during a test, this test is considered to be failed, but
+ // the rest of the tests will still be run.
+ bool RunAllTests();
- // Clears the results of all tests, including the ad hoc test.
- void ClearResult() {
+ // Clears the results of all tests, except the ad hoc tests.
+ void ClearNonAdHocTestResult() {
ForEach(test_cases_, TestCase::ClearTestCaseResult);
+ }
+
+ // Clears the results of ad-hoc test assertions.
+ void ClearAdHocTestResult() {
ad_hoc_test_result_.Clear();
}
@@ -818,6 +754,12 @@
// UnitTestOptions. Must not be called before InitGoogleTest.
void ConfigureXmlOutput();
+#if GTEST_CAN_STREAM_RESULTS_
+ // Initializes the event listener for streaming test results to a socket.
+ // Must not be called before InitGoogleTest.
+ void ConfigureStreamingOutput();
+#endif
+
// Performs initialization dependent upon flag values obtained in
// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to
// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest
@@ -838,9 +780,17 @@
// Restores the test cases and tests to their order before the first shuffle.
void UnshuffleTests();
+ // Returns the value of GTEST_FLAG(catch_exceptions) at the moment
+ // UnitTest::Run() starts.
+ bool catch_exceptions() const { return catch_exceptions_; }
+
private:
friend class ::testing::UnitTest;
+ // Used by UnitTest::Run() to capture the state of
+ // GTEST_FLAG(catch_exceptions) at the moment it starts.
+ void set_catch_exceptions(bool value) { catch_exceptions_ = value; }
+
// The UnitTest object that owns this implementation object.
UnitTest* const parent_;
@@ -943,6 +893,10 @@
// A per-thread stack of traces created by the SCOPED_TRACE() macro.
internal::ThreadLocal<std::vector<TraceInfo> > gtest_trace_stack_;
+ // The value of GTEST_FLAG(catch_exceptions) at the moment RunAllTests()
+ // starts.
+ bool catch_exceptions_;
+
GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestImpl);
}; // class UnitTestImpl
@@ -952,14 +906,16 @@
return UnitTest::GetInstance()->impl();
}
+#if GTEST_USES_SIMPLE_RE
+
// Internal helper functions for implementing the simple regular
// expression matcher.
GTEST_API_ bool IsInSet(char ch, const char* str);
-GTEST_API_ bool IsDigit(char ch);
-GTEST_API_ bool IsPunct(char ch);
+GTEST_API_ bool IsAsciiDigit(char ch);
+GTEST_API_ bool IsAsciiPunct(char ch);
GTEST_API_ bool IsRepeat(char ch);
-GTEST_API_ bool IsWhiteSpace(char ch);
-GTEST_API_ bool IsWordChar(char ch);
+GTEST_API_ bool IsAsciiWhiteSpace(char ch);
+GTEST_API_ bool IsAsciiWordChar(char ch);
GTEST_API_ bool IsValidEscape(char ch);
GTEST_API_ bool AtomMatchesChar(bool escaped, char pattern, char ch);
GTEST_API_ bool ValidateRegex(const char* regex);
@@ -968,6 +924,8 @@
bool escaped, char ch, char repeat, const char* regex, const char* str);
GTEST_API_ bool MatchRegexAnywhere(const char* regex, const char* str);
+#endif // GTEST_USES_SIMPLE_RE
+
// Parses the command line for Google Test flags, without initializing
// other parts of Google Test.
GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, char** argv);
@@ -977,9 +935,9 @@
// Returns the message describing the last system error, regardless of the
// platform.
-String GetLastErrnoDescription();
+GTEST_API_ String GetLastErrnoDescription();
-#if GTEST_OS_WINDOWS
+# if GTEST_OS_WINDOWS
// Provides leak-safe Windows kernel handle ownership.
class AutoHandle {
public:
@@ -1003,7 +961,7 @@
GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle);
};
-#endif // GTEST_OS_WINDOWS
+# endif // GTEST_OS_WINDOWS
// Attempts to parse a string into a positive integer pointed to by the
// number parameter. Returns true if that is possible.
@@ -1014,7 +972,7 @@
// Fail fast if the given string does not begin with a digit;
// this bypasses strtoXXX's "optional leading whitespace and plus
// or minus sign" semantics, which are undesirable here.
- if (str.empty() || !isdigit(str[0])) {
+ if (str.empty() || !IsDigit(str[0])) {
return false;
}
errno = 0;
@@ -1022,14 +980,20 @@
char* end;
// BiggestConvertible is the largest integer type that system-provided
// string-to-number conversion routines can return.
-#if GTEST_OS_WINDOWS && !defined(__GNUC__)
+
+# if GTEST_OS_WINDOWS && !defined(__GNUC__)
+
// MSVC and C++ Builder define __int64 instead of the standard long long.
typedef unsigned __int64 BiggestConvertible;
const BiggestConvertible parsed = _strtoui64(str.c_str(), &end, 10);
-#else
+
+# else
+
typedef unsigned long long BiggestConvertible; // NOLINT
const BiggestConvertible parsed = strtoull(str.c_str(), &end, 10);
-#endif // GTEST_OS_WINDOWS && !defined(__GNUC__)
+
+# endif // GTEST_OS_WINDOWS && !defined(__GNUC__)
+
const bool parse_success = *end == '\0' && errno == 0;
// TODO(vladl@google.com): Convert this to compile time assertion when it is
diff --git a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-internal.h b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-internal.h
index 0b90132..b198a3d 100644
--- a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-internal.h
+++ b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-internal.h
@@ -37,13 +37,13 @@
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-port.h"
#if GTEST_OS_LINUX
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
+# include <stdlib.h>
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <unistd.h>
#endif // GTEST_OS_LINUX
#include <ctype.h>
@@ -52,9 +52,9 @@
#include <limits>
#include <set>
-#include <gtest/internal/gtest-string.h>
-#include <gtest/internal/gtest-filepath.h>
-#include <gtest/internal/gtest-type-util.h>
+#include "gtest/internal/gtest-string.h"
+#include "gtest/internal/gtest-filepath.h"
+#include "gtest/internal/gtest-type-util.h"
#include "llvm/Support/raw_os_ostream.h"
@@ -117,9 +117,12 @@
cos << val;
}
+class ProtocolMessage;
+namespace proto2 { class Message; }
+
namespace testing {
-// Forward declaration of classes.
+// Forward declarations.
class AssertionResult; // Result of an assertion.
class Message; // Represents a failure message.
@@ -128,6 +131,9 @@
class TestPartResult; // Result of a test part.
class UnitTest; // A collection of test cases.
+template <typename T>
+::std::string PrintToString(const T& value);
+
namespace internal {
struct TraceInfo; // Information about a trace point.
@@ -170,9 +176,9 @@
#ifdef GTEST_ELLIPSIS_NEEDS_POD_
// We lose support for NULL detection where the compiler doesn't like
// passing non-POD classes through ellipsis (...).
-#define GTEST_IS_NULL_LITERAL_(x) false
+# define GTEST_IS_NULL_LITERAL_(x) false
#else
-#define GTEST_IS_NULL_LITERAL_(x) \
+# define GTEST_IS_NULL_LITERAL_(x) \
(sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1)
#endif // GTEST_ELLIPSIS_NEEDS_POD_
@@ -209,72 +215,32 @@
template <typename T>
String StreamableToString(const T& streamable);
-// Formats a value to be used in a failure message.
-
-#ifdef GTEST_NEEDS_IS_POINTER_
-
-// These are needed as the Nokia Symbian and IBM XL C/C++ compilers
-// cannot decide between const T& and const T* in a function template.
-// These compilers _can_ decide between class template specializations
-// for T and T*, so a tr1::type_traits-like is_pointer works, and we
-// can overload on that.
-
-// This overload makes sure that all pointers (including
-// those to char or wchar_t) are printed as raw pointers.
-template <typename T>
-inline String FormatValueForFailureMessage(internal::true_type /*dummy*/,
- T* pointer) {
- return StreamableToString(static_cast<const void*>(pointer));
-}
-
-template <typename T>
-inline String FormatValueForFailureMessage(internal::false_type /*dummy*/,
- const T& value) {
- return StreamableToString(value);
-}
-
-template <typename T>
-inline String FormatForFailureMessage(const T& value) {
- return FormatValueForFailureMessage(
- typename internal::is_pointer<T>::type(), value);
-}
-
+// The Symbian compiler has a bug that prevents it from selecting the
+// correct overload of FormatForComparisonFailureMessage (see below)
+// unless we pass the first argument by reference. If we do that,
+// however, Visual Age C++ 10.1 generates a compiler error. Therefore
+// we only apply the work-around for Symbian.
+#if defined(__SYMBIAN32__)
+# define GTEST_CREF_WORKAROUND_ const&
#else
+# define GTEST_CREF_WORKAROUND_
+#endif
-// These are needed as the above solution using is_pointer has the
-// limitation that T cannot be a type without external linkage, when
-// compiled using MSVC.
-
-template <typename T>
-inline String FormatForFailureMessage(const T& value) {
- return StreamableToString(value);
-}
-
-// This overload makes sure that all pointers (including
-// those to char or wchar_t) are printed as raw pointers.
-template <typename T>
-inline String FormatForFailureMessage(T* pointer) {
- return StreamableToString(static_cast<const void*>(pointer));
-}
-
-#endif // GTEST_NEEDS_IS_POINTER_
-
-// These overloaded versions handle narrow and wide characters.
-GTEST_API_ String FormatForFailureMessage(char ch);
-GTEST_API_ String FormatForFailureMessage(wchar_t wchar);
-
-// When this operand is a const char* or char*, and the other operand
+// When this operand is a const char* or char*, if the other operand
// is a ::std::string or ::string, we print this operand as a C string
-// rather than a pointer. We do the same for wide strings.
+// rather than a pointer (we do the same for wide strings); otherwise
+// we print it as a pointer to be safe.
// This internal macro is used to avoid duplicated code.
#define GTEST_FORMAT_IMPL_(operand2_type, operand1_printer)\
inline String FormatForComparisonFailureMessage(\
- operand2_type::value_type* str, const operand2_type& /*operand2*/) {\
+ operand2_type::value_type* GTEST_CREF_WORKAROUND_ str, \
+ const operand2_type& /*operand2*/) {\
return operand1_printer(str);\
}\
inline String FormatForComparisonFailureMessage(\
- const operand2_type::value_type* str, const operand2_type& /*operand2*/) {\
+ const operand2_type::value_type* GTEST_CREF_WORKAROUND_ str, \
+ const operand2_type& /*operand2*/) {\
return operand1_printer(str);\
}
@@ -292,6 +258,24 @@
#undef GTEST_FORMAT_IMPL_
+// The next four overloads handle the case where the operand being
+// printed is a char/wchar_t pointer and the other operand is not a
+// string/wstring object. In such cases, we just print the operand as
+// a pointer to be safe.
+#define GTEST_FORMAT_CHAR_PTR_IMPL_(CharType) \
+ template <typename T> \
+ String FormatForComparisonFailureMessage(CharType* GTEST_CREF_WORKAROUND_ p, \
+ const T&) { \
+ return PrintToString(static_cast<const void*>(p)); \
+ }
+
+GTEST_FORMAT_CHAR_PTR_IMPL_(char)
+GTEST_FORMAT_CHAR_PTR_IMPL_(const char)
+GTEST_FORMAT_CHAR_PTR_IMPL_(wchar_t)
+GTEST_FORMAT_CHAR_PTR_IMPL_(const wchar_t)
+
+#undef GTEST_FORMAT_CHAR_PTR_IMPL_
+
// Constructs and returns the message for an equality assertion
// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
//
@@ -578,20 +562,6 @@
#endif // GTEST_OS_WINDOWS
-// Formats a source file path and a line number as they would appear
-// in a compiler error message.
-inline String FormatFileLocation(const char* file, int line) {
- const char* const file_name = file == NULL ? "unknown file" : file;
- if (line < 0) {
- return String::Format("%s:", file_name);
- }
-#ifdef _MSC_VER
- return String::Format("%s(%d):", file_name, line);
-#else
- return String::Format("%s:%d:", file_name, line);
-#endif // _MSC_VER
-}
-
// Types of SetUpTestCase() and TearDownTestCase() functions.
typedef void (*SetUpTestCaseFunc)();
typedef void (*TearDownTestCaseFunc)();
@@ -603,10 +573,10 @@
//
// test_case_name: name of the test case
// name: name of the test
-// test_case_comment: a comment on the test case that will be included in
-// the test output
-// comment: a comment on the test that will be included in the
-// test output
+// type_param the name of the test's type parameter, or NULL if
+// this is not a typed or a type-parameterized test.
+// value_param text representation of the test's value parameter,
+// or NULL if this is not a type-parameterized test.
// fixture_class_id: ID of the test fixture class
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
@@ -615,7 +585,8 @@
// ownership of the factory object.
GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
const char* test_case_name, const char* name,
- const char* test_case_comment, const char* comment,
+ const char* type_param,
+ const char* value_param,
TypeId fixture_class_id,
SetUpTestCaseFunc set_up_tc,
TearDownTestCaseFunc tear_down_tc,
@@ -624,7 +595,7 @@
// If *pstr starts with the given prefix, modifies *pstr to be right
// past the prefix and returns true; otherwise leaves *pstr unchanged
// and returns false. None of pstr, *pstr, and prefix can be NULL.
-bool SkipPrefix(const char* prefix, const char** pstr);
+GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr);
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
@@ -667,7 +638,7 @@
if (comma == NULL) {
return NULL;
}
- while (isspace(*(++comma))) {}
+ while (IsSpace(*(++comma))) {}
return comma;
}
@@ -704,8 +675,8 @@
String::Format("%s%s%s/%d", prefix, prefix[0] == '\0' ? "" : "/",
case_name, index).c_str(),
GetPrefixUntilComma(test_names).c_str(),
- String::Format("TypeParam = %s", GetTypeName<Type>().c_str()).c_str(),
- "",
+ GetTypeName<Type>().c_str(),
+ NULL, // No value parameter.
GetTypeId<FixtureClass>(),
TestClass::SetUpTestCase,
TestClass::TearDownTestCase,
@@ -782,6 +753,15 @@
// Always returns false.
inline bool AlwaysFalse() { return !AlwaysTrue(); }
+// Helper for suppressing false warning from Clang on a const char*
+// variable declared in a conditional expression always being NULL in
+// the else branch.
+struct GTEST_API_ ConstCharPtr {
+ ConstCharPtr(const char* str) : value(str) {}
+ operator bool() const { return true; }
+ const char* value;
+};
+
// A simple Linear Congruential Generator for generating random
// numbers with a uniform distribution. Unlike rand() and srand(), it
// doesn't use global state (and therefore can't interfere with user
@@ -804,13 +784,338 @@
GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
};
+// Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a
+// compiler error iff T1 and T2 are different types.
+template <typename T1, typename T2>
+struct CompileAssertTypesEqual;
+
+template <typename T>
+struct CompileAssertTypesEqual<T, T> {
+};
+
+// Removes the reference from a type if it is a reference type,
+// otherwise leaves it unchanged. This is the same as
+// tr1::remove_reference, which is not widely available yet.
+template <typename T>
+struct RemoveReference { typedef T type; }; // NOLINT
+template <typename T>
+struct RemoveReference<T&> { typedef T type; }; // NOLINT
+
+// A handy wrapper around RemoveReference that works when the argument
+// T depends on template parameters.
+#define GTEST_REMOVE_REFERENCE_(T) \
+ typename ::testing::internal::RemoveReference<T>::type
+
+// Removes const from a type if it is a const type, otherwise leaves
+// it unchanged. This is the same as tr1::remove_const, which is not
+// widely available yet.
+template <typename T>
+struct RemoveConst { typedef T type; }; // NOLINT
+template <typename T>
+struct RemoveConst<const T> { typedef T type; }; // NOLINT
+
+// MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above
+// definition to fail to remove the const in 'const int[3]' and 'const
+// char[3][4]'. The following specialization works around the bug.
+// However, it causes trouble with GCC and thus needs to be
+// conditionally compiled.
+#if defined(_MSC_VER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
+template <typename T, size_t N>
+struct RemoveConst<const T[N]> {
+ typedef typename RemoveConst<T>::type type[N];
+};
+#endif
+
+// A handy wrapper around RemoveConst that works when the argument
+// T depends on template parameters.
+#define GTEST_REMOVE_CONST_(T) \
+ typename ::testing::internal::RemoveConst<T>::type
+
+// Turns const U&, U&, const U, and U all into U.
+#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \
+ GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T))
+
+// Adds reference to a type if it is not a reference type,
+// otherwise leaves it unchanged. This is the same as
+// tr1::add_reference, which is not widely available yet.
+template <typename T>
+struct AddReference { typedef T& type; }; // NOLINT
+template <typename T>
+struct AddReference<T&> { typedef T& type; }; // NOLINT
+
+// A handy wrapper around AddReference that works when the argument T
+// depends on template parameters.
+#define GTEST_ADD_REFERENCE_(T) \
+ typename ::testing::internal::AddReference<T>::type
+
+// Adds a reference to const on top of T as necessary. For example,
+// it transforms
+//
+// char ==> const char&
+// const char ==> const char&
+// char& ==> const char&
+// const char& ==> const char&
+//
+// The argument T must depend on some template parameters.
+#define GTEST_REFERENCE_TO_CONST_(T) \
+ GTEST_ADD_REFERENCE_(const GTEST_REMOVE_REFERENCE_(T))
+
+// ImplicitlyConvertible<From, To>::value is a compile-time bool
+// constant that's true iff type From can be implicitly converted to
+// type To.
+template <typename From, typename To>
+class ImplicitlyConvertible {
+ private:
+ // We need the following helper functions only for their types.
+ // They have no implementations.
+
+ // MakeFrom() is an expression whose type is From. We cannot simply
+ // use From(), as the type From may not have a public default
+ // constructor.
+ static From MakeFrom();
+
+ // These two functions are overloaded. Given an expression
+ // Helper(x), the compiler will pick the first version if x can be
+ // implicitly converted to type To; otherwise it will pick the
+ // second version.
+ //
+ // The first version returns a value of size 1, and the second
+ // version returns a value of size 2. Therefore, by checking the
+ // size of Helper(x), which can be done at compile time, we can tell
+ // which version of Helper() is used, and hence whether x can be
+ // implicitly converted to type To.
+ static char Helper(To);
+ static char (&Helper(...))[2]; // NOLINT
+
+ // We have to put the 'public' section after the 'private' section,
+ // or MSVC refuses to compile the code.
+ public:
+ // MSVC warns about implicitly converting from double to int for
+ // possible loss of data, so we need to temporarily disable the
+ // warning.
+#ifdef _MSC_VER
+# pragma warning(push) // Saves the current warning state.
+# pragma warning(disable:4244) // Temporarily disables warning 4244.
+
+ static const bool value =
+ sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
+# pragma warning(pop) // Restores the warning state.
+#elif defined(__BORLANDC__)
+ // C++Builder cannot use member overload resolution during template
+ // instantiation. The simplest workaround is to use its C++0x type traits
+ // functions (C++Builder 2009 and above only).
+ static const bool value = __is_convertible(From, To);
+#else
+ static const bool value =
+ sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
+#endif // _MSV_VER
+};
+template <typename From, typename To>
+const bool ImplicitlyConvertible<From, To>::value;
+
+// IsAProtocolMessage<T>::value is a compile-time bool constant that's
+// true iff T is type ProtocolMessage, proto2::Message, or a subclass
+// of those.
+template <typename T>
+struct IsAProtocolMessage
+ : public bool_constant<
+ ImplicitlyConvertible<const T*, const ::ProtocolMessage*>::value ||
+ ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> {
+};
+
+// When the compiler sees expression IsContainerTest<C>(0), if C is an
+// STL-style container class, the first overload of IsContainerTest
+// will be viable (since both C::iterator* and C::const_iterator* are
+// valid types and NULL can be implicitly converted to them). It will
+// be picked over the second overload as 'int' is a perfect match for
+// the type of argument 0. If C::iterator or C::const_iterator is not
+// a valid type, the first overload is not viable, and the second
+// overload will be picked. Therefore, we can determine whether C is
+// a container class by checking the type of IsContainerTest<C>(0).
+// The value of the expression is insignificant.
+//
+// Note that we look for both C::iterator and C::const_iterator. The
+// reason is that C++ injects the name of a class as a member of the
+// class itself (e.g. you can refer to class iterator as either
+// 'iterator' or 'iterator::iterator'). If we look for C::iterator
+// only, for example, we would mistakenly think that a class named
+// iterator is an STL container.
+//
+// Also note that the simpler approach of overloading
+// IsContainerTest(typename C::const_iterator*) and
+// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
+typedef int IsContainer;
+template <class C>
+IsContainer IsContainerTest(int /* dummy */,
+ typename C::iterator* /* it */ = NULL,
+ typename C::const_iterator* /* const_it */ = NULL) {
+ return 0;
+}
+
+typedef char IsNotContainer;
+template <class C>
+IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
+
+// EnableIf<condition>::type is void when 'Cond' is true, and
+// undefined when 'Cond' is false. To use SFINAE to make a function
+// overload only apply when a particular expression is true, add
+// "typename EnableIf<expression>::type* = 0" as the last parameter.
+template<bool> struct EnableIf;
+template<> struct EnableIf<true> { typedef void type; }; // NOLINT
+
+// Utilities for native arrays.
+
+// ArrayEq() compares two k-dimensional native arrays using the
+// elements' operator==, where k can be any integer >= 0. When k is
+// 0, ArrayEq() degenerates into comparing a single pair of values.
+
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline bool ArrayEq(const T& lhs, const U& rhs) { return lhs == rhs; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline bool ArrayEq(const T(&lhs)[N], const U(&rhs)[N]) {
+ return internal::ArrayEq(lhs, N, rhs);
+}
+
+// This helper reduces code bloat. If we instead put its logic inside
+// the previous ArrayEq() function, arrays with different sizes would
+// lead to different copies of the template code.
+template <typename T, typename U>
+bool ArrayEq(const T* lhs, size_t size, const U* rhs) {
+ for (size_t i = 0; i != size; i++) {
+ if (!internal::ArrayEq(lhs[i], rhs[i]))
+ return false;
+ }
+ return true;
+}
+
+// Finds the first element in the iterator range [begin, end) that
+// equals elem. Element may be a native array type itself.
+template <typename Iter, typename Element>
+Iter ArrayAwareFind(Iter begin, Iter end, const Element& elem) {
+ for (Iter it = begin; it != end; ++it) {
+ if (internal::ArrayEq(*it, elem))
+ return it;
+ }
+ return end;
+}
+
+// CopyArray() copies a k-dimensional native array using the elements'
+// operator=, where k can be any integer >= 0. When k is 0,
+// CopyArray() degenerates into copying a single value.
+
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to);
+
+// This generic version is used when k is 0.
+template <typename T, typename U>
+inline void CopyArray(const T& from, U* to) { *to = from; }
+
+// This overload is used when k >= 1.
+template <typename T, typename U, size_t N>
+inline void CopyArray(const T(&from)[N], U(*to)[N]) {
+ internal::CopyArray(from, N, *to);
+}
+
+// This helper reduces code bloat. If we instead put its logic inside
+// the previous CopyArray() function, arrays with different sizes
+// would lead to different copies of the template code.
+template <typename T, typename U>
+void CopyArray(const T* from, size_t size, U* to) {
+ for (size_t i = 0; i != size; i++) {
+ internal::CopyArray(from[i], to + i);
+ }
+}
+
+// The relation between an NativeArray object (see below) and the
+// native array it represents.
+enum RelationToSource {
+ kReference, // The NativeArray references the native array.
+ kCopy // The NativeArray makes a copy of the native array and
+ // owns the copy.
+};
+
+// Adapts a native array to a read-only STL-style container. Instead
+// of the complete STL container concept, this adaptor only implements
+// members useful for Google Mock's container matchers. New members
+// should be added as needed. To simplify the implementation, we only
+// support Element being a raw type (i.e. having no top-level const or
+// reference modifier). It's the client's responsibility to satisfy
+// this requirement. Element can be an array type itself (hence
+// multi-dimensional arrays are supported).
+template <typename Element>
+class NativeArray {
+ public:
+ // STL-style container typedefs.
+ typedef Element value_type;
+ typedef Element* iterator;
+ typedef const Element* const_iterator;
+
+ // Constructs from a native array.
+ NativeArray(const Element* array, size_t count, RelationToSource relation) {
+ Init(array, count, relation);
+ }
+
+ // Copy constructor.
+ NativeArray(const NativeArray& rhs) {
+ Init(rhs.array_, rhs.size_, rhs.relation_to_source_);
+ }
+
+ ~NativeArray() {
+ // Ensures that the user doesn't instantiate NativeArray with a
+ // const or reference type.
+ static_cast<void>(StaticAssertTypeEqHelper<Element,
+ GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>());
+ if (relation_to_source_ == kCopy)
+ delete[] array_;
+ }
+
+ // STL-style container methods.
+ size_t size() const { return size_; }
+ const_iterator begin() const { return array_; }
+ const_iterator end() const { return array_ + size_; }
+ bool operator==(const NativeArray& rhs) const {
+ return size() == rhs.size() &&
+ ArrayEq(begin(), size(), rhs.begin());
+ }
+
+ private:
+ // Initializes this object; makes a copy of the input array if
+ // 'relation' is kCopy.
+ void Init(const Element* array, size_t a_size, RelationToSource relation) {
+ if (relation == kReference) {
+ array_ = array;
+ } else {
+ Element* const copy = new Element[a_size];
+ CopyArray(array, a_size, copy);
+ array_ = copy;
+ }
+ size_ = a_size;
+ relation_to_source_ = relation;
+ }
+
+ const Element* array_;
+ size_t size_;
+ RelationToSource relation_to_source_;
+
+ GTEST_DISALLOW_ASSIGN_(NativeArray);
+};
+
} // namespace internal
} // namespace testing
-#define GTEST_MESSAGE_(message, result_type) \
- ::testing::internal::AssertHelper(result_type, __FILE__, __LINE__, message) \
+#define GTEST_MESSAGE_AT_(file, line, message, result_type) \
+ ::testing::internal::AssertHelper(result_type, file, line, message) \
= ::testing::Message()
+#define GTEST_MESSAGE_(message, result_type) \
+ GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type)
+
#define GTEST_FATAL_FAILURE_(message) \
return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure)
@@ -828,7 +1133,7 @@
#define GTEST_TEST_THROW_(statement, expected_exception, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (const char* gtest_msg = "") { \
+ if (::testing::internal::ConstCharPtr gtest_msg = "") { \
bool gtest_caught_expected = false; \
try { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
@@ -837,38 +1142,38 @@
gtest_caught_expected = true; \
} \
catch (...) { \
- gtest_msg = "Expected: " #statement " throws an exception of type " \
- #expected_exception ".\n Actual: it throws a different " \
- "type."; \
+ gtest_msg.value = \
+ "Expected: " #statement " throws an exception of type " \
+ #expected_exception ".\n Actual: it throws a different type."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
if (!gtest_caught_expected) { \
- gtest_msg = "Expected: " #statement " throws an exception of type " \
- #expected_exception ".\n Actual: it throws nothing."; \
+ gtest_msg.value = \
+ "Expected: " #statement " throws an exception of type " \
+ #expected_exception ".\n Actual: it throws nothing."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \
- fail(gtest_msg)
+ fail(gtest_msg.value)
#define GTEST_TEST_NO_THROW_(statement, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (const char* gtest_msg = "") { \
+ if (::testing::internal::AlwaysTrue()) { \
try { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
} \
catch (...) { \
- gtest_msg = "Expected: " #statement " doesn't throw an exception.\n" \
- " Actual: it throws."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \
- fail(gtest_msg)
+ fail("Expected: " #statement " doesn't throw an exception.\n" \
+ " Actual: it throws.")
#define GTEST_TEST_ANY_THROW_(statement, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (const char* gtest_msg = "") { \
+ if (::testing::internal::AlwaysTrue()) { \
bool gtest_caught_any = false; \
try { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
@@ -877,13 +1182,12 @@
gtest_caught_any = true; \
} \
if (!gtest_caught_any) { \
- gtest_msg = "Expected: " #statement " throws an exception.\n" \
- " Actual: it doesn't."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \
- fail(gtest_msg)
+ fail("Expected: " #statement " throws an exception.\n" \
+ " Actual: it doesn't.")
// Implements Boolean test assertions such as EXPECT_TRUE. expression can be
@@ -900,18 +1204,17 @@
#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
- if (const char* gtest_msg = "") { \
+ if (::testing::internal::AlwaysTrue()) { \
::testing::internal::HasNewFatalFailureHelper gtest_fatal_failure_checker; \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
if (gtest_fatal_failure_checker.has_new_fatal_failure()) { \
- gtest_msg = "Expected: " #statement " doesn't generate new fatal " \
- "failures in the current thread.\n" \
- " Actual: it does."; \
goto GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__); \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_testnofatal_, __LINE__): \
- fail(gtest_msg)
+ fail("Expected: " #statement " doesn't generate new fatal " \
+ "failures in the current thread.\n" \
+ " Actual: it does.")
// Expands to the name of the class that implements the given test.
#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
@@ -924,7 +1227,7 @@
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
private:\
virtual void TestBody();\
- static ::testing::TestInfo* const test_info_;\
+ static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\
GTEST_DISALLOW_COPY_AND_ASSIGN_(\
GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\
};\
@@ -932,7 +1235,7 @@
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\
::test_info_ =\
::testing::internal::MakeAndRegisterTestInfo(\
- #test_case_name, #test_name, "", "", \
+ #test_case_name, #test_name, NULL, NULL, \
(parent_id), \
parent_class::SetUpTestCase, \
parent_class::TearDownTestCase, \
diff --git a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h
index 2404ea8..57147b4 100644
--- a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h
+++ b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h
@@ -71,7 +71,7 @@
#include <stdlib.h>
#include <assert.h>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-port.h"
namespace testing {
namespace internal {
@@ -172,16 +172,6 @@
T* get() const { return value_; }
T* operator->() const { return value_; }
T& operator*() const { return *value_; }
- // Release ownership of the pointed object and returns it.
- // Sole ownership by this linked_ptr object is required.
- T* release() {
- bool last = link_.depart();
- (void) last;
- assert(last);
- T* v = value_;
- value_ = NULL;
- return v;
- }
bool operator==(T* p) const { return value_ == p; }
bool operator!=(T* p) const { return value_ != p; }
diff --git a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h
index ab4ab56..2582675 100644
--- a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h
+++ b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-param-util-generated.h
@@ -1,4 +1,6 @@
-// This file was GENERATED by a script. DO NOT EDIT BY HAND!!!
+// This file was GENERATED by command:
+// pump.py gtest-param-util-generated.h.pump
+// DO NOT EDIT BY HAND!!!
// Copyright 2008 Google Inc.
// All Rights Reserved.
@@ -47,8 +49,8 @@
// scripts/fuse_gtest.py depends on gtest's own header being #included
// *unconditionally*. Therefore these #includes cannot be moved
// inside #if GTEST_HAS_PARAM_TEST.
-#include <gtest/internal/gtest-param-util.h>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-param-util.h"
+#include "gtest/internal/gtest-port.h"
#if GTEST_HAS_PARAM_TEST
@@ -58,8 +60,8 @@
// include/gtest/gtest-param-test.h.
template <typename ForwardIterator>
internal::ParamGenerator<
- typename ::std::iterator_traits<ForwardIterator>::value_type> ValuesIn(
- ForwardIterator begin, ForwardIterator end);
+ typename ::testing::internal::IteratorTraits<ForwardIterator>::value_type>
+ValuesIn(ForwardIterator begin, ForwardIterator end);
template <typename T, size_t N>
internal::ParamGenerator<T> ValuesIn(const T (&array)[N]);
@@ -2826,7 +2828,7 @@
const T50 v50_;
};
-#if GTEST_HAS_COMBINE
+# if GTEST_HAS_COMBINE
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
// Generates values from the Cartesian product of values produced
@@ -4810,7 +4812,7 @@
const Generator10 g10_;
}; // class CartesianProductHolder10
-#endif // GTEST_HAS_COMBINE
+# endif // GTEST_HAS_COMBINE
} // namespace internal
} // namespace testing
diff --git a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h
index 0cbb58c..0ef9718 100644
--- a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h
+++ b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-param-util.h
@@ -41,9 +41,10 @@
// scripts/fuse_gtest.py depends on gtest's own header being #included
// *unconditionally*. Therefore these #includes cannot be moved
// inside #if GTEST_HAS_PARAM_TEST.
-#include <gtest/internal/gtest-internal.h>
-#include <gtest/internal/gtest-linked_ptr.h>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-internal.h"
+#include "gtest/internal/gtest-linked_ptr.h"
+#include "gtest/internal/gtest-port.h"
+#include "gtest/gtest-printers.h"
#if GTEST_HAS_PARAM_TEST
@@ -171,7 +172,7 @@
iterator end() const { return iterator(impl_->End()); }
private:
- ::testing::internal::linked_ptr<const ParamGeneratorInterface<T> > impl_;
+ linked_ptr<const ParamGeneratorInterface<T> > impl_;
};
// Generates values from a range of two comparable values. Can be used to
@@ -285,7 +286,7 @@
public:
Iterator(const ParamGeneratorInterface<T>* base,
typename ContainerType::const_iterator iterator)
- : base_(base), iterator_(iterator) {}
+ : base_(base), iterator_(iterator) {}
virtual ~Iterator() {}
virtual const ParamGeneratorInterface<T>* BaseGenerator() const {
@@ -416,7 +417,7 @@
virtual ~ParameterizedTestCaseInfoBase() {}
// Base part of test case name for display purposes.
- virtual const String& GetTestCaseName() const = 0;
+ virtual const string& GetTestCaseName() const = 0;
// Test case id to verify identity.
virtual TypeId GetTestCaseTypeId() const = 0;
// UnitTest class invokes this method to register tests in this
@@ -453,7 +454,7 @@
: test_case_name_(name) {}
// Test case base name for display purposes.
- virtual const String& GetTestCaseName() const { return test_case_name_; }
+ virtual const string& GetTestCaseName() const { return test_case_name_; }
// Test case id to verify identity.
virtual TypeId GetTestCaseTypeId() const { return GetTypeId<TestCase>(); }
// TEST_P macro uses AddTestPattern() to record information
@@ -471,7 +472,7 @@
}
// INSTANTIATE_TEST_CASE_P macro uses AddGenerator() to record information
// about a generator.
- int AddTestCaseInstantiation(const char* instantiation_name,
+ int AddTestCaseInstantiation(const string& instantiation_name,
GeneratorCreationFunc* func,
const char* /* file */,
int /* line */) {
@@ -490,26 +491,25 @@
for (typename InstantiationContainer::iterator gen_it =
instantiations_.begin(); gen_it != instantiations_.end();
++gen_it) {
- const String& instantiation_name = gen_it->first;
+ const string& instantiation_name = gen_it->first;
ParamGenerator<ParamType> generator((*gen_it->second)());
Message test_case_name_stream;
if ( !instantiation_name.empty() )
- test_case_name_stream << instantiation_name.c_str() << "/";
- test_case_name_stream << test_info->test_case_base_name.c_str();
+ test_case_name_stream << instantiation_name << "/";
+ test_case_name_stream << test_info->test_case_base_name;
int i = 0;
for (typename ParamGenerator<ParamType>::iterator param_it =
generator.begin();
param_it != generator.end(); ++param_it, ++i) {
Message test_name_stream;
- test_name_stream << test_info->test_base_name.c_str() << "/" << i;
- ::testing::internal::MakeAndRegisterTestInfo(
+ test_name_stream << test_info->test_base_name << "/" << i;
+ MakeAndRegisterTestInfo(
test_case_name_stream.GetString().c_str(),
test_name_stream.GetString().c_str(),
- "", // test_case_comment
- "", // comment; TODO(vladl@google.com): provide parameter value
- // representation.
+ NULL, // No type parameter.
+ PrintToString(*param_it).c_str(),
GetTestCaseTypeId(),
TestCase::SetUpTestCase,
TestCase::TearDownTestCase,
@@ -530,17 +530,17 @@
test_base_name(a_test_base_name),
test_meta_factory(a_test_meta_factory) {}
- const String test_case_base_name;
- const String test_base_name;
+ const string test_case_base_name;
+ const string test_base_name;
const scoped_ptr<TestMetaFactoryBase<ParamType> > test_meta_factory;
};
typedef ::std::vector<linked_ptr<TestInfo> > TestInfoContainer;
// Keeps pairs of <Instantiation name, Sequence generator creation function>
// received from INSTANTIATE_TEST_CASE_P macros.
- typedef ::std::vector<std::pair<String, GeneratorCreationFunc*> >
+ typedef ::std::vector<std::pair<string, GeneratorCreationFunc*> >
InstantiationContainer;
- const String test_case_name_;
+ const string test_case_name_;
TestInfoContainer tests_;
InstantiationContainer instantiations_;
@@ -579,7 +579,7 @@
// and terminate the program since we cannot guaranty correct
// test case setup and tear-down in this case.
ReportInvalidTestCaseType(test_case_name, file, line);
- abort();
+ posix::Abort();
} else {
// At this point we are sure that the object we found is of the same
// type we are looking for, so we downcast it to that type
diff --git a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-port.h b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-port.h
index 9683271..8ef5d7d 100644
--- a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-port.h
+++ b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-port.h
@@ -50,6 +50,8 @@
// GTEST_HAS_GLOBAL_WSTRING - Define it to 1/0 to indicate that ::string
// is/isn't available (some systems define
// ::wstring, which is different to std::wstring).
+// GTEST_HAS_POSIX_RE - Define it to 1/0 to indicate that POSIX regular
+// expressions are/aren't available.
// GTEST_HAS_PTHREAD - Define it to 1/0 to indicate that <pthread.h>
// is/isn't available.
// GTEST_HAS_RTTI - Define it to 1/0 to indicate that RTTI is/isn't
@@ -62,6 +64,10 @@
// GTEST_HAS_SEH - Define it to 1/0 to indicate whether the
// compiler supports Microsoft's "Structured
// Exception Handling".
+// GTEST_HAS_STREAM_REDIRECTION
+// - Define it to 1/0 to indicate whether the
+// platform supports I/O stream redirection using
+// dup() and dup2().
// GTEST_USE_OWN_TR1_TUPLE - Define it to 1/0 to indicate whether Google
// Test's own tr1 tuple implementation should be
// used. Unused when the user sets
@@ -81,8 +87,11 @@
// GTEST_OS_AIX - IBM AIX
// GTEST_OS_CYGWIN - Cygwin
// GTEST_OS_HAIKU - Haiku
+// GTEST_OS_HPUX - HP-UX
// GTEST_OS_LINUX - Linux
+// GTEST_OS_LINUX_ANDROID - Google Android
// GTEST_OS_MAC - Mac OS X
+// GTEST_OS_NACL - Google Native Client (NaCl)
// GTEST_OS_SOLARIS - Sun Solaris
// GTEST_OS_SYMBIAN - Symbian
// GTEST_OS_WINDOWS - Windows (Desktop, MinGW, or Mobile)
@@ -108,7 +117,9 @@
// GTEST_HAS_PARAM_TEST - value-parameterized tests
// GTEST_HAS_TYPED_TEST - typed tests
// GTEST_HAS_TYPED_TEST_P - type-parameterized tests
-// GTEST_USES_POSIX_RE - enhanced POSIX regex is used.
+// GTEST_USES_POSIX_RE - enhanced POSIX regex is used. Do not confuse with
+// GTEST_HAS_POSIX_RE (see above) which users can
+// define themselves.
// GTEST_USES_SIMPLE_RE - our own simple regex is used;
// the above two are mutually exclusive.
// GTEST_CAN_COMPARE_NULL - accepts untyped NULL in EXPECT_EQ().
@@ -130,14 +141,17 @@
//
// Template meta programming:
// is_pointer - as in TR1; needed on Symbian and IBM XL C/C++ only.
+// IteratorTraits - partial implementation of std::iterator_traits, which
+// is not available in libCstd when compiled with Sun C++.
//
// Smart pointers:
// scoped_ptr - as in TR2.
//
// Regular expressions:
// RE - a simple regular expression class using the POSIX
-// Extended Regular Expression syntax. Not available on
-// Windows.
+// Extended Regular Expression syntax on UNIX-like
+// platforms, or a reduced regular exception syntax on
+// other platforms, including Windows.
//
// Logging:
// GTEST_LOG_() - logs messages at the specified severity level.
@@ -170,12 +184,14 @@
// Int32FromGTestEnv() - parses an Int32 environment variable.
// StringFromGTestEnv() - parses a string environment variable.
-#include <stddef.h> // For ptrdiff_t
+#include <ctype.h> // for isspace, etc
+#include <stddef.h> // for ptrdiff_t
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifndef _WIN32_WCE
-#include <sys/stat.h>
+# include <sys/types.h>
+# include <sys/stat.h>
#endif // !_WIN32_WCE
#include <iostream> // NOLINT
@@ -192,116 +208,140 @@
// Determines the version of gcc that is used to compile this.
#ifdef __GNUC__
// 40302 means version 4.3.2.
-#define GTEST_GCC_VER_ \
+# define GTEST_GCC_VER_ \
(__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__)
#endif // __GNUC__
// Determines the platform on which Google Test is compiled.
#ifdef __CYGWIN__
-#define GTEST_OS_CYGWIN 1
+# define GTEST_OS_CYGWIN 1
#elif defined __SYMBIAN32__
-#define GTEST_OS_SYMBIAN 1
+# define GTEST_OS_SYMBIAN 1
#elif defined _WIN32
-#define GTEST_OS_WINDOWS 1
-#ifdef _WIN32_WCE
-#define GTEST_OS_WINDOWS_MOBILE 1
-#elif defined(__MINGW__) || defined(__MINGW32__)
-#define GTEST_OS_WINDOWS_MINGW 1
-#else
-#define GTEST_OS_WINDOWS_DESKTOP 1
-#endif // _WIN32_WCE
+# define GTEST_OS_WINDOWS 1
+# ifdef _WIN32_WCE
+# define GTEST_OS_WINDOWS_MOBILE 1
+# elif defined(__MINGW__) || defined(__MINGW32__)
+# define GTEST_OS_WINDOWS_MINGW 1
+# else
+# define GTEST_OS_WINDOWS_DESKTOP 1
+# endif // _WIN32_WCE
#elif defined __APPLE__
-#define GTEST_OS_MAC 1
+# define GTEST_OS_MAC 1
#elif defined __linux__
-#define GTEST_OS_LINUX 1
+# define GTEST_OS_LINUX 1
+# ifdef ANDROID
+# define GTEST_OS_LINUX_ANDROID 1
+# endif // ANDROID
#elif defined __MVS__
-#define GTEST_OS_ZOS 1
+# define GTEST_OS_ZOS 1
#elif defined(__sun) && defined(__SVR4)
-#define GTEST_OS_SOLARIS 1
+# define GTEST_OS_SOLARIS 1
#elif defined(_AIX)
-#define GTEST_OS_AIX 1
+# define GTEST_OS_AIX 1
+#elif defined(__hpux)
+# define GTEST_OS_HPUX 1
+#elif defined __native_client__
+# define GTEST_OS_NACL 1
#elif defined(__HAIKU__)
-#define GTEST_OS_HAIKU 1
+# define GTEST_OS_HAIKU 1
#endif // __CYGWIN__
-#if GTEST_OS_CYGWIN || GTEST_OS_HAIKU || GTEST_OS_LINUX || GTEST_OS_MAC || \
- GTEST_OS_SYMBIAN || GTEST_OS_SOLARIS || GTEST_OS_AIX
+// Brings in definitions for functions used in the testing::internal::posix
+// namespace (read, write, close, chdir, isatty, stat). We do not currently
+// use them on Windows Mobile.
+#if !GTEST_OS_WINDOWS
+// This assumes that non-Windows OSes provide unistd.h. For OSes where this
+// is not the case, we need to include headers that provide the functions
+// mentioned above.
+# include <unistd.h>
+# if !GTEST_OS_NACL
+// TODO(vladl@google.com): Remove this condition when Native Client SDK adds
+// strings.h (tracked in
+// http://code.google.com/p/nativeclient/issues/detail?id=1175).
+# include <strings.h> // Native Client doesn't provide strings.h.
+# endif
+#elif !GTEST_OS_WINDOWS_MOBILE
+# include <direct.h>
+# include <io.h>
+#endif
+
+// Defines this to true iff Google Test can use POSIX regular expressions.
+#ifndef GTEST_HAS_POSIX_RE
+# define GTEST_HAS_POSIX_RE (!GTEST_OS_WINDOWS)
+#endif
+
+#if GTEST_HAS_POSIX_RE
// On some platforms, <regex.h> needs someone to define size_t, and
// won't compile otherwise. We can #include it here as we already
// included <stdlib.h>, which is guaranteed to define size_t through
// <stddef.h>.
-#include <regex.h> // NOLINT
-#include <strings.h> // NOLINT
-#include <sys/types.h> // NOLINT
-#include <time.h> // NOLINT
-#include <unistd.h> // NOLINT
+# include <regex.h> // NOLINT
-#define GTEST_USES_POSIX_RE 1
+# define GTEST_USES_POSIX_RE 1
#elif GTEST_OS_WINDOWS
-#if !GTEST_OS_WINDOWS_MOBILE
-#include <direct.h> // NOLINT
-#include <io.h> // NOLINT
-#endif
-
// <regex.h> is not available on Windows. Use our own simple regex
// implementation instead.
-#define GTEST_USES_SIMPLE_RE 1
+# define GTEST_USES_SIMPLE_RE 1
#else
// <regex.h> may not be available on this platform. Use our own
// simple regex implementation instead.
-#define GTEST_USES_SIMPLE_RE 1
+# define GTEST_USES_SIMPLE_RE 1
-#endif // GTEST_OS_CYGWIN || GTEST_OS_LINUX || GTEST_OS_MAC ||
- // GTEST_OS_SYMBIAN || GTEST_OS_SOLARIS || GTEST_OS_AIX
+#endif // GTEST_HAS_POSIX_RE
#ifndef GTEST_HAS_EXCEPTIONS
// The user didn't tell us whether exceptions are enabled, so we need
// to figure it out.
-#if defined(_MSC_VER) || defined(__BORLANDC__)
+# if defined(_MSC_VER) || defined(__BORLANDC__)
// MSVC's and C++Builder's implementations of the STL use the _HAS_EXCEPTIONS
// macro to enable exceptions, so we'll do the same.
// Assumes that exceptions are enabled by default.
-#ifndef _HAS_EXCEPTIONS
-#define _HAS_EXCEPTIONS 1
-#endif // _HAS_EXCEPTIONS
-#define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS
-#elif defined(__GNUC__) && __EXCEPTIONS
+# ifndef _HAS_EXCEPTIONS
+# define _HAS_EXCEPTIONS 1
+# endif // _HAS_EXCEPTIONS
+# define GTEST_HAS_EXCEPTIONS _HAS_EXCEPTIONS
+# elif defined(__GNUC__) && __EXCEPTIONS
// gcc defines __EXCEPTIONS to 1 iff exceptions are enabled.
-#define GTEST_HAS_EXCEPTIONS 1
-#elif defined(__SUNPRO_CC)
+# define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__SUNPRO_CC)
// Sun Pro CC supports exceptions. However, there is no compile-time way of
// detecting whether they are enabled or not. Therefore, we assume that
// they are enabled unless the user tells us otherwise.
-#define GTEST_HAS_EXCEPTIONS 1
-#elif defined(__IBMCPP__) && __EXCEPTIONS
+# define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__IBMCPP__) && __EXCEPTIONS
// xlC defines __EXCEPTIONS to 1 iff exceptions are enabled.
-#define GTEST_HAS_EXCEPTIONS 1
-#else
+# define GTEST_HAS_EXCEPTIONS 1
+# elif defined(__HP_aCC)
+// Exception handling is in effect by default in HP aCC compiler. It has to
+// be turned of by +noeh compiler option if desired.
+# define GTEST_HAS_EXCEPTIONS 1
+# else
// For other compilers, we assume exceptions are disabled to be
// conservative.
-#define GTEST_HAS_EXCEPTIONS 0
-#endif // defined(_MSC_VER) || defined(__BORLANDC__)
+# define GTEST_HAS_EXCEPTIONS 0
+# endif // defined(_MSC_VER) || defined(__BORLANDC__)
#endif // GTEST_HAS_EXCEPTIONS
#if !defined(GTEST_HAS_STD_STRING)
// Even though we don't use this macro any longer, we keep it in case
// some clients still depend on it.
-#define GTEST_HAS_STD_STRING 1
+# define GTEST_HAS_STD_STRING 1
#elif !GTEST_HAS_STD_STRING
// The user told us that ::std::string isn't available.
-#error "Google Test cannot be used where ::std::string isn't available."
+# error "Google Test cannot be used where ::std::string isn't available."
#endif // !defined(GTEST_HAS_STD_STRING)
#ifndef GTEST_HAS_GLOBAL_STRING
// The user didn't tell us whether ::string is available, so we need
// to figure it out.
-#define GTEST_HAS_GLOBAL_STRING 0
+# define GTEST_HAS_GLOBAL_STRING 0
#endif // GTEST_HAS_GLOBAL_STRING
@@ -311,18 +351,19 @@
// TODO(wan@google.com): uses autoconf to detect whether ::std::wstring
// is available.
-// Cygwin 1.5 and below doesn't support ::std::wstring.
-// Cygwin 1.7 might add wstring support; this should be updated when clear.
-// Solaris' libc++ doesn't support it either.
+// Cygwin 1.7 and below doesn't support ::std::wstring.
+// Solaris' libc++ doesn't support it either. Android has
+// no support for it at least as recent as Froyo (2.2).
// Minix currently doesn't support it either.
-#define GTEST_HAS_STD_WSTRING (!(GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || GTEST_OS_HAIKU || defined(_MINIX)))
+# define GTEST_HAS_STD_WSTRING \
+ (!(GTEST_OS_LINUX_ANDROID || GTEST_OS_CYGWIN || GTEST_OS_SOLARIS || GTEST_OS_HAIKU || defined(_MINIX)))
#endif // GTEST_HAS_STD_WSTRING
#ifndef GTEST_HAS_GLOBAL_WSTRING
// The user didn't tell us whether ::wstring is available, so we need
// to figure it out.
-#define GTEST_HAS_GLOBAL_WSTRING \
+# define GTEST_HAS_GLOBAL_WSTRING \
(GTEST_HAS_STD_WSTRING && GTEST_HAS_GLOBAL_STRING)
#endif // GTEST_HAS_GLOBAL_WSTRING
@@ -331,46 +372,46 @@
// The user didn't tell us whether RTTI is enabled, so we need to
// figure it out.
-#ifdef _MSC_VER
+# ifdef _MSC_VER
-#ifdef _CPPRTTI // MSVC defines this macro iff RTTI is enabled.
-#define GTEST_HAS_RTTI 1
-#else
-#define GTEST_HAS_RTTI 0
-#endif
+# ifdef _CPPRTTI // MSVC defines this macro iff RTTI is enabled.
+# define GTEST_HAS_RTTI 1
+# else
+# define GTEST_HAS_RTTI 0
+# endif
// Starting with version 4.3.2, gcc defines __GXX_RTTI iff RTTI is enabled.
-#elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302)
+# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40302)
-#ifdef __GXX_RTTI
-#define GTEST_HAS_RTTI 1
-#else
-#define GTEST_HAS_RTTI 0
-#endif // __GXX_RTTI
+# ifdef __GXX_RTTI
+# define GTEST_HAS_RTTI 1
+# else
+# define GTEST_HAS_RTTI 0
+# endif // __GXX_RTTI
// Starting with version 9.0 IBM Visual Age defines __RTTI_ALL__ to 1 if
// both the typeid and dynamic_cast features are present.
-#elif defined(__IBMCPP__) && (__IBMCPP__ >= 900)
+# elif defined(__IBMCPP__) && (__IBMCPP__ >= 900)
-#ifdef __RTTI_ALL__
-#define GTEST_HAS_RTTI 1
-#else
-#define GTEST_HAS_RTTI 0
-#endif
+# ifdef __RTTI_ALL__
+# define GTEST_HAS_RTTI 1
+# else
+# define GTEST_HAS_RTTI 0
+# endif
-#else
+# else
// For all other compilers, we assume RTTI is enabled.
-#define GTEST_HAS_RTTI 1
+# define GTEST_HAS_RTTI 1
-#endif // _MSC_VER
+# endif // _MSC_VER
#endif // GTEST_HAS_RTTI
// It's this header's responsibility to #include <typeinfo> when RTTI
// is enabled.
#if GTEST_HAS_RTTI
-#include <typeinfo>
+# include <typeinfo>
#endif
// Determines whether Google Test can use the pthreads library.
@@ -380,15 +421,24 @@
//
// 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)
+# define GTEST_HAS_PTHREAD (GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_HPUX)
#endif // GTEST_HAS_PTHREAD
+#if GTEST_HAS_PTHREAD
+// gtest-port.h guarantees to #include <pthread.h> when GTEST_HAS_PTHREAD is
+// true.
+# include <pthread.h> // NOLINT
+
+// For timespec and nanosleep, used below.
+# include <time.h> // NOLINT
+#endif
+
// Determines whether Google Test can use tr1/tuple. You can define
// this macro to 0 to prevent Google Test from using tuple (any
// feature depending on tuple with be disabled in this mode).
#ifndef GTEST_HAS_TR1_TUPLE
// The user didn't tell us not to do it, so we assume it's OK.
-#define GTEST_HAS_TR1_TUPLE 1
+# define GTEST_HAS_TR1_TUPLE 1
#endif // GTEST_HAS_TR1_TUPLE
// Determines whether Google Test's own tr1 tuple implementation
@@ -403,12 +453,13 @@
// defining __GNUC__ and friends, but cannot compile GCC's tuple
// implementation. MSVC 2008 (9.0) provides TR1 tuple in a 323 MB
// Feature Pack download, which we cannot assume the user has.
-#if (defined(__GNUC__) && !defined(__CUDACC__) && (GTEST_GCC_VER_ >= 40000)) \
+# if (defined(__GNUC__) && !(defined(__CUDACC__) || defined(__clang__)) \
+ && (GTEST_GCC_VER_ >= 40000)) \
|| _MSC_VER >= 1600
-#define GTEST_USE_OWN_TR1_TUPLE 0
-#else
-#define GTEST_USE_OWN_TR1_TUPLE 1
-#endif
+# define GTEST_USE_OWN_TR1_TUPLE 0
+# else
+# define GTEST_USE_OWN_TR1_TUPLE 1
+# endif
#endif // GTEST_USE_OWN_TR1_TUPLE
@@ -417,47 +468,47 @@
// tr1/tuple.
#if GTEST_HAS_TR1_TUPLE
-#if GTEST_USE_OWN_TR1_TUPLE
-#include <gtest/internal/gtest-tuple.h>
-#elif GTEST_OS_SYMBIAN
+# if GTEST_USE_OWN_TR1_TUPLE
+# include "gtest/internal/gtest-tuple.h"
+# elif GTEST_OS_SYMBIAN
// On Symbian, BOOST_HAS_TR1_TUPLE causes Boost's TR1 tuple library to
// use STLport's tuple implementation, which unfortunately doesn't
// work as the copy of STLport distributed with Symbian is incomplete.
// By making sure BOOST_HAS_TR1_TUPLE is undefined, we force Boost to
// use its own tuple implementation.
-#ifdef BOOST_HAS_TR1_TUPLE
-#undef BOOST_HAS_TR1_TUPLE
-#endif // BOOST_HAS_TR1_TUPLE
+# ifdef BOOST_HAS_TR1_TUPLE
+# undef BOOST_HAS_TR1_TUPLE
+# endif // BOOST_HAS_TR1_TUPLE
// This prevents <boost/tr1/detail/config.hpp>, which defines
// BOOST_HAS_TR1_TUPLE, from being #included by Boost's <tuple>.
-#define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED
-#include <tuple>
+# define BOOST_TR1_DETAIL_CONFIG_HPP_INCLUDED
+# include <tuple>
-#elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000)
+# elif defined(__GNUC__) && (GTEST_GCC_VER_ >= 40000)
// GCC 4.0+ implements tr1/tuple in the <tr1/tuple> header. This does
// not conform to the TR1 spec, which requires the header to be <tuple>.
-#if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+# if !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
// Until version 4.3.2, gcc has a bug that causes <tr1/functional>,
// which is #included by <tr1/tuple>, to not compile when RTTI is
// disabled. _TR1_FUNCTIONAL is the header guard for
// <tr1/functional>. Hence the following #define is a hack to prevent
// <tr1/functional> from being included.
-#define _TR1_FUNCTIONAL 1
-#include <tr1/tuple>
-#undef _TR1_FUNCTIONAL // Allows the user to #include
+# define _TR1_FUNCTIONAL 1
+# include <tr1/tuple>
+# undef _TR1_FUNCTIONAL // Allows the user to #include
// <tr1/functional> if he chooses to.
-#else
-#include <tr1/tuple> // NOLINT
-#endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
+# else
+# include <tr1/tuple> // NOLINT
+# endif // !GTEST_HAS_RTTI && GTEST_GCC_VER_ < 40302
-#else
+# else
// If the compiler is not GCC 4.0+, we assume the user is using a
// spec-conforming TR1 implementation.
-#include <tuple> // NOLINT
-#endif // GTEST_USE_OWN_TR1_TUPLE
+# include <tuple> // NOLINT
+# endif // GTEST_USE_OWN_TR1_TUPLE
#endif // GTEST_HAS_TR1_TUPLE
@@ -468,19 +519,25 @@
#ifndef GTEST_HAS_CLONE
// The user didn't tell us, so we need to figure it out.
-#if GTEST_OS_LINUX && !defined(__ia64__)
-#define GTEST_HAS_CLONE 1
-#else
-#define GTEST_HAS_CLONE 0
-#endif // GTEST_OS_LINUX && !defined(__ia64__)
+# if GTEST_OS_LINUX && !defined(__ia64__)
+# define GTEST_HAS_CLONE 1
+# else
+# define GTEST_HAS_CLONE 0
+# endif // GTEST_OS_LINUX && !defined(__ia64__)
#endif // GTEST_HAS_CLONE
// Determines whether to support stream redirection. This is used to test
// output correctness and to implement death tests.
-#if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN
-#define GTEST_HAS_STREAM_REDIRECTION_ 1
-#endif // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN
+#ifndef GTEST_HAS_STREAM_REDIRECTION
+// By default, we assume that stream redirection is supported on all
+// platforms except known mobile ones.
+# if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN
+# define GTEST_HAS_STREAM_REDIRECTION 0
+# else
+# define GTEST_HAS_STREAM_REDIRECTION 1
+# endif // !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_SYMBIAN
+#endif // GTEST_HAS_STREAM_REDIRECTION
// Determines whether to support death tests.
// Google Test does not support death tests for VC 7.1 and earlier as
@@ -488,9 +545,9 @@
// 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)
-#define GTEST_HAS_DEATH_TEST 1
-#include <vector> // NOLINT
+ GTEST_OS_WINDOWS_MINGW || GTEST_OS_AIX || GTEST_OS_HPUX)
+# define GTEST_HAS_DEATH_TEST 1
+# include <vector> // NOLINT
#endif
// We don't support MSVC 7.1 with exceptions disabled now. Therefore
@@ -501,11 +558,11 @@
// Determines whether to support type-driven tests.
// Typed tests need <typeinfo> and variadic macros, which GCC, VC++ 8.0,
-// Sun Pro CC, and IBM Visual Age support.
+// Sun Pro CC, IBM Visual Age, and HP aCC support.
#if defined(__GNUC__) || (_MSC_VER >= 1400) || defined(__SUNPRO_CC) || \
- defined(__IBMCPP__)
-#define GTEST_HAS_TYPED_TEST 1
-#define GTEST_HAS_TYPED_TEST_P 1
+ defined(__IBMCPP__) || defined(__HP_aCC)
+# define GTEST_HAS_TYPED_TEST 1
+# define GTEST_HAS_TYPED_TEST_P 1
#endif
// Determines whether to support Combine(). This only makes sense when
@@ -513,13 +570,18 @@
// work on Sun Studio since it doesn't understand templated conversion
// operators.
#if GTEST_HAS_PARAM_TEST && GTEST_HAS_TR1_TUPLE && !defined(__SUNPRO_CC)
-#define GTEST_HAS_COMBINE 1
+# define GTEST_HAS_COMBINE 1
#endif
// Determines whether the system compiler uses UTF-16 for encoding wide strings.
#define GTEST_WIDE_STRING_USES_UTF16_ \
(GTEST_OS_WINDOWS || GTEST_OS_CYGWIN || GTEST_OS_SYMBIAN || GTEST_OS_AIX)
+// Determines whether test results can be streamed to a socket.
+#if GTEST_OS_LINUX
+# define GTEST_CAN_STREAM_RESULTS_ 1
+#endif
+
// Defines some utility macros.
// The GNU compiler emits a warning if nested "if" statements are followed by
@@ -531,9 +593,9 @@
//
// The "switch (0) case 0:" idiom is used to suppress this.
#ifdef __INTEL_COMPILER
-#define GTEST_AMBIGUOUS_ELSE_BLOCKER_
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_
#else
-#define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: // NOLINT
+# define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default: // NOLINT
#endif
// Use this annotation at the end of a struct/class definition to
@@ -548,9 +610,9 @@
// Also use it after a variable or parameter declaration to tell the
// compiler the variable/parameter does not have to be used.
#if defined(__GNUC__) && !defined(COMPILER_ICC)
-#define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
+# define GTEST_ATTRIBUTE_UNUSED_ __attribute__ ((unused))
#else
-#define GTEST_ATTRIBUTE_UNUSED_
+# define GTEST_ATTRIBUTE_UNUSED_
#endif
// A macro to disallow operator=
@@ -570,9 +632,9 @@
//
// Sprocket* AllocateSprocket() GTEST_MUST_USE_RESULT_;
#if defined(__GNUC__) && (GTEST_GCC_VER_ >= 30400) && !defined(COMPILER_ICC)
-#define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result))
+# define GTEST_MUST_USE_RESULT_ __attribute__ ((warn_unused_result))
#else
-#define GTEST_MUST_USE_RESULT_
+# define GTEST_MUST_USE_RESULT_
#endif // __GNUC__ && (GTEST_GCC_VER_ >= 30400) && !COMPILER_ICC
// Determine whether the compiler supports Microsoft's Structured Exception
@@ -581,28 +643,35 @@
#ifndef GTEST_HAS_SEH
// The user didn't tell us, so we need to figure it out.
-#if defined(_MSC_VER) || defined(__BORLANDC__)
+# if defined(_MSC_VER) || defined(__BORLANDC__)
// These two compilers are known to support SEH.
-#define GTEST_HAS_SEH 1
-#else
+# define GTEST_HAS_SEH 1
+# else
// Assume no SEH.
-#define GTEST_HAS_SEH 0
-#endif
+# define GTEST_HAS_SEH 0
+# endif
#endif // GTEST_HAS_SEH
#ifdef _MSC_VER
-#if GTEST_LINKED_AS_SHARED_LIBRARY
-#define GTEST_API_ __declspec(dllimport)
-#elif GTEST_CREATE_SHARED_LIBRARY
-#define GTEST_API_ __declspec(dllexport)
-#endif
+# if GTEST_LINKED_AS_SHARED_LIBRARY
+# define GTEST_API_ __declspec(dllimport)
+# elif GTEST_CREATE_SHARED_LIBRARY
+# define GTEST_API_ __declspec(dllexport)
+# endif
#endif // _MSC_VER
#ifndef GTEST_API_
-#define GTEST_API_
+# define GTEST_API_
+#endif
+
+#ifdef __GNUC__
+// Ask the compiler to never inline a given function.
+# define GTEST_NO_INLINE_ __attribute__((noinline))
+#else
+# define GTEST_NO_INLINE_
#endif
namespace testing {
@@ -613,7 +682,90 @@
class String;
-typedef ::std::stringstream StrStream;
+// The GTEST_COMPILE_ASSERT_ macro can be used to verify that a compile time
+// expression is true. For example, you could use it to verify the
+// size of a static array:
+//
+// GTEST_COMPILE_ASSERT_(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES,
+// content_type_names_incorrect_size);
+//
+// or to make sure a struct is smaller than a certain size:
+//
+// GTEST_COMPILE_ASSERT_(sizeof(foo) < 128, foo_too_large);
+//
+// The second argument to the macro is the name of the variable. If
+// the expression is false, most compilers will issue a warning/error
+// containing the name of the variable.
+
+template <bool>
+struct CompileAssert {
+};
+
+#define GTEST_COMPILE_ASSERT_(expr, msg) \
+ typedef ::testing::internal::CompileAssert<(bool(expr))> \
+ msg[bool(expr) ? 1 : -1]
+
+// Implementation details of GTEST_COMPILE_ASSERT_:
+//
+// - GTEST_COMPILE_ASSERT_ works by defining an array type that has -1
+// elements (and thus is invalid) when the expression is false.
+//
+// - The simpler definition
+//
+// #define GTEST_COMPILE_ASSERT_(expr, msg) typedef char msg[(expr) ? 1 : -1]
+//
+// does not work, as gcc supports variable-length arrays whose sizes
+// are determined at run-time (this is gcc's extension and not part
+// of the C++ standard). As a result, gcc fails to reject the
+// following code with the simple definition:
+//
+// int foo;
+// GTEST_COMPILE_ASSERT_(foo, msg); // not supposed to compile as foo is
+// // not a compile-time constant.
+//
+// - By using the type CompileAssert<(bool(expr))>, we ensures that
+// expr is a compile-time constant. (Template arguments must be
+// determined at compile-time.)
+//
+// - The outter parentheses in CompileAssert<(bool(expr))> are necessary
+// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
+//
+// CompileAssert<bool(expr)>
+//
+// instead, these compilers will refuse to compile
+//
+// GTEST_COMPILE_ASSERT_(5 > 0, some_message);
+//
+// (They seem to think the ">" in "5 > 0" marks the end of the
+// template argument list.)
+//
+// - The array size is (bool(expr) ? 1 : -1), instead of simply
+//
+// ((expr) ? 1 : -1).
+//
+// This is to avoid running into a bug in MS VC 7.1, which
+// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
+
+// StaticAssertTypeEqHelper is used by StaticAssertTypeEq defined in gtest.h.
+//
+// This template is declared, but intentionally undefined.
+template <typename T1, typename T2>
+struct StaticAssertTypeEqHelper;
+
+template <typename T>
+struct StaticAssertTypeEqHelper<T, T> {};
+
+#if GTEST_HAS_GLOBAL_STRING
+typedef ::string string;
+#else
+typedef ::std::string string;
+#endif // GTEST_HAS_GLOBAL_STRING
+
+#if GTEST_HAS_GLOBAL_WSTRING
+typedef ::wstring wstring;
+#elif GTEST_HAS_STD_WSTRING
+typedef ::std::wstring wstring;
+#endif // GTEST_HAS_GLOBAL_WSTRING
// A helper for suppressing warnings on constant condition. It just
// returns 'condition'.
@@ -669,7 +821,9 @@
RE(const ::std::string& regex) { Init(regex.c_str()); } // NOLINT
#if GTEST_HAS_GLOBAL_STRING
+
RE(const ::string& regex) { Init(regex.c_str()); } // NOLINT
+
#endif // GTEST_HAS_GLOBAL_STRING
RE(const char* regex) { Init(regex); } // NOLINT
@@ -693,12 +847,14 @@
}
#if GTEST_HAS_GLOBAL_STRING
+
static bool FullMatch(const ::string& str, const RE& re) {
return FullMatch(str.c_str(), re);
}
static bool PartialMatch(const ::string& str, const RE& re) {
return PartialMatch(str.c_str(), re);
}
+
#endif // GTEST_HAS_GLOBAL_STRING
static bool FullMatch(const char* str, const RE& re);
@@ -713,16 +869,31 @@
// files.
const char* pattern_;
bool is_valid_;
+
#if GTEST_USES_POSIX_RE
+
regex_t full_regex_; // For FullMatch().
regex_t partial_regex_; // For PartialMatch().
+
#else // GTEST_USES_SIMPLE_RE
+
const char* full_pattern_; // For FullMatch();
+
#endif
GTEST_DISALLOW_ASSIGN_(RE);
};
+// Formats a source file path and a line number as they would appear
+// in an error message from the compiler used to compile this code.
+GTEST_API_ ::std::string FormatFileLocation(const char* file, int line);
+
+// Formats a file location for compiler-independent XML output.
+// Although this function is not platform dependent, we put it next to
+// FormatFileLocation in order to contrast the two functions.
+GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(const char* file,
+ int line);
+
// Defines logging utilities:
// GTEST_LOG_(severity) - logs messages at the specified severity level. The
// message itself is streamed into the macro.
@@ -794,6 +965,66 @@
// INTERNAL IMPLEMENTATION - DO NOT USE IN USER CODE.
//
+// Use ImplicitCast_ as a safe version of static_cast for upcasting in
+// the type hierarchy (e.g. casting a Foo* to a SuperclassOfFoo* or a
+// const Foo*). When you use ImplicitCast_, the compiler checks that
+// the cast is safe. Such explicit ImplicitCast_s are necessary in
+// surprisingly many situations where C++ demands an exact type match
+// instead of an argument type convertable to a target type.
+//
+// The syntax for using ImplicitCast_ is the same as for static_cast:
+//
+// ImplicitCast_<ToType>(expr)
+//
+// ImplicitCast_ would have been part of the C++ standard library,
+// but the proposal was submitted too late. It will probably make
+// its way into the language in the future.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., implicit_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To>
+inline To ImplicitCast_(To x) { return x; }
+
+// When you upcast (that is, cast a pointer from type Foo to type
+// SuperclassOfFoo), it's fine to use ImplicitCast_<>, since upcasts
+// always succeed. When you downcast (that is, cast a pointer from
+// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
+// how do you know the pointer is really of type SubclassOfFoo? It
+// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus,
+// when you downcast, you should use this macro. In debug mode, we
+// use dynamic_cast<> to double-check the downcast is legal (we die
+// if it's not). In normal mode, we do the efficient static_cast<>
+// instead. Thus, it's important to test in debug mode to make sure
+// the cast is legal!
+// This is the only place in the code we should use dynamic_cast<>.
+// In particular, you SHOULDN'T be using dynamic_cast<> in order to
+// do RTTI (eg code like this:
+// if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
+// if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
+// You should design the code some other way not to need this.
+//
+// This relatively ugly name is intentional. It prevents clashes with
+// similar functions users may have (e.g., down_cast). The internal
+// namespace alone is not enough because the function can be found by ADL.
+template<typename To, typename From> // use like this: DownCast_<T*>(foo);
+inline To DownCast_(From* f) { // so we only accept pointers
+ // Ensures that To is a sub-type of From *. This test is here only
+ // for compile-time type checking, and has no overhead in an
+ // optimized build at run-time, as it will be optimized away
+ // completely.
+ if (false) {
+ const To to = NULL;
+ ::testing::internal::ImplicitCast_<From*>(to);
+ }
+
+#if GTEST_HAS_RTTI
+ // RTTI: debug mode only!
+ GTEST_CHECK_(f == NULL || dynamic_cast<To>(f) != NULL);
+#endif
+ return static_cast<To>(f);
+}
+
// Downcasts the pointer of type Base to Derived.
// Derived must be a subclass of Base. The parameter MUST
// point to a class of type Derived, not any subclass of it.
@@ -809,7 +1040,7 @@
#endif
}
-#if GTEST_HAS_STREAM_REDIRECTION_
+#if GTEST_HAS_STREAM_REDIRECTION
// Defines the stderr capturer:
// CaptureStdout - starts capturing stdout.
@@ -822,7 +1053,7 @@
GTEST_API_ void CaptureStderr();
GTEST_API_ String GetCapturedStderr();
-#endif // GTEST_HAS_STREAM_REDIRECTION_
+#endif // GTEST_HAS_STREAM_REDIRECTION
#if GTEST_HAS_DEATH_TEST
@@ -956,10 +1187,6 @@
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParam);
};
-// gtest-port.h guarantees to #include <pthread.h> when GTEST_HAS_PTHREAD is
-// true.
-#include <pthread.h>
-
// MutexBase and Mutex implement mutex on pthreads-based platforms. They
// are used in conjunction with class MutexLock:
//
@@ -1014,11 +1241,11 @@
};
// Forward-declares a static mutex.
-#define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
extern ::testing::internal::MutexBase mutex
// Defines and statically (i.e. at link time) initializes a static mutex.
-#define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) \
::testing::internal::MutexBase mutex = { PTHREAD_MUTEX_INITIALIZER, 0 }
// The Mutex class can only be used for mutexes created at runtime. It
@@ -1165,7 +1392,7 @@
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadLocal);
};
-#define GTEST_IS_THREADSAFE 1
+# define GTEST_IS_THREADSAFE 1
#else // GTEST_HAS_PTHREAD
@@ -1180,10 +1407,10 @@
void AssertHeld() const {}
};
-#define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
+# define GTEST_DECLARE_STATIC_MUTEX_(mutex) \
extern ::testing::internal::Mutex mutex
-#define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
+# define GTEST_DEFINE_STATIC_MUTEX_(mutex) ::testing::internal::Mutex mutex
class GTestMutexLock {
public:
@@ -1207,7 +1434,7 @@
// The above synchronization primitives have dummy implementations.
// Therefore Google Test is not thread-safe.
-#define GTEST_IS_THREADSAFE 0
+# define GTEST_IS_THREADSAFE 0
#endif // GTEST_HAS_PTHREAD
@@ -1224,9 +1451,9 @@
#if defined(__SYMBIAN32__) || defined(__IBMCPP__) || defined(__SUNPRO_CC)
// We lose support for NULL detection where the compiler doesn't like
// passing non-POD classes through ellipsis (...).
-#define GTEST_ELLIPSIS_NEEDS_POD_ 1
+# define GTEST_ELLIPSIS_NEEDS_POD_ 1
#else
-#define GTEST_CAN_COMPARE_NULL 1
+# define GTEST_CAN_COMPARE_NULL 1
#endif
// The Nokia Symbian and IBM XL C/C++ compilers cannot decide between
@@ -1234,7 +1461,7 @@
// _can_ decide between class template specializations for T and T*,
// so a tr1::type_traits-like is_pointer works.
#if defined(__SYMBIAN32__) || defined(__IBMCPP__)
-#define GTEST_NEEDS_IS_POINTER_ 1
+# define GTEST_NEEDS_IS_POINTER_ 1
#endif
template <bool bool_value>
@@ -1253,17 +1480,68 @@
template <typename T>
struct is_pointer<T*> : public true_type {};
+template <typename Iterator>
+struct IteratorTraits {
+ typedef typename Iterator::value_type value_type;
+};
+
+template <typename T>
+struct IteratorTraits<T*> {
+ typedef T value_type;
+};
+
+template <typename T>
+struct IteratorTraits<const T*> {
+ typedef T value_type;
+};
+
#if GTEST_OS_WINDOWS
-#define GTEST_PATH_SEP_ "\\"
-#define GTEST_HAS_ALT_PATH_SEP_ 1
+# define GTEST_PATH_SEP_ "\\"
+# define GTEST_HAS_ALT_PATH_SEP_ 1
// The biggest signed integer type the compiler supports.
typedef __int64 BiggestInt;
#else
-#define GTEST_PATH_SEP_ "/"
-#define GTEST_HAS_ALT_PATH_SEP_ 0
+# define GTEST_PATH_SEP_ "/"
+# define GTEST_HAS_ALT_PATH_SEP_ 0
typedef long long BiggestInt; // NOLINT
#endif // GTEST_OS_WINDOWS
+// Utilities for char.
+
+// isspace(int ch) and friends accept an unsigned char or EOF. char
+// may be signed, depending on the compiler (or compiler flags).
+// Therefore we need to cast a char to unsigned char before calling
+// isspace(), etc.
+
+inline bool IsAlpha(char ch) {
+ return isalpha(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsAlNum(char ch) {
+ return isalnum(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsDigit(char ch) {
+ return isdigit(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsLower(char ch) {
+ return islower(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsSpace(char ch) {
+ return isspace(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsUpper(char ch) {
+ return isupper(static_cast<unsigned char>(ch)) != 0;
+}
+inline bool IsXDigit(char ch) {
+ return isxdigit(static_cast<unsigned char>(ch)) != 0;
+}
+
+inline char ToLower(char ch) {
+ return static_cast<char>(tolower(static_cast<unsigned char>(ch)));
+}
+inline char ToUpper(char ch) {
+ return static_cast<char>(toupper(static_cast<unsigned char>(ch)));
+}
+
// The testing::internal::posix namespace holds wrappers for common
// POSIX functions. These wrappers hide the differences between
// Windows/MSVC and POSIX systems. Since some compilers define these
@@ -1278,36 +1556,36 @@
typedef struct _stat StatStruct;
-#ifdef __BORLANDC__
+# ifdef __BORLANDC__
inline int IsATTY(int fd) { return isatty(fd); }
inline int StrCaseCmp(const char* s1, const char* s2) {
return stricmp(s1, s2);
}
inline char* StrDup(const char* src) { return strdup(src); }
-#else // !__BORLANDC__
-#if GTEST_OS_WINDOWS_MOBILE
+# else // !__BORLANDC__
+# if GTEST_OS_WINDOWS_MOBILE
inline int IsATTY(int /* fd */) { return 0; }
-#else
+# else
inline int IsATTY(int fd) { return _isatty(fd); }
-#endif // GTEST_OS_WINDOWS_MOBILE
+# endif // GTEST_OS_WINDOWS_MOBILE
inline int StrCaseCmp(const char* s1, const char* s2) {
return _stricmp(s1, s2);
}
inline char* StrDup(const char* src) { return _strdup(src); }
-#endif // __BORLANDC__
+# endif // __BORLANDC__
-#if GTEST_OS_WINDOWS_MOBILE
+# if GTEST_OS_WINDOWS_MOBILE
inline int FileNo(FILE* file) { return reinterpret_cast<int>(_fileno(file)); }
// Stat(), RmDir(), and IsDir() are not needed on Windows CE at this
// time and thus not defined there.
-#else
+# else
inline int FileNo(FILE* file) { return _fileno(file); }
inline int Stat(const char* path, StatStruct* buf) { return _stat(path, buf); }
inline int RmDir(const char* dir) { return _rmdir(dir); }
inline bool IsDir(const StatStruct& st) {
return (_S_IFDIR & st.st_mode) != 0;
}
-#endif // GTEST_OS_WINDOWS_MOBILE
+# endif // GTEST_OS_WINDOWS_MOBILE
#else
@@ -1329,8 +1607,8 @@
#ifdef _MSC_VER
// Temporarily disable warning 4996 (deprecated function).
-#pragma warning(push)
-#pragma warning(disable:4996)
+# pragma warning(push)
+# pragma warning(disable:4996)
#endif
inline const char* StrNCpy(char* dest, const char* src, size_t n) {
@@ -1379,7 +1657,7 @@
}
#ifdef _MSC_VER
-#pragma warning(pop) // Restores the warning state.
+# pragma warning(pop) // Restores the warning state.
#endif
#if GTEST_OS_WINDOWS_MOBILE
@@ -1445,6 +1723,7 @@
template <>
class TypeWithSize<8> {
public:
+
#if GTEST_OS_WINDOWS
typedef __int64 Int;
typedef unsigned __int64 UInt;
diff --git a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-string.h b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-string.h
index aff093de..dc3a07b 100644
--- a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-string.h
+++ b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-string.h
@@ -43,11 +43,11 @@
#ifdef __BORLANDC__
// string.h is not guaranteed to provide strcpy on C++ Builder.
-#include <mem.h>
+# include <mem.h>
#endif
#include <string.h>
-#include <gtest/internal/gtest-port.h>
+#include "gtest/internal/gtest-port.h"
#include <string>
@@ -296,7 +296,7 @@
private:
// Constructs a non-NULL String from the given content. This
- // function can only be called when data_ has not been allocated.
+ // function can only be called when c_str_ has not been allocated.
// ConstructNonNull(NULL, 0) results in an empty string ("").
// ConstructNonNull(NULL, non_zero) is undefined behavior.
void ConstructNonNull(const char* buffer, size_t a_length) {
@@ -329,9 +329,9 @@
return os;
}
-// Gets the content of the StrStream's buffer as a String. Each '\0'
+// Gets the content of the stringstream's buffer as a String. Each '\0'
// character in the buffer is replaced with "\\0".
-GTEST_API_ String StrStreamToString(StrStream* stream);
+GTEST_API_ String StringStreamToString(::std::stringstream* stream);
// Converts a streamable value to a String. A NULL pointer is
// converted to "(null)". When the input value is a ::string,
diff --git a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h
index 16178fc..d1af50e 100644
--- a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h
+++ b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-tuple.h
@@ -44,9 +44,9 @@
// private as public.
// Sun Studio versions < 12 also have the above bug.
#if defined(__SYMBIAN32__) || (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
-#define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ public:
#else
-#define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
+# define GTEST_DECLARE_TUPLE_AS_FRIEND_ \
template <GTEST_10_TYPENAMES_(U)> friend class tuple; \
private:
#endif
diff --git a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h
index 093eee6..b7b01b0 100644
--- a/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h
+++ b/src/LLVM/utils/unittest/googletest/include/gtest/internal/gtest-type-util.h
@@ -44,20 +44,52 @@
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
-#include <gtest/internal/gtest-port.h>
-#include <gtest/internal/gtest-string.h>
-
-#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+#include "gtest/internal/gtest-port.h"
+#include "gtest/internal/gtest-string.h"
// #ifdef __GNUC__ is too general here. It is possible to use gcc without using
// libstdc++ (which is where cxxabi.h comes from).
-#ifdef __GLIBCXX__
-#include <cxxabi.h>
-#endif // __GLIBCXX__
+# ifdef __GLIBCXX__
+# include <cxxabi.h>
+# elif defined(__HP_aCC)
+# include <acxx_demangle.h>
+# endif // __GLIBCXX__
namespace testing {
namespace internal {
+// GetTypeName<T>() returns a human-readable name of type T.
+// NB: This function is also used in Google Mock, so don't move it inside of
+// the typed-test-only section below.
+template <typename T>
+String GetTypeName() {
+# if GTEST_HAS_RTTI
+
+ const char* const name = typeid(T).name();
+# if defined(__GLIBCXX__) || defined(__HP_aCC)
+ int status = 0;
+ // gcc's implementation of typeid(T).name() mangles the type name,
+ // so we have to demangle it.
+# ifdef __GLIBCXX__
+ using abi::__cxa_demangle;
+# endif // __GLIBCXX__
+ char* const readable_name = __cxa_demangle(name, 0, 0, &status);
+ const String name_str(status == 0 ? readable_name : name);
+ free(readable_name);
+ return name_str;
+# else
+ return name;
+# endif // __GLIBCXX__ || __HP_aCC
+
+# else
+
+ return "<type>";
+
+# endif // GTEST_HAS_RTTI
+}
+
+#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
// AssertyTypeEq<T1, T2>::type is defined iff T1 and T2 are the same
// type. This can be used as a compile-time assertion to ensure that
// two types are equal.
@@ -70,29 +102,6 @@
typedef bool type;
};
-// GetTypeName<T>() returns a human-readable name of type T.
-template <typename T>
-String GetTypeName() {
-#if GTEST_HAS_RTTI
-
- const char* const name = typeid(T).name();
-#ifdef __GLIBCXX__
- int status = 0;
- // gcc's implementation of typeid(T).name() mangles the type name,
- // so we have to demangle it.
- char* const readable_name = abi::__cxa_demangle(name, 0, 0, &status);
- const String name_str(status == 0 ? readable_name : name);
- free(readable_name);
- return name_str;
-#else
- return name;
-#endif // __GLIBCXX__
-
-#else
- return "<type>";
-#endif // GTEST_HAS_RTTI
-}
-
// A unique type used as the default value for the arguments of class
// template Types. This allows us to simulate variadic templates
// (e.g. Types<int>, Type<int, double>, and etc), which C++ doesn't
@@ -1611,7 +1620,7 @@
namespace internal {
-#define GTEST_TEMPLATE_ template <typename T> class
+# define GTEST_TEMPLATE_ template <typename T> class
// The template "selector" struct TemplateSel<Tmpl> is used to
// represent Tmpl, which must be a class template with one type
@@ -1629,7 +1638,7 @@
};
};
-#define GTEST_BIND_(TmplSel, T) \
+# define GTEST_BIND_(TmplSel, T) \
TmplSel::template Bind<T>::type
// A unique struct template used as the default value for the
@@ -3313,9 +3322,9 @@
T41, T42, T43, T44, T45, T46, T47, T48, T49, T50>::type type;
};
+#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
+
} // namespace internal
} // namespace testing
-#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P
-
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_TYPE_UTIL_H_
diff --git a/src/LLVM/utils/valgrind/i386-pc-linux-gnu.supp b/src/LLVM/utils/valgrind/i386-pc-linux-gnu.supp
new file mode 100644
index 0000000..ddd0a08
--- /dev/null
+++ b/src/LLVM/utils/valgrind/i386-pc-linux-gnu.supp
@@ -0,0 +1,48 @@
+{
+ False leak under RegisterPass
+ Memcheck:Leak
+ ...
+ fun:_ZN83_GLOBAL_*PassRegistrar12RegisterPassERKN4llvm8PassInfoE
+ fun:_ZN4llvm8PassInfo12registerPassEv
+}
+
+# Python false positives according to
+# http://svn.python.org/projects/python/trunk/Misc/README.valgrind
+
+{
+ ADDRESS_IN_RANGE/Invalid read of size 4
+ Memcheck:Addr4
+ obj:/usr/bin/python*
+}
+
+{
+ ADDRESS_IN_RANGE/Invalid read of size 4
+ Memcheck:Value4
+ obj:/usr/bin/python*
+}
+
+{
+ ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value
+ Memcheck:Cond
+ obj:/usr/bin/python*
+}
+
+{
+ We don't care if as leaks
+ Memcheck:Leak
+ obj:/usr/bin/as
+}
+
+{
+ We don't care if python leaks
+ Memcheck:Leak
+ fun:malloc
+ obj:/usr/bin/python*
+}
+
+{
+ We don't care about anything ld.so does.
+ Memcheck:Cond
+ obj:/lib/ld*.so
+}
+
diff --git a/src/LLVM/utils/valgrind/x86_64-pc-linux-gnu.supp b/src/LLVM/utils/valgrind/x86_64-pc-linux-gnu.supp
new file mode 100644
index 0000000..fc863b8
--- /dev/null
+++ b/src/LLVM/utils/valgrind/x86_64-pc-linux-gnu.supp
@@ -0,0 +1,64 @@
+{
+ False leak under RegisterPass
+ Memcheck:Leak
+ ...
+ fun:_ZN4llvm12PassRegistry12registerPassERKNS_8PassInfoE
+}
+
+# Python false positives according to
+# http://svn.python.org/projects/python/trunk/Misc/README.valgrind
+
+{
+ ADDRESS_IN_RANGE/Invalid read of size 4
+ Memcheck:Addr4
+ obj:/usr/bin/python*
+}
+
+{
+ ADDRESS_IN_RANGE/Invalid read of size 4
+ Memcheck:Value8
+ obj:/usr/bin/python*
+}
+
+{
+ ADDRESS_IN_RANGE/Conditional jump or move depends on uninitialised value
+ Memcheck:Cond
+ obj:/usr/bin/python*
+}
+
+{
+ We don't care if as leaks
+ Memcheck:Leak
+ obj:/usr/bin/as
+}
+
+{
+ We don't care if grep leaks
+ Memcheck:Leak
+ obj:/bin/grep
+}
+
+{
+ We don't care if python leaks
+ Memcheck:Leak
+ fun:malloc
+ obj:/usr/bin/python*
+}
+
+{
+ We don't care about anything ld.so does.
+ Memcheck:Cond
+ obj:/lib/ld*.so
+}
+
+{
+ suppress optimized strcasecmp, to be fixed in valgrind 3.6.1
+ Memcheck:Value8
+ fun:__GI___strcasecmp_l
+}
+
+{
+ suppress optimized strcasecmp, to be fixed in valgrind 3.6.1
+ Memcheck:Addr8
+ fun:__GI___strcasecmp_l
+}
diff --git a/src/LLVM/utils/vim/llvm.vim b/src/LLVM/utils/vim/llvm.vim
index 66419ec..2f36501 100644
--- a/src/LLVM/utils/vim/llvm.vim
+++ b/src/LLVM/utils/vim/llvm.vim
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: llvm
" Maintainer: The LLVM team, http://llvm.org/
-" Version: $Revision: 109772 $
+" Version: $Revision: 137806 $
if version < 600
syntax clear
@@ -49,19 +49,18 @@
syn keyword llvmKeyword except deplibs
syn keyword llvmKeyword volatile fastcc coldcc cc ccc
syn keyword llvmKeyword x86_stdcallcc x86_fastcallcc
+syn keyword llvmKeyword ptx_kernel ptx_device
syn keyword llvmKeyword signext zeroext inreg sret nounwind noreturn
-syn keyword llvmKeyword nocapture byval nest readnone readonly noalias
+syn keyword llvmKeyword nocapture byval nest readnone readonly noalias uwtable
syn keyword llvmKeyword inlinehint noinline alwaysinline optsize ssp sspreq
syn keyword llvmKeyword noredzone noimplicitfloat naked alignstack
syn keyword llvmKeyword module asm align tail to
syn keyword llvmKeyword addrspace section alias sideeffect c gc
syn keyword llvmKeyword target datalayout triple
syn keyword llvmKeyword blockaddress
-syn keyword llvmKeyword union
" Obsolete keywords.
-syn keyword llvmError uninitialized implementation
-syn keyword llvmError getresult big little endian begin end
+syn keyword llvmError getresult begin end
" Misc syntax.
syn match llvmNoName /[%@]\d\+\>/
diff --git a/src/LLVM/utils/vim/tablegen.vim b/src/LLVM/utils/vim/tablegen.vim
index ffd4ea8..b452bc4 100644
--- a/src/LLVM/utils/vim/tablegen.vim
+++ b/src/LLVM/utils/vim/tablegen.vim
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: TableGen
" Maintainer: The LLVM team, http://llvm.org/
-" Version: $Revision: 97271 $
+" Version: $Revision: 141378 $
if version < 600
syntax clear
diff --git a/src/LLVM/utils/vim/vimrc b/src/LLVM/utils/vim/vimrc
index a48a068..05daf69 100644
--- a/src/LLVM/utils/vim/vimrc
+++ b/src/LLVM/utils/vim/vimrc
@@ -1,5 +1,5 @@
" LLVM coding guidelines conformance for VIM
-" $Revision: 97273 $
+" $Revision: 117415 $
"
" Maintainer: The LLVM Team, http://llvm.org
" WARNING: Read before you source in all these commands and macros! Some
@@ -91,3 +91,131 @@
"set showmode
"set incsearch
"set ruler
+
+" Clang code-completion support. This is somewhat experimental!
+
+" A path to a clang executable.
+let g:clang_path = "clang++"
+
+" A list of options to add to the clang commandline, for example to add
+" include paths, predefined macros, and language options.
+let g:clang_opts = [
+ \ "-x","c++",
+ \ "-D__STDC_LIMIT_MACROS=1","-D__STDC_CONSTANT_MACROS=1",
+ \ "-Iinclude" ]
+
+function! ClangComplete(findstart, base)
+ if a:findstart == 1
+ " In findstart mode, look for the beginning of the current identifier.
+ let l:line = getline('.')
+ let l:start = col('.') - 1
+ while l:start > 0 && l:line[l:start - 1] =~ '\i'
+ let l:start -= 1
+ endwhile
+ return l:start
+ endif
+
+ " Get the current line and column numbers.
+ let l:l = line('.')
+ let l:c = col('.')
+
+ " Build a clang commandline to do code completion on stdin.
+ let l:the_command = shellescape(g:clang_path) .
+ \ " -cc1 -code-completion-at=-:" . l:l . ":" . l:c
+ for l:opt in g:clang_opts
+ let l:the_command .= " " . shellescape(l:opt)
+ endfor
+
+ " Copy the contents of the current buffer into a string for stdin.
+ " TODO: The extra space at the end is for working around clang's
+ " apparent inability to do code completion at the very end of the
+ " input.
+ " TODO: Is it better to feed clang the entire file instead of truncating
+ " it at the current line?
+ let l:process_input = join(getline(1, l:l), "\n") . " "
+
+ " Run it!
+ let l:input_lines = split(system(l:the_command, l:process_input), "\n")
+
+ " Parse the output.
+ for l:input_line in l:input_lines
+ " Vim's substring operator is annoyingly inconsistent with python's.
+ if l:input_line[:11] == 'COMPLETION: '
+ let l:value = l:input_line[12:]
+
+ " Chop off anything after " : ", if present, and move it to the menu.
+ let l:menu = ""
+ let l:spacecolonspace = stridx(l:value, " : ")
+ if l:spacecolonspace != -1
+ let l:menu = l:value[l:spacecolonspace+3:]
+ let l:value = l:value[:l:spacecolonspace-1]
+ endif
+
+ " Chop off " (Hidden)", if present, and move it to the menu.
+ let l:hidden = stridx(l:value, " (Hidden)")
+ if l:hidden != -1
+ let l:menu .= " (Hidden)"
+ let l:value = l:value[:l:hidden-1]
+ endif
+
+ " Handle "Pattern". TODO: Make clang less weird.
+ if l:value == "Pattern"
+ let l:value = l:menu
+ let l:pound = stridx(l:value, "#")
+ " Truncate the at the first [#, <#, or {#.
+ if l:pound != -1
+ let l:value = l:value[:l:pound-2]
+ endif
+ endif
+
+ " Filter out results which don't match the base string.
+ if a:base != ""
+ if l:value[:strlen(a:base)-1] != a:base
+ continue
+ end
+ endif
+
+ " TODO: Don't dump the raw input into info, though it's nice for now.
+ " TODO: The kind string?
+ let l:item = {
+ \ "word": l:value,
+ \ "menu": l:menu,
+ \ "info": l:input_line,
+ \ "dup": 1 }
+
+ " Report a result.
+ if complete_add(l:item) == 0
+ return []
+ endif
+ if complete_check()
+ return []
+ endif
+
+ elseif l:input_line[:9] == "OVERLOAD: "
+ " An overload candidate. Use a crazy hack to get vim to
+ " display the results. TODO: Make this better.
+ let l:value = l:input_line[10:]
+ let l:item = {
+ \ "word": " ",
+ \ "menu": l:value,
+ \ "info": l:input_line,
+ \ "dup": 1}
+
+ " Report a result.
+ if complete_add(l:item) == 0
+ return []
+ endif
+ if complete_check()
+ return []
+ endif
+
+ endif
+ endfor
+
+
+ return []
+endfunction ClangComplete
+
+" This to enables the somewhat-experimental clang-based
+" autocompletion support.
+set omnifunc=ClangComplete