diff options
author | Alexander Kornienko <alexfh@google.com> | 2013-03-14 10:51:38 +0000 |
---|---|---|
committer | Alexander Kornienko <alexfh@google.com> | 2013-03-14 10:51:38 +0000 |
commit | 647735c781c5b37061ee03d6e9e6c7dda92218e2 (patch) | |
tree | 5a5e56606d41060263048b5a5586b3d2380898ba /utils/TableGen | |
parent | 6aed25d93d1cfcde5809a73ffa7dc1b0d6396f66 (diff) | |
parent | f635ef401786c84df32090251a8cf45981ecca33 (diff) |
Updating branches/google/stable to r176857
git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/google/stable@177040 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils/TableGen')
-rw-r--r-- | utils/TableGen/AsmMatcherEmitter.cpp | 34 | ||||
-rw-r--r-- | utils/TableGen/AsmWriterEmitter.cpp | 19 | ||||
-rw-r--r-- | utils/TableGen/CMakeLists.txt | 1 | ||||
-rw-r--r-- | utils/TableGen/CodeGenMapTable.cpp | 9 | ||||
-rw-r--r-- | utils/TableGen/CodeGenRegisters.cpp | 16 | ||||
-rw-r--r-- | utils/TableGen/CodeGenSchedule.cpp | 16 | ||||
-rw-r--r-- | utils/TableGen/CodeGenSchedule.h | 15 | ||||
-rw-r--r-- | utils/TableGen/CodeGenTarget.cpp | 6 | ||||
-rw-r--r-- | utils/TableGen/DAGISelMatcherEmitter.cpp | 2 | ||||
-rw-r--r-- | utils/TableGen/DisassemblerEmitter.cpp | 5 | ||||
-rw-r--r-- | utils/TableGen/EDEmitter.cpp | 1012 | ||||
-rw-r--r-- | utils/TableGen/FixedLenDecoderEmitter.cpp | 2 | ||||
-rw-r--r-- | utils/TableGen/IntrinsicEmitter.cpp | 63 | ||||
-rw-r--r-- | utils/TableGen/OptParserEmitter.cpp | 5 | ||||
-rw-r--r-- | utils/TableGen/PseudoLoweringEmitter.cpp | 1 | ||||
-rw-r--r-- | utils/TableGen/RegisterInfoEmitter.cpp | 10 | ||||
-rw-r--r-- | utils/TableGen/SubtargetEmitter.cpp | 16 | ||||
-rw-r--r-- | utils/TableGen/TableGen.cpp | 6 | ||||
-rw-r--r-- | utils/TableGen/TableGenBackends.h | 1 | ||||
-rw-r--r-- | utils/TableGen/X86RecognizableInstr.cpp | 12 |
20 files changed, 159 insertions, 1092 deletions
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; |