diff options
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 mov |