summaryrefslogtreecommitdiffstats
path: root/utils/TableGen
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2014-02-11 20:01:10 -0800
committerStephen Hines <srhines@google.com>2014-02-11 20:01:10 -0800
commitce9904c6ea8fd669978a8eefb854b330eb9828ff (patch)
tree2418ee2e96ea220977c8fb74959192036ab5b133 /utils/TableGen
parentc27b10b198c1d9e9b51f2303994313ec2778edd7 (diff)
parentdbb832b83351cec97b025b61c26536ef50c3181c (diff)
downloadexternal_llvm-ce9904c6ea8fd669978a8eefb854b330eb9828ff.zip
external_llvm-ce9904c6ea8fd669978a8eefb854b330eb9828ff.tar.gz
external_llvm-ce9904c6ea8fd669978a8eefb854b330eb9828ff.tar.bz2
Merge remote-tracking branch 'upstream/release_34' into merge-20140211
Conflicts: lib/Linker/LinkModules.cpp lib/Support/Unix/Signals.inc Change-Id: Ia54f291fa5dc828052d2412736e8495c1282aa64
Diffstat (limited to 'utils/TableGen')
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp115
-rw-r--r--utils/TableGen/AsmWriterEmitter.cpp138
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp156
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.h6
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp17
-rw-r--r--utils/TableGen/CodeGenInstruction.h3
-rw-r--r--utils/TableGen/CodeGenMapTable.cpp1
-rw-r--r--utils/TableGen/CodeGenRegisters.cpp7
-rw-r--r--utils/TableGen/CodeGenSchedule.cpp6
-rw-r--r--utils/TableGen/CodeGenTarget.cpp7
-rw-r--r--utils/TableGen/DAGISelEmitter.cpp16
-rw-r--r--utils/TableGen/DAGISelMatcher.cpp6
-rw-r--r--utils/TableGen/DAGISelMatcher.h32
-rw-r--r--utils/TableGen/DAGISelMatcherEmitter.cpp15
-rw-r--r--utils/TableGen/DAGISelMatcherOpt.cpp6
-rw-r--r--utils/TableGen/FastISelEmitter.cpp82
-rw-r--r--utils/TableGen/FixedLenDecoderEmitter.cpp1
-rw-r--r--utils/TableGen/InstrInfoEmitter.cpp68
-rw-r--r--utils/TableGen/IntrinsicEmitter.cpp158
-rw-r--r--utils/TableGen/OptParserEmitter.cpp23
-rw-r--r--utils/TableGen/RegisterInfoEmitter.cpp20
-rw-r--r--utils/TableGen/SequenceToOffsetTable.h1
-rw-r--r--utils/TableGen/SetTheory.cpp49
-rw-r--r--utils/TableGen/StringToOffsetTable.h83
-rw-r--r--utils/TableGen/SubtargetEmitter.cpp5
-rw-r--r--utils/TableGen/TGValueTypes.cpp11
-rw-r--r--utils/TableGen/X86DisassemblerTables.cpp161
-rw-r--r--utils/TableGen/X86DisassemblerTables.h60
-rw-r--r--utils/TableGen/X86RecognizableInstr.cpp147
-rw-r--r--utils/TableGen/X86RecognizableInstr.h2
30 files changed, 820 insertions, 582 deletions
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index 468ce1c..de24cde 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -97,7 +97,6 @@
//===----------------------------------------------------------------------===//
#include "CodeGenTarget.h"
-#include "StringToOffsetTable.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/STLExtras.h"
@@ -110,8 +109,10 @@
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/StringMatcher.h"
+#include "llvm/TableGen/StringToOffsetTable.h"
#include "llvm/TableGen/TableGenBackend.h"
#include <cassert>
+#include <cctype>
#include <map>
#include <set>
#include <sstream>
@@ -125,6 +126,13 @@ namespace {
class AsmMatcherInfo;
struct SubtargetFeatureInfo;
+// Register sets are used as keys in some second-order sets TableGen creates
+// when generating its data structures. This means that the order of two
+// RegisterSets can be seen in the outputted AsmMatcher tables occasionally, and
+// can even affect compiler output (at least seen in diagnostics produced when
+// all matches fail). So we use a type that sorts them consistently.
+typedef std::set<Record*, LessRecordByID> RegisterSet;
+
class AsmMatcherEmitter {
RecordKeeper &Records;
public:
@@ -185,7 +193,7 @@ struct ClassInfo {
std::string ParserMethod;
/// For register classes, the records for all the registers in this class.
- std::set<Record*> Registers;
+ RegisterSet Registers;
/// For custom match classes, he diagnostic kind for when the predicate fails.
std::string DiagnosticType;
@@ -213,11 +221,11 @@ public:
if (!isRegisterClass() || !RHS.isRegisterClass())
return false;
- std::set<Record*> Tmp;
- std::insert_iterator< std::set<Record*> > II(Tmp, Tmp.begin());
+ RegisterSet Tmp;
+ std::insert_iterator<RegisterSet> II(Tmp, Tmp.begin());
std::set_intersection(Registers.begin(), Registers.end(),
RHS.Registers.begin(), RHS.Registers.end(),
- II);
+ II, LessRecordByID());
return !Tmp.empty();
}
@@ -430,6 +438,9 @@ struct MatchableInfo {
/// function.
std::string ConversionFnKind;
+ /// If this instruction is deprecated in some form.
+ bool HasDeprecation;
+
MatchableInfo(const CodeGenInstruction &CGI)
: AsmVariantID(0), TheDef(CGI.TheDef), DefRec(&CGI),
AsmString(CGI.AsmString) {
@@ -613,7 +624,7 @@ public:
RegisterClassesTy RegisterClasses;
/// Map of Predicate records to their subtarget information.
- std::map<Record*, SubtargetFeatureInfo*> SubtargetFeatures;
+ std::map<Record*, SubtargetFeatureInfo*, LessRecordByID> SubtargetFeatures;
/// Map of AsmOperandClass records to their class information.
std::map<Record*, ClassInfo*> AsmOperandClasses;
@@ -663,7 +674,7 @@ public:
/// given operand.
SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const {
assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!");
- std::map<Record*, SubtargetFeatureInfo*>::const_iterator I =
+ std::map<Record*, SubtargetFeatureInfo*, LessRecordByID>::const_iterator I =
SubtargetFeatures.find(Def);
return I == SubtargetFeatures.end() ? 0 : I->second;
}
@@ -779,6 +790,13 @@ void MatchableInfo::initialize(const AsmMatcherInfo &Info,
if (Record *Reg = AsmOperands[i].SingletonReg)
SingletonRegisters.insert(Reg);
}
+
+ const RecordVal *DepMask = TheDef->getValue("DeprecatedFeatureMask");
+ if (!DepMask)
+ DepMask = TheDef->getValue("ComplexDeprecationPredicate");
+
+ HasDeprecation =
+ DepMask ? !DepMask->getValue()->getAsUnquotedString().empty() : false;
}
/// tokenizeAsmString - Tokenize a simplified assembly string.
@@ -1047,6 +1065,18 @@ AsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) {
PrintFatalError(Rec->getLoc(), "operand has no match class!");
}
+struct LessRegisterSet {
+ bool operator() (const RegisterSet &LHS, const RegisterSet & RHS) const {
+ // std::set<T> defines its own compariso "operator<", but it
+ // performs a lexicographical comparison by T's innate comparison
+ // for some reason. We don't want non-deterministic pointer
+ // comparisons so use this instead.
+ return std::lexicographical_compare(LHS.begin(), LHS.end(),
+ RHS.begin(), RHS.end(),
+ LessRecordByID());
+ }
+};
+
void AsmMatcherInfo::
buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
const std::vector<CodeGenRegister*> &Registers =
@@ -1054,33 +1084,35 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
ArrayRef<CodeGenRegisterClass*> RegClassList =
Target.getRegBank().getRegClasses();
+ typedef std::set<RegisterSet, LessRegisterSet> RegisterSetSet;
+
// The register sets used for matching.
- std::set< std::set<Record*> > RegisterSets;
+ RegisterSetSet RegisterSets;
// Gather the defined sets.
for (ArrayRef<CodeGenRegisterClass*>::const_iterator it =
- RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it)
- RegisterSets.insert(std::set<Record*>(
+ RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it)
+ RegisterSets.insert(RegisterSet(
(*it)->getOrder().begin(), (*it)->getOrder().end()));
// Add any required singleton sets.
for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(),
ie = SingletonRegisters.end(); it != ie; ++it) {
Record *Rec = *it;
- RegisterSets.insert(std::set<Record*>(&Rec, &Rec + 1));
+ RegisterSets.insert(RegisterSet(&Rec, &Rec + 1));
}
// Introduce derived sets where necessary (when a register does not determine
// a unique register set class), and build the mapping of registers to the set
// they should classify to.
- std::map<Record*, std::set<Record*> > RegisterMap;
+ std::map<Record*, RegisterSet> RegisterMap;
for (std::vector<CodeGenRegister*>::const_iterator it = Registers.begin(),
ie = Registers.end(); it != ie; ++it) {
const CodeGenRegister &CGR = **it;
// Compute the intersection of all sets containing this register.
- std::set<Record*> ContainingSet;
+ RegisterSet ContainingSet;
- for (std::set< std::set<Record*> >::iterator it = RegisterSets.begin(),
+ for (RegisterSetSet::iterator it = RegisterSets.begin(),
ie = RegisterSets.end(); it != ie; ++it) {
if (!it->count(CGR.TheDef))
continue;
@@ -1090,11 +1122,12 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
continue;
}
- std::set<Record*> Tmp;
+ RegisterSet Tmp;
std::swap(Tmp, ContainingSet);
- std::insert_iterator< std::set<Record*> > II(ContainingSet,
- ContainingSet.begin());
- std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(), II);
+ std::insert_iterator<RegisterSet> II(ContainingSet,
+ ContainingSet.begin());
+ std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(), II,
+ LessRecordByID());
}
if (!ContainingSet.empty()) {
@@ -1104,9 +1137,9 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
}
// Construct the register classes.
- std::map<std::set<Record*>, ClassInfo*> RegisterSetClasses;
+ std::map<RegisterSet, ClassInfo*, LessRegisterSet> RegisterSetClasses;
unsigned Index = 0;
- for (std::set< std::set<Record*> >::iterator it = RegisterSets.begin(),
+ for (RegisterSetSet::iterator it = RegisterSets.begin(),
ie = RegisterSets.end(); it != ie; ++it, ++Index) {
ClassInfo *CI = new ClassInfo();
CI->Kind = ClassInfo::RegisterClass0 + Index;
@@ -1124,13 +1157,14 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
// Find the superclasses; we could compute only the subgroup lattice edges,
// but there isn't really a point.
- for (std::set< std::set<Record*> >::iterator it = RegisterSets.begin(),
+ for (RegisterSetSet::iterator it = RegisterSets.begin(),
ie = RegisterSets.end(); it != ie; ++it) {
ClassInfo *CI = RegisterSetClasses[*it];
- for (std::set< std::set<Record*> >::iterator it2 = RegisterSets.begin(),
+ for (RegisterSetSet::iterator it2 = RegisterSets.begin(),
ie2 = RegisterSets.end(); it2 != ie2; ++it2)
if (*it != *it2 &&
- std::includes(it2->begin(), it2->end(), it->begin(), it->end()))
+ std::includes(it2->begin(), it2->end(), it->begin(), it->end(),
+ LessRecordByID()))
CI->SuperClasses.push_back(RegisterSetClasses[*it2]);
}
@@ -1142,8 +1176,8 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
Record *Def = RC.getDef();
if (!Def)
continue;
- ClassInfo *CI = RegisterSetClasses[std::set<Record*>(RC.getOrder().begin(),
- RC.getOrder().end())];
+ ClassInfo *CI = RegisterSetClasses[RegisterSet(RC.getOrder().begin(),
+ RC.getOrder().end())];
if (CI->ValueName.empty()) {
CI->ClassName = RC.getName();
CI->Name = "MCK_" + RC.getName();
@@ -1155,7 +1189,7 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
}
// Populate the map for individual registers.
- for (std::map<Record*, std::set<Record*> >::iterator it = RegisterMap.begin(),
+ for (std::map<Record*, RegisterSet>::iterator it = RegisterMap.begin(),
ie = RegisterMap.end(); it != ie; ++it)
RegisterClasses[it->first] = RegisterSetClasses[it->second];
@@ -2179,7 +2213,7 @@ static void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info,
OS << "// Flags for subtarget features that participate in "
<< "instruction matching.\n";
OS << "enum SubtargetFeatureFlag {\n";
- for (std::map<Record*, SubtargetFeatureInfo*>::const_iterator
+ for (std::map<Record*, SubtargetFeatureInfo*, LessRecordByID>::const_iterator
it = Info.SubtargetFeatures.begin(),
ie = Info.SubtargetFeatures.end(); it != ie; ++it) {
SubtargetFeatureInfo &SFI = *it->second;
@@ -2217,9 +2251,9 @@ static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) {
<< "static const char *getSubtargetFeatureName(unsigned Val) {\n";
if (!Info.SubtargetFeatures.empty()) {
OS << " switch(Val) {\n";
- for (std::map<Record*, SubtargetFeatureInfo*>::const_iterator
- it = Info.SubtargetFeatures.begin(),
- ie = Info.SubtargetFeatures.end(); it != ie; ++it) {
+ typedef std::map<Record*, SubtargetFeatureInfo*, LessRecordByID> RecFeatMap;
+ for (RecFeatMap::const_iterator it = Info.SubtargetFeatures.begin(),
+ ie = Info.SubtargetFeatures.end(); it != ie; ++it) {
SubtargetFeatureInfo &SFI = *it->second;
// FIXME: Totally just a placeholder name to get the algorithm working.
OS << " case " << SFI.getEnumName() << ": return \""
@@ -2244,7 +2278,7 @@ static void emitComputeAvailableFeatures(AsmMatcherInfo &Info,
OS << "unsigned " << Info.Target.getName() << ClassName << "::\n"
<< "ComputeAvailableFeatures(uint64_t FB) const {\n";
OS << " unsigned Features = 0;\n";
- for (std::map<Record*, SubtargetFeatureInfo*>::const_iterator
+ for (std::map<Record*, SubtargetFeatureInfo*, LessRecordByID>::const_iterator
it = Info.SubtargetFeatures.begin(),
ie = Info.SubtargetFeatures.end(); it != ie; ++it) {
SubtargetFeatureInfo &SFI = *it->second;
@@ -2743,11 +2777,13 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
size_t MaxNumOperands = 0;
unsigned MaxMnemonicIndex = 0;
+ bool HasDeprecation = false;
for (std::vector<MatchableInfo*>::const_iterator it =
Info.Matchables.begin(), ie = Info.Matchables.end();
it != ie; ++it) {
MatchableInfo &II = **it;
MaxNumOperands = std::max(MaxNumOperands, II.AsmOperands.size());
+ HasDeprecation |= II.HasDeprecation;
// Store a pascal-style length byte in the mnemonic.
std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str();
@@ -2804,9 +2840,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
unsigned VariantCount = Target.getAsmParserVariantCount();
for (unsigned VC = 0; VC != VariantCount; ++VC) {
Record *AsmVariant = Target.getAsmParserVariant(VC);
- std::string CommentDelimiter =
- AsmVariant->getValueAsString("CommentDelimiter");
- std::string RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix");
int AsmVariantNo = AsmVariant->getValueAsInt("Variant");
OS << "static const MatchEntry MatchTable" << VC << "[] = {\n";
@@ -2857,9 +2890,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " default: // unreachable\n";
for (unsigned VC = 0; VC != VariantCount; ++VC) {
Record *AsmVariant = Target.getAsmParserVariant(VC);
- std::string CommentDelimiter =
- AsmVariant->getValueAsString("CommentDelimiter");
- std::string RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix");
int AsmVariantNo = AsmVariant->getValueAsInt("Variant");
OS << " case " << AsmVariantNo << ": Start = MatchTable" << VC
<< "; End = array_endof(MatchTable" << VC << "); break;\n";
@@ -2915,9 +2945,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " default: // unreachable\n";
for (unsigned VC = 0; VC != VariantCount; ++VC) {
Record *AsmVariant = Target.getAsmParserVariant(VC);
- std::string CommentDelimiter =
- AsmVariant->getValueAsString("CommentDelimiter");
- std::string RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix");
int AsmVariantNo = AsmVariant->getValueAsInt("Variant");
OS << " case " << AsmVariantNo << ": Start = MatchTable" << VC
<< "; End = array_endof(MatchTable" << VC << "); break;\n";
@@ -3018,6 +3045,14 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
if (!InsnCleanupFn.empty())
OS << " " << InsnCleanupFn << "(Inst);\n";
+ if (HasDeprecation) {
+ OS << " std::string Info;\n";
+ OS << " if (MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, STI, Info)) {\n";
+ OS << " SMLoc Loc = ((" << Target.getName() << "Operand*)Operands[0])->getStartLoc();\n";
+ OS << " Parser.Warning(Loc, Info, None);\n";
+ OS << " }\n";
+ }
+
OS << " return Match_Success;\n";
OS << " }\n\n";
diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp
index ac8d896..a18b6b5 100644
--- a/utils/TableGen/AsmWriterEmitter.cpp
+++ b/utils/TableGen/AsmWriterEmitter.cpp
@@ -18,6 +18,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
@@ -31,10 +32,12 @@ using namespace llvm;
namespace {
class AsmWriterEmitter {
RecordKeeper &Records;
+ CodeGenTarget Target;
std::map<const CodeGenInstruction*, AsmWriterInst*> CGIAWIMap;
std::vector<const CodeGenInstruction*> NumberedInstructions;
+ std::vector<AsmWriterInst> Instructions;
public:
- AsmWriterEmitter(RecordKeeper &R) : Records(R) {}
+ AsmWriterEmitter(RecordKeeper &R);
void run(raw_ostream &o);
@@ -272,9 +275,9 @@ static void UnescapeString(std::string &Str) {
}
/// EmitPrintInstruction - Generate the code for the "printInstruction" method
-/// implementation.
+/// implementation. Destroys all instances of AsmWriterInst information, by
+/// clearing the Instructions vector.
void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
- CodeGenTarget Target(Records);
Record *AsmWriter = Target.getAsmWriter();
std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
bool isMC = AsmWriter->getValueAsBit("isMCAsmWriter");
@@ -287,27 +290,6 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
<< "::printInstruction(const " << MachineInstrClassName
<< " *MI, raw_ostream &O) {\n";
- std::vector<AsmWriterInst> Instructions;
-
- for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
- E = Target.inst_end(); I != E; ++I)
- if (!(*I)->AsmString.empty() &&
- (*I)->TheDef->getName() != "PHI")
- Instructions.push_back(
- AsmWriterInst(**I,
- AsmWriter->getValueAsInt("Variant"),
- AsmWriter->getValueAsInt("FirstOperandColumn"),
- AsmWriter->getValueAsInt("OperandSpacing")));
-
- // Get the instruction numbering.
- NumberedInstructions = Target.getInstructionsByEnumValue();
-
- // Compute the CodeGenInstruction -> AsmWriterInst mapping. Note that not
- // all machine instructions are necessarily being printed, so there may be
- // target instructions not in this map.
- for (unsigned i = 0, e = Instructions.size(); i != e; ++i)
- CGIAWIMap.insert(std::make_pair(Instructions[i].CGI, &Instructions[i]));
-
// Build an aggregate string, and build a table of offsets into it.
SequenceToOffsetTable<std::string> StringTable;
@@ -591,7 +573,6 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName,
}
void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
- CodeGenTarget Target(Records);
Record *AsmWriter = Target.getAsmWriter();
std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
const std::vector<CodeGenRegister*> &Registers =
@@ -657,7 +638,10 @@ public:
void addCond(const std::string &C) { Conds.push_back(C); }
- void addOperand(StringRef Op, unsigned Idx) { OpMap[Op] = Idx; }
+ void addOperand(StringRef Op, unsigned Idx) {
+ assert(Idx < 0xFF && "Index too large!");
+ OpMap[Op] = Idx;
+ }
unsigned getOpIndex(StringRef Op) { return OpMap[Op]; }
bool isOpMapped(StringRef Op) { return OpMap.find(Op) != OpMap.end(); }
@@ -681,12 +665,35 @@ public:
O << ") {\n";
O.indent(6) << "// " << Result << "\n";
- O.indent(6) << "AsmString = \"" << AsmString << "\";\n";
- for (std::map<StringRef, unsigned>::iterator
- I = OpMap.begin(), E = OpMap.end(); I != E; ++I)
- O.indent(6) << "OpMap.push_back(std::make_pair(\"" << I->first << "\", "
- << I->second << "));\n";
+ // Directly mangle mapped operands into the string. Each operand is
+ // identified by a '$' sign followed by a byte identifying the number of the
+ // operand. We add one to the index to avoid zero bytes.
+ std::pair<StringRef, StringRef> ASM = StringRef(AsmString).split(' ');
+ SmallString<128> OutString = ASM.first;
+ if (!ASM.second.empty()) {
+ raw_svector_ostream OS(OutString);
+ OS << ' ';
+ for (StringRef::iterator I = ASM.second.begin(), E = ASM.second.end();
+ I != E;) {
+ OS << *I;
+ if (*I == '$') {
+ StringRef::iterator Start = ++I;
+ while (I != E &&
+ ((*I >= 'a' && *I <= 'z') || (*I >= 'A' && *I <= 'Z') ||
+ (*I >= '0' && *I <= '9') || *I == '_'))
+ ++I;
+ StringRef Name(Start, I - Start);
+ assert(isOpMapped(Name) && "Unmapped operand!");
+ OS << format("\\x%02X", (unsigned char)getOpIndex(Name) + 1);
+ } else {
+ ++I;
+ }
+ }
+ }
+
+ // Emit the string.
+ O.indent(6) << "AsmString = \"" << OutString.str() << "\";\n";
O.indent(6) << "break;\n";
O.indent(4) << '}';
@@ -721,19 +728,6 @@ public:
} // end anonymous namespace
-static void EmitGetMapOperandNumber(raw_ostream &O) {
- O << "static unsigned getMapOperandNumber("
- << "const SmallVectorImpl<std::pair<StringRef, unsigned> > &OpMap,\n";
- O << " StringRef Name) {\n";
- O << " for (SmallVectorImpl<std::pair<StringRef, unsigned> >::"
- << "const_iterator\n";
- O << " I = OpMap.begin(), E = OpMap.end(); I != E; ++I)\n";
- O << " if (I->first == Name)\n";
- O << " return I->second;\n";
- O << " llvm_unreachable(\"Operand not in map!\");\n";
- O << "}\n\n";
-}
-
static unsigned CountNumOperands(StringRef AsmString) {
unsigned NumOps = 0;
std::pair<StringRef, StringRef> ASM = AsmString.split(' ');
@@ -768,7 +762,6 @@ static unsigned CountResultNumOperands(StringRef AsmString) {
}
void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
- CodeGenTarget Target(Records);
Record *AsmWriter = Target.getAsmWriter();
if (!AsmWriter->getValueAsBit("isMCAsmWriter"))
@@ -822,7 +815,6 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
Cond = std::string("MI->getNumOperands() == ") + llvm::utostr(LastOpNo);
IAP->addCond(Cond);
- std::map<StringRef, unsigned> OpMap;
bool CantHandle = false;
for (unsigned i = 0, e = LastOpNo; i != e; ++i) {
@@ -955,11 +947,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
return;
}
- EmitGetMapOperandNumber(O);
-
O << HeaderO.str();
- O.indent(2) << "StringRef AsmString;\n";
- O.indent(2) << "SmallVector<std::pair<StringRef, unsigned>, 4> OpMap;\n";
+ O.indent(2) << "const char *AsmString;\n";
O.indent(2) << "switch (MI->getOpcode()) {\n";
O.indent(2) << "default: return false;\n";
O << CasesO.str();
@@ -967,27 +956,21 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
// Code that prints the alias, replacing the operands with the ones from the
// MCInst.
- O << " std::pair<StringRef, StringRef> ASM = AsmString.split(' ');\n";
- O << " OS << '\\t' << ASM.first;\n";
+ O << " unsigned I = 0;\n";
+ O << " while (AsmString[I] != ' ' && AsmString[I] != '\\0')\n";
+ O << " ++I;\n";
+ O << " OS << '\\t' << StringRef(AsmString, I);\n";
- O << " if (!ASM.second.empty()) {\n";
+ O << " if (AsmString[I] != '\\0') {\n";
O << " OS << '\\t';\n";
- O << " for (StringRef::iterator\n";
- O << " I = ASM.second.begin(), E = ASM.second.end(); I != E; ) {\n";
- O << " if (*I == '$') {\n";
- O << " StringRef::iterator Start = ++I;\n";
- O << " while (I != E &&\n";
- O << " ((*I >= 'a' && *I <= 'z') ||\n";
- O << " (*I >= 'A' && *I <= 'Z') ||\n";
- O << " (*I >= '0' && *I <= '9') ||\n";
- O << " *I == '_'))\n";
- O << " ++I;\n";
- O << " StringRef Name(Start, I - Start);\n";
- O << " printOperand(MI, getMapOperandNumber(OpMap, Name), OS);\n";
+ O << " do {\n";
+ O << " if (AsmString[I] == '$') {\n";
+ O << " ++I;\n";
+ O << " printOperand(MI, unsigned(AsmString[I++]) - 1, OS);\n";
O << " } else {\n";
- O << " OS << *I++;\n";
+ O << " OS << AsmString[I++];\n";
O << " }\n";
- O << " }\n";
+ O << " } while (AsmString[I] != '\\0');\n";
O << " }\n\n";
O << " return true;\n";
@@ -996,6 +979,27 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
O << "#endif // PRINT_ALIAS_INSTR\n";
}
+AsmWriterEmitter::AsmWriterEmitter(RecordKeeper &R) : Records(R), Target(R) {
+ Record *AsmWriter = Target.getAsmWriter();
+ for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
+ E = Target.inst_end();
+ I != E; ++I)
+ if (!(*I)->AsmString.empty() && (*I)->TheDef->getName() != "PHI")
+ Instructions.push_back(
+ AsmWriterInst(**I, AsmWriter->getValueAsInt("Variant"),
+ AsmWriter->getValueAsInt("FirstOperandColumn"),
+ AsmWriter->getValueAsInt("OperandSpacing")));
+
+ // Get the instruction numbering.
+ NumberedInstructions = Target.getInstructionsByEnumValue();
+
+ // Compute the CodeGenInstruction -> AsmWriterInst mapping. Note that not
+ // all machine instructions are necessarily being printed, so there may be
+ // target instructions not in this map.
+ for (unsigned i = 0, e = Instructions.size(); i != e; ++i)
+ CGIAWIMap.insert(std::make_pair(Instructions[i].CGI, &Instructions[i]));
+}
+
void AsmWriterEmitter::run(raw_ostream &O) {
EmitPrintInstruction(O);
EmitGetRegisterName(O);
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index ee025a0..717090a 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -30,16 +30,16 @@ using namespace llvm;
//===----------------------------------------------------------------------===//
static inline bool isInteger(MVT::SimpleValueType VT) {
- return EVT(VT).isInteger();
+ return MVT(VT).isInteger();
}
static inline bool isFloatingPoint(MVT::SimpleValueType VT) {
- return EVT(VT).isFloatingPoint();
+ return MVT(VT).isFloatingPoint();
}
static inline bool isVector(MVT::SimpleValueType VT) {
- return EVT(VT).isVector();
+ return MVT(VT).isVector();
}
static inline bool isScalar(MVT::SimpleValueType VT) {
- return !EVT(VT).isVector();
+ return !MVT(VT).isVector();
}
EEVT::TypeSet::TypeSet(MVT::SimpleValueType VT, TreePattern &TP) {
@@ -385,8 +385,8 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
// Otherwise, if these are both vector types, either this vector
// must have a larger bitsize than the other, or this element type
// must be larger than the other.
- EVT Type(TypeVec[0]);
- EVT OtherType(Other.TypeVec[0]);
+ MVT Type(TypeVec[0]);
+ MVT OtherType(Other.TypeVec[0]);
if (hasVectorTypes() && Other.hasVectorTypes()) {
if (Type.getSizeInBits() >= OtherType.getSizeInBits())
@@ -397,8 +397,7 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
Other.getName() +"'!");
return false;
}
- }
- else
+ } else
// For scalar types, the bitsize of this type must be larger
// than that of the other.
if (Type.getSizeInBits() >= OtherType.getSizeInBits()) {
@@ -450,8 +449,7 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
MadeChange = true;
continue;
}
- }
- else if (isFloatingPoint(*TVI)) {
+ } else if (isFloatingPoint(*TVI)) {
++OtherFPSize;
if (*TVI == SmallestFP) {
TVI = Other.TypeVec.erase(TVI);
@@ -465,8 +463,8 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
// If this is the only type in the large set, the constraint can never be
// satisfied.
- if ((Other.hasIntegerTypes() && OtherIntSize == 0)
- || (Other.hasFloatingPointTypes() && OtherFPSize == 0)) {
+ if ((Other.hasIntegerTypes() && OtherIntSize == 0) ||
+ (Other.hasFloatingPointTypes() && OtherFPSize == 0)) {
TP.error("Type inference contradiction found, '" +
Other.getName() + "' has nothing larger than '" + getName() +"'!");
return false;
@@ -508,8 +506,7 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
MadeChange = true;
continue;
}
- }
- else if (isFloatingPoint(*TVI)) {
+ } else if (isFloatingPoint(*TVI)) {
++FPSize;
if (*TVI == LargestFP) {
TVI = TypeVec.erase(TVI);
@@ -523,8 +520,8 @@ bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
// If this is the only type in the small set, the constraint can never be
// satisfied.
- if ((hasIntegerTypes() && IntSize == 0)
- || (hasFloatingPointTypes() && FPSize == 0)) {
+ if ((hasIntegerTypes() && IntSize == 0) ||
+ (hasFloatingPointTypes() && FPSize == 0)) {
TP.error("Type inference contradiction found, '" +
getName() + "' has nothing smaller than '" + Other.getName()+"'!");
return false;
@@ -547,10 +544,10 @@ bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand,
// If we know the vector type, it forces the scalar to agree.
if (isConcrete()) {
- EVT IVT = getConcrete();
+ MVT IVT = getConcrete();
IVT = IVT.getVectorElementType();
return MadeChange |
- VTOperand.MergeInTypeInfo(IVT.getSimpleVT().SimpleTy, TP);
+ VTOperand.MergeInTypeInfo(IVT.SimpleTy, TP);
}
// If the scalar type is known, filter out vector types whose element types
@@ -565,7 +562,7 @@ bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand,
// Filter out all the types which don't have the right element type.
for (unsigned i = 0; i != TypeVec.size(); ++i) {
assert(isVector(TypeVec[i]) && "EnforceVector didn't work");
- if (EVT(TypeVec[i]).getVectorElementType().getSimpleVT().SimpleTy != VT) {
+ if (MVT(TypeVec[i]).getVectorElementType().SimpleTy != VT) {
TypeVec.erase(TypeVec.begin()+i--);
MadeChange = true;
}
@@ -593,16 +590,16 @@ bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand,
// If we know the vector type, it forces the scalar types to agree.
if (isConcrete()) {
- EVT IVT = getConcrete();
+ MVT IVT = getConcrete();
IVT = IVT.getVectorElementType();
- EEVT::TypeSet EltTypeSet(IVT.getSimpleVT().SimpleTy, TP);
+ EEVT::TypeSet EltTypeSet(IVT.SimpleTy, TP);
MadeChange |= VTOperand.EnforceVectorEltTypeIs(EltTypeSet, TP);
} else if (VTOperand.isConcrete()) {
- EVT IVT = VTOperand.getConcrete();
+ MVT IVT = VTOperand.getConcrete();
IVT = IVT.getVectorElementType();
- EEVT::TypeSet EltTypeSet(IVT.getSimpleVT().SimpleTy, TP);
+ EEVT::TypeSet EltTypeSet(IVT.SimpleTy, TP);
MadeChange |= EnforceVectorEltTypeIs(EltTypeSet, TP);
}
@@ -1522,7 +1519,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
if (VT == MVT::iPTR || VT == MVT::iPTRAny)
return MadeChange;
- unsigned Size = EVT(VT).getSizeInBits();
+ unsigned Size = MVT(VT).getSizeInBits();
// Make sure that the value is representable for this type.
if (Size >= 32) return MadeChange;
@@ -2678,54 +2675,13 @@ static bool checkOperandClass(CGIOperandList::OperandInfo &OI,
return false;
}
-/// ParseInstructions - Parse all of the instructions, inlining and resolving
-/// any fragments involved. This populates the Instructions list with fully
-/// resolved instructions.
-void CodeGenDAGPatterns::ParseInstructions() {
- std::vector<Record*> Instrs = Records.getAllDerivedDefinitions("Instruction");
-
- for (unsigned i = 0, e = Instrs.size(); i != e; ++i) {
- ListInit *LI = 0;
+const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern(
+ CodeGenInstruction &CGI, ListInit *Pat, DAGInstMap &DAGInsts) {
- if (isa<ListInit>(Instrs[i]->getValueInit("Pattern")))
- LI = Instrs[i]->getValueAsListInit("Pattern");
-
- // If there is no pattern, only collect minimal information about the
- // instruction for its operand list. We have to assume that there is one
- // result, as we have no detailed info. A pattern which references the
- // null_frag operator is as-if no pattern were specified. Normally this
- // is from a multiclass expansion w/ a SDPatternOperator passed in as
- // null_frag.
- if (!LI || LI->getSize() == 0 || hasNullFragReference(LI)) {
- std::vector<Record*> Results;
- std::vector<Record*> Operands;
-
- CodeGenInstruction &InstInfo = Target.getInstruction(Instrs[i]);
-
- if (InstInfo.Operands.size() != 0) {
- if (InstInfo.Operands.NumDefs == 0) {
- // These produce no results
- for (unsigned j = 0, e = InstInfo.Operands.size(); j < e; ++j)
- Operands.push_back(InstInfo.Operands[j].Rec);
- } else {
- // Assume the first operand is the result.
- Results.push_back(InstInfo.Operands[0].Rec);
-
- // The rest are inputs.
- for (unsigned j = 1, e = InstInfo.Operands.size(); j < e; ++j)
- Operands.push_back(InstInfo.Operands[j].Rec);
- }
- }
-
- // Create and insert the instruction.
- std::vector<Record*> ImpResults;
- Instructions.insert(std::make_pair(Instrs[i],
- DAGInstruction(0, Results, Operands, ImpResults)));
- continue; // no pattern.
- }
+ assert(!DAGInsts.count(CGI.TheDef) && "Instruction already parsed!");
// Parse the instruction.
- TreePattern *I = new TreePattern(Instrs[i], LI, true, *this);
+ TreePattern *I = new TreePattern(CGI.TheDef, Pat, true, *this);
// Inline pattern fragments into it.
I->InlinePatternFragments();
@@ -2764,7 +2720,6 @@ void CodeGenDAGPatterns::ParseInstructions() {
// Parse the operands list from the (ops) list, validating it.
assert(I->getArgList().empty() && "Args list should still be empty here!");
- CodeGenInstruction &CGI = Target.getInstruction(Instrs[i]);
// Check that all of the results occur first in the list.
std::vector<Record*> Results;
@@ -2863,18 +2818,71 @@ void CodeGenDAGPatterns::ParseInstructions() {
// Create and insert the instruction.
// FIXME: InstImpResults should not be part of DAGInstruction.
DAGInstruction TheInst(I, Results, Operands, InstImpResults);
- Instructions.insert(std::make_pair(I->getRecord(), TheInst));
+ DAGInsts.insert(std::make_pair(I->getRecord(), TheInst));
// Use a temporary tree pattern to infer all types and make sure that the
// constructed result is correct. This depends on the instruction already
- // being inserted into the Instructions map.
+ // being inserted into the DAGInsts map.
TreePattern Temp(I->getRecord(), ResultPattern, false, *this);
Temp.InferAllTypes(&I->getNamedNodesMap());
- DAGInstruction &TheInsertedInst = Instructions.find(I->getRecord())->second;
+ DAGInstruction &TheInsertedInst = DAGInsts.find(I->getRecord())->second;
TheInsertedInst.setResultPattern(Temp.getOnlyTree());
- DEBUG(I->dump());
+ return TheInsertedInst;
+ }
+
+/// ParseInstructions - Parse all of the instructions, inlining and resolving
+/// any fragments involved. This populates the Instructions list with fully
+/// resolved instructions.
+void CodeGenDAGPatterns::ParseInstructions() {
+ std::vector<Record*> Instrs = Records.getAllDerivedDefinitions("Instruction");
+
+ for (unsigned i = 0, e = Instrs.size(); i != e; ++i) {
+ ListInit *LI = 0;
+
+ if (isa<ListInit>(Instrs[i]->getValueInit("Pattern")))
+ LI = Instrs[i]->getValueAsListInit("Pattern");
+
+ // If there is no pattern, only collect minimal information about the
+ // instruction for its operand list. We have to assume that there is one
+ // result, as we have no detailed info. A pattern which references the
+ // null_frag operator is as-if no pattern were specified. Normally this
+ // is from a multiclass expansion w/ a SDPatternOperator passed in as
+ // null_frag.
+ if (!LI || LI->getSize() == 0 || hasNullFragReference(LI)) {
+ std::vector<Record*> Results;
+ std::vector<Record*> Operands;
+
+ CodeGenInstruction &InstInfo = Target.getInstruction(Instrs[i]);
+
+ if (InstInfo.Operands.size() != 0) {
+ if (InstInfo.Operands.NumDefs == 0) {
+ // These produce no results
+ for (unsigned j = 0, e = InstInfo.Operands.size(); j < e; ++j)
+ Operands.push_back(InstInfo.Operands[j].Rec);
+ } else {
+ // Assume the first operand is the result.
+ Results.push_back(InstInfo.Operands[0].Rec);
+
+ // The rest are inputs.
+ for (unsigned j = 1, e = InstInfo.Operands.size(); j < e; ++j)
+ Operands.push_back(InstInfo.Operands[j].Rec);
+ }
+ }
+
+ // Create and insert the instruction.
+ std::vector<Record*> ImpResults;
+ Instructions.insert(std::make_pair(Instrs[i],
+ DAGInstruction(0, Results, Operands, ImpResults)));
+ continue; // no pattern.
+ }
+
+ CodeGenInstruction &CGI = Target.getInstruction(Instrs[i]);
+ const DAGInstruction &DI = parseInstructionPattern(CGI, LI, Instructions);
+
+ (void)DI;
+ DEBUG(DI.getPattern()->dump());
}
// If we can, convert the instructions to be patterns that are matched!
diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h
index 7c2fa36..6fbdd4f 100644
--- a/utils/TableGen/CodeGenDAGPatterns.h
+++ b/utils/TableGen/CodeGenDAGPatterns.h
@@ -778,7 +778,11 @@ public:
ptm_iterator ptm_begin() const { return PatternsToMatch.begin(); }
ptm_iterator ptm_end() const { return PatternsToMatch.end(); }
-
+ /// Parse the Pattern for an instruction, and insert the result in DAGInsts.
+ typedef std::map<Record*, DAGInstruction, LessRecordByID> DAGInstMap;
+ const DAGInstruction &parseInstructionPattern(
+ CodeGenInstruction &CGI, ListInit *Pattern,
+ DAGInstMap &DAGInsts);
const DAGInstruction &getInstruction(Record *R) const {
assert(Instructions.count(R) && "Unknown instruction!");
diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp
index 3673204..576388b 100644
--- a/utils/TableGen/CodeGenInstruction.cpp
+++ b/utils/TableGen/CodeGenInstruction.cpp
@@ -90,7 +90,7 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
if (unsigned NumArgs = MIOpInfo->getNumArgs())
NumOps = NumArgs;
- if (Rec->isSubClassOf("PredicateOperand"))
+ if (Rec->isSubClassOf("PredicateOp"))
isPredicable = true;
else if (Rec->isSubClassOf("OptionalDefOperand"))
hasOptionalDef = true;
@@ -192,6 +192,7 @@ CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
// Otherwise, didn't find it!
PrintFatalError(TheDef->getName() + ": unknown suboperand name in '" + Op + "'");
+ return std::make_pair(0U, 0U);
}
static void ParseConstraint(const std::string &CStr, CGIOperandList &Ops) {
@@ -336,6 +337,20 @@ CodeGenInstruction::CodeGenInstruction(Record *R)
// Parse the DisableEncoding field.
Operands.ProcessDisableEncoding(R->getValueAsString("DisableEncoding"));
+
+ // First check for a ComplexDeprecationPredicate.
+ if (R->getValue("ComplexDeprecationPredicate")) {
+ HasComplexDeprecationPredicate = true;
+ DeprecatedReason = R->getValueAsString("ComplexDeprecationPredicate");
+ } else if (RecordVal *Dep = R->getValue("DeprecatedFeatureMask")) {
+ // Check if we have a Subtarget feature mask.
+ HasComplexDeprecationPredicate = false;
+ DeprecatedReason = Dep->getValue()->getAsString();
+ } else {
+ // This instruction isn't deprecated.
+ HasComplexDeprecationPredicate = false;
+ DeprecatedReason = "";
+ }
}
/// HasOneImplicitDefWithKnownVT - If the instruction has at least one
diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h
index d1e1153..6004f66 100644
--- a/utils/TableGen/CodeGenInstruction.h
+++ b/utils/TableGen/CodeGenInstruction.h
@@ -248,6 +248,9 @@ namespace llvm {
bool isCodeGenOnly;
bool isPseudo;
+ std::string DeprecatedReason;
+ bool HasComplexDeprecationPredicate;
+
/// Are there any undefined flags?
bool hasUndefFlags() const {
return mayLoad_Unset || mayStore_Unset || hasSideEffects_Unset;
diff --git a/utils/TableGen/CodeGenMapTable.cpp b/utils/TableGen/CodeGenMapTable.cpp
index ee32aa1..cb7ec3e 100644
--- a/utils/TableGen/CodeGenMapTable.cpp
+++ b/utils/TableGen/CodeGenMapTable.cpp
@@ -240,7 +240,6 @@ public:
void MapTableEmitter::buildRowInstrMap() {
for (unsigned i = 0, e = InstrDefs.size(); i < e; i++) {
- std::vector<Record*> InstrList;
Record *CurInstr = InstrDefs[i];
std::vector<Init*> KeyValue;
ListInit *RowFields = InstrMapDesc.getRowFields();
diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp
index 43de2be..f2eef4f 100644
--- a/utils/TableGen/CodeGenRegisters.cpp
+++ b/utils/TableGen/CodeGenRegisters.cpp
@@ -813,9 +813,10 @@ static bool testSubClass(const CodeGenRegisterClass *A,
/// Register classes with the same registers, spill size, and alignment form a
/// clique. They will be ordered alphabetically.
///
-static int TopoOrderRC(const void *PA, const void *PB) {
- const CodeGenRegisterClass *A = *(const CodeGenRegisterClass* const*)PA;
- const CodeGenRegisterClass *B = *(const CodeGenRegisterClass* const*)PB;
+static int TopoOrderRC(CodeGenRegisterClass *const *PA,
+ CodeGenRegisterClass *const *PB) {
+ const CodeGenRegisterClass *A = *PA;
+ const CodeGenRegisterClass *B = *PB;
if (A == B)
return 0;
diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp
index 001e97d..dd06433 100644
--- a/utils/TableGen/CodeGenSchedule.cpp
+++ b/utils/TableGen/CodeGenSchedule.cpp
@@ -36,10 +36,11 @@ static void dumpIdxVec(const SmallVectorImpl<unsigned> &V) {
}
#endif
+namespace {
// (instrs a, b, ...) Evaluate and union all arguments. Identical to AddOp.
struct InstrsOp : public SetTheory::Operator {
- void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts,
- ArrayRef<SMLoc> Loc) {
+ virtual void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts,
+ ArrayRef<SMLoc> Loc) {
ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts, Loc);
}
};
@@ -84,6 +85,7 @@ struct InstRegexOp : public SetTheory::Operator {
DeleteContainerPointers(RegexList);
}
};
+} // end anonymous namespace
/// CodeGenModels ctor interprets machine model records and populates maps.
CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK,
diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp
index b2c883d..dd17059 100644
--- a/utils/TableGen/CodeGenTarget.cpp
+++ b/utils/TableGen/CodeGenTarget.cpp
@@ -75,6 +75,7 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::v16i1: return "MVT::v16i1";
case MVT::v32i1: return "MVT::v32i1";
case MVT::v64i1: return "MVT::v64i1";
+ case MVT::v1i8: return "MVT::v1i8";
case MVT::v2i8: return "MVT::v2i8";
case MVT::v4i8: return "MVT::v4i8";
case MVT::v8i8: return "MVT::v8i8";
@@ -98,10 +99,14 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) {
case MVT::v8i64: return "MVT::v8i64";
case MVT::v16i64: return "MVT::v16i64";
case MVT::v2f16: return "MVT::v2f16";
+ case MVT::v4f16: return "MVT::v4f16";
+ case MVT::v8f16: return "MVT::v8f16";
+ case MVT::v1f32: return "MVT::v1f32";
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::v1f64: return "MVT::v1f64";
case MVT::v2f64: return "MVT::v2f64";
case MVT::v4f64: return "MVT::v4f64";
case MVT::v8f64: return "MVT::v8f64";
@@ -316,6 +321,8 @@ void CodeGenTarget::ComputeInstrsByEnum() const {
"BUNDLE",
"LIFETIME_START",
"LIFETIME_END",
+ "STACKMAP",
+ "PATCHPOINT",
0
};
const DenseMap<const Record*, CodeGenInstruction*> &Insts = getInstructions();
diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp
index b47dd71..a76ea32 100644
--- a/utils/TableGen/DAGISelEmitter.cpp
+++ b/utils/TableGen/DAGISelEmitter.cpp
@@ -81,15 +81,13 @@ struct PatternSortingPredicate {
const TreePatternNode *LHSSrc = LHS->getSrcPattern();
const TreePatternNode *RHSSrc = RHS->getSrcPattern();
- if (LHSSrc->getNumTypes() != 0 && RHSSrc->getNumTypes() != 0 &&
- LHSSrc->getType(0) != RHSSrc->getType(0)) {
- MVT::SimpleValueType V1 = LHSSrc->getType(0), V2 = RHSSrc->getType(0);
- if (MVT(V1).isVector() != MVT(V2).isVector())
- return MVT(V2).isVector();
-
- if (MVT(V1).isFloatingPoint() != MVT(V2).isFloatingPoint())
- return MVT(V2).isFloatingPoint();
- }
+ MVT LHSVT = (LHSSrc->getNumTypes() != 0 ? LHSSrc->getType(0) : MVT::Other);
+ MVT RHSVT = (RHSSrc->getNumTypes() != 0 ? RHSSrc->getType(0) : MVT::Other);
+ if (LHSVT.isVector() != RHSVT.isVector())
+ return RHSVT.isVector();
+
+ if (LHSVT.isFloatingPoint() != RHSVT.isFloatingPoint())
+ return RHSVT.isFloatingPoint();
// Otherwise, if the patterns might both match, sort based on complexity,
// which means that we prefer to match patterns that cover more nodes in the
diff --git a/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp
index d173cf0..5d6a11a 100644
--- a/utils/TableGen/DAGISelMatcher.cpp
+++ b/utils/TableGen/DAGISelMatcher.cpp
@@ -63,7 +63,7 @@ bool Matcher::canMoveBefore(const Matcher *Other) const {
}
}
-/// canMoveBefore - Return true if it is safe to move the current matcher
+/// canMoveBeforeNode - Return true if it is safe to move the current matcher
/// across the specified one.
bool Matcher::canMoveBeforeNode(const Matcher *Other) const {
// We can move simple predicates before record nodes.
@@ -134,6 +134,10 @@ void CheckSameMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
OS.indent(indent) << "CheckSame " << MatchNumber << '\n';
}
+void CheckChildSameMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckChild" << ChildNo << "Same\n";
+}
+
void CheckPatternPredicateMatcher::
printImpl(raw_ostream &OS, unsigned indent) const {
OS.indent(indent) << "CheckPatternPredicate " << Predicate << '\n';
diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h
index f978188..70031fa 100644
--- a/utils/TableGen/DAGISelMatcher.h
+++ b/utils/TableGen/DAGISelMatcher.h
@@ -55,6 +55,7 @@ public:
// Predicate checking.
CheckSame, // Fail if not same as prev match.
+ CheckChildSame, // Fail if child not same as prev match.
CheckPatternPredicate,
CheckPredicate, // Fail if node predicate fails.
CheckOpcode, // Fail if not opcode.
@@ -122,6 +123,7 @@ public:
switch (getKind()) {
default: return false;
case CheckSame:
+ case CheckChildSame:
case CheckPatternPredicate:
case CheckPredicate:
case CheckOpcode:
@@ -154,7 +156,7 @@ public:
/// node. Other must be equal to or before this.
bool canMoveBefore(const Matcher *Other) const;
- /// canMoveBefore - Return true if it is safe to move the current matcher
+ /// canMoveBeforeNode - Return true if it is safe to move the current matcher
/// across the specified one.
bool canMoveBeforeNode(const Matcher *Other) const;
@@ -392,6 +394,34 @@ private:
virtual unsigned getHashImpl() const { return getMatchNumber(); }
};
+/// CheckChildSameMatcher - This checks to see if child node is exactly the same
+/// node as the specified match that was recorded with 'Record'. This is used
+/// when patterns have the same name in them, like '(mul GPR:$in, GPR:$in)'.
+class CheckChildSameMatcher : public Matcher {
+ unsigned ChildNo;
+ unsigned MatchNumber;
+public:
+ CheckChildSameMatcher(unsigned childno, unsigned matchnumber)
+ : Matcher(CheckChildSame), ChildNo(childno), MatchNumber(matchnumber) {}
+
+ unsigned getChildNo() const { return ChildNo; }
+ unsigned getMatchNumber() const { return MatchNumber; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckChildSame;
+ }
+
+ virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
+
+private:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const;
+ virtual bool isEqualImpl(const Matcher *M) const {
+ return cast<CheckChildSameMatcher>(M)->ChildNo == ChildNo &&
+ cast<CheckChildSameMatcher>(M)->MatchNumber == MatchNumber;
+ }
+ virtual unsigned getHashImpl() const { return (MatchNumber << 2) | ChildNo; }
+};
+
/// CheckPatternPredicateMatcher - This checks the target-specific predicate
/// to see if the entire pattern is capable of matching. This predicate does
/// not take a node as input. This is used for subtarget feature checks etc.
diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp
index 93f84ce..04fe0d1 100644
--- a/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ b/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -242,6 +242,12 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
<< cast<CheckSameMatcher>(N)->getMatchNumber() << ",\n";
return 2;
+ case Matcher::CheckChildSame:
+ OS << "OPC_CheckChild"
+ << cast<CheckChildSameMatcher>(N)->getChildNo() << "Same, "
+ << cast<CheckChildSameMatcher>(N)->getMatchNumber() << ",\n";
+ return 2;
+
case Matcher::CheckPatternPredicate: {
StringRef Pred =cast<CheckPatternPredicateMatcher>(N)->getPredicate();
OS << "OPC_CheckPatternPredicate, " << getPatternPredicate(Pred) << ',';
@@ -315,10 +321,12 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
assert(ChildSize != 0 && "Should not have a zero-sized child!");
if (i != 0) {
+ if (!OmitComments)
+ OS << "/*" << CurrentIdx << "*/";
OS.PadToColumn(Indent*2);
if (!OmitComments)
- OS << (isa<SwitchOpcodeMatcher>(N) ?
- "/*SwitchOpcode*/ " : "/*SwitchType*/ ");
+ OS << (isa<SwitchOpcodeMatcher>(N) ?
+ "/*SwitchOpcode*/ " : "/*SwitchType*/ ");
}
// Emit the VBR.
@@ -340,6 +348,8 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
}
// Emit the final zero to terminate the switch.
+ if (!OmitComments)
+ OS << "/*" << CurrentIdx << "*/";
OS.PadToColumn(Indent*2) << "0, ";
if (!OmitComments)
OS << (isa<SwitchOpcodeMatcher>(N) ?
@@ -749,6 +759,7 @@ void MatcherTableEmitter::EmitHistogram(const Matcher *M,
case Matcher::MoveChild: OS << "OPC_MoveChild"; break;
case Matcher::MoveParent: OS << "OPC_MoveParent"; break;
case Matcher::CheckSame: OS << "OPC_CheckSame"; break;
+ case Matcher::CheckChildSame: OS << "OPC_CheckChildSame"; break;
case Matcher::CheckPatternPredicate:
OS << "OPC_CheckPatternPredicate"; break;
case Matcher::CheckPredicate: OS << "OPC_CheckPredicate"; break;
diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp
index f996422..82e5d63 100644
--- a/utils/TableGen/DAGISelMatcherOpt.cpp
+++ b/utils/TableGen/DAGISelMatcherOpt.cpp
@@ -51,7 +51,11 @@ static void ContractNodes(OwningPtr<Matcher> &MatcherPtr,
if (MC->getChildNo() < 8 && // Only have CheckChildType0...7
CT->getResNo() == 0) // CheckChildType checks res #0
New = new CheckChildTypeMatcher(MC->getChildNo(), CT->getType());
-
+
+ if (CheckSameMatcher *CS = dyn_cast<CheckSameMatcher>(MC->getNext()))
+ if (MC->getChildNo() < 4) // Only have CheckChildSame0...3
+ New = new CheckChildSameMatcher(MC->getChildNo(), CS->getMatchNumber());
+
if (New) {
// Insert the new node.
New->setNext(MatcherPtr.take());
diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp
index ce7f8c8..e35cf0f 100644
--- a/utils/TableGen/FastISelEmitter.cpp
+++ b/utils/TableGen/FastISelEmitter.cpp
@@ -46,7 +46,7 @@ class ImmPredicateSet {
DenseMap<TreePattern *, unsigned> ImmIDs;
std::vector<TreePredicateFn> PredsByName;
public:
-
+
unsigned getIDFor(TreePredicateFn Pred) {
unsigned &Entry = ImmIDs[Pred.getOrigPatFragRecord()];
if (Entry == 0) {
@@ -55,16 +55,16 @@ public:
}
return Entry-1;
}
-
+
const TreePredicateFn &getPredicate(unsigned i) {
assert(i < PredsByName.size());
return PredsByName[i];
}
-
+
typedef std::vector<TreePredicateFn>::const_iterator iterator;
iterator begin() const { return PredsByName.begin(); }
iterator end() const { return PredsByName.end(); }
-
+
};
} // End anonymous namespace
@@ -77,9 +77,9 @@ struct OperandsSignature {
enum { OK_Reg, OK_FP, OK_Imm, OK_Invalid = -1 };
char Repr;
public:
-
+
OpKind() : Repr(OK_Invalid) {}
-
+
bool operator<(OpKind RHS) const { return Repr < RHS.Repr; }
bool operator==(OpKind RHS) const { return Repr == RHS.Repr; }
@@ -90,13 +90,13 @@ struct OperandsSignature {
"Too many integer predicates for the 'Repr' char");
OpKind K; K.Repr = OK_Imm+V; return K;
}
-
+
bool isReg() const { return Repr == OK_Reg; }
bool isFP() const { return Repr == OK_FP; }
bool isImm() const { return Repr >= OK_Imm; }
-
+
unsigned getImmCode() const { assert(isImm()); return Repr-OK_Imm; }
-
+
void printManglingSuffix(raw_ostream &OS, ImmPredicateSet &ImmPredicates,
bool StripImmCodes) const {
if (isReg())
@@ -111,8 +111,8 @@ struct OperandsSignature {
}
}
};
-
-
+
+
SmallVector<OpKind, 3> Operands;
bool operator<(const OperandsSignature &O) const {
@@ -130,7 +130,7 @@ struct OperandsSignature {
return true;
return false;
}
-
+
/// getWithoutImmCodes - Return a copy of this with any immediate codes forced
/// to zero.
OperandsSignature getWithoutImmCodes() const {
@@ -142,31 +142,31 @@ struct OperandsSignature {
Result.Operands.push_back(OpKind::getImm(0));
return Result;
}
-
+
void emitImmediatePredicate(raw_ostream &OS, ImmPredicateSet &ImmPredicates) {
bool EmittedAnything = false;
for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
if (!Operands[i].isImm()) continue;
-
+
unsigned Code = Operands[i].getImmCode();
if (Code == 0) continue;
-
+
if (EmittedAnything)
OS << " &&\n ";
-
+
TreePredicateFn PredFn = ImmPredicates.getPredicate(Code-1);
-
+
// Emit the type check.
OS << "VT == "
<< getEnumName(PredFn.getOrigPatFragRecord()->getTree(0)->getType(0))
<< " && ";
-
-
+
+
OS << PredFn.getFnName() << "(imm" << i <<')';
EmittedAnything = true;
}
}
-
+
/// initialize - Examine the given pattern and initialize the contents
/// of the Operands array accordingly. Return true if all the operands
/// are supported, false otherwise.
@@ -177,12 +177,12 @@ struct OperandsSignature {
const CodeGenRegisterClass *OrigDstRC) {
if (InstPatNode->isLeaf())
return false;
-
+
if (InstPatNode->getOperator()->getName() == "imm") {
Operands.push_back(OpKind::getImm(0));
return true;
}
-
+
if (InstPatNode->getOperator()->getName() == "fpimm") {
Operands.push_back(OpKind::getFP());
return true;
@@ -211,19 +211,19 @@ struct OperandsSignature {
Record *Rec = PredFn.getOrigPatFragRecord()->getRecord();
if (Rec->getValueAsBit("FastIselShouldIgnore"))
return false;
-
+
PredNo = ImmediatePredicates.getIDFor(PredFn)+1;
}
-
+
// Handle unmatched immediate sizes here.
//if (Op->getType(0) != VT)
// return false;
-
+
Operands.push_back(OpKind::getImm(PredNo));
continue;
}
-
+
// For now, filter out any operand with a predicate.
// For now, filter out any operand with multiple values.
if (!Op->getPredicateFns().empty() || Op->getNumTypes() != 1)
@@ -237,7 +237,7 @@ struct OperandsSignature {
// For now, ignore other non-leaf nodes.
return false;
}
-
+
assert(Op->hasTypeSet(0) && "Type infererence not done?");
// For now, all the operands must have the same type (if they aren't
@@ -250,7 +250,7 @@ struct OperandsSignature {
if (!OpDI)
return false;
Record *OpLeafRec = OpDI->getDef();
-
+
// For now, the only other thing we accept is register operands.
const CodeGenRegisterClass *RC = 0;
if (OpLeafRec->isSubClassOf("RegisterOperand"))
@@ -375,7 +375,7 @@ class FastISelMap {
std::map<OperandsSignature, std::vector<OperandsSignature> >
SignaturesWithConstantForms;
-
+
std::string InstNS;
ImmPredicateSet ImmediatePredicates;
public:
@@ -551,13 +551,13 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
SubRegNo,
PhysRegInputs
};
-
+
if (SimplePatterns[Operands][OpcodeName][VT][RetVT].count(PredicateCheck))
PrintFatalError(Pattern.getSrcRecord()->getLoc(),
"Duplicate record in FastISel table!");
SimplePatterns[Operands][OpcodeName][VT][RetVT][PredicateCheck] = Memo;
-
+
// If any of the operands were immediates with predicates on them, strip
// them down to a signature that doesn't have predicates so that we can
// associate them with the stripped predicate version.
@@ -571,14 +571,14 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
void FastISelMap::printImmediatePredicates(raw_ostream &OS) {
if (ImmediatePredicates.begin() == ImmediatePredicates.end())
return;
-
+
OS << "\n// FastEmit Immediate Predicate functions.\n";
for (ImmPredicateSet::iterator I = ImmediatePredicates.begin(),
E = ImmediatePredicates.end(); I != E; ++I) {
OS << "static bool " << I->getFnName() << "(int64_t Imm) {\n";
OS << I->getImmediatePredicateCode() << "\n}\n";
}
-
+
OS << "\n\n";
}
@@ -804,11 +804,11 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
OS << ", ";
Operands.PrintParameters(OS);
OS << ") {\n";
-
- // If there are any forms of this signature available that operand on
- // constrained forms of the immediate (e.g. 32-bit sext immediate in a
+
+ // If there are any forms of this signature available that operate on
+ // constrained forms of the immediate (e.g., 32-bit sext immediate in a
// 64-bit operand), check them first.
-
+
std::map<OperandsSignature, std::vector<OperandsSignature> >::iterator MI
= SignaturesWithConstantForms.find(Operands);
if (MI != SignaturesWithConstantForms.end()) {
@@ -816,7 +816,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
std::sort(MI->second.begin(), MI->second.end());
MI->second.erase(std::unique(MI->second.begin(), MI->second.end()),
MI->second.end());
-
+
// Check each in order it was seen. It would be nice to have a good
// relative ordering between them, but we're not going for optimality
// here.
@@ -831,11 +831,11 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
MI->second[i].PrintArguments(OS);
OS << "))\n return Reg;\n\n";
}
-
+
// Done with this, remove it.
SignaturesWithConstantForms.erase(MI);
}
-
+
OS << " switch (Opcode) {\n";
for (OpcodeTypeRetPredMap::const_iterator I = OTM.begin(), E = OTM.end();
I != E; ++I) {
@@ -855,7 +855,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
OS << "}\n";
OS << "\n";
}
-
+
// TODO: SignaturesWithConstantForms should be empty here.
}
diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp
index 6e45240..87d18cd 100644
--- a/utils/TableGen/FixedLenDecoderEmitter.cpp
+++ b/utils/TableGen/FixedLenDecoderEmitter.cpp
@@ -2038,7 +2038,6 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
}
DecoderTableInfo TableInfo;
- std::set<unsigned> Sizes;
for (std::map<std::pair<std::string, unsigned>,
std::vector<unsigned> >::const_iterator
I = OpcMap.begin(), E = OpcMap.end(); I != E; ++I) {
diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index c8304de..d3d9cc1 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/utils/TableGen/InstrInfoEmitter.cpp
@@ -57,6 +57,7 @@ private:
std::map<std::vector<Record*>, unsigned> &EL,
const OperandInfoMapTy &OpInfo,
raw_ostream &OS);
+ void emitOperandTypesEnum(raw_ostream &OS, const CodeGenTarget &Target);
void initOperandMapData(
const std::vector<const CodeGenInstruction *> NumberedInstructions,
const std::string &Namespace,
@@ -132,8 +133,8 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
Res += "|(1<<MCOI::LookupPtrRegClass)";
// Predicate operands. Check to see if the original unexpanded operand
- // was of type PredicateOperand.
- if (Inst.Operands[i].Rec->isSubClassOf("PredicateOperand"))
+ // was of type PredicateOp.
+ if (Inst.Operands[i].Rec->isSubClassOf("PredicateOp"))
Res += "|(1<<MCOI::Predicate)";
// Optional def operands. Check to see if the original unexpanded operand
@@ -311,6 +312,34 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS,
}
+/// Generate an enum for all the operand types for this target, under the
+/// llvm::TargetNamespace::OpTypes namespace.
+/// Operand types are all definitions derived of the Operand Target.td class.
+void InstrInfoEmitter::emitOperandTypesEnum(raw_ostream &OS,
+ const CodeGenTarget &Target) {
+
+ const std::string &Namespace = Target.getInstNamespace();
+ std::vector<Record *> Operands = Records.getAllDerivedDefinitions("Operand");
+
+ OS << "\n#ifdef GET_INSTRINFO_OPERAND_TYPES_ENUM\n";
+ OS << "#undef GET_INSTRINFO_OPERAND_TYPES_ENUM\n";
+ OS << "namespace llvm {";
+ OS << "namespace " << Namespace << " {\n";
+ OS << "namespace OpTypes { \n";
+ OS << "enum OperandType {\n";
+
+ for (unsigned oi = 0, oe = Operands.size(); oi != oe; ++oi) {
+ if (!Operands[oi]->isAnonymous())
+ OS << " " << Operands[oi]->getName() << " = " << oi << ",\n";
+ }
+
+ OS << " OPERAND_TYPE_LIST_END" << "\n};\n";
+ OS << "} // End namespace OpTypes\n";
+ OS << "} // End namespace " << Namespace << "\n";
+ OS << "} // End namespace llvm\n";
+ OS << "#endif // GET_INSTRINFO_OPERAND_TYPES_ENUM\n";
+}
+
//===----------------------------------------------------------------------===//
// Main Output.
//===----------------------------------------------------------------------===//
@@ -408,13 +437,14 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
OS << "namespace llvm {\n";
OS << "struct " << ClassName << " : public TargetInstrInfo {\n"
<< " explicit " << ClassName << "(int SO = -1, int DO = -1);\n"
+ << " virtual ~" << ClassName << "();\n"
<< "};\n";
OS << "} // End llvm namespace \n";
OS << "#endif // GET_INSTRINFO_HEADER\n\n";
- OS << "\n#ifdef GET_INSTRINFO_CTOR\n";
- OS << "#undef GET_INSTRINFO_CTOR\n";
+ OS << "\n#ifdef GET_INSTRINFO_CTOR_DTOR\n";
+ OS << "#undef GET_INSTRINFO_CTOR_DTOR\n";
OS << "namespace llvm {\n";
OS << "extern const MCInstrDesc " << TargetName << "Insts[];\n";
@@ -424,12 +454,15 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
<< " : TargetInstrInfo(SO, DO) {\n"
<< " InitMCInstrInfo(" << TargetName << "Insts, "
<< TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, "
- << NumberedInstructions.size() << ");\n}\n";
+ << NumberedInstructions.size() << ");\n}\n"
+ << ClassName << "::~" << ClassName << "() {}\n";
OS << "} // End llvm namespace \n";
- OS << "#endif // GET_INSTRINFO_CTOR\n\n";
+ OS << "#endif // GET_INSTRINFO_CTOR_DTOR\n\n";
emitOperandNameMappings(OS, Target, NumberedInstructions);
+
+ emitOperandTypesEnum(OS, Target);
}
void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
@@ -514,6 +547,19 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
else
OS << "OperandInfo" << OpInfo.find(OperandInfo)->second;
+ CodeGenTarget &Target = CDP.getTargetInfo();
+ if (Inst.HasComplexDeprecationPredicate)
+ // Emit a function pointer to the complex predicate method.
+ OS << ",0"
+ << ",&get" << Inst.DeprecatedReason << "DeprecationInfo";
+ else if (!Inst.DeprecatedReason.empty())
+ // Emit the Subtarget feature.
+ OS << "," << Target.getInstNamespace() << "::" << Inst.DeprecatedReason
+ << ",0";
+ else
+ // Instruction isn't deprecated.
+ OS << ",0,0";
+
OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";
}
@@ -545,7 +591,15 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
<< "\t= " << i << ",\n";
}
OS << " INSTRUCTION_LIST_END = " << NumberedInstructions.size() << "\n";
- OS << " };\n}\n";
+ OS << " };\n";
+ OS << "namespace Sched {\n";
+ OS << " enum {\n";
+ for (unsigned i = 0, e = SchedModels.numInstrSchedClasses(); i != e; ++i) {
+ OS << " " << SchedModels.getSchedClass(i).Name
+ << "\t= " << i << ",\n";
+ }
+ OS << " SCHED_LIST_END = " << SchedModels.numInstrSchedClasses() << "\n";
+ OS << " };\n}\n}\n";
OS << "} // End llvm namespace \n";
OS << "#endif // GET_INSTRINFO_ENUM\n\n";
diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp
index c508795..8f137f8 100644
--- a/utils/TableGen/IntrinsicEmitter.cpp
+++ b/utils/TableGen/IntrinsicEmitter.cpp
@@ -84,10 +84,10 @@ void IntrinsicEmitter::run(raw_ostream &OS) {
// Emit the function name recognizer.
EmitFnNameRecognizer(Ints, OS);
-
+
// Emit the intrinsic declaration generator.
EmitGenerator(Ints, OS);
-
+
// Emit the intrinsic parameter attributes.
EmitAttributes(Ints, OS);
@@ -125,7 +125,7 @@ void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
OS << " " << Ints[i].EnumName;
OS << ((i != e-1) ? ", " : " ");
- OS << std::string(40-Ints[i].EnumName.size(), ' ')
+ OS << std::string(40-Ints[i].EnumName.size(), ' ')
<< "// " << Ints[i].Name << "\n";
}
OS << "#endif\n\n";
@@ -146,13 +146,13 @@ private:
};
void IntrinsicEmitter::
-EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
+EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
raw_ostream &OS) {
// Build a 'first character of function name' -> intrinsic # mapping.
std::map<char, std::vector<unsigned> > IntMapping;
for (unsigned i = 0, e = Ints.size(); i != e; ++i)
IntMapping[Ints[i].Name[5]].push_back(i);
-
+
OS << "// Function name -> enum value recognizer code.\n";
OS << "#ifdef GET_FUNCTION_RECOGNIZER\n";
OS << " StringRef NameR(Name+6, Len-6); // Skip over 'llvm.'\n";
@@ -171,7 +171,7 @@ EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
// Emit all the overloaded intrinsics first, build a table of the
// non-overloaded ones.
std::vector<StringMatcher::StringPair> MatchTable;
-
+
for (unsigned i = 0, e = IntList.size(); i != e; ++i) {
unsigned IntNo = IntList[i];
std::string Result = "return " + TargetPrefix + "Intrinsic::" +
@@ -188,18 +188,18 @@ EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
OS << " if (NameR.startswith(\"" << TheStr << "\")) "
<< Result << '\n';
}
-
+
// Emit the matcher logic for the fixed length strings.
StringMatcher("NameR", MatchTable, OS).Emit(1);
OS << " break; // end of '" << I->first << "' case.\n";
}
-
+
OS << " }\n";
OS << "#endif\n\n";
}
void IntrinsicEmitter::
-EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
+EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
raw_ostream &OS) {
OS << "// Intrinsic ID to name table\n";
OS << "#ifdef GET_INTRINSIC_NAME_TABLE\n";
@@ -210,7 +210,7 @@ EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
}
void IntrinsicEmitter::
-EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints,
+EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints,
raw_ostream &OS) {
OS << "// Intrinsic ID to overload bitset\n";
OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n";
@@ -260,7 +260,9 @@ enum IIT_Info {
IIT_STRUCT5 = 22,
IIT_EXTEND_VEC_ARG = 23,
IIT_TRUNC_VEC_ARG = 24,
- IIT_ANYPTR = 25
+ IIT_ANYPTR = 25,
+ IIT_V1 = 26,
+ IIT_VARARG = 27
};
@@ -277,7 +279,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT,
case 64: return Sig.push_back(IIT_I64);
}
}
-
+
switch (VT) {
default: PrintFatalError("unhandled MVT in intrinsic!");
case MVT::f16: return Sig.push_back(IIT_F16);
@@ -287,16 +289,18 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT,
case MVT::x86mmx: return Sig.push_back(IIT_MMX);
// MVT::OtherVT is used to mean the empty struct type here.
case MVT::Other: return Sig.push_back(IIT_EMPTYSTRUCT);
+ // MVT::isVoid is used to represent varargs here.
+ case MVT::isVoid: return Sig.push_back(IIT_VARARG);
}
}
#ifdef _MSC_VER
#pragma optimize("",off) // MSVC 2010 optimizer can't deal with this function.
-#endif
+#endif
static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
std::vector<unsigned char> &Sig) {
-
+
if (R->isSubClassOf("LLVMMatchType")) {
unsigned Number = R->getValueAsInt("Number");
assert(Number < ArgCodes.size() && "Invalid matching number!");
@@ -308,7 +312,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
Sig.push_back(IIT_ARG);
return Sig.push_back((Number << 2) | ArgCodes[Number]);
}
-
+
MVT::SimpleValueType VT = getValueType(R->getValueAsDef("VT"));
unsigned Tmp = 0;
@@ -319,17 +323,17 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
case MVT::fAny: ++Tmp; // FALL THROUGH.
case MVT::iAny: {
// If this is an "any" valuetype, then the type is the type of the next
- // type in the list specified to getIntrinsic().
+ // type in the list specified to getIntrinsic().
Sig.push_back(IIT_ARG);
-
+
// Figure out what arg # this is consuming, and remember what kind it was.
unsigned ArgNo = ArgCodes.size();
ArgCodes.push_back(Tmp);
-
+
// Encode what sort of argument it must be in the low 2 bits of the ArgNo.
return Sig.push_back((ArgNo << 2) | Tmp);
}
-
+
case MVT::iPTR: {
unsigned AddrSpace = 0;
if (R->isSubClassOf("LLVMQualPointerType")) {
@@ -345,18 +349,19 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
return EncodeFixedType(R->getValueAsDef("ElTy"), ArgCodes, Sig);
}
}
-
+
if (EVT(VT).isVector()) {
EVT VVT = VT;
switch (VVT.getVectorNumElements()) {
default: PrintFatalError("unhandled vector type width in intrinsic!");
+ case 1: Sig.push_back(IIT_V1); break;
case 2: Sig.push_back(IIT_V2); break;
case 4: Sig.push_back(IIT_V4); break;
case 8: Sig.push_back(IIT_V8); break;
case 16: Sig.push_back(IIT_V16); break;
case 32: Sig.push_back(IIT_V32); break;
}
-
+
return EncodeFixedValueType(VVT.getVectorElementType().
getSimpleVT().SimpleTy, Sig);
}
@@ -373,7 +378,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
static void ComputeFixedEncoding(const CodeGenIntrinsic &Int,
std::vector<unsigned char> &TypeSig) {
std::vector<unsigned char> ArgCodes;
-
+
if (Int.IS.RetVTs.empty())
TypeSig.push_back(IIT_Done);
else if (Int.IS.RetVTs.size() == 1 &&
@@ -388,11 +393,11 @@ static void ComputeFixedEncoding(const CodeGenIntrinsic &Int,
case 5: TypeSig.push_back(IIT_STRUCT5); break;
default: assert(0 && "Unhandled case in struct");
}
-
+
for (unsigned i = 0, e = Int.IS.RetVTs.size(); i != e; ++i)
EncodeFixedType(Int.IS.RetTypeDefs[i], ArgCodes, TypeSig);
}
-
+
for (unsigned i = 0, e = Int.IS.ParamTypeDefs.size(); i != e; ++i)
EncodeFixedType(Int.IS.ParamTypeDefs[i], ArgCodes, TypeSig);
}
@@ -401,16 +406,16 @@ static void printIITEntry(raw_ostream &OS, unsigned char X) {
OS << (unsigned)X;
}
-void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
+void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
raw_ostream &OS) {
// If we can compute a 32-bit fixed encoding for this intrinsic, do so and
// capture it in this vector, otherwise store a ~0U.
std::vector<unsigned> FixedEncodings;
-
+
SequenceToOffsetTable<std::vector<unsigned char> > LongEncodingTable;
-
+
std::vector<unsigned char> TypeSig;
-
+
// Compute the unique argument type info.
for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
// Get the signature for the intrinsic.
@@ -430,7 +435,7 @@ void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
}
Result = (Result << 4) | TypeSig[e-i-1];
}
-
+
// If this could be encoded into a 31-bit word, return it.
if (!Failed && (Result >> 31) == 0) {
FixedEncodings.push_back(Result);
@@ -441,45 +446,45 @@ void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
// Otherwise, we're going to unique the sequence into the
// LongEncodingTable, and use its offset in the 32-bit table instead.
LongEncodingTable.add(TypeSig);
-
+
// This is a placehold that we'll replace after the table is laid out.
FixedEncodings.push_back(~0U);
}
-
+
LongEncodingTable.layout();
-
+
OS << "// Global intrinsic function declaration type table.\n";
OS << "#ifdef GET_INTRINSIC_GENERATOR_GLOBAL\n";
OS << "static const unsigned IIT_Table[] = {\n ";
-
+
for (unsigned i = 0, e = FixedEncodings.size(); i != e; ++i) {
if ((i & 7) == 7)
OS << "\n ";
-
+
// If the entry fit in the table, just emit it.
if (FixedEncodings[i] != ~0U) {
OS << "0x" << utohexstr(FixedEncodings[i]) << ", ";
continue;
}
-
+
TypeSig.clear();
ComputeFixedEncoding(Ints[i], TypeSig);
-
+
// Otherwise, emit the offset into the long encoding table. We emit it this
// way so that it is easier to read the offset in the .def file.
OS << "(1U<<31) | " << LongEncodingTable.get(TypeSig) << ", ";
}
-
+
OS << "0\n};\n\n";
-
+
// Emit the shared table of register lists.
OS << "static const unsigned char IIT_LongEncodingTable[] = {\n";
if (!LongEncodingTable.empty())
LongEncodingTable.emit(OS, printIITEntry);
OS << " 255\n};\n\n";
-
+
OS << "#endif\n\n"; // End of GET_INTRINSIC_GENERATOR_GLOBAL
}
@@ -567,7 +572,6 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
OS << " AttributeSet AS[" << maxArgAttrs+1 << "];\n";
OS << " unsigned NumAttrs = 0;\n";
OS << " if (id != 0) {\n";
- OS << " SmallVector<Attribute::AttrKind, 8> AttrVec;\n";
OS << " switch(IntrinsicsToAttributesMap[id - ";
if (TargetOnly)
OS << "Intrinsic::num_intrinsics";
@@ -577,7 +581,7 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
OS << " default: llvm_unreachable(\"Invalid attribute number\");\n";
for (UniqAttrMapTy::const_iterator I = UniqAttributes.begin(),
E = UniqAttributes.end(); I != E; ++I) {
- OS << " case " << I->second << ":\n";
+ OS << " case " << I->second << ": {\n";
const CodeGenIntrinsic &intrinsic = *(I->first);
@@ -590,60 +594,82 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
while (ai != ae) {
unsigned argNo = intrinsic.ArgumentAttributes[ai].first;
- OS << " AttrVec.clear();\n";
+ OS << " const Attribute::AttrKind AttrParam" << argNo + 1 <<"[]= {";
+ bool addComma = false;
do {
switch (intrinsic.ArgumentAttributes[ai].second) {
case CodeGenIntrinsic::NoCapture:
- OS << " AttrVec.push_back(Attribute::NoCapture);\n";
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::NoCapture";
+ addComma = true;
break;
case CodeGenIntrinsic::ReadOnly:
- OS << " AttrVec.push_back(Attribute::ReadOnly);\n";
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::ReadOnly";
+ addComma = true;
break;
case CodeGenIntrinsic::ReadNone:
- OS << " AttrVec.push_back(Attribute::ReadNone);\n";
+ if (addComma)
+ OS << ",";
+ OS << "Attributes::ReadNone";
+ addComma = true;
break;
}
++ai;
} while (ai != ae && intrinsic.ArgumentAttributes[ai].first == argNo);
-
+ OS << "};\n";
OS << " AS[" << numAttrs++ << "] = AttributeSet::get(C, "
- << argNo+1 << ", AttrVec);\n";
+ << argNo+1 << ", AttrParam" << argNo +1 << ");\n";
}
}
ModRefKind modRef = getModRefKind(intrinsic);
if (!intrinsic.canThrow || modRef || intrinsic.isNoReturn) {
- OS << " AttrVec.clear();\n";
-
- if (!intrinsic.canThrow)
- OS << " AttrVec.push_back(Attribute::NoUnwind);\n";
- if (intrinsic.isNoReturn)
- OS << " AttrVec.push_back(Attribute::NoReturn);\n";
+ OS << " const Attribute::AttrKind Atts[] = {";
+ bool addComma = false;
+ if (!intrinsic.canThrow) {
+ OS << "Attribute::NoUnwind";
+ addComma = true;
+ }
+ if (intrinsic.isNoReturn) {
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::NoReturn";
+ addComma = true;
+ }
switch (modRef) {
case MRK_none: break;
case MRK_readonly:
- OS << " AttrVec.push_back(Attribute::ReadOnly);\n";
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::ReadOnly";
break;
case MRK_readnone:
- OS << " AttrVec.push_back(Attribute::ReadNone);\n";
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::ReadNone";
break;
}
+ OS << "};\n";
OS << " AS[" << numAttrs++ << "] = AttributeSet::get(C, "
- << "AttributeSet::FunctionIndex, AttrVec);\n";
+ << "AttributeSet::FunctionIndex, Atts);\n";
}
if (numAttrs) {
OS << " NumAttrs = " << numAttrs << ";\n";
OS << " break;\n";
+ OS << " }\n";
} else {
OS << " return AttributeSet();\n";
}
}
-
+
OS << " }\n";
OS << " }\n";
OS << " return AttributeSet::get(C, ArrayRef<AttributeSet>(AS, "
@@ -692,9 +718,9 @@ EmitModRefBehavior(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS){
static void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM,
const std::string &TargetPrefix,
raw_ostream &OS) {
-
+
std::vector<StringMatcher::StringPair> Results;
-
+
for (std::map<std::string, std::string>::const_iterator I = BIM.begin(),
E = BIM.end(); I != E; ++I) {
std::string ResultCode =
@@ -705,9 +731,9 @@ static void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM,
StringMatcher("BuiltinName", Results, OS).Emit();
}
-
+
void IntrinsicEmitter::
-EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
+EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
raw_ostream &OS) {
typedef std::map<std::string, std::map<std::string, std::string> > BIMTy;
BIMTy BuiltinMap;
@@ -715,20 +741,20 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
if (!Ints[i].GCCBuiltinName.empty()) {
// Get the map for this target prefix.
std::map<std::string, std::string> &BIM =BuiltinMap[Ints[i].TargetPrefix];
-
+
if (!BIM.insert(std::make_pair(Ints[i].GCCBuiltinName,
Ints[i].EnumName)).second)
PrintFatalError("Intrinsic '" + Ints[i].TheDef->getName() +
"': duplicate GCC builtin name!");
}
}
-
+
OS << "// Get the LLVM intrinsic that corresponds to a GCC builtin.\n";
OS << "// This is used by the C front-end. The GCC builtin name is passed\n";
OS << "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n";
OS << "// in as TargetPrefix. The result is assigned to 'IntrinsicID'.\n";
OS << "#ifdef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN\n";
-
+
if (TargetOnly) {
OS << "static " << TargetPrefix << "Intrinsic::ID "
<< "getIntrinsicForGCCBuiltin(const char "
@@ -737,10 +763,10 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char "
<< "*TargetPrefixStr, const char *BuiltinNameStr) {\n";
}
-
+
OS << " StringRef BuiltinName(BuiltinNameStr);\n";
OS << " StringRef TargetPrefix(TargetPrefixStr);\n\n";
-
+
// Note: this could emit significantly better code if we cared.
for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){
OS << " ";
diff --git a/utils/TableGen/OptParserEmitter.cpp b/utils/TableGen/OptParserEmitter.cpp
index 86328bf..9c4daaf 100644
--- a/utils/TableGen/OptParserEmitter.cpp
+++ b/utils/TableGen/OptParserEmitter.cpp
@@ -13,18 +13,23 @@
#include "llvm/ADT/Twine.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
+#include <cstring>
+#include <cctype>
#include <map>
using namespace llvm;
+// Ordering on Info. The logic should match with the consumer-side function in
+// llvm/Option/OptTable.h.
static int StrCmpOptionName(const char *A, const char *B) {
- char a = *A, b = *B;
+ const char *X = A, *Y = B;
+ char a = tolower(*A), b = tolower(*B);
while (a == b) {
if (a == '\0')
- return 0;
+ return strcmp(A, B);
- a = *++A;
- b = *++B;
+ a = tolower(*++X);
+ b = tolower(*++Y);
}
if (a == '\0') // A is a prefix of B.
@@ -36,9 +41,9 @@ static int StrCmpOptionName(const char *A, const char *B) {
return (a < b) ? -1 : 1;
}
-static int CompareOptionRecords(const void *Av, const void *Bv) {
- const Record *A = *(const Record*const*) Av;
- const Record *B = *(const Record*const*) Bv;
+static int CompareOptionRecords(Record *const *Av, Record *const *Bv) {
+ const Record *A = *Av;
+ const Record *B = *Bv;
// Sentinel options precede all others and are only ordered by precedence.
bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel");
@@ -50,7 +55,7 @@ static int CompareOptionRecords(const void *Av, const void *Bv) {
if (!ASent)
if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(),
B->getValueAsString("Name").c_str()))
- return Cmp;
+ return Cmp;
if (!ASent) {
std::vector<std::string> APrefixes = A->getValueAsListOfStrings("Prefixes");
@@ -74,7 +79,7 @@ static int CompareOptionRecords(const void *Av, const void *Bv) {
if (APrec == BPrec &&
A->getValueAsListOfStrings("Prefixes") ==
B->getValueAsListOfStrings("Prefixes")) {
- PrintError(A->getLoc(), Twine("Option is equivilent to"));
+ PrintError(A->getLoc(), Twine("Option is equivalent to"));
PrintError(B->getLoc(), Twine("Other defined here"));
PrintFatalError("Equivalent Options found.");
}
diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp
index 731dccf..cc08df9 100644
--- a/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/utils/TableGen/RegisterInfoEmitter.cpp
@@ -121,7 +121,7 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << "}\n";
}
- const std::vector<Record*> RegAltNameIndices = Target.getRegAltNameIndices();
+ const std::vector<Record*> &RegAltNameIndices = Target.getRegAltNameIndices();
// If the only definition is the default NoRegAltName, we don't need to
// emit anything.
if (RegAltNameIndices.size() > 1) {
@@ -722,7 +722,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
// Keep track of sub-register names as well. These are not differentially
// encoded.
typedef SmallVector<const CodeGenSubRegIndex*, 4> SubRegIdxVec;
- SequenceToOffsetTable<SubRegIdxVec> SubRegIdxSeqs;
+ SequenceToOffsetTable<SubRegIdxVec, CodeGenSubRegIndex::Less> SubRegIdxSeqs;
SmallVector<SubRegIdxVec, 4> SubRegIdxLists(Regs.size());
SequenceToOffsetTable<std::string> RegStrings;
@@ -1090,7 +1090,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
// Compress the sub-reg index lists.
typedef std::vector<const CodeGenSubRegIndex*> IdxList;
SmallVector<IdxList, 8> SuperRegIdxLists(RegisterClasses.size());
- SequenceToOffsetTable<IdxList> SuperRegIdxSeqs;
+ SequenceToOffsetTable<IdxList, CodeGenSubRegIndex::Less> SuperRegIdxSeqs;
BitVector MaskBV(RegisterClasses.size());
for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) {
@@ -1314,9 +1314,21 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "0 };\n";
// Emit the *_RegMask bit mask of call-preserved registers.
+ BitVector Covered = RegBank.computeCoveredRegisters(*Regs);
+
+ // Check for an optional OtherPreserved set.
+ // Add those registers to RegMask, but not to SaveList.
+ if (DagInit *OPDag =
+ dyn_cast<DagInit>(CSRSet->getValueInit("OtherPreserved"))) {
+ SetTheory::RecSet OPSet;
+ RegBank.getSets().evaluate(OPDag, OPSet, CSRSet->getLoc());
+ Covered |= RegBank.computeCoveredRegisters(
+ ArrayRef<Record*>(OPSet.begin(), OPSet.end()));
+ }
+
OS << "static const uint32_t " << CSRSet->getName()
<< "_RegMask[] = { ";
- printBitVectorAsHex(OS, RegBank.computeCoveredRegisters(*Regs), 32);
+ printBitVectorAsHex(OS, Covered, 32);
OS << "};\n";
}
OS << "\n\n";
diff --git a/utils/TableGen/SequenceToOffsetTable.h b/utils/TableGen/SequenceToOffsetTable.h
index fcda233..e6ab664 100644
--- a/utils/TableGen/SequenceToOffsetTable.h
+++ b/utils/TableGen/SequenceToOffsetTable.h
@@ -21,6 +21,7 @@
#include <cassert>
#include <cctype>
#include <functional>
+#include <map>
#include <vector>
namespace llvm {
diff --git a/utils/TableGen/SetTheory.cpp b/utils/TableGen/SetTheory.cpp
index 3e5c38c..ad3d7c7 100644
--- a/utils/TableGen/SetTheory.cpp
+++ b/utils/TableGen/SetTheory.cpp
@@ -27,14 +27,16 @@ typedef SetTheory::RecVec RecVec;
// (add a, b, ...) Evaluate and union all arguments.
struct AddOp : public SetTheory::Operator {
- void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) {
+ virtual void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts,
+ ArrayRef<SMLoc> Loc) {
ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts, Loc);
}
};
// (sub Add, Sub, ...) Set difference.
struct SubOp : public SetTheory::Operator {
- void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) {
+ virtual void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts,
+ ArrayRef<SMLoc> Loc) {
if (Expr->arg_size() < 2)
PrintFatalError(Loc, "Set difference needs at least two arguments: " +
Expr->getAsString());
@@ -49,7 +51,8 @@ struct SubOp : public SetTheory::Operator {
// (and S1, S2) Set intersection.
struct AndOp : public SetTheory::Operator {
- void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) {
+ virtual void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts,
+ ArrayRef<SMLoc> Loc) {
if (Expr->arg_size() != 2)
PrintFatalError(Loc, "Set intersection requires two arguments: " +
Expr->getAsString());
@@ -68,7 +71,8 @@ struct SetIntBinOp : public SetTheory::Operator {
RecSet &Set, int64_t N,
RecSet &Elts, ArrayRef<SMLoc> Loc) =0;
- void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) {
+ virtual void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts,
+ ArrayRef<SMLoc> Loc) {
if (Expr->arg_size() != 2)
PrintFatalError(Loc, "Operator requires (Op Set, Int) arguments: " +
Expr->getAsString());
@@ -84,9 +88,9 @@ struct SetIntBinOp : public SetTheory::Operator {
// (shl S, N) Shift left, remove the first N elements.
struct ShlOp : public SetIntBinOp {
- void apply2(SetTheory &ST, DagInit *Expr,
- RecSet &Set, int64_t N,
- RecSet &Elts, ArrayRef<SMLoc> Loc) {
+ virtual void apply2(SetTheory &ST, DagInit *Expr,
+ RecSet &Set, int64_t N,
+ RecSet &Elts, ArrayRef<SMLoc> Loc) {
if (N < 0)
PrintFatalError(Loc, "Positive shift required: " +
Expr->getAsString());
@@ -97,9 +101,9 @@ struct ShlOp : public SetIntBinOp {
// (trunc S, N) Truncate after the first N elements.
struct TruncOp : public SetIntBinOp {
- void apply2(SetTheory &ST, DagInit *Expr,
- RecSet &Set, int64_t N,
- RecSet &Elts, ArrayRef<SMLoc> Loc) {
+ virtual void apply2(SetTheory &ST, DagInit *Expr,
+ RecSet &Set, int64_t N,
+ RecSet &Elts, ArrayRef<SMLoc> Loc) {
if (N < 0)
PrintFatalError(Loc, "Positive length required: " +
Expr->getAsString());
@@ -115,9 +119,9 @@ struct RotOp : public SetIntBinOp {
RotOp(bool Rev) : Reverse(Rev) {}
- void apply2(SetTheory &ST, DagInit *Expr,
- RecSet &Set, int64_t N,
- RecSet &Elts, ArrayRef<SMLoc> Loc) {
+ virtual void apply2(SetTheory &ST, DagInit *Expr,
+ RecSet &Set, int64_t N,
+ RecSet &Elts, ArrayRef<SMLoc> Loc) {
if (Reverse)
N = -N;
// N > 0 -> rotate left, N < 0 -> rotate right.
@@ -134,9 +138,9 @@ struct RotOp : public SetIntBinOp {
// (decimate S, N) Pick every N'th element of S.
struct DecimateOp : public SetIntBinOp {
- void apply2(SetTheory &ST, DagInit *Expr,
- RecSet &Set, int64_t N,
- RecSet &Elts, ArrayRef<SMLoc> Loc) {
+ virtual void apply2(SetTheory &ST, DagInit *Expr,
+ RecSet &Set, int64_t N,
+ RecSet &Elts, ArrayRef<SMLoc> Loc) {
if (N <= 0)
PrintFatalError(Loc, "Positive stride required: " +
Expr->getAsString());
@@ -147,7 +151,8 @@ struct DecimateOp : public SetIntBinOp {
// (interleave S1, S2, ...) Interleave elements of the arguments.
struct InterleaveOp : public SetTheory::Operator {
- void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) {
+ virtual void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts,
+ ArrayRef<SMLoc> Loc) {
// Evaluate the arguments individually.
SmallVector<RecSet, 4> Args(Expr->getNumArgs());
unsigned MaxSize = 0;
@@ -165,7 +170,8 @@ struct InterleaveOp : public SetTheory::Operator {
// (sequence "Format", From, To) Generate a sequence of records by name.
struct SequenceOp : public SetTheory::Operator {
- void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts, ArrayRef<SMLoc> Loc) {
+ virtual void apply(SetTheory &ST, DagInit *Expr, RecSet &Elts,
+ ArrayRef<SMLoc> Loc) {
int Step = 1;
if (Expr->arg_size() > 4)
PrintFatalError(Loc, "Bad args to (sequence \"Format\", From, To): " +
@@ -232,15 +238,16 @@ struct FieldExpander : public SetTheory::Expander {
FieldExpander(StringRef fn) : FieldName(fn) {}
- void expand(SetTheory &ST, Record *Def, RecSet &Elts) {
+ virtual void expand(SetTheory &ST, Record *Def, RecSet &Elts) {
ST.evaluate(Def->getValueInit(FieldName), Elts, Def->getLoc());
}
};
} // end anonymous namespace
-void SetTheory::Operator::anchor() { }
+// Pin the vtables to this file.
+void SetTheory::Operator::anchor() {}
+void SetTheory::Expander::anchor() {}
-void SetTheory::Expander::anchor() { }
SetTheory::SetTheory() {
addOperator("add", new AddOp);
diff --git a/utils/TableGen/StringToOffsetTable.h b/utils/TableGen/StringToOffsetTable.h
deleted file mode 100644
index d94d3a2..0000000
--- a/utils/TableGen/StringToOffsetTable.h
+++ /dev/null
@@ -1,83 +0,0 @@
-//===- StringToOffsetTable.h - Emit a big concatenated string ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef TBLGEN_STRING_TO_OFFSET_TABLE_H
-#define TBLGEN_STRING_TO_OFFSET_TABLE_H
-
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cctype>
-
-namespace llvm {
-
-/// StringToOffsetTable - This class uniques a bunch of nul-terminated strings
-/// and keeps track of their offset in a massive contiguous string allocation.
-/// It can then output this string blob and use indexes into the string to
-/// reference each piece.
-class StringToOffsetTable {
- StringMap<unsigned> StringOffset;
- std::string AggregateString;
-public:
-
- unsigned GetOrAddStringOffset(StringRef Str, bool appendZero = true) {
- StringMapEntry<unsigned> &Entry = StringOffset.GetOrCreateValue(Str, -1U);
- if (Entry.getValue() == -1U) {
- // Add the string to the aggregate if this is the first time found.
- Entry.setValue(AggregateString.size());
- AggregateString.append(Str.begin(), Str.end());
- if (appendZero)
- AggregateString += '\0';
- }
-
- return Entry.getValue();
- }
-
- void EmitString(raw_ostream &O) {
- // Escape the string.
- SmallString<256> Str;
- raw_svector_ostream(Str).write_escaped(AggregateString);
- AggregateString = Str.str();
-
- O << " \"";
- unsigned CharsPrinted = 0;
- for (unsigned i = 0, e = AggregateString.size(); i != e; ++i) {
- if (CharsPrinted > 70) {
- O << "\"\n \"";
- CharsPrinted = 0;
- }
- O << AggregateString[i];
- ++CharsPrinted;
-
- // Print escape sequences all together.
- if (AggregateString[i] != '\\')
- continue;
-
- assert(i+1 < AggregateString.size() && "Incomplete escape sequence!");
- if (isdigit(AggregateString[i+1])) {
- assert(isdigit(AggregateString[i+2]) &&
- isdigit(AggregateString[i+3]) &&
- "Expected 3 digit octal escape!");
- O << AggregateString[++i];
- O << AggregateString[++i];
- O << AggregateString[++i];
- CharsPrinted += 3;
- } else {
- O << AggregateString[++i];
- ++CharsPrinted;
- }
- }
- O << "\"";
- }
-};
-
-} // end namespace llvm
-
-#endif
diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp
index 81bb6f8..b9f9d06 100644
--- a/utils/TableGen/SubtargetEmitter.cpp
+++ b/utils/TableGen/SubtargetEmitter.cpp
@@ -1198,6 +1198,11 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ',');
EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ',');
EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ',');
+
+ OS << " " << (bool)(PI->ModelDef ?
+ PI->ModelDef->getValueAsBit("CompleteModel") : 0)
+ << ", // " << "CompleteModel\n";
+
OS << " " << PI->Index << ", // Processor ID\n";
if (PI->hasInstrSchedModel())
OS << " " << PI->ModelName << "ProcResources" << ",\n"
diff --git a/utils/TableGen/TGValueTypes.cpp b/utils/TableGen/TGValueTypes.cpp
index 3ac71a4..f4893f5 100644
--- a/utils/TableGen/TGValueTypes.cpp
+++ b/utils/TableGen/TGValueTypes.cpp
@@ -35,11 +35,15 @@ public:
}
Type(TypeKind K) : Kind(K) {}
virtual unsigned getSizeInBits() const = 0;
- virtual ~Type() {}
+ virtual ~Type();
};
+// Provide out-of-line definition to prevent weak vtable.
+Type::~Type() {}
+
}
+namespace {
class ExtendedIntegerType : public Type {
unsigned BitWidth;
public:
@@ -48,7 +52,7 @@ public:
static bool classof(const Type *T) {
return T->getKind() == TK_ExtendedIntegerType;
}
- unsigned getSizeInBits() const {
+ virtual unsigned getSizeInBits() const {
return getBitWidth();
}
unsigned getBitWidth() const {
@@ -65,7 +69,7 @@ public:
static bool classof(const Type *T) {
return T->getKind() == TK_ExtendedVectorType;
}
- unsigned getSizeInBits() const {
+ virtual unsigned getSizeInBits() const {
return getNumElements() * getElementType().getSizeInBits();
}
EVT getElementType() const {
@@ -75,6 +79,7 @@ public:
return NumElements;
}
};
+} // end anonymous namespace
static std::map<unsigned, const Type *>
ExtendedIntegerTypeMap;
diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp
index 0838ac4..bdb4793 100644
--- a/utils/TableGen/X86DisassemblerTables.cpp
+++ b/utils/TableGen/X86DisassemblerTables.cpp
@@ -81,31 +81,37 @@ static inline bool inheritsFrom(InstructionContext child,
case IC_64BIT_REXW_OPSIZE:
return false;
case IC_VEX:
- return inheritsFrom(child, IC_VEX_L_W) ||
+ return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W)) ||
inheritsFrom(child, IC_VEX_W) ||
(VEX_LIG && inheritsFrom(child, IC_VEX_L));
case IC_VEX_XS:
- return inheritsFrom(child, IC_VEX_L_W_XS) ||
+ return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W_XS)) ||
inheritsFrom(child, IC_VEX_W_XS) ||
(VEX_LIG && inheritsFrom(child, IC_VEX_L_XS));
case IC_VEX_XD:
- return inheritsFrom(child, IC_VEX_L_W_XD) ||
+ return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W_XD)) ||
inheritsFrom(child, IC_VEX_W_XD) ||
(VEX_LIG && inheritsFrom(child, IC_VEX_L_XD));
case IC_VEX_OPSIZE:
- return inheritsFrom(child, IC_VEX_L_W_OPSIZE) ||
+ return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W_OPSIZE)) ||
inheritsFrom(child, IC_VEX_W_OPSIZE) ||
(VEX_LIG && inheritsFrom(child, IC_VEX_L_OPSIZE));
case IC_VEX_W:
+ return VEX_LIG && inheritsFrom(child, IC_VEX_L_W);
case IC_VEX_W_XS:
+ return VEX_LIG && inheritsFrom(child, IC_VEX_L_W_XS);
case IC_VEX_W_XD:
+ return VEX_LIG && inheritsFrom(child, IC_VEX_L_W_XD);
case IC_VEX_W_OPSIZE:
- return false;
+ return VEX_LIG && inheritsFrom(child, IC_VEX_L_W_OPSIZE);
case IC_VEX_L:
+ return inheritsFrom(child, IC_VEX_L_W);
case IC_VEX_L_XS:
+ return inheritsFrom(child, IC_VEX_L_W_XS);
case IC_VEX_L_XD:
+ return inheritsFrom(child, IC_VEX_L_W_XD);
case IC_VEX_L_OPSIZE:
- return false;
+ return inheritsFrom(child, IC_VEX_L_W_OPSIZE);
case IC_VEX_L_W:
case IC_VEX_L_W_XS:
case IC_VEX_L_W_XD:
@@ -122,7 +128,7 @@ static inline bool inheritsFrom(InstructionContext child,
inheritsFrom(child, IC_EVEX_L_W_XD);
case IC_EVEX_OPSIZE:
return inheritsFrom(child, IC_EVEX_W_OPSIZE) ||
- inheritsFrom(child, IC_EVEX_W_OPSIZE);
+ inheritsFrom(child, IC_EVEX_L_W_OPSIZE);
case IC_EVEX_W:
case IC_EVEX_W_XS:
case IC_EVEX_W_XD:
@@ -170,10 +176,24 @@ static inline bool inheritsFrom(InstructionContext child,
case IC_EVEX_L_XD_K:
case IC_EVEX_L_OPSIZE_K:
return false;
+ case IC_EVEX_W_KZ:
+ case IC_EVEX_W_XS_KZ:
+ case IC_EVEX_W_XD_KZ:
+ case IC_EVEX_W_OPSIZE_KZ:
+ return false;
+ case IC_EVEX_L_KZ:
+ case IC_EVEX_L_XS_KZ:
+ case IC_EVEX_L_XD_KZ:
+ case IC_EVEX_L_OPSIZE_KZ:
+ return false;
case IC_EVEX_L_W_K:
case IC_EVEX_L_W_XS_K:
case IC_EVEX_L_W_XD_K:
case IC_EVEX_L_W_OPSIZE_K:
+ case IC_EVEX_L_W_KZ:
+ case IC_EVEX_L_W_XS_KZ:
+ case IC_EVEX_L_W_XD_KZ:
+ case IC_EVEX_L_W_OPSIZE_KZ:
return false;
case IC_EVEX_L2_K:
case IC_EVEX_L2_B:
@@ -181,12 +201,25 @@ static inline bool inheritsFrom(InstructionContext child,
case IC_EVEX_L2_XD_K:
case IC_EVEX_L2_OPSIZE_K:
case IC_EVEX_L2_OPSIZE_B:
+ case IC_EVEX_L2_OPSIZE_K_B:
+ case IC_EVEX_L2_KZ:
+ case IC_EVEX_L2_XS_KZ:
+ case IC_EVEX_L2_XD_KZ:
+ case IC_EVEX_L2_OPSIZE_KZ:
+ case IC_EVEX_L2_OPSIZE_KZ_B:
return false;
case IC_EVEX_L2_W_K:
+ case IC_EVEX_L2_W_B:
case IC_EVEX_L2_W_XS_K:
case IC_EVEX_L2_W_XD_K:
case IC_EVEX_L2_W_OPSIZE_K:
case IC_EVEX_L2_W_OPSIZE_B:
+ case IC_EVEX_L2_W_OPSIZE_K_B:
+ case IC_EVEX_L2_W_KZ:
+ case IC_EVEX_L2_W_XS_KZ:
+ case IC_EVEX_L2_W_XD_KZ:
+ case IC_EVEX_L2_W_OPSIZE_KZ:
+ case IC_EVEX_L2_W_OPSIZE_KZ_B:
return false;
default:
llvm_unreachable("Unknown instruction class");
@@ -207,7 +240,8 @@ static inline bool outranks(InstructionContext upper,
#define ENUM_ENTRY(n, r, d) r,
#define ENUM_ENTRY_K_B(n, r, d) ENUM_ENTRY(n, r, d) \
- ENUM_ENTRY(n##_K_B, r, d) ENUM_ENTRY(n##_K, r, d) ENUM_ENTRY(n##_B, r, d)
+ ENUM_ENTRY(n##_K_B, r, d) ENUM_ENTRY(n##_KZ_B, r, d) \
+ ENUM_ENTRY(n##_KZ, r, d) ENUM_ENTRY(n##_K, r, d) ENUM_ENTRY(n##_B, r, d)
static int ranks[IC_max] = {
INSTRUCTION_CONTEXTS
};
@@ -229,7 +263,8 @@ static inline const char* stringForContext(InstructionContext insnContext) {
llvm_unreachable("Unhandled instruction class");
#define ENUM_ENTRY(n, r, d) case n: return #n; break;
#define ENUM_ENTRY_K_B(n, r, d) ENUM_ENTRY(n, r, d) ENUM_ENTRY(n##_K_B, r, d)\
- ENUM_ENTRY(n##_K, r, d) ENUM_ENTRY(n##_B, r, d)
+ ENUM_ENTRY(n##_KZ, r, d) ENUM_ENTRY(n##_K, r, d) ENUM_ENTRY(n##_B, r, d)\
+ ENUM_ENTRY(n##_KZ_B, r, d)
INSTRUCTION_CONTEXTS
#undef ENUM_ENTRY
#undef ENUM_ENTRY_K_B
@@ -259,35 +294,6 @@ static inline const char* stringForOperandEncoding(OperandEncoding encoding) {
}
}
-void DisassemblerTables::emitOneID(raw_ostream &o, unsigned &i, InstrUID id,
- bool addComma) const {
- if (id)
- o.indent(i * 2) << format("0x%hx", id);
- else
- o.indent(i * 2) << 0;
-
- if (addComma)
- o << ", ";
- else
- o << " ";
-
- o << "/* ";
- o << InstructionSpecifiers[id].name;
- o << "*/";
-
- o << "\n";
-}
-
-/// emitEmptyTable - Emits the modRMEmptyTable, which is used as a ID table by
-/// all ModR/M decisions for instructions that are invalid for all possible
-/// ModR/M byte values.
-///
-/// @param o - The output stream on which to emit the table.
-/// @param i - The indentation level for that output stream.
-static void emitEmptyTable(raw_ostream &o, unsigned &i) {
- o.indent(i * 2) << "0x0, /* EmptyTable */\n";
-}
-
/// getDecisionType - Determines whether a ModRM decision with 255 entries can
/// be compacted by eliminating redundant information.
///
@@ -387,6 +393,7 @@ DisassemblerTables::~DisassemblerTables() {
void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
unsigned &i1, unsigned &i2,
+ unsigned &ModRMTableNum,
ModRMDecision &decision) const {
static uint32_t sTableNumber = 0;
static uint32_t sEntryNumber = 1;
@@ -405,44 +412,56 @@ void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
return;
}
- o1 << "/* Table" << sTableNumber << " */\n";
- i1++;
+ std::vector<unsigned> ModRMDecision;
switch (dt) {
default:
llvm_unreachable("Unknown decision type");
case MODRM_ONEENTRY:
- emitOneID(o1, i1, decision.instructionIDs[0], true);
+ ModRMDecision.push_back(decision.instructionIDs[0]);
break;
case MODRM_SPLITRM:
- emitOneID(o1, i1, decision.instructionIDs[0x00], true); // mod = 0b00
- emitOneID(o1, i1, decision.instructionIDs[0xc0], true); // mod = 0b11
+ ModRMDecision.push_back(decision.instructionIDs[0x00]);
+ ModRMDecision.push_back(decision.instructionIDs[0xc0]);
break;
case MODRM_SPLITREG:
for (unsigned index = 0; index < 64; index += 8)
- emitOneID(o1, i1, decision.instructionIDs[index], true);
+ ModRMDecision.push_back(decision.instructionIDs[index]);
for (unsigned index = 0xc0; index < 256; index += 8)
- emitOneID(o1, i1, decision.instructionIDs[index], true);
+ ModRMDecision.push_back(decision.instructionIDs[index]);
break;
case MODRM_SPLITMISC:
for (unsigned index = 0; index < 64; index += 8)
- emitOneID(o1, i1, decision.instructionIDs[index], true);
+ ModRMDecision.push_back(decision.instructionIDs[index]);
for (unsigned index = 0xc0; index < 256; ++index)
- emitOneID(o1, i1, decision.instructionIDs[index], true);
+ ModRMDecision.push_back(decision.instructionIDs[index]);
break;
case MODRM_FULL:
for (unsigned index = 0; index < 256; ++index)
- emitOneID(o1, i1, decision.instructionIDs[index], true);
+ ModRMDecision.push_back(decision.instructionIDs[index]);
break;
}
- i1--;
+ unsigned &EntryNumber = ModRMTable[ModRMDecision];
+ if (EntryNumber == 0) {
+ EntryNumber = ModRMTableNum;
+
+ ModRMTableNum += ModRMDecision.size();
+ o1 << "/* Table" << EntryNumber << " */\n";
+ i1++;
+ for (std::vector<unsigned>::const_iterator I = ModRMDecision.begin(),
+ E = ModRMDecision.end(); I != E; ++I) {
+ o1.indent(i1 * 2) << format("0x%hx", *I) << ", /* "
+ << InstructionSpecifiers[*I].name << " */\n";
+ }
+ i1--;
+ }
o2.indent(i2) << "{ /* struct ModRMDecision */" << "\n";
i2++;
o2.indent(i2) << stringForDecisionType(dt) << "," << "\n";
- o2.indent(i2) << sEntryNumber << " /* Table" << sTableNumber << " */\n";
+ o2.indent(i2) << EntryNumber << " /* Table" << EntryNumber << " */\n";
i2--;
o2.indent(i2) << "}";
@@ -476,6 +495,7 @@ void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
void DisassemblerTables::emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2,
unsigned &i1, unsigned &i2,
+ unsigned &ModRMTableNum,
OpcodeDecision &decision) const {
o2.indent(i2) << "{ /* struct OpcodeDecision */" << "\n";
i2++;
@@ -487,7 +507,8 @@ void DisassemblerTables::emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2,
o2 << "/* 0x" << format("%02hhx", index) << " */" << "\n";
- emitModRMDecision(o1, o2, i1, i2, decision.modRMDecisions[index]);
+ emitModRMDecision(o1, o2, i1, i2, ModRMTableNum,
+ decision.modRMDecisions[index]);
if (index < 255)
o2 << ",";
@@ -503,6 +524,7 @@ void DisassemblerTables::emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2,
void DisassemblerTables::emitContextDecision(raw_ostream &o1, raw_ostream &o2,
unsigned &i1, unsigned &i2,
+ unsigned &ModRMTableNum,
ContextDecision &decision,
const char* name) const {
o2.indent(i2) << "static const struct ContextDecision " << name << " = {\n";
@@ -516,7 +538,8 @@ void DisassemblerTables::emitContextDecision(raw_ostream &o1, raw_ostream &o2,
o2 << " */";
o2 << "\n";
- emitOpcodeDecision(o1, o2, i1, i2, decision.opcodeDecisions[index]);
+ emitOpcodeDecision(o1, o2, i1, i2, ModRMTableNum,
+ decision.opcodeDecisions[index]);
if (index + 1 < IC_max)
o2 << ", ";
@@ -622,6 +645,12 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_OPSIZE))
o << "IC_VEX_L_W_OPSIZE";
+ else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_XD))
+ o << "IC_VEX_L_W_XD";
+ else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_XS))
+ o << "IC_VEX_L_W_XS";
+ else if ((index & ATTR_VEXL) && (index & ATTR_REXW))
+ o << "IC_VEX_L_W";
else if ((index & ATTR_VEXL) && (index & ATTR_OPSIZE))
o << "IC_VEX_L_OPSIZE";
else if ((index & ATTR_VEXL) && (index & ATTR_XD))
@@ -699,13 +728,17 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
}
void DisassemblerTables::emitContextDecisions(raw_ostream &o1, raw_ostream &o2,
- unsigned &i1, unsigned &i2) const {
- emitContextDecision(o1, o2, i1, i2, *Tables[0], ONEBYTE_STR);
- emitContextDecision(o1, o2, i1, i2, *Tables[1], TWOBYTE_STR);
- emitContextDecision(o1, o2, i1, i2, *Tables[2], THREEBYTE38_STR);
- emitContextDecision(o1, o2, i1, i2, *Tables[3], THREEBYTE3A_STR);
- emitContextDecision(o1, o2, i1, i2, *Tables[4], THREEBYTEA6_STR);
- emitContextDecision(o1, o2, i1, i2, *Tables[5], THREEBYTEA7_STR);
+ unsigned &i1, unsigned &i2,
+ unsigned &ModRMTableNum) const {
+ emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[0], ONEBYTE_STR);
+ emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[1], TWOBYTE_STR);
+ emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[2], THREEBYTE38_STR);
+ emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[3], THREEBYTE3A_STR);
+ emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[4], THREEBYTEA6_STR);
+ emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[5], THREEBYTEA7_STR);
+ emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[6], XOP8_MAP_STR);
+ emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[7], XOP9_MAP_STR);
+ emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[8], XOPA_MAP_STR);
}
void DisassemblerTables::emit(raw_ostream &o) const {
@@ -724,11 +757,17 @@ void DisassemblerTables::emit(raw_ostream &o) const {
emitContextTable(o, i2);
o << "\n";
+ unsigned ModRMTableNum = 0;
+
o << "static const InstrUID modRMTable[] = {\n";
i1++;
- emitEmptyTable(o1, i1);
+ std::vector<unsigned> EmptyTable(1, 0);
+ ModRMTable[EmptyTable] = ModRMTableNum;
+ ModRMTableNum += EmptyTable.size();
+ o1 << "/* EmptyTable */\n";
+ o1.indent(i1 * 2) << "0x0,\n";
i1--;
- emitContextDecisions(o1, o2, i1, i2);
+ emitContextDecisions(o1, o2, i1, i2, ModRMTableNum);
o << o1.str();
o << " 0x0\n";
diff --git a/utils/TableGen/X86DisassemblerTables.h b/utils/TableGen/X86DisassemblerTables.h
index 01aeaaf..bf8b127 100644
--- a/utils/TableGen/X86DisassemblerTables.h
+++ b/utils/TableGen/X86DisassemblerTables.h
@@ -20,6 +20,7 @@
#include "X86DisassemblerShared.h"
#include "X86ModRMFilters.h"
#include "llvm/Support/raw_ostream.h"
+#include <map>
#include <vector>
namespace llvm {
@@ -39,7 +40,14 @@ private:
/// [3] three-byte opcodes of the form 0f 3a __
/// [4] three-byte opcodes of the form 0f a6 __
/// [5] three-byte opcodes of the form 0f a7 __
- ContextDecision* Tables[6];
+ /// [6] XOP8 map opcode
+ /// [7] XOP9 map opcode
+ /// [8] XOPA map opcode
+ ContextDecision* Tables[9];
+
+ // Table of ModRM encodings.
+ typedef std::map<std::vector<unsigned>, unsigned> ModRMMapTy;
+ mutable ModRMMapTy ModRMTable;
/// The instruction information table
std::vector<InstructionSpecifier> InstructionSpecifiers;
@@ -47,22 +55,6 @@ private:
/// True if there are primary decode conflicts in the instruction set
bool HasConflicts;
- /// emitOneID - Emits a table entry for a single instruction entry, at the
- /// innermost level of the structure hierarchy. The entry is printed out
- /// in the format "nnnn, /* MNEMONIC */" where nnnn is the ID in decimal,
- /// the comma is printed if addComma is true, and the menonic is the name
- /// of the instruction as listed in the LLVM tables.
- ///
- /// @param o - The output stream to print the entry on.
- /// @param i - The indentation level for o.
- /// @param id - The unique ID of the instruction to print.
- /// @param addComma - Whether or not to print a comma after the ID. True if
- /// additional items will follow.
- void emitOneID(raw_ostream &o,
- uint32_t &i,
- InstrUID id,
- bool addComma) const;
-
/// emitModRMDecision - Emits a table of entries corresponding to a single
/// ModR/M decision. Compacts the ModR/M decision if possible. ModR/M
/// decisions are printed as:
@@ -91,12 +83,11 @@ private:
/// @param o2 - The output stream to print the decision structure to.
/// @param i1 - The indentation level to use with stream o1.
/// @param i2 - The indentation level to use with stream o2.
+ /// @param ModRMTableNum - next table number for adding to ModRMTable.
/// @param decision - The ModR/M decision to emit. This decision has 256
/// entries - emitModRMDecision decides how to compact it.
- void emitModRMDecision(raw_ostream &o1,
- raw_ostream &o2,
- uint32_t &i1,
- uint32_t &i2,
+ void emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
+ unsigned &i1, unsigned &i2, unsigned &ModRMTableNum,
ModRMDecision &decision) const;
/// emitOpcodeDecision - Emits an OpcodeDecision and all its subsidiary ModR/M
@@ -120,12 +111,11 @@ private:
/// @param o2 - The output stream for the decision structure itself.
/// @param i1 - The indent level to use with stream o1.
/// @param i2 - The indent level to use with stream o2.
+ /// @param ModRMTableNum - next table number for adding to ModRMTable.
/// @param decision - The OpcodeDecision to emit along with its subsidiary
/// structures.
- void emitOpcodeDecision(raw_ostream &o1,
- raw_ostream &o2,
- uint32_t &i1,
- uint32_t &i2,
+ void emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2,
+ unsigned &i1, unsigned &i2, unsigned &ModRMTableNum,
OpcodeDecision &decision) const;
/// emitContextDecision - Emits a ContextDecision and all its subsidiary
@@ -155,15 +145,13 @@ private:
/// @param o2 - The output stream to print the decision structure to.
/// @param i1 - The indent level to use with stream o1.
/// @param i2 - The indent level to use with stream o2.
+ /// @param ModRMTableNum - next table number for adding to ModRMTable.
/// @param decision - The ContextDecision to emit along with its subsidiary
/// structures.
/// @param name - The name for the ContextDecision.
- void emitContextDecision(raw_ostream &o1,
- raw_ostream &o2,
- uint32_t &i1,
- uint32_t &i2,
- ContextDecision &decision,
- const char* name) const;
+ void emitContextDecision(raw_ostream &o1, raw_ostream &o2,
+ unsigned &i1, unsigned &i2, unsigned &ModRMTableNum,
+ ContextDecision &decision, const char* name) const;
/// emitInstructionInfo - Prints the instruction specifier table, which has
/// one entry for each instruction, and contains name and operand
@@ -194,7 +182,7 @@ private:
/// @param o - The output stream to which the instruction table should be
/// written.
/// @param i - The indent level for use with the stream.
- void emitInstructionInfo(raw_ostream &o, uint32_t &i) const;
+ void emitInstructionInfo(raw_ostream &o, unsigned &i) const;
/// emitContextTable - Prints the table that is used to translate from an
/// instruction attribute mask to an instruction context. This table is
@@ -220,10 +208,10 @@ private:
/// @param o2 - The output stream to print the decision structures to.
/// @param i1 - The indent level to use with stream o1.
/// @param i2 - The indent level to use with stream o2.
- void emitContextDecisions(raw_ostream &o1,
- raw_ostream &o2,
- uint32_t &i1,
- uint32_t &i2) const;
+ /// @param ModRMTableNum - next table number for adding to ModRMTable.
+ void emitContextDecisions(raw_ostream &o1, raw_ostream &o2,
+ unsigned &i1, unsigned &i2,
+ unsigned &ModRMTableNum) const;
/// setTableFields - Uses a ModRMFilter to set the appropriate entries in a
/// ModRMDecision to refer to a particular instruction ID.
diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp
index 7962f9b..708e72d 100644
--- a/utils/TableGen/X86RecognizableInstr.cpp
+++ b/utils/TableGen/X86RecognizableInstr.cpp
@@ -79,7 +79,8 @@ namespace X86Local {
DC = 7, DD = 8, DE = 9, DF = 10,
XD = 11, XS = 12,
T8 = 13, P_TA = 14,
- A6 = 15, A7 = 16, T8XD = 17, T8XS = 18, TAXD = 19
+ A6 = 15, A7 = 16, T8XD = 17, T8XS = 18, TAXD = 19,
+ XOP8 = 20, XOP9 = 21, XOPA = 22
};
}
@@ -134,6 +135,10 @@ namespace X86Local {
#define THREE_BYTE_38_EXTENSION_TABLES \
EXTENSION_TABLE(F3)
+#define XOP9_MAP_EXTENSION_TABLES \
+ EXTENSION_TABLE(01) \
+ EXTENSION_TABLE(02)
+
using namespace X86Disassembler;
/// needsModRMForDecode - Indicates whether a particular instruction requires a
@@ -239,6 +244,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
HasEVEXPrefix = Rec->getValueAsBit("hasEVEXPrefix");
HasEVEX_L2Prefix = Rec->getValueAsBit("hasEVEX_L2");
HasEVEX_K = Rec->getValueAsBit("hasEVEX_K");
+ HasEVEX_KZ = Rec->getValueAsBit("hasEVEX_Z");
HasEVEX_B = Rec->getValueAsBit("hasEVEX_B");
HasLockPrefix = Rec->getValueAsBit("hasLockPrefix");
IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly");
@@ -299,8 +305,10 @@ void RecognizableInstr::processInstr(DisassemblerTables &tables,
recogInstr.emitDecodePath(tables);
}
-#define EVEX_KB(n) (HasEVEX_K && HasEVEX_B? n##_K_B : \
- (HasEVEX_K? n##_K : (HasEVEX_B ? n##_B : n)))
+#define EVEX_KB(n) (HasEVEX_KZ && HasEVEX_B ? n##_KZ_B : \
+ (HasEVEX_K && HasEVEX_B ? n##_K_B : \
+ (HasEVEX_KZ ? n##_KZ : \
+ (HasEVEX_K? n##_K : (HasEVEX_B ? n##_B : n)))))
InstructionContext RecognizableInstr::insnContext() const {
InstructionContext insnContext;
@@ -486,7 +494,8 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const {
assert(Rec->isSubClassOf("X86Inst") && "Can only filter X86 instructions");
if (Form == X86Local::Pseudo ||
- (IsCodeGenOnly && Name.find("_REV") == Name.npos))
+ (IsCodeGenOnly && Name.find("_REV") == Name.npos &&
+ Name.find("INC32") == Name.npos && Name.find("DEC32") == Name.npos))
return FILTER_STRONG;
@@ -516,35 +525,17 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const {
// Filter out alternate forms of AVX instructions
if (Name.find("_alt") != Name.npos ||
- Name.find("XrYr") != Name.npos ||
- (Name.find("r64r") != Name.npos && Name.find("r64r64") == Name.npos) ||
+ (Name.find("r64r") != Name.npos && Name.find("r64r64") == Name.npos && Name.find("r64r8") == Name.npos) ||
Name.find("_64mr") != Name.npos ||
- Name.find("Xrr") != Name.npos ||
Name.find("rr64") != Name.npos)
return FILTER_WEAK;
// Special cases.
- if (Name.find("PCMPISTRI") != Name.npos && Name != "PCMPISTRI")
- return FILTER_WEAK;
- if (Name.find("PCMPESTRI") != Name.npos && Name != "PCMPESTRI")
- return FILTER_WEAK;
-
- if (Name.find("MOV") != Name.npos && Name.find("r0") != Name.npos)
- return FILTER_WEAK;
- if (Name.find("MOVZ") != Name.npos && Name.find("MOVZX") == Name.npos)
- return FILTER_WEAK;
- if (Name.find("Fs") != Name.npos)
- return FILTER_WEAK;
if (Name == "PUSH64i16" ||
Name == "MOVPQI2QImr" ||
Name == "VMOVPQI2QImr" ||
- Name == "MMX_MOVD64rrv164" ||
- Name == "MOV64ri64i32" ||
- Name == "VMASKMOVDQU64" ||
- Name == "VEXTRACTPSrr64" ||
- Name == "VMOVQd64rr" ||
- Name == "VMOVQs64rr")
+ Name == "VMASKMOVDQU64")
return FILTER_WEAK;
// XACQUIRE and XRELEASE reuse REPNE and REP respectively.
@@ -553,11 +544,6 @@ RecognizableInstr::filter_ret RecognizableInstr::filter() const {
Name == "XRELEASE_PREFIX")
return FILTER_WEAK;
- if (HasFROperands && Name.find("MOV") != Name.npos &&
- ((Name.find("2") != Name.npos && Name.find("32") == Name.npos) ||
- (Name.find("to") != Name.npos)))
- return FILTER_STRONG;
-
return FILTER_NORMAL;
}
@@ -818,17 +804,20 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
case X86Local::MRM5r:
case X86Local::MRM6r:
case X86Local::MRM7r:
- // Operand 1 is a register operand in the R/M field.
- // Operand 2 (optional) is an immediate or relocation.
- // Operand 3 (optional) is an immediate.
- if (HasVEX_4VPrefix)
- assert(numPhysicalOperands <= 3 &&
- "Unexpected number of operands for MRMnRFrm with VEX_4V");
- else
- assert(numPhysicalOperands <= 3 &&
- "Unexpected number of operands for MRMnRFrm");
+ {
+ // Operand 1 is a register operand in the R/M field.
+ // Operand 2 (optional) is an immediate or relocation.
+ // Operand 3 (optional) is an immediate.
+ unsigned kOp = (HasEVEX_K) ? 1:0;
+ unsigned Op4v = (HasVEX_4VPrefix) ? 1:0;
+ if (numPhysicalOperands > 3 + kOp + Op4v)
+ llvm_unreachable("Unexpected number of operands for MRMnr");
+ }
if (HasVEX_4VPrefix)
HANDLE_OPERAND(vvvvRegister)
+
+ if (HasEVEX_K)
+ HANDLE_OPERAND(writemaskRegister)
HANDLE_OPTIONAL(rmRegister)
HANDLE_OPTIONAL(relocation)
HANDLE_OPTIONAL(immediate)
@@ -841,16 +830,19 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
case X86Local::MRM5m:
case X86Local::MRM6m:
case X86Local::MRM7m:
- // Operand 1 is a memory operand (possibly SIB-extended)
- // Operand 2 (optional) is an immediate or relocation.
- if (HasVEX_4VPrefix)
- assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 &&
- "Unexpected number of operands for MRMnMFrm");
- else
- assert(numPhysicalOperands >= 1 && numPhysicalOperands <= 2 &&
- "Unexpected number of operands for MRMnMFrm");
+ {
+ // Operand 1 is a memory operand (possibly SIB-extended)
+ // Operand 2 (optional) is an immediate or relocation.
+ unsigned kOp = (HasEVEX_K) ? 1:0;
+ unsigned Op4v = (HasVEX_4VPrefix) ? 1:0;
+ if (numPhysicalOperands < 1 + kOp + Op4v ||
+ numPhysicalOperands > 2 + kOp + Op4v)
+ llvm_unreachable("Unexpected number of operands for MRMnm");
+ }
if (HasVEX_4VPrefix)
HANDLE_OPERAND(vvvvRegister)
+ if (HasEVEX_K)
+ HANDLE_OPERAND(writemaskRegister)
HANDLE_OPERAND(memory)
HANDLE_OPTIONAL(relocation)
break;
@@ -902,6 +894,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
uint8_t opcodeToSet = 0;
switch (Prefix) {
+ default: llvm_unreachable("Invalid prefix!");
// Extended two-byte opcodes can start with f2 0f, f3 0f, or 0f
case X86Local::XD:
case X86Local::XS:
@@ -1015,6 +1008,63 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
filter = new DumbFilter();
opcodeToSet = Opcode;
break;
+ case X86Local::XOP8:
+ opcodeType = XOP8_MAP;
+ if (needsModRMForDecode(Form))
+ filter = new ModFilter(isRegFormat(Form));
+ else
+ filter = new DumbFilter();
+ opcodeToSet = Opcode;
+ break;
+ case X86Local::XOP9:
+ opcodeType = XOP9_MAP;
+ switch (Opcode) {
+ default:
+ if (needsModRMForDecode(Form))
+ filter = new ModFilter(isRegFormat(Form));
+ else
+ filter = new DumbFilter();
+ break;
+#define EXTENSION_TABLE(n) case 0x##n:
+ XOP9_MAP_EXTENSION_TABLES
+#undef EXTENSION_TABLE
+ switch (Form) {
+ default:
+ llvm_unreachable("Unhandled XOP9 extended opcode");
+ case X86Local::MRM0r:
+ case X86Local::MRM1r:
+ case X86Local::MRM2r:
+ case X86Local::MRM3r:
+ case X86Local::MRM4r:
+ case X86Local::MRM5r:
+ case X86Local::MRM6r:
+ case X86Local::MRM7r:
+ filter = new ExtendedFilter(true, Form - X86Local::MRM0r);
+ break;
+ case X86Local::MRM0m:
+ case X86Local::MRM1m:
+ case X86Local::MRM2m:
+ case X86Local::MRM3m:
+ case X86Local::MRM4m:
+ case X86Local::MRM5m:
+ case X86Local::MRM6m:
+ case X86Local::MRM7m:
+ filter = new ExtendedFilter(false, Form - X86Local::MRM0m);
+ break;
+ MRM_MAPPING
+ } // switch (Form)
+ break;
+ } // switch (Opcode)
+ opcodeToSet = Opcode;
+ break;
+ case X86Local::XOPA:
+ opcodeType = XOPA_MAP;
+ if (needsModRMForDecode(Form))
+ filter = new ModFilter(isRegFormat(Form));
+ else
+ filter = new DumbFilter();
+ opcodeToSet = Opcode;
+ break;
case X86Local::D8:
case X86Local::D9:
case X86Local::DA:
@@ -1035,7 +1085,7 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
opcodeToSet = 0xd8 + (Prefix - X86Local::D8);
break;
case X86Local::REP:
- default:
+ case 0:
opcodeType = ONEBYTE;
switch (Opcode) {
#define EXTENSION_TABLE(n) case 0x##n:
@@ -1166,6 +1216,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("i32i8imm", TYPE_IMM32)
TYPE("u32u8imm", TYPE_IMM32)
TYPE("GR32", TYPE_Rv)
+ TYPE("GR32orGR64", TYPE_R32)
TYPE("i64mem", TYPE_Mv)
TYPE("i64i32imm", TYPE_IMM64)
TYPE("i64i8imm", TYPE_IMM64)
@@ -1276,6 +1327,7 @@ OperandEncoding RecognizableInstr::rmRegisterEncodingFromString
bool hasOpSizePrefix) {
ENCODING("GR16", ENCODING_RM)
ENCODING("GR32", ENCODING_RM)
+ ENCODING("GR32orGR64", ENCODING_RM)
ENCODING("GR64", ENCODING_RM)
ENCODING("GR8", ENCODING_RM)
ENCODING("VR128", ENCODING_RM)
@@ -1299,6 +1351,7 @@ OperandEncoding RecognizableInstr::roRegisterEncodingFromString
bool hasOpSizePrefix) {
ENCODING("GR16", ENCODING_REG)
ENCODING("GR32", ENCODING_REG)
+ ENCODING("GR32orGR64", ENCODING_REG)
ENCODING("GR64", ENCODING_REG)
ENCODING("GR8", ENCODING_REG)
ENCODING("VR128", ENCODING_REG)
diff --git a/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h
index 7e1d362..4d4686e 100644
--- a/utils/TableGen/X86RecognizableInstr.h
+++ b/utils/TableGen/X86RecognizableInstr.h
@@ -72,6 +72,8 @@ private:
bool HasEVEX_L2Prefix;
/// The hasEVEX_K field from the record
bool HasEVEX_K;
+ /// The hasEVEX_KZ field from the record
+ bool HasEVEX_KZ;
/// The hasEVEX_B field from the record
bool HasEVEX_B;
/// The hasLockPrefix field from the record