diff options
Diffstat (limited to 'utils')
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 +} |