summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Target/Target.td39
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp25
-rw-r--r--utils/TableGen/AsmWriterEmitter.cpp116
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp27
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp7
-rw-r--r--utils/TableGen/CodeGenTarget.cpp5
-rw-r--r--utils/TableGen/CodeGenTarget.h7
-rw-r--r--utils/TableGen/DAGISelMatcherGen.cpp18
-rw-r--r--utils/TableGen/FastISelEmitter.cpp4
-rw-r--r--utils/TableGen/FixedLenDecoderEmitter.cpp4
-rw-r--r--utils/TableGen/InstrInfoEmitter.cpp34
-rw-r--r--utils/TableGen/Record.cpp19
-rw-r--r--utils/TableGen/Record.h6
-rw-r--r--utils/TableGen/RegisterInfoEmitter.cpp12
14 files changed, 268 insertions, 55 deletions
diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td
index bc8be89da8..4d7116b53b 100644
--- a/include/llvm/Target/Target.td
+++ b/include/llvm/Target/Target.td
@@ -26,11 +26,19 @@ class SubRegIndex {
string Namespace = "";
}
+// RegAltNameIndex - The alternate name set to use for register operands of
+// this register class when printing.
+class RegAltNameIndex {
+ string Namespace = "";
+}
+def NoRegAltName : RegAltNameIndex;
+
// Register - You should define one instance of this class for each register
// in the target machine. String n will become the "name" of the register.
-class Register<string n> {
+class Register<string n, list<string> altNames = []> {
string Namespace = "";
string AsmName = n;
+ list<string> AltNames = altNames;
// Aliases - A list of registers that this register overlaps with. A read or
// modification of this register can potentially read or modify the aliased
@@ -48,6 +56,10 @@ class Register<string n> {
// SubRegs.
list<SubRegIndex> SubRegIndices = [];
+ // RegAltNameIndices - The alternate name indices which are valid for this
+ // register.
+ list<RegAltNameIndex> RegAltNameIndices = [];
+
// CompositeIndices - Specify subreg indices that don't correspond directly to
// a register in SubRegs and are not inherited. The following formats are
// supported:
@@ -92,7 +104,7 @@ class RegisterWithSubRegs<string n, list<Register> subregs> : Register<n> {
// registers by register allocators.
//
class RegisterClass<string namespace, list<ValueType> regTypes, int alignment,
- dag regList> {
+ dag regList, RegAltNameIndex idx = NoRegAltName> {
string Namespace = namespace;
// RegType - Specify the list ValueType of the registers in this register
@@ -124,6 +136,11 @@ class RegisterClass<string namespace, list<ValueType> regTypes, int alignment,
//
dag MemberList = regList;
+ // AltNameIndex - The alternate register name to use when printing operands
+ // of this register class. Every register in the register class must have
+ // a valid alternate name for the given index.
+ RegAltNameIndex altNameIndex = idx;
+
// SubRegClasses - Specify the register class of subregisters as a list of
// dags: (RegClass SubRegIndex, SubRegindex, ...)
list<dag> SubRegClasses = [];
@@ -466,6 +483,24 @@ class Operand<ValueType ty> {
AsmOperandClass ParserMatchClass = ImmAsmOperand;
}
+class RegisterOperand<RegisterClass regclass, string pm = "printOperand"> {
+ // RegClass - The register class of the operand.
+ RegisterClass RegClass = regclass;
+ // PrintMethod - The target method to call to print register operands of
+ // this type. The method normally will just use an alt-name index to look
+ // up the name to print. Default to the generic printOperand().
+ string PrintMethod = pm;
+ // ParserMatchClass - The "match class" that operands of this type fit
+ // in. Match classes are used to define the order in which instructions are
+ // match, to ensure that which instructions gets matched is deterministic.
+ //
+ // The target specific parser must be able to classify an parsed operand into
+ // a unique class, which does not partially overlap with any other classes. It
+ // can match a subset of some other class, in which case the AsmOperandClass
+ // should declare the other operand as one of its super classes.
+ AsmOperandClass ParserMatchClass;
+}
+
def i1imm : Operand<i1>;
def i8imm : Operand<i8>;
def i16imm : Operand<i16>;
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index a05867bb3c..1fb92ee733 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -871,6 +871,31 @@ AsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI,
if (SubOpIdx != -1)
Rec = dynamic_cast<DefInit*>(OI.MIOperandInfo->getArg(SubOpIdx))->getDef();
+ if (Rec->isSubClassOf("RegisterOperand")) {
+ // RegisterOperand may have an associated ParserMatchClass. If it does,
+ // use it, else just fall back to the underlying register class.
+ const RecordVal *R = Rec->getValue("ParserMatchClass");
+ if (R == 0 || R->getValue() == 0)
+ throw "Record `" + Rec->getName() +
+ "' does not have a ParserMatchClass!\n";
+
+ if (DefInit *DI= dynamic_cast<DefInit*>(R->getValue())) {
+ Record *MatchClass = DI->getDef();
+ if (ClassInfo *CI = AsmOperandClasses[MatchClass])
+ return CI;
+ }
+
+ // No custom match class. Just use the register class.
+ Record *ClassRec = Rec->getValueAsDef("RegClass");
+ if (!ClassRec)
+ throw TGError(Rec->getLoc(), "RegisterOperand `" + Rec->getName() +
+ "' has no associated register class!\n");
+ if (ClassInfo *CI = RegisterClassClasses[ClassRec])
+ return CI;
+ throw TGError(Rec->getLoc(), "register class has no class info!");
+ }
+
+
if (Rec->isSubClassOf("RegisterClass")) {
if (ClassInfo *CI = RegisterClassClasses[Rec])
return CI;
diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp
index 066e03d8c7..53df7dd71a 100644
--- a/utils/TableGen/AsmWriterEmitter.cpp
+++ b/utils/TableGen/AsmWriterEmitter.cpp
@@ -18,6 +18,7 @@
#include "CodeGenTarget.h"
#include "Record.h"
#include "StringToOffsetTable.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
@@ -458,6 +459,58 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
O << "}\n";
}
+static void
+emitRegisterNameString(raw_ostream &O, StringRef AltName,
+ const std::vector<CodeGenRegister*> &Registers) {
+ StringToOffsetTable StringTable;
+ O << " static const unsigned RegAsmOffset" << AltName << "[] = {\n ";
+ for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
+ const CodeGenRegister &Reg = *Registers[i];
+
+ StringRef AsmName;
+ // "NoRegAltName" is special. We don't need to do a lookup for that,
+ // as it's just a reference to the default register name.
+ if (AltName == "" || AltName == "NoRegAltName") {
+ AsmName = Reg.TheDef->getValueAsString("AsmName");
+ if (AsmName.empty())
+ AsmName = Reg.getName();
+ } else {
+ // Make sure the register has an alternate name for this index.
+ std::vector<Record*> AltNameList =
+ Reg.TheDef->getValueAsListOfDefs("RegAltNameIndices");
+ unsigned Idx = 0, e;
+ for (e = AltNameList.size();
+ Idx < e && (AltNameList[Idx]->getName() != AltName);
+ ++Idx)
+ ;
+ // If the register has an alternate name for this index, use it.
+ // Otherwise, leave it empty as an error flag.
+ if (Idx < e) {
+ std::vector<std::string> AltNames =
+ Reg.TheDef->getValueAsListOfStrings("AltNames");
+ if (AltNames.size() <= Idx)
+ throw TGError(Reg.TheDef->getLoc(),
+ (Twine("Register definition missing alt name for '") +
+ AltName + "'.").str());
+ AsmName = AltNames[Idx];
+ }
+ }
+
+ O << StringTable.GetOrAddStringOffset(AsmName);
+ if (((i + 1) % 14) == 0)
+ O << ",\n ";
+ else
+ O << ", ";
+
+ }
+ O << "0\n"
+ << " };\n"
+ << "\n";
+
+ O << " const char *AsmStrs" << AltName << " =\n";
+ StringTable.EmitString(O);
+ O << ";\n";
+}
void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
CodeGenTarget Target(Records);
@@ -465,40 +518,48 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
const std::vector<CodeGenRegister*> &Registers =
Target.getRegBank().getRegisters();
+ std::vector<Record*> AltNameIndices = Target.getRegAltNameIndices();
+ bool hasAltNames = AltNameIndices.size() > 1;
- StringToOffsetTable StringTable;
O <<
"\n\n/// getRegisterName - This method is automatically generated by tblgen\n"
"/// from the register set description. This returns the assembler name\n"
"/// for the specified register.\n"
- "const char *" << Target.getName() << ClassName
- << "::getRegisterName(unsigned RegNo) {\n"
- << " assert(RegNo && RegNo < " << (Registers.size()+1)
- << " && \"Invalid register number!\");\n"
- << "\n"
- << " static const unsigned RegAsmOffset[] = {";
- for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
- const CodeGenRegister &Reg = *Registers[i];
-
- std::string AsmName = Reg.TheDef->getValueAsString("AsmName");
- if (AsmName.empty())
- AsmName = Reg.getName();
-
-
- if ((i % 14) == 0)
- O << "\n ";
-
- O << StringTable.GetOrAddStringOffset(AsmName) << ", ";
- }
- O << "0\n"
- << " };\n"
+ "const char *" << Target.getName() << ClassName << "::";
+ if (hasAltNames)
+ O << "\ngetRegisterName(unsigned RegNo, unsigned AltIdx) {\n";
+ else
+ O << "getRegisterName(unsigned RegNo) {\n";
+ O << " assert(RegNo && RegNo < " << (Registers.size()+1)
+ << " && \"Invalid register number!\");\n"
<< "\n";
- O << " const char *AsmStrs =\n";
- StringTable.EmitString(O);
- O << ";\n";
+ if (hasAltNames) {
+ for (unsigned i = 0, e = AltNameIndices.size(); i < e; ++i)
+ emitRegisterNameString(O, AltNameIndices[i]->getName(), Registers);
+ } else
+ emitRegisterNameString(O, "", Registers);
+
+ if (hasAltNames) {
+ O << " const unsigned *RegAsmOffset;\n"
+ << " const char *AsmStrs;\n"
+ << " switch(AltIdx) {\n"
+ << " default: assert(0 && \"Invalid register alt name index!\");\n";
+ for (unsigned i = 0, e = AltNameIndices.size(); i < e; ++i) {
+ StringRef Namespace = AltNameIndices[1]->getValueAsString("Namespace");
+ StringRef AltName(AltNameIndices[i]->getName());
+ O << " case " << Namespace << "::" << AltName
+ << ":\n"
+ << " AsmStrs = AsmStrs" << AltName << ";\n"
+ << " RegAsmOffset = RegAsmOffset" << AltName << ";\n"
+ << " break;\n";
+ }
+ O << "}\n";
+ }
- O << " return AsmStrs+RegAsmOffset[RegNo-1];\n"
+ O << " assert (*(AsmStrs+RegAsmOffset[RegNo-1]) &&\n"
+ << " \"Invalid alt name index for register!\");\n"
+ << " return AsmStrs+RegAsmOffset[RegNo-1];\n"
<< "}\n";
}
@@ -936,6 +997,9 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
const Record *Rec = RO.getRecord();
StringRef ROName = RO.getName();
+
+ if (Rec->isSubClassOf("RegisterOperand"))
+ Rec = Rec->getValueAsDef("RegClass");
if (Rec->isSubClassOf("RegisterClass")) {
Cond = std::string("MI->getOperand(")+llvm::utostr(i)+").isReg()";
IAP->addCond(Cond);
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index 1930a96ad7..0fe5d0510c 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -1242,6 +1242,16 @@ TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
///
static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo,
bool NotRegisters, TreePattern &TP) {
+ // Check to see if this is a register operand.
+ if (R->isSubClassOf("RegisterOperand")) {
+ assert(ResNo == 0 && "Regoperand ref only has one result!");
+ if (NotRegisters)
+ return EEVT::TypeSet(); // Unknown.
+ Record *RegClass = R->getValueAsDef("RegClass");
+ const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
+ return EEVT::TypeSet(T.getRegisterClass(RegClass).getValueTypes());
+ }
+
// Check to see if this is a register or a register class.
if (R->isSubClassOf("RegisterClass")) {
assert(ResNo == 0 && "Regclass ref only has one result!");
@@ -1524,6 +1534,11 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
if (ResultNode->isSubClassOf("PointerLikeRegClass")) {
MadeChange |= UpdateNodeType(ResNo, MVT::iPTR, TP);
+ } else if (ResultNode->isSubClassOf("RegisterOperand")) {
+ Record *RegClass = ResultNode->getValueAsDef("RegClass");
+ const CodeGenRegisterClass &RC =
+ CDP.getTargetInfo().getRegisterClass(RegClass);
+ MadeChange |= UpdateNodeType(ResNo, RC.getValueTypes(), TP);
} else if (ResultNode->getName() == "unknown") {
// Nothing to do.
} else {
@@ -1582,6 +1597,11 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
const CodeGenRegisterClass &RC =
CDP.getTargetInfo().getRegisterClass(OperandNode);
MadeChange |= Child->UpdateNodeType(ChildResNo, RC.getValueTypes(), TP);
+ } else if (OperandNode->isSubClassOf("RegisterOperand")) {
+ Record *RegClass = OperandNode->getValueAsDef("RegClass");
+ const CodeGenRegisterClass &RC =
+ CDP.getTargetInfo().getRegisterClass(RegClass);
+ MadeChange |= Child->UpdateNodeType(ChildResNo, RC.getValueTypes(), TP);
} else if (OperandNode->isSubClassOf("Operand")) {
VT = getValueType(OperandNode->getValueAsDef("Type"));
MadeChange |= Child->UpdateNodeType(ChildResNo, VT, TP);
@@ -1928,7 +1948,8 @@ InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) {
// def : Pat<(v1i64 (bitconvert(v2i32 DPR:$src))), (v1i64 DPR:$src)>;
if (Nodes[i] == Trees[0] && Nodes[i]->isLeaf()) {
DefInit *DI = dynamic_cast<DefInit*>(Nodes[i]->getLeafValue());
- if (DI && DI->getDef()->isSubClassOf("RegisterClass"))
+ if (DI && (DI->getDef()->isSubClassOf("RegisterClass") ||
+ DI->getDef()->isSubClassOf("RegisterOperand")))
continue;
}
@@ -2211,7 +2232,8 @@ static bool HandleUse(TreePattern *I, TreePatternNode *Pat,
if (Pat->getName().empty()) {
if (Pat->isLeaf()) {
DefInit *DI = dynamic_cast<DefInit*>(Pat->getLeafValue());
- if (DI && DI->getDef()->isSubClassOf("RegisterClass"))
+ if (DI && (DI->getDef()->isSubClassOf("RegisterClass") ||
+ DI->getDef()->isSubClassOf("RegisterOperand")))
I->error("Input " + DI->getDef()->getName() + " must be named!");
}
return false;
@@ -2318,6 +2340,7 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
I->error("set destination should be a register!");
if (Val->getDef()->isSubClassOf("RegisterClass") ||
+ Val->getDef()->isSubClassOf("RegisterOperand") ||
Val->getDef()->isSubClassOf("PointerLikeRegClass")) {
if (Dest->getName().empty())
I->error("set destination must have a name!");
diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp
index e9557d2b4b..5fa91be488 100644
--- a/utils/TableGen/CodeGenInstruction.cpp
+++ b/utils/TableGen/CodeGenInstruction.cpp
@@ -69,7 +69,9 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
std::string EncoderMethod;
unsigned NumOps = 1;
DagInit *MIOpInfo = 0;
- if (Rec->isSubClassOf("Operand")) {
+ if (Rec->isSubClassOf("RegisterOperand")) {
+ PrintMethod = Rec->getValueAsString("PrintMethod");
+ } else if (Rec->isSubClassOf("Operand")) {
PrintMethod = Rec->getValueAsString("PrintMethod");
// If there is an explicit encoder method, use it.
EncoderMethod = Rec->getValueAsString("EncoderMethod");
@@ -415,6 +417,9 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
// Handle explicit registers.
if (ADI && ADI->getDef()->isSubClassOf("Register")) {
+ if (InstOpRec->isSubClassOf("RegisterOperand"))
+ InstOpRec = InstOpRec->getValueAsDef("RegClass");
+
if (!InstOpRec->isSubClassOf("RegisterClass"))
return false;
diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp
index 5b0b315126..929791c318 100644
--- a/utils/TableGen/CodeGenTarget.cpp
+++ b/utils/TableGen/CodeGenTarget.cpp
@@ -164,6 +164,11 @@ CodeGenRegBank &CodeGenTarget::getRegBank() const {
return *RegBank;
}
+void CodeGenTarget::ReadRegAltNameIndices() const {
+ RegAltNameIndices = Records.getAllDerivedDefinitions("RegAltNameIndex");
+ std::sort(RegAltNameIndices.begin(), RegAltNameIndices.end(), LessRecord());
+}
+
/// getRegisterByName - If there is a register with the specific AsmName,
/// return it.
const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {
diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h
index 9bedb9ce45..143daedae8 100644
--- a/utils/TableGen/CodeGenTarget.h
+++ b/utils/TableGen/CodeGenTarget.h
@@ -66,7 +66,9 @@ class CodeGenTarget {
mutable DenseMap<const Record*, CodeGenInstruction*> Instructions;
mutable CodeGenRegBank *RegBank;
+ mutable std::vector<Record*> RegAltNameIndices;
mutable std::vector<MVT::SimpleValueType> LegalValueTypes;
+ void ReadRegAltNameIndices() const;
void ReadInstructions() const;
void ReadLegalValueTypes() const;
@@ -100,6 +102,11 @@ public:
/// return it.
const CodeGenRegister *getRegisterByName(StringRef Name) const;
+ const std::vector<Record*> &getRegAltNameIndices() const {
+ if (RegAltNameIndices.empty()) ReadRegAltNameIndices();
+ return RegAltNameIndices;
+ }
+
const std::vector<CodeGenRegisterClass> &getRegisterClasses() const {
return getRegBank().getRegClasses();
}
diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp
index 54553a8f17..c5897c72d3 100644
--- a/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/utils/TableGen/DAGISelMatcherGen.cpp
@@ -224,6 +224,7 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) {
Record *LeafRec = DI->getDef();
if (// Handle register references. Nothing to do here, they always match.
LeafRec->isSubClassOf("RegisterClass") ||
+ LeafRec->isSubClassOf("RegisterOperand") ||
LeafRec->isSubClassOf("PointerLikeRegClass") ||
LeafRec->isSubClassOf("SubRegIndex") ||
// Place holder for SRCVALUE nodes. Nothing to do here.
@@ -579,15 +580,16 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N,
// If this is an explicit register reference, handle it.
if (DefInit *DI = dynamic_cast<DefInit*>(N->getLeafValue())) {
- if (DI->getDef()->isSubClassOf("Register")) {
+ Record *Def = DI->getDef();
+ if (Def->isSubClassOf("Register")) {
const CodeGenRegister *Reg =
- CGP.getTargetInfo().getRegBank().getReg(DI->getDef());
+ CGP.getTargetInfo().getRegBank().getReg(Def);
AddMatcher(new EmitRegisterMatcher(Reg, N->getType(0)));
ResultOps.push_back(NextRecordedOperandNo++);
return;
}
- if (DI->getDef()->getName() == "zero_reg") {
+ if (Def->getName() == "zero_reg") {
AddMatcher(new EmitRegisterMatcher(0, N->getType(0)));
ResultOps.push_back(NextRecordedOperandNo++);
return;
@@ -595,16 +597,18 @@ void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N,
// Handle a reference to a register class. This is used
// in COPY_TO_SUBREG instructions.
- if (DI->getDef()->isSubClassOf("RegisterClass")) {
- std::string Value = getQualifiedName(DI->getDef()) + "RegClassID";
+ if (Def->isSubClassOf("RegisterOperand"))
+ Def = Def->getValueAsDef("RegClass");
+ if (Def->isSubClassOf("RegisterClass")) {
+ std::string Value = getQualifiedName(Def) + "RegClassID";
AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32));
ResultOps.push_back(NextRecordedOperandNo++);
return;
}
// Handle a subregister index. This is used for INSERT_SUBREG etc.
- if (DI->getDef()->isSubClassOf("SubRegIndex")) {
- std::string Value = getQualifiedName(DI->getDef());
+ if (Def->isSubClassOf("SubRegIndex")) {
+ std::string Value = getQualifiedName(Def);
AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32));
ResultOps.push_back(NextRecordedOperandNo++);
return;
diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp
index f946ac73ca..f54e8df40f 100644
--- a/utils/TableGen/FastISelEmitter.cpp
+++ b/utils/TableGen/FastISelEmitter.cpp
@@ -248,6 +248,8 @@ struct OperandsSignature {
// For now, the only other thing we accept is register operands.
const CodeGenRegisterClass *RC = 0;
+ if (OpLeafRec->isSubClassOf("RegisterOperand"))
+ OpLeafRec = OpLeafRec->getValueAsDef("RegClass");
if (OpLeafRec->isSubClassOf("RegisterClass"))
RC = &Target.getRegisterClass(OpLeafRec);
else if (OpLeafRec->isSubClassOf("Register"))
@@ -454,6 +456,8 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
std::string SubRegNo;
if (Op->getName() != "EXTRACT_SUBREG") {
Record *Op0Rec = II.Operands[0].Rec;
+ if (Op0Rec->isSubClassOf("RegisterOperand"))
+ Op0Rec = Op0Rec->getValueAsDef("RegClass");
if (!Op0Rec->isSubClassOf("RegisterClass"))
continue;
DstRC = &Target.getRegisterClass(Op0Rec);
diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp
index 9312fe8d02..ba6cd863c8 100644
--- a/utils/TableGen/FixedLenDecoderEmitter.cpp
+++ b/utils/TableGen/FixedLenDecoderEmitter.cpp
@@ -1305,8 +1305,10 @@ bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI,
RecordRecTy *Type = dynamic_cast<RecordRecTy*>(TI->getType());
Record *TypeRecord = Type->getRecord();
bool isReg = false;
+ if (TypeRecord->isSubClassOf("RegisterOperand"))
+ TypeRecord = TypeRecord->getValueAsDef("RegClass");
if (TypeRecord->isSubClassOf("RegisterClass")) {
- Decoder = "Decode" + Type->getRecord()->getName() + "RegisterClass";
+ Decoder = "Decode" + TypeRecord->getName() + "RegisterClass";
isReg = true;
}
diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index fc544ee658..6a96696b24 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/utils/TableGen/InstrInfoEmitter.cpp
@@ -43,10 +43,10 @@ void InstrInfoEmitter::GatherItinClasses() {
std::vector<Record*> DefList =
Records.getAllDerivedDefinitions("InstrItinClass");
std::sort(DefList.begin(), DefList.end(), LessRecord());
-
+
for (unsigned i = 0, N = DefList.size(); i < N; i++)
ItinClassMap[DefList[i]->getName()] = i;
-}
+}
unsigned InstrInfoEmitter::getItinClassNumber(const Record *InstRec) {
return ItinClassMap[InstRec->getValueAsDef("Itinerary")->getName()];
@@ -59,7 +59,7 @@ unsigned InstrInfoEmitter::getItinClassNumber(const Record *InstRec) {
std::vector<std::string>
InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
std::vector<std::string> Result;
-
+
for (unsigned i = 0, e = Inst.Operands.size(); i != e; ++i) {
// Handle aggregate operands and normal operands the same way by expanding
// either case into a list of operands for this op.
@@ -70,7 +70,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
// operand, which has a single operand, but no declared class for the
// operand.
DagInit *MIOI = Inst.Operands[i].MIOperandInfo;
-
+
if (!MIOI || MIOI->getNumArgs() == 0) {
// Single, anonymous, operand.
OperandList.push_back(Inst.Operands[i]);
@@ -86,7 +86,9 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
for (unsigned j = 0, e = OperandList.size(); j != e; ++j) {
Record *OpR = OperandList[j].Rec;
std::string Res;
-
+
+ if (OpR->isSubClassOf("RegisterOperand"))
+ OpR = OpR->getValueAsDef("RegClass");
if (OpR->isSubClassOf("RegisterClass"))
Res += getQualifiedName(OpR) + "RegClassID, ";
else if (OpR->isSubClassOf("PointerLikeRegClass"))
@@ -94,10 +96,10 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
else
// -1 means the operand does not have a fixed register class.
Res += "-1, ";
-
+
// Fill in applicable flags.
Res += "0";
-
+
// Ptr value whose register class is resolved via callback.
if (OpR->isSubClassOf("PointerLikeRegClass"))
Res += "|(1<<TOI::LookupPtrRegClass)";
@@ -106,7 +108,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
// was of type PredicateOperand.
if (Inst.Operands[i].Rec->isSubClassOf("PredicateOperand"))
Res += "|(1<<TOI::Predicate)";
-
+
// Optional def operands. Check to see if the original unexpanded operand
// was of type OptionalDefOperand.
if (Inst.Operands[i].Rec->isSubClassOf("OptionalDefOperand"))
@@ -114,7 +116,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
// Fill in constraint info.
Res += ", ";
-
+
const CGIOperandList::ConstraintInfo &Constraint =
Inst.Operands[i].Constraints[j];
if (Constraint.isNone())
@@ -126,7 +128,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
Res += "((" + utostr(Constraint.getTiedOperand()) +
" << 16) | (1 << TOI::TIED_TO))";
}
-
+
Result.push_back(Res);
}
}
@@ -134,12 +136,12 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
return Result;
}
-void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
+void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
OperandInfoMapTy &OperandInfoIDs) {
// ID #0 is for no operand info.
unsigned OperandListNum = 0;
OperandInfoIDs[std::vector<std::string>()] = ++OperandListNum;
-
+
OS << "\n";
const CodeGenTarget &Target = CDP.getTargetInfo();
for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
@@ -147,7 +149,7 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
std::vector<std::string> OperandInfo = GetOperandInfo(**II);
unsigned &N = OperandInfoIDs[OperandInfo];
if (N != 0) continue;
-
+
N = ++OperandListNum;
OS << "static const TargetOperandInfo OperandInfo" << N << "[] = { ";
for (unsigned i = 0, e = OperandInfo.size(); i != e; ++i)
@@ -205,7 +207,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
std::map<std::vector<Record*>, unsigned> EmittedBarriers;
unsigned BarrierNumber = 0;
std::map<Record*, unsigned> BarriersMap;
-
+
// Emit all of the instruction's implicit uses and defs.
for (CodeGenTarget::inst_iterator II = Target.inst_begin(),
E = Target.inst_end(); II != E; ++II) {
@@ -231,10 +233,10 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
}
OperandInfoMapTy OperandInfoIDs;
-
+
// Emit all of the operand info records.
EmitOperandInfo(OS, OperandInfoIDs);
-
+
// Emit all of the TargetInstrDesc records in their ENUM ordering.
//
OS << "\nstatic const TargetInstrDesc " << TargetName
diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp
index 3c750da55f..730eca1b3c 100644
--- a/utils/TableGen/Record.cpp
+++ b/utils/TableGen/Record.cpp
@@ -1443,6 +1443,25 @@ Record::getValueAsListOfInts(StringRef FieldName) const {
return Ints;
}
+/// getValueAsListOfStrings - This method looks up the specified field and
+/// returns its value as a vector of strings, throwing an exception if the
+/// field does not exist or if the value is not the right type.
+///
+std::vector<std::string>
+Record::getValueAsListOfStrings(StringRef FieldName) const {
+ ListInit *List = getValueAsListInit(FieldName);
+ std::vector<std::string> Strings;
+ for (unsigned i = 0; i < List->getSize(); i++) {
+ if (StringInit *II = dynamic_cast<StringInit*>(List->getElement(i))) {
+ Strings.push_back(II->getValue());
+ } else {
+ throw "Record `" + getName() + "', field `" + FieldName.str() +
+ "' does not have a list of strings initializer!";
+ }
+ }
+ return Strings;
+}
+
/// getValueAsDef - This method looks up the specified field and returns its
/// value as a Record, throwing an exception if the field does not exist or if
/// the value is not the right type.
diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h
index c8905ccde7..f24f5e66fa 100644
--- a/utils/TableGen/Record.h
+++ b/utils/TableGen/Record.h
@@ -1368,6 +1368,12 @@ public:
///
std::vector<int64_t> getValueAsListOfInts(StringRef FieldName) const;
+ /// getValueAsListOfStrings - This method looks up the specified field and
+ /// returns its value as a vector of strings, throwing an exception if the
+ /// field does not exist or if the value is not the right type.
+ ///
+ std::vector<std::string> getValueAsListOfStrings(StringRef FieldName) const;
+
/// getValueAsDef - This method looks up the specified field and returns its
/// value as a Record, throwing an exception if the field does not exist or if
/// the value is not the right type.
diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp
index ab081eb013..f8ce3ac153 100644
--- a/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/utils/TableGen/RegisterInfoEmitter.cpp
@@ -112,6 +112,18 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "0 };\n";
}
+ 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) {
+ OS << "\n// Register alternate name indices\n";
+ OS << "enum {\n";
+ for (unsigned i = 0, e = RegAltNameIndices.size(); i != e; ++i)
+ OS << " " << RegAltNameIndices[i]->getName() << ",\t// " << i << "\n";
+ OS << " NUM_TARGET_REG_ALT_NAMES = " << RegAltNameIndices.size() << "\n";
+ OS << "};\n";
+ }
+
// Emit the empty sub-registers list
OS << " const unsigned Empty_SubRegsSet[] = { 0 };\n";
// Loop over all of the registers which have sub-registers, emitting the