aboutsummaryrefslogtreecommitdiffstats
path: root/utils/TableGen
diff options
context:
space:
mode:
Diffstat (limited to 'utils/TableGen')
-rw-r--r--utils/TableGen/ARMDecoderEmitter.cpp3
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp46
-rw-r--r--utils/TableGen/AsmWriterEmitter.cpp152
-rw-r--r--utils/TableGen/CMakeLists.txt1
-rw-r--r--utils/TableGen/CodeEmitterGen.cpp9
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp2
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.h2
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp12
-rw-r--r--utils/TableGen/CodeGenInstruction.h13
-rw-r--r--utils/TableGen/EDEmitter.cpp35
-rw-r--r--utils/TableGen/FixedLenDecoderEmitter.cpp9
-rw-r--r--utils/TableGen/InstrInfoEmitter.cpp15
-rw-r--r--utils/TableGen/IntrinsicEmitter.cpp2
-rw-r--r--utils/TableGen/LLVMCConfigurationEmitter.cpp4
-rw-r--r--utils/TableGen/PseudoLoweringEmitter.cpp243
-rw-r--r--utils/TableGen/PseudoLoweringEmitter.h65
-rw-r--r--utils/TableGen/Record.h5
-rw-r--r--utils/TableGen/RegisterInfoEmitter.cpp21
-rw-r--r--utils/TableGen/SetTheory.h2
-rw-r--r--utils/TableGen/SubtargetEmitter.cpp80
-rw-r--r--utils/TableGen/TGParser.h2
-rw-r--r--utils/TableGen/TableGen.cpp7
-rw-r--r--utils/TableGen/X86RecognizableInstr.cpp26
-rw-r--r--utils/TableGen/X86RecognizableInstr.h2
24 files changed, 524 insertions, 234 deletions
diff --git a/utils/TableGen/ARMDecoderEmitter.cpp b/utils/TableGen/ARMDecoderEmitter.cpp
index a7cbbcd..8a5dc8b 100644
--- a/utils/TableGen/ARMDecoderEmitter.cpp
+++ b/utils/TableGen/ARMDecoderEmitter.cpp
@@ -421,6 +421,9 @@ public:
protected:
// Populates the insn given the uid.
void insnWithID(insn_t &Insn, unsigned Opcode) const {
+ if (AllInstructions[Opcode]->isPseudo)
+ return;
+
BitsInit &Bits = getBitsField(*AllInstructions[Opcode]->TheDef, "Inst");
for (unsigned i = 0; i < BIT_WIDTH; ++i)
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index 1fb92ee..a6a4fec 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -1153,7 +1153,7 @@ void AsmMatcherInfo::BuildInfo() {
assert(FeatureNo < 32 && "Too many subtarget features!");
}
- StringRef CommentDelimiter = AsmParser->getValueAsString("CommentDelimiter");
+ std::string CommentDelimiter = AsmParser->getValueAsString("CommentDelimiter");
// Parse the instructions; we need to do this first so that we can gather the
// singleton register classes.
@@ -1656,6 +1656,10 @@ static void EmitValidateOperandClass(AsmMatcherInfo &Info,
OS << " " << Info.Target.getName() << "Operand &Operand = *("
<< Info.Target.getName() << "Operand*)GOp;\n";
+ // The InvalidMatchClass is not to match any operand.
+ OS << " if (Kind == InvalidMatchClass)\n";
+ OS << " return false;\n\n";
+
// Check for Token operands first.
OS << " if (Operand.isToken())\n";
OS << " return MatchTokenString(Operand.getToken()) == Kind;\n\n";
@@ -1817,15 +1821,44 @@ static void EmitComputeAvailableFeatures(AsmMatcherInfo &Info,
Info.AsmParser->getValueAsString("AsmParserClassName");
OS << "unsigned " << Info.Target.getName() << ClassName << "::\n"
- << "ComputeAvailableFeatures(const " << Info.Target.getName()
- << "Subtarget *Subtarget) const {\n";
+ << "ComputeAvailableFeatures(uint64_t FB) const {\n";
OS << " unsigned Features = 0;\n";
for (std::map<Record*, SubtargetFeatureInfo*>::const_iterator
it = Info.SubtargetFeatures.begin(),
ie = Info.SubtargetFeatures.end(); it != ie; ++it) {
SubtargetFeatureInfo &SFI = *it->second;
- OS << " if (" << SFI.TheDef->getValueAsString("CondString")
- << ")\n";
+
+ OS << " if (";
+ std::string CondStorage = SFI.TheDef->getValueAsString("AssemblerCondString");
+ StringRef Conds = CondStorage;
+ std::pair<StringRef,StringRef> Comma = Conds.split(',');
+ bool First = true;
+ do {
+ if (!First)
+ OS << " && ";
+
+ bool Neg = false;
+ StringRef Cond = Comma.first;
+ if (Cond[0] == '!') {
+ Neg = true;
+ Cond = Cond.substr(1);
+ }
+
+ OS << "((FB & " << Info.Target.getName() << "::" << Cond << ")";
+ if (Neg)
+ OS << " == 0";
+ else
+ OS << " != 0";
+ OS << ")";
+
+ if (Comma.second.empty())
+ break;
+
+ First = false;
+ Comma = Comma.second.split(',');
+ } while (true);
+
+ OS << ")\n";
OS << " Features |= " << SFI.getEnumName() << ";\n";
}
OS << " return Features;\n";
@@ -2140,8 +2173,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << "#undef GET_ASSEMBLER_HEADER\n";
OS << " // This should be included into the middle of the declaration of\n";
OS << " // your subclasses implementation of TargetAsmParser.\n";
- OS << " unsigned ComputeAvailableFeatures(const " <<
- Target.getName() << "Subtarget *Subtarget) const;\n";
+ OS << " unsigned ComputeAvailableFeatures(uint64_t FeatureBits) const;\n";
OS << " enum MatchResultTy {\n";
OS << " Match_ConversionFail,\n";
OS << " Match_InvalidOperand,\n";
diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp
index b77d2e4..f44f050 100644
--- a/utils/TableGen/AsmWriterEmitter.cpp
+++ b/utils/TableGen/AsmWriterEmitter.cpp
@@ -606,92 +606,29 @@ void AsmWriterEmitter::EmitGetInstructionName(raw_ostream &O) {
}
namespace {
-
-/// SubtargetFeatureInfo - Helper class for storing information on a subtarget
-/// feature which participates in instruction matching.
-struct SubtargetFeatureInfo {
- /// \brief The predicate record for this feature.
- const Record *TheDef;
-
- /// \brief An unique index assigned to represent this feature.
- unsigned Index;
-
- SubtargetFeatureInfo(const Record *D, unsigned Idx) : TheDef(D), Index(Idx) {}
-
- /// \brief The name of the enumerated constant identifying this feature.
- std::string getEnumName() const {
- return "Feature_" + TheDef->getName();
- }
-};
-
-struct AsmWriterInfo {
- /// Map of Predicate records to their subtarget information.
- std::map<const Record*, SubtargetFeatureInfo*> SubtargetFeatures;
-
- /// getSubtargetFeature - Lookup or create the subtarget feature info for the
- /// given operand.
- SubtargetFeatureInfo *getSubtargetFeature(const Record *Def) const {
- assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!");
- std::map<const Record*, SubtargetFeatureInfo*>::const_iterator I =
- SubtargetFeatures.find(Def);
- return I == SubtargetFeatures.end() ? 0 : I->second;
- }
-
- void addReqFeatures(const std::vector<Record*> &Features) {
- for (std::vector<Record*>::const_iterator
- I = Features.begin(), E = Features.end(); I != E; ++I) {
- const Record *Pred = *I;
-
- // Ignore predicates that are not intended for the assembler.
- if (!Pred->getValueAsBit("AssemblerMatcherPredicate"))
- continue;
-
- if (Pred->getName().empty())
- throw TGError(Pred->getLoc(), "Predicate has no name!");
-
- // Don't add the predicate again.
- if (getSubtargetFeature(Pred))
- continue;
-
- unsigned FeatureNo = SubtargetFeatures.size();
- SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo);
- assert(FeatureNo < 32 && "Too many subtarget features!");
- }
- }
-
- const SubtargetFeatureInfo *getFeatureInfo(const Record *R) {
- return SubtargetFeatures[R];
- }
-};
-
// IAPrinter - Holds information about an InstAlias. Two InstAliases match if
// they both have the same conditionals. In which case, we cannot print out the
// alias for that pattern.
class IAPrinter {
- AsmWriterInfo &AWI;
std::vector<std::string> Conds;
std::map<StringRef, unsigned> OpMap;
std::string Result;
std::string AsmString;
std::vector<Record*> ReqFeatures;
public:
- IAPrinter(AsmWriterInfo &Info, std::string R, std::string AS)
- : AWI(Info), Result(R), AsmString(AS) {}
+ IAPrinter(std::string R, std::string AS)
+ : Result(R), AsmString(AS) {}
void addCond(const std::string &C) { Conds.push_back(C); }
- void addReqFeatures(const std::vector<Record*> &Features) {
- AWI.addReqFeatures(Features);
- ReqFeatures = Features;
- }
void addOperand(StringRef Op, unsigned Idx) { OpMap[Op] = Idx; }
unsigned getOpIndex(StringRef Op) { return OpMap[Op]; }
bool isOpMapped(StringRef Op) { return OpMap.find(Op) != OpMap.end(); }
- bool print(raw_ostream &O) {
+ void print(raw_ostream &O) {
if (Conds.empty() && ReqFeatures.empty()) {
O.indent(6) << "return true;\n";
- return false;
+ return;
}
O << "if (";
@@ -706,27 +643,6 @@ public:
O << *I;
}
- if (!ReqFeatures.empty()) {
- if (Conds.begin() != Conds.end()) {
- O << " &&\n";
- O.indent(8);
- } else {
- O << "if (";
- }
-
- std::string Req;
- raw_string_ostream ReqO(Req);
-
- for (std::vector<Record*>::iterator
- I = ReqFeatures.begin(), E = ReqFeatures.end(); I != E; ++I) {
- if (I != ReqFeatures.begin()) ReqO << " | ";
- ReqO << AWI.getFeatureInfo(*I)->getEnumName();
- }
-
- O << "(AvailableFeatures & (" << ReqO.str() << ")) == ("
- << ReqO.str() << ')';
- }
-
O << ") {\n";
O.indent(6) << "// " << Result << "\n";
O.indent(6) << "AsmString = \"" << AsmString << "\";\n";
@@ -738,7 +654,6 @@ public:
O.indent(6) << "break;\n";
O.indent(4) << '}';
- return !ReqFeatures.empty();
}
bool operator==(const IAPrinter &RHS) {
@@ -770,53 +685,6 @@ public:
} // end anonymous namespace
-/// EmitSubtargetFeatureFlagEnumeration - Emit the subtarget feature flag
-/// definitions.
-static void EmitSubtargetFeatureFlagEnumeration(AsmWriterInfo &Info,
- raw_ostream &O) {
- O << "namespace {\n\n";
- O << "// Flags for subtarget features that participate in "
- << "alias instruction matching.\n";
- O << "enum SubtargetFeatureFlag {\n";
-
- for (std::map<const Record*, SubtargetFeatureInfo*>::const_iterator
- I = Info.SubtargetFeatures.begin(),
- E = Info.SubtargetFeatures.end(); I != E; ++I) {
- SubtargetFeatureInfo &SFI = *I->second;
- O << " " << SFI.getEnumName() << " = (1 << " << SFI.Index << "),\n";
- }
-
- O << " Feature_None = 0\n";
- O << "};\n\n";
- O << "} // end anonymous namespace\n\n";
-}
-
-/// EmitComputeAvailableFeatures - Emit the function to compute the list of
-/// available features given a subtarget.
-static void EmitComputeAvailableFeatures(AsmWriterInfo &Info,
- Record *AsmWriter,
- CodeGenTarget &Target,
- raw_ostream &O) {
- std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
-
- O << "unsigned " << Target.getName() << ClassName << "::\n"
- << "ComputeAvailableFeatures(const " << Target.getName()
- << "Subtarget *Subtarget) const {\n";
- O << " unsigned Features = 0;\n";
-
- for (std::map<const Record*, SubtargetFeatureInfo*>::const_iterator
- I = Info.SubtargetFeatures.begin(),
- E = Info.SubtargetFeatures.end(); I != E; ++I) {
- SubtargetFeatureInfo &SFI = *I->second;
- O << " if (" << SFI.TheDef->getValueAsString("CondString")
- << ")\n";
- O << " Features |= " << SFI.getEnumName() << ";\n";
- }
-
- O << " return Features;\n";
- O << "}\n\n";
-}
-
static void EmitGetMapOperandNumber(raw_ostream &O) {
O << "static unsigned getMapOperandNumber("
<< "const SmallVectorImpl<std::pair<StringRef, unsigned> > &OpMap,\n";
@@ -960,7 +828,6 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
// A map of which conditions need to be met for each instruction operand
// before it can be matched to the mnemonic.
std::map<std::string, std::vector<IAPrinter*> > IAPrinterMap;
- AsmWriterInfo AWI;
for (std::map<std::string, std::vector<CodeGenInstAlias*> >::iterator
I = AliasMap.begin(), E = AliasMap.end(); I != E; ++I) {
@@ -977,9 +844,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
if (NumResultOps < CountNumOperands(CGA->AsmString))
continue;
- IAPrinter *IAP = new IAPrinter(AWI, CGA->Result->getAsString(),
+ IAPrinter *IAP = new IAPrinter(CGA->Result->getAsString(),
CGA->AsmString);
- IAP->addReqFeatures(CGA->TheDef->getValueAsListOfDefs("Predicates"));
std::string Cond;
Cond = std::string("MI->getNumOperands() == ") + llvm::utostr(LastOpNo);
@@ -1049,9 +915,6 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
}
}
- EmitSubtargetFeatureFlagEnumeration(AWI, O);
- EmitComputeAvailableFeatures(AWI, AsmWriter, Target, O);
-
std::string Header;
raw_string_ostream HeaderO(Header);
@@ -1061,7 +924,6 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
std::string Cases;
raw_string_ostream CasesO(Cases);
- bool NeedAvailableFeatures = false;
for (std::map<std::string, std::vector<IAPrinter*> >::iterator
I = IAPrinterMap.begin(), E = IAPrinterMap.end(); I != E; ++I) {
@@ -1092,7 +954,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
II = UniqueIAPs.begin(), IE = UniqueIAPs.end(); II != IE; ++II) {
IAPrinter *IAP = *II;
CasesO.indent(4);
- NeedAvailableFeatures |= IAP->print(CasesO);
+ IAP->print(CasesO);
CasesO << '\n';
}
@@ -1112,8 +974,6 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
O << HeaderO.str();
O.indent(2) << "StringRef AsmString;\n";
O.indent(2) << "SmallVector<std::pair<StringRef, unsigned>, 4> OpMap;\n";
- if (NeedAvailableFeatures)
- O.indent(2) << "unsigned AvailableFeatures = getAvailableFeatures();\n\n";
O.indent(2) << "switch (MI->getOpcode()) {\n";
O.indent(2) << "default: return false;\n";
O << CasesO.str();
diff --git a/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt
index 957045e..4d71259 100644
--- a/utils/TableGen/CMakeLists.txt
+++ b/utils/TableGen/CMakeLists.txt
@@ -34,6 +34,7 @@ add_llvm_utility(tblgen
LLVMCConfigurationEmitter.cpp
NeonEmitter.cpp
OptParserEmitter.cpp
+ PseudoLoweringEmitter.cpp
Record.cpp
RegisterInfoEmitter.cpp
SetTheory.cpp
diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp
index 9d4dc5c4..d828dfc 100644
--- a/utils/TableGen/CodeEmitterGen.cpp
+++ b/utils/TableGen/CodeEmitterGen.cpp
@@ -34,7 +34,8 @@ void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) {
for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end();
I != E; ++I) {
Record *R = *I;
- if (R->getValueAsString("Namespace") == "TargetOpcode")
+ if (R->getValueAsString("Namespace") == "TargetOpcode" ||
+ R->getValueAsBit("isPseudo"))
continue;
BitsInit *BI = R->getValueAsBitsInit("Inst");
@@ -231,7 +232,8 @@ void CodeEmitterGen::run(raw_ostream &o) {
const CodeGenInstruction *CGI = *IN;
Record *R = CGI->TheDef;
- if (R->getValueAsString("Namespace") == "TargetOpcode") {
+ if (R->getValueAsString("Namespace") == "TargetOpcode" ||
+ R->getValueAsBit("isPseudo")) {
o << " 0U,\n";
continue;
}
@@ -255,7 +257,8 @@ void CodeEmitterGen::run(raw_ostream &o) {
for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end();
IC != EC; ++IC) {
Record *R = *IC;
- if (R->getValueAsString("Namespace") == "TargetOpcode")
+ if (R->getValueAsString("Namespace") == "TargetOpcode" ||
+ R->getValueAsBit("isPseudo"))
continue;
const std::string &InstName = R->getValueAsString("Namespace") + "::"
+ R->getName();
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index 0fe5d05..072893f 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -1744,7 +1744,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
Record *R = DI->getDef();
// Direct reference to a leaf DagNode or PatFrag? Turn it into a
- // TreePatternNode if its own. For example:
+ // TreePatternNode of its own. For example:
/// (foo GPR, imm) -> (foo GPR, (imm))
if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag"))
return ParseTreePattern(new DagInit(DI, "",
diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h
index e4e8574..936fd01 100644
--- a/utils/TableGen/CodeGenDAGPatterns.h
+++ b/utils/TableGen/CodeGenDAGPatterns.h
@@ -26,7 +26,7 @@
namespace llvm {
class Record;
- struct Init;
+ class Init;
class ListInit;
class DagInit;
class SDNodeInfo;
diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp
index 5fa91be..a52ce86c 100644
--- a/utils/TableGen/CodeGenInstruction.cpp
+++ b/utils/TableGen/CodeGenInstruction.cpp
@@ -67,12 +67,14 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
Record *Rec = Arg->getDef();
std::string PrintMethod = "printOperand";
std::string EncoderMethod;
+ std::string OperandType = "OPERAND_UNKNOWN";
unsigned NumOps = 1;
DagInit *MIOpInfo = 0;
if (Rec->isSubClassOf("RegisterOperand")) {
PrintMethod = Rec->getValueAsString("PrintMethod");
} else if (Rec->isSubClassOf("Operand")) {
PrintMethod = Rec->getValueAsString("PrintMethod");
+ OperandType = Rec->getValueAsString("OperandType");
// If there is an explicit encoder method, use it.
EncoderMethod = Rec->getValueAsString("EncoderMethod");
MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
@@ -96,8 +98,9 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
} else if (Rec->getName() == "variable_ops") {
isVariadic = true;
continue;
- } else if (!Rec->isSubClassOf("RegisterClass") &&
- !Rec->isSubClassOf("PointerLikeRegClass") &&
+ } else if (Rec->isSubClassOf("RegisterClass")) {
+ OperandType = "OPERAND_REGISTER";
+ } else if (!Rec->isSubClassOf("PointerLikeRegClass") &&
Rec->getName() != "unknown")
throw "Unknown operand class '" + Rec->getName() +
"' in '" + R->getName() + "' instruction!";
@@ -111,7 +114,8 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
" has the same name as a previous operand!";
OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, EncoderMethod,
- MIOperandNo, NumOps, MIOpInfo));
+ OperandType, MIOperandNo, NumOps,
+ MIOpInfo));
MIOperandNo += NumOps;
}
@@ -311,6 +315,8 @@ CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R), Operands(R) {
isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove");
hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq");
hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq");
+ isCodeGenOnly = R->getValueAsBit("isCodeGenOnly");
+ isPseudo = R->getValueAsBit("isPseudo");
ImplicitDefs = R->getValueAsListOfDefs("Defs");
ImplicitUses = R->getValueAsListOfDefs("Uses");
diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h
index 5f1e0be..8d7669a 100644
--- a/utils/TableGen/CodeGenInstruction.h
+++ b/utils/TableGen/CodeGenInstruction.h
@@ -78,6 +78,10 @@ namespace llvm {
/// for binary encoding. "getMachineOpValue" by default.
std::string EncoderMethodName;
+ /// OperandType - A value from MCOI::OperandType representing the type of
+ /// the operand.
+ std::string OperandType;
+
/// MIOperandNo - Currently (this is meant to be phased out), some logical
/// operands correspond to multiple MachineInstr operands. In the X86
/// target for example, one address operand is represented as 4
@@ -101,10 +105,11 @@ namespace llvm {
std::vector<ConstraintInfo> Constraints;
OperandInfo(Record *R, const std::string &N, const std::string &PMN,
- const std::string &EMN, unsigned MION, unsigned MINO,
- DagInit *MIOI)
+ const std::string &EMN, const std::string &OT, unsigned MION,
+ unsigned MINO, DagInit *MIOI)
: Rec(R), Name(N), PrinterMethodName(PMN), EncoderMethodName(EMN),
- MIOperandNo(MION), MINumOperands(MINO), MIOperandInfo(MIOI) {}
+ OperandType(OT), MIOperandNo(MION), MINumOperands(MINO),
+ MIOperandInfo(MIOI) {}
/// getTiedOperand - If this operand is tied to another one, return the
@@ -235,6 +240,8 @@ namespace llvm {
bool isAsCheapAsAMove;
bool hasExtraSrcRegAllocReq;
bool hasExtraDefRegAllocReq;
+ bool isCodeGenOnly;
+ bool isPseudo;
CodeGenInstruction(Record *R);
diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp
index 4c0d385..2f9814a 100644
--- a/utils/TableGen/EDEmitter.cpp
+++ b/utils/TableGen/EDEmitter.cpp
@@ -588,8 +588,11 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
IMM("imm0_31");
IMM("imm0_31_m1");
IMM("nModImm");
+ IMM("imm0_7");
+ IMM("imm0_15");
IMM("imm0_255");
IMM("imm0_4095");
+ IMM("imm0_65535");
IMM("jt2block_operand");
IMM("t_imm_s4");
IMM("pclabel");
@@ -653,12 +656,12 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
MISC("t2am_imm8s4_offset", "kOperandTypeThumb2AddrModeImm8s4Offset");
// R, I
MISC("tb_addrmode", "kOperandTypeARMTBAddrMode"); // I
- MISC("t_addrmode_rrs1", "kOperandTypeThumbAddrModeRegS"); // R, R
- MISC("t_addrmode_rrs2", "kOperandTypeThumbAddrModeRegS"); // R, R
- MISC("t_addrmode_rrs4", "kOperandTypeThumbAddrModeRegS"); // R, R
- MISC("t_addrmode_is1", "kOperandTypeThumbAddrModeImmS"); // R, I
- MISC("t_addrmode_is2", "kOperandTypeThumbAddrModeImmS"); // R, I
- MISC("t_addrmode_is4", "kOperandTypeThumbAddrModeImmS"); // R, I
+ MISC("t_addrmode_rrs1", "kOperandTypeThumbAddrModeRegS1"); // R, R
+ MISC("t_addrmode_rrs2", "kOperandTypeThumbAddrModeRegS2"); // R, R
+ MISC("t_addrmode_rrs4", "kOperandTypeThumbAddrModeRegS4"); // R, R
+ MISC("t_addrmode_is1", "kOperandTypeThumbAddrModeImmS1"); // R, I
+ MISC("t_addrmode_is2", "kOperandTypeThumbAddrModeImmS2"); // R, I
+ MISC("t_addrmode_is4", "kOperandTypeThumbAddrModeImmS4"); // R, I
MISC("t_addrmode_rr", "kOperandTypeThumbAddrModeRR"); // R, R
MISC("t_addrmode_sp", "kOperandTypeThumbAddrModeSP"); // R, I
MISC("t_addrmode_pc", "kOperandTypeThumbAddrModePC"); // R, I
@@ -666,14 +669,9 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
return 1;
}
-#undef SOREG
-#undef SOIMM
-#undef PRED
#undef REG
#undef MEM
-#undef LEA
-#undef IMM
-#undef PCR
+#undef MISC
#undef SET
@@ -774,6 +772,11 @@ static void populateInstInfo(CompoundConstantEmitter &infoArray,
for (index = 0; index < numInstructions; ++index) {
const CodeGenInstruction& inst = *numberedInstructions[index];
+ // We don't need to do anything for pseudo-instructions, as we'll never
+ // see them here. We'll only see real instructions.
+ if (inst.isPseudo)
+ continue;
+
CompoundConstantEmitter *infoStruct = new CompoundConstantEmitter;
infoArray.addEntry(infoStruct);
@@ -869,8 +872,12 @@ static void emitCommonEnums(raw_ostream &o, unsigned int &i) {
operandTypes.addEntry("kOperandTypeARMSPRRegisterList");
operandTypes.addEntry("kOperandTypeARMTBAddrMode");
operandTypes.addEntry("kOperandTypeThumbITMask");
- operandTypes.addEntry("kOperandTypeThumbAddrModeRegS");
- operandTypes.addEntry("kOperandTypeThumbAddrModeImmS");
+ operandTypes.addEntry("kOperandTypeThumbAddrModeImmS1");
+ operandTypes.addEntry("kOperandTypeThumbAddrModeImmS2");
+ operandTypes.addEntry("kOperandTypeThumbAddrModeImmS4");
+ operandTypes.addEntry("kOperandTypeThumbAddrModeRegS1");
+ operandTypes.addEntry("kOperandTypeThumbAddrModeRegS2");
+ operandTypes.addEntry("kOperandTypeThumbAddrModeRegS4");
operandTypes.addEntry("kOperandTypeThumbAddrModeRR");
operandTypes.addEntry("kOperandTypeThumbAddrModeSP");
operandTypes.addEntry("kOperandTypeThumbAddrModePC");
diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp
index ba6cd86..c9dcb01 100644
--- a/utils/TableGen/FixedLenDecoderEmitter.cpp
+++ b/utils/TableGen/FixedLenDecoderEmitter.cpp
@@ -1225,14 +1225,14 @@ bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI,
//
// This also removes pseudo instructions from considerations of disassembly,
// which is a better design and less fragile than the name matchings.
- BitsInit &Bits = getBitsField(Def, "Inst");
- if (Bits.allInComplete()) return false;
-
// Ignore "asm parser only" instructions.
if (Def.getValueAsBit("isAsmParserOnly") ||
Def.getValueAsBit("isCodeGenOnly"))
return false;
+ BitsInit &Bits = getBitsField(Def, "Inst");
+ if (Bits.allInComplete()) return false;
+
std::vector<OperandInfo> InsnOperands;
// If the instruction has specified a custom decoding hook, use that instead
@@ -1354,7 +1354,8 @@ bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI,
void FixedLenDecoderEmitter::populateInstructions() {
for (unsigned i = 0, e = NumberedInstructions.size(); i < e; ++i) {
Record *R = NumberedInstructions[i]->TheDef;
- if (R->getValueAsString("Namespace") == "TargetOpcode")
+ if (R->getValueAsString("Namespace") == "TargetOpcode" ||
+ R->getValueAsBit("isPseudo"))
continue;
if (populateInstruction(*NumberedInstructions[i], i))
diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index 18d4db0..5ebaf17 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/utils/TableGen/InstrInfoEmitter.cpp
@@ -121,6 +121,11 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
" << 16) | (1 << MCOI::TIED_TO))";
}
+ // Fill in operand type.
+ Res += ", MCOI::";
+ assert(!Inst.Operands[i].OperandType.empty() && "Invalid operand type.");
+ Res += Inst.Operands[i].OperandType;
+
Result.push_back(Res);
}
}
@@ -198,8 +203,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
// Emit all of the MCInstrDesc records in their ENUM ordering.
//
- OS << "\nstatic const MCInstrDesc " << TargetName
- << "Insts[] = {\n";
+ OS << "\nMCInstrDesc " << TargetName << "Insts[] = {\n";
const std::vector<const CodeGenInstruction*> &NumberedInstructions =
Target.getInstructionsByEnumValue();
@@ -235,6 +239,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
OS << "#undef GET_INSTRINFO_CTOR\n";
OS << "namespace llvm {\n";
+ OS << "extern MCInstrDesc " << TargetName << "Insts[];\n";
OS << ClassName << "::" << ClassName << "(int SO, int DO)\n"
<< " : TargetInstrInfoImpl(SO, DO) {\n"
<< " InitMCInstrInfo(" << TargetName << "Insts, "
@@ -257,8 +262,10 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
OS << " { ";
OS << Num << ",\t" << MinOperands << ",\t"
- << Inst.Operands.NumDefs << ",\t" << getItinClassNumber(Inst.TheDef)
- << ",\t\"" << Inst.TheDef->getName() << "\", 0";
+ << Inst.Operands.NumDefs << ",\t"
+ << getItinClassNumber(Inst.TheDef) << ",\t"
+ << Inst.TheDef->getValueAsInt("Size") << ",\t\""
+ << Inst.TheDef->getName() << "\", 0";
// Emit all of the target indepedent flags...
if (Inst.isReturn) OS << "|(1<<MCID::Return)";
diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp
index 7a53138..e5e7cea 100644
--- a/utils/TableGen/IntrinsicEmitter.cpp
+++ b/utils/TableGen/IntrinsicEmitter.cpp
@@ -259,7 +259,7 @@ static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType,
} else if (VT == MVT::iPTRAny) {
// Make sure the user has passed us an argument type to overload. If not,
// treat it as an ordinary (not overloaded) intrinsic.
- OS << "(" << ArgNo << " < numTys) ? Tys[" << ArgNo
+ OS << "(" << ArgNo << " < Tys.size()) ? Tys[" << ArgNo
<< "] : PointerType::getUnqual(";
EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo);
OS << ")";
diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp
index 090faf5..cd0cbeb 100644
--- a/utils/TableGen/LLVMCConfigurationEmitter.cpp
+++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp
@@ -2969,8 +2969,8 @@ void EmitHookDeclarations(const ToolDescriptions& ToolDescs,
for (HookInfoMap::const_iterator B = HookNames.begin(),
E = HookNames.end(); B != E; ++B) {
- const char* HookName = B->first();
- const HookInfo& Info = B->second;
+ StringRef HookName = B->first();
+ const HookInfo &Info = B->second;
O.indent(Indent1) << "std::string " << HookName << "(";
diff --git a/utils/TableGen/PseudoLoweringEmitter.cpp b/utils/TableGen/PseudoLoweringEmitter.cpp
new file mode 100644
index 0000000..db33c1f
--- /dev/null
+++ b/utils/TableGen/PseudoLoweringEmitter.cpp
@@ -0,0 +1,243 @@
+//===- PseudoLoweringEmitter.cpp - PseudoLowering Generator -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "pseudo-lowering"
+#include "Error.h"
+#include "CodeGenInstruction.h"
+#include "PseudoLoweringEmitter.h"
+#include "Record.h"
+#include "llvm/ADT/IndexedMap.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Debug.h"
+#include <vector>
+using namespace llvm;
+
+// FIXME: This pass currently can only expand a pseudo to a single instruction.
+// The pseudo expansion really should take a list of dags, not just
+// a single dag, so we can do fancier things.
+
+unsigned PseudoLoweringEmitter::
+addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Insn,
+ IndexedMap<OpData> &OperandMap, unsigned BaseIdx) {
+ unsigned OpsAdded = 0;
+ for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
+ if (DefInit *DI = dynamic_cast<DefInit*>(Dag->getArg(i))) {
+ // Physical register reference. Explicit check for the special case
+ // "zero_reg" definition.
+ if (DI->getDef()->isSubClassOf("Register") ||
+ DI->getDef()->getName() == "zero_reg") {
+ OperandMap[BaseIdx + i].Kind = OpData::Reg;
+ OperandMap[BaseIdx + i].Data.Reg = DI->getDef();
+ ++OpsAdded;
+ continue;
+ }
+
+ // Normal operands should always have the same type, or we have a
+ // problem.
+ // FIXME: We probably shouldn't ever get a non-zero BaseIdx here.
+ assert(BaseIdx == 0 && "Named subargument in pseudo expansion?!");
+ if (DI->getDef() != Insn.Operands[BaseIdx + i].Rec)
+ throw TGError(Rec->getLoc(),
+ "Pseudo operand type '" + DI->getDef()->getName() +
+ "' does not match expansion operand type '" +
+ Insn.Operands[BaseIdx + i].Rec->getName() + "'");
+ // Source operand maps to destination operand. The Data element
+ // will be filled in later, just set the Kind for now. Do it
+ // for each corresponding MachineInstr operand, not just the first.
+ for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I)
+ OperandMap[BaseIdx + i + I].Kind = OpData::Operand;
+ OpsAdded += Insn.Operands[i].MINumOperands;
+ } else if (IntInit *II = dynamic_cast<IntInit*>(Dag->getArg(i))) {
+ OperandMap[BaseIdx + i].Kind = OpData::Imm;
+ OperandMap[BaseIdx + i].Data.Imm = II->getValue();
+ ++OpsAdded;
+ } else if (DagInit *SubDag = dynamic_cast<DagInit*>(Dag->getArg(i))) {
+ // Just add the operands recursively. This is almost certainly
+ // a constant value for a complex operand (> 1 MI operand).
+ unsigned NewOps =
+ addDagOperandMapping(Rec, SubDag, Insn, OperandMap, BaseIdx + i);
+ OpsAdded += NewOps;
+ // Since we added more than one, we also need to adjust the base.
+ BaseIdx += NewOps - 1;
+ } else
+ assert(0 && "Unhandled pseudo-expansion argument type!");
+ }
+ return OpsAdded;
+}
+
+void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) {
+ DEBUG(dbgs() << "Pseudo definition: " << Rec->getName() << "\n");
+
+ // Validate that the result pattern has the corrent number and types
+ // of arguments for the instruction it references.
+ DagInit *Dag = Rec->getValueAsDag("ResultInst");
+ assert(Dag && "Missing result instruction in pseudo expansion!");
+ DEBUG(dbgs() << " Result: " << *Dag << "\n");
+
+ DefInit *OpDef = dynamic_cast<DefInit*>(Dag->getOperator());
+ if (!OpDef)
+ throw TGError(Rec->getLoc(), Rec->getName() +
+ " has unexpected operator type!");
+ Record *Operator = OpDef->getDef();
+ if (!Operator->isSubClassOf("Instruction"))
+ throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
+ "' is not an instruction!");
+
+ CodeGenInstruction Insn(Operator);
+
+ if (Insn.isCodeGenOnly || Insn.isPseudo)
+ throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
+ "' cannot be another pseudo instruction!");
+
+ if (Insn.Operands.size() != Dag->getNumArgs())
+ throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
+ "' operand count mismatch");
+
+ IndexedMap<OpData> OperandMap;
+ OperandMap.grow(Insn.Operands.size());
+
+ addDagOperandMapping(Rec, Dag, Insn, OperandMap, 0);
+
+ // If there are more operands that weren't in the DAG, they have to
+ // be operands that have default values, or we have an error. Currently,
+ // PredicateOperand and OptionalDefOperand both have default values.
+
+
+ // Validate that each result pattern argument has a matching (by name)
+ // argument in the source instruction, in either the (outs) or (ins) list.
+ // Also check that the type of the arguments match.
+ //
+ // Record the mapping of the source to result arguments for use by
+ // the lowering emitter.
+ CodeGenInstruction SourceInsn(Rec);
+ StringMap<unsigned> SourceOperands;
+ for (unsigned i = 0, e = SourceInsn.Operands.size(); i != e; ++i)
+ SourceOperands[SourceInsn.Operands[i].Name] = i;
+
+ DEBUG(dbgs() << " Operand mapping:\n");
+ for (unsigned i = 0, e = Insn.Operands.size(); i != e; ++i) {
+ // We've already handled constant values. Just map instruction operands
+ // here.
+ if (OperandMap[Insn.Operands[i].MIOperandNo].Kind != OpData::Operand)
+ continue;
+ StringMap<unsigned>::iterator SourceOp =
+ SourceOperands.find(Dag->getArgName(i));
+ if (SourceOp == SourceOperands.end())
+ throw TGError(Rec->getLoc(),
+ "Pseudo output operand '" + Dag->getArgName(i) +
+ "' has no matching source operand.");
+ // Map the source operand to the destination operand index for each
+ // MachineInstr operand.
+ for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I)
+ OperandMap[Insn.Operands[i].MIOperandNo + I].Data.Operand =
+ SourceOp->getValue();
+
+ DEBUG(dbgs() << " " << SourceOp->getValue() << " ==> " << i << "\n");
+ }
+
+ Expansions.push_back(PseudoExpansion(SourceInsn, Insn, OperandMap));
+}
+
+void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) {
+ // Emit file header.
+ EmitSourceFileHeader("Pseudo-instruction MC lowering Source Fragment", o);
+
+ o << "bool " << Target.getName() + "AsmPrinter" << "::\n"
+ << "emitPseudoExpansionLowering(MCStreamer &OutStreamer,\n"
+ << " const MachineInstr *MI) {\n"
+ << " switch (MI->getOpcode()) {\n"
+ << " default: return false;\n";
+ for (unsigned i = 0, e = Expansions.size(); i != e; ++i) {
+ PseudoExpansion &Expansion = Expansions[i];
+ CodeGenInstruction &Source = Expansion.Source;
+ CodeGenInstruction &Dest = Expansion.Dest;
+ o << " case " << Source.Namespace << "::"
+ << Source.TheDef->getName() << ": {\n"
+ << " MCInst TmpInst;\n"
+ << " MCOperand MCOp;\n"
+ << " TmpInst.setOpcode(" << Dest.Namespace << "::"
+ << Dest.TheDef->getName() << ");\n";
+
+ // Copy the operands from the source instruction.
+ // FIXME: Instruction operands with defaults values (predicates and cc_out
+ // in ARM, for example shouldn't need explicit values in the
+ // expansion DAG.
+ unsigned MIOpNo = 0;
+ for (unsigned OpNo = 0, E = Dest.Operands.size(); OpNo != E;
+ ++OpNo) {
+ o << " // Operand: " << Dest.Operands[OpNo].Name << "\n";
+ for (unsigned i = 0, e = Dest.Operands[OpNo].MINumOperands;
+ i != e; ++i) {
+ switch (Expansion.OperandMap[MIOpNo + i].Kind) {
+ default:
+ llvm_unreachable("Unknown operand type?!");
+ case OpData::Operand:
+ o << " lowerOperand(MI->getOperand("
+ << Source.Operands[Expansion.OperandMap[MIOpNo].Data
+ .Operand].MIOperandNo + i
+ << "), MCOp);\n"
+ << " TmpInst.addOperand(MCOp);\n";
+ break;
+ case OpData::Imm:
+ o << " TmpInst.addOperand(MCOperand::CreateImm("
+ << Expansion.OperandMap[MIOpNo + i].Data.Imm << "));\n";
+ break;
+ case OpData::Reg: {
+ Record *Reg = Expansion.OperandMap[MIOpNo + i].Data.Reg;
+ o << " TmpInst.addOperand(MCOperand::CreateReg(";
+ // "zero_reg" is special.
+ if (Reg->getName() == "zero_reg")
+ o << "0";
+ else
+ o << Reg->getValueAsString("Namespace") << "::" << Reg->getName();
+ o << "));\n";
+ break;
+ }
+ }
+ }
+ MIOpNo += Dest.Operands[OpNo].MINumOperands;
+ }
+ if (Dest.Operands.isVariadic) {
+ o << " // variable_ops\n";
+ o << " for (unsigned i = " << MIOpNo
+ << ", e = MI->getNumOperands(); i != e; ++i)\n"
+ << " if (lowerOperand(MI->getOperand(i), MCOp))\n"
+ << " TmpInst.addOperand(MCOp);\n";
+ }
+ o << " OutStreamer.EmitInstruction(TmpInst);\n"
+ << " break;\n"
+ << " }\n";
+ }
+ o << " }\n return true;\n}\n\n";
+}
+
+void PseudoLoweringEmitter::run(raw_ostream &o) {
+ Record *ExpansionClass = Records.getClass("PseudoInstExpansion");
+ Record *InstructionClass = Records.getClass("PseudoInstExpansion");
+ assert(ExpansionClass && "PseudoInstExpansion class definition missing!");
+ assert(InstructionClass && "Instruction class definition missing!");
+
+ std::vector<Record*> Insts;
+ for (std::map<std::string, Record*>::const_iterator I =
+ Records.getDefs().begin(), E = Records.getDefs().end(); I != E; ++I) {
+ if (I->second->isSubClassOf(ExpansionClass) &&
+ I->second->isSubClassOf(InstructionClass))
+ Insts.push_back(I->second);
+ }
+
+ // Process the pseudo expansion definitions, validating them as we do so.
+ for (unsigned i = 0, e = Insts.size(); i != e; ++i)
+ evaluateExpansion(Insts[i]);
+
+ // Generate expansion code to lower the pseudo to an MCInst of the real
+ // instruction.
+ emitLoweringEmitter(o);
+}
+
diff --git a/utils/TableGen/PseudoLoweringEmitter.h b/utils/TableGen/PseudoLoweringEmitter.h
new file mode 100644
index 0000000..2749280
--- /dev/null
+++ b/utils/TableGen/PseudoLoweringEmitter.h
@@ -0,0 +1,65 @@
+//===- PseudoLoweringEmitter.h - PseudoLowering Generator -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PSEUDOLOWERINGEMITTER_H
+#define PSEUDOLOWERINGEMITTER_H
+
+#include "CodeGenInstruction.h"
+#include "CodeGenTarget.h"
+#include "TableGenBackend.h"
+#include "llvm/ADT/IndexedMap.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm {
+
+class PseudoLoweringEmitter : public TableGenBackend {
+ struct OpData {
+ enum MapKind { Operand, Imm, Reg };
+ MapKind Kind;
+ union {
+ unsigned Operand; // Operand number mapped to.
+ uint64_t Imm; // Integer immedate value.
+ Record *Reg; // Physical register.
+ } Data;
+ };
+ struct PseudoExpansion {
+ CodeGenInstruction Source; // The source pseudo instruction definition.
+ CodeGenInstruction Dest; // The destination instruction to lower to.
+ IndexedMap<OpData> OperandMap;
+
+ PseudoExpansion(CodeGenInstruction &s, CodeGenInstruction &d,
+ IndexedMap<OpData> &m) :
+ Source(s), Dest(d), OperandMap(m) {}
+ };
+
+ RecordKeeper &Records;
+
+ // It's overkill to have an instance of the full CodeGenTarget object,
+ // but it loads everything on demand, not in the constructor, so it's
+ // lightweight in performance, so it works out OK.
+ CodeGenTarget Target;
+
+ SmallVector<PseudoExpansion, 64> Expansions;
+
+ unsigned addDagOperandMapping(Record *Rec, DagInit *Dag,
+ CodeGenInstruction &Insn,
+ IndexedMap<OpData> &OperandMap,
+ unsigned BaseIdx);
+ void evaluateExpansion(Record *Pseudo);
+ void emitLoweringEmitter(raw_ostream &o);
+public:
+ PseudoLoweringEmitter(RecordKeeper &R) : Records(R), Target(R) {}
+
+ /// run - Output the pseudo-lowerings.
+ void run(raw_ostream &o);
+};
+
+} // end llvm namespace
+
+#endif
diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h
index f24f5e6..2f4080b 100644
--- a/utils/TableGen/Record.h
+++ b/utils/TableGen/Record.h
@@ -34,7 +34,7 @@ class DagRecTy;
class RecordRecTy;
// Init subclasses.
-struct Init;
+class Init;
class UnsetInit;
class BitInit;
class BitsInit;
@@ -453,7 +453,8 @@ RecTy *resolveTypes(RecTy *T1, RecTy *T2);
// Initializer Classes
//===----------------------------------------------------------------------===//
-struct Init {
+class Init {
+public:
virtual ~Init() {}
/// isComplete - This virtual method should be overridden by values that may
diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp
index abb8624..65d4a9b 100644
--- a/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/utils/TableGen/RegisterInfoEmitter.cpp
@@ -162,16 +162,17 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << getQualifiedName(SR[j]->TheDef) << ", ";
OS << "0 };\n";
}
+ OS << "}\n"; // End of anonymous namespace...
- OS << "\n const MCRegisterDesc " << TargetName
+ OS << "\nMCRegisterDesc " << TargetName
<< "RegDesc[] = { // Descriptors\n";
- OS << " { \"NOREG\",\t0,\t0,\t0 },\n";
+ OS << " { \"NOREG\",\t0,\t0,\t0 },\n";
// Now that register alias and sub-registers sets have been emitted, emit the
// register descriptors now.
for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
const CodeGenRegister &Reg = *Regs[i];
- OS << " { \"";
+ OS << " { \"";
OS << Reg.getName() << "\",\t" << Reg.getName() << "_Overlaps,\t";
if (!Reg.getSubRegs().empty())
OS << Reg.getName() << "_SubRegsSet,\t";
@@ -183,9 +184,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "Empty_SuperRegsSet";
OS << " },\n";
}
- OS << " };\n"; // End of register descriptors...
-
- OS << "}\n\n"; // End of anonymous namespace...
+ OS << "};\n\n"; // End of register descriptors...
// MCRegisterInfo initialization routine.
OS << "static inline void Init" << TargetName
@@ -545,6 +544,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << " &" << getQualifiedName(RegisterClasses[i].TheDef)
<< "RegClass,\n";
OS << " };\n";
+ OS << "}\n"; // End of anonymous namespace...
// Emit extra information about registers.
const std::string &TargetName = Target.getName();
@@ -569,7 +569,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
// Emit SubRegIndex names, skipping 0
const std::vector<Record*> &SubRegIndices = RegBank.getSubRegIndices();
- OS << "\n const char *const SubRegIndexTable[] = { \"";
+ OS << "\n static const char *const " << TargetName
+ << "SubRegIndexTable[] = { \"";
for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) {
OS << SubRegIndices[i]->getName();
if (i+1 != e)
@@ -587,7 +588,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
}
OS << "\n };\n\n";
}
- OS << "}\n\n"; // End of anonymous namespace...
+ OS << "\n";
std::string ClassName = Target.getName() + "GenRegisterInfo";
@@ -658,11 +659,13 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << " }\n}\n\n";
// Emit the constructor of the class...
+ OS << "extern MCRegisterDesc " << TargetName << "RegDesc[];\n";
+
OS << ClassName << "::" << ClassName
<< "()\n"
<< " : TargetRegisterInfo(" << TargetName << "RegInfoDesc"
<< ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n"
- << " SubRegIndexTable) {\n"
+ << " " << TargetName << "SubRegIndexTable) {\n"
<< " InitMCRegisterInfo(" << TargetName << "RegDesc, "
<< Regs.size()+1 << ");\n"
<< "}\n\n";
diff --git a/utils/TableGen/SetTheory.h b/utils/TableGen/SetTheory.h
index e37a76e..6e8313b 100644
--- a/utils/TableGen/SetTheory.h
+++ b/utils/TableGen/SetTheory.h
@@ -55,7 +55,7 @@
namespace llvm {
class DagInit;
-struct Init;
+class Init;
class Record;
class RecordKeeper;
diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp
index df0425e..978e91a 100644
--- a/utils/TableGen/SubtargetEmitter.cpp
+++ b/utils/TableGen/SubtargetEmitter.cpp
@@ -81,8 +81,7 @@ unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
// Begin feature table
OS << "// Sorted (by key) array of values for CPU features.\n"
- << "static const llvm::SubtargetFeatureKV "
- << Target << "FeatureKV[] = {\n";
+ << "llvm::SubtargetFeatureKV " << Target << "FeatureKV[] = {\n";
// For each feature
unsigned NumFeatures = 0;
@@ -141,8 +140,7 @@ unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
// Begin processor table
OS << "// Sorted (by key) array of values for CPU subtype.\n"
- << "static const llvm::SubtargetFeatureKV "
- << Target << "SubTypeKV[] = {\n";
+ << "llvm::SubtargetFeatureKV " << Target << "SubTypeKV[] = {\n";
// For each processor
for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
@@ -329,9 +327,9 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS,
OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
<< "\"\n" << "namespace " << Name << "Bypass {\n";
- OS << " const unsigned NoBypass = 0;\n";
+ OS << " unsigned NoBypass = 0;\n";
for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j)
- OS << " const unsigned " << BPs[j]->getName()
+ OS << " unsigned " << BPs[j]->getName()
<< " = 1 << " << j << ";\n";
OS << "}\n";
@@ -339,17 +337,16 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS,
}
// Begin stages table
- std::string StageTable = "\nstatic const llvm::InstrStage " + Target +
- "Stages[] = {\n";
+ std::string StageTable = "\nllvm::InstrStage " + Target + "Stages[] = {\n";
StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
// Begin operand cycle table
- std::string OperandCycleTable = "static const unsigned " + Target +
+ std::string OperandCycleTable = "unsigned " + Target +
"OperandCycles[] = {\n";
OperandCycleTable += " 0, // No itinerary\n";
// Begin pipeline bypass table
- std::string BypassTable = "static const unsigned " + Target +
+ std::string BypassTable = "unsigned " + Target +
"ForwardingPathes[] = {\n";
BypassTable += " 0, // No itinerary\n";
@@ -491,7 +488,7 @@ EmitProcessorData(raw_ostream &OS,
// Begin processor itinerary table
OS << "\n";
- OS << "static const llvm::InstrItinerary " << Name << "[] = {\n";
+ OS << "llvm::InstrItinerary " << Name << "[] = {\n";
// For each itinerary class
std::vector<InstrItinerary> &ItinList = *ProcListIter++;
@@ -533,7 +530,7 @@ void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
// Begin processor table
OS << "\n";
OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
- << "static const llvm::SubtargetInfoKV "
+ << "llvm::SubtargetInfoKV "
<< Target << "ProcItinKV[] = {\n";
// For each processor
@@ -605,8 +602,7 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
<< "// subtarget options.\n"
<< "void llvm::";
OS << Target;
- OS << "Subtarget::ParseSubtargetFeatures(const std::string &FS,\n"
- << " const std::string &CPU) {\n"
+ OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n"
<< " DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n"
<< " DEBUG(dbgs() << \"\\nCPU:\" << CPU);\n";
@@ -615,11 +611,7 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
return;
}
- OS << " SubtargetFeatures Features(FS);\n"
- << " uint64_t Bits = Features.getFeatureBits(CPU, "
- << Target << "SubTypeKV, " << NumProcs << ",\n"
- << " " << Target << "FeatureKV, "
- << NumFeatures << ");\n";
+ OS << " uint64_t Bits = ReInitMCSubtargetInfo(CPU, FS);\n";
for (unsigned i = 0; i < Features.size(); i++) {
// Next record
@@ -629,10 +621,12 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
const std::string &Attribute = R->getValueAsString("Attribute");
if (Value=="true" || Value=="false")
- OS << " if ((Bits & " << Target << "::" << Instance << ") != 0) "
+ OS << " if ((Bits & " << Target << "::"
+ << Instance << ") != 0) "
<< Attribute << " = " << Value << ";\n";
else
- OS << " if ((Bits & " << Target << "::" << Instance << ") != 0 && "
+ OS << " if ((Bits & " << Target << "::"
+ << Instance << ") != 0 && "
<< Attribute << " < " << Value << ") "
<< Attribute << " = " << Value << ";\n";
}
@@ -648,23 +642,36 @@ void SubtargetEmitter::run(raw_ostream &OS) {
EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
+ OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
+ OS << "#undef GET_SUBTARGETINFO_ENUM\n";
+
+ OS << "namespace llvm {\n";
+ Enumeration(OS, "SubtargetFeature", true);
+ OS << "} // End llvm namespace \n";
+ OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
+
OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
OS << "#undef GET_SUBTARGETINFO_MC_DESC\n";
OS << "namespace llvm {\n";
- Enumeration(OS, "SubtargetFeature", true);
- OS<<"\n";
+#if 0
+ OS << "namespace {\n";
+#endif
unsigned NumFeatures = FeatureKeyValues(OS);
- OS<<"\n";
+ OS << "\n";
unsigned NumProcs = CPUKeyValues(OS);
- OS<<"\n";
+ OS << "\n";
EmitData(OS);
- OS<<"\n";
+ OS << "\n";
+#if 0
+ OS << "}\n";
+#endif
// MCInstrInfo initialization routine.
OS << "static inline void Init" << Target
- << "MCSubtargetInfo(MCSubtargetInfo *II) {\n";
- OS << " II->InitMCSubtargetInfo(";
+ << "MCSubtargetInfo(MCSubtargetInfo *II, "
+ << "StringRef TT, StringRef CPU, StringRef FS) {\n";
+ OS << " II->InitMCSubtargetInfo(TT, CPU, FS, ";
if (NumFeatures)
OS << Target << "FeatureKV, ";
else
@@ -702,7 +709,8 @@ void SubtargetEmitter::run(raw_ostream &OS) {
std::string ClassName = Target + "GenSubtargetInfo";
OS << "namespace llvm {\n";
OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n"
- << " explicit " << ClassName << "();\n"
+ << " explicit " << ClassName << "(StringRef TT, StringRef CPU, "
+ << "StringRef FS);\n"
<< "};\n";
OS << "} // End llvm namespace \n";
@@ -712,9 +720,19 @@ void SubtargetEmitter::run(raw_ostream &OS) {
OS << "#undef GET_SUBTARGETINFO_CTOR\n";
OS << "namespace llvm {\n";
- OS << ClassName << "::" << ClassName << "()\n"
+ OS << "extern llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
+ OS << "extern llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n";
+ if (HasItineraries) {
+ OS << "extern llvm::SubtargetInfoKV " << Target << "ProcItinKV[];\n";
+ OS << "extern llvm::InstrStage " << Target << "Stages[];\n";
+ OS << "extern unsigned " << Target << "OperandCycles[];\n";
+ OS << "extern unsigned " << Target << "ForwardingPathes[];\n";
+ }
+
+ OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, "
+ << "StringRef FS)\n"
<< " : TargetSubtargetInfo() {\n"
- << " InitMCSubtargetInfo(";
+ << " InitMCSubtargetInfo(TT, CPU, FS, ";
if (NumFeatures)
OS << Target << "FeatureKV, ";
else
diff --git a/utils/TableGen/TGParser.h b/utils/TableGen/TGParser.h
index 94a1c2b..dce7e1d 100644
--- a/utils/TableGen/TGParser.h
+++ b/utils/TableGen/TGParser.h
@@ -25,7 +25,7 @@ namespace llvm {
class RecordVal;
class RecordKeeper;
struct RecTy;
- struct Init;
+ class Init;
struct MultiClass;
struct SubClassReference;
struct SubMultiClassReference;
diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index ce16c9a..e8eacb8 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/utils/TableGen/TableGen.cpp
@@ -33,6 +33,7 @@
#include "LLVMCConfigurationEmitter.h"
#include "NeonEmitter.h"
#include "OptParserEmitter.h"
+#include "PseudoLoweringEmitter.h"
#include "Record.h"
#include "RegisterInfoEmitter.h"
#include "ARMDecoderEmitter.h"
@@ -59,6 +60,7 @@ enum ActionType {
GenAsmMatcher,
GenARMDecoder,
GenDisassembler,
+ GenPseudoLowering,
GenCallingConv,
GenClangAttrClasses,
GenClangAttrImpl,
@@ -106,6 +108,8 @@ namespace {
"Generate decoders for ARM/Thumb"),
clEnumValN(GenDisassembler, "gen-disassembler",
"Generate disassembler"),
+ clEnumValN(GenPseudoLowering, "gen-pseudo-lowering",
+ "Generate pseudo instruction lowering"),
clEnumValN(GenAsmMatcher, "gen-asm-matcher",
"Generate assembly instruction matcher"),
clEnumValN(GenDAGISel, "gen-dag-isel",
@@ -314,6 +318,9 @@ int main(int argc, char **argv) {
case GenDisassembler:
DisassemblerEmitter(Records).run(Out.os());
break;
+ case GenPseudoLowering:
+ PseudoLoweringEmitter(Records).run(Out.os());
+ break;
case GenOptParserDefs:
OptParserEmitter(Records, true).run(Out.os());
break;
diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp
index f7518a9..ea3bb70 100644
--- a/utils/TableGen/X86RecognizableInstr.cpp
+++ b/utils/TableGen/X86RecognizableInstr.cpp
@@ -229,6 +229,30 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
HasFROperands = hasFROperands();
HasVEX_LPrefix = has256BitOperands() || Rec->getValueAsBit("hasVEX_L");
+ // Check for 64-bit inst which does not require REX
+ Is64Bit = false;
+ // FIXME: Is there some better way to check for In64BitMode?
+ std::vector<Record*> Predicates = Rec->getValueAsListOfDefs("Predicates");
+ for (unsigned i = 0, e = Predicates.size(); i != e; ++i) {
+ if (Predicates[i]->getName().find("64Bit") != Name.npos) {
+ Is64Bit = true;
+ break;
+ }
+ }
+ // FIXME: These instructions aren't marked as 64-bit in any way
+ Is64Bit |= Rec->getName() == "JMP64pcrel32" ||
+ Rec->getName() == "MASKMOVDQU64" ||
+ Rec->getName() == "POPFS64" ||
+ Rec->getName() == "POPGS64" ||
+ Rec->getName() == "PUSHFS64" ||
+ Rec->getName() == "PUSHGS64" ||
+ Rec->getName() == "REX64_PREFIX" ||
+ Rec->getName().find("VMREAD64") != Name.npos ||
+ Rec->getName().find("VMWRITE64") != Name.npos ||
+ Rec->getName().find("MOV64") != Name.npos ||
+ Rec->getName().find("PUSH64") != Name.npos ||
+ Rec->getName().find("POP64") != Name.npos;
+
ShouldBeEmitted = true;
}
@@ -276,7 +300,7 @@ InstructionContext RecognizableInstr::insnContext() const {
insnContext = IC_VEX_XS;
else
insnContext = IC_VEX;
- } else if (Name.find("64") != Name.npos || HasREX_WPrefix) {
+ } else if (Is64Bit || HasREX_WPrefix) {
if (HasREX_WPrefix && HasOpSizePrefix)
insnContext = IC_64BIT_REXW_OPSIZE;
else if (HasOpSizePrefix)
diff --git a/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h
index c7ec18c..677d9f0 100644
--- a/utils/TableGen/X86RecognizableInstr.h
+++ b/utils/TableGen/X86RecognizableInstr.h
@@ -64,6 +64,8 @@ private:
bool HasLockPrefix;
/// The isCodeGenOnly filed from the record
bool IsCodeGenOnly;
+ // Whether the instruction has the predicate "Mode64Bit"
+ bool Is64Bit;
/// The instruction name as listed in the tables
std::string Name;