diff options
Diffstat (limited to 'utils')
114 files changed, 1605 insertions, 2207 deletions
diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index a0eeb0edff..563cab0d5d 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -242,7 +242,7 @@ bool Pattern::ParsePattern(StringRef PatternStr, SourceMgr &SM, } // Name can't start with a digit. - if (isdigit(Name[0])) { + if (isdigit(static_cast<unsigned char>(Name[0]))) { SM.PrintMessage(SMLoc::getFromPointer(Name.data()), SourceMgr::DK_Error, "invalid name in named regex"); return true; @@ -587,9 +587,13 @@ struct CheckString { : Pat(P), Loc(L), IsCheckNext(isCheckNext) {} }; -/// CanonicalizeInputFile - Remove duplicate horizontal space from the specified -/// memory buffer, free it, and return a new one. -static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB) { +/// Canonicalize whitespaces in the input file. Line endings are replaced +/// with UNIX-style '\n'. +/// +/// \param PreserveHorizontal Don't squash consecutive horizontal whitespace +/// characters to a single space. +static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB, + bool PreserveHorizontal) { SmallString<128> NewFile; NewFile.reserve(MB->getBufferSize()); @@ -600,8 +604,9 @@ static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB) { continue; } - // If current char is not a horizontal whitespace, dump it to output as is. - if (*Ptr != ' ' && *Ptr != '\t') { + // If current char is not a horizontal whitespace or if horizontal + // whitespace canonicalization is disabled, dump it to output as is. + if (PreserveHorizontal || (*Ptr != ' ' && *Ptr != '\t')) { NewFile.push_back(*Ptr); continue; } @@ -637,9 +642,8 @@ static bool ReadCheckFile(SourceMgr &SM, MemoryBuffer *F = File.take(); // If we want to canonicalize whitespace, strip excess whitespace from the - // buffer containing the CHECK lines. - if (!NoCanonicalizeWhiteSpace) - F = CanonicalizeInputFile(F); + // buffer containing the CHECK lines. Remove DOS style line endings. + F = CanonicalizeInputFile(F, NoCanonicalizeWhiteSpace); SM.AddNewSourceBuffer(F, SMLoc()); @@ -807,8 +811,8 @@ int main(int argc, char **argv) { } // Remove duplicate spaces in the input file if requested. - if (!NoCanonicalizeWhiteSpace) - F = CanonicalizeInputFile(F); + // Remove DOS style line endings. + F = CanonicalizeInputFile(F, NoCanonicalizeWhiteSpace); SM.AddNewSourceBuffer(F, SMLoc()); diff --git a/utils/GenLibDeps.pl b/utils/GenLibDeps.pl index 656250c7e3..7748cabdab 100755 --- a/utils/GenLibDeps.pl +++ b/utils/GenLibDeps.pl @@ -98,7 +98,7 @@ if ($PEROBJ) { $libpath =~ s/^BitWriter/Bitcode\/Writer/; $libpath =~ s/^CppBackend/Target\/CppBackend/; $libpath =~ s/^MSIL/Target\/MSIL/; - $libpath =~ s/^Core/VMCore/; + $libpath =~ s/^Core/IR/; $libpath =~ s/^Instrumentation/Transforms\/Instrumentation/; $libpath =~ s/^Interpreter/ExecutionEngine\/Interpreter/; $libpath =~ s/^JIT/ExecutionEngine\/JIT/; diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index bc0cf4368f..6faf819529 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -958,8 +958,12 @@ static std::string getEnumNameForToken(StringRef Str) { case ':': Res += "_COLON_"; break; case '!': Res += "_EXCLAIM_"; break; case '.': Res += "_DOT_"; break; + case '<': Res += "_LT_"; break; + case '>': Res += "_GT_"; break; default: - if (isalnum(*it)) + if ((*it >= 'A' && *it <= 'Z') || + (*it >= 'a' && *it <= 'z') || + (*it >= '0' && *it <= '9')) Res += *it; else Res += "_" + utostr((unsigned) *it) + "_"; @@ -1723,7 +1727,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, << " default: llvm_unreachable(\"invalid conversion entry!\");\n" << " case CVT_Reg:\n" << " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n" - << " Operands[*(p + 1)]->setConstraint(\"m\");\n" + << " Operands[*(p + 1)]->setConstraint(\"r\");\n" << " ++NumMCOperands;\n" << " break;\n" << " case CVT_Tied:\n" @@ -1754,7 +1758,8 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // Remember this converter for the kind enum. unsigned KindID = OperandConversionKinds.size(); - OperandConversionKinds.insert("CVT_" + AsmMatchConverter); + OperandConversionKinds.insert("CVT_" + + getEnumNameForToken(AsmMatchConverter)); // Add the converter row for this instruction. ConversionTable.push_back(std::vector<uint8_t>()); @@ -1762,7 +1767,8 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, ConversionTable.back().push_back(CVT_Done); // Add the handler to the conversion driver function. - CvtOS << " case CVT_" << AsmMatchConverter << ":\n" + CvtOS << " case CVT_" + << getEnumNameForToken(AsmMatchConverter) << ":\n" << " " << AsmMatchConverter << "(Inst, Operands);\n" << " break;\n"; @@ -1800,6 +1806,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // the index of its entry in the vector). std::string Name = "CVT_" + (Op.Class->isRegisterClass() ? "Reg" : Op.Class->RenderMethod); + Name = getEnumNameForToken(Name); bool IsNewConverter = false; unsigned ID = getConverterOperandID(Name, OperandConversionKinds, @@ -1823,9 +1830,13 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, // Add a handler for the operand number lookup. OpOS << " case " << Name << ":\n" - << " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n" - << " Operands[*(p + 1)]->setConstraint(\"m\");\n" - << " NumMCOperands += " << OpInfo.MINumOperands << ";\n" + << " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n"; + + if (Op.Class->isRegisterClass()) + OpOS << " Operands[*(p + 1)]->setConstraint(\"r\");\n"; + else + OpOS << " Operands[*(p + 1)]->setConstraint(\"m\");\n"; + OpOS << " NumMCOperands += " << OpInfo.MINumOperands << ";\n" << " break;\n"; break; } @@ -2867,6 +2878,15 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "(MatchClassKind)it->Classes[i]);\n"; OS << " if (Diag == Match_Success)\n"; OS << " continue;\n"; + OS << " // If the generic handler indicates an invalid operand\n"; + OS << " // failure, check for a special case.\n"; + OS << " if (Diag == Match_InvalidOperand) {\n"; + OS << " Diag = validateTargetOperandClass(Operands[i+1],\n"; + OS.indent(43); + OS << "(MatchClassKind)it->Classes[i]);\n"; + OS << " if (Diag == Match_Success)\n"; + OS << " continue;\n"; + OS << " }\n"; OS << " // If this operand is broken for all of the instances of this\n"; OS << " // mnemonic, keep track of it so we can report loc info.\n"; OS << " // If we already had a match that only failed due to a\n"; diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index a4114d9815..ac8d896d36 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -842,8 +842,11 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { if (!IAP->isOpMapped(ROName)) { IAP->addOperand(ROName, i); + Record *R = CGA->ResultOperands[i].getRecord(); + if (R->isSubClassOf("RegisterOperand")) + R = R->getValueAsDef("RegClass"); Cond = std::string("MRI.getRegClass(") + Target.getName() + "::" + - CGA->ResultOperands[i].getRecord()->getName() + "RegClassID)" + R->getName() + "RegClassID)" ".contains(MI->getOperand(" + llvm::utostr(i) + ").getReg())"; IAP->addCond(Cond); } else { @@ -863,12 +866,18 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { break; } - case CodeGenInstAlias::ResultOperand::K_Imm: - Cond = std::string("MI->getOperand(") + - llvm::utostr(i) + ").getImm() == " + - llvm::utostr(CGA->ResultOperands[i].getImm()); + case CodeGenInstAlias::ResultOperand::K_Imm: { + std::string Op = "MI->getOperand(" + llvm::utostr(i) + ")"; + + // Just because the alias has an immediate result, doesn't mean the + // MCInst will. An MCExpr could be present, for example. + IAP->addCond(Op + ".isImm()"); + + Cond = Op + ".getImm() == " + + llvm::utostr(CGA->ResultOperands[i].getImm()); IAP->addCond(Cond); break; + } case CodeGenInstAlias::ResultOperand::K_Reg: // If this is zero_reg, something's playing tricks we're not // equipped to handle. diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt index 0527aa6180..d0f44be69a 100644 --- a/utils/TableGen/CMakeLists.txt +++ b/utils/TableGen/CMakeLists.txt @@ -19,7 +19,6 @@ add_tablegen(llvm-tblgen LLVM DAGISelMatcher.cpp DFAPacketizerEmitter.cpp DisassemblerEmitter.cpp - EDEmitter.cpp FastISelEmitter.cpp FixedLenDecoderEmitter.cpp InstrInfoEmitter.cpp diff --git a/utils/TableGen/CodeGenMapTable.cpp b/utils/TableGen/CodeGenMapTable.cpp index 1653d67da9..ee32aa13e0 100644 --- a/utils/TableGen/CodeGenMapTable.cpp +++ b/utils/TableGen/CodeGenMapTable.cpp @@ -533,12 +533,11 @@ static void emitEnums(raw_ostream &OS, RecordKeeper &Records) { II = ColFieldValueMap.begin(), IE = ColFieldValueMap.end(); II != IE; II++) { std::vector<Init*> FieldValues = (*II).second; - unsigned FieldSize = FieldValues.size(); // Delete duplicate entries from ColFieldValueMap - for (unsigned i = 0; i < FieldSize - 1; i++) { + for (unsigned i = 0; i < FieldValues.size() - 1; i++) { Init *CurVal = FieldValues[i]; - for (unsigned j = i+1; j < FieldSize; j++) { + for (unsigned j = i+1; j < FieldValues.size(); j++) { if (CurVal == FieldValues[j]) { FieldValues.erase(FieldValues.begin()+j); } @@ -547,9 +546,9 @@ static void emitEnums(raw_ostream &OS, RecordKeeper &Records) { // Emit enumerated values for the column fields. OS << "enum " << (*II).first << " {\n"; - for (unsigned i = 0; i < FieldSize; i++) { + for (unsigned i = 0, endFV = FieldValues.size(); i < endFV; i++) { OS << "\t" << (*II).first << "_" << FieldValues[i]->getAsUnquotedString(); - if (i != FieldValues.size() - 1) + if (i != endFV - 1) OS << ",\n"; else OS << "\n};\n\n"; diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp index 20d439f8f7..993b8dba42 100644 --- a/utils/TableGen/CodeGenRegisters.cpp +++ b/utils/TableGen/CodeGenRegisters.cpp @@ -636,8 +636,10 @@ struct TupleExpander : SetTheory::Expander { Elts.insert(NewReg); // Copy Proto super-classes. - for (unsigned i = 0, e = Proto->getSuperClasses().size(); i != e; ++i) - NewReg->addSuperClass(Proto->getSuperClasses()[i]); + ArrayRef<Record *> Supers = Proto->getSuperClasses(); + ArrayRef<SMRange> Ranges = Proto->getSuperClassRanges(); + for (unsigned i = 0, e = Supers.size(); i != e; ++i) + NewReg->addSuperClass(Supers[i], Ranges[i]); // Copy Proto fields. for (unsigned i = 0, e = Proto->getValues().size(); i != e; ++i) { @@ -701,7 +703,9 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) // Rename anonymous register classes. if (R->getName().size() > 9 && R->getName()[9] == '.') { static unsigned AnonCounter = 0; - R->setName("AnonRegClass_"+utostr(AnonCounter++)); + R->setName("AnonRegClass_" + utostr(AnonCounter)); + // MSVC2012 ICEs if AnonCounter++ is directly passed to utostr. + ++AnonCounter; } std::vector<Record*> TypeList = R->getValueAsListOfDefs("RegTypes"); @@ -1196,6 +1200,12 @@ void CodeGenRegBank::computeSubRegIndexLaneMasks() { if (Idx->getComposites().empty()) { Idx->LaneMask = 1u << Bit; // Share bit 31 in the unlikely case there are more than 32 leafs. + // + // Sharing bits is harmless; it allows graceful degradation in targets + // with more than 32 vector lanes. They simply get a limited resolution + // view of lanes beyond the 32nd. + // + // See also the comment for getSubRegIndexLaneMask(). if (Bit < 31) ++Bit; } else { Idx->LaneMask = 0; diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp index c653c49f25..23b79fcddf 100644 --- a/utils/TableGen/CodeGenSchedule.cpp +++ b/utils/TableGen/CodeGenSchedule.cpp @@ -1380,8 +1380,22 @@ void CodeGenSchedModels::collectProcResources() { SCI != SCE; ++SCI) { if (SCI->ItinClassDef) collectItinProcResources(SCI->ItinClassDef); - else + else { + // This class may have a default ReadWrite list which can be overriden by + // InstRW definitions. + if (!SCI->InstRWs.empty()) { + for (RecIter RWI = SCI->InstRWs.begin(), RWE = SCI->InstRWs.end(); + RWI != RWE; ++RWI) { + Record *RWModelDef = (*RWI)->getValueAsDef("SchedModel"); + IdxVec ProcIndices(1, getProcModel(RWModelDef).Index); + IdxVec Writes, Reads; + findRWs((*RWI)->getValueAsListOfDefs("OperandReadWrites"), + Writes, Reads); + collectRWResources(Writes, Reads, ProcIndices); + } + } collectRWResources(SCI->Writes, SCI->Reads, SCI->ProcIndices); + } } // Add resources separately defined by each subtarget. RecVec WRDefs = Records.getAllDerivedDefinitions("WriteRes"); diff --git a/utils/TableGen/CodeGenSchedule.h b/utils/TableGen/CodeGenSchedule.h index dc927e68ff..78f115ecd8 100644 --- a/utils/TableGen/CodeGenSchedule.h +++ b/utils/TableGen/CodeGenSchedule.h @@ -55,10 +55,11 @@ struct CodeGenSchedRW { IdxVec Sequence; RecVec Aliases; - CodeGenSchedRW(): Index(0), TheDef(0), IsAlias(false), HasVariants(false), - IsVariadic(false), IsSequence(false) {} - CodeGenSchedRW(unsigned Idx, Record *Def): Index(Idx), TheDef(Def), - IsAlias(false), IsVariadic(false) { + CodeGenSchedRW() + : Index(0), TheDef(0), IsRead(false), IsAlias(false), + HasVariants(false), IsVariadic(false), IsSequence(false) {} + CodeGenSchedRW(unsigned Idx, Record *Def) + : Index(Idx), TheDef(Def), IsAlias(false), IsVariadic(false) { Name = Def->getName(); IsRead = Def->isSubClassOf("SchedRead"); HasVariants = Def->isSubClassOf("SchedVariant"); @@ -72,9 +73,9 @@ struct CodeGenSchedRW { } CodeGenSchedRW(unsigned Idx, bool Read, const IdxVec &Seq, - const std::string &Name): - Index(Idx), Name(Name), TheDef(0), IsRead(Read), IsAlias(false), - HasVariants(false), IsVariadic(false), IsSequence(true), Sequence(Seq) { + const std::string &Name) + : Index(Idx), Name(Name), TheDef(0), IsRead(Read), IsAlias(false), + HasVariants(false), IsVariadic(false), IsSequence(true), Sequence(Seq) { assert(Sequence.size() > 1 && "implied sequence needs >1 RWs"); } diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index d946d035c0..dd3f6e29fd 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -73,16 +73,20 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) { case MVT::v4i1: return "MVT::v4i1"; case MVT::v8i1: return "MVT::v8i1"; case MVT::v16i1: return "MVT::v16i1"; + case MVT::v32i1: return "MVT::v32i1"; + case MVT::v64i1: return "MVT::v64i1"; case MVT::v2i8: return "MVT::v2i8"; case MVT::v4i8: return "MVT::v4i8"; case MVT::v8i8: return "MVT::v8i8"; case MVT::v16i8: return "MVT::v16i8"; case MVT::v32i8: return "MVT::v32i8"; + case MVT::v64i8: return "MVT::v64i8"; case MVT::v1i16: return "MVT::v1i16"; case MVT::v2i16: return "MVT::v2i16"; case MVT::v4i16: return "MVT::v4i16"; case MVT::v8i16: return "MVT::v8i16"; case MVT::v16i16: return "MVT::v16i16"; + case MVT::v32i16: return "MVT::v32i16"; case MVT::v1i32: return "MVT::v1i32"; case MVT::v2i32: return "MVT::v2i32"; case MVT::v4i32: return "MVT::v4i32"; @@ -97,8 +101,10 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) { case MVT::v2f32: return "MVT::v2f32"; case MVT::v4f32: return "MVT::v4f32"; case MVT::v8f32: return "MVT::v8f32"; + case MVT::v16f32: return "MVT::v16f32"; case MVT::v2f64: return "MVT::v2f64"; case MVT::v4f64: return "MVT::v4f64"; + case MVT::v8f64: return "MVT::v8f64"; case MVT::Metadata: return "MVT::Metadata"; case MVT::iPTR: return "MVT::iPTR"; case MVT::iPTRAny: return "MVT::iPTRAny"; diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp index 4345708783..93f84ce6e8 100644 --- a/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -132,7 +132,7 @@ static uint64_t EmitVBRValue(uint64_t Val, raw_ostream &OS) { return NumBytes+1; } -/// EmitMatcherOpcodes - Emit bytes for the specified matcher and return +/// EmitMatcher - Emit bytes for the specified matcher and return /// the number of bytes emitted. unsigned MatcherTableEmitter:: EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, diff --git a/utils/TableGen/DisassemblerEmitter.cpp b/utils/TableGen/DisassemblerEmitter.cpp index 2d11d2480d..5a2a41b456 100644 --- a/utils/TableGen/DisassemblerEmitter.cpp +++ b/utils/TableGen/DisassemblerEmitter.cpp @@ -127,8 +127,9 @@ void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) { // ARM and Thumb have a CHECK() macro to deal with DecodeStatuses. if (Target.getName() == "ARM" || - Target.getName() == "Thumb") { - EmitFixedLenDecoder(Records, OS, "ARM", + Target.getName() == "Thumb" || + Target.getName() == "AArch64") { + EmitFixedLenDecoder(Records, OS, Target.getName() == "AArch64" ? "AArch64" : "ARM", "if (!Check(S, ", ")) return MCDisassembler::Fail;", "S", "MCDisassembler::Fail", " MCDisassembler::DecodeStatus S = " diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp deleted file mode 100644 index 428630edc9..0000000000 --- a/utils/TableGen/EDEmitter.cpp +++ /dev/null @@ -1,1012 +0,0 @@ -//===- EDEmitter.cpp - Generate instruction descriptions for ED -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This tablegen backend is responsible for emitting a description of each -// instruction in a format that the enhanced disassembler can use to tokenize -// and parse instructions. -// -//===----------------------------------------------------------------------===// - -#include "AsmWriterInst.h" -#include "CodeGenTarget.h" -#include "llvm/MC/EDInstInfo.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/TableGen/Error.h" -#include "llvm/TableGen/Record.h" -#include "llvm/TableGen/TableGenBackend.h" -#include <string> -#include <vector> - -using namespace llvm; - -// TODO: There's a suspiciously large amount of "table" data in this -// backend which should probably be in the TableGen file itself. - -/////////////////////////////////////////////////////////// -// Support classes for emitting nested C data structures // -/////////////////////////////////////////////////////////// - -// TODO: These classes are probably generally useful to other backends; -// add them to TableGen's "helper" API's. - -namespace { -class EnumEmitter { -private: - std::string Name; - std::vector<std::string> Entries; -public: - EnumEmitter(const char *N) : Name(N) { - } - int addEntry(const char *e) { - Entries.push_back(std::string(e)); - return Entries.size() - 1; - } - void emit(raw_ostream &o, unsigned int &i) { - o.indent(i) << "enum " << Name.c_str() << " {" << "\n"; - i += 2; - - unsigned int index = 0; - unsigned int numEntries = Entries.size(); - for (index = 0; index < numEntries; ++index) { - o.indent(i) << Entries[index]; - if (index < (numEntries - 1)) - o << ","; - o << "\n"; - } - - i -= 2; - o.indent(i) << "};" << "\n"; - } - - void emitAsFlags(raw_ostream &o, unsigned int &i) { - o.indent(i) << "enum " << Name.c_str() << " {" << "\n"; - i += 2; - - unsigned int index = 0; - unsigned int numEntries = Entries.size(); - unsigned int flag = 1; - for (index = 0; index < numEntries; ++index) { - o.indent(i) << Entries[index] << " = " << format("0x%x", flag); - if (index < (numEntries - 1)) - o << ","; - o << "\n"; - flag <<= 1; - } - - i -= 2; - o.indent(i) << "};" << "\n"; - } -}; -} // End anonymous namespace - -namespace { -class ConstantEmitter { -public: - virtual ~ConstantEmitter() { } - virtual void emit(raw_ostream &o, unsigned int &i) = 0; -}; -} // End anonymous namespace - -namespace { -class LiteralConstantEmitter : public ConstantEmitter { -private: - bool IsNumber; - union { - int Number; - const char* String; - }; -public: - LiteralConstantEmitter(int number = 0) : - IsNumber(true), - Number(number) { - } - void set(const char *string) { - IsNumber = false; - Number = 0; - String = string; - } - bool is(const char *string) { - return !strcmp(String, string); - } - void emit(raw_ostream &o, unsigned int &i) { - if (IsNumber) - o << Number; - else - o << String; - } -}; -} // End anonymous namespace - -namespace { -class CompoundConstantEmitter : public ConstantEmitter { -private: - unsigned int Padding; - std::vector<ConstantEmitter *> Entries; -public: - CompoundConstantEmitter(unsigned int padding = 0) : Padding(padding) { - } - CompoundConstantEmitter &addEntry(ConstantEmitter *e) { - Entries.push_back(e); - - return *this; - } - ~CompoundConstantEmitter() { - while (Entries.size()) { - ConstantEmitter *entry = Entries.back(); - Entries.pop_back(); - delete entry; - } - } - void emit(raw_ostream &o, unsigned int &i) { - o << "{" << "\n"; - i += 2; - - unsigned int index; - unsigned int numEntries = Entries.size(); - - unsigned int numToPrint; - - if (Padding) { - if (numEntries > Padding) { - fprintf(stderr, "%u entries but %u padding\n", numEntries, Padding); - llvm_unreachable("More entries than padding"); - } - numToPrint = Padding; - } else { - numToPrint = numEntries; - } - - for (index = 0; index < numToPrint; ++index) { - o.indent(i); - if (index < numEntries) - Entries[index]->emit(o, i); - else - o << "-1"; - - if (index < (numToPrint - 1)) - o << ","; - o << "\n"; - } - - i -= 2; - o.indent(i) << "}"; - } -}; -} // End anonymous namespace - -namespace { -class FlagsConstantEmitter : public ConstantEmitter { -private: - std::vector<std::string> Flags; -public: - FlagsConstantEmitter() { - } - FlagsConstantEmitter &addEntry(const char *f) { - Flags.push_back(std::string(f)); - return *this; - } - void emit(raw_ostream &o, unsigned int &i) { - unsigned int index; - unsigned int numFlags = Flags.size(); - if (numFlags == 0) - o << "0"; - - for (index = 0; index < numFlags; ++index) { - o << Flags[index].c_str(); - if (index < (numFlags - 1)) - o << " | "; - } - } -}; -} // End anonymous namespace - -/// populateOperandOrder - Accepts a CodeGenInstruction and generates its -/// AsmWriterInst for the desired assembly syntax, giving an ordered list of -/// operands in the order they appear in the printed instruction. Then, for -/// each entry in that list, determines the index of the same operand in the -/// CodeGenInstruction, and emits the resulting mapping into an array, filling -/// in unused slots with -1. -/// -/// @arg operandOrder - The array that will be populated with the operand -/// mapping. Each entry will contain -1 (invalid index -/// into the operands present in the AsmString) or a number -/// representing an index in the operand descriptor array. -/// @arg inst - The instruction to use when looking up the operands -/// @arg syntax - The syntax to use, according to LLVM's enumeration -static void populateOperandOrder(CompoundConstantEmitter *operandOrder, - const CodeGenInstruction &inst, - unsigned syntax) { - unsigned int numArgs = 0; - - AsmWriterInst awInst(inst, syntax, -1, -1); - - std::vector<AsmWriterOperand>::iterator operandIterator; - - for (operandIterator = awInst.Operands.begin(); - operandIterator != awInst.Operands.end(); - ++operandIterator) { - if (operandIterator->OperandType == - AsmWriterOperand::isMachineInstrOperand) { - operandOrder->addEntry( - new LiteralConstantEmitter(operandIterator->CGIOpNo)); - numArgs++; - } - } -} - -///////////////////////////////////////////////////// -// Support functions for handling X86 instructions // -///////////////////////////////////////////////////// - -#define SET(flag) { type->set(flag); return 0; } - -#define REG(str) if (name == str) SET("kOperandTypeRegister"); -#define MEM(str) if (name == str) SET("kOperandTypeX86Memory"); -#define LEA(str) if (name == str) SET("kOperandTypeX86EffectiveAddress"); -#define IMM(str) if (name == str) SET("kOperandTypeImmediate"); -#define PCR(str) if (name == str) SET("kOperandTypeX86PCRelative"); - -/// X86TypeFromOpName - Processes the name of a single X86 operand (which is -/// actually its type) and translates it into an operand type -/// -/// @arg flags - The type object to set -/// @arg name - The name of the operand -static int X86TypeFromOpName(LiteralConstantEmitter *type, - const std::string &name) { - REG("GR8"); - REG("GR8_NOREX"); - REG("GR16"); - REG("GR16_NOAX"); - REG("GR32"); - REG("GR32_NOAX"); - REG("GR32_NOREX"); - REG("GR32_TC"); - REG("FR32"); - REG("RFP32"); - REG("GR64"); - REG("GR64_NOAX"); - REG("GR64_TC"); - REG("FR64"); - REG("VR64"); - REG("RFP64"); - REG("RFP80"); - REG("VR128"); - REG("VR256"); - REG("RST"); - REG("SEGMENT_REG"); - REG("DEBUG_REG"); - REG("CONTROL_REG"); - - IMM("i8imm"); - IMM("i16imm"); - IMM("i16i8imm"); - IMM("i32imm"); - IMM("i32i8imm"); - IMM("u32u8imm"); - IMM("i64imm"); - IMM("i64i8imm"); - IMM("i64i32imm"); - IMM("SSECC"); - IMM("AVXCC"); - - // all R, I, R, I, R - MEM("i8mem"); - MEM("i8mem_NOREX"); - MEM("i16mem"); - MEM("i32mem"); - MEM("i32mem_TC"); - MEM("f32mem"); - MEM("ssmem"); - MEM("opaque32mem"); - MEM("opaque48mem"); - MEM("i64mem"); - MEM("i64mem_TC"); - MEM("f64mem"); - MEM("sdmem"); - MEM("f80mem"); - MEM("opaque80mem"); - MEM("i128mem"); - MEM("i256mem"); - MEM("f128mem"); - MEM("f256mem"); - MEM("opaque512mem"); - // Gather - MEM("vx32mem") - MEM("vy32mem") - MEM("vx64mem") - MEM("vy64mem") - - // all R, I, R, I - LEA("lea32mem"); - LEA("lea64_32mem"); - LEA("lea64mem"); - - // all I - PCR("i16imm_pcrel"); - PCR("i32imm_pcrel"); - PCR("i64i32imm_pcrel"); - PCR("brtarget8"); - PCR("offset8"); - PCR("offset16"); - PCR("offset32"); - PCR("offset64"); - PCR("brtarget"); - PCR("uncondbrtarget"); - PCR("bltarget"); - - // all I, ARM mode only, conditional/unconditional - PCR("br_target"); - PCR("bl_target"); - return 1; -} - -#undef REG -#undef MEM -#undef LEA -#undef IMM -#undef PCR - -#undef SET - -/// X86PopulateOperands - Handles all the operands in an X86 instruction, adding -/// the appropriate flags to their descriptors -/// -/// \param operandTypes A reference the array of operand type objects -/// \param inst The instruction to use as a source of information -static void X86PopulateOperands( - LiteralConstantEmitter *(&operandTypes)[EDIS_MAX_OPERANDS], - const CodeGenInstruction &inst) { - if (!inst.TheDef->isSubClassOf("X86Inst")) - return; - - unsigned int index; - unsigned int numOperands = inst.Operands.size(); - - for (index = 0; index < numOperands; ++index) { - const CGIOperandList::OperandInfo &operandInfo = inst.Operands[index]; - Record &rec = *operandInfo.Rec; - - if (X86TypeFromOpName(operandTypes[index], rec.getName()) && - !rec.isSubClassOf("PointerLikeRegClass")) { - errs() << "Operand type: " << rec.getName().c_str() << "\n"; - errs() << "Operand name: " << operandInfo.Name.c_str() << "\n"; - errs() << "Instruction name: " << inst.TheDef->getName().c_str() << "\n"; - llvm_unreachable("Unhandled type"); - } - } -} - -/// decorate1 - Decorates a named operand with a new flag -/// -/// \param operandFlags The array of operand flag objects, which don't have -/// names -/// \param inst The CodeGenInstruction, which provides a way to -// translate between names and operand indices -/// \param opName The name of the operand -/// \param opFlag The name of the flag to add -static inline void decorate1( - FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS], - const CodeGenInstruction &inst, - const char *opName, - const char *opFlag) { - unsigned opIndex; - - opIndex = inst.Operands.getOperandNamed(std::string(opName)); - - operandFlags[opIndex]->addEntry(opFlag); -} - -#define DECORATE1(opName, opFlag) decorate1(operandFlags, inst, opName, opFlag) - -#define MOV(source, target) { \ - instType.set("kInstructionTypeMove"); \ - DECORATE1(source, "kOperandFlagSource"); \ - DECORATE1(target, "kOperandFlagTarget"); \ -} - -#define BRANCH(target) { \ - instType.set("kInstructionTypeBranch"); \ - DECORATE1(target, "kOperandFlagTarget"); \ -} - -#define PUSH(source) { \ - instType.set("kInstructionTypePush"); \ - DECORATE1(source, "kOperandFlagSource"); \ -} - -#define POP(target) { \ - instType.set("kInstructionTypePop"); \ - DECORATE1(target, "kOperandFlagTarget"); \ -} - -#define CALL(target) { \ - instType.set("kInstructionTypeCall"); \ - DECORATE1(target, "kOperandFlagTarget"); \ -} - -#define RETURN() { \ - instType.set("kInstructionTypeReturn"); \ -} - -/// X86ExtractSemantics - Performs various checks on the name of an X86 -/// instruction to determine what sort of an instruction it is and then adds -/// the appropriate flags to the instruction and its operands -/// -/// \param instType A reference to the type for the instruction as a whole -/// \param operandFlags A reference to the array of operand flag object pointers -/// \param inst A reference to the original instruction -static void X86ExtractSemantics( - LiteralConstantEmitter &instType, - FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS], - const CodeGenInstruction &inst) { - const std::string &name = inst.TheDef->getName(); - - if (name.find("MOV") != name.npos) { - if (name.find("MOV_V") != name.npos) { - // ignore (this is a pseudoinstruction) - } else if (name.find("MASK") != name.npos) { - // ignore (this is a masking move) - } else if (name.find("r0") != name.npos) { - // ignore (this is a pseudoinstruction) - } else if (name.find("PS") != name.npos || - name.find("PD") != name.npos) { - // ignore (this is a shuffling move) - } else if (name.find("MOVS") != name.npos) { - // ignore (this is a string move) - } else if (name.find("_F") != name.npos) { - // TODO handle _F moves to ST(0) - } else if (name.find("a") != name.npos) { - // TODO handle moves to/from %ax - } else if (name.find("CMOV") != name.npos) { - MOV("src2", "dst"); - } else if (name.find("PC") != name.npos) { - MOV("label", "reg") - } else { - MOV("src", "dst"); - } - } - - if (name.find("JMP") != name.npos || - name.find("J") == 0) { - if (name.find("FAR") != name.npos && name.find("i") != name.npos) { - BRANCH("off"); - } else { - BRANCH("dst"); - } - } - - if (name.find("PUSH") != name.npos) { - if (name.find("CS") != name.npos || - name.find("DS") != name.npos || - name.find("ES") != name.npos || - name.find("FS") != name.npos || - name.find("GS") != name.npos || - name.find("SS") != name.npos) { - instType.set("kInstructionTypePush"); - // TODO add support for fixed operands - } else if (name.find("F") != name.npos) { - // ignore (this pushes onto the FP stack) - } else if (name.find("A") != name.npos) { - // ignore (pushes all GP registoers onto the stack) - } else if (name[name.length() - 1] == 'm') { - PUSH("src"); - } else if (name.find("i") != name.npos) { - PUSH("imm"); - } else { - PUSH("reg"); - } - } - - if (name.find("POP") != name.npos) { - if (name.find("POPCNT") != name.npos) { - // ignore (not a real pop) - } else if (name.find("CS") != name.npos || - name.find("DS") != name.npos || - name.find("ES") != name.npos || - name.find("FS") != name.npos || - name.find("GS") != name.npos || - name.find("SS") != name.npos) { - instType.set("kInstructionTypePop"); - // TODO add support for fixed operands - } else if (name.find("F") != name.npos) { - // ignore (this pops from the FP stack) - } else if (name.find("A") != name.npos) { - // ignore (pushes all GP registoers onto the stack) - } else if (name[name.length() - 1] == 'm') { - POP("dst"); - } else { - POP("reg"); - } - } - - if (name.find("CALL") != name.npos) { - if (name.find("ADJ") != name.npos) { - // ignore (not a call) - } else if (name.find("SYSCALL") != name.npos) { - // ignore (doesn't go anywhere we know about) - } else if (name.find("VMCALL") != name.npos) { - // ignore (rather different semantics than a regular call) - } else if (name.find("VMMCALL") != name.npos) { - // ignore (rather different semantics than a regular call) - } else if (name.find("FAR") != name.npos && name.find("i") != name.npos) { - CALL("off"); - } else { - CALL("dst"); - } - } - - if (name.find("RET") != name.npos) { - RETURN(); - } -} - -#undef MOV -#undef BRANCH -#undef PUSH -#undef POP -#undef CALL -#undef RETURN - -///////////////////////////////////////////////////// -// Support functions for handling ARM instructions // -///////////////////////////////////////////////////// - -#define SET(flag) { type->set(flag); return 0; } - -#define REG(str) if (name == str) SET("kOperandTypeRegister"); -#define IMM(str) if (name == str) SET("kOperandTypeImmediate"); - -#define MISC(str, type) if (name == str) SET(type); - -/// ARMFlagFromOpName - Processes the name of a single ARM operand (which is -/// actually its type) and translates it into an operand type -/// -/// \param type The type object to set -/// \param name The name of the operand -static int ARMFlagFromOpName(LiteralConstantEmitter *type, - const std::string &name) { - REG("GPR"); - REG("rGPR"); - REG("GPRnopc"); - REG("GPRsp"); - REG("tcGPR"); - REG("cc_out"); - REG("s_cc_out"); - REG("tGPR"); - REG("GPRPairOp"); - REG("DPR"); - REG("DPR_VFP2"); - REG("DPR_8"); - REG("DPair"); - REG("SPR"); - REG("QPR"); - REG("QQPR"); - REG("QQQQPR"); - REG("VecListOneD"); - REG("VecListDPair"); - REG("VecListDPairSpaced"); - REG("VecListThreeD"); - REG("VecListFourD"); - REG("VecListOneDAllLanes"); - REG("VecListDPairAllLanes"); - REG("VecListDPairSpacedAllLanes"); - - IMM("i32imm"); - IMM("fbits16"); - IMM("fbits32"); - IMM("i32imm_hilo16"); - IMM("bf_inv_mask_imm"); - IMM("lsb_pos_imm"); - IMM("width_imm"); - IMM("jtblock_operand"); - IMM("nohash_imm"); - IMM("p_imm"); - IMM("pf_imm"); - IMM("c_imm"); - IMM("coproc_option_imm"); - IMM("imod_op"); - IMM("iflags_op"); - IMM("cpinst_operand"); - IMM("setend_op"); - IMM("cps_opt"); - IMM("vfp_f64imm"); - IMM("vfp_f32imm"); - IMM("memb_opt"); - IMM("msr_mask"); - IMM("neg_zero"); - IMM("imm0_31"); - IMM("imm0_31_m1"); - IMM("imm1_16"); - IMM("imm1_32"); - IMM("nModImm"); - IMM("nImmSplatI8"); - IMM("nImmSplatI16"); - IMM("nImmSplatI32"); - IMM("nImmSplatI64"); - IMM("nImmVMOVI32"); - IMM("nImmVMOVF32"); - IMM("imm8"); - IMM("imm16"); - IMM("imm32"); - IMM("imm1_7"); - IMM("imm1_15"); - IMM("imm1_31"); - IMM("imm0_1"); - IMM("imm0_3"); - IMM("imm0_7"); - IMM("imm0_15"); - IMM("imm0_255"); - IMM("imm0_4095"); - IMM("imm0_65535"); - IMM("imm0_65535_expr"); - IMM("imm24b"); - IMM("pkh_lsl_amt"); - IMM("pkh_asr_amt"); - IMM("jt2block_operand"); - IMM("t_imm0_1020s4"); - IMM("t_imm0_508s4"); - IMM("pclabel"); - IMM("adrlabel"); - IMM("t_adrlabel"); - IMM("t2adrlabel"); - IMM("shift_imm"); - IMM("t2_shift_imm"); - IMM("neon_vcvt_imm32"); - IMM("shr_imm8"); - IMM("shr_imm16"); - IMM("shr_imm32"); - IMM("shr_imm64"); - IMM("t2ldrlabel"); - IMM("postidx_imm8"); - IMM("postidx_imm8s4"); - IMM("imm_sr"); - IMM("imm1_31"); - IMM("VectorIndex8"); - IMM("VectorIndex16"); - IMM("VectorIndex32"); - - MISC("brtarget", "kOperandTypeARMBranchTarget"); // ? - MISC("uncondbrtarget", "kOperandTypeARMBranchTarget"); // ? - MISC("t_brtarget", "kOperandTypeARMBranchTarget"); // ? - MISC("t_bcctarget", "kOperandTypeARMBranchTarget"); // ? - MISC("t_cbtarget", "kOperandTypeARMBranchTarget"); // ? - MISC("bltarget", "kOperandTypeARMBranchTarget"); // ? - - MISC("br_target", "kOperandTypeARMBranchTarget"); // ? - MISC("bl_target", "kOperandTypeARMBranchTarget"); // ? - MISC("blx_target", "kOperandTypeARMBranchTarget"); // ? - - MISC("t_bltarget", "kOperandTypeARMBranchTarget"); // ? - MISC("t_blxtarget", "kOperandTypeARMBranchTarget"); // ? - MISC("so_reg_imm", "kOperandTypeARMSoRegReg"); // R, R, I - MISC("so_reg_reg", "kOperandTypeARMSoRegImm"); // R, R, I - MISC("shift_so_reg_reg", "kOperandTypeARMSoRegReg"); // R, R, I - MISC("shift_so_reg_imm", "kOperandTypeARMSoRegImm"); // R, R, I - MISC("t2_so_reg", "kOperandTypeThumb2SoReg"); // R, I - MISC("so_imm", "kOperandTypeARMSoImm"); // I - MISC("rot_imm", "kOperandTypeARMRotImm"); // I - MISC("t2_so_imm", "kOperandTypeThumb2SoImm"); // I - MISC("so_imm2part", "kOperandTypeARMSoImm2Part"); // I - MISC("pred", "kOperandTypeARMPredicate"); // I, R - MISC("it_pred", "kOperandTypeARMPredicate"); // I - MISC("addrmode_imm12", "kOperandTypeAddrModeImm12"); // R, I - MISC("ldst_so_reg", "kOperandTypeLdStSOReg"); // R, R, I - MISC("postidx_reg", "kOperandTypeARMAddrMode3Offset"); // R, I - MISC("addrmode2", "kOperandTypeARMAddrMode2"); // R, R, I - MISC("am2offset_reg", "kOperandTypeARMAddrMode2Offset"); // R, I - MISC("am2offset_imm", "kOperandTypeARMAddrMode2Offset"); // R, I - MISC("addrmode3", "kOperandTypeARMAddrMode3"); // R, R, I - MISC("am3offset", "kOperandTypeARMAddrMode3Offset"); // R, I - MISC("ldstm_mode", "kOperandTypeARMLdStmMode"); // I - MISC("addrmode5", "kOperandTypeARMAddrMode5"); // R, I - MISC("addrmode6", "kOperandTypeARMAddrMode6"); // R, R, I, I - MISC("am6offset", "kOperandTypeARMAddrMode6Offset"); // R, I, I - MISC("addrmode6dup", "kOperandTypeARMAddrMode6"); // R, R, I, I - MISC("addrmode6oneL32", "kOperandTypeARMAddrMode6"); // R, R, I, I - MISC("addrmodepc", "kOperandTypeARMAddrModePC"); // R, I - MISC("addr_offset_none", "kOperandTypeARMAddrMode7"); // R - MISC("reglist", "kOperandTypeARMRegisterList"); // I, R, ... - MISC("dpr_reglist", "kOperandTypeARMDPRRegisterList"); // I, R, ... - MISC("spr_reglist", "kOperandTypeARMSPRRegisterList"); // I, R, ... - MISC("it_mask", "kOperandTypeThumbITMask"); // I - MISC("t2addrmode_reg", "kOperandTypeThumb2AddrModeReg"); // R - MISC("t2addrmode_posimm8", "kOperandTypeThumb2AddrModeImm8"); // R, I - MISC("t2addrmode_negimm8", "kOperandTypeThumb2AddrModeImm8"); // R, I - MISC("t2addrmode_imm8", "kOperandTypeThumb2AddrModeImm8"); // R, I - MISC("t2am_imm8_offset", "kOperandTypeThumb2AddrModeImm8Offset");//I - MISC("t2addrmode_imm12", "kOperandTypeThumb2AddrModeImm12"); // R, I - MISC("t2addrmode_so_reg", "kOperandTypeThumb2AddrModeSoReg"); // R, R, I - MISC("t2addrmode_imm8s4", "kOperandTypeThumb2AddrModeImm8s4"); // R, I - MISC("t2addrmode_imm0_1020s4", "kOperandTypeThumb2AddrModeImm8s4"); // R, I - MISC("t2am_imm8s4_offset", "kOperandTypeThumb2AddrModeImm8s4Offset"); - // R, I - MISC("tb_addrmode", "kOperandTypeARMTBAddrMode"); // I - MISC("t_addrmode_rrs1", "kOperandTypeThumbAddrModeRegS1"); // R, R - MISC("t_addrmode_rrs2", "kOperandTypeThumbAddrModeRegS2"); // R, R - MISC("t_addrmode_rrs4", "kOperandTypeThumbAddrModeRegS4"); // R, R - MISC("t_addrmode_is1", "kOperandTypeThumbAddrModeImmS1"); // R, I - MISC("t_addrmode_is2", "kOperandTypeThumbAddrModeImmS2"); // R, I - MISC("t_addrmode_is4", "kOperandTypeThumbAddrModeImmS4"); // R, I - MISC("t_addrmode_rr", "kOperandTypeThumbAddrModeRR"); // R, R - MISC("t_addrmode_sp", "kOperandTypeThumbAddrModeSP"); // R, I - MISC("t_addrmode_pc", "kOperandTypeThumbAddrModePC"); // R, I - MISC("addrmode_tbb", "kOperandTypeThumbAddrModeRR"); // R, R - MISC("addrmode_tbh", "kOperandTypeThumbAddrModeRR"); // R, R - - return 1; -} - -#undef REG -#undef MEM -#undef MISC - -#undef SET - -/// ARMPopulateOperands - Handles all the operands in an ARM instruction, adding -/// the appropriate flags to their descriptors -/// -/// \param operandTypes A reference the array of operand type objects -/// \param inst The instruction to use as a source of information -static void ARMPopulateOperands( - LiteralConstantEmitter *(&operandTypes)[EDIS_MAX_OPERANDS], - const CodeGenInstruction &inst) { - if (!inst.TheDef->isSubClassOf("InstARM") && - !inst.TheDef->isSubClassOf("InstThumb")) - return; - - unsigned int index; - unsigned int numOperands = inst.Operands.size(); - - if (numOperands > EDIS_MAX_OPERANDS) { - errs() << "numOperands == " << numOperands << " > " << - EDIS_MAX_OPERANDS << '\n'; - llvm_unreachable("Too many operands"); - } - - for (index = 0; index < numOperands; ++index) { - const CGIOperandList::OperandInfo &operandInfo = inst.Operands[index]; - Record &rec = *operandInfo.Rec; - - if (ARMFlagFromOpName(operandTypes[index], rec.getName())) { - errs() << "Operand type: " << rec.getName() << '\n'; - errs() << "Operand name: " << operandInfo.Name << '\n'; - errs() << "Instruction name: " << inst.TheDef->getName() << '\n'; - PrintFatalError("Unhandled type in EDEmitter"); - } - } -} - -#define BRANCH(target) { \ - instType.set("kInstructionTypeBranch"); \ - DECORATE1(target, "kOperandFlagTarget"); \ -} - -/// ARMExtractSemantics - Performs various checks on the name of an ARM -/// instruction to determine what sort of an instruction it is and then adds -/// the appropriate flags to the instruction and its operands -/// -/// \param instType A reference to the type for the instruction as a whole -/// \param operandTypes A reference to the array of operand type object pointers -/// \param operandFlags A reference to the array of operand flag object pointers -/// \param inst A reference to the original instruction -static void ARMExtractSemantics( - LiteralConstantEmitter &instType, - LiteralConstantEmitter *(&operandTypes)[EDIS_MAX_OPERANDS], - FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS], - const CodeGenInstruction &inst) { - const std::string &name = inst.TheDef->getName(); - - if (name == "tBcc" || - name == "tB" || - name == "t2Bcc" || - name == "Bcc" || - name == "tCBZ" || - name == "tCBNZ") { - BRANCH("target"); - } - - if (name == "tBLr9" || - name == "BLr9_pred" || - name == "tBLXi_r9" || - name == "tBLXr_r9" || - name == "BLXr9" || - name == "t2BXJ" || - name == "BXJ") { - BRANCH("func"); - - unsigned opIndex; - opIndex = inst.Operands.getOperandNamed("func"); - if (operandTypes[opIndex]->is("kOperandTypeImmediate")) - operandTypes[opIndex]->set("kOperandTypeARMBranchTarget"); - } -} - -#undef BRANCH - -/// populateInstInfo - Fills an array of InstInfos with information about each -/// instruction in a target -/// -/// \param infoArray The array of InstInfo objects to populate -/// \param target The CodeGenTarget to use as a source of instructions -static void populateInstInfo(CompoundConstantEmitter &infoArray, - CodeGenTarget &target) { - const std::vector<const CodeGenInstruction*> &numberedInstructions = - target.getInstructionsByEnumValue(); - - unsigned int index; - unsigned int numInstructions = numberedInstructions.size(); - - for (index = 0; index < numInstructions; ++index) { - const CodeGenInstruction& inst = *numberedInstructions[index]; - - CompoundConstantEmitter *infoStruct = new CompoundConstantEmitter; - infoArray.addEntry(infoStruct); - - LiteralConstantEmitter *instType = new LiteralConstantEmitter; - infoStruct->addEntry(instType); - - LiteralConstantEmitter *numOperandsEmitter = - new LiteralConstantEmitter(inst.Operands.size()); - infoStruct->addEntry(numOperandsEmitter); - - CompoundConstantEmitter *operandTypeArray = new CompoundConstantEmitter; - infoStruct->addEntry(operandTypeArray); - - LiteralConstantEmitter *operandTypes[EDIS_MAX_OPERANDS]; - - CompoundConstantEmitter *operandFlagArray = new CompoundConstantEmitter; - infoStruct->addEntry(operandFlagArray); - - FlagsConstantEmitter *operandFlags[EDIS_MAX_OPERANDS]; - - for (unsigned operandIndex = 0; - operandIndex < EDIS_MAX_OPERANDS; - ++operandIndex) { - operandTypes[operandIndex] = new LiteralConstantEmitter; - operandTypeArray->addEntry(operandTypes[operandIndex]); - - operandFlags[operandIndex] = new FlagsConstantEmitter; - operandFlagArray->addEntry(operandFlags[operandIndex]); - } - - unsigned numSyntaxes = 0; - - // We don't need to do anything for pseudo-instructions, as we'll never - // see them here. We'll only see real instructions. - // We still need to emit null initializers for everything. - if (!inst.isPseudo) { - if (target.getName() == "X86") { - X86PopulateOperands(operandTypes, inst); - X86ExtractSemantics(*instType, operandFlags, inst); - numSyntaxes = 2; - } - else if (target.getName() == "ARM") { - ARMPopulateOperands(operandTypes, inst); - ARMExtractSemantics(*instType, operandTypes, operandFlags, inst); - numSyntaxes = 1; - } - } - - CompoundConstantEmitter *operandOrderArray = new CompoundConstantEmitter; - - infoStruct->addEntry(operandOrderArray); - - for (unsigned syntaxIndex = 0; - syntaxIndex < EDIS_MAX_SYNTAXES; - ++syntaxIndex) { - CompoundConstantEmitter *operandOrder = - new CompoundConstantEmitter(EDIS_MAX_OPERANDS); - - operandOrderArray->addEntry(operandOrder); - - if (syntaxIndex < numSyntaxes) { - populateOperandOrder(operandOrder, inst, syntaxIndex); - } - } - - infoStruct = NULL; - } -} - -static void emitCommonEnums(raw_ostream &o, unsigned int &i) { - EnumEmitter operandTypes("OperandTypes"); - operandTypes.addEntry("kOperandTypeNone"); - operandTypes.addEntry("kOperandTypeImmediate"); - operandTypes.addEntry("kOperandTypeRegister"); - operandTypes.addEntry("kOperandTypeX86Memory"); - operandTypes.addEntry("kOperandTypeX86EffectiveAddress"); - operandTypes.addEntry("kOperandTypeX86PCRelative"); - operandTypes.addEntry("kOperandTypeARMBranchTarget"); - operandTypes.addEntry("kOperandTypeARMSoRegReg"); - operandTypes.addEntry("kOperandTypeARMSoRegImm"); - operandTypes.addEntry("kOperandTypeARMSoImm"); - operandTypes.addEntry("kOperandTypeARMRotImm"); - operandTypes.addEntry("kOperandTypeARMSoImm2Part"); - operandTypes.addEntry("kOperandTypeARMPredicate"); - operandTypes.addEntry("kOperandTypeAddrModeImm12"); - operandTypes.addEntry("kOperandTypeLdStSOReg"); - operandTypes.addEntry("kOperandTypeARMAddrMode2"); - operandTypes.addEntry("kOperandTypeARMAddrMode2Offset"); - operandTypes.addEntry("kOperandTypeARMAddrMode3"); - operandTypes.addEntry("kOperandTypeARMAddrMode3Offset"); - operandTypes.addEntry("kOperandTypeARMLdStmMode"); - operandTypes.addEntry("kOperandTypeARMAddrMode5"); - operandTypes.addEntry("kOperandTypeARMAddrMode6"); - operandTypes.addEntry("kOperandTypeARMAddrMode6Offset"); - operandTypes.addEntry("kOperandTypeARMAddrMode7"); - operandTypes.addEntry("kOperandTypeARMAddrModePC"); - operandTypes.addEntry("kOperandTypeARMRegisterList"); - operandTypes.addEntry("kOperandTypeARMDPRRegisterList"); - operandTypes.addEntry("kOperandTypeARMSPRRegisterList"); - operandTypes.addEntry("kOperandTypeARMTBAddrMode"); - operandTypes.addEntry("kOperandTypeThumbITMask"); - operandTypes.addEntry("kOperandTypeThumbAddrModeImmS1"); - operandTypes.addEntry("kOperandTypeThumbAddrModeImmS2"); - operandTypes.addEntry("kOperandTypeThumbAddrModeImmS4"); - operandTypes.addEntry("kOperandTypeThumbAddrModeRegS1"); - operandTypes.addEntry("kOperandTypeThumbAddrModeRegS2"); - operandTypes.addEntry("kOperandTypeThumbAddrModeRegS4"); - operandTypes.addEntry("kOperandTypeThumbAddrModeRR"); - operandTypes.addEntry("kOperandTypeThumbAddrModeSP"); - operandTypes.addEntry("kOperandTypeThumbAddrModePC"); - operandTypes.addEntry("kOperandTypeThumb2AddrModeReg"); - operandTypes.addEntry("kOperandTypeThumb2SoReg"); - operandTypes.addEntry("kOperandTypeThumb2SoImm"); - operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8"); - operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8Offset"); - operandTypes.addEntry("kOperandTypeThumb2AddrModeImm12"); - operandTypes.addEntry("kOperandTypeThumb2AddrModeSoReg"); - operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8s4"); - operandTypes.addEntry("kOperandTypeThumb2AddrModeImm8s4Offset"); - operandTypes.emit(o, i); - - o << "\n"; - - EnumEmitter operandFlags("OperandFlags"); - operandFlags.addEntry("kOperandFlagSource"); - operandFlags.addEntry("kOperandFlagTarget"); - operandFlags.emitAsFlags(o, i); - - o << "\n"; - - EnumEmitter instructionTypes("InstructionTypes"); - instructionTypes.addEntry("kInstructionTypeNone"); - instructionTypes.addEntry("kInstructionTypeMove"); - instructionTypes.addEntry("kInstructionTypeBranch"); - instructionTypes.addEntry("kInstructionTypePush"); - instructionTypes.addEntry("kInstructionTypePop"); - instructionTypes.addEntry("kInstructionTypeCall"); - instructionTypes.addEntry("kInstructionTypeReturn"); - instructionTypes.emit(o, i); - - o << "\n"; -} - -namespace llvm { - -void EmitEnhancedDisassemblerInfo(RecordKeeper &RK, raw_ostream &OS) { - emitSourceFileHeader("Enhanced Disassembler Info", OS); - unsigned int i = 0; - - CompoundConstantEmitter infoArray; - CodeGenTarget target(RK); - - populateInstInfo(infoArray, target); - - emitCommonEnums(OS, i); - - OS << "static const llvm::EDInstInfo instInfo" - << target.getName() << "[] = "; - infoArray.emit(OS, i); - OS << ";" << "\n"; -} - -} // End llvm namespace diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp index b2dc878880..0c3017f389 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -1866,7 +1866,7 @@ static void emitFieldFromInstruction(formatted_raw_ostream &OS) { << " if (numBits == sizeof(InsnType)*8)\n" << " fieldMask = (InsnType)(-1LL);\n" << " else\n" - << " fieldMask = ((1 << numBits) - 1) << startBit;\n" + << " fieldMask = (((InsnType)1 << numBits) - 1) << startBit;\n" << " return (insn & fieldMask) >> startBit;\n" << "}\n\n"; } diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index 967c58b3d2..df4d847a4d 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -221,27 +221,28 @@ enum IIT_Info { IIT_I16 = 3, IIT_I32 = 4, IIT_I64 = 5, - IIT_F32 = 6, - IIT_F64 = 7, - IIT_V2 = 8, - IIT_V4 = 9, - IIT_V8 = 10, - IIT_V16 = 11, - IIT_V32 = 12, - IIT_MMX = 13, + IIT_F16 = 6, + IIT_F32 = 7, + IIT_F64 = 8, + IIT_V2 = 9, + IIT_V4 = 10, + IIT_V8 = 11, + IIT_V16 = 12, + IIT_V32 = 13, IIT_PTR = 14, IIT_ARG = 15, - + // Values from 16+ are only encodable with the inefficient encoding. - IIT_METADATA = 16, - IIT_EMPTYSTRUCT = 17, - IIT_STRUCT2 = 18, - IIT_STRUCT3 = 19, - IIT_STRUCT4 = 20, - IIT_STRUCT5 = 21, - IIT_EXTEND_VEC_ARG = 22, - IIT_TRUNC_VEC_ARG = 23, - IIT_ANYPTR = 24 + IIT_MMX = 16, + IIT_METADATA = 17, + IIT_EMPTYSTRUCT = 18, + IIT_STRUCT2 = 19, + IIT_STRUCT3 = 20, + IIT_STRUCT4 = 21, + IIT_STRUCT5 = 22, + IIT_EXTEND_VEC_ARG = 23, + IIT_TRUNC_VEC_ARG = 24, + IIT_ANYPTR = 25 }; @@ -261,6 +262,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT, switch (VT) { default: PrintFatalError("unhandled MVT in intrinsic!"); + case MVT::f16: return Sig.push_back(IIT_F16); case MVT::f32: return Sig.push_back(IIT_F32); case MVT::f64: return Sig.push_back(IIT_F64); case MVT::Metadata: return Sig.push_back(IIT_METADATA); @@ -532,9 +534,8 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { N = ++AttrNum; } - // Emit an array of AttributeWithIndex. Most intrinsics will have - // at least one entry, for the function itself (index ~1), which is - // usually nounwind. + // Emit an array of AttributeSet. Most intrinsics will have at least one + // entry, for the function itself (index ~1), which is usually nounwind. OS << " static const uint8_t IntrinsicsToAttributesMap[] = {\n"; for (unsigned i = 0, e = Ints.size(); i != e; ++i) { @@ -545,10 +546,10 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { } OS << " };\n\n"; - OS << " AttributeWithIndex AWI[" << maxArgAttrs+1 << "];\n"; + OS << " AttributeSet AS[" << maxArgAttrs+1 << "];\n"; OS << " unsigned NumAttrs = 0;\n"; OS << " if (id != 0) {\n"; - OS << " SmallVector<Attributes::AttrVal, 8> AttrVec;\n"; + OS << " SmallVector<Attribute::AttrKind, 8> AttrVec;\n"; OS << " switch(IntrinsicsToAttributesMap[id - "; if (TargetOnly) OS << "Intrinsic::num_intrinsics"; @@ -576,14 +577,14 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { do { switch (intrinsic.ArgumentAttributes[ai].second) { case CodeGenIntrinsic::NoCapture: - OS << " AttrVec.push_back(Attributes::NoCapture);\n"; + OS << " AttrVec.push_back(Attribute::NoCapture);\n"; break; } ++ai; } while (ai != ae && intrinsic.ArgumentAttributes[ai].first == argNo); - OS << " AWI[" << numAttrs++ << "] = AttributeWithIndex::get(C, " + OS << " AS[" << numAttrs++ << "] = AttributeSet::get(C, " << argNo+1 << ", AttrVec);\n"; } } @@ -594,20 +595,20 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { OS << " AttrVec.clear();\n"; if (!intrinsic.canThrow) - OS << " AttrVec.push_back(Attributes::NoUnwind);\n"; + OS << " AttrVec.push_back(Attribute::NoUnwind);\n"; if (intrinsic.isNoReturn) - OS << " AttrVec.push_back(Attributes::NoReturn);\n"; + OS << " AttrVec.push_back(Attribute::NoReturn);\n"; switch (modRef) { case MRK_none: break; case MRK_readonly: - OS << " AttrVec.push_back(Attributes::ReadOnly);\n"; + OS << " AttrVec.push_back(Attribute::ReadOnly);\n"; break; case MRK_readnone: - OS << " AttrVec.push_back(Attributes::ReadNone);\n"; + OS << " AttrVec.push_back(Attribute::ReadNone);\n"; break; } - OS << " AWI[" << numAttrs++ << "] = AttributeWithIndex::get(C, " + OS << " AS[" << numAttrs++ << "] = AttributeSet::get(C, " << "AttributeSet::FunctionIndex, AttrVec);\n"; } @@ -621,7 +622,7 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) { OS << " }\n"; OS << " }\n"; - OS << " return AttributeSet::get(C, ArrayRef<AttributeWithIndex>(AWI, " + OS << " return AttributeSet::get(C, ArrayRef<AttributeSet>(AS, " "NumAttrs));\n"; OS << "}\n"; OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n"; diff --git a/utils/TableGen/OptParserEmitter.cpp b/utils/TableGen/OptParserEmitter.cpp index 5dab9e63a0..0c1f6236e0 100644 --- a/utils/TableGen/OptParserEmitter.cpp +++ b/utils/TableGen/OptParserEmitter.cpp @@ -8,12 +8,11 @@ //===----------------------------------------------------------------------===// #include "llvm/TableGen/Error.h" -#include "llvm/TableGen/Record.h" -#include "llvm/TableGen/TableGenBackend.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" - +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenBackend.h" #include <map> using namespace llvm; diff --git a/utils/TableGen/PseudoLoweringEmitter.cpp b/utils/TableGen/PseudoLoweringEmitter.cpp index 64aaee756b..1ea6f7932a 100644 --- a/utils/TableGen/PseudoLoweringEmitter.cpp +++ b/utils/TableGen/PseudoLoweringEmitter.cpp @@ -252,6 +252,7 @@ void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) { MIOpNo += Dest.Operands[OpNo].MINumOperands; } if (Dest.Operands.isVariadic) { + MIOpNo = Source.Operands.size() + 1; o << " // variable_ops\n"; o << " for (unsigned i = " << MIOpNo << ", e = MI->getNumOperands(); i != e; ++i)\n" diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 66adb61a32..cf225117e1 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -921,9 +921,9 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, // MCRegisterInfo initialization routine. OS << "static inline void Init" << TargetName << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, " - << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0) {\n" + << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0, unsigned PC = 0) {\n" << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " - << Regs.size()+1 << ", RA, " << TargetName << "MCRegisterClasses, " + << Regs.size()+1 << ", RA, PC, " << TargetName << "MCRegisterClasses, " << RegisterClasses.size() << ", " << TargetName << "RegUnitRoots, " << RegBank.getNumNativeRegUnits() << ", " @@ -958,7 +958,7 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, OS << "struct " << ClassName << " : public TargetRegisterInfo {\n" << " explicit " << ClassName - << "(unsigned RA, unsigned D = 0, unsigned E = 0);\n" + << "(unsigned RA, unsigned D = 0, unsigned E = 0, unsigned PC = 0);\n" << " virtual bool needsStackRealignment(const MachineFunction &) const\n" << " { return false; }\n"; if (!RegBank.getSubRegIndices().empty()) { @@ -1267,12 +1267,12 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, EmitRegMappingTables(OS, Regs, true); OS << ClassName << "::\n" << ClassName - << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour)\n" + << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour, unsigned PC)\n" << " : TargetRegisterInfo(" << TargetName << "RegInfoDesc" << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n" << " SubRegIndexNameTable, SubRegIndexLaneMaskTable) {\n" << " InitMCRegisterInfo(" << TargetName << "RegDesc, " - << Regs.size()+1 << ", RA,\n " << TargetName + << Regs.size()+1 << ", RA, PC,\n " << TargetName << "MCRegisterClasses, " << RegisterClasses.size() << ",\n" << " " << TargetName << "RegUnitRoots,\n" << " " << RegBank.getNumNativeRegUnits() << ",\n" diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index 3b7d006fd1..93eef868ea 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -893,7 +893,20 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel, WPREntry.Cycles = Cycles[PRIdx]; else WPREntry.Cycles = 1; - WriteProcResources.push_back(WPREntry); + // If this resource is already used in this sequence, add the current + // entry's cycles so that the same resource appears to be used + // serially, rather than multiple parallel uses. This is important for + // in-order machine where the resource consumption is a hazard. + unsigned WPRIdx = 0, WPREnd = WriteProcResources.size(); + for( ; WPRIdx != WPREnd; ++WPRIdx) { + if (WriteProcResources[WPRIdx].ProcResourceIdx + == WPREntry.ProcResourceIdx) { + WriteProcResources[WPRIdx].Cycles += WPREntry.Cycles; + break; + } + } + if (WPRIdx == WPREnd) + WriteProcResources.push_back(WPREntry); } } WriteLatencies.push_back(WLEntry); @@ -1108,6 +1121,7 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { EmitProcessorProp(OS, PI->ModelDef, "MinLatency", ','); EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ','); EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ','); + EmitProcessorProp(OS, PI->ModelDef, "ILPWindow", ','); EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ','); OS << " " << PI->Index << ", // Processor ID\n"; if (PI->hasInstrSchedModel()) diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index 06be55bde7..510f2548cd 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -38,7 +38,6 @@ enum ActionType { GenSubtarget, GenIntrinsic, GenTgtIntrinsic, - GenEDInfo, PrintEnums, PrintSets, GenOptParserDefs @@ -77,8 +76,6 @@ namespace { "Generate intrinsic information"), clEnumValN(GenTgtIntrinsic, "gen-tgt-intrinsic", "Generate target intrinsic information"), - clEnumValN(GenEDInfo, "gen-enhanced-disassembly-info", - "Generate enhanced disassembly info"), clEnumValN(PrintEnums, "print-enums", "Print enum values for a class"), clEnumValN(PrintSets, "print-sets", @@ -138,9 +135,6 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) { case GenTgtIntrinsic: EmitIntrinsics(Records, OS, true); break; - case GenEDInfo: - EmitEnhancedDisassemblerInfo(Records, OS); - break; case GenOptParserDefs: EmitOptParser(Records, OS); break; diff --git a/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h index 4c0d8dcb4f..cc99092658 100644 --- a/utils/TableGen/TableGenBackends.h +++ b/utils/TableGen/TableGenBackends.h @@ -68,7 +68,6 @@ void EmitCodeEmitter(RecordKeeper &RK, raw_ostream &OS); void EmitDAGISel(RecordKeeper &RK, raw_ostream &OS); void EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS); void EmitDisassembler(RecordKeeper &RK, raw_ostream &OS); -void EmitEnhancedDisassemblerInfo(RecordKeeper &RK, raw_ostream &OS); void EmitFastISel(RecordKeeper &RK, raw_ostream &OS); void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS); void EmitPseudoLowering(RecordKeeper &RK, raw_ostream &OS); diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index b99a6eb87e..8471faaaf6 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -119,6 +119,7 @@ namespace X86Local { #define TWO_BYTE_EXTENSION_TABLES \ EXTENSION_TABLE(00) \ EXTENSION_TABLE(01) \ + EXTENSION_TABLE(0d) \ EXTENSION_TABLE(18) \ EXTENSION_TABLE(71) \ EXTENSION_TABLE(72) \ @@ -763,6 +764,17 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) { HANDLE_OPERAND(immediate) HANDLE_OPERAND(immediate) break; + case X86Local::MRM_F8: + if (Opcode == 0xc6) { + assert(numPhysicalOperands == 1 && + "Unexpected number of operands for X86Local::MRM_F8"); + HANDLE_OPERAND(immediate) + } else if (Opcode == 0xc7) { + assert(numPhysicalOperands == 1 && + "Unexpected number of operands for X86Local::MRM_F8"); + HANDLE_OPERAND(relocation) + } + break; case X86Local::MRMInitReg: // Ignored. break; diff --git a/utils/buildit/build_llvm b/utils/buildit/build_llvm index 6aee831046..c056b9742b 100755 --- a/utils/buildit/build_llvm +++ b/utils/buildit/build_llvm @@ -77,6 +77,45 @@ rm $SRC_DIR/Makefile || exit 1 # Now create our own by editing the top-level Makefile, deleting every line marked "Apple-style": sed -e '/[Aa]pple-style/d' -e '/include.*GNUmakefile/d' $ORIG_SRC_DIR/Makefile > $SRC_DIR/Makefile || exit 1 +SUBVERSION=`echo $RC_ProjectSourceVersion | sed -e 's/.*\.\([0-9]*\).*/\1/'` +if [ "x$SUBVERSION" != "x$RC_ProjectSourceVersion" ]; then + LLVM_SUBMIT_SUBVERSION=`printf "%02d" $SUBVERSION` + RC_ProjectSourceVersion=`echo $RC_ProjectSourceVersion | sed -e 's/\..*//'` + LLVM_SUBMIT_VERSION=$RC_ProjectSourceVersion +fi +if [ "x$LLVM_SUBMIT_SUBVERSION" = "x00" -o "x$LLVM_SUBMIT_SUBVERSION" = "x0" ]; then + LLVM_VERSION="$LLVM_SUBMIT_VERSION" +else + LLVM_VERSION="$LLVM_SUBMIT_VERSION-$LLVM_SUBMIT_SUBVERSION" +fi + +# Figure out how many make processes to run. +SYSCTL=`sysctl -n hw.activecpu` +# sysctl -n hw.* does not work when invoked via B&I chroot /BuildRoot. +# Builders can default to 2, since even if they are single processor, +# nothing else is running on the machine. +if [ -z "$SYSCTL" ]; then + SYSCTL=2 +fi +JOBS_FLAG="-j $SYSCTL" + +COMMON_CONFIGURE_OPTS="\ + --prefix=$DEST_DIR$DEST_ROOT \ + --enable-assertions=$LLVM_ASSERTIONS \ + --enable-optimized=$LLVM_OPTIMIZED \ + --disable-bindings" + +COMMON_MAKEFLAGS="\ + UNIVERSAL=1 \ + UNIVERSAL_SDK_PATH=$SDKROOT \ + NO_RUNTIME_LIBS=1 \ + DISABLE_EDIS=1 \ + REQUIRES_RTTI=1 \ + DEBUG_SYMBOLS=1 \ + LLVM_SUBMIT_VERSION=$LLVM_SUBMIT_VERSION \ + LLVM_SUBMIT_SUBVERSION=$LLVM_SUBMIT_SUBVERSION \ + VERBOSE=1" + # Build the LLVM tree universal. mkdir -p $DIR/obj-llvm || exit 1 cd $DIR/obj-llvm || exit 1 @@ -89,6 +128,7 @@ if [ "$ARM_HOSTED_BUILD" = yes ]; then for prog in ar nm ranlib strip lipo ld as ; do P=$DIR/bin/arm-apple-darwin$DARWIN_VERS-${prog} T=`xcrun -sdk $SDKROOT -find ${prog}` + ln -s $T $DIR/bin/$prog echo '#!/bin/sh' > $P || exit 1 echo 'exec '$T' "$@"' >> $P || exit 1 chmod a+x $P || exit 1 @@ -97,80 +137,74 @@ if [ "$ARM_HOSTED_BUILD" = yes ]; then for prog in clang clang++ ; do P=$DIR/bin/arm-apple-darwin$DARWIN_VERS-${prog} T=`xcrun -sdk $SDKROOT -find ${prog}` + ln -s $T $DIR/bin/$prog echo '#!/bin/sh' > $P || exit 1 echo 'exec '$T' -arch armv7 -isysroot '${SDKROOT}' "$@"' >> $P || exit 1 chmod a+x $P || exit 1 done PATH=$DIR/bin:$PATH -fi -if [ "$ARM_HOSTED_BUILD" = yes ]; then - configure_opts="--enable-targets=arm --host=arm-apple-darwin10 \ - --target=arm-apple-darwin10 --build=i686-apple-darwin10" -elif [ "$IOS_SIM_BUILD" = yes ]; then - # Use a non-standard "darwin_sim" host triple to trigger a cross-build. - configure_opts="--enable-targets=x86 --host=i686-apple-darwin_sim \ - --build=i686-apple-darwin10" + unset SDKROOT && \ + $SRC_DIR/configure $COMMON_CONFIGURE_OPTS \ + --enable-targets=arm \ + --host=arm-apple-darwin10 \ + --target=arm-apple-darwin10 \ + --build=i686-apple-darwin10 \ + --program-prefix="" \ + || exit 1 + + if [ -n "$IPHONEOS_DEPLOYMENT_TARGET" ]; then + COMMON_MAKEFLAGS="$COMMON_MAKEFLAGS \ + DEPLOYMENT_TARGET=-mios-version-min=$IPHONEOS_DEPLOYMENT_TARGET" + fi + + make $JOBS_FLAG $COMMON_MAKEFLAGS SDKROOT= UNIVERSAL_ARCH="$HOSTS" \ + CXXFLAGS="-DLLVM_VERSION_INFO='\" Apple Build #$LLVM_VERSION\"'" + if [ $? != 0 ] ; then + echo "error: LLVM 'make' failed!" + exit 1 + fi + else - configure_opts="--enable-targets=arm,x86" -fi +# not $ARM_HOSTED_BUILD + + export CC=`xcrun -find clang` + export CXX=`xcrun -find clang++` + + if [ "$IOS_SIM_BUILD" = yes ]; then + # Use a non-standard "darwin_sim" host triple to trigger a cross-build. + configure_opts="--enable-targets=x86 --host=i686-apple-darwin_sim \ + --build=i686-apple-darwin10" + if [ -n "$IPHONEOS_DEPLOYMENT_TARGET" ]; then + COMMON_MAKEFLAGS="$COMMON_MAKEFLAGS \ + DEPLOYMENT_TARGET=-mios-simulator-version-min=$IPHONEOS_DEPLOYMENT_TARGET" + fi + else + configure_opts="--enable-targets=arm,x86" + if [ -n "$MACOSX_DEPLOYMENT_TARGET" ]; then + COMMON_MAKEFLAGS="$COMMON_MAKEFLAGS \ + DEPLOYMENT_TARGET=-mmacosx-version-min=$MACOSX_DEPLOYMENT_TARGET" + fi + fi -if [ "$ARM_HOSTED_BUILD" != yes ]; then if [ $SDKROOT ]; then CPPFLAGS="$CPPFLAGS -isysroot $SDKROOT" fi for host in $HOSTS; do :; done CPPFLAGS="$CPPFLAGS -arch $host" -fi -if [ \! -f Makefile.config ]; then - $SRC_DIR/configure --prefix=$DEST_DIR$DEST_ROOT $configure_opts \ - --enable-assertions=$LLVM_ASSERTIONS \ - --enable-optimized=$LLVM_OPTIMIZED \ - --disable-bindings \ + $SRC_DIR/configure $COMMON_CONFIGURE_OPTS $configure_opts \ + --program-prefix="" \ CPPFLAGS="$CPPFLAGS" \ || exit 1 -fi - -SUBVERSION=`echo $RC_ProjectSourceVersion | sed -e 's/.*\.\([0-9]*\).*/\1/'` - -if [ "x$SUBVERSION" != "x$RC_ProjectSourceVersion" ]; then - LLVM_SUBMIT_SUBVERSION=`printf "%02d" $SUBVERSION` - RC_ProjectSourceVersion=`echo $RC_ProjectSourceVersion | sed -e 's/\..*//'` - LLVM_SUBMIT_VERSION=$RC_ProjectSourceVersion -fi -if [ "x$LLVM_SUBMIT_SUBVERSION" = "x00" -o "x$LLVM_SUBMIT_SUBVERSION" = "x0" ]; then - LLVM_VERSION="$LLVM_SUBMIT_VERSION" -else - LLVM_VERSION="$LLVM_SUBMIT_VERSION-$LLVM_SUBMIT_SUBVERSION" -fi - -# Figure out how many make processes to run. -SYSCTL=`sysctl -n hw.activecpu` -# sysctl -n hw.* does not work when invoked via B&I chroot /BuildRoot. -# Builders can default to 2, since even if they are single processor, -# nothing else is running on the machine. -if [ -z "$SYSCTL" ]; then - SYSCTL=2 -fi -JOBS_FLAG="-j $SYSCTL" - -make $JOBS_FLAG $OPTIMIZE_OPTS UNIVERSAL=1 UNIVERSAL_ARCH="$HOSTS" \ - UNIVERSAL_SDK_PATH=$SDKROOT \ - NO_RUNTIME_LIBS=1 \ - DISABLE_EDIS=1 \ - REQUIRES_RTTI=1 \ - DEBUG_SYMBOLS=1 \ - LLVM_SUBMIT_VERSION=$LLVM_SUBMIT_VERSION \ - LLVM_SUBMIT_SUBVERSION=$LLVM_SUBMIT_SUBVERSION \ - CXXFLAGS="-DLLVM_VERSION_INFO='\" Apple Build #$LLVM_VERSION\"'" \ - VERBOSE=1 - -if [ $? != 0 ] ; then + make $JOBS_FLAG $COMMON_MAKEFLAGS UNIVERSAL_ARCH="$HOSTS" \ + CXXFLAGS="-DLLVM_VERSION_INFO='\" Apple Build #$LLVM_VERSION\"'" + if [ $? != 0 ] ; then echo "error: LLVM 'make' failed!" exit 1 + fi fi ################################################################################ @@ -185,14 +219,7 @@ rm -rf * || exit 1 cd $DIR/obj-llvm || exit 1 # Install the tree into the destination directory. -make $LOCAL_MAKEFLAGS $OPTIMIZE_OPTS UNIVERSAL=1 UNIVERSAL_ARCH="$HOSTS" \ - NO_RUNTIME_LIBS=1 \ - DISABLE_EDIS=1 \ - DEBUG_SYMBOLS=1 \ - LLVM_SUBMIT_VERSION=$LLVM_SUBMIT_VERSION \ - LLVM_SUBMIT_SUBVERSION=$LLVM_SUBMIT_SUBVERSION \ - OPTIMIZE_OPTION='-O3' VERBOSE=1 install - +make $JOBS_FLAG $COMMON_MAKEFLAGS UNIVERSAL_ARCH="$HOSTS" install if ! test $? == 0 ; then echo "error: LLVM 'make install' failed!" exit 1 @@ -207,6 +234,16 @@ RC_ProjectSourceSubversion=`printf "%d" $LLVM_MINOR_VERSION` echo "#define LLVM_VERSION ${RC_ProjectSourceVersion}" > $DEST_DIR$DEST_ROOT/include/llvm/Version.h echo "#define LLVM_MINOR_VERSION ${RC_ProjectSourceSubversion}" >> $DEST_DIR$DEST_ROOT/include/llvm/Version.h +# Run unifdef to preprocess the installed headers to reflect whether this +# was a debug or release build. +for file in `find $DEST_DIR$DEST_ROOT/include -type f -print`; do + if [ "$LLVM_ASSERTIONS" = yes ]; then + unifdef -UNDEBUG -D_DEBUG -o $file $file + else + unifdef -DNDEBUG -U_DEBUG -ULLVM_ENABLE_DUMP -o $file $file + fi +done + # Find the right version of strip to use. STRIP=strip if [ -n "$SDKROOT" ]; then @@ -263,9 +300,10 @@ cd $SYM_DIR || exit 1 rm -rf * || exit 1 # Generate .dSYM files +DSYMUTIL=`xcrun -find dsymutil` find $DEST_DIR -perm -0111 -type f \ ! \( -name '*.la' -o -name gccas -o -name gccld -o -name llvm-config -o -name '*.a' \) \ - -print | xargs -n 1 -P ${SYSCTL} dsymutil + -print | xargs -n 1 -P ${SYSCTL} ${DSYMUTIL} # Save .dSYM files and .a archives cd $DEST_DIR || exit 1 diff --git a/utils/clang-parse-diagnostics-file b/utils/clang-parse-diagnostics-file index b8ea8eae31..59b13f3065 100755 --- a/utils/clang-parse-diagnostics-file +++ b/utils/clang-parse-diagnostics-file @@ -1,5 +1,6 @@ #!/usr/bin/env python +import os import plistlib def main(): @@ -59,20 +60,37 @@ Utility for dumping Clang-style logged diagnostics.\ </array> </plist>""" % data - # Load the diagnostics. + # Get the list of files and diagnostics to report. + to_report = [] diags = plistlib.readPlistFromString(data) + for file_diags in diags: + file = file_diags.get('main-file') + + # Ignore diagnostics for 'conftest.c', which is the file autoconf uses + # for its tests (which frequently will have warnings). + if os.path.basename(file) == 'conftest.c': + continue + + # Get the diagnostics for the selected levels. + selected_diags = [d + for d in file_diags.get('diagnostics', ()) + if levels[d.get('level')] or opts.all] + if selected_diags: + to_report.append((file, selected_diags)) - # Print out the diagnostics. + # If there are no diagnostics to report, show nothing. + if not to_report: + return + + # Otherwise, print out the diagnostics. print print "**** BUILD DIAGNOSTICS ****" - for i, file_diags in enumerate(diags): - file = file_diags.get('main-file') + for file,selected_diags in to_report: print "*** %s ***" % file - for d in file_diags.get('diagnostics', ()): - if levels[d.get('level')] or opts.all: - print " %s:%s:%s: %s: %s" % ( - d.get('filename'), d.get('line'), d.get('column'), - d.get('level'), d.get('message')) + for d in selected_diags: + print " %s:%s:%s: %s: %s" % ( + d.get('filename'), d.get('line'), d.get('column'), + d.get('level'), d.get('message')) if __name__ == "__main__": main() diff --git a/utils/git/find-rev b/utils/git/find-rev index a6161db189..059ca0b78d 100755 --- a/utils/git/find-rev +++ b/utils/git/find-rev @@ -5,9 +5,9 @@ import os, sys, subprocess def main(): from optparse import OptionParser, OptionGroup parser = OptionParser("usage: %prog [options] <repo> <revision>") - parser.add_option("", "--dump-section-data", dest="dumpSectionData", - help="Dump the contents of sections", - action="store_true", default=False) + parser.add_option("", "--branch", dest="branch", + help="Ref for the branch to search [%default]", + action="store", default="git-svn") (opts, args) = parser.parse_args() if len(args) != 2: @@ -21,7 +21,7 @@ def main(): parser.error("invalid revision argument (not an integer)") os.chdir(repo) - p = subprocess.Popen(['git', 'rev-list', 'git-svn', '--pretty'], + p = subprocess.Popen(['git', 'rev-list', opts.branch, '--pretty'], stdout=subprocess.PIPE) bestRev = bestCommit = None diff --git a/utils/kate/llvm.xml b/utils/kate/llvm.xml index 074fa16cb8..1778cfce38 100644 --- a/utils/kate/llvm.xml +++ b/utils/kate/llvm.xml @@ -90,6 +90,7 @@ <item> readonly </item> <item> ssp </item> <item> sspreq </item> + <item> sspstrong </item> </list> <list name="types"> <item> float </item> diff --git a/utils/lit/MANIFEST.in b/utils/lit/MANIFEST.in new file mode 100644 index 0000000000..6491a02dd1 --- /dev/null +++ b/utils/lit/MANIFEST.in @@ -0,0 +1,7 @@ +include TODO lit.py +recursive-include tests * +global-exclude *pyc +global-exclude *~ +prune tests/Output +prune tests/*/Output +prune tests/*/*/Output diff --git a/utils/lit/TODO b/utils/lit/TODO index 6d7f7ea529..d2ff842f31 100644 --- a/utils/lit/TODO +++ b/utils/lit/TODO @@ -7,3 +7,20 @@ - Support valgrind in all configs, and LLVM style valgrind. - Support a timeout / ulimit. + + - Rename 'lit' injected variable for config to be lit_config. + + - Allow import of 'lit' in test suite definitions. + + - Create an explicit test suite object (instead of using the top-level + TestingConfig object). + + - Allow 'lit' driver to cooperate with test suites to add options (or at least + sanitize accepted params). + + - Consider move to identifying all tests by path-to-test-suite and then path to + subtest, and don't use test suite names. + + - Consider move to change workflow to always load suites, then resolve command + line arguments. + diff --git a/utils/lit/lit/ExampleTests/Clang/lit.cfg b/utils/lit/lit/ExampleTests/Clang/lit.cfg index 1e1e807f36..9295bd9ddb 100644 --- a/utils/lit/lit/ExampleTests/Clang/lit.cfg +++ b/utils/lit/lit/ExampleTests/Clang/lit.cfg @@ -14,7 +14,7 @@ config.test_format = lit.formats.ShTest(execute_external = True) # suffixes: A list of file extensions to treat as test files. config.suffixes = ['.c', '.cpp', '.m', '.mm'] -# target_triple: Used by ShTest and TclTest formats for XFAIL checks. +# target_triple: Used by ShTest format for XFAIL checks. config.target_triple = 'foo' ### diff --git a/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/data.txt b/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/data.txt new file mode 100644 index 0000000000..45b983be36 --- /dev/null +++ b/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/data.txt @@ -0,0 +1 @@ +hi diff --git a/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/dg.exp b/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/dg.exp deleted file mode 100644 index 2bda07a31c..0000000000 --- a/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/dg.exp +++ /dev/null @@ -1,6 +0,0 @@ -load_lib llvm.exp - -if { [llvm_supports_target X86] } { - RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll}]] -} - diff --git a/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/pct-S.ll b/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/pct-S.ll new file mode 100644 index 0000000000..3ff363315a --- /dev/null +++ b/utils/lit/lit/ExampleTests/LLVM.InTree/test/Bar/pct-S.ll @@ -0,0 +1 @@ +; RUN: grep "hi" %S/data.txt diff --git a/utils/lit/lit/ExampleTests/LLVM.InTree/test/lit.cfg b/utils/lit/lit/ExampleTests/LLVM.InTree/test/lit.cfg index 3fdd63c224..533c44501f 100644 --- a/utils/lit/lit/ExampleTests/LLVM.InTree/test/lit.cfg +++ b/utils/lit/lit/ExampleTests/LLVM.InTree/test/lit.cfg @@ -8,11 +8,11 @@ import os config.name = 'LLVM' # testFormat: The test format to use to interpret tests. -config.test_format = lit.formats.TclTest() +config.test_format = lit.formats.ShTest() # suffixes: A list of file extensions to treat as test files, this is actually # set by on_clone(). -config.suffixes = [] +config.suffixes = [ '.ll' ] # test_source_root: The root path where tests are located. config.test_source_root = os.path.dirname(__file__) @@ -64,74 +64,3 @@ if config.test_exec_root is None: lit.load_config(config, site_cfg) raise SystemExit -### - -# Load site data from DejaGNU's site.exp. -import re -site_exp = {} -# FIXME: Implement lit.site.cfg. -for line in open(os.path.join(config.llvm_obj_root, 'test', 'site.exp')): - m = re.match('set ([^ ]+) "([^"]*)"', line) - if m: - site_exp[m.group(1)] = m.group(2) - -excludes = [] - -# Provide target_triple for use in XFAIL. -config.target_triple = site_exp['target_triplet'] - -# Provide llvm_supports_target for use in local configs. -targets = set(site_exp["TARGETS_TO_BUILD"].split()) -def llvm_supports_target(name): - return name in targets - -# Provide on_clone hook for reading 'dg.exp'. -import os -simpleLibData = re.compile(r"""load_lib llvm.exp - -RunLLVMTests \[lsort \[glob -nocomplain \$srcdir/\$subdir/\*\.(.*)\]\]""", - re.MULTILINE) -conditionalLibData = re.compile(r"""load_lib llvm.exp - -if.*\[ ?(llvm[^ ]*) ([^ ]*) ?\].*{ - *RunLLVMTests \[lsort \[glob -nocomplain \$srcdir/\$subdir/\*\.(.*)\]\] -\}""", re.MULTILINE) -def on_clone(parent, cfg, for_path): - def addSuffixes(match): - if match[0] == '{' and match[-1] == '}': - cfg.suffixes = ['.' + s for s in match[1:-1].split(',')] - else: - cfg.suffixes = ['.' + match] - - libPath = os.path.join(os.path.dirname(for_path), - 'dg.exp') - if not os.path.exists(libPath): - cfg.unsupported = True - return - - # Reset unsupported, in case we inherited it. - cfg.unsupported = False - lib = open(libPath).read().strip() - - # Check for a simple library. - m = simpleLibData.match(lib) - if m: - addSuffixes(m.group(1)) - return - - # Check for a conditional test set. - m = conditionalLibData.match(lib) - if m: - funcname,arg,match = m.groups() - addSuffixes(match) - - func = globals().get(funcname) - if not func: - lit.error('unsupported predicate %r' % funcname) - elif not func(arg): - cfg.unsupported = True - return - # Otherwise, give up. - lit.error('unable to understand %r:\n%s' % (libPath, lib)) - -config.on_clone = on_clone diff --git a/utils/lit/lit/ExampleTests/LLVM.InTree/test/lit.site.cfg b/utils/lit/lit/ExampleTests/LLVM.InTree/test/lit.site.cfg index 3bfee547b7..d45f3ac762 100644 --- a/utils/lit/lit/ExampleTests/LLVM.InTree/test/lit.site.cfg +++ b/utils/lit/lit/ExampleTests/LLVM.InTree/test/lit.site.cfg @@ -1,8 +1,5 @@ # -*- Python -*- -## Autogenerated by Makefile ## -# Do not edit! - # Preserve some key paths for use by main LLVM test suite config. config.llvm_obj_root = os.path.dirname(os.path.dirname(__file__)) diff --git a/utils/lit/lit/ExampleTests/LLVM.InTree/test/site.exp b/utils/lit/lit/ExampleTests/LLVM.InTree/test/site.exp deleted file mode 100644 index 2b60cb9f20..0000000000 --- a/utils/lit/lit/ExampleTests/LLVM.InTree/test/site.exp +++ /dev/null @@ -1,10 +0,0 @@ -## these variables are automatically generated by make ## -# Do not edit here. If you wish to override these values -# edit the last section -set target_triplet "x86_64-apple-darwin10" -set TARGETS_TO_BUILD "X86 Sparc PowerPC ARM Mips PIC16 XCore MSP430 Blackfin MSIL CppBackend" -set srcroot "/Volumes/Data/ddunbar/llvm" -set objroot "/Volumes/Data/ddunbar/llvm.obj.64" -set srcdir "/Volumes/Data/ddunbar/llvm/test" -set objdir "/Volumes/Data/ddunbar/llvm.obj.64/test" -## All variables above are generated by configure. Do Not Edit ## diff --git a/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/lit.site.cfg b/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/lit.site.cfg index bdcc35e093..94a02d8f85 100644 --- a/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/lit.site.cfg +++ b/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/lit.site.cfg @@ -1,8 +1,5 @@ # -*- Python -*- -## Autogenerated by Makefile ## -# Do not edit! - # Preserve some key paths for use by main LLVM test suite config. config.llvm_obj_root = os.path.dirname(os.path.dirname(__file__)) diff --git a/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/site.exp b/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/site.exp deleted file mode 100644 index 2b60cb9f20..0000000000 --- a/utils/lit/lit/ExampleTests/LLVM.OutOfTree/obj/test/site.exp +++ /dev/null @@ -1,10 +0,0 @@ -## these variables are automatically generated by make ## -# Do not edit here. If you wish to override these values -# edit the last section -set target_triplet "x86_64-apple-darwin10" -set TARGETS_TO_BUILD "X86 Sparc PowerPC ARM Mips PIC16 XCore MSP430 Blackfin MSIL CppBackend" -set srcroot "/Volumes/Data/ddunbar/llvm" -set objroot "/Volumes/Data/ddunbar/llvm.obj.64" -set srcdir "/Volumes/Data/ddunbar/llvm/test" -set objdir "/Volumes/Data/ddunbar/llvm.obj.64/test" -## All variables above are generated by configure. Do Not Edit ## diff --git a/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/dg.exp b/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/dg.exp deleted file mode 100644 index 2bda07a31c..0000000000 --- a/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/dg.exp +++ /dev/null @@ -1,6 +0,0 @@ -load_lib llvm.exp - -if { [llvm_supports_target X86] } { - RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll}]] -} - diff --git a/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/lit.cfg b/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/lit.cfg index 3fdd63c224..533c44501f 100644 --- a/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/lit.cfg +++ b/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/lit.cfg @@ -8,11 +8,11 @@ import os config.name = 'LLVM' # testFormat: The test format to use to interpret tests. -config.test_format = lit.formats.TclTest() +config.test_format = lit.formats.ShTest() # suffixes: A list of file extensions to treat as test files, this is actually # set by on_clone(). -config.suffixes = [] +config.suffixes = [ '.ll' ] # test_source_root: The root path where tests are located. config.test_source_root = os.path.dirname(__file__) @@ -64,74 +64,3 @@ if config.test_exec_root is None: lit.load_config(config, site_cfg) raise SystemExit -### - -# Load site data from DejaGNU's site.exp. -import re -site_exp = {} -# FIXME: Implement lit.site.cfg. -for line in open(os.path.join(config.llvm_obj_root, 'test', 'site.exp')): - m = re.match('set ([^ ]+) "([^"]*)"', line) - if m: - site_exp[m.group(1)] = m.group(2) - -excludes = [] - -# Provide target_triple for use in XFAIL. -config.target_triple = site_exp['target_triplet'] - -# Provide llvm_supports_target for use in local configs. -targets = set(site_exp["TARGETS_TO_BUILD"].split()) -def llvm_supports_target(name): - return name in targets - -# Provide on_clone hook for reading 'dg.exp'. -import os -simpleLibData = re.compile(r"""load_lib llvm.exp - -RunLLVMTests \[lsort \[glob -nocomplain \$srcdir/\$subdir/\*\.(.*)\]\]""", - re.MULTILINE) -conditionalLibData = re.compile(r"""load_lib llvm.exp - -if.*\[ ?(llvm[^ ]*) ([^ ]*) ?\].*{ - *RunLLVMTests \[lsort \[glob -nocomplain \$srcdir/\$subdir/\*\.(.*)\]\] -\}""", re.MULTILINE) -def on_clone(parent, cfg, for_path): - def addSuffixes(match): - if match[0] == '{' and match[-1] == '}': - cfg.suffixes = ['.' + s for s in match[1:-1].split(',')] - else: - cfg.suffixes = ['.' + match] - - libPath = os.path.join(os.path.dirname(for_path), - 'dg.exp') - if not os.path.exists(libPath): - cfg.unsupported = True - return - - # Reset unsupported, in case we inherited it. - cfg.unsupported = False - lib = open(libPath).read().strip() - - # Check for a simple library. - m = simpleLibData.match(lib) - if m: - addSuffixes(m.group(1)) - return - - # Check for a conditional test set. - m = conditionalLibData.match(lib) - if m: - funcname,arg,match = m.groups() - addSuffixes(match) - - func = globals().get(funcname) - if not func: - lit.error('unsupported predicate %r' % funcname) - elif not func(arg): - cfg.unsupported = True - return - # Otherwise, give up. - lit.error('unable to understand %r:\n%s' % (libPath, lib)) - -config.on_clone = on_clone diff --git a/utils/lit/lit/ExampleTests/TclTest/lit.local.cfg b/utils/lit/lit/ExampleTests/TclTest/lit.local.cfg deleted file mode 100644 index 6a37129acd..0000000000 --- a/utils/lit/lit/ExampleTests/TclTest/lit.local.cfg +++ /dev/null @@ -1,5 +0,0 @@ -# -*- Python -*- - -config.test_format = lit.formats.TclTest() - -config.suffixes = ['.ll'] diff --git a/utils/lit/lit/ExampleTests/TclTest/stderr-pipe.ll b/utils/lit/lit/ExampleTests/TclTest/stderr-pipe.ll deleted file mode 100644 index 6c55fe8a0b..0000000000 --- a/utils/lit/lit/ExampleTests/TclTest/stderr-pipe.ll +++ /dev/null @@ -1 +0,0 @@ -; RUN: gcc -### > /dev/null |& grep {gcc version} diff --git a/utils/lit/lit/ExampleTests/TclTest/tcl-redir-1.ll b/utils/lit/lit/ExampleTests/TclTest/tcl-redir-1.ll deleted file mode 100644 index 61240ba459..0000000000 --- a/utils/lit/lit/ExampleTests/TclTest/tcl-redir-1.ll +++ /dev/null @@ -1,7 +0,0 @@ -; RUN: echo 'hi' > %t.1 | echo 'hello' > %t.2 -; RUN: not grep 'hi' %t.1 -; RUN: grep 'hello' %t.2 - - - - diff --git a/utils/lit/lit/ExampleTests/lit.cfg b/utils/lit/lit/ExampleTests/lit.cfg index 2629918d9f..164daba903 100644 --- a/utils/lit/lit/ExampleTests/lit.cfg +++ b/utils/lit/lit/ExampleTests/lit.cfg @@ -19,8 +19,8 @@ config.test_source_root = None # root). config.test_exec_root = None -# target_triple: Used by ShTest and TclTest formats for XFAIL checks. +# target_triple: Used by ShTest format for XFAIL checks. config.target_triple = 'foo' -# available_features: Used by ShTest and TclTest formats for REQUIRES checks. +# available_features: Used by ShTest format for REQUIRES checks. config.available_features.add('some-feature-name') diff --git a/utils/lit/lit/LitConfig.py b/utils/lit/lit/LitConfig.py index 0a359a3db8..9bcf20b2f1 100644 --- a/utils/lit/lit/LitConfig.py +++ b/utils/lit/lit/LitConfig.py @@ -12,16 +12,15 @@ class LitConfig: import Test # Provide access to built-in formats. - import LitFormats as formats + import TestFormats as formats # Provide access to built-in utility functions. import Util as util def __init__(self, progname, path, quiet, useValgrind, valgrindLeakCheck, valgrindArgs, - useTclAsSh, noExecute, ignoreStdErr, debug, isWindows, - params): + params, config_prefix = None): # The name of the test runner. self.progname = progname # The items to add to the PATH environment variable. @@ -30,7 +29,6 @@ class LitConfig: self.useValgrind = bool(useValgrind) self.valgrindLeakCheck = bool(valgrindLeakCheck) self.valgrindUserArgs = list(valgrindArgs) - self.useTclAsSh = bool(useTclAsSh) self.noExecute = noExecute self.ignoreStdErr = ignoreStdErr self.debug = debug @@ -38,6 +36,12 @@ class LitConfig: self.params = dict(params) self.bashPath = None + # Configuration files to look for when discovering test suites. + self.config_prefix = config_prefix or 'lit' + self.config_name = '%s.cfg' % (self.config_prefix,) + self.site_config_name = '%s.site.cfg' % (self.config_prefix,) + self.local_config_name = '%s.local.cfg' % (self.config_prefix,) + self.numErrors = 0 self.numWarnings = 0 @@ -80,7 +84,7 @@ class LitConfig: break if self.bashPath is None: - self.warning("Unable to find 'bash', running Tcl tests internally.") + self.warning("Unable to find 'bash'.") self.bashPath = '' return self.bashPath diff --git a/utils/lit/lit/LitFormats.py b/utils/lit/lit/LitFormats.py deleted file mode 100644 index 931d107109..0000000000 --- a/utils/lit/lit/LitFormats.py +++ /dev/null @@ -1,3 +0,0 @@ -from TestFormats import FileBasedTest -from TestFormats import GoogleTest, ShTest, TclTest -from TestFormats import SyntaxCheckTest, OneCommandPerFileTest diff --git a/utils/lit/lit/ShUtil.py b/utils/lit/lit/ShUtil.py index dda622a48a..50f7910319 100644 --- a/utils/lit/lit/ShUtil.py +++ b/utils/lit/lit/ShUtil.py @@ -35,7 +35,7 @@ class ShLexer: if ('|' in chunk or '&' in chunk or '<' in chunk or '>' in chunk or "'" in chunk or '"' in chunk or - '\\' in chunk): + ';' in chunk or '\\' in chunk): return None self.pos = self.pos - 1 + len(chunk) @@ -48,7 +48,7 @@ class ShLexer: str = c while self.pos != self.end: c = self.look() - if c.isspace() or c in "|&": + if c.isspace() or c in "|&;": break elif c in '><': # This is an annoying case; we treat '2>' as a single token so @@ -129,7 +129,7 @@ class ShLexer: lex_one_token - Lex a single 'sh' token. """ c = self.eat() - if c in ';!': + if c == ';': return (c,) if c == '|': if self.maybe_eat('|'): @@ -219,9 +219,6 @@ class ShParser: def parse_pipeline(self): negate = False - if self.look() == ('!',): - self.lex() - negate = True commands = [self.parse_command()] while self.look() == ('|',): @@ -253,9 +250,9 @@ class TestShLexer(unittest.TestCase): return list(ShLexer(str, *args, **kwargs).lex()) def test_basic(self): - self.assertEqual(self.lex('a|b>c&d<e'), + self.assertEqual(self.lex('a|b>c&d<e;f'), ['a', ('|',), 'b', ('>',), 'c', ('&',), 'd', - ('<',), 'e']) + ('<',), 'e', (';',), 'f']) def test_redirection_tokens(self): self.assertEqual(self.lex('a2>c'), @@ -317,10 +314,6 @@ class TestShParse(unittest.TestCase): Command(['c'], [])], False)) - self.assertEqual(self.parse('! a'), - Pipeline([Command(['a'], [])], - True)) - def test_list(self): self.assertEqual(self.parse('a ; b'), Seq(Pipeline([Command(['a'], [])], False), @@ -349,5 +342,10 @@ class TestShParse(unittest.TestCase): '||', Pipeline([Command(['c'], [])], False))) + self.assertEqual(self.parse('a; b'), + Seq(Pipeline([Command(['a'], [])], False), + ';', + Pipeline([Command(['b'], [])], False))) + if __name__ == '__main__': unittest.main() diff --git a/utils/lit/lit/TclUtil.py b/utils/lit/lit/TclUtil.py deleted file mode 100644 index 4a3f34508d..0000000000 --- a/utils/lit/lit/TclUtil.py +++ /dev/null @@ -1,322 +0,0 @@ -import itertools - -from ShCommands import Command, Pipeline - -def tcl_preprocess(data): - # Tcl has a preprocessing step to replace escaped newlines. - i = data.find('\\\n') - if i == -1: - return data - - # Replace '\\\n' and subsequent whitespace by a single space. - n = len(data) - str = data[:i] - i += 2 - while i < n and data[i] in ' \t': - i += 1 - return str + ' ' + data[i:] - -class TclLexer: - """TclLexer - Lex a string into "words", following the Tcl syntax.""" - - def __init__(self, data): - self.data = tcl_preprocess(data) - self.pos = 0 - self.end = len(self.data) - - def at_end(self): - return self.pos == self.end - - def eat(self): - c = self.data[self.pos] - self.pos += 1 - return c - - def look(self): - return self.data[self.pos] - - def maybe_eat(self, c): - """ - maybe_eat(c) - Consume the character c if it is the next character, - returning True if a character was consumed. """ - if self.data[self.pos] == c: - self.pos += 1 - return True - return False - - def escape(self, c): - if c == 'a': - return '\x07' - elif c == 'b': - return '\x08' - elif c == 'f': - return '\x0c' - elif c == 'n': - return '\n' - elif c == 'r': - return '\r' - elif c == 't': - return '\t' - elif c == 'v': - return '\x0b' - elif c in 'uxo': - raise ValueError,'Invalid quoted character %r' % c - else: - return c - - def lex_braced(self): - # Lex until whitespace or end of string, the opening brace has already - # been consumed. - - str = '' - while 1: - if self.at_end(): - raise ValueError,"Unterminated '{' quoted word" - - c = self.eat() - if c == '}': - break - elif c == '{': - str += '{' + self.lex_braced() + '}' - elif c == '\\' and self.look() in '{}': - str += self.eat() - else: - str += c - - return str - - def lex_quoted(self): - str = '' - - while 1: - if self.at_end(): - raise ValueError,"Unterminated '\"' quoted word" - - c = self.eat() - if c == '"': - break - elif c == '\\': - if self.at_end(): - raise ValueError,'Missing quoted character' - - str += self.escape(self.eat()) - else: - str += c - - return str - - def lex_unquoted(self, process_all=False): - # Lex until whitespace or end of string. - str = '' - while not self.at_end(): - if not process_all: - if self.look().isspace() or self.look() == ';': - break - - c = self.eat() - if c == '\\': - if self.at_end(): - raise ValueError,'Missing quoted character' - - str += self.escape(self.eat()) - elif c == '[': - raise NotImplementedError, ('Command substitution is ' - 'not supported') - elif c == '$' and not self.at_end() and (self.look().isalpha() or - self.look() == '{'): - raise NotImplementedError, ('Variable substitution is ' - 'not supported') - else: - str += c - - return str - - def lex_one_token(self): - if self.maybe_eat('"'): - return self.lex_quoted() - elif self.maybe_eat('{'): - # Check for argument substitution. - if not self.maybe_eat('*'): - return self.lex_braced() - - if not self.maybe_eat('}'): - return '*' + self.lex_braced() - - if self.at_end() or self.look().isspace(): - return '*' - - raise NotImplementedError, "Argument substitution is unsupported" - else: - return self.lex_unquoted() - - def lex(self): - while not self.at_end(): - c = self.look() - if c in ' \t': - self.eat() - elif c in ';\n': - self.eat() - yield (';',) - else: - yield self.lex_one_token() - -class TclExecCommand: - kRedirectPrefixes1 = ('<', '>') - kRedirectPrefixes2 = ('<@', '<<', '2>', '>&', '>>', '>@') - kRedirectPrefixes3 = ('2>@', '2>>', '>>&', '>&@') - kRedirectPrefixes4 = ('2>@1',) - - def __init__(self, args): - self.args = iter(args) - - def lex(self): - try: - return self.args.next() - except StopIteration: - return None - - def look(self): - next = self.lex() - if next is not None: - self.args = itertools.chain([next], self.args) - return next - - def parse_redirect(self, tok, length): - if len(tok) == length: - arg = self.lex() - if arg is None: - raise ValueError,'Missing argument to %r redirection' % tok - else: - tok,arg = tok[:length],tok[length:] - - if tok[0] == '2': - op = (tok[1:],2) - else: - op = (tok,) - return (op, arg) - - def parse_pipeline(self): - if self.look() is None: - raise ValueError,"Expected at least one argument to exec" - - commands = [Command([],[])] - while 1: - arg = self.lex() - if arg is None: - break - elif arg == '|': - commands.append(Command([],[])) - elif arg == '|&': - # Write this as a redirect of stderr; it must come first because - # stdout may have already been redirected. - commands[-1].redirects.insert(0, (('>&',2),'1')) - commands.append(Command([],[])) - elif arg[:4] in TclExecCommand.kRedirectPrefixes4: - commands[-1].redirects.append(self.parse_redirect(arg, 4)) - elif arg[:3] in TclExecCommand.kRedirectPrefixes3: - commands[-1].redirects.append(self.parse_redirect(arg, 3)) - elif arg[:2] in TclExecCommand.kRedirectPrefixes2: - commands[-1].redirects.append(self.parse_redirect(arg, 2)) - elif arg[:1] in TclExecCommand.kRedirectPrefixes1: - commands[-1].redirects.append(self.parse_redirect(arg, 1)) - else: - commands[-1].args.append(arg) - - return Pipeline(commands, False, pipe_err=True) - - def parse(self): - ignoreStderr = False - keepNewline = False - - # Parse arguments. - while 1: - next = self.look() - if not isinstance(next, str) or next[0] != '-': - break - - if next == '--': - self.lex() - break - elif next == '-ignorestderr': - ignoreStderr = True - elif next == '-keepnewline': - keepNewline = True - else: - raise ValueError,"Invalid exec argument %r" % next - - return (ignoreStderr, keepNewline, self.parse_pipeline()) - -### - -import unittest - -class TestTclLexer(unittest.TestCase): - def lex(self, str, *args, **kwargs): - return list(TclLexer(str, *args, **kwargs).lex()) - - def test_preprocess(self): - self.assertEqual(tcl_preprocess('a b'), 'a b') - self.assertEqual(tcl_preprocess('a\\\nb c'), 'a b c') - - def test_unquoted(self): - self.assertEqual(self.lex('a b c'), - ['a', 'b', 'c']) - self.assertEqual(self.lex(r'a\nb\tc\ '), - ['a\nb\tc ']) - self.assertEqual(self.lex(r'a \\\$b c $\\'), - ['a', r'\$b', 'c', '$\\']) - - def test_braced(self): - self.assertEqual(self.lex('a {b c} {}'), - ['a', 'b c', '']) - self.assertEqual(self.lex(r'a {b {c\n}}'), - ['a', 'b {c\\n}']) - self.assertEqual(self.lex(r'a {b\{}'), - ['a', 'b{']) - self.assertEqual(self.lex(r'{*}'), ['*']) - self.assertEqual(self.lex(r'{*} a'), ['*', 'a']) - self.assertEqual(self.lex(r'{*} a'), ['*', 'a']) - self.assertEqual(self.lex('{a\\\n b}'), - ['a b']) - - def test_quoted(self): - self.assertEqual(self.lex('a "b c"'), - ['a', 'b c']) - - def test_terminators(self): - self.assertEqual(self.lex('a\nb'), - ['a', (';',), 'b']) - self.assertEqual(self.lex('a;b'), - ['a', (';',), 'b']) - self.assertEqual(self.lex('a ; b'), - ['a', (';',), 'b']) - -class TestTclExecCommand(unittest.TestCase): - def parse(self, str): - return TclExecCommand(list(TclLexer(str).lex())).parse() - - def test_basic(self): - self.assertEqual(self.parse('echo hello'), - (False, False, - Pipeline([Command(['echo', 'hello'], [])], - False, True))) - self.assertEqual(self.parse('echo hello | grep hello'), - (False, False, - Pipeline([Command(['echo', 'hello'], []), - Command(['grep', 'hello'], [])], - False, True))) - - def test_redirect(self): - self.assertEqual(self.parse('echo hello > a >b >>c 2> d |& e'), - (False, False, - Pipeline([Command(['echo', 'hello'], - [(('>&',2),'1'), - (('>',),'a'), - (('>',),'b'), - (('>>',),'c'), - (('>',2),'d')]), - Command(['e'], [])], - False, True))) - -if __name__ == '__main__': - unittest.main() diff --git a/utils/lit/lit/Test.py b/utils/lit/lit/Test.py index db2e032465..9471e3a98b 100644 --- a/utils/lit/lit/Test.py +++ b/utils/lit/lit/Test.py @@ -7,6 +7,10 @@ class TestResult: self.name = name self.isFailure = isFailure + def __repr__(self): + return '%s%r' % (self.__class__.__name__, + (self.name, self.isFailure)) + PASS = TestResult('PASS', False) XFAIL = TestResult('XFAIL', False) FAIL = TestResult('FAIL', True) diff --git a/utils/lit/lit/TestFormats.py b/utils/lit/lit/TestFormats.py index d1c0558b5f..a272976ca0 100644 --- a/utils/lit/lit/TestFormats.py +++ b/utils/lit/lit/TestFormats.py @@ -54,28 +54,36 @@ class GoogleTest(object): else: yield ''.join(nested_tests) + ln + def getTestsInExecutable(self, testSuite, path_in_suite, execpath, + litConfig, localConfig): + if not execpath.endswith(self.test_suffix): + return + (dirname, basename) = os.path.split(execpath) + # Discover the tests in this executable. + for testname in self.getGTestTests(execpath, litConfig, localConfig): + testPath = path_in_suite + (dirname, basename, testname) + yield Test.Test(testSuite, testPath, localConfig) + def getTestsInDirectory(self, testSuite, path_in_suite, litConfig, localConfig): source_path = testSuite.getSourcePath(path_in_suite) for filename in os.listdir(source_path): - # Check for the one subdirectory (build directory) tests will be in. - if not '.' in self.test_sub_dir: + filepath = os.path.join(source_path, filename) + if os.path.isdir(filepath): + # Iterate over executables in a directory. if not os.path.normcase(filename) in self.test_sub_dir: continue - - filepath = os.path.join(source_path, filename) - if not os.path.isdir(filepath): - continue - - for subfilename in os.listdir(filepath): - if subfilename.endswith(self.test_suffix): + for subfilename in os.listdir(filepath): execpath = os.path.join(filepath, subfilename) - - # Discover the tests in this executable. - for name in self.getGTestTests(execpath, litConfig, - localConfig): - testPath = path_in_suite + (filename, subfilename, name) - yield Test.Test(testSuite, testPath, localConfig) + for test in self.getTestsInExecutable( + testSuite, path_in_suite, execpath, + litConfig, localConfig): + yield test + elif ('.' in self.test_sub_dir): + for test in self.getTestsInExecutable( + testSuite, path_in_suite, filepath, + litConfig, localConfig): + yield test def execute(self, test, litConfig): testPath,testName = os.path.split(test.getSourcePath()) @@ -124,14 +132,6 @@ class ShTest(FileBasedTest): return TestRunner.executeShTest(test, litConfig, self.execute_external) -class TclTest(FileBasedTest): - def __init__(self, ignoreStdErr=False): - self.ignoreStdErr = ignoreStdErr - - def execute(self, test, litConfig): - litConfig.ignoreStdErr = self.ignoreStdErr - return TestRunner.executeTclTest(test, litConfig) - ### import re @@ -221,12 +221,3 @@ class OneCommandPerFileTest: report += """Output:\n--\n%s--""" % diags return Test.FAIL, report - -class SyntaxCheckTest(OneCommandPerFileTest): - def __init__(self, compiler, dir, extra_cxx_args=[], *args, **kwargs): - cmd = [compiler, '-x', 'c++', '-fsyntax-only'] + extra_cxx_args - OneCommandPerFileTest.__init__(self, cmd, dir, - useTempInput=1, *args, **kwargs) - - def createTempInput(self, tmp, test): - print >>tmp, '#include "%s"' % test.source_path diff --git a/utils/lit/lit/TestRunner.py b/utils/lit/lit/TestRunner.py index 652e8b499c..07fb43f840 100644 --- a/utils/lit/lit/TestRunner.py +++ b/utils/lit/lit/TestRunner.py @@ -49,13 +49,14 @@ def executeShCmd(cmd, cfg, cwd, results): return executeShCmd(cmd.rhs, cfg, cwd, results) if cmd.op == '&': - raise NotImplementedError,"unsupported test command: '&'" + raise InternalShellError(cmd,"unsupported shell operator: '&'") if cmd.op == '||': res = executeShCmd(cmd.lhs, cfg, cwd, results) if res != 0: res = executeShCmd(cmd.rhs, cfg, cwd, results) return res + if cmd.op == '&&': res = executeShCmd(cmd.lhs, cfg, cwd, results) if res is None: @@ -77,7 +78,7 @@ def executeShCmd(cmd, cfg, cwd, results): # output. This is null until we have seen some output using # stderr. for i,j in enumerate(cmd.commands): - # Apply the redirections, we use (N,) as a sentinal to indicate stdin, + # Apply the redirections, we use (N,) as a sentinel to indicate stdin, # stdout, stderr for N equal to 0, 1, or 2 respectively. Redirects to or # from a file are represented with a list [file, mode, file-object] # where file-object is initially None. @@ -98,7 +99,7 @@ def executeShCmd(cmd, cfg, cwd, results): elif r[0] == ('<',): redirects[0] = [r[1], 'r', None] else: - raise NotImplementedError,"Unsupported redirect: %r" % (r,) + raise InternalShellError(j,"Unsupported redirect: %r" % (r,)) # Map from the final redirections to something subprocess can handle. final_redirects = [] @@ -107,14 +108,14 @@ def executeShCmd(cmd, cfg, cwd, results): result = input elif r == (1,): if index == 0: - raise NotImplementedError,"Unsupported redirect for stdin" + raise InternalShellError(j,"Unsupported redirect for stdin") elif index == 1: result = subprocess.PIPE else: result = subprocess.STDOUT elif r == (2,): if index != 2: - raise NotImplementedError,"Unsupported redirect on stdout" + raise InternalShellError(j,"Unsupported redirect on stdout") result = subprocess.PIPE else: if r[2] is None: @@ -256,9 +257,8 @@ def executeScriptInternal(test, litConfig, tmpBase, commands, cwd): try: exitCode = executeShCmd(cmd, test.config, cwd, results) except InternalShellError,e: - out = '' - err = e.message - exitCode = 255 + exitCode = 127 + results.append((e.command, '', e.message, exitCode)) out = err = '' for i,(cmd, cmd_out,cmd_err,res) in enumerate(results): @@ -269,82 +269,6 @@ def executeScriptInternal(test, litConfig, tmpBase, commands, cwd): return out, err, exitCode -def executeTclScriptInternal(test, litConfig, tmpBase, commands, cwd): - import TclUtil - cmds = [] - for ln in commands: - # Given the unfortunate way LLVM's test are written, the line gets - # backslash substitution done twice. - ln = TclUtil.TclLexer(ln).lex_unquoted(process_all = True) - - try: - tokens = list(TclUtil.TclLexer(ln).lex()) - except: - return (Test.FAIL, "Tcl lexer error on: %r" % ln) - - # Validate there are no control tokens. - for t in tokens: - if not isinstance(t, str): - return (Test.FAIL, - "Invalid test line: %r containing %r" % (ln, t)) - - try: - cmds.append(TclUtil.TclExecCommand(tokens).parse_pipeline()) - except: - return (Test.FAIL, "Tcl 'exec' parse error on: %r" % ln) - - if litConfig.useValgrind: - for pipeline in cmds: - if pipeline.commands: - # Only valgrind the first command in each pipeline, to avoid - # valgrinding things like grep, not, and FileCheck. - cmd = pipeline.commands[0] - cmd.args = litConfig.valgrindArgs + cmd.args - - cmd = cmds[0] - for c in cmds[1:]: - cmd = ShUtil.Seq(cmd, '&&', c) - - # FIXME: This is lame, we shouldn't need bash. See PR5240. - bashPath = litConfig.getBashPath() - if litConfig.useTclAsSh and bashPath: - script = tmpBase + '.script' - - # Write script file - f = open(script,'w') - print >>f, 'set -o pipefail' - cmd.toShell(f, pipefail = True) - f.close() - - if 0: - print >>sys.stdout, cmd - print >>sys.stdout, open(script).read() - print >>sys.stdout - return '', '', 0 - - command = [litConfig.getBashPath(), script] - out,err,exitCode = executeCommand(command, cwd=cwd, - env=test.config.environment) - - return out,err,exitCode - else: - results = [] - try: - exitCode = executeShCmd(cmd, test.config, cwd, results) - except InternalShellError,e: - results.append((e.command, '', e.message + '\n', 255)) - exitCode = 255 - - out = err = '' - - for i,(cmd, cmd_out, cmd_err, res) in enumerate(results): - out += 'Command %d: %s\n' % (i, ' '.join('"%s"' % s for s in cmd.args)) - out += 'Command %d Result: %r\n' % (i, res) - out += 'Command %d Output:\n%s\n\n' % (i, cmd_out) - out += 'Command %d Stderr:\n%s\n\n' % (i, cmd_err) - - return out, err, exitCode - def executeScript(test, litConfig, tmpBase, commands, cwd): bashPath = litConfig.getBashPath(); isWin32CMDEXE = (litConfig.isWindows and not bashPath) @@ -429,8 +353,6 @@ def parseIntegratedTestScript(test, normalize_slashes=False, ('%{pathsep}', os.pathsep), ('%t', tmpBase + '.tmp'), ('%T', tmpDir), - # FIXME: Remove this once we kill DejaGNU. - ('%abs_tmp', tmpBase + '.tmp'), ('#_MARKER_#', '%')]) # Collect the test lines from the script. @@ -506,17 +428,14 @@ def parseIntegratedTestScript(test, normalize_slashes=False, isXFail = isExpectedFail(test, xfails) return script,isXFail,tmpBase,execdir -def formatTestOutput(status, out, err, exitCode, failDueToStderr, script): +def formatTestOutput(status, out, err, exitCode, script): output = StringIO.StringIO() print >>output, "Script:" print >>output, "--" print >>output, '\n'.join(script) print >>output, "--" print >>output, "Exit Code: %r" % exitCode, - if failDueToStderr: - print >>output, "(but there was output on stderr)" - else: - print >>output + print >>output if out: print >>output, "Command Output (stdout):" print >>output, "--" @@ -529,53 +448,6 @@ def formatTestOutput(status, out, err, exitCode, failDueToStderr, script): print >>output, "--" return (status, output.getvalue()) -def executeTclTest(test, litConfig): - if test.config.unsupported: - return (Test.UNSUPPORTED, 'Test is unsupported') - - # Parse the test script, normalizing slashes in substitutions on Windows - # (since otherwise Tcl style lexing will treat them as escapes). - res = parseIntegratedTestScript(test, normalize_slashes=kIsWindows) - if len(res) == 2: - return res - - script, isXFail, tmpBase, execdir = res - - if litConfig.noExecute: - return (Test.PASS, '') - - # Create the output directory if it does not already exist. - Util.mkdir_p(os.path.dirname(tmpBase)) - - res = executeTclScriptInternal(test, litConfig, tmpBase, script, execdir) - if len(res) == 2: - return res - - # Test for failure. In addition to the exit code, Tcl commands are - # considered to fail if there is any standard error output. - out,err,exitCode = res - if isXFail: - ok = exitCode != 0 or err and not litConfig.ignoreStdErr - if ok: - status = Test.XFAIL - else: - status = Test.XPASS - else: - ok = exitCode == 0 and (not err or litConfig.ignoreStdErr) - if ok: - status = Test.PASS - else: - status = Test.FAIL - - if ok: - return (status,'') - - # Set a flag for formatTestOutput so it can explain why the test was - # considered to have failed, despite having an exit code of 0. - failDueToStderr = exitCode == 0 and err and not litConfig.ignoreStdErr - - return formatTestOutput(status, out, err, exitCode, failDueToStderr, script) - def executeShTest(test, litConfig, useExternalSh, extra_substitutions=[]): if test.config.unsupported: @@ -617,7 +489,4 @@ def executeShTest(test, litConfig, useExternalSh, if ok: return (status,'') - # Sh tests are not considered to fail just from stderr output. - failDueToStderr = False - - return formatTestOutput(status, out, err, exitCode, failDueToStderr, script) + return formatTestOutput(status, out, err, exitCode, script) diff --git a/utils/lit/lit/discovery.py b/utils/lit/lit/discovery.py new file mode 100644 index 0000000000..c869a671ef --- /dev/null +++ b/utils/lit/lit/discovery.py @@ -0,0 +1,234 @@ +""" +Test discovery functions. +""" + +import os +import sys + +from lit.TestingConfig import TestingConfig +from lit import LitConfig, Test + +def dirContainsTestSuite(path, lit_config): + cfgpath = os.path.join(path, lit_config.site_config_name) + if os.path.exists(cfgpath): + return cfgpath + cfgpath = os.path.join(path, lit_config.config_name) + if os.path.exists(cfgpath): + return cfgpath + +def getTestSuite(item, litConfig, cache): + """getTestSuite(item, litConfig, cache) -> (suite, relative_path) + + Find the test suite containing @arg item. + + @retval (None, ...) - Indicates no test suite contains @arg item. + @retval (suite, relative_path) - The suite that @arg item is in, and its + relative path inside that suite. + """ + def search1(path): + # Check for a site config or a lit config. + cfgpath = dirContainsTestSuite(path, litConfig) + + # If we didn't find a config file, keep looking. + if not cfgpath: + parent,base = os.path.split(path) + if parent == path: + return (None, ()) + + ts, relative = search(parent) + return (ts, relative + (base,)) + + # We found a config file, load it. + if litConfig.debug: + litConfig.note('loading suite config %r' % cfgpath) + + cfg = TestingConfig.frompath(cfgpath, None, litConfig, mustExist = True) + source_root = os.path.realpath(cfg.test_source_root or path) + exec_root = os.path.realpath(cfg.test_exec_root or path) + return Test.TestSuite(cfg.name, source_root, exec_root, cfg), () + + def search(path): + # Check for an already instantiated test suite. + res = cache.get(path) + if res is None: + cache[path] = res = search1(path) + return res + + # Canonicalize the path. + item = os.path.realpath(item) + + # Skip files and virtual components. + components = [] + while not os.path.isdir(item): + parent,base = os.path.split(item) + if parent == item: + return (None, ()) + components.append(base) + item = parent + components.reverse() + + ts, relative = search(item) + return ts, tuple(relative + tuple(components)) + +def getLocalConfig(ts, path_in_suite, litConfig, cache): + def search1(path_in_suite): + # Get the parent config. + if not path_in_suite: + parent = ts.config + else: + parent = search(path_in_suite[:-1]) + + # Load the local configuration. + source_path = ts.getSourcePath(path_in_suite) + cfgpath = os.path.join(source_path, litConfig.local_config_name) + if litConfig.debug: + litConfig.note('loading local config %r' % cfgpath) + return TestingConfig.frompath(cfgpath, parent, litConfig, + mustExist = False, + config = parent.clone(cfgpath)) + + def search(path_in_suite): + key = (ts, path_in_suite) + res = cache.get(key) + if res is None: + cache[key] = res = search1(path_in_suite) + return res + + return search(path_in_suite) + +def getTests(path, litConfig, testSuiteCache, localConfigCache): + # Find the test suite for this input and its relative path. + ts,path_in_suite = getTestSuite(path, litConfig, testSuiteCache) + if ts is None: + litConfig.warning('unable to find test suite for %r' % path) + return (),() + + if litConfig.debug: + litConfig.note('resolved input %r to %r::%r' % (path, ts.name, + path_in_suite)) + + return ts, getTestsInSuite(ts, path_in_suite, litConfig, + testSuiteCache, localConfigCache) + +def getTestsInSuite(ts, path_in_suite, litConfig, + testSuiteCache, localConfigCache): + # Check that the source path exists (errors here are reported by the + # caller). + source_path = ts.getSourcePath(path_in_suite) + if not os.path.exists(source_path): + return + + # Check if the user named a test directly. + if not os.path.isdir(source_path): + lc = getLocalConfig(ts, path_in_suite[:-1], litConfig, localConfigCache) + yield Test.Test(ts, path_in_suite, lc) + return + + # Otherwise we have a directory to search for tests, start by getting the + # local configuration. + lc = getLocalConfig(ts, path_in_suite, litConfig, localConfigCache) + + # Search for tests. + if lc.test_format is not None: + for res in lc.test_format.getTestsInDirectory(ts, path_in_suite, + litConfig, lc): + yield res + + # Search subdirectories. + for filename in os.listdir(source_path): + # FIXME: This doesn't belong here? + if filename in ('Output', '.svn') or filename in lc.excludes: + continue + + # Ignore non-directories. + file_sourcepath = os.path.join(source_path, filename) + if not os.path.isdir(file_sourcepath): + continue + + # Check for nested test suites, first in the execpath in case there is a + # site configuration and then in the source path. + file_execpath = ts.getExecPath(path_in_suite + (filename,)) + if dirContainsTestSuite(file_execpath, litConfig): + sub_ts, subiter = getTests(file_execpath, litConfig, + testSuiteCache, localConfigCache) + elif dirContainsTestSuite(file_sourcepath, litConfig): + sub_ts, subiter = getTests(file_sourcepath, litConfig, + testSuiteCache, localConfigCache) + else: + # Otherwise, continue loading from inside this test suite. + subiter = getTestsInSuite(ts, path_in_suite + (filename,), + litConfig, testSuiteCache, + localConfigCache) + sub_ts = None + + N = 0 + for res in subiter: + N += 1 + yield res + if sub_ts and not N: + litConfig.warning('test suite %r contained no tests' % sub_ts.name) + +def find_tests_for_inputs(lit_config, inputs): + """ + find_tests_for_inputs(lit_config, inputs) -> [Test] + + Given a configuration object and a list of input specifiers, find all the + tests to execute. + """ + + # 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 = [] + test_suite_cache = {} + local_config_cache = {} + for input in actual_inputs: + prev = len(tests) + tests.extend(getTests(input, lit_config, + test_suite_cache, local_config_cache)[1]) + if prev == len(tests): + lit_config.warning('input %r contained no tests' % input) + + # If there were any errors during test discovery, exit now. + if lit_config.numErrors: + print >>sys.stderr, '%d errors, exiting.' % lit_config.numErrors + sys.exit(2) + + return tests + +def load_test_suite(inputs): + import platform + import unittest + from lit.LitTestCase import LitTestCase + + # Create the global config object. + litConfig = LitConfig.LitConfig(progname = 'lit', + path = [], + quiet = False, + useValgrind = False, + valgrindLeakCheck = False, + valgrindArgs = [], + noExecute = False, + ignoreStdErr = False, + debug = False, + isWindows = (platform.system()=='Windows'), + params = {}) + + tests = find_tests_for_inputs(litConfig, inputs) + + # Return a unittest test suite which just runs the tests in order. + return unittest.TestSuite([LitTestCase(test, litConfig) for test in tests]) + diff --git a/utils/lit/lit/main.py b/utils/lit/lit/main.py index 25bbcbd9f2..da961eeedc 100755 --- a/utils/lit/lit/main.py +++ b/utils/lit/lit/main.py @@ -12,18 +12,10 @@ import ProgressBar import TestRunner import Util -from TestingConfig import TestingConfig import LitConfig import Test -# Configuration files to look for when discovering test suites. These can be -# overridden with --config-prefix. -# -# FIXME: Rename to 'config.lit', 'site.lit', and 'local.lit' ? -gConfigName = 'lit.cfg' -gSiteConfigName = 'lit.site.cfg' - -kLocalConfigName = 'lit.local.cfg' +import lit.discovery class TestingProgressDisplay: def __init__(self, opts, numTests, progressBar=None): @@ -137,166 +129,6 @@ class Tester(threading.Thread): test.setResult(result, output, elapsed) self.display.update(test) -def dirContainsTestSuite(path): - cfgpath = os.path.join(path, gSiteConfigName) - if os.path.exists(cfgpath): - return cfgpath - cfgpath = os.path.join(path, gConfigName) - if os.path.exists(cfgpath): - return cfgpath - -def getTestSuite(item, litConfig, cache): - """getTestSuite(item, litConfig, cache) -> (suite, relative_path) - - Find the test suite containing @arg item. - - @retval (None, ...) - Indicates no test suite contains @arg item. - @retval (suite, relative_path) - The suite that @arg item is in, and its - relative path inside that suite. - """ - def search1(path): - # Check for a site config or a lit config. - cfgpath = dirContainsTestSuite(path) - - # If we didn't find a config file, keep looking. - if not cfgpath: - parent,base = os.path.split(path) - if parent == path: - return (None, ()) - - ts, relative = search(parent) - return (ts, relative + (base,)) - - # We found a config file, load it. - if litConfig.debug: - litConfig.note('loading suite config %r' % cfgpath) - - cfg = TestingConfig.frompath(cfgpath, None, litConfig, mustExist = True) - source_root = os.path.realpath(cfg.test_source_root or path) - exec_root = os.path.realpath(cfg.test_exec_root or path) - return Test.TestSuite(cfg.name, source_root, exec_root, cfg), () - - def search(path): - # Check for an already instantiated test suite. - res = cache.get(path) - if res is None: - cache[path] = res = search1(path) - return res - - # Canonicalize the path. - item = os.path.realpath(item) - - # Skip files and virtual components. - components = [] - while not os.path.isdir(item): - parent,base = os.path.split(item) - if parent == item: - return (None, ()) - components.append(base) - item = parent - components.reverse() - - ts, relative = search(item) - return ts, tuple(relative + tuple(components)) - -def getLocalConfig(ts, path_in_suite, litConfig, cache): - def search1(path_in_suite): - # Get the parent config. - if not path_in_suite: - parent = ts.config - else: - parent = search(path_in_suite[:-1]) - - # Load the local configuration. - source_path = ts.getSourcePath(path_in_suite) - cfgpath = os.path.join(source_path, kLocalConfigName) - if litConfig.debug: - litConfig.note('loading local config %r' % cfgpath) - return TestingConfig.frompath(cfgpath, parent, litConfig, - mustExist = False, - config = parent.clone(cfgpath)) - - def search(path_in_suite): - key = (ts, path_in_suite) - res = cache.get(key) - if res is None: - cache[key] = res = search1(path_in_suite) - return res - - return search(path_in_suite) - -def getTests(path, litConfig, testSuiteCache, localConfigCache): - # Find the test suite for this input and its relative path. - ts,path_in_suite = getTestSuite(path, litConfig, testSuiteCache) - if ts is None: - litConfig.warning('unable to find test suite for %r' % path) - return (),() - - if litConfig.debug: - litConfig.note('resolved input %r to %r::%r' % (path, ts.name, - path_in_suite)) - - return ts, getTestsInSuite(ts, path_in_suite, litConfig, - testSuiteCache, localConfigCache) - -def getTestsInSuite(ts, path_in_suite, litConfig, - testSuiteCache, localConfigCache): - # Check that the source path exists (errors here are reported by the - # caller). - source_path = ts.getSourcePath(path_in_suite) - if not os.path.exists(source_path): - return - - # Check if the user named a test directly. - if not os.path.isdir(source_path): - lc = getLocalConfig(ts, path_in_suite[:-1], litConfig, localConfigCache) - yield Test.Test(ts, path_in_suite, lc) - return - - # Otherwise we have a directory to search for tests, start by getting the - # local configuration. - lc = getLocalConfig(ts, path_in_suite, litConfig, localConfigCache) - - # Search for tests. - if lc.test_format is not None: - for res in lc.test_format.getTestsInDirectory(ts, path_in_suite, - litConfig, lc): - yield res - - # Search subdirectories. - for filename in os.listdir(source_path): - # FIXME: This doesn't belong here? - if filename in ('Output', '.svn') or filename in lc.excludes: - continue - - # Ignore non-directories. - file_sourcepath = os.path.join(source_path, filename) - if not os.path.isdir(file_sourcepath): - continue - - # Check for nested test suites, first in the execpath in case there is a - # site configuration and then in the source path. - file_execpath = ts.getExecPath(path_in_suite + (filename,)) - if dirContainsTestSuite(file_execpath): - sub_ts, subiter = getTests(file_execpath, litConfig, - testSuiteCache, localConfigCache) - elif dirContainsTestSuite(file_sourcepath): - sub_ts, subiter = getTests(file_sourcepath, litConfig, - testSuiteCache, localConfigCache) - else: - # Otherwise, continue loading from inside this test suite. - subiter = getTestsInSuite(ts, path_in_suite + (filename,), - litConfig, testSuiteCache, - localConfigCache) - sub_ts = None - - N = 0 - for res in subiter: - N += 1 - yield res - if sub_ts and not N: - litConfig.warning('test suite %r contained no tests' % sub_ts.name) - def runTests(numThreads, litConfig, provider, display): # If only using one testing thread, don't use threads at all; this lets us # profile, among other things. @@ -316,50 +148,8 @@ def runTests(numThreads, litConfig, provider, display): except KeyboardInterrupt: sys.exit(2) -def load_test_suite(inputs): - import unittest - - # Create the global config object. - litConfig = LitConfig.LitConfig(progname = 'lit', - path = [], - quiet = False, - useValgrind = False, - valgrindLeakCheck = False, - valgrindArgs = [], - useTclAsSh = False, - noExecute = False, - ignoreStdErr = False, - debug = False, - isWindows = (platform.system()=='Windows'), - params = {}) - - # Load the tests from the inputs. - tests = [] - testSuiteCache = {} - localConfigCache = {} - for input in inputs: - prev = len(tests) - tests.extend(getTests(input, litConfig, - testSuiteCache, localConfigCache)[1]) - if prev == len(tests): - litConfig.warning('input %r contained no tests' % input) - - # If there were any errors during test discovery, exit now. - if litConfig.numErrors: - print >>sys.stderr, '%d errors, exiting.' % litConfig.numErrors - sys.exit(2) - - # Return a unittest test suite which just runs the tests in order. - def get_test_fn(test): - return unittest.FunctionTestCase( - lambda: test.config.test_format.execute( - test, litConfig), - description = test.getFullName()) - - from LitTestCase import LitTestCase - return unittest.TestSuite([LitTestCase(test, litConfig) for test in tests]) - -def main(builtinParameters = {}): # Bump the GIL check interval, its more important to get any one thread to a +def main(builtinParameters = {}): + # Bump the GIL check interval, its more important to get any one thread to a # blocking operation (hopefully exec) than to try and unblock other threads. # # FIXME: This is a hack. @@ -442,9 +232,6 @@ def main(builtinParameters = {}): # Bump the GIL check interval, its more imp group.add_option("", "--show-suites", dest="showSuites", help="Show discovered test suites", action="store_true", default=False) - group.add_option("", "--no-tcl-as-sh", dest="useTclAsSh", - help="Don't run Tcl scripts using 'sh'", - action="store_false", default=True) group.add_option("", "--repeat", dest="repeatTests", metavar="N", help="Repeat tests N times (for timing)", action="store", default=None, type=int) @@ -455,12 +242,6 @@ def main(builtinParameters = {}): # Bump the GIL check interval, its more imp if not args: parser.error('No inputs specified') - if opts.configPrefix is not None: - global gConfigName, gSiteConfigName, kLocalConfigName - gConfigName = '%s.cfg' % opts.configPrefix - gSiteConfigName = '%s.site.cfg' % opts.configPrefix - kLocalConfigName = '%s.local.cfg' % opts.configPrefix - if opts.numThreads is None: # Python <2.5 has a race condition causing lit to always fail with numThreads>1 # http://bugs.python.org/issue1731717 @@ -489,50 +270,20 @@ def main(builtinParameters = {}): # Bump the GIL check interval, its more imp useValgrind = opts.useValgrind, valgrindLeakCheck = opts.valgrindLeakCheck, valgrindArgs = opts.valgrindArgs, - useTclAsSh = opts.useTclAsSh, noExecute = opts.noExecute, ignoreStdErr = False, debug = opts.debug, isWindows = (platform.system()=='Windows'), - params = userParams) + params = userParams, + config_prefix = opts.configPrefix) - # Expand '@...' form in inputs. - actual_inputs = [] - for input in inputs: - if os.path.exists(input) or not input.startswith('@'): - actual_inputs.append(input) - else: - f = open(input[1:]) - try: - for ln in f: - ln = ln.strip() - if ln: - actual_inputs.append(ln) - finally: - f.close() - - - # Load the tests from the inputs. - tests = [] - testSuiteCache = {} - localConfigCache = {} - for input in actual_inputs: - prev = len(tests) - tests.extend(getTests(input, litConfig, - testSuiteCache, localConfigCache)[1]) - if prev == len(tests): - litConfig.warning('input %r contained no tests' % input) - - # If there were any errors during test discovery, exit now. - if litConfig.numErrors: - print >>sys.stderr, '%d errors, exiting.' % litConfig.numErrors - sys.exit(2) + tests = lit.discovery.find_tests_for_inputs(litConfig, inputs) if opts.showSuites: - suitesAndTests = dict([(ts,[]) - for ts,_ in testSuiteCache.values() - if ts]) + suitesAndTests = {} for t in tests: + if t.suite not in suitesAndTests: + suitesAndTests[t.suite] = [] suitesAndTests[t.suite].append(t) print '-- Test Suites --' diff --git a/utils/lit/tests/.coveragerc b/utils/lit/tests/.coveragerc new file mode 100644 index 0000000000..c886d0ac1a --- /dev/null +++ b/utils/lit/tests/.coveragerc @@ -0,0 +1,11 @@ +# .coveragerc to control coverage.py +[run] +branch = False +parallel = True +source = lit + +[html] +directory = coverage_html_report + +[report] +omit = Inputs diff --git a/utils/lit/tests/Inputs/discovery/lit.cfg b/utils/lit/tests/Inputs/discovery/lit.cfg new file mode 100644 index 0000000000..3513bfffd1 --- /dev/null +++ b/utils/lit/tests/Inputs/discovery/lit.cfg @@ -0,0 +1,5 @@ +config.name = 'top-level-suite' +config.suffixes = ['.txt'] +config.test_format = lit.formats.ShTest() +config.test_source_root = None +config.test_exec_root = None diff --git a/utils/lit/tests/Inputs/discovery/subdir/lit.local.cfg b/utils/lit/tests/Inputs/discovery/subdir/lit.local.cfg new file mode 100644 index 0000000000..5ae6b3cd01 --- /dev/null +++ b/utils/lit/tests/Inputs/discovery/subdir/lit.local.cfg @@ -0,0 +1 @@ +config.suffixes = ['.py'] diff --git a/utils/lit/tests/Inputs/discovery/subdir/test-three.py b/utils/lit/tests/Inputs/discovery/subdir/test-three.py new file mode 100644 index 0000000000..b80b60b7a2 --- /dev/null +++ b/utils/lit/tests/Inputs/discovery/subdir/test-three.py @@ -0,0 +1 @@ +# RUN: true diff --git a/utils/lit/tests/Inputs/discovery/subsuite/lit.cfg b/utils/lit/tests/Inputs/discovery/subsuite/lit.cfg new file mode 100644 index 0000000000..0c2979d74a --- /dev/null +++ b/utils/lit/tests/Inputs/discovery/subsuite/lit.cfg @@ -0,0 +1,5 @@ +config.name = 'sub-suite' +config.suffixes = ['.txt'] +config.test_format = lit.formats.ShTest() +config.test_source_root = None +config.test_exec_root = None diff --git a/utils/lit/tests/Inputs/discovery/subsuite/test-one.txt b/utils/lit/tests/Inputs/discovery/subsuite/test-one.txt new file mode 100644 index 0000000000..b80b60b7a2 --- /dev/null +++ b/utils/lit/tests/Inputs/discovery/subsuite/test-one.txt @@ -0,0 +1 @@ +# RUN: true diff --git a/utils/lit/tests/Inputs/discovery/subsuite/test-two.txt b/utils/lit/tests/Inputs/discovery/subsuite/test-two.txt new file mode 100644 index 0000000000..b80b60b7a2 --- /dev/null +++ b/utils/lit/tests/Inputs/discovery/subsuite/test-two.txt @@ -0,0 +1 @@ +# RUN: true diff --git a/utils/lit/tests/Inputs/discovery/test-one.txt b/utils/lit/tests/Inputs/discovery/test-one.txt new file mode 100644 index 0000000000..b80b60b7a2 --- /dev/null +++ b/utils/lit/tests/Inputs/discovery/test-one.txt @@ -0,0 +1 @@ +# RUN: true diff --git a/utils/lit/tests/Inputs/discovery/test-two.txt b/utils/lit/tests/Inputs/discovery/test-two.txt new file mode 100644 index 0000000000..b80b60b7a2 --- /dev/null +++ b/utils/lit/tests/Inputs/discovery/test-two.txt @@ -0,0 +1 @@ +# RUN: true diff --git a/utils/lit/tests/Inputs/shtest-format/external_shell/fail.txt b/utils/lit/tests/Inputs/shtest-format/external_shell/fail.txt new file mode 100644 index 0000000000..1e74be5dbd --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-format/external_shell/fail.txt @@ -0,0 +1,3 @@ +# Run a command that fails with error on stdout. +# +# RUN: cat "does-not-exist" diff --git a/utils/lit/tests/Inputs/shtest-format/external_shell/lit.local.cfg b/utils/lit/tests/Inputs/shtest-format/external_shell/lit.local.cfg new file mode 100644 index 0000000000..d14d147977 --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-format/external_shell/lit.local.cfg @@ -0,0 +1 @@ +config.test_format = lit.formats.ShTest(execute_external=True) diff --git a/utils/lit/tests/Inputs/shtest-format/external_shell/pass.txt b/utils/lit/tests/Inputs/shtest-format/external_shell/pass.txt new file mode 100644 index 0000000000..b80b60b7a2 --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-format/external_shell/pass.txt @@ -0,0 +1 @@ +# RUN: true diff --git a/utils/lit/tests/Inputs/shtest-format/fail.txt b/utils/lit/tests/Inputs/shtest-format/fail.txt new file mode 100644 index 0000000000..49932c3006 --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-format/fail.txt @@ -0,0 +1 @@ +# RUN: false diff --git a/utils/lit/tests/Inputs/shtest-format/lit.cfg b/utils/lit/tests/Inputs/shtest-format/lit.cfg new file mode 100644 index 0000000000..78dd1bfb2e --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-format/lit.cfg @@ -0,0 +1,7 @@ +config.name = 'shtest-format' +config.suffixes = ['.txt'] +config.test_format = lit.formats.ShTest() +config.test_source_root = None +config.test_exec_root = None +config.target_triple = 'x86_64-unknown-unknown' +config.available_features.add('a-present-feature') diff --git a/utils/lit/tests/Inputs/shtest-format/no-test-line.txt b/utils/lit/tests/Inputs/shtest-format/no-test-line.txt new file mode 100644 index 0000000000..f2316bd73a --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-format/no-test-line.txt @@ -0,0 +1 @@ +# Empty! diff --git a/utils/lit/tests/Inputs/shtest-format/pass.txt b/utils/lit/tests/Inputs/shtest-format/pass.txt new file mode 100644 index 0000000000..b80b60b7a2 --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-format/pass.txt @@ -0,0 +1 @@ +# RUN: true diff --git a/utils/lit/tests/Inputs/shtest-format/requires-missing.txt b/utils/lit/tests/Inputs/shtest-format/requires-missing.txt new file mode 100644 index 0000000000..9e6648d8b8 --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-format/requires-missing.txt @@ -0,0 +1,2 @@ +RUN: true +REQUIRES: a-missing-feature diff --git a/utils/lit/tests/Inputs/shtest-format/requires-present.txt b/utils/lit/tests/Inputs/shtest-format/requires-present.txt new file mode 100644 index 0000000000..064f7074a7 --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-format/requires-present.txt @@ -0,0 +1,2 @@ +RUN: true +REQUIRES: a-present-feature diff --git a/utils/lit/tests/Inputs/shtest-format/unsupported_dir/lit.local.cfg b/utils/lit/tests/Inputs/shtest-format/unsupported_dir/lit.local.cfg new file mode 100644 index 0000000000..462e3dc5d1 --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-format/unsupported_dir/lit.local.cfg @@ -0,0 +1 @@ +config.unsupported = True diff --git a/utils/lit/tests/Inputs/shtest-format/unsupported_dir/some-test.txt b/utils/lit/tests/Inputs/shtest-format/unsupported_dir/some-test.txt new file mode 100644 index 0000000000..b80b60b7a2 --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-format/unsupported_dir/some-test.txt @@ -0,0 +1 @@ +# RUN: true diff --git a/utils/lit/tests/Inputs/shtest-format/xfail-feature.txt b/utils/lit/tests/Inputs/shtest-format/xfail-feature.txt new file mode 100644 index 0000000000..bd6241f8e4 --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-format/xfail-feature.txt @@ -0,0 +1,2 @@ +# RUN: false +# XFAIL: a-present-feature diff --git a/utils/lit/tests/Inputs/shtest-format/xfail-target.txt b/utils/lit/tests/Inputs/shtest-format/xfail-target.txt new file mode 100644 index 0000000000..36760bee43 --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-format/xfail-target.txt @@ -0,0 +1,2 @@ +RUN: false +XFAIL: x86_64 diff --git a/utils/lit/tests/Inputs/shtest-format/xfail.txt b/utils/lit/tests/Inputs/shtest-format/xfail.txt new file mode 100644 index 0000000000..6814cda401 --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-format/xfail.txt @@ -0,0 +1,2 @@ +RUN: false +XFAIL: * diff --git a/utils/lit/tests/Inputs/shtest-format/xpass.txt b/utils/lit/tests/Inputs/shtest-format/xpass.txt new file mode 100644 index 0000000000..764d21798b --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-format/xpass.txt @@ -0,0 +1,2 @@ +RUN: true +XFAIL: x86_64 diff --git a/utils/lit/tests/Inputs/shtest-shell/error-0.txt b/utils/lit/tests/Inputs/shtest-shell/error-0.txt new file mode 100644 index 0000000000..631c8df233 --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-shell/error-0.txt @@ -0,0 +1,3 @@ +# Check error on an internal shell error (unable to find command). +# +# RUN: not-a-real-command diff --git a/utils/lit/tests/Inputs/shtest-shell/error-1.txt b/utils/lit/tests/Inputs/shtest-shell/error-1.txt new file mode 100644 index 0000000000..e5c8be6b66 --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-shell/error-1.txt @@ -0,0 +1,3 @@ +# Check error on a shell parsing failure. +# +# RUN: echo "missing quote diff --git a/utils/lit/tests/Inputs/shtest-shell/error-2.txt b/utils/lit/tests/Inputs/shtest-shell/error-2.txt new file mode 100644 index 0000000000..a976286bdd --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-shell/error-2.txt @@ -0,0 +1,3 @@ +# Check error on a unsupported redirect. +# +# RUN: echo "hello" 3>&1 diff --git a/utils/lit/tests/Inputs/shtest-shell/lit.cfg b/utils/lit/tests/Inputs/shtest-shell/lit.cfg new file mode 100644 index 0000000000..4878b65609 --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-shell/lit.cfg @@ -0,0 +1,5 @@ +config.name = 'shtest-shell' +config.suffixes = ['.txt'] +config.test_format = lit.formats.ShTest() +config.test_source_root = None +config.test_exec_root = None diff --git a/utils/lit/tests/Inputs/shtest-shell/redirects.txt b/utils/lit/tests/Inputs/shtest-shell/redirects.txt new file mode 100644 index 0000000000..6be88b67ce --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-shell/redirects.txt @@ -0,0 +1,41 @@ +# Check stdout redirect (> and >>). +# +# RUN: echo "not-present" > %t.stdout-write +# RUN: echo "is-present" > %t.stdout-write +# RUN: FileCheck --check-prefix=STDOUT-WRITE < %t.stdout-write %s +# +# STDOUT-WRITE-NOT: not-present +# STDOUT-WRITE: is-present +# +# RUN: echo "appended-line" >> %t.stdout-write +# RUN: FileCheck --check-prefix=STDOUT-APPEND < %t.stdout-write %s +# +# STDOUT-APPEND: is-present +# STDOUT-APPEND: appended-line + + +# Check stderr redirect (2> and 2>>). +# +# RUN: echo "not-present" > %t.stderr-write +# RUN: %S/write-to-stderr.sh 2> %t.stderr-write +# RUN: FileCheck --check-prefix=STDERR-WRITE < %t.stderr-write %s +# +# STDERR-WRITE-NOT: not-present +# STDERR-WRITE: a line on stderr +# +# RUN: %S/write-to-stderr.sh 2>> %t.stderr-write +# RUN: FileCheck --check-prefix=STDERR-APPEND < %t.stderr-write %s +# +# STDERR-APPEND: a line on stderr +# STDERR-APPEND: a line on stderr + + +# Check combined redirect (&>). +# +# RUN: echo "not-present" > %t.combined +# RUN: %S/write-to-stdout-and-stderr.sh &> %t.combined +# RUN: FileCheck --check-prefix=COMBINED-WRITE < %t.combined %s +# +# COMBINED-WRITE-NOT: not-present +# COMBINED-WRITE: a line on stdout +# COMBINED-WRITE: a line on stderr diff --git a/utils/lit/tests/Inputs/shtest-shell/sequencing-0.txt b/utils/lit/tests/Inputs/shtest-shell/sequencing-0.txt new file mode 100644 index 0000000000..6578db25af --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-shell/sequencing-0.txt @@ -0,0 +1,28 @@ +# Check sequencing operations. +# +# RUN: echo "first-line" > %t.out && echo "second-line" >> %t.out +# RUN: FileCheck --check-prefix CHECK-AND < %t.out %s +# +# CHECK-AND: first-line +# CHECK-AND: second-line +# +# The false case of && is tested in sequencing-2.txt + + +# RUN: echo "first-line" > %t.out || echo "second-line" >> %t.out +# RUN: FileCheck --check-prefix CHECK-OR-1 < %t.out %s +# +# CHECK-OR-1: first-line +# CHECK-OR-1-NOT: second-line + +# RUN: false || echo "second-line" > %t.out +# RUN: FileCheck --check-prefix CHECK-OR-2 < %t.out %s +# +# CHECK-OR-2: second-line + + +# RUN: echo "first-line" > %t.out; echo "second-line" >> %t.out +# RUN: FileCheck --check-prefix CHECK-SEQ < %t.out %s +# +# CHECK-SEQ: first-line +# CHECK-SEQ: second-line diff --git a/utils/lit/tests/Inputs/shtest-shell/sequencing-1.txt b/utils/lit/tests/Inputs/shtest-shell/sequencing-1.txt new file mode 100644 index 0000000000..5a1794c26c --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-shell/sequencing-1.txt @@ -0,0 +1,2 @@ +# RUN: false && true +# XFAIL: * diff --git a/utils/lit/tests/Inputs/shtest-shell/write-to-stderr.sh b/utils/lit/tests/Inputs/shtest-shell/write-to-stderr.sh new file mode 100755 index 0000000000..ead3fd3ce3 --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-shell/write-to-stderr.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +echo "a line on stderr" 1>&2 diff --git a/utils/lit/tests/Inputs/shtest-shell/write-to-stdout-and-stderr.sh b/utils/lit/tests/Inputs/shtest-shell/write-to-stdout-and-stderr.sh new file mode 100755 index 0000000000..f20de5d904 --- /dev/null +++ b/utils/lit/tests/Inputs/shtest-shell/write-to-stdout-and-stderr.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +echo "a line on stdout" +echo "a line on stderr" 1>&2 diff --git a/utils/lit/tests/Inputs/unittest-adaptor/lit.cfg b/utils/lit/tests/Inputs/unittest-adaptor/lit.cfg new file mode 100644 index 0000000000..52de709662 --- /dev/null +++ b/utils/lit/tests/Inputs/unittest-adaptor/lit.cfg @@ -0,0 +1,5 @@ +config.name = 'unittest-adaptor' +config.suffixes = ['.txt'] +config.test_format = lit.formats.ShTest() +config.test_source_root = None +config.test_exec_root = None diff --git a/utils/lit/tests/Inputs/unittest-adaptor/test-one.txt b/utils/lit/tests/Inputs/unittest-adaptor/test-one.txt new file mode 100644 index 0000000000..b80b60b7a2 --- /dev/null +++ b/utils/lit/tests/Inputs/unittest-adaptor/test-one.txt @@ -0,0 +1 @@ +# RUN: true diff --git a/utils/lit/tests/Inputs/unittest-adaptor/test-two.txt b/utils/lit/tests/Inputs/unittest-adaptor/test-two.txt new file mode 100644 index 0000000000..49932c3006 --- /dev/null +++ b/utils/lit/tests/Inputs/unittest-adaptor/test-two.txt @@ -0,0 +1 @@ +# RUN: false diff --git a/utils/lit/tests/discovery.py b/utils/lit/tests/discovery.py new file mode 100644 index 0000000000..54b99d3945 --- /dev/null +++ b/utils/lit/tests/discovery.py @@ -0,0 +1,25 @@ +# Check the basic discovery process, including a sub-suite. +# +# RUN: %{lit} %{inputs}/discovery \ +# RUN: -j 1 --debug --no-execute --show-suites -v > %t.out 2> %t.err +# RUN: FileCheck --check-prefix=CHECK-BASIC-OUT < %t.out %s +# RUN: FileCheck --check-prefix=CHECK-BASIC-ERR < %t.err %s +# +# CHECK-BASIC-ERR: loading suite config '{{.*}}/tests/Inputs/discovery/lit.cfg' +# CHECK-BASIC-ERR: loading local config '{{.*}}/tests/Inputs/discovery/subdir/lit.local.cfg' +# CHECK-BASIC-ERR: loading suite config '{{.*}}/tests/Inputs/discovery/subsuite/lit.cfg' +# +# CHECK-BASIC-OUT: -- Test Suites -- +# CHECK-BASIC-OUT: sub-suite - 2 tests +# CHECK-BASIC-OUT: Source Root: +# CHECK-BASIC-OUT: Exec Root : +# CHECK-BASIC-OUT: top-level-suite - 3 tests +# CHECK-BASIC-OUT: Source Root: +# CHECK-BASIC-OUT: Exec Root : +# +# CHECK-BASIC-OUT: -- Testing: 5 tests, 1 threads -- +# CHECK-BASIC-OUT: PASS: sub-suite :: test-one +# CHECK-BASIC-OUT: PASS: sub-suite :: test-two +# CHECK-BASIC-OUT: PASS: top-level-suite :: subdir/test-three +# CHECK-BASIC-OUT: PASS: top-level-suite :: test-one +# CHECK-BASIC-OUT: PASS: top-level-suite :: test-two diff --git a/utils/lit/tests/lit.cfg b/utils/lit/tests/lit.cfg new file mode 100644 index 0000000000..32760ceb27 --- /dev/null +++ b/utils/lit/tests/lit.cfg @@ -0,0 +1,36 @@ +# -*- Python -*- + +import os + +# Configuration file for the 'lit' test runner. + +# name: The name of this test suite. +config.name = 'lit' + +# testFormat: The test format to use to interpret tests. +config.test_format = lit.formats.ShTest(execute_external=False) + +# suffixes: A list of file extensions to treat as test files. +config.suffixes = ['.py'] + +# excludes: A list of individual files to exclude. +config.excludes = ['Inputs'] + +# test_source_root: The root path where tests are located. +config.test_source_root = os.path.dirname(__file__) +config.test_exec_root = config.test_source_root + +config.target_triple = None + +src_root = os.path.join(config.test_source_root, '..') +config.environment['PYTHONPATH'] = src_root +config.substitutions.append(('%{src_root}', src_root)) +config.substitutions.append(('%{inputs}', os.path.join( + src_root, 'tests', 'Inputs'))) +config.substitutions.append(('%{lit}', os.path.join(src_root, 'lit.py'))) + +# Enable coverage.py reporting, assuming the coverage module has been installed +# and sitecustomize.py in the virtualenv has been modified appropriately. +if lit.params.get('check-coverage', None): + config.environment['COVERAGE_PROCESS_START'] = os.path.join( + os.path.dirname(__file__), ".coveragerc") diff --git a/utils/lit/tests/shell-parsing.py b/utils/lit/tests/shell-parsing.py new file mode 100644 index 0000000000..f644132f29 --- /dev/null +++ b/utils/lit/tests/shell-parsing.py @@ -0,0 +1,3 @@ +# Just run the ShUtil unit tests. +# +# RUN: python -m lit.ShUtil diff --git a/utils/lit/tests/shtest-format.py b/utils/lit/tests/shtest-format.py new file mode 100644 index 0000000000..4b36873a3d --- /dev/null +++ b/utils/lit/tests/shtest-format.py @@ -0,0 +1,43 @@ +# Check the various features of the ShTest format. +# +# RUN: not %{lit} -j 1 -v %{inputs}/shtest-format > %t.out +# RUN: FileCheck < %t.out %s +# +# END. + +# CHECK: -- Testing: + +# CHECK: FAIL: shtest-format :: external_shell/fail.txt +# CHECK: *** TEST 'shtest-format :: external_shell/fail.txt' FAILED *** +# CHECK: Command Output (stderr): +# CHECK: cat: does-not-exist: No such file or directory +# CHECK: -- + +# CHECK: PASS: shtest-format :: external_shell/pass.txt + +# CHECK: FAIL: shtest-format :: fail.txt + +# CHECK: UNRESOLVED: shtest-format :: no-test-line.txt +# CHECK: PASS: shtest-format :: pass.txt +# CHECK: UNSUPPORTED: shtest-format :: requires-missing.txt +# CHECK: PASS: shtest-format :: requires-present.txt +# CHECK: UNSUPPORTED: shtest-format :: unsupported_dir/some-test.txt +# CHECK: XFAIL: shtest-format :: xfail-feature.txt +# CHECK: XFAIL: shtest-format :: xfail-target.txt +# CHECK: XFAIL: shtest-format :: xfail.txt +# CHECK: XPASS: shtest-format :: xpass.txt +# CHECK: Testing Time + +# CHECK: Unexpected Passing Tests (1) +# CHECK: shtest-format :: xpass.txt + +# CHECK: Failing Tests (2) +# CHECK: shtest-format :: external_shell/fail.txt +# CHECK: shtest-format :: fail.txt + +# CHECK: Expected Passes : 3 +# CHECK: Expected Failures : 3 +# CHECK: Unsupported Tests : 2 +# CHECK: Unresolved Tests : 1 +# CHECK: Unexpected Passes : 1 +# CHECK: Unexpected Failures: 2 diff --git a/utils/lit/tests/shtest-shell.py b/utils/lit/tests/shtest-shell.py new file mode 100644 index 0000000000..32479e19a1 --- /dev/null +++ b/utils/lit/tests/shtest-shell.py @@ -0,0 +1,33 @@ +# Check the internal shell handling component of the ShTest format. +# +# RUN: not %{lit} -j 1 -v %{inputs}/shtest-shell > %t.out +# RUN: FileCheck < %t.out %s +# +# END. + +# CHECK: -- Testing: + +# CHECK: FAIL: shtest-shell :: error-0.txt +# CHECK: *** TEST 'shtest-shell :: error-0.txt' FAILED *** +# CHECK: Command 0: "not-a-real-command" +# CHECK: Command 0 Result: 127 +# CHECK: Command 0 Stderr: +# CHECK: 'not-a-real-command': command not found +# CHECK: *** + +# FIXME: The output here sucks. +# +# CHECK: FAIL: shtest-shell :: error-1.txt +# CHECK: *** TEST 'shtest-shell :: error-1.txt' FAILED *** +# CHECK: shell parser error on: 'echo "missing quote' +# CHECK: *** + +# CHECK: FAIL: shtest-shell :: error-2.txt +# CHECK: *** TEST 'shtest-shell :: error-2.txt' FAILED *** +# CHECK: Unsupported redirect: +# CHECK: *** + +# CHECK: PASS: shtest-shell :: redirects.txt +# CHECK: PASS: shtest-shell :: sequencing-0.txt +# CHECK: XFAIL: shtest-shell :: sequencing-1.txt +# CHECK: Failing Tests (3) diff --git a/utils/lit/tests/unittest-adaptor.py b/utils/lit/tests/unittest-adaptor.py new file mode 100644 index 0000000000..243dd4191d --- /dev/null +++ b/utils/lit/tests/unittest-adaptor.py @@ -0,0 +1,18 @@ +# Check the lit adaption to run under unittest. +# +# RUN: python %s %{inputs}/unittest-adaptor 2> %t.err +# RUN: FileCheck < %t.err %s +# +# CHECK: unittest-adaptor :: test-one.txt ... ok +# CHECK: unittest-adaptor :: test-two.txt ... FAIL + +import unittest +import sys + +import lit +import lit.discovery + +input_path = sys.argv[1] +unittest_suite = lit.discovery.load_test_suite([input_path]) +runner = unittest.TextTestRunner(verbosity=2) +runner.run(unittest_suite) diff --git a/utils/lit/tests/usage.py b/utils/lit/tests/usage.py new file mode 100644 index 0000000000..e10d6134a0 --- /dev/null +++ b/utils/lit/tests/usage.py @@ -0,0 +1,6 @@ +# Basic sanity check that usage works. +# +# RUN: %{lit} --help > %t.out +# RUN: FileCheck < %t.out %s +# +# CHECK: Usage: lit.py [options] {file-or-path} diff --git a/utils/lit/utils/README.txt b/utils/lit/utils/README.txt new file mode 100644 index 0000000000..81862ba099 --- /dev/null +++ b/utils/lit/utils/README.txt @@ -0,0 +1,2 @@ +Utilities for the project that aren't intended to be part of a source +distribution. diff --git a/utils/lit/utils/check-coverage b/utils/lit/utils/check-coverage new file mode 100755 index 0000000000..bb3d17e757 --- /dev/null +++ b/utils/lit/utils/check-coverage @@ -0,0 +1,50 @@ +#!/bin/sh + +prog=$(basename $0) + +# Expect to be run from the parent lit directory. +if [ ! -f setup.py ] || [ ! -d lit ]; then + printf 1>&2 "%s: expected to be run from base lit directory\n" "$prog" + exit 1 +fi + +# Parse command line arguments. +if [ "$1" == "--generate-html" ]; then + GENERATE_HTML=1 + shift +fi + +# If invoked with no arguments, run all the tests. +if [ $# == "0" ]; then + set -- "tests" +fi + +# Check that the active python has been modified to enable coverage in its +# sitecustomize. +if ! python -c \ + 'import sitecustomize, sys; sys.exit("coverage" not in dir(sitecustomize))' \ + &> /dev/null; then + printf 1>&2 "error: active python does not appear to enable coverage in its 'sitecustomize.py'\n" + exit 1 +fi + +# First, remove any existing coverage data files. +rm -f tests/.coverage +find tests -name .coverage.\* -exec rm {} \; + +# Next, run the tests. +lit -sv --param check-coverage=1 "$@" + +# Next, move all the data files from subdirectories up. +find tests/* -name .coverage.\* -exec mv {} tests \; + +# Combine all the data files. +(cd tests && python -m coverage combine) + +# Finally, generate the report. +(cd tests && python -m coverage report) + +# Generate the HTML report, if requested. +if [ ! -z "$GENERATE_HTML" ]; then + (cd tests && python -m coverage html) +fi diff --git a/utils/lit/utils/check-sdist b/utils/lit/utils/check-sdist new file mode 100755 index 0000000000..6186446aba --- /dev/null +++ b/utils/lit/utils/check-sdist @@ -0,0 +1,44 @@ +#!/bin/sh + +if [ $# == 1 ]; then + cd $1 +fi + +# Create a list of all the files in the source tree, excluding various things we +# know don't belong. +echo "Creating current directory contents list." +find . | \ + grep -v '^\./.gitignore' | \ + grep -v '^\./dist' | \ + grep -v '^\./utils' | \ + grep -v '^\./venv' | \ + grep -v '^\./lit.egg-info' | \ + grep -v '^\./lit/ExampleTests' | \ + grep -v '/Output' | \ + grep -v '__pycache__' | \ + grep -v '.pyc$' | grep -v '~$' | \ + sort > /tmp/lit_source_files.txt + +# Create the source distribution. +echo "Creating source distribution." +rm -rf lit.egg-info dist +python setup.py sdist > /tmp/lit_sdist_log.txt + +# Creating list of files in source distribution. +echo "Creating source distribution file list." +tar zft dist/lit*.tar.gz | \ + sed -e 's#lit-[0-9.dev]*/#./#' | \ + sed -e 's#/$##' | \ + grep -v '^\./PKG-INFO' | \ + grep -v '^\./setup.cfg' | \ + grep -v '^\./lit.egg-info' | \ + sort > /tmp/lit_sdist_files.txt + +# Diff the files. +echo "Running diff..." +if (diff /tmp/lit_source_files.txt /tmp/lit_sdist_files.txt); then + echo "Diff is clean!" +else + echo "error: there were differences in the source lists!" + exit 1 +fi diff --git a/utils/llvm-build/llvmbuild/main.py b/utils/llvm-build/llvmbuild/main.py index 27d23d0855..87e8819bde 100644 --- a/utils/llvm-build/llvmbuild/main.py +++ b/utils/llvm-build/llvmbuild/main.py @@ -182,7 +182,9 @@ class LLVMProjectInfo(object): # out easily. If we don't, we should special case the check. self.ordered_component_infos = [] - components_to_visit = set(self.component_infos) + components_to_visit = sorted( + set(self.component_infos), + key = lambda c: c.name) while components_to_visit: visit_component_info(iter(components_to_visit).next(), [], set()) @@ -807,7 +809,7 @@ given by --build-root) at the same SUBPATH""", # Determine the LLVM source path, if not given. source_root = opts.source_root if source_root: - if not os.path.exists(os.path.join(source_root, 'lib', 'VMCore', + if not os.path.exists(os.path.join(source_root, 'lib', 'IR', 'Function.cpp')): parser.error('invalid LLVM source root: %r' % source_root) else: @@ -815,7 +817,7 @@ given by --build-root) at the same SUBPATH""", llvm_build_path = os.path.dirname(llvmbuild_path) utils_path = os.path.dirname(llvm_build_path) source_root = os.path.dirname(utils_path) - if not os.path.exists(os.path.join(source_root, 'lib', 'VMCore', + if not os.path.exists(os.path.join(source_root, 'lib', 'IR', 'Function.cpp')): parser.error('unable to infer LLVM source root, please specify') diff --git a/utils/llvm-compilers-check b/utils/llvm-compilers-check index 623ebc6a32..3173027759 100755 --- a/utils/llvm-compilers-check +++ b/utils/llvm-compilers-check @@ -1,11 +1,11 @@ #!/usr/bin/python3 ##===- utils/llvmbuild - Build the LLVM project ----------------*-python-*-===## -# +# # The LLVM Compiler Infrastructure # # This file is distributed under the University of Illinois Open Source # License. See LICENSE.TXT for details. -# +# ##===----------------------------------------------------------------------===## # # This script builds many different flavors of the LLVM ecosystem. It @@ -147,6 +147,8 @@ def add_options(parser): help=("Do not build dragonegg")) parser.add_option("--no-install", default=False, action="store_true", help=("Do not do installs")) + parser.add_option("--keep-going", default=False, action="store_true", + help=("Keep going after failures")) return def check_options(parser, options, valid_builds): @@ -282,7 +284,7 @@ class Builder(threading.Thread): for key, value in env.items(): execenv[key] = value - + self.logger.debug("[" + prefix + "] " + "env " + str(env) + " " + " ".join(command)); @@ -299,6 +301,11 @@ class Builder(threading.Thread): + str(line, "utf-8").rstrip()) line = proc.stdout.readline() + (stdoutdata, stderrdata) = proc.communicate() + retcode = proc.wait() + + return retcode + except: traceback.print_exc() @@ -327,6 +334,7 @@ class Builder(threading.Thread): self.logger.debug("Start Gather") gather = True line = proc.stdout.readline() + except: traceback.print_exc() self.logger.debug(includes) @@ -353,16 +361,16 @@ class Builder(threading.Thread): configure_flags = dict( llvm=dict(debug=["--prefix=" + self.install_prefix, - "--with-extra-options=-Werror", + "--enable-werror", "--enable-assertions", "--disable-optimized", "--with-gcc-toolchain=" + cxxroot], release=["--prefix=" + self.install_prefix, - "--with-extra-options=-Werror", + "--enable-werror", "--enable-optimized", "--with-gcc-toolchain=" + cxxroot], paranoid=["--prefix=" + self.install_prefix, - "--with-extra-options=-Werror", + "--enable-werror", "--enable-assertions", "--enable-expensive-checks", "--disable-optimized", @@ -438,7 +446,7 @@ class Builder(threading.Thread): for component in components: comp = component[:] - + if (self.options.no_dragonegg): if (comp == 'dragonegg'): self.logger.info("Skipping " + component + " in " @@ -458,43 +466,74 @@ class Builder(threading.Thread): "").split()) self.logger.info("Configuring " + component + " in " + builddir) - self.configure(component, srcdir, builddir, - config_args, - configure_env[comp_key][build]) - - self.logger.info("Building " + component + " in " + builddir) - self.logger.info("Build: make " + str(make_flags[comp_key][build])) - self.make(component, srcdir, builddir, - make_flags[comp_key][build], - make_env[comp_key][build]) - - if (not self.options.no_install): - self.logger.info("Installing " + component + " in " + installdir) - self.make(component, srcdir, builddir, - make_install_flags[comp_key][build], - make_install_env[comp_key][build]) - - self.logger.info("Testing " + component + " in " + builddir) - self.logger.info("Test: make " - + str(make_check_flags[comp_key][build])) - self.make(component, srcdir, builddir, - make_check_flags[comp_key][build], - make_check_env[comp_key][build]) - + configrc = self.configure(component, srcdir, builddir, + config_args, + configure_env[comp_key][build]) + + if (configrc == None) : + self.logger.info("[None] Failed to configure " + component + " in " + installdir) + + if (configrc == 0 or self.options.keep_going) : + self.logger.info("Building " + component + " in " + builddir) + self.logger.info("Build: make " + str(make_flags[comp_key][build])) + buildrc = self.make(component, srcdir, builddir, + make_flags[comp_key][build], + make_env[comp_key][build]) + + if (buildrc == None) : + self.logger.info("[None] Failed to build " + component + " in " + installdir) + + if (buildrc == 0 or self.options.keep_going) : + self.logger.info("Testing " + component + " in " + builddir) + self.logger.info("Test: make " + + str(make_check_flags[comp_key][build])) + testrc = self.make(component, srcdir, builddir, + make_check_flags[comp_key][build], + make_check_env[comp_key][build]) + + if (testrc == None) : + self.logger.info("[None] Failed to test " + component + " in " + installdir) + + if ((testrc == 0 or self.options.keep_going) + and not self.options.no_install): + self.logger.info("Installing " + component + " in " + installdir) + self.make(component, srcdir, builddir, + make_install_flags[comp_key][build], + make_install_env[comp_key][build]) + else : + self.logger.info("Failed testing " + component + " in " + installdir) + + else : + self.logger.info("Failed to build " + component + " in " + installdir) + + else : + self.logger.info("Failed to configure " + component + " in " + installdir) def configure(self, component, srcdir, builddir, flags, env): + prefix = self.component_abbrev[component.replace("-", "_")] + self.logger.debug("Configure " + str(flags) + " " + str(srcdir) + " -> " + str(builddir)) configure_files = dict( llvm=[(srcdir + "/configure", builddir + "/Makefile")], - dragonegg=[("","")]) + dragonegg=[(None,None)]) doconfig = False for conf, mf in configure_files[component.replace("-", "_")]: + if conf is None: + # No configure necessary + return 0 + if not os.path.exists(conf): - return + self.logger.info("[" + prefix + "] Configure failed, no configure script " + conf) + return -1 + + if not os.path.exists(mf): + self.logger.info("[" + prefix + "] Configure failed, no makefile " + mf) + return -1 + if os.path.exists(conf) and os.path.exists(mf): confstat = os.stat(conf) makestat = os.stat(mf) @@ -506,16 +545,17 @@ class Builder(threading.Thread): break if not doconfig and not self.options.force_configure: - return + return 0 program = srcdir + "/configure" if not is_executable(program): - return + self.logger.info("[" + prefix + "] Configure failed, cannot execute " + program) + return -1 args = [program] args += ["--verbose"] args += flags - self.execute(args, builddir, env, component) + return self.execute(args, builddir, env, component) def make(self, component, srcdir, builddir, flags, env): program = find_executable("make") @@ -527,7 +567,7 @@ class Builder(threading.Thread): args = [program] args += flags - self.execute(args, builddir, env, component) + return self.execute(args, builddir, env, component) # Global constants build_abbrev = dict(debug="dbg", release="opt", paranoid="par") diff --git a/utils/llvm-lit/llvm-lit.in b/utils/llvm-lit/llvm-lit.in index 768dc5103c..87878d5638 100755 --- a/utils/llvm-lit/llvm-lit.in +++ b/utils/llvm-lit/llvm-lit.in @@ -13,8 +13,7 @@ sys.path.insert(0, os.path.join(llvm_source_root, 'utils', 'lit')) # Set up some builtin parameters, so that by default the LLVM test suite # configuration file knows how to find the object tree. builtin_parameters = { - 'build_config' : "@CMAKE_CFG_INTDIR@", - 'build_mode' : "@RUNTIME_BUILD_MODE@", + 'build_mode' : "@CMAKE_CFG_INTDIR@", 'llvm_site_config' : os.path.join(llvm_obj_root, 'test', 'lit.site.cfg') } diff --git a/utils/llvm.grm b/utils/llvm.grm index 322036b2c2..d65f075076 100644 --- a/utils/llvm.grm +++ b/utils/llvm.grm @@ -174,7 +174,9 @@ FuncAttr ::= noreturn | sspreq | returns_twice | nonlazybind - | address_safety + | sanitize_address + | sanitize_thread + | sanitize_memory ; OptFuncAttrs ::= + _ | OptFuncAttrs FuncAttr ; diff --git a/utils/llvm.natvis b/utils/llvm.natvis new file mode 100644 index 0000000000..6b4ef83c67 --- /dev/null +++ b/utils/llvm.natvis @@ -0,0 +1,181 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!--
+Visual Studio 2012 Native Debugging Visualizers for LLVM
+
+Put this file into "%USERPROFILE%\Documents\Visual Studio 2012\Visualizers"
+or create a symbolic link so it updates automatically.
+-->
+<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
+ <Type Name="llvm::SmallVector<*,*>">
+ <DisplayString Condition="(($T1*)EndX - ($T1*)BeginX) == 0">empty</DisplayString>
+ <DisplayString Condition="(($T1*)EndX - ($T1*)BeginX) != 0">{{ size={($T1*)EndX - ($T1*)BeginX} }}</DisplayString>
+ <Expand>
+ <Item Name="[size]">($T1*)EndX - ($T1*)BeginX</Item>
+ <Item Name="[capacity]">($T1*)CapacityX - ($T1*)BeginX</Item>
+ <ArrayItems>
+ <Size>($T1*)EndX - ($T1*)BeginX</Size>
+ <ValuePointer>($T1*)BeginX</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+
+ <Type Name="llvm::SmallVectorImpl<*>">
+ <DisplayString Condition="(($T1*)EndX - ($T1*)BeginX) == 0">empty</DisplayString>
+ <DisplayString Condition="(($T1*)EndX - ($T1*)BeginX) != 0">[{($T1*)EndX - ($T1*)BeginX}]</DisplayString>
+ <Expand>
+ <Item Name="[size]">($T1*)EndX - ($T1*)BeginX</Item>
+ <Item Name="[capacity]">($T1*)CapacityX - ($T1*)BeginX</Item>
+ <ArrayItems>
+ <Size>($T1*)EndX - ($T1*)BeginX</Size>
+ <ValuePointer>($T1*)BeginX</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+
+ <Type Name="llvm::SmallString<*>">
+ <DisplayString>{BeginX,s}</DisplayString>
+ <StringView>BeginX,s</StringView>
+ <Expand>
+ <Item Name="[size]">(char*)EndX - (char*)BeginX</Item>
+ <Item Name="[capacity]">(char*)CapacityX - (char*)BeginX</Item>
+ <ArrayItems>
+ <Size>(char*)EndX - (char*)BeginX</Size>
+ <ValuePointer>(char*)BeginX</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+
+ <Type Name="llvm::StringRef">
+ <DisplayString>[{Length}] {Data,s}</DisplayString>
+ <StringView>Data,s</StringView>
+ <Expand>
+ <Item Name="[length]">Length</Item>
+ <ArrayItems>
+ <Size>Length</Size>
+ <ValuePointer>Data</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+
+ <Type Name="llvm::PointerIntPair<*,*,*,*>">
+ <DisplayString>{Value & PointerBitMask} [{(Value >> IntShift) & IntMask}]</DisplayString>
+ <Expand>
+ <Item Name="[ptr]">Value & PointerBitMask</Item>
+ <Item Name="[int]">(Value >> IntShift) & IntMask</Item>
+ </Expand>
+ </Type>
+
+ <Type Name="llvm::PointerUnion<*,*>">
+ <DisplayString Condition="((Val.Value >> Val.IntShift) & Val.IntMask) == 0">[P1] {($T1)(Val.Value & Val.PointerBitMask)}</DisplayString>
+ <DisplayString Condition="((Val.Value >> Val.IntShift) & Val.IntMask) != 0">[P2] {($T2)(Val.Value & Val.PointerBitMask)}</DisplayString>
+ <Expand>
+ <Item Name="[ptr]" Condition="((Val.Value >> Val.IntShift) & Val.IntMask) == 0">($T1)(Val.Value & Val.PointerBitMask)</Item>
+ <Item Name="[ptr]" Condition="((Val.Value >> Val.IntShift) & Val.IntMask) != 0">($T2)(Val.Value & Val.PointerBitMask)</Item>
+ </Expand>
+ </Type>
+
+ <Type Name="llvm::PointerUnion3<*,*,*>">
+ <DisplayString Condition="(Val.Val.Value & 2) != 2 && (Val.Val.Value & 1) != 1">[P1] {($T1)((Val.Val.Value >> 2) << 2)}</DisplayString>
+ <DisplayString Condition="(Val.Val.Value & 2) == 2">[P2] {($T2)((Val.Val.Value >> 2) << 2)}</DisplayString>
+ <DisplayString Condition="(Val.Val.Value & 1) == 1">[P3] {($T3)((Val.Val.Value >> 2) << 2)}</DisplayString>
+ <Expand>
+ <Item Name="[ptr]" Condition="(Val.Val.Value & 2) != 2 && (Val.Val.Value & 1) != 1">($T1)((Val.Val.Value >> 2) << 2)</Item>
+ <Item Name="[ptr]" Condition="(Val.Val.Value & 2) == 2">($T2)((Val.Val.Value >> 2) << 2)</Item>
+ <Item Name="[ptr]" Condition="(Val.Val.Value & 1) == 1">($T3)((Val.Val.Value >> 2) << 2)</Item>
+ </Expand>
+ </Type>
+
+ <Type Name="llvm::PointerUnion4<*,*,*,*>">
+ <DisplayString Condition="(Val.Val.Value & 3) != 3 && (Val.Val.Value & 2) != 2 && (Val.Val.Value & 1) != 1">[P1] {($T1)((Val.Val.Value >> 2) << 2)}</DisplayString>
+ <DisplayString Condition="(Val.Val.Value & 3) != 3 && (Val.Val.Value & 2) == 2">[P2] {($T2)((Val.Val.Value >> 2) << 2)}</DisplayString>
+ <DisplayString Condition="(Val.Val.Value & 3) != 3 && (Val.Val.Value & 1) == 1">[P3] {($T3)((Val.Val.Value >> 2) << 2)}</DisplayString>
+ <DisplayString Condition="(Val.Val.Value & 3) == 3">[P4] {($T4)((Val.Val.Value >> 2) << 2)}</DisplayString>
+ <Expand>
+ <Item Name="[ptr]" Condition="(Val.Val.Value & 3) != 3 && (Val.Val.Value & 2) != 2 && (Val.Val.Value & 1) != 1">($T1)((Val.Val.Value >> 2) << 2)</Item>
+ <Item Name="[ptr]" Condition="(Val.Val.Value & 3) != 3 && (Val.Val.Value & 2) == 2">($T2)((Val.Val.Value >> 2) << 2)</Item>
+ <Item Name="[ptr]" Condition="(Val.Val.Value & 3) != 3 && (Val.Val.Value & 1) == 1">($T3)((Val.Val.Value >> 2) << 2)</Item>
+ <Item Name="[ptr]" Condition="(Val.Val.Value & 3) == 3">($T4)((Val.Val.Value >> 2) << 2)</Item>
+ </Expand>
+ </Type>
+
+ <Type Name="llvm::iplist<*,*>">
+ <DisplayString Condition="Head == 0">{{ empty }}</DisplayString>
+ <DisplayString Condition="Head != 0">{{ head={Head} }}</DisplayString>
+ <Expand>
+ <LinkedListItems>
+ <HeadPointer>Head</HeadPointer>
+ <NextPointer>Next</NextPointer>
+ <ValueNode>this</ValueNode>
+ </LinkedListItems>
+ </Expand>
+ </Type>
+
+ <Type Name="llvm::IntrusiveRefCntPtr<*>">
+ <DisplayString Condition="Obj == 0">empty</DisplayString>
+ <DisplayString Condition="(Obj != 0) && (Obj->ref_cnt == 1)">RefPtr [1 ref] {*Obj}</DisplayString>
+ <DisplayString Condition="(Obj != 0) && (Obj->ref_cnt != 1)">RefPtr [{Obj->ref_cnt} refs] {*Obj}</DisplayString>
+ <Expand>
+ <Item Condition="Obj != 0" Name="[refs]">Obj->ref_cnt</Item>
+ <Item Condition="Obj != 0" Name="[ptr]">Obj</Item>
+ </Expand>
+ </Type>
+
+ <Type Name="llvm::OwningPtr<*>">
+ <DisplayString Condition="Ptr == 0">empty</DisplayString>
+ <DisplayString Condition="Ptr != 0">OwningPtr {*Ptr}</DisplayString>
+ <Expand>
+ <Item Condition="Ptr != 0" Name="[ptr]">Ptr</Item>
+ </Expand>
+ </Type>
+
+ <Type Name="llvm::SmallPtrSet<*,*>">
+ <DisplayString Condition="CurArray == SmallArray">{{ [Small Mode] elements={NumElements}, arraySize={CurArraySize} }}</DisplayString>
+ <DisplayString Condition="CurArray != SmallArray">{{ [Big Mode] elements={NumElements}, arraySize={CurArraySize} }}</DisplayString>
+ <Expand>
+ <Item Name="[NumElements]">NumElements</Item>
+ <Item Name="[CurArraySize]">CurArraySize</Item>
+ <IndexListItems>
+ <Size>CurArraySize + 1</Size>
+ <ValueNode>($T1*)&CurArray[$i]</ValueNode>
+ </IndexListItems>
+ </Expand>
+ </Type>
+
+ <Type Name="llvm::DenseMap<*,*,*>">
+ <DisplayString Condition="NumEntries == 0">empty</DisplayString>
+ <DisplayString Condition="NumEntries != 0">{{ entries={NumEntries}, buckets={NumBuckets} }}</DisplayString>
+ <Expand>
+ <Item Name="[NumEntries]">NumEntries</Item>
+ <Item Name="[NumBuckets]">NumBuckets</Item>
+ <ArrayItems>
+ <Size>NumBuckets</Size>
+ <ValuePointer>Buckets</ValuePointer>
+ </ArrayItems>
+ </Expand>
+ </Type>
+
+ <Type Name="llvm::StringMap<*,*>">
+ <DisplayString>{{ NumBuckets={NumBuckets}, ItemSize={ItemSize} }}</DisplayString>
+ <Expand>
+ <Item Name="[NumBuckets]">NumBuckets</Item>
+ <Item Name="[ItemSize]">ItemSize</Item>
+ <IndexListItems>
+ <Size>NumBuckets</Size>
+ <ValueNode>(llvm::StringMapEntry<$T1>*)TheTable[$i]</ValueNode>
+ </IndexListItems>
+ </Expand>
+ </Type>
+
+ <Type Name="llvm::StringMapEntry<*>">
+ <DisplayString Condition="StrLen == 0">empty</DisplayString>
+ <DisplayString Condition="StrLen != 0">({((llvm::StringMapEntry<$T1>*)this)+1,s}, {second})</DisplayString>
+ <Expand>
+ <Item Name="[key]">((llvm::StringMapEntry<$T1>*)this)+1,s</Item>
+ <Item Name="[value]" Condition="StrLen != 0">second</Item>
+ </Expand>
+ </Type>
+
+ <Type Name="llvm::Triple">
+ <DisplayString>{Data}</DisplayString>
+ </Type>
+</AutoVisualizer>
diff --git a/utils/sort_includes.py b/utils/sort_includes.py index 8ff7d059c4..fef97550db 100755 --- a/utils/sort_includes.py +++ b/utils/sort_includes.py @@ -64,9 +64,9 @@ def sort_includes(f): if not found_headers: return - local_headers.sort() - project_headers.sort() - system_headers.sort() + local_headers = sorted(set(local_headers)) + project_headers = sorted(set(project_headers)) + system_headers = sorted(set(system_headers)) headers = api_headers + local_headers + project_headers + system_headers header_lines = ['#include ' + h for h in headers] lines = lines[:headers_begin] + header_lines + lines[headers_end + 1:] diff --git a/utils/testgen/mc-bundling-x86-gen.py b/utils/testgen/mc-bundling-x86-gen.py new file mode 100644 index 0000000000..5c1c6c4562 --- /dev/null +++ b/utils/testgen/mc-bundling-x86-gen.py @@ -0,0 +1,103 @@ + +#!/usr/bin/python + +# Auto-generates an exhaustive and repetitive test for correct bundle-locked +# alignment on x86. +# For every possible offset in an aligned bundle, a bundle-locked group of every +# size in the inclusive range [1, bundle_size] is inserted. An appropriate CHECK +# is added to verify that NOP padding occurred (or did not occur) as expected. +# Run with --align-to-end to generate a similar test with align_to_end for each +# .bundle_lock directive. + +# This script runs with Python 2.7 and 3.2+ + +from __future__ import print_function +import argparse + +BUNDLE_SIZE_POW2 = 4 +BUNDLE_SIZE = 2 ** BUNDLE_SIZE_POW2 + +PREAMBLE = ''' +# RUN: llvm-mc -filetype=obj -triple i386-pc-linux-gnu %s -o - \\ +# RUN: | llvm-objdump -triple i386 -disassemble -no-show-raw-insn - | FileCheck %s + +# !!! This test is auto-generated from utils/testgen/mc-bundling-x86-gen.py !!! +# It tests that bundle-aligned grouping works correctly in MC. Read the +# source of the script for more details. + + .text + .bundle_align_mode {0} +'''.format(BUNDLE_SIZE_POW2).lstrip() + +ALIGNTO = ' .align {0}, 0x90' +NOPFILL = ' .fill {0}, 1, 0x90' + +def print_bundle_locked_sequence(len, align_to_end=False): + print(' .bundle_lock{0}'.format(' align_to_end' if align_to_end else '')) + print(' .rept {0}'.format(len)) + print(' inc %eax') + print(' .endr') + print(' .bundle_unlock') + +def generate(align_to_end=False): + print(PREAMBLE) + + ntest = 0 + for instlen in range(1, BUNDLE_SIZE + 1): + for offset in range(0, BUNDLE_SIZE): + # Spread out all the instructions to not worry about cross-bundle + # interference. + print(ALIGNTO.format(2 * BUNDLE_SIZE)) + print('INSTRLEN_{0}_OFFSET_{1}:'.format(instlen, offset)) + if offset > 0: + print(NOPFILL.format(offset)) + print_bundle_locked_sequence(instlen, align_to_end) + + # Now generate an appropriate CHECK line + base_offset = ntest * 2 * BUNDLE_SIZE + inst_orig_offset = base_offset + offset # had it not been padded... + + def print_check(adjusted_offset=None, nop_split_offset=None): + if adjusted_offset is not None: + print('# CHECK: {0:x}: nop'.format(inst_orig_offset)) + if nop_split_offset is not None: + print('# CHECK: {0:x}: nop'.format(nop_split_offset)) + print('# CHECK: {0:x}: incl'.format(adjusted_offset)) + else: + print('# CHECK: {0:x}: incl'.format(inst_orig_offset)) + + if align_to_end: + if offset + instlen == BUNDLE_SIZE: + # No padding needed + print_check() + elif offset + instlen < BUNDLE_SIZE: + # Pad to end at nearest bundle boundary + offset_to_end = base_offset + (BUNDLE_SIZE - instlen) + print_check(offset_to_end) + else: # offset + instlen > BUNDLE_SIZE + # Pad to end at next bundle boundary, splitting the nop sequence + # at the nearest bundle boundary + offset_to_nearest_bundle = base_offset + BUNDLE_SIZE + offset_to_end = base_offset + (BUNDLE_SIZE * 2 - instlen) + if offset_to_nearest_bundle == offset_to_end: + offset_to_nearest_bundle = None + print_check(offset_to_end, offset_to_nearest_bundle) + else: + if offset + instlen > BUNDLE_SIZE: + # Padding needed + aligned_offset = (inst_orig_offset + instlen) & ~(BUNDLE_SIZE - 1) + print_check(aligned_offset) + else: + # No padding needed + print_check() + + print() + ntest += 1 + +if __name__ == '__main__': + argparser = argparse.ArgumentParser() + argparser.add_argument('--align-to-end', + action='store_true', + help='generate .bundle_lock with align_to_end option') + args = argparser.parse_args() + generate(align_to_end=args.align_to_end) diff --git a/utils/textmate/README b/utils/textmate/README new file mode 100644 index 0000000000..b01352551a --- /dev/null +++ b/utils/textmate/README @@ -0,0 +1,8 @@ +This directory contains a "bundle" for doing syntax highlighting of TableGen +files for the TextMate editor for OS X. The highlighting follows that done +by the TextMate "C" bundle. Currently, keywords, comments, and strings are +highlighted. + +To install this bundle, copy it to the per user area: + cp -R utils/textmate/TableGen.tmbundle \ + ~/Library/Application\ Support/TextMate/Bundles/TableGen.tmbundle diff --git a/utils/textmate/TableGen.tmbundle/Syntaxes/TableGen.tmLanguage b/utils/textmate/TableGen.tmbundle/Syntaxes/TableGen.tmLanguage new file mode 100644 index 0000000000..f3cf2d618f --- /dev/null +++ b/utils/textmate/TableGen.tmbundle/Syntaxes/TableGen.tmLanguage @@ -0,0 +1,132 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>fileTypes</key> + <array><string>td</string></array> + <key>foldingStartMarker</key> + <string>/\*\*|\{\s*$</string> + <key>foldingStopMarker</key> + <string>\*\*/|^\s*\}</string> + <key>name</key> + <string>TableGen</string> + <key>patterns</key> + <array> + <dict> + <key>include</key> + <string>#comments</string> + </dict> + <dict> + <key>match</key> + <string>\b(def|let|in|code|dag|string|list|bits|bit|field|include|defm|foreach|class|multiclass|int)\b</string> + <key>name</key> + <string>keyword.control.tablegen</string> + </dict> + <dict> + <key>begin</key> + <string>"</string> + <key>end</key> + <string>"</string> + <key>name</key> + <string>string.quoted.double.untitled</string> + <key>patterns</key> + <array> + <dict> + <key>match</key> + <string>\\.</string> + <key>name</key> + <string>constant.character.escape.tablegen</string> + </dict> + </array> + </dict> + </array> + <key>repository</key> + <dict> + <key>comments</key> + <dict> + <key>patterns</key> + <array> + <dict> + <key>captures</key> + <dict> + <key>1</key> + <dict> + <key>name</key> + <string>meta.toc-list.banner.block.tablegen</string> + </dict> + </dict> + <key>match</key> + <string>^/\* =(\s*.*?)\s*= \*/$\n?</string> + <key>name</key> + <string>comment.block.tablegen</string> + </dict> + <dict> + <key>begin</key> + <string>/\*</string> + <key>captures</key> + <dict> + <key>0</key> + <dict> + <key>name</key> + <string>punctuation.definition.comment.tablegen</string> + </dict> + </dict> + <key>end</key> + <string>\*/</string> + <key>name</key> + <string>comment.block.tablegen</string> + </dict> + <dict> + <key>match</key> + <string>\*/.*\n</string> + <key>name</key> + <string>invalid.illegal.stray-comment-end.tablegen</string> + </dict> + <dict> + <key>captures</key> + <dict> + <key>1</key> + <dict> + <key>name</key> + <string>meta.toc-list.banner.line.tablegen</string> + </dict> + </dict> + <key>match</key> + <string>^// =(\s*.*?)\s*=\s*$\n?</string> + <key>name</key> + <string>comment.line.banner.tablegen</string> + </dict> + <dict> + <key>begin</key> + <string>//</string> + <key>beginCaptures</key> + <dict> + <key>0</key> + <dict> + <key>name</key> + <string>punctuation.definition.comment.tablegen</string> + </dict> + </dict> + <key>end</key> + <string>$\n?</string> + <key>name</key> + <string>comment.line.double-slash.tablegen</string> + <key>patterns</key> + <array> + <dict> + <key>match</key> + <string>(?>\\\s*\n)</string> + <key>name</key> + <string>punctuation.separator.continuation.tablegen</string> + </dict> + </array> + </dict> + </array> + </dict> + </dict> + <key>scopeName</key> + <string>source.tablegen</string> + <key>uuid</key> + <string>3A090BFC-E74B-4993-8DAE-7CCF6D238A32</string> +</dict> +</plist> diff --git a/utils/textmate/TableGen.tmbundle/info.plist b/utils/textmate/TableGen.tmbundle/info.plist new file mode 100644 index 0000000000..c2f680ac51 --- /dev/null +++ b/utils/textmate/TableGen.tmbundle/info.plist @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>name</key> + <string>TableGen</string> + <key>ordering</key> + <array/> + <key>uuid</key> + <string>96925448-7219-41E9-A7F0-8D5B70E9B877</string> +</dict> +</plist> diff --git a/utils/unittest/UnitTestMain/TestMain.cpp b/utils/unittest/UnitTestMain/TestMain.cpp index b35bae5abf..ce32b7380f 100644 --- a/utils/unittest/UnitTestMain/TestMain.cpp +++ b/utils/unittest/UnitTestMain/TestMain.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Config/config.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Signals.h" #include "gtest/gtest.h" @@ -22,6 +23,7 @@ int main(int argc, char **argv) { llvm::sys::PrintStackTraceOnErrorSignal(); testing::InitGoogleTest(&argc, argv); + llvm::cl::ParseCommandLineOptions(argc, argv); # if defined(LLVM_ON_WIN32) // Disable all of the possible ways Windows conspires to make automated diff --git a/utils/unittest/googletest/gtest-printers.cc b/utils/unittest/googletest/gtest-printers.cc index ed63c7b3b9..205a39425f 100644 --- a/utils/unittest/googletest/gtest-printers.cc +++ b/utils/unittest/googletest/gtest-printers.cc @@ -127,7 +127,7 @@ namespace internal { // Depending on the value of a char (or wchar_t), we print it in one // of three formats: // - as is if it's a printable ASCII (e.g. 'a', '2', ' '), -// - as a hexidecimal escape sequence (e.g. '\x7F'), or +// - as a hexadecimal escape sequence (e.g. '\x7F'), or // - as a special escape sequence (e.g. '\r', '\n'). enum CharFormat { kAsIs, @@ -230,7 +230,7 @@ void PrintCharAndCodeTo(Char c, ostream* os) { return; *os << " (" << String::Format("%d", c).c_str(); - // For more convenience, we print c's code again in hexidecimal, + // For more convenience, we print c's code again in hexadecimal, // unless c was already printed in the form '\x##' or the code is in // [1, 9]. if (format == kHexEscape || (1 <= c && c <= 9)) { diff --git a/utils/valgrind/x86_64-pc-linux-gnu.supp b/utils/valgrind/x86_64-pc-linux-gnu.supp index fc863b85e2..c8e5cd0917 100644 --- a/utils/valgrind/x86_64-pc-linux-gnu.supp +++ b/utils/valgrind/x86_64-pc-linux-gnu.supp @@ -33,6 +33,12 @@ } { + We don't care of cmp + Memcheck:Cond + obj:/usr/bin/cmp +} + +{ We don't care if grep leaks Memcheck:Leak obj:/bin/grep diff --git a/utils/vim/llvm.vim b/utils/vim/llvm.vim index 753549fd72..830476f158 100644 --- a/utils/vim/llvm.vim +++ b/utils/vim/llvm.vim @@ -35,7 +35,7 @@ syn keyword llvmStatement uitofp ule ult umax umin une uno unreachable unwind syn keyword llvmStatement urem va_arg xchg xor zext " Keywords. -syn keyword llvmKeyword acq_rel acquire address_safety addrspace alias align +syn keyword llvmKeyword acq_rel acquire sanitize_address addrspace alias align syn keyword llvmKeyword alignstack alwaysinline appending arm_aapcs_vfpcc syn keyword llvmKeyword arm_aapcscc arm_apcscc asm atomic available_externally syn keyword llvmKeyword blockaddress byval c catch cc ccc cleanup coldcc common @@ -51,10 +51,11 @@ syn keyword llvmKeyword noimplicitfloat noinline nonlazybind noredzone noreturn syn keyword llvmKeyword nounwind optsize personality private protected syn keyword llvmKeyword ptx_device ptx_kernel readnone readonly release syn keyword llvmKeyword returns_twice section seq_cst sideeffect signext -syn keyword llvmKeyword singlethread spir_func spir_kernel sret ssp sspreq tail -syn keyword llvmKeyword target thread_local to triple unnamed_addr unordered -syn keyword llvmKeyword uwtable volatile weak weak_odr x86_fastcallcc -syn keyword llvmKeyword x86_stdcallcc x86_thiscallcc zeroext +syn keyword llvmKeyword singlethread spir_func spir_kernel sret ssp sspreq +syn keyword llvmKeyword sspstrong tail target thread_local to triple +syn keyword llvmKeyword unnamed_addr unordered uwtable volatile weak weak_odr +syn keyword llvmKeyword x86_fastcallcc x86_stdcallcc x86_thiscallcc zeroext +syn keyword llvmKeyword sanitize_thread sanitize_memory " Obsolete keywords. syn keyword llvmError getresult begin end diff --git a/utils/vim/vimrc b/utils/vim/vimrc index 3ef54c08cf..fd87d767d6 100644 --- a/utils/vim/vimrc +++ b/utils/vim/vimrc @@ -85,6 +85,13 @@ augroup filetype au! BufRead,BufNewFile *.td set filetype=tablegen augroup END +" Enable syntax highlighting for reStructuredText files. To use, copy +" rest.vim (http://www.vim.org/scripts/script.php?script_id=973) +" to ~/.vim/syntax . +augroup filetype + au! BufRead,BufNewFile *.rst set filetype=rest +augroup END + " Additional vim features to optionally uncomment. "set showcmd "set showmatch diff --git a/utils/yaml2obj/yaml2obj.cpp b/utils/yaml2obj/yaml2obj.cpp index c9436090dd..5a8ec1d096 100644 --- a/utils/yaml2obj/yaml2obj.cpp +++ b/utils/yaml2obj/yaml2obj.cpp @@ -790,7 +790,8 @@ template <typename value_type> raw_ostream &operator <<( raw_ostream &OS , const binary_le_impl<value_type> &BLE) { char Buffer[sizeof(BLE.Value)]; - support::endian::write_le<value_type, support::unaligned>(Buffer, BLE.Value); + support::endian::write<value_type, support::little, support::unaligned>( + Buffer, BLE.Value); OS.write(Buffer, sizeof(BLE.Value)); return OS; } |