summaryrefslogtreecommitdiffstats
path: root/utils
diff options
context:
space:
mode:
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp23
-rw-r--r--utils/TableGen/CMakeLists.txt1
-rw-r--r--utils/TableGen/ClangASTNodesEmitter.cpp141
-rw-r--r--utils/TableGen/ClangASTNodesEmitter.h36
-rw-r--r--utils/TableGen/ClangDiagnosticsEmitter.cpp19
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp5
-rw-r--r--utils/TableGen/CodeGenRegisters.h4
-rw-r--r--utils/TableGen/CodeGenTarget.cpp42
-rw-r--r--utils/TableGen/CodeGenTarget.h22
-rw-r--r--utils/TableGen/DAGISelMatcherGen.cpp9
-rw-r--r--utils/TableGen/EDEmitter.cpp9
-rw-r--r--utils/TableGen/FastISelEmitter.cpp33
-rw-r--r--utils/TableGen/IntrinsicEmitter.cpp19
-rw-r--r--utils/TableGen/IntrinsicEmitter.h3
-rw-r--r--utils/TableGen/Makefile4
-rw-r--r--utils/TableGen/Record.h2
-rw-r--r--utils/TableGen/RegisterInfoEmitter.cpp408
-rw-r--r--utils/TableGen/TableGen.cpp27
-rw-r--r--utils/TableGen/X86RecognizableInstr.cpp10
-rw-r--r--utils/buildit/GNUmakefile9
-rwxr-xr-xutils/buildit/build_llvm51
-rw-r--r--utils/lit/lit/LitConfig.py2
-rw-r--r--utils/lit/lit/ShUtil.py7
-rw-r--r--utils/lit/lit/TestFormats.py4
-rwxr-xr-xutils/lit/lit/lit.py25
-rw-r--r--utils/valgrind/i386-pc-linux-gnu.supp7
-rw-r--r--utils/valgrind/x86_64-pc-linux-gnu.supp7
27 files changed, 639 insertions, 290 deletions
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index 1947824..4ba3df1 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -388,6 +388,9 @@ public:
/// operator< - Compare two classes.
bool operator<(const ClassInfo &RHS) const {
+ if (this == &RHS)
+ return false;
+
// Unrelated classes can be ordered by kind.
if (!isRelatedTo(RHS))
return Kind < RHS.Kind;
@@ -403,7 +406,13 @@ public:
default:
// This class preceeds the RHS if it is a proper subset of the RHS.
- return this != &RHS && isSubsetOf(RHS);
+ if (isSubsetOf(RHS))
+ return true;
+ if (RHS.isSubsetOf(*this))
+ return false;
+
+ // Otherwise, order by name to ensure we have a total ordering.
+ return ValueName < RHS.ValueName;
}
}
};
@@ -794,15 +803,19 @@ void AsmMatcherInfo::BuildOperandClasses(CodeGenTarget &Target) {
ClassInfo *CI = AsmOperandClasses[*it];
CI->Kind = ClassInfo::UserClass0 + Index;
- Init *Super = (*it)->getValueInit("SuperClass");
- if (DefInit *DI = dynamic_cast<DefInit*>(Super)) {
+ ListInit *Supers = (*it)->getValueAsListInit("SuperClasses");
+ for (unsigned i = 0, e = Supers->getSize(); i != e; ++i) {
+ DefInit *DI = dynamic_cast<DefInit*>(Supers->getElement(i));
+ if (!DI) {
+ PrintError((*it)->getLoc(), "Invalid super class reference!");
+ continue;
+ }
+
ClassInfo *SC = AsmOperandClasses[DI->getDef()];
if (!SC)
PrintError((*it)->getLoc(), "Invalid super class reference!");
else
CI->SuperClasses.push_back(SC);
- } else {
- assert(dynamic_cast<UnsetInit*>(Super) && "Unexpected SuperClass field!");
}
CI->ClassName = (*it)->getValueAsString("Name");
CI->Name = "MCK_" + CI->ClassName;
diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt
index f68159a..731cde9 100644
--- a/utils/TableGen/CMakeLists.txt
+++ b/utils/TableGen/CMakeLists.txt
@@ -4,6 +4,7 @@ add_executable(tblgen
AsmWriterEmitter.cpp
AsmWriterInst.cpp
CallingConvEmitter.cpp
+ ClangASTNodesEmitter.cpp
ClangDiagnosticsEmitter.cpp
CodeEmitterGen.cpp
CodeGenDAGPatterns.cpp
diff --git a/utils/TableGen/ClangASTNodesEmitter.cpp b/utils/TableGen/ClangASTNodesEmitter.cpp
new file mode 100644
index 0000000..5d6423d
--- /dev/null
+++ b/utils/TableGen/ClangASTNodesEmitter.cpp
@@ -0,0 +1,141 @@
+//=== ClangASTNodesEmitter.cpp - Generate Clang AST node tables -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These tablegen backends emit Clang AST node tables
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangASTNodesEmitter.h"
+#include "Record.h"
+#include <map>
+#include <cctype>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// Statement Node Tables (.inc file) generation.
+//===----------------------------------------------------------------------===//
+
+// Create a macro-ized version of a name
+static std::string macroName(std::string S) {
+ for (unsigned i = 0; i < S.size(); ++i)
+ S[i] = std::toupper(S[i]);
+
+ return S;
+}
+
+// A map from a node to each of its derived nodes.
+typedef std::multimap<Record*, Record*> ChildMap;
+typedef ChildMap::const_iterator ChildIterator;
+
+// Returns the first and last non-abstract subrecords
+// Called recursively to ensure that nodes remain contiguous
+static std::pair<Record *, Record *> EmitStmtNode(const ChildMap &Tree,
+ raw_ostream &OS,
+ Record *Base,
+ bool Root = true) {
+ std::string BaseName = macroName(Base->getName());
+
+ ChildIterator i = Tree.lower_bound(Base), e = Tree.upper_bound(Base);
+
+ Record *First = 0, *Last = 0;
+ // This might be the pseudo-node for Stmt; don't assume it has an Abstract
+ // bit
+ if (Base->getValue("Abstract") && !Base->getValueAsBit("Abstract"))
+ First = Last = Base;
+
+ for (; i != e; ++i) {
+ Record *R = i->second;
+ bool Abstract = R->getValueAsBit("Abstract");
+ std::string NodeName = macroName(R->getName());
+
+ OS << "#ifndef " << NodeName << "\n";
+ OS << "# define " << NodeName << "(Type, Base) "
+ << BaseName << "(Type, Base)\n";
+ OS << "#endif\n";
+
+ if (Abstract)
+ OS << "ABSTRACT_STMT(" << NodeName << "(" << R->getName() << ", "
+ << Base->getName() << "))\n";
+ else
+ OS << NodeName << "(" << R->getName() << ", "
+ << Base->getName() << ")\n";
+
+ if (Tree.find(R) != Tree.end()) {
+ const std::pair<Record *, Record *> &Result
+ = EmitStmtNode(Tree, OS, R, false);
+ if (!First && Result.first)
+ First = Result.first;
+ if (Result.second)
+ Last = Result.second;
+ } else {
+ if (!Abstract) {
+ Last = R;
+
+ if (!First)
+ First = R;
+ }
+ }
+
+ OS << "#undef " << NodeName << "\n\n";
+ }
+
+ if (First) {
+ assert (Last && "Got a first node but not a last node for a range!");
+ if (Root)
+ OS << "LAST_STMT_RANGE(";
+ else
+ OS << "STMT_RANGE(";
+
+ OS << Base->getName() << ", " << First->getName() << ", "
+ << Last->getName() << ")\n\n";
+ }
+
+ return std::make_pair(First, Last);
+}
+
+void ClangStmtNodesEmitter::run(raw_ostream &OS) {
+ // Write the preamble
+ OS << "#ifndef ABSTRACT_STMT\n";
+ OS << "# define ABSTRACT_STMT(Stmt) Stmt\n";
+ OS << "#endif\n";
+
+ OS << "#ifndef STMT_RANGE\n";
+ OS << "# define STMT_RANGE(Base, First, Last)\n";
+ OS << "#endif\n\n";
+
+ OS << "#ifndef LAST_STMT_RANGE\n";
+ OS << "# define LAST_STMT_RANGE(Base, First, Last) "
+ "STMT_RANGE(Base, First, Last)\n";
+ OS << "#endif\n\n";
+
+ // Emit statements
+ const std::vector<Record*> Stmts = Records.getAllDerivedDefinitions("Stmt");
+
+ ChildMap Tree;
+
+ // Create a pseudo-record to serve as the Stmt node, which isn't actually
+ // output.
+ Record Stmt ("Stmt", SMLoc());
+
+ for (unsigned i = 0, e = Stmts.size(); i != e; ++i) {
+ Record *R = Stmts[i];
+
+ if (R->getValue("Base"))
+ Tree.insert(std::make_pair(R->getValueAsDef("Base"), R));
+ else
+ Tree.insert(std::make_pair(&Stmt, R));
+ }
+
+ EmitStmtNode(Tree, OS, &Stmt);
+
+ OS << "#undef STMT\n";
+ OS << "#undef STMT_RANGE\n";
+ OS << "#undef LAST_STMT_RANGE\n";
+ OS << "#undef ABSTRACT_STMT\n";
+}
diff --git a/utils/TableGen/ClangASTNodesEmitter.h b/utils/TableGen/ClangASTNodesEmitter.h
new file mode 100644
index 0000000..c4ce9fa
--- /dev/null
+++ b/utils/TableGen/ClangASTNodesEmitter.h
@@ -0,0 +1,36 @@
+//===- ClangASTNodesEmitter.h - Generate Clang AST node tables -*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These tablegen backends emit Clang AST node tables
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANGAST_EMITTER_H
+#define CLANGAST_EMITTER_H
+
+#include "TableGenBackend.h"
+
+namespace llvm {
+
+/// ClangStmtNodesEmitter - The top-level class emits .def files containing
+/// declarations of Clang statements.
+///
+class ClangStmtNodesEmitter : public TableGenBackend {
+ RecordKeeper &Records;
+public:
+ explicit ClangStmtNodesEmitter(RecordKeeper &R)
+ : Records(R) {}
+
+ // run - Output the .def file contents
+ void run(raw_ostream &OS);
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/utils/TableGen/ClangDiagnosticsEmitter.cpp b/utils/TableGen/ClangDiagnosticsEmitter.cpp
index d0e813b..75b6252 100644
--- a/utils/TableGen/ClangDiagnosticsEmitter.cpp
+++ b/utils/TableGen/ClangDiagnosticsEmitter.cpp
@@ -70,15 +70,16 @@ getCategoryFromDiagGroup(const Record *Group,
/// lives in.
static std::string getDiagnosticCategory(const Record *R,
DiagGroupParentMap &DiagGroupParents) {
- // If the diagnostic itself has a category, get it.
- std::string CatName = R->getValueAsString("CategoryName");
- if (!CatName.empty()) return CatName;
-
- DefInit *Group = dynamic_cast<DefInit*>(R->getValueInit("Group"));
- if (Group == 0) return "";
+ // If the diagnostic is in a group, and that group has a category, use it.
+ if (DefInit *Group = dynamic_cast<DefInit*>(R->getValueInit("Group"))) {
+ // Check the diagnostic's diag group for a category.
+ std::string CatName = getCategoryFromDiagGroup(Group->getDef(),
+ DiagGroupParents);
+ if (!CatName.empty()) return CatName;
+ }
- // Check the diagnostic's diag group for a category.
- return getCategoryFromDiagGroup(Group->getDef(), DiagGroupParents);
+ // If the diagnostic itself has a category, get it.
+ return R->getValueAsString("CategoryName");
}
namespace {
@@ -239,7 +240,7 @@ void ClangDiagGroupsEmitter::run(raw_ostream &OS) {
const std::vector<std::string> &SubGroups = I->second.SubGroups;
if (!SubGroups.empty()) {
- OS << "static const char DiagSubGroup" << I->second.IDNo << "[] = { ";
+ OS << "static const short DiagSubGroup" << I->second.IDNo << "[] = { ";
for (unsigned i = 0, e = SubGroups.size(); i != e; ++i) {
std::map<std::string, GroupInfo>::iterator RI =
DiagsInGroup.find(SubGroups[i]);
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index a0bccfc..878ed09 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -1057,6 +1057,11 @@ static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo,
const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
return EEVT::TypeSet(T.getRegisterVTs(R));
}
+
+ if (R->isSubClassOf("SubRegIndex")) {
+ 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!");
diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h
index 6f8682b..344f77f 100644
--- a/utils/TableGen/CodeGenRegisters.h
+++ b/utils/TableGen/CodeGenRegisters.h
@@ -16,6 +16,7 @@
#define CODEGEN_REGISTERS_H
#include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/ADT/DenseMap.h"
#include <string>
#include <vector>
#include <cstdlib>
@@ -40,7 +41,8 @@ namespace llvm {
unsigned SpillSize;
unsigned SpillAlignment;
int CopyCost;
- std::vector<Record*> SubRegClasses;
+ // Map SubRegIndex -> RegisterClass
+ DenseMap<Record*,Record*> SubRegClasses;
std::string MethodProtos, MethodBodies;
const std::string &getName() const;
diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp
index 1efe2ff..3797992 100644
--- a/utils/TableGen/CodeGenTarget.cpp
+++ b/utils/TableGen/CodeGenTarget.cpp
@@ -80,6 +80,7 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) {
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";
@@ -158,6 +159,7 @@ 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());
@@ -172,6 +174,11 @@ const std::string &CodeGenRegister::getName() const {
return TheDef->getName();
}
+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");
@@ -228,17 +235,30 @@ CodeGenRegisterClass::CodeGenRegisterClass(Record *R) : TheDef(R) {
"' does not derive from the Register class!";
Elements.push_back(Reg);
}
-
- std::vector<Record*> SubRegClassList =
- R->getValueAsListOfDefs("SubRegClassList");
- for (unsigned i = 0, e = SubRegClassList.size(); i != e; ++i) {
- Record *SubRegClass = SubRegClassList[i];
- if (!SubRegClass->isSubClassOf("RegisterClass"))
- throw "Register Class member '" + SubRegClass->getName() +
- "' does not derive from the RegisterClass class!";
- SubRegClasses.push_back(SubRegClass);
- }
-
+
+ // 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");
diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h
index 2926418..6b06b66 100644
--- a/utils/TableGen/CodeGenTarget.h
+++ b/utils/TableGen/CodeGenTarget.h
@@ -19,14 +19,12 @@
#include "CodeGenRegisters.h"
#include "CodeGenInstruction.h"
+#include "Record.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/ADT/DenseMap.h"
#include <algorithm>
namespace llvm {
-class Record;
-class RecordKeeper;
struct CodeGenRegister;
class CodeGenTarget;
@@ -65,9 +63,11 @@ class CodeGenTarget {
mutable DenseMap<const Record*, CodeGenInstruction*> Instructions;
mutable std::vector<CodeGenRegister> Registers;
+ mutable std::vector<Record*> SubRegIndices;
mutable std::vector<CodeGenRegisterClass> RegisterClasses;
mutable std::vector<MVT::SimpleValueType> LegalValueTypes;
void ReadRegisters() const;
+ void ReadSubRegIndices() const;
void ReadRegisterClasses() const;
void ReadInstructions() const;
void ReadLegalValueTypes() const;
@@ -100,11 +100,25 @@ public:
return Registers;
}
+ const std::vector<Record*> &getSubRegIndices() const {
+ if (SubRegIndices.empty()) ReadSubRegIndices();
+ return SubRegIndices;
+ }
+
+ // 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 CodeGenRegisterClass &getRegisterClass(Record *R) const {
const std::vector<CodeGenRegisterClass> &RC = getRegisterClasses();
for (unsigned i = 0, e = RC.size(); i != e; ++i)
diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp
index 9d469a9..eb528eb 100644
--- a/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/utils/TableGen/DAGISelMatcherGen.cpp
@@ -224,6 +224,7 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) {
if (// Handle register references. Nothing to do here, they always match.
LeafRec->isSubClassOf("RegisterClass") ||
LeafRec->isSubClassOf("PointerLikeRegClass") ||
+ LeafRec->isSubClassOf("SubRegIndex") ||
// Place holder for SRCVALUE nodes. Nothing to do here.
LeafRec->getName() == "srcvalue")
return;
@@ -597,6 +598,14 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N,
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());
+ AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ return;
+ }
}
errs() << "unhandled leaf node: \n";
diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp
index d3bf60e..0d5ee40 100644
--- a/utils/TableGen/EDEmitter.cpp
+++ b/utils/TableGen/EDEmitter.cpp
@@ -309,8 +309,7 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type,
REG("RST");
REG("SEGMENT_REG");
REG("DEBUG_REG");
- REG("CONTROL_REG_32");
- REG("CONTROL_REG_64");
+ REG("CONTROL_REG");
IMM("i8imm");
IMM("i16imm");
@@ -575,10 +574,12 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
REG("s_cc_out");
REG("tGPR");
REG("DPR");
- REG("SPR");
- REG("QPR");
REG("DPR_VFP2");
REG("DPR_8");
+ REG("SPR");
+ REG("QPR");
+ REG("QQPR");
+ REG("QQQQPR");
IMM("i32imm");
IMM("bf_inv_mask_imm");
diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp
index ba59e50..9ec9e08 100644
--- a/utils/TableGen/FastISelEmitter.cpp
+++ b/utils/TableGen/FastISelEmitter.cpp
@@ -31,7 +31,7 @@ namespace {
struct InstructionMemo {
std::string Name;
const CodeGenRegisterClass *RC;
- unsigned char SubRegNo;
+ std::string SubRegNo;
std::vector<std::string>* PhysRegs;
};
@@ -123,7 +123,7 @@ struct OperandsSignature {
void PrintParameters(raw_ostream &OS) const {
for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
if (Operands[i] == "r") {
- OS << "unsigned Op" << i;
+ OS << "unsigned Op" << i << ", bool Op" << i << "IsKill";
} else if (Operands[i] == "i") {
OS << "uint64_t imm" << i;
} else if (Operands[i] == "f") {
@@ -149,7 +149,7 @@ struct OperandsSignature {
if (PrintedArg)
OS << ", ";
if (Operands[i] == "r") {
- OS << "Op" << i;
+ OS << "Op" << i << ", Op" << i << "IsKill";
PrintedArg = true;
} else if (Operands[i] == "i") {
OS << "imm" << i;
@@ -167,7 +167,7 @@ struct OperandsSignature {
void PrintArguments(raw_ostream &OS) const {
for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
if (Operands[i] == "r") {
- OS << "Op" << i;
+ OS << "Op" << i << ", Op" << i << "IsKill";
} else if (Operands[i] == "i") {
OS << "imm" << i;
} else if (Operands[i] == "f") {
@@ -278,7 +278,7 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) {
// For now, ignore instructions where the first operand is not an
// output register.
const CodeGenRegisterClass *DstRC = 0;
- unsigned SubRegNo = ~0;
+ std::string SubRegNo;
if (Op->getName() != "EXTRACT_SUBREG") {
Record *Op0Rec = II.OperandList[0].Rec;
if (!Op0Rec->isSubClassOf("RegisterClass"))
@@ -287,8 +287,11 @@ void FastISelMap::CollectPatterns(CodeGenDAGPatterns &CGP) {
if (!DstRC)
continue;
} else {
- SubRegNo = static_cast<IntInit*>(
- Dst->getChild(1)->getLeafValue())->getValue();
+ DefInit *SR = dynamic_cast<DefInit*>(Dst->getChild(1)->getLeafValue());
+ if (SR)
+ SubRegNo = getQualifiedName(SR->getDef());
+ else
+ SubRegNo = Dst->getChild(1)->getLeafValue()->getAsString();
}
// Inspect the pattern.
@@ -433,11 +436,11 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) {
<< (*Memo.PhysRegs)[i] << ", Op" << i << ", "
<< "TM.getRegisterInfo()->getPhysicalRegisterRegClass("
<< (*Memo.PhysRegs)[i] << "), "
- << "MRI.getRegClass(Op" << i << "));\n";
+ << "MRI.getRegClass(Op" << i << "), DL);\n";
}
OS << " return FastEmitInst_";
- if (Memo.SubRegNo == (unsigned char)~0) {
+ if (Memo.SubRegNo.empty()) {
Operands.PrintManglingSuffix(OS, *Memo.PhysRegs);
OS << "(" << InstNS << Memo.Name << ", ";
OS << InstNS << Memo.RC->getName() << "RegisterClass";
@@ -447,8 +450,8 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) {
OS << ");\n";
} else {
OS << "extractsubreg(" << getName(RetVT);
- OS << ", Op0, ";
- OS << (unsigned)Memo.SubRegNo;
+ OS << ", Op0, Op0IsKill, ";
+ OS << Memo.SubRegNo;
OS << ");\n";
}
@@ -527,12 +530,12 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) {
<< (*Memo.PhysRegs)[i] << ", Op" << i << ", "
<< "TM.getRegisterInfo()->getPhysicalRegisterRegClass("
<< (*Memo.PhysRegs)[i] << "), "
- << "MRI.getRegClass(Op" << i << "));\n";
+ << "MRI.getRegClass(Op" << i << "), DL);\n";
}
OS << " return FastEmitInst_";
- if (Memo.SubRegNo == (unsigned char)~0) {
+ if (Memo.SubRegNo.empty()) {
Operands.PrintManglingSuffix(OS, *Memo.PhysRegs);
OS << "(" << InstNS << Memo.Name << ", ";
OS << InstNS << Memo.RC->getName() << "RegisterClass";
@@ -541,8 +544,8 @@ void FastISelMap::PrintFunctionDefinitions(raw_ostream &OS) {
Operands.PrintArguments(OS, *Memo.PhysRegs);
OS << ");\n";
} else {
- OS << "extractsubreg(RetVT, Op0, ";
- OS << (unsigned)Memo.SubRegNo;
+ OS << "extractsubreg(RetVT, Op0, Op0IsKill, ";
+ OS << Memo.SubRegNo;
OS << ");\n";
}
diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp
index 417aca7..d7a9051 100644
--- a/utils/TableGen/IntrinsicEmitter.cpp
+++ b/utils/TableGen/IntrinsicEmitter.cpp
@@ -30,6 +30,8 @@ void IntrinsicEmitter::run(raw_ostream &OS) {
if (TargetOnly && !Ints.empty())
TargetPrefix = Ints[0].TargetPrefix;
+ EmitPrefix(OS);
+
// Emit the enum information.
EmitEnumInfo(Ints, OS);
@@ -59,6 +61,23 @@ void IntrinsicEmitter::run(raw_ostream &OS) {
// Emit code to translate GCC builtins into LLVM intrinsics.
EmitIntrinsicToGCCBuiltinMap(Ints, OS);
+
+ EmitSuffix(OS);
+}
+
+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"
+ "#endif\n\n";
+}
+
+void IntrinsicEmitter::EmitSuffix(raw_ostream &OS) {
+ OS << "#if defined(_MSC_VER) && defined(setjmp_undefined_for_visual_studio)\n"
+ "// let's return it to _setjmp state\n"
+ "#define setjmp _setjmp\n"
+ "#endif\n\n";
}
void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
diff --git a/utils/TableGen/IntrinsicEmitter.h b/utils/TableGen/IntrinsicEmitter.h
index c3c92bc..b1efecb 100644
--- a/utils/TableGen/IntrinsicEmitter.h
+++ b/utils/TableGen/IntrinsicEmitter.h
@@ -28,6 +28,8 @@ namespace llvm {
: Records(R), TargetOnly(T) {}
void run(raw_ostream &OS);
+
+ void EmitPrefix(raw_ostream &OS);
void EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
raw_ostream &OS);
@@ -50,6 +52,7 @@ namespace llvm {
raw_ostream &OS);
void EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
raw_ostream &OS);
+ void EmitSuffix(raw_ostream &OS);
};
} // End llvm namespace
diff --git a/utils/TableGen/Makefile b/utils/TableGen/Makefile
index 7ea88de..f27cd99 100644
--- a/utils/TableGen/Makefile
+++ b/utils/TableGen/Makefile
@@ -1,10 +1,10 @@
##===- utils/TableGen/Makefile -----------------------------*- Makefile -*-===##
-#
+#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
-#
+#
##===----------------------------------------------------------------------===##
LEVEL = ../..
diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h
index 576d626..8f9fd95 100644
--- a/utils/TableGen/Record.h
+++ b/utils/TableGen/Record.h
@@ -1461,7 +1461,7 @@ public:
///
struct LessRecord {
bool operator()(const Record *Rec1, const Record *Rec2) const {
- return Rec1->getName() < Rec2->getName();
+ return StringRef(Rec1->getName()).compare_numeric(Rec2->getName()) < 0;
}
};
diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp
index fcf4123..c99bbd9 100644
--- a/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/utils/TableGen/RegisterInfoEmitter.cpp
@@ -35,14 +35,29 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS) {
if (!Namespace.empty())
OS << "namespace " << Namespace << " {\n";
- OS << " enum {\n NoRegister,\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 << " NUM_TARGET_REGS \t// " << Registers.size()+1 << "\n";
- OS << " };\n";
+ OS << " " << Registers[i].getName() << ", \t// " << i+1 << "\n";
+ 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");
+ 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 << "};\n";
+ if (!Namespace.empty())
+ OS << "}\n";
+ }
OS << "} // End llvm namespace \n";
}
@@ -156,6 +171,90 @@ static void addSubSuperReg(Record *R, Record *S,
addSubSuperReg(R, *I, SubRegs, SuperRegs, Aliases);
}
+// Map SubRegIndex -> Register
+typedef std::map<Record*, Record*, LessRecord> SubRegMap;
+// Map Register -> SubRegMap
+typedef std::map<Record*, SubRegMap> AllSubRegMap;
+
+// Calculate all subregindices for Reg. Loopy subregs cause infinite recursion.
+static SubRegMap &inferSubRegIndices(Record *Reg, AllSubRegMap &ASRM) {
+ SubRegMap &SRM = ASRM[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], ASRM);
+ }
+
+ // 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 = ASRM[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 = ASRM[R2].find(IdxInit->getDef());
+ if (ni == ASRM[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;
+}
+
class RegisterSorter {
private:
std::map<Record*, std::set<Record*>, LessRecord> &RegisterSubRegs;
@@ -243,80 +342,82 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
std::map<unsigned, std::set<unsigned> > SuperRegClassMap;
OS << "\n";
- // Emit the sub-register classes for each RegisterClass
- for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
- const CodeGenRegisterClass &RC = RegisterClasses[rc];
+ unsigned NumSubRegIndices = Target.getSubRegIndices().size();
+
+ if (NumSubRegIndices) {
+ // Emit the sub-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);
+ 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;
+ }
+ }
+ }
- // Give the register class a legal C name if it's anonymous.
- std::string Name = RC.TheDef->getName();
+ // 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 ";
+ OS << " // " << Name
+ << " Sub-register Classes...\n"
+ << " static const TargetRegisterClass* const "
+ << Name << "SubRegClasses[] = {\n ";
- bool Empty = true;
+ 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";
+ }
- for (unsigned subrc = 0, subrcMax = RC.SubRegClasses.size();
- subrc != subrcMax; ++subrc) {
- unsigned rc2 = 0, e2 = RegisterClasses.size();
- for (; rc2 != e2; ++rc2) {
- const CodeGenRegisterClass &RC2 = RegisterClasses[rc2];
- if (RC.SubRegClasses[subrc]->getName() == RC2.getName()) {
+ // Emit the super-register classes for each RegisterClass
+ for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
+ const CodeGenRegisterClass &RC = RegisterClasses[rc];
+
+ // Give the register class a legal C name if it's anonymous.
+ std::string Name = RC.TheDef->getName();
+
+ OS << " // " << Name
+ << " Super-register Classes...\n"
+ << " static const TargetRegisterClass* const "
+ << Name << "SuperRegClasses[] = {\n ";
+
+ bool Empty = true;
+ std::map<unsigned, std::set<unsigned> >::iterator I =
+ SuperRegClassMap.find(rc);
+ 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];
if (!Empty)
OS << ", ";
OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
Empty = false;
-
- std::map<unsigned, std::set<unsigned> >::iterator SCMI =
- SuperRegClassMap.find(rc2);
- if (SCMI == SuperRegClassMap.end()) {
- SuperRegClassMap.insert(std::make_pair(rc2,
- std::set<unsigned>()));
- SCMI = SuperRegClassMap.find(rc2);
- }
- SCMI->second.insert(rc);
- break;
}
}
- if (rc2 == e2)
- throw "Register Class member '" +
- RC.SubRegClasses[subrc]->getName() +
- "' is not a valid RegisterClass!";
- }
-
- OS << (!Empty ? ", " : "") << "NULL";
- 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];
-
- // Give the register class a legal C name if it's anonymous.
- std::string Name = RC.TheDef->getName();
- OS << " // " << Name
- << " Super-register Classes...\n"
- << " static const TargetRegisterClass* const "
- << Name << "SuperRegClasses[] = {\n ";
-
- bool Empty = true;
- std::map<unsigned, std::set<unsigned> >::iterator I =
- SuperRegClassMap.find(rc);
- 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];
- if (!Empty)
- OS << ", ";
- OS << "&" << getQualifiedName(RC2.TheDef) << "RegClass";
- Empty = false;
- }
+ OS << (!Empty ? ", " : "") << "NULL";
+ OS << "\n };\n\n";
}
-
- 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
@@ -413,8 +514,10 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
<< RC.getName() + "VTs" << ", "
<< RC.getName() + "Subclasses" << ", "
<< RC.getName() + "Superclasses" << ", "
- << RC.getName() + "SubRegClasses" << ", "
- << RC.getName() + "SuperRegClasses" << ", "
+ << (NumSubRegIndices ? RC.getName() + "Sub" : std::string("Null"))
+ << "RegClasses, "
+ << (NumSubRegIndices ? RC.getName() + "Super" : std::string("Null"))
+ << "RegClasses, "
<< RC.SpillSize/8 << ", "
<< RC.SpillAlignment/8 << ", "
<< RC.CopyCost << ", "
@@ -436,7 +539,6 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
std::map<Record*, std::set<Record*>, LessRecord> RegisterSubRegs;
std::map<Record*, std::set<Record*>, LessRecord> RegisterSuperRegs;
std::map<Record*, std::set<Record*>, LessRecord> RegisterAliases;
- std::map<Record*, std::vector<std::pair<int, Record*> > > SubRegVectors;
typedef std::map<Record*, std::vector<int64_t>, LessRecord> DwarfRegNumsMapTy;
DwarfRegNumsMapTy DwarfRegNums;
@@ -556,83 +658,6 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
delete [] SubregHashTable;
- // Print the SuperregHashTable, a simple quadratically probed
- // hash table for determining if a register is a super-register
- // of another register.
- unsigned NumSupRegs = 0;
- RegNo.clear();
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- RegNo[Regs[i].TheDef] = i;
- NumSupRegs += RegisterSuperRegs[Regs[i].TheDef].size();
- }
-
- unsigned SuperregHashTableSize = 2 * NextPowerOf2(2 * NumSupRegs);
- unsigned* SuperregHashTable = new unsigned[2 * SuperregHashTableSize];
- std::fill(SuperregHashTable, SuperregHashTable + 2 * SuperregHashTableSize, ~0U);
-
- hashMisses = 0;
-
- for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
- Record* R = Regs[i].TheDef;
- for (std::set<Record*>::iterator I = RegisterSuperRegs[R].begin(),
- E = RegisterSuperRegs[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) & (SuperregHashTableSize-1);
- unsigned ProbeAmt = 2;
- while (SuperregHashTable[index*2] != ~0U &&
- SuperregHashTable[index*2+1] != ~0U) {
- index = (index + ProbeAmt) & (SuperregHashTableSize-1);
- ProbeAmt += 2;
-
- hashMisses++;
- }
-
- SuperregHashTable[index*2] = i;
- SuperregHashTable[index*2+1] = RegNo[RJ];
- }
- }
-
- OS << "\n\n // Number of hash collisions: " << hashMisses << "\n";
-
- if (SuperregHashTableSize) {
- std::string Namespace = Regs[0].TheDef->getValueAsString("Namespace");
-
- OS << " const unsigned SuperregHashTable[] = { ";
- for (unsigned i = 0; i < SuperregHashTableSize - 1; ++i) {
- if (i != 0)
- // Insert spaces for nice formatting.
- OS << " ";
-
- if (SuperregHashTable[2*i] != ~0U) {
- OS << getQualifiedName(Regs[SuperregHashTable[2*i]].TheDef) << ", "
- << getQualifiedName(Regs[SuperregHashTable[2*i+1]].TheDef) << ", \n";
- } else {
- OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister, \n";
- }
- }
-
- unsigned Idx = SuperregHashTableSize*2-2;
- if (SuperregHashTable[Idx] != ~0U) {
- OS << " "
- << getQualifiedName(Regs[SuperregHashTable[Idx]].TheDef) << ", "
- << getQualifiedName(Regs[SuperregHashTable[Idx+1]].TheDef) << " };\n";
- } else {
- OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister };\n";
- }
-
- OS << " const unsigned SuperregHashTableSize = "
- << SuperregHashTableSize << ";\n";
- } else {
- OS << " const unsigned SuperregHashTable[] = { ~0U, ~0U };\n"
- << " const unsigned SuperregHashTableSize = 1;\n";
- }
-
- delete [] SuperregHashTable;
-
-
// Print the AliasHashTable, a simple quadratically probed
// hash table for determining if a register aliases another register.
unsigned NumAliases = 0;
@@ -717,6 +742,8 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
// 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)
@@ -733,6 +760,8 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
// 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(),
@@ -754,6 +783,8 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
// 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;
@@ -772,78 +803,77 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
// Now that register alias and sub-registers sets have been emitted, emit the
// register descriptors now.
- const std::vector<CodeGenRegister> &Registers = Target.getRegisters();
- for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
- const CodeGenRegister &Reg = Registers[i];
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ const CodeGenRegister &Reg = Regs[i];
OS << " { \"";
OS << Reg.getName() << "\",\t";
- if (RegisterAliases.count(Reg.TheDef))
+ if (!RegisterAliases[Reg.TheDef].empty())
OS << Reg.getName() << "_AliasSet,\t";
else
OS << "Empty_AliasSet,\t";
- if (RegisterSubRegs.count(Reg.TheDef))
+ if (!RegisterSubRegs[Reg.TheDef].empty())
OS << Reg.getName() << "_SubRegsSet,\t";
else
OS << "Empty_SubRegsSet,\t";
- if (RegisterSuperRegs.count(Reg.TheDef))
+ if (!RegisterSuperRegs[Reg.TheDef].empty())
OS << Reg.getName() << "_SuperRegsSet },\n";
else
OS << "Empty_SuperRegsSet },\n";
}
OS << " };\n"; // End of register descriptors...
+
+ // Emit SubRegIndex names, skipping 0
+ const std::vector<Record*> SubRegIndices = Target.getSubRegIndices();
+ OS << "\n const char *const 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...
std::string ClassName = Target.getName() + "GenRegisterInfo";
// Calculate the mapping of subregister+index pairs to physical registers.
- std::vector<Record*> SubRegs = Records.getAllDerivedDefinitions("SubRegSet");
- for (unsigned i = 0, e = SubRegs.size(); i != e; ++i) {
- int subRegIndex = SubRegs[i]->getValueAsInt("index");
- std::vector<Record*> From = SubRegs[i]->getValueAsListOfDefs("From");
- std::vector<Record*> To = SubRegs[i]->getValueAsListOfDefs("To");
-
- if (From.size() != To.size()) {
- errs() << "Error: register list and sub-register list not of equal length"
- << " in SubRegSet\n";
- exit(1);
- }
-
- // For each entry in from/to vectors, insert the to register at index
- for (unsigned ii = 0, ee = From.size(); ii != ee; ++ii)
- SubRegVectors[From[ii]].push_back(std::make_pair(subRegIndex, To[ii]));
- }
-
+ AllSubRegMap AllSRM;
+
// Emit the subregister + index mapping function based on the information
// calculated above.
- OS << "unsigned " << ClassName
+ OS << "unsigned " << ClassName
<< "::getSubReg(unsigned RegNo, unsigned Index) const {\n"
<< " switch (RegNo) {\n"
<< " default:\n return 0;\n";
- for (std::map<Record*, std::vector<std::pair<int, Record*> > >::iterator
- I = SubRegVectors.begin(), E = SubRegVectors.end(); I != E; ++I) {
- OS << " case " << getQualifiedName(I->first) << ":\n";
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ SubRegMap &SRM = inferSubRegIndices(Regs[i].TheDef, AllSRM);
+ if (SRM.empty())
+ continue;
+ OS << " case " << getQualifiedName(Regs[i].TheDef) << ":\n";
OS << " switch (Index) {\n";
OS << " default: return 0;\n";
- for (unsigned i = 0, e = I->second.size(); i != e; ++i)
- OS << " case " << (I->second)[i].first << ": return "
- << getQualifiedName((I->second)[i].second) << ";\n";
+ for (SubRegMap::const_iterator ii = SRM.begin(), ie = SRM.end(); ii != ie;
+ ++ii)
+ OS << " case " << getQualifiedName(ii->first)
+ << ": return " << getQualifiedName(ii->second) << ";\n";
OS << " };\n" << " break;\n";
}
OS << " };\n";
OS << " return 0;\n";
OS << "}\n\n";
- OS << "unsigned " << ClassName
+ OS << "unsigned " << ClassName
<< "::getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const {\n"
<< " switch (RegNo) {\n"
<< " default:\n return 0;\n";
- for (std::map<Record*, std::vector<std::pair<int, Record*> > >::iterator
- I = SubRegVectors.begin(), E = SubRegVectors.end(); I != E; ++I) {
- OS << " case " << getQualifiedName(I->first) << ":\n";
- for (unsigned i = 0, e = I->second.size(); i != e; ++i)
- OS << " if (SubRegNo == "
- << getQualifiedName((I->second)[i].second)
- << ") return " << (I->second)[i].first << ";\n";
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ SubRegMap &SRM = AllSRM[Regs[i].TheDef];
+ if (SRM.empty())
+ continue;
+ OS << " case " << getQualifiedName(Regs[i].TheDef) << ":\n";
+ for (SubRegMap::const_iterator ii = SRM.begin(), ie = SRM.end(); ii != ie;
+ ++ii)
+ OS << " if (SubRegNo == " << getQualifiedName(ii->second)
+ << ") return " << getQualifiedName(ii->first) << ";\n";
OS << " return 0;\n";
}
OS << " };\n";
@@ -853,11 +883,11 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
// Emit the constructor of the class...
OS << ClassName << "::" << ClassName
<< "(int CallFrameSetupOpcode, int CallFrameDestroyOpcode)\n"
- << " : TargetRegisterInfo(RegisterDescriptors, " << Registers.size()+1
- << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n "
+ << " : TargetRegisterInfo(RegisterDescriptors, " << Regs.size()+1
+ << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n"
+ << " SubRegIndexTable,\n"
<< " CallFrameSetupOpcode, CallFrameDestroyOpcode,\n"
<< " SubregHashTable, SubregHashTableSize,\n"
- << " SuperregHashTable, SuperregHashTableSize,\n"
<< " AliasesHashTable, AliasesHashTableSize) {\n"
<< "}\n\n";
@@ -865,8 +895,8 @@ void RegisterInfoEmitter::run(raw_ostream &OS) {
// First, just pull all provided information to the map
unsigned maxLength = 0;
- for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
- Record *Reg = Registers[i].TheDef;
+ 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))
diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index 1c66399..17435f6 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/utils/TableGen/TableGen.cpp
@@ -18,6 +18,7 @@
#include "AsmMatcherEmitter.h"
#include "AsmWriterEmitter.h"
#include "CallingConvEmitter.h"
+#include "ClangASTNodesEmitter.h"
#include "ClangDiagnosticsEmitter.h"
#include "CodeEmitterGen.h"
#include "DAGISelEmitter.h"
@@ -53,6 +54,7 @@ enum ActionType {
GenCallingConv,
GenClangDiagsDefs,
GenClangDiagGroups,
+ GenClangStmtNodes,
GenDAGISel,
GenFastISel,
GenOptParserDefs, GenOptParserImpl,
@@ -109,6 +111,8 @@ namespace {
"Generate Clang diagnostics definitions"),
clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups",
"Generate Clang diagnostic groups"),
+ clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes",
+ "Generate Clang AST statement nodes"),
clEnumValN(GenLLVMCConf, "gen-llvmc",
"Generate LLVMC configuration library"),
clEnumValN(GenEDHeader, "gen-enhanced-disassembly-header",
@@ -133,7 +137,7 @@ namespace {
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"),
@@ -160,18 +164,18 @@ static bool ParseFile(const std::string &Filename,
std::string ErrorStr;
MemoryBuffer *F = MemoryBuffer::getFileOrSTDIN(Filename.c_str(), &ErrorStr);
if (F == 0) {
- errs() << "Could not open input file '" << Filename << "': "
+ errs() << "Could not open input file '" << Filename << "': "
<< ErrorStr <<"\n";
return true;
}
-
+
// 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();
@@ -182,7 +186,7 @@ int main(int argc, char **argv) {
PrettyStackTraceProgram X(argc, argv);
cl::ParseCommandLineOptions(argc, argv);
-
+
// Parse the input file.
if (ParseFile(InputFilename, IncludeDirs, SrcMgr))
return 1;
@@ -193,7 +197,7 @@ int main(int argc, char **argv) {
Out = new raw_fd_ostream(OutputFilename.c_str(), Error);
if (!Error.empty()) {
- errs() << argv[0] << ": error opening " << OutputFilename
+ errs() << argv[0] << ": error opening " << OutputFilename
<< ":" << Error << "\n";
return 1;
}
@@ -244,6 +248,9 @@ int main(int argc, char **argv) {
case GenClangDiagGroups:
ClangDiagGroupsEmitter(Records).run(*Out);
break;
+ case GenClangStmtNodes:
+ ClangStmtNodesEmitter(Records).run(*Out);
+ break;
case GenDisassembler:
DisassemblerEmitter(Records).run(*Out);
break;
@@ -289,15 +296,15 @@ int main(int argc, char **argv) {
assert(1 && "Invalid Action");
return 1;
}
-
+
if (Out != &outs())
delete Out; // Close the file
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) {
@@ -305,7 +312,7 @@ int main(int argc, char **argv) {
} catch (...) {
errs() << argv[0] << ": Unknown unexpected exception occurred.\n";
}
-
+
if (Out != &outs()) {
delete Out; // Close the file
std::remove(OutputFilename.c_str()); // Remove the file, it's broken
diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp
index b15db2f..b7085ae 100644
--- a/utils/TableGen/X86RecognizableInstr.cpp
+++ b/utils/TableGen/X86RecognizableInstr.cpp
@@ -230,6 +230,10 @@ void RecognizableInstr::processInstr(DisassemblerTables &tables,
const CodeGenInstruction &insn,
InstrUID uid)
{
+ // Ignore "asm parser only" instructions.
+ if (insn.TheDef->getValueAsBit("isAsmParserOnly"))
+ return;
+
RecognizableInstr recogInstr(tables, insn, uid);
recogInstr.emitInstructionSpecifier(tables);
@@ -835,8 +839,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("opaque512mem", TYPE_M512)
TYPE("SEGMENT_REG", TYPE_SEGMENTREG)
TYPE("DEBUG_REG", TYPE_DEBUGREG)
- TYPE("CONTROL_REG_32", TYPE_CR32)
- TYPE("CONTROL_REG_64", TYPE_CR64)
+ TYPE("CONTROL_REG", TYPE_CONTROLREG)
TYPE("offset8", TYPE_MOFFS8)
TYPE("offset16", TYPE_MOFFS16)
TYPE("offset32", TYPE_MOFFS32)
@@ -895,8 +898,7 @@ OperandEncoding RecognizableInstr::roRegisterEncodingFromString
ENCODING("VR64", ENCODING_REG)
ENCODING("SEGMENT_REG", ENCODING_REG)
ENCODING("DEBUG_REG", ENCODING_REG)
- ENCODING("CONTROL_REG_32", ENCODING_REG)
- ENCODING("CONTROL_REG_64", ENCODING_REG)
+ ENCODING("CONTROL_REG", ENCODING_REG)
errs() << "Unhandled reg/opcode register encoding " << s << "\n";
llvm_unreachable("Unhandled reg/opcode register encoding");
}
diff --git a/utils/buildit/GNUmakefile b/utils/buildit/GNUmakefile
index e0568d2..0f3b7eb 100644
--- a/utils/buildit/GNUmakefile
+++ b/utils/buildit/GNUmakefile
@@ -49,6 +49,9 @@ endif
# Default to not install libLTO.dylib.
INSTALL_LIBLTO := no
+# Default to do a native build, not a cross-build for an ARM host.
+ARM_HOSTED_BUILD := no
+
ifndef RC_ProjectSourceVersion
RC_ProjectSourceVersion = 9999
endif
@@ -63,8 +66,12 @@ install: $(OBJROOT) $(SYMROOT) $(DSTROOT)
$(SRC)/utils/buildit/build_llvm "$(RC_ARCHS)" "$(TARGETS)" \
$(SRC) $(PREFIX) $(DSTROOT) $(SYMROOT) \
$(ENABLE_ASSERTIONS) $(LLVM_OPTIMIZED) $(INSTALL_LIBLTO) \
+ $(ARM_HOSTED_BUILD) \
$(RC_ProjectSourceVersion) $(RC_ProjectSourceSubversion)
+EmbeddedHosted:
+ $(MAKE) ARM_HOSTED_BUILD=yes install
+
# installhdrs does nothing, because the headers aren't useful until
# the compiler is installed.
installhdrs:
@@ -113,4 +120,4 @@ clean:
$(OBJROOT) $(SYMROOT) $(DSTROOT):
mkdir -p $@
-.PHONY: install installsrc clean
+.PHONY: install installsrc clean EmbeddedHosted
diff --git a/utils/buildit/build_llvm b/utils/buildit/build_llvm
index 78cc655..a9a11d9 100755
--- a/utils/buildit/build_llvm
+++ b/utils/buildit/build_llvm
@@ -46,11 +46,14 @@ LLVM_OPTIMIZED="$8"
# should be installed.
INSTALL_LIBLTO="$9"
-# The tenth parameter is the version number of the submission, e.g. 1007.
-LLVM_SUBMIT_VERSION="${10}"
+# A yes/no parameter that controls whether to cross-build for an ARM host.
+ARM_HOSTED_BUILD="${10}"
-# The eleventh parameter is the subversion number of the submission, e.g. 03.
-LLVM_SUBMIT_SUBVERSION="${11}"
+# The version number of the submission, e.g. 1007.
+LLVM_SUBMIT_VERSION="${11}"
+
+# The subversion number of the submission, e.g. 03.
+LLVM_SUBMIT_SUBVERSION="${12}"
# The current working directory is where the build will happen. It may already
# contain a partial result of an interrupted build, in which case this script
@@ -61,7 +64,7 @@ DARWIN_VERS=`uname -r | sed 's/\..*//'`
echo DARWIN_VERS = $DARWIN_VERS
DEVELOPER_DIR="${DEVELOPER_DIR-Developer}"
-if [ "x$RC_ProjectName" = "xllvmCore_EmbeddedHosted" ]; then
+if [ "$ARM_HOSTED_BUILD" = yes ]; then
DT_HOME="$DEST_DIR/usr"
HOST_SDKROOT=$SDKROOT
else
@@ -89,8 +92,7 @@ sed -e '/[Aa]pple-style/d' -e '/include.*GNUmakefile/d' $ORIG_SRC_DIR/Makefile >
mkdir -p $DIR/obj-llvm || exit 1
cd $DIR/obj-llvm || exit 1
-
-if [ "x$RC_ProjectName" = "xllvmCore_EmbeddedHosted" ]; then
+if [ "$ARM_HOSTED_BUILD" = yes ]; then
# The cross-tools' build process expects to find an existing cross toolchain
# under names like 'arm-apple-darwin$DARWIN_VERS-as'; so make them.
rm -rf $DIR/bin || exit 1
@@ -129,28 +131,21 @@ elif [ $DARWIN_VERS -gt 9 ]; then
unset XTMPCC savedPATH
fi
-
-if [ "x$RC_ProjectName" = "xllvmCore_EmbeddedHosted" ]; then
- if [ \! -f Makefile.config ]; then
- $SRC_DIR/configure --prefix=$DT_HOME \
- --enable-targets=arm \
- --host=arm-apple-darwin10 \
- --target=arm-apple-darwin10 \
- --build=i686-apple-darwin10 \
- --enable-assertions=$LLVM_ASSERTIONS \
- --enable-optimized=$LLVM_OPTIMIZED \
- --disable-bindings \
- || exit 1
- fi
+if [ "$ARM_HOSTED_BUILD" = yes ]; then
+ configure_prefix=$DT_HOME
+ configure_opts="--enable-targets=arm --host=arm-apple-darwin10 \
+ --target=arm-apple-darwin10 --build=i686-apple-darwin10"
else
- if [ \! -f Makefile.config ]; then
- $SRC_DIR/configure --prefix=$DT_HOME/local \
- --enable-targets=arm,x86,powerpc,cbe \
- --enable-assertions=$LLVM_ASSERTIONS \
- --enable-optimized=$LLVM_OPTIMIZED \
- --disable-bindings \
- || exit 1
- fi
+ configure_prefix=$DT_HOME/local
+ configure_opts="--enable-targets=arm,x86,powerpc,cbe"
+fi
+
+if [ \! -f Makefile.config ]; then
+ $SRC_DIR/configure --prefix=$configure_prefix $configure_opts \
+ --enable-assertions=$LLVM_ASSERTIONS \
+ --enable-optimized=$LLVM_OPTIMIZED \
+ --disable-bindings \
+ || exit 1
fi
SUBVERSION=`echo $RC_ProjectSourceVersion | sed -e 's/[^.]*\.\([0-9]*\).*/\1/'`
diff --git a/utils/lit/lit/LitConfig.py b/utils/lit/lit/LitConfig.py
index 9b62470..ac48591 100644
--- a/utils/lit/lit/LitConfig.py
+++ b/utils/lit/lit/LitConfig.py
@@ -71,7 +71,7 @@ class LitConfig:
self.bashPath = Util.which('bash', os.pathsep.join(self.path))
if self.bashPath is None:
# Check some known paths.
- for path in ('/bin/bash', '/usr/bin/bash'):
+ for path in ('/bin/bash', '/usr/bin/bash', '/usr/local/bin/bash'):
if os.path.exists(path):
self.bashPath = path
break
diff --git a/utils/lit/lit/ShUtil.py b/utils/lit/lit/ShUtil.py
index c8f9332..dda622a 100644
--- a/utils/lit/lit/ShUtil.py
+++ b/utils/lit/lit/ShUtil.py
@@ -67,6 +67,9 @@ class ShLexer:
elif c == '"':
self.eat()
str += self.lex_arg_quoted('"')
+ elif c == "'":
+ self.eat()
+ str += self.lex_arg_quoted("'")
elif not self.win32Escapes and c == '\\':
# Outside of a string, '\\' escapes everything.
self.eat()
@@ -287,6 +290,10 @@ class TestShParse(unittest.TestCase):
Pipeline([Command(['echo', 'hello'], [])], False))
self.assertEqual(self.parse('echo ""'),
Pipeline([Command(['echo', ''], [])], False))
+ self.assertEqual(self.parse("""echo -DFOO='a'"""),
+ Pipeline([Command(['echo', '-DFOO=a'], [])], False))
+ self.assertEqual(self.parse('echo -DFOO="a"'),
+ Pipeline([Command(['echo', '-DFOO=a'], [])], False))
def test_redirection(self):
self.assertEqual(self.parse('echo hello > c'),
diff --git a/utils/lit/lit/TestFormats.py b/utils/lit/lit/TestFormats.py
index 5e1a811..e52d0e4 100644
--- a/utils/lit/lit/TestFormats.py
+++ b/utils/lit/lit/TestFormats.py
@@ -183,8 +183,10 @@ class OneCommandPerFileTest:
self.createTempInput(tmp, test)
tmp.flush()
cmd.append(tmp.name)
- else:
+ elif hasattr(test, 'source_path'):
cmd.append(test.source_path)
+ else:
+ cmd.append(test.getSourcePath())
out, err, exitCode = TestRunner.executeCommand(cmd)
diff --git a/utils/lit/lit/lit.py b/utils/lit/lit/lit.py
index a29fa42..db0653f 100755
--- a/utils/lit/lit/lit.py
+++ b/utils/lit/lit/lit.py
@@ -258,9 +258,10 @@ def getTestsInSuite(ts, path_in_suite, litConfig,
lc = getLocalConfig(ts, path_in_suite, litConfig, localConfigCache)
# Search for tests.
- for res in lc.test_format.getTestsInDirectory(ts, path_in_suite,
- litConfig, lc):
- yield res
+ 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):
@@ -489,11 +490,27 @@ def main():
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 inputs:
+ for input in actual_inputs:
prev = len(tests)
tests.extend(getTests(input, litConfig,
testSuiteCache, localConfigCache)[1])
diff --git a/utils/valgrind/i386-pc-linux-gnu.supp b/utils/valgrind/i386-pc-linux-gnu.supp
new file mode 100644
index 0000000..f8fd99a
--- /dev/null
+++ b/utils/valgrind/i386-pc-linux-gnu.supp
@@ -0,0 +1,7 @@
+{
+ False leak under RegisterPass
+ Memcheck:Leak
+ ...
+ fun:_ZN83_GLOBAL_*PassRegistrar12RegisterPassERKN4llvm8PassInfoE
+ fun:_ZN4llvm8PassInfo12registerPassEv
+}
diff --git a/utils/valgrind/x86_64-pc-linux-gnu.supp b/utils/valgrind/x86_64-pc-linux-gnu.supp
new file mode 100644
index 0000000..f8fd99a
--- /dev/null
+++ b/utils/valgrind/x86_64-pc-linux-gnu.supp
@@ -0,0 +1,7 @@
+{
+ False leak under RegisterPass
+ Memcheck:Leak
+ ...
+ fun:_ZN83_GLOBAL_*PassRegistrar12RegisterPassERKN4llvm8PassInfoE
+ fun:_ZN4llvm8PassInfo12registerPassEv
+}
OpenPOWER on IntegriCloud