diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-05-04 16:11:02 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-05-04 16:11:02 +0000 |
commit | 750ce4d809c7e2a298a389a512a17652ff5be3f2 (patch) | |
tree | 70fbd90da02177c8e6ef82adba9fa8ace285a5e3 /utils | |
parent | 5f970ec96e421f64db6b1c6509a902ea73d98cc7 (diff) | |
download | FreeBSD-src-750ce4d809c7e2a298a389a512a17652ff5be3f2.zip FreeBSD-src-750ce4d809c7e2a298a389a512a17652ff5be3f2.tar.gz |
Update LLVM to r103004.
Diffstat (limited to 'utils')
21 files changed, 589 insertions, 309 deletions
diff --git a/utils/TableGen/ARMDecoderEmitter.cpp b/utils/TableGen/ARMDecoderEmitter.cpp index 5fb8b6b..c879a54 100644 --- a/utils/TableGen/ARMDecoderEmitter.cpp +++ b/utils/TableGen/ARMDecoderEmitter.cpp @@ -623,7 +623,7 @@ void Filter::recurse() { assert(FilterChooserMap.size() == 1); return; } - + // Otherwise, create sub choosers. for (mapIterator = FilteredInstructions.begin(); mapIterator != FilteredInstructions.end(); @@ -631,7 +631,7 @@ void Filter::recurse() { // Marks all the segment positions with either BIT_TRUE or BIT_FALSE. for (bitIndex = 0; bitIndex < NumBits; bitIndex++) { - if (mapIterator->first & (1 << bitIndex)) + if (mapIterator->first & (1ULL << bitIndex)) BitValueArray[StartBit + bitIndex] = BIT_TRUE; else BitValueArray[StartBit + bitIndex] = BIT_FALSE; @@ -853,7 +853,7 @@ bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn, return false; if (Insn[StartBit + i] == BIT_TRUE) - Field = Field | (1 << i); + Field = Field | (1ULL << i); } return true; @@ -1344,23 +1344,8 @@ void FilterChooser::doFilter() { return; // If we come to here, the instruction decoding has failed. - // Print out the instructions in the conflict set... + // Set the BestIndex to -1 to indicate so. BestIndex = -1; - - DEBUG({ - errs() << "Conflict:\n"; - - dumpStack(errs(), "\t\t"); - - for (unsigned i = 0; i < Num; i++) { - const std::string &Name = nameWithID(Opcodes[i]); - - errs() << '\t' << Name << " "; - dumpBits(errs(), - getBitsField(*AllInstructions[Opcodes[i]]->TheDef, "Inst")); - errs() << '\n'; - } - }); } // Emits code to decode our share of instructions. Returns true if the @@ -1465,7 +1450,9 @@ bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) { // Otherwise, it does not belong to the known conflict sets. } - // We don't know how to decode these instructions! Dump the conflict set! + + // We don't know how to decode these instructions! Return 0 and dump the + // conflict set! o.indent(Indentation) << "return 0;" << " // Conflict set: "; for (int i = 0, N = Opcodes.size(); i < N; ++i) { o << nameWithID(Opcodes[i]); @@ -1474,6 +1461,21 @@ bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) { else o << '\n'; } + + // Print out useful conflict information for postmortem analysis. + errs() << "Decoding Conflict:\n"; + + dumpStack(errs(), "\t\t"); + + for (unsigned i = 0; i < Opcodes.size(); i++) { + const std::string &Name = nameWithID(Opcodes[i]); + + errs() << '\t' << Name << " "; + dumpBits(errs(), + getBitsField(*AllInstructions[Opcodes[i]]->TheDef, "Inst")); + errs() << '\n'; + } + return true; } @@ -1548,6 +1550,16 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( const StringRef Name = Def.getName(); uint8_t Form = getByteField(Def, "Form"); + BitsInit &Bits = getBitsField(Def, "Inst"); + + // If all the bit positions are not specified; do not decode this instruction. + // We are bound to fail! For proper disassembly, the well-known encoding bits + // of the instruction must be fully specified. + // + // This also removes pseudo instructions from considerations of disassembly, + // which is a better design and less fragile than the name matchings. + if (Bits.allInComplete()) return false; + if (TN == TARGET_ARM) { // FIXME: what about Int_MemBarrierV6 and Int_SyncBarrierV6? if ((Name != "Int_MemBarrierV7" && Name != "Int_SyncBarrierV7") && @@ -1668,11 +1680,6 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( if (!thumbInstruction(Form)) return false; - // Ignore pseudo instructions. - if (Name == "tInt_eh_sjlj_setjmp" || Name == "t2Int_eh_sjlj_setjmp" || - Name == "t2MOVi32imm" || Name == "tBX" || Name == "tBXr9") - return false; - // On Darwin R9 is call-clobbered. Ignore the non-Darwin counterparts. if (Name == "tBL" || Name == "tBLXi" || Name == "tBLXr") return false; @@ -1692,8 +1699,12 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( // Ignore tADDrSP, tADDspr, and tPICADD, prefer the generic tADDhirr. // Ignore t2SUBrSPs, prefer the t2SUB[S]r[r|s]. // Ignore t2ADDrSPs, prefer the t2ADD[S]r[r|s]. + // Ignore t2ADDrSPi/t2SUBrSPi, which have more generic couterparts. + // Ignore t2ADDrSPi12/t2SUBrSPi12, which have more generic couterparts if (Name == "tADDrSP" || Name == "tADDspr" || Name == "tPICADD" || - Name == "t2SUBrSPs" || Name == "t2ADDrSPs") + Name == "t2SUBrSPs" || Name == "t2ADDrSPs" || + Name == "t2ADDrSPi" || Name == "t2SUBrSPi" || + Name == "t2ADDrSPi12" || Name == "t2SUBrSPi12") return false; // Ignore t2LDRDpci, prefer the generic t2LDRDi8, t2LDRD_PRE, t2LDRD_POST. @@ -1716,7 +1727,6 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( // tLDRcp conflicts with tLDRspi // tRestore conflicts with tLDRspi // t2LEApcrelJT conflicts with t2LEApcrel - // t2ADDrSPi/t2SUBrSPi have more generic couterparts if (Name == "tBfar" || /* Name == "tCMNz" || */ Name == "tCMPzi8" || Name == "tCMPzr" || Name == "tCMPzhir" || /* Name == "t2CMNzrr" || Name == "t2CMNzrs" || @@ -1724,7 +1734,7 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( Name == "t2CMPzri" || Name == "tPOP_RET" || Name == "t2LDM_RET" || Name == "tMOVCCi" || Name == "tMOVCCr" || Name == "tBR_JTr" || Name == "tSpill" || Name == "tLDRcp" || Name == "tRestore" || - Name == "t2LEApcrelJT" || Name == "t2ADDrSPi" || Name == "t2SUBrSPi") + Name == "t2LEApcrelJT") return false; } @@ -1737,8 +1747,6 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( } DEBUG({ - BitsInit &Bits = getBitsField(Def, "Inst"); - errs() << " "; // Dumps the instruction encoding bits. diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index e5c068b..1947824 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -1564,10 +1564,14 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { Info.Instructions.begin(), ie = Info.Instructions.end(); it != ie; ++it) MaxNumOperands = std::max(MaxNumOperands, (*it)->Operands.size()); - - OS << "bool " << Target.getName() << ClassName - << "::\nMatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> " - "&Operands,\n MCInst &Inst) {\n"; + + const std::string &MatchName = + AsmParser->getValueAsString("MatchInstructionName"); + OS << "bool " << Target.getName() << ClassName << "::\n" + << MatchName + << "(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,\n"; + OS.indent(MatchName.size() + 1); + OS << "MCInst &Inst) {\n"; // Emit the static match table; unused classes get initalized to 0 which is // guaranteed to be InvalidMatchClass. diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index 641c224..2a2a4ef 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -35,7 +35,8 @@ void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) { R->getName() == "IMPLICIT_DEF" || R->getName() == "SUBREG_TO_REG" || R->getName() == "COPY_TO_REGCLASS" || - R->getName() == "DBG_VALUE") continue; + R->getName() == "DBG_VALUE" || + R->getName() == "REG_SEQUENCE") continue; BitsInit *BI = R->getValueAsBitsInit("Inst"); @@ -113,7 +114,8 @@ void CodeEmitterGen::run(raw_ostream &o) { R->getName() == "IMPLICIT_DEF" || R->getName() == "SUBREG_TO_REG" || R->getName() == "COPY_TO_REGCLASS" || - R->getName() == "DBG_VALUE") { + R->getName() == "DBG_VALUE" || + R->getName() == "REG_SEQUENCE") { o << " 0U,\n"; continue; } @@ -152,7 +154,8 @@ void CodeEmitterGen::run(raw_ostream &o) { InstName == "IMPLICIT_DEF" || InstName == "SUBREG_TO_REG" || InstName == "COPY_TO_REGCLASS" || - InstName == "DBG_VALUE") continue; + InstName == "DBG_VALUE" || + InstName == "REG_SEQUENCE") continue; BitsInit *BI = R->getValueAsBitsInit("Inst"); const std::vector<RecordVal> &Vals = R->getValues(); @@ -249,7 +252,7 @@ void CodeEmitterGen::run(raw_ostream &o) { << " std::string msg;\n" << " raw_string_ostream Msg(msg);\n" << " Msg << \"Not supported instr: \" << MI;\n" - << " llvm_report_error(Msg.str());\n" + << " report_fatal_error(Msg.str());\n" << " }\n" << " return Value;\n" << "}\n\n"; diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index d2c0195..a0bccfc 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -1992,16 +1992,13 @@ void CodeGenDAGPatterns::ParseDefaultOperands() { /// HandleUse - Given "Pat" a leaf in the pattern, check to see if it is an /// instruction input. Return true if this is a real use. static bool HandleUse(TreePattern *I, TreePatternNode *Pat, - std::map<std::string, TreePatternNode*> &InstInputs, - std::vector<Record*> &InstImpInputs) { + std::map<std::string, TreePatternNode*> &InstInputs) { // No name -> not interesting. if (Pat->getName().empty()) { if (Pat->isLeaf()) { DefInit *DI = dynamic_cast<DefInit*>(Pat->getLeafValue()); if (DI && DI->getDef()->isSubClassOf("RegisterClass")) I->error("Input " + DI->getDef()->getName() + " must be named!"); - else if (DI && DI->getDef()->isSubClassOf("Register")) - InstImpInputs.push_back(DI->getDef()); } return false; } @@ -2047,10 +2044,9 @@ void CodeGenDAGPatterns:: FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, std::map<std::string, TreePatternNode*> &InstInputs, std::map<std::string, TreePatternNode*>&InstResults, - std::vector<Record*> &InstImpInputs, std::vector<Record*> &InstImpResults) { if (Pat->isLeaf()) { - bool isUse = HandleUse(I, Pat, InstInputs, InstImpInputs); + bool isUse = HandleUse(I, Pat, InstInputs); if (!isUse && Pat->getTransformFn()) I->error("Cannot specify a transform function for a non-input value!"); return; @@ -2077,12 +2073,12 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, if (Pat->getChild(i)->getNumTypes() == 0) I->error("Cannot have void nodes inside of patterns!"); FindPatternInputsAndOutputs(I, Pat->getChild(i), InstInputs, InstResults, - InstImpInputs, InstImpResults); + InstImpResults); } // If this is a non-leaf node with no children, treat it basically as if // it were a leaf. This handles nodes like (imm). - bool isUse = HandleUse(I, Pat, InstInputs, InstImpInputs); + bool isUse = HandleUse(I, Pat, InstInputs); if (!isUse && Pat->getTransformFn()) I->error("Cannot specify a transform function for a non-input value!"); @@ -2123,8 +2119,7 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, // Verify and collect info from the computation. FindPatternInputsAndOutputs(I, Pat->getChild(NumDests), - InstInputs, InstResults, - InstImpInputs, InstImpResults); + InstInputs, InstResults, InstImpResults); } //===----------------------------------------------------------------------===// @@ -2297,10 +2292,8 @@ void CodeGenDAGPatterns::ParseInstructions() { // Create and insert the instruction. std::vector<Record*> ImpResults; - std::vector<Record*> ImpOperands; Instructions.insert(std::make_pair(Instrs[i], - DAGInstruction(0, Results, Operands, ImpResults, - ImpOperands))); + DAGInstruction(0, Results, Operands, ImpResults))); continue; // no pattern. } @@ -2322,7 +2315,6 @@ void CodeGenDAGPatterns::ParseInstructions() { // in the instruction, including what reg class they are. std::map<std::string, TreePatternNode*> InstResults; - std::vector<Record*> InstImpInputs; std::vector<Record*> InstImpResults; // Verify that the top-level forms in the instruction are of void type, and @@ -2335,7 +2327,7 @@ void CodeGenDAGPatterns::ParseInstructions() { // Find inputs and outputs, and verify the structure of the uses/defs. FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults, - InstImpInputs, InstImpResults); + InstImpResults); } // Now that we have inputs and outputs of the pattern, inspect the operands @@ -2445,9 +2437,8 @@ void CodeGenDAGPatterns::ParseInstructions() { ResultPattern->setType(i, Res0Node->getExtType(i)); // Create and insert the instruction. - // FIXME: InstImpResults and InstImpInputs should not be part of - // DAGInstruction. - DAGInstruction TheInst(I, Results, Operands, InstImpResults, InstImpInputs); + // FIXME: InstImpResults should not be part of DAGInstruction. + DAGInstruction TheInst(I, Results, Operands, InstImpResults); Instructions.insert(std::make_pair(I->getRecord(), TheInst)); // Use a temporary tree pattern to infer all types and make sure that the @@ -2682,12 +2673,11 @@ void CodeGenDAGPatterns::ParsePatterns() { // Validate that the input pattern is correct. std::map<std::string, TreePatternNode*> InstInputs; std::map<std::string, TreePatternNode*> InstResults; - std::vector<Record*> InstImpInputs; std::vector<Record*> InstImpResults; for (unsigned j = 0, ee = Pattern->getNumTrees(); j != ee; ++j) FindPatternInputsAndOutputs(Pattern, Pattern->getTree(j), InstInputs, InstResults, - InstImpInputs, InstImpResults); + InstImpResults); // Promote the xform function to be an explicit node if set. TreePatternNode *DstPattern = Result->getOnlyTree(); diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index 5480513..0a1362a 100644 --- a/utils/TableGen/CodeGenDAGPatterns.h +++ b/utils/TableGen/CodeGenDAGPatterns.h @@ -529,23 +529,19 @@ class DAGInstruction { std::vector<Record*> Results; std::vector<Record*> Operands; std::vector<Record*> ImpResults; - std::vector<Record*> ImpOperands; TreePatternNode *ResultPattern; public: DAGInstruction(TreePattern *TP, const std::vector<Record*> &results, const std::vector<Record*> &operands, - const std::vector<Record*> &impresults, - const std::vector<Record*> &impoperands) + const std::vector<Record*> &impresults) : Pattern(TP), Results(results), Operands(operands), - ImpResults(impresults), ImpOperands(impoperands), - ResultPattern(0) {} + ImpResults(impresults), ResultPattern(0) {} const TreePattern *getPattern() const { return Pattern; } unsigned getNumResults() const { return Results.size(); } unsigned getNumOperands() const { return Operands.size(); } unsigned getNumImpResults() const { return ImpResults.size(); } - unsigned getNumImpOperands() const { return ImpOperands.size(); } const std::vector<Record*>& getImpResults() const { return ImpResults; } void setResultPattern(TreePatternNode *R) { ResultPattern = R; } @@ -565,11 +561,6 @@ public: return ImpResults[RN]; } - Record *getImpOperand(unsigned ON) const { - assert(ON < ImpOperands.size()); - return ImpOperands[ON]; - } - TreePatternNode *getResultPattern() const { return ResultPattern; } }; @@ -750,7 +741,6 @@ private: TreePatternNode*> &InstInputs, std::map<std::string, TreePatternNode*> &InstResults, - std::vector<Record*> &InstImpInputs, std::vector<Record*> &InstImpResults); }; } // end namespace llvm diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index 0392895..1efe2ff 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -326,6 +326,7 @@ void CodeGenTarget::ComputeInstrsByEnum() const { const CodeGenInstruction *COPY_TO_REGCLASS = GetInstByName("COPY_TO_REGCLASS", Insts); const CodeGenInstruction *DBG_VALUE = GetInstByName("DBG_VALUE", Insts); + const CodeGenInstruction *REG_SEQUENCE = GetInstByName("REG_SEQUENCE", Insts); // Print out the rest of the instructions now. InstrsByEnum.push_back(PHI); @@ -340,6 +341,7 @@ void CodeGenTarget::ComputeInstrsByEnum() const { InstrsByEnum.push_back(SUBREG_TO_REG); InstrsByEnum.push_back(COPY_TO_REGCLASS); InstrsByEnum.push_back(DBG_VALUE); + InstrsByEnum.push_back(REG_SEQUENCE); unsigned EndOfPredefines = InstrsByEnum.size(); @@ -357,7 +359,8 @@ void CodeGenTarget::ComputeInstrsByEnum() const { CGI != IMPLICIT_DEF && CGI != SUBREG_TO_REG && CGI != COPY_TO_REGCLASS && - CGI != DBG_VALUE) + CGI != DBG_VALUE && + CGI != REG_SEQUENCE) InstrsByEnum.push_back(CGI); } diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index f83ab48..d3bf60e 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -19,15 +19,14 @@ #include "CodeGenTarget.h" #include "Record.h" +#include "llvm/MC/EDInstInfo.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" -#include <vector> +#include <map> #include <string> - -#define MAX_OPERANDS 5 -#define MAX_SYNTAXES 2 +#include <vector> using namespace llvm; @@ -54,9 +53,9 @@ namespace { unsigned int index = 0; unsigned int numEntries = Entries.size(); - for(index = 0; index < numEntries; ++index) { + for (index = 0; index < numEntries; ++index) { o.indent(i) << Entries[index]; - if(index < (numEntries - 1)) + if (index < (numEntries - 1)) o << ","; o << "\n"; } @@ -88,24 +87,24 @@ namespace { class StructEmitter { private: std::string Name; - std::vector<std::string> MemberTypes; - std::vector<std::string> MemberNames; + typedef std::pair<const char*, const char*> member; + std::vector< member > Members; public: StructEmitter(const char *N) : Name(N) { } void addMember(const char *t, const char *n) { - MemberTypes.push_back(std::string(t)); - MemberNames.push_back(std::string(n)); + member m(t, n); + Members.push_back(m); } void emit(raw_ostream &o, unsigned int &i) { o.indent(i) << "struct " << Name.c_str() << " {" << "\n"; i += 2; unsigned int index = 0; - unsigned int numMembers = MemberTypes.size(); + unsigned int numMembers = Members.size(); for (index = 0; index < numMembers; ++index) { - o.indent(i) << MemberTypes[index] << " " << MemberNames[index] << ";"; - o << "\n"; + o.indent(i) << Members[index].first << " "; + o.indent(i) << Members[index].second << ";" << "\n"; } i -= 2; @@ -121,47 +120,87 @@ namespace { class LiteralConstantEmitter : public ConstantEmitter { private: - std::string Literal; + bool IsNumber; + union { + int Number; + const char* String; + }; public: - LiteralConstantEmitter(const char *literal) : Literal(literal) { + LiteralConstantEmitter(const char *string) : + IsNumber(false), + String(string) { } - LiteralConstantEmitter(int literal) { - char buf[256]; - snprintf(buf, 256, "%d", literal); - Literal = buf; + LiteralConstantEmitter(int number = 0) : + IsNumber(true), + Number(number) { + } + void set(const char *string) { + IsNumber = false; + Number = 0; + String = string; + } + void set(int number) { + IsNumber = true; + String = NULL; + Number = number; + } + bool is(const char *string) { + return !strcmp(String, string); } void emit(raw_ostream &o, unsigned int &i) { - o << Literal; + if (IsNumber) + o << Number; + else + o << String; } }; class CompoundConstantEmitter : public ConstantEmitter { private: - std::vector<ConstantEmitter*> Entries; + unsigned int Padding; + std::vector<ConstantEmitter *> Entries; public: - CompoundConstantEmitter() { - } - ~CompoundConstantEmitter() { - unsigned int index; - unsigned int numEntries = Entries.size(); - for (index = 0; index < numEntries; ++index) { - delete Entries[index]; - } + 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(); - for (index = 0; index < numEntries; ++index) { + + 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); - Entries[index]->emit(o, i); - if (index < (numEntries - 1)) + if (index < numEntries) + Entries[index]->emit(o, i); + else + o << "-1"; + + if (index < (numToPrint - 1)) o << ","; o << "\n"; } @@ -226,40 +265,31 @@ void populateOperandOrder(CompoundConstantEmitter *operandOrder, ++operandIterator) { if (operandIterator->OperandType == AsmWriterOperand::isMachineInstrOperand) { - char buf[2]; - snprintf(buf, sizeof(buf), "%u", operandIterator->CGIOpNo); - operandOrder->addEntry(new LiteralConstantEmitter(buf)); + operandOrder->addEntry( + new LiteralConstantEmitter(operandIterator->CGIOpNo)); numArgs++; } } - - for(; numArgs < MAX_OPERANDS; numArgs++) { - operandOrder->addEntry(new LiteralConstantEmitter("-1")); - } } ///////////////////////////////////////////////////// // Support functions for handling X86 instructions // ///////////////////////////////////////////////////// -#define ADDFLAG(flag) flags->addEntry(flag) +#define SET(flag) { type->set(flag); return 0; } -#define REG(str) if (name == str) { ADDFLAG("kOperandFlagRegister"); return 0; } -#define MEM(str) if (name == str) { ADDFLAG("kOperandFlagMemory"); return 0; } -#define LEA(str) if (name == str) { ADDFLAG("kOperandFlagEffectiveAddress"); \ - return 0; } -#define IMM(str) if (name == str) { ADDFLAG("kOperandFlagImmediate"); \ - return 0; } -#define PCR(str) if (name == str) { ADDFLAG("kOperandFlagMemory"); \ - ADDFLAG("kOperandFlagPCRelative"); \ - 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"); -/// X86FlagFromOpName - Processes the name of a single X86 operand (which is -/// actually its type) and translates it into an operand flag +/// X86TypeFromOpName - Processes the name of a single X86 operand (which is +/// actually its type) and translates it into an operand type /// -/// @arg flags - The flags object to add the flag to +/// @arg flags - The type object to set /// @arg name - The name of the operand -static int X86FlagFromOpName(FlagsConstantEmitter *flags, +static int X86TypeFromOpName(LiteralConstantEmitter *type, const std::string &name) { REG("GR8"); REG("GR8_NOREX"); @@ -282,6 +312,17 @@ static int X86FlagFromOpName(FlagsConstantEmitter *flags, REG("CONTROL_REG_32"); REG("CONTROL_REG_64"); + IMM("i8imm"); + IMM("i16imm"); + IMM("i16i8imm"); + IMM("i32imm"); + IMM("i32i8imm"); + IMM("i64imm"); + IMM("i64i8imm"); + IMM("i64i32imm"); + IMM("SSECC"); + + // all R, I, R, I, R MEM("i8mem"); MEM("i8mem_NOREX"); MEM("i16mem"); @@ -301,22 +342,14 @@ static int X86FlagFromOpName(FlagsConstantEmitter *flags, MEM("f128mem"); MEM("opaque512mem"); + // all R, I, R, I LEA("lea32mem"); LEA("lea64_32mem"); LEA("lea64mem"); - IMM("i8imm"); - IMM("i16imm"); - IMM("i16i8imm"); - IMM("i32imm"); - IMM("i32imm_pcrel"); - IMM("i32i8imm"); - IMM("i64imm"); - IMM("i64i8imm"); - IMM("i64i32imm"); - IMM("i64i32imm_pcrel"); - IMM("SSECC"); - + // all I + PCR("i32imm_pcrel"); + PCR("i64i32imm_pcrel"); PCR("brtarget8"); PCR("offset8"); PCR("offset16"); @@ -332,7 +365,8 @@ static int X86FlagFromOpName(FlagsConstantEmitter *flags, #undef LEA #undef IMM #undef PCR -#undef ADDFLAG + +#undef SET /// X86PopulateOperands - Handles all the operands in an X86 instruction, adding /// the appropriate flags to their descriptors @@ -340,7 +374,7 @@ static int X86FlagFromOpName(FlagsConstantEmitter *flags, /// @operandFlags - A reference the array of operand flag objects /// @inst - The instruction to use as a source of information static void X86PopulateOperands( - FlagsConstantEmitter *(&operandFlags)[MAX_OPERANDS], + LiteralConstantEmitter *(&operandTypes)[EDIS_MAX_OPERANDS], const CodeGenInstruction &inst) { if (!inst.TheDef->isSubClassOf("X86Inst")) return; @@ -353,7 +387,7 @@ static void X86PopulateOperands( inst.OperandList[index]; Record &rec = *operandInfo.Rec; - if (X86FlagFromOpName(operandFlags[index], rec.getName())) { + if (X86TypeFromOpName(operandTypes[index], rec.getName())) { errs() << "Operand type: " << rec.getName().c_str() << "\n"; errs() << "Operand name: " << operandInfo.Name.c_str() << "\n"; errs() << "Instruction mame: " << inst.TheDef->getName().c_str() << "\n"; @@ -369,10 +403,11 @@ static void X86PopulateOperands( /// between names and operand indices /// @opName - The name of the operand /// @flag - The name of the flag to add -static inline void decorate1(FlagsConstantEmitter *(&operandFlags)[MAX_OPERANDS], - const CodeGenInstruction &inst, - const char *opName, - const char *opFlag) { +static inline void decorate1( + FlagsConstantEmitter *(&operandFlags)[EDIS_MAX_OPERANDS], + const CodeGenInstruction &inst, + const char *opName, + const char *opFlag) { unsigned opIndex; opIndex = inst.getOperandNamed(std::string(opName)); @@ -382,78 +417,70 @@ static inline void decorate1(FlagsConstantEmitter *(&operandFlags)[MAX_OPERANDS] #define DECORATE1(opName, opFlag) decorate1(operandFlags, inst, opName, opFlag) -#define MOV(source, target) { \ - instFlags.addEntry("kInstructionFlagMove"); \ - DECORATE1(source, "kOperandFlagSource"); \ - DECORATE1(target, "kOperandFlagTarget"); \ +#define MOV(source, target) { \ + instType.set("kInstructionTypeMove"); \ + DECORATE1(source, "kOperandFlagSource"); \ + DECORATE1(target, "kOperandFlagTarget"); \ } -#define BRANCH(target) { \ - instFlags.addEntry("kInstructionFlagBranch"); \ - DECORATE1(target, "kOperandFlagTarget"); \ +#define BRANCH(target) { \ + instType.set("kInstructionTypeBranch"); \ + DECORATE1(target, "kOperandFlagTarget"); \ } -#define PUSH(source) { \ - instFlags.addEntry("kInstructionFlagPush"); \ - DECORATE1(source, "kOperandFlagSource"); \ +#define PUSH(source) { \ + instType.set("kInstructionTypePush"); \ + DECORATE1(source, "kOperandFlagSource"); \ } -#define POP(target) { \ - instFlags.addEntry("kInstructionFlagPop"); \ - DECORATE1(target, "kOperandFlagTarget"); \ +#define POP(target) { \ + instType.set("kInstructionTypePop"); \ + DECORATE1(target, "kOperandFlagTarget"); \ } -#define CALL(target) { \ - instFlags.addEntry("kInstructionFlagCall"); \ - DECORATE1(target, "kOperandFlagTarget"); \ +#define CALL(target) { \ + instType.set("kInstructionTypeCall"); \ + DECORATE1(target, "kOperandFlagTarget"); \ } -#define RETURN() { \ - instFlags.addEntry("kInstructionFlagReturn"); \ +#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 /// -/// @arg instFlags - A reference to the flags for the instruction as a whole +/// @arg instType - A reference to the type for the instruction as a whole /// @arg operandFlags - A reference to the array of operand flag object pointers /// @arg inst - A reference to the original instruction -static void X86ExtractSemantics(FlagsConstantEmitter &instFlags, - FlagsConstantEmitter *(&operandFlags)[MAX_OPERANDS], - const CodeGenInstruction &inst) { +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) { + } else if (name.find("MASK") != name.npos) { // ignore (this is a masking move) - } - else if (name.find("r0") != name.npos) { + } else if (name.find("r0") != name.npos) { // ignore (this is a pseudoinstruction) - } - else if (name.find("PS") != name.npos || + } 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) { + } else if (name.find("MOVS") != name.npos) { // ignore (this is a string move) - } - else if (name.find("_F") != name.npos) { + } else if (name.find("_F") != name.npos) { // TODO handle _F moves to ST(0) - } - else if (name.find("a") != name.npos) { + } else if (name.find("a") != name.npos) { // TODO handle moves to/from %ax - } - else if (name.find("CMOV") != name.npos) { + } else if (name.find("CMOV") != name.npos) { MOV("src2", "dst"); - } - else if (name.find("PC") != name.npos) { + } else if (name.find("PC") != name.npos) { MOV("label", "reg") - } - else { + } else { MOV("src", "dst"); } } @@ -462,8 +489,7 @@ static void X86ExtractSemantics(FlagsConstantEmitter &instFlags, name.find("J") == 0) { if (name.find("FAR") != name.npos && name.find("i") != name.npos) { BRANCH("off"); - } - else { + } else { BRANCH("dst"); } } @@ -471,19 +497,15 @@ static void X86ExtractSemantics(FlagsConstantEmitter &instFlags, if (name.find("PUSH") != name.npos) { if (name.find("FS") != name.npos || name.find("GS") != name.npos) { - instFlags.addEntry("kInstructionFlagPush"); + instType.set("kInstructionTypePush"); // TODO add support for fixed operands - } - else if (name.find("F") != name.npos) { + } else if (name.find("F") != name.npos) { // ignore (this pushes onto the FP stack) - } - else if (name[name.length() - 1] == 'm') { + } else if (name[name.length() - 1] == 'm') { PUSH("src"); - } - else if (name.find("i") != name.npos) { + } else if (name.find("i") != name.npos) { PUSH("imm"); - } - else { + } else { PUSH("reg"); } } @@ -491,19 +513,15 @@ static void X86ExtractSemantics(FlagsConstantEmitter &instFlags, if (name.find("POP") != name.npos) { if (name.find("POPCNT") != name.npos) { // ignore (not a real pop) - } - else if (name.find("FS") != name.npos || + } else if (name.find("FS") != name.npos || name.find("GS") != name.npos) { - instFlags.addEntry("kInstructionFlagPop"); + instType.set("kInstructionTypePop"); // TODO add support for fixed operands - } - else if (name.find("F") != name.npos) { + } else if (name.find("F") != name.npos) { // ignore (this pops from the FP stack) - } - else if (name[name.length() - 1] == 'm') { + } else if (name[name.length() - 1] == 'm') { POP("dst"); - } - else { + } else { POP("reg"); } } @@ -511,17 +529,13 @@ static void X86ExtractSemantics(FlagsConstantEmitter &instFlags, if (name.find("CALL") != name.npos) { if (name.find("ADJ") != name.npos) { // ignore (not a call) - } - else if (name.find("SYSCALL") != name.npos) { + } else if (name.find("SYSCALL") != name.npos) { // ignore (doesn't go anywhere we know about) - } - else if (name.find("VMCALL") != name.npos) { + } else if (name.find("VMCALL") != name.npos) { // ignore (rather different semantics than a regular call) - } - else if (name.find("FAR") != name.npos && name.find("i") != name.npos) { + } else if (name.find("FAR") != name.npos && name.find("i") != name.npos) { CALL("off"); - } - else { + } else { CALL("dst"); } } @@ -538,9 +552,182 @@ static void X86ExtractSemantics(FlagsConstantEmitter &instFlags, #undef CALL #undef RETURN -#undef COND_DECORATE_2 -#undef COND_DECORATE_1 -#undef DECORATE1 +///////////////////////////////////////////////////// +// 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 +/// +/// @arg type - The type object to set +/// @arg name - The name of the operand +static int ARMFlagFromOpName(LiteralConstantEmitter *type, + const std::string &name) { + REG("GPR"); + REG("cc_out"); + REG("s_cc_out"); + REG("tGPR"); + REG("DPR"); + REG("SPR"); + REG("QPR"); + REG("DPR_VFP2"); + REG("DPR_8"); + + IMM("i32imm"); + IMM("bf_inv_mask_imm"); + IMM("jtblock_operand"); + IMM("nohash_imm"); + IMM("cpinst_operand"); + IMM("cps_opt"); + IMM("vfp_f64imm"); + IMM("vfp_f32imm"); + IMM("msr_mask"); + IMM("neg_zero"); + IMM("imm0_31"); + IMM("h8imm"); + IMM("h16imm"); + IMM("h32imm"); + IMM("h64imm"); + IMM("imm0_4095"); + IMM("jt2block_operand"); + IMM("t_imm_s4"); + IMM("pclabel"); + + MISC("brtarget", "kOperandTypeARMBranchTarget"); // ? + MISC("so_reg", "kOperandTypeARMSoReg"); // R, R, I + MISC("t2_so_reg", "kOperandTypeThumb2SoReg"); // R, I + MISC("so_imm", "kOperandTypeARMSoImm"); // I + MISC("t2_so_imm", "kOperandTypeThumb2SoImm"); // I + MISC("so_imm2part", "kOperandTypeARMSoImm2Part"); // I + MISC("pred", "kOperandTypeARMPredicate"); // I, R + MISC("it_pred", "kOperandTypeARMPredicate"); // I + MISC("addrmode2", "kOperandTypeARMAddrMode2"); // R, R, I + MISC("am2offset", "kOperandTypeARMAddrMode2Offset"); // R, I + MISC("addrmode3", "kOperandTypeARMAddrMode3"); // R, R, I + MISC("am3offset", "kOperandTypeARMAddrMode3Offset"); // R, I + MISC("addrmode4", "kOperandTypeARMAddrMode4"); // R, I + MISC("addrmode5", "kOperandTypeARMAddrMode5"); // R, I + MISC("addrmode6", "kOperandTypeARMAddrMode6"); // R, R, I, I + MISC("am6offset", "kOperandTypeARMAddrMode6Offset"); // R, I, I + MISC("addrmodepc", "kOperandTypeARMAddrModePC"); // R, I + MISC("reglist", "kOperandTypeARMRegisterList"); // I, R, ... + MISC("it_mask", "kOperandTypeThumbITMask"); // I + MISC("t2addrmode_imm8", "kOperandTypeThumb2AddrModeImm8"); // R, I + MISC("t2am_imm8_offset", "kOperandTypeThumb2AddrModeImm8Offset");//I + MISC("t2addrmode_imm12", "kOperandTypeThumb2AddrModeImm12"); // R, I + MISC("t2addrmode_so_reg", "kOperandTypeThumb2AddrModeSoReg"); // R, R, I + MISC("t2addrmode_imm8s4", "kOperandTypeThumb2AddrModeImm8s4"); // R, I + MISC("t2am_imm8s4_offset", "kOperandTypeThumb2AddrModeImm8s4Offset"); + // R, I + MISC("tb_addrmode", "kOperandTypeARMTBAddrMode"); // I + MISC("t_addrmode_s1", "kOperandTypeThumbAddrModeS1"); // R, I, R + MISC("t_addrmode_s2", "kOperandTypeThumbAddrModeS2"); // R, I, R + MISC("t_addrmode_s4", "kOperandTypeThumbAddrModeS4"); // R, I, R + MISC("t_addrmode_rr", "kOperandTypeThumbAddrModeRR"); // R, R + MISC("t_addrmode_sp", "kOperandTypeThumbAddrModeSP"); // R, I + + return 1; +} + +#undef SOREG +#undef SOIMM +#undef PRED +#undef REG +#undef MEM +#undef LEA +#undef IMM +#undef PCR + +#undef SET + +/// ARMPopulateOperands - Handles all the operands in an ARM instruction, adding +/// the appropriate flags to their descriptors +/// +/// @operandFlags - A reference the array of operand flag objects +/// @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.OperandList.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 CodeGenInstruction::OperandInfo &operandInfo = + inst.OperandList[index]; + Record &rec = *operandInfo.Rec; + + if (ARMFlagFromOpName(operandTypes[index], rec.getName())) { + errs() << "Operand type: " << rec.getName() << '\n'; + errs() << "Operand name: " << operandInfo.Name << '\n'; + errs() << "Instruction mame: " << inst.TheDef->getName() << '\n'; + llvm_unreachable("Unhandled type"); + } + } +} + +#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 +/// +/// @arg instType - A reference to the type for the instruction as a whole +/// @arg operandTypes - A reference to the array of operand type object pointers +/// @arg operandFlags - A reference to the array of operand flag object pointers +/// @arg 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.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 @@ -561,19 +748,29 @@ static void populateInstInfo(CompoundConstantEmitter &infoArray, CompoundConstantEmitter *infoStruct = new CompoundConstantEmitter; infoArray.addEntry(infoStruct); - FlagsConstantEmitter *instFlags = new FlagsConstantEmitter; - infoStruct->addEntry(instFlags); + LiteralConstantEmitter *instType = new LiteralConstantEmitter; + infoStruct->addEntry(instType); LiteralConstantEmitter *numOperandsEmitter = new LiteralConstantEmitter(inst.OperandList.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[MAX_OPERANDS]; + FlagsConstantEmitter *operandFlags[EDIS_MAX_OPERANDS]; - for (unsigned operandIndex = 0; operandIndex < MAX_OPERANDS; ++operandIndex) { + 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]); } @@ -581,32 +778,99 @@ static void populateInstInfo(CompoundConstantEmitter &infoArray, unsigned numSyntaxes = 0; if (target.getName() == "X86") { - X86PopulateOperands(operandFlags, inst); - X86ExtractSemantics(*instFlags, operandFlags, inst); + 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; - CompoundConstantEmitter *operandOrderArray = new CompoundConstantEmitter; infoStruct->addEntry(operandOrderArray); - for (unsigned syntaxIndex = 0; syntaxIndex < MAX_SYNTAXES; ++syntaxIndex) { - CompoundConstantEmitter *operandOrder = new CompoundConstantEmitter; + 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); } - else { - for (unsigned operandIndex = 0; - operandIndex < MAX_OPERANDS; - ++operandIndex) { - operandOrder->addEntry(new LiteralConstantEmitter("-1")); - } - } } + + 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("kOperandTypeARMSoReg"); + operandTypes.addEntry("kOperandTypeARMSoImm"); + operandTypes.addEntry("kOperandTypeARMSoImm2Part"); + operandTypes.addEntry("kOperandTypeARMPredicate"); + operandTypes.addEntry("kOperandTypeARMAddrMode2"); + operandTypes.addEntry("kOperandTypeARMAddrMode2Offset"); + operandTypes.addEntry("kOperandTypeARMAddrMode3"); + operandTypes.addEntry("kOperandTypeARMAddrMode3Offset"); + operandTypes.addEntry("kOperandTypeARMAddrMode4"); + operandTypes.addEntry("kOperandTypeARMAddrMode5"); + operandTypes.addEntry("kOperandTypeARMAddrMode6"); + operandTypes.addEntry("kOperandTypeARMAddrMode6Offset"); + operandTypes.addEntry("kOperandTypeARMAddrModePC"); + operandTypes.addEntry("kOperandTypeARMRegisterList"); + operandTypes.addEntry("kOperandTypeARMTBAddrMode"); + operandTypes.addEntry("kOperandTypeThumbITMask"); + operandTypes.addEntry("kOperandTypeThumbAddrModeS1"); + operandTypes.addEntry("kOperandTypeThumbAddrModeS2"); + operandTypes.addEntry("kOperandTypeThumbAddrModeS4"); + operandTypes.addEntry("kOperandTypeThumbAddrModeRR"); + operandTypes.addEntry("kOperandTypeThumbAddrModeSP"); + 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"; +} + void EDEmitter::run(raw_ostream &o) { unsigned int i = 0; @@ -615,9 +879,15 @@ void EDEmitter::run(raw_ostream &o) { populateInstInfo(infoArray, target); - o << "InstInfo instInfo" << target.getName().c_str() << "[] = "; + emitCommonEnums(o, i); + + o << "namespace {\n"; + + o << "llvm::EDInstInfo instInfo" << target.getName().c_str() << "[] = "; infoArray.emit(o, i); o << ";" << "\n"; + + o << "}\n"; } void EDEmitter::runHeader(raw_ostream &o) { @@ -626,43 +896,13 @@ void EDEmitter::runHeader(raw_ostream &o) { o << "#ifndef EDInfo_" << "\n"; o << "#define EDInfo_" << "\n"; o << "\n"; - o << "#include <inttypes.h>" << "\n"; - o << "\n"; - o << "#define MAX_OPERANDS " << format("%d", MAX_OPERANDS) << "\n"; - o << "#define MAX_SYNTAXES " << format("%d", MAX_SYNTAXES) << "\n"; + o << "#define EDIS_MAX_OPERANDS " << format("%d", EDIS_MAX_OPERANDS) << "\n"; + o << "#define EDIS_MAX_SYNTAXES " << format("%d", EDIS_MAX_SYNTAXES) << "\n"; o << "\n"; unsigned int i = 0; - EnumEmitter operandFlags("OperandFlags"); - operandFlags.addEntry("kOperandFlagImmediate"); - operandFlags.addEntry("kOperandFlagRegister"); - operandFlags.addEntry("kOperandFlagMemory"); - operandFlags.addEntry("kOperandFlagEffectiveAddress"); - operandFlags.addEntry("kOperandFlagPCRelative"); - operandFlags.addEntry("kOperandFlagSource"); - operandFlags.addEntry("kOperandFlagTarget"); - operandFlags.emitAsFlags(o, i); - - o << "\n"; - - EnumEmitter instructionFlags("InstructionFlags"); - instructionFlags.addEntry("kInstructionFlagMove"); - instructionFlags.addEntry("kInstructionFlagBranch"); - instructionFlags.addEntry("kInstructionFlagPush"); - instructionFlags.addEntry("kInstructionFlagPop"); - instructionFlags.addEntry("kInstructionFlagCall"); - instructionFlags.addEntry("kInstructionFlagReturn"); - instructionFlags.emitAsFlags(o, i); - - o << "\n"; - - StructEmitter instInfo("InstInfo"); - instInfo.addMember("uint32_t", "instructionFlags"); - instInfo.addMember("uint8_t", "numOperands"); - instInfo.addMember("uint8_t", "operandFlags[MAX_OPERANDS]"); - instInfo.addMember("const char", "operandOrders[MAX_SYNTAXES][MAX_OPERANDS]"); - instInfo.emit(o, i); + emitCommonEnums(o, i); o << "\n"; o << "#endif" << "\n"; diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h index 55c1a80..576d626 100644 --- a/utils/TableGen/Record.h +++ b/utils/TableGen/Record.h @@ -609,6 +609,11 @@ public: if (!getBit(i)->isComplete()) return false; return true; } + bool allInComplete() const { + for (unsigned i = 0; i != getNumBits(); ++i) + if (getBit(i)->isComplete()) return false; + return true; + } virtual std::string getAsString() const; virtual Init *resolveReferences(Record &R, const RecordVal *RV); diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index 9ac652f..b04eaf8 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -203,7 +203,8 @@ unsigned SubtargetEmitter::CollectAllItinClasses(raw_ostream &OS, // data initialization for the specified itinerary. N is the number // of stages. // -void SubtargetEmitter::FormItineraryStageString(Record *ItinData, +void SubtargetEmitter::FormItineraryStageString(const std::string &Name, + Record *ItinData, std::string &ItinString, unsigned &NStages) { // Get states list @@ -216,7 +217,7 @@ void SubtargetEmitter::FormItineraryStageString(Record *ItinData, // Next stage const Record *Stage = StageList[i]; - // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc } + // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind } int Cycles = Stage->getValueAsInt("Cycles"); ItinString += " { " + itostr(Cycles) + ", "; @@ -226,13 +227,16 @@ void SubtargetEmitter::FormItineraryStageString(Record *ItinData, // For each unit for (unsigned j = 0, M = UnitList.size(); j < M;) { // Add name and bitwise or - ItinString += UnitList[j]->getName(); + ItinString += Name + "FU::" + UnitList[j]->getName(); if (++j < M) ItinString += " | "; } int TimeInc = Stage->getValueAsInt("TimeInc"); ItinString += ", " + itostr(TimeInc); + int Kind = Stage->getValueAsInt("Kind"); + ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind); + // Close off stage ItinString += " }"; if (++i < N) ItinString += ", "; @@ -276,9 +280,29 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, // If just no itinerary then don't bother if (ProcItinList.size() < 2) return; + // Emit functional units for all the itineraries. + for (unsigned i = 0, N = ProcItinList.size(); i < N; ++i) { + // Next record + Record *Proc = ProcItinList[i]; + + std::vector<Record*> FUs = Proc->getValueAsListOfDefs("FU"); + if (FUs.empty()) + continue; + + const std::string &Name = Proc->getName(); + OS << "\n// Functional units for itineraries \"" << Name << "\"\n" + << "namespace " << Name << "FU {\n"; + + for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j) + OS << " const unsigned " << FUs[j]->getName() + << " = 1 << " << j << ";\n"; + + OS << "}\n"; + } + // Begin stages table - std::string StageTable = "static const llvm::InstrStage Stages[] = {\n"; - StageTable += " { 0, 0, 0 }, // No itinerary\n"; + std::string StageTable = "\nstatic const llvm::InstrStage Stages[] = {\n"; + StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n"; // Begin operand cycle table std::string OperandCycleTable = "static const unsigned OperandCycles[] = {\n"; @@ -312,7 +336,7 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, // Get string and stage count std::string ItinStageString; unsigned NStages; - FormItineraryStageString(ItinData, ItinStageString, NStages); + FormItineraryStageString(Name, ItinData, ItinStageString, NStages); // Get string and operand cycle count std::string ItinOperandCycleString; @@ -367,7 +391,7 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, } // Closing stage - StageTable += " { 0, 0, 0 } // End itinerary\n"; + StageTable += " { 0, 0, 0, llvm::InstrStage::Required } // End itinerary\n"; StageTable += "};\n"; // Closing operand cycles @@ -564,9 +588,9 @@ void SubtargetEmitter::run(raw_ostream &OS) { OS << "#include \"llvm/Support/raw_ostream.h\"\n"; OS << "#include \"llvm/Target/SubtargetFeature.h\"\n"; OS << "#include \"llvm/Target/TargetInstrItineraries.h\"\n\n"; - - Enumeration(OS, "FuncUnit", true); - OS<<"\n"; + +// Enumeration(OS, "FuncUnit", true); +// OS<<"\n"; // Enumeration(OS, "InstrItinClass", false); // OS<<"\n"; Enumeration(OS, "SubtargetFeature", true); diff --git a/utils/TableGen/SubtargetEmitter.h b/utils/TableGen/SubtargetEmitter.h index 1d7088f..f43a443 100644 --- a/utils/TableGen/SubtargetEmitter.h +++ b/utils/TableGen/SubtargetEmitter.h @@ -34,7 +34,8 @@ class SubtargetEmitter : public TableGenBackend { void CPUKeyValues(raw_ostream &OS); unsigned CollectAllItinClasses(raw_ostream &OS, std::map<std::string, unsigned> &ItinClassesMap); - void FormItineraryStageString(Record *ItinData, std::string &ItinString, + void FormItineraryStageString(const std::string &Names, + Record *ItinData, std::string &ItinString, unsigned &NStages); void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString, unsigned &NOperandCycles); diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp index be07031..2176224 100644 --- a/utils/TableGen/X86DisassemblerTables.cpp +++ b/utils/TableGen/X86DisassemblerTables.cpp @@ -161,7 +161,7 @@ void DisassemblerTables::emitOneID(raw_ostream &o, /// @param i - The indentation level for that output stream. static void emitEmptyTable(raw_ostream &o, uint32_t &i) { - o.indent(i * 2) << "InstrUID modRMEmptyTable[1] = { 0 };" << "\n"; + o.indent(i * 2) << "static InstrUID modRMEmptyTable[1] = { 0 };" << "\n"; o << "\n"; } @@ -275,7 +275,7 @@ void DisassemblerTables::emitModRMDecision(raw_ostream &o1, return; } - o1.indent(i1) << "InstrUID modRMTable" << thisTableNumber; + o1.indent(i1) << "static InstrUID modRMTable" << thisTableNumber; switch (dt) { default: diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index d71252c..b15db2f 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -820,7 +820,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("i128mem", TYPE_M128) TYPE("i64i32imm_pcrel", TYPE_REL64) TYPE("i32imm_pcrel", TYPE_REL32) - TYPE("SSECC", TYPE_IMM8) + TYPE("SSECC", TYPE_IMM3) TYPE("brtarget", TYPE_RELv) TYPE("brtarget8", TYPE_REL8) TYPE("f80mem", TYPE_M80FP) diff --git a/utils/buildit/GNUmakefile b/utils/buildit/GNUmakefile index 8d8504c..e0568d2 100644 --- a/utils/buildit/GNUmakefile +++ b/utils/buildit/GNUmakefile @@ -46,6 +46,9 @@ else LLVM_OPTIMIZED := yes endif +# Default to not install libLTO.dylib. +INSTALL_LIBLTO := no + ifndef RC_ProjectSourceVersion RC_ProjectSourceVersion = 9999 endif @@ -59,10 +62,9 @@ install: $(OBJROOT) $(SYMROOT) $(DSTROOT) cd $(OBJROOT) && \ $(SRC)/utils/buildit/build_llvm "$(RC_ARCHS)" "$(TARGETS)" \ $(SRC) $(PREFIX) $(DSTROOT) $(SYMROOT) \ - $(ENABLE_ASSERTIONS) $(LLVM_OPTIMIZED) \ + $(ENABLE_ASSERTIONS) $(LLVM_OPTIMIZED) $(INSTALL_LIBLTO) \ $(RC_ProjectSourceVersion) $(RC_ProjectSourceSubversion) - # installhdrs does nothing, because the headers aren't useful until # the compiler is installed. installhdrs: diff --git a/utils/buildit/build_llvm b/utils/buildit/build_llvm index 33f471d..78cc655 100755 --- a/utils/buildit/build_llvm +++ b/utils/buildit/build_llvm @@ -9,12 +9,12 @@ set -x # The first parameter is a space-separated list of the architectures the # compilers will run on. For instance, "ppc i386". If the current machine # isn't in the list, it will (effectively) be added. -# FIXME: HOSTS is not used in this script. Use it or Remove it. HOSTS="$1" # The second parameter is a space-separated list of the architectures the # compilers will generate code for. If the current machine isn't in the list, a # compiler for it will get built anyway, but won't be installed. +# FIXME: The list of targets is currently hard-coded and TARGETS is not used. TARGETS="$2" # The third parameter is the path to the compiler sources. There should be a @@ -42,11 +42,15 @@ LLVM_ASSERTIONS="$7" # build. LLVM_OPTIMIZED="$8" -# The nineth parameter is the version number of the submission, e.g. 1007. -LLVM_SUBMIT_VERSION="$9" +# The ninth parameter is a yes/no that indicates whether libLTO.dylib +# should be installed. +INSTALL_LIBLTO="$9" -# The tenth parameter is the subversion number of the submission, e.g. 03. -LLVM_SUBMIT_SUBVERSION="${10}" +# The tenth parameter is the version number of the submission, e.g. 1007. +LLVM_SUBMIT_VERSION="${10}" + +# The eleventh parameter is the subversion number of the submission, e.g. 03. +LLVM_SUBMIT_SUBVERSION="${11}" # The current working directory is where the build will happen. It may already # contain a partial result of an interrupted build, in which case this script @@ -56,11 +60,6 @@ DIR=`pwd` DARWIN_VERS=`uname -r | sed 's/\..*//'` echo DARWIN_VERS = $DARWIN_VERS -if [ "x$RC_ProjectName" = "xllvmCore_Embedded" ]; then - DEST_DIR="$DEST_DIR/Developer/Platforms/iPhoneOS.platform" - mkdir -p "$DEST_DIR" -fi - DEVELOPER_DIR="${DEVELOPER_DIR-Developer}" if [ "x$RC_ProjectName" = "xllvmCore_EmbeddedHosted" ]; then DT_HOME="$DEST_DIR/usr" @@ -200,7 +199,7 @@ if [ "x$MAJ_VER" != "x4" -o "x$MIN_VER" != "x0" ]; then JOBS_FLAG="-j $SYSCTL" fi -make $JOBS_FLAG $OPTIMIZE_OPTS UNIVERSAL=1 UNIVERSAL_ARCH="$TARGETS" \ +make $JOBS_FLAG $OPTIMIZE_OPTS UNIVERSAL=1 UNIVERSAL_ARCH="$HOSTS" \ UNIVERSAL_SDK_PATH=$HOST_SDKROOT \ NO_RUNTIME_LIBS=1 \ DISABLE_EDIS=1 \ @@ -226,7 +225,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="$TARGETS" \ +make $LOCAL_MAKEFLAGS $OPTIMIZE_OPTS UNIVERSAL=1 UNIVERSAL_ARCH="$HOSTS" \ NO_RUNTIME_LIBS=1 \ DISABLE_EDIS=1 \ LLVM_SUBMIT_VERSION=$LLVM_SUBMIT_VERSION \ @@ -276,9 +275,11 @@ else fi cd $DEST_DIR$DEST_ROOT -mkdir -p $DT_HOME/lib -mv lib/libLTO.dylib $DT_HOME/lib/libLTO.dylib -strip -S $DT_HOME/lib/libLTO.dylib +if [ "$INSTALL_LIBLTO" == yes ]; then + mkdir -p $DT_HOME/lib + mv lib/libLTO.dylib $DT_HOME/lib/libLTO.dylib + strip -S $DT_HOME/lib/libLTO.dylib +fi rm -f lib/libLTO.a lib/libLTO.la # The Hello dylib is an example of how to build a pass. No need to install it. @@ -343,10 +344,11 @@ find $DEST_DIR -name html.tar.gz -exec rm {} \; ################################################################################ # symlinks so that B&I can find things -cd $DEST_DIR -mkdir -p ./usr/lib/ -cd usr/lib -ln -s ../../$DEVELOPER_DIR/usr/lib/libLTO.dylib ./libLTO.dylib +if [ "$INSTALL_LIBLTO" == yes ]; then + mkdir -p $DEST_DIR/usr/lib/ + cd $DEST_DIR/usr/lib && \ + ln -s ../../$DEVELOPER_DIR/usr/lib/libLTO.dylib ./libLTO.dylib +fi ################################################################################ # w00t! Done! diff --git a/utils/fpcmp/fpcmp.cpp b/utils/fpcmp/fpcmp.cpp index 66d8ab1..5f6b5e8 100644 --- a/utils/fpcmp/fpcmp.cpp +++ b/utils/fpcmp/fpcmp.cpp @@ -14,7 +14,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileUtilities.h" -#include <iostream> +#include "llvm/Support/raw_ostream.h" using namespace llvm; namespace { @@ -37,7 +37,7 @@ int main(int argc, char **argv) { sys::PathWithStatus(File2), AbsTolerance, RelTolerance, &ErrorMsg); if (!ErrorMsg.empty()) - std::cerr << argv[0] << ": " << ErrorMsg << "\n"; + errs() << argv[0] << ": " << ErrorMsg << "\n"; return DF; } diff --git a/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/pct-S.ll b/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/pct-S.ll index 4e8a582..3ff3633 100644 --- a/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/pct-S.ll +++ b/utils/lit/lit/ExampleTests/LLVM.OutOfTree/src/test/Foo/pct-S.ll @@ -1 +1 @@ -; RUN: grep "hi" %S/data.txt
\ No newline at end of file +; RUN: grep "hi" %S/data.txt diff --git a/utils/lit/lit/TestFormats.py b/utils/lit/lit/TestFormats.py index 7ab9bb6..5e1a811 100644 --- a/utils/lit/lit/TestFormats.py +++ b/utils/lit/lit/TestFormats.py @@ -129,14 +129,20 @@ class OneCommandPerFileTest: self.command = [command] else: self.command = list(command) - self.dir = str(dir) + if dir is not None: + dir = str(dir) + self.dir = dir self.recursive = bool(recursive) self.pattern = re.compile(pattern) self.useTempInput = useTempInput def getTestsInDirectory(self, testSuite, path_in_suite, litConfig, localConfig): - for dirname,subdirs,filenames in os.walk(self.dir): + dir = self.dir + if dir is None: + dir = testSuite.getSourcePath(path_in_suite) + + for dirname,subdirs,filenames in os.walk(dir): if not self.recursive: subdirs[:] = [] @@ -151,7 +157,7 @@ class OneCommandPerFileTest: continue path = os.path.join(dirname,filename) - suffix = path[len(self.dir):] + suffix = path[len(dir):] if suffix.startswith(os.sep): suffix = suffix[1:] test = Test.Test(testSuite, diff --git a/utils/llvm.grm b/utils/llvm.grm index d391e2a..fa0dcd1 100644 --- a/utils/llvm.grm +++ b/utils/llvm.grm @@ -398,7 +398,7 @@ OptVolatile ::= - volatile | _ ; OptExact ::= - exact | _ ; OptNSW ::= - nsw | _ ; OptNUW ::= - nuw | _ ; -OptNW ::= OptNUW OptNSW ; +OptNW ::= OptNUW OptNSW | OptNSW OptNUW ; OptInBounds ::= - inbounds | _ ; MemoryInst ::= malloc Types OptCAlign diff --git a/utils/unittest/googletest/gtest-filepath.cc b/utils/unittest/googletest/gtest-filepath.cc index 640c27c..493ba0b 100644 --- a/utils/unittest/googletest/gtest-filepath.cc +++ b/utils/unittest/googletest/gtest-filepath.cc @@ -167,7 +167,7 @@ bool FilePath::FileOrDirectoryExists() const { return _stat(pathname_.c_str(), &file_stat) == 0; #endif // _WIN32_WCE #else - struct stat file_stat = {}; + struct stat file_stat; return stat(pathname_.c_str(), &file_stat) == 0; #endif // GTEST_OS_WINDOWS } @@ -195,7 +195,7 @@ bool FilePath::DirectoryExists() const { (_S_IFDIR & file_stat.st_mode) != 0; #endif // _WIN32_WCE #else - struct stat file_stat = {}; + struct stat file_stat; result = stat(pathname_.c_str(), &file_stat) == 0 && S_ISDIR(file_stat.st_mode); #endif // GTEST_OS_WINDOWS diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h b/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h index f98af0b..d4c7a39 100644 --- a/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h +++ b/utils/unittest/googletest/include/gtest/internal/gtest-linked_ptr.h @@ -176,6 +176,7 @@ class linked_ptr { // Sole ownership by this linked_ptr object is required. T* release() { bool last = link_.depart(); + (void) last; assert(last); T* v = value_; value_ = NULL; diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-port.h b/utils/unittest/googletest/include/gtest/internal/gtest-port.h index 3e49993..20a95c9 100644 --- a/utils/unittest/googletest/include/gtest/internal/gtest-port.h +++ b/utils/unittest/googletest/include/gtest/internal/gtest-port.h @@ -227,9 +227,10 @@ // TODO(wan@google.com): uses autoconf to detect whether ::std::wstring // is available. -#if defined(GTEST_OS_CYGWIN) || defined(GTEST_OS_SOLARIS) || defined(GTEST_OS_HAIKU) +#if defined(GTEST_OS_CYGWIN) || defined(GTEST_OS_SOLARIS) || defined(GTEST_OS_HAIKU) || defined(_MINIX) // At least some versions of cygwin don't support ::std::wstring. // Solaris' libc++ doesn't support it either. +// Minix currently doesn't support it either. #define GTEST_HAS_STD_WSTRING 0 #else #define GTEST_HAS_STD_WSTRING GTEST_HAS_STD_STRING |