summaryrefslogtreecommitdiffstats
path: root/llvm/utils
diff options
context:
space:
mode:
authorOwen Anderson <resistor@mac.com>2011-06-27 21:06:21 +0000
committerOwen Anderson <resistor@mac.com>2011-06-27 21:06:21 +0000
commita84be6c96b677788380b43525273871e23420458 (patch)
tree60b068e37b0651ffa87df377eab6e3130b8eb3a9 /llvm/utils
parent0ceb5473a3875d46e37989f5137a278c7e332bcb (diff)
downloadbcm5719-llvm-a84be6c96b677788380b43525273871e23420458.tar.gz
bcm5719-llvm-a84be6c96b677788380b43525273871e23420458.zip
Add support for alternative register names, useful for instructions whose operands are logically equivalent to existing registers, but happen to be printed specially. For example, an instruciton that prints d0[0] instead of s0.
Patch by Jim Grosbach. llvm-svn: 133940
Diffstat (limited to 'llvm/utils')
-rw-r--r--llvm/utils/TableGen/AsmMatcherEmitter.cpp25
-rw-r--r--llvm/utils/TableGen/AsmWriterEmitter.cpp116
-rw-r--r--llvm/utils/TableGen/CodeGenDAGPatterns.cpp27
-rw-r--r--llvm/utils/TableGen/CodeGenInstruction.cpp7
-rw-r--r--llvm/utils/TableGen/CodeGenTarget.cpp5
-rw-r--r--llvm/utils/TableGen/CodeGenTarget.h7
-rw-r--r--llvm/utils/TableGen/DAGISelMatcherGen.cpp18
-rw-r--r--llvm/utils/TableGen/FastISelEmitter.cpp4
-rw-r--r--llvm/utils/TableGen/FixedLenDecoderEmitter.cpp4
-rw-r--r--llvm/utils/TableGen/InstrInfoEmitter.cpp34
-rw-r--r--llvm/utils/TableGen/Record.cpp19
-rw-r--r--llvm/utils/TableGen/Record.h6
-rw-r--r--llvm/utils/TableGen/RegisterInfoEmitter.cpp12
13 files changed, 231 insertions, 53 deletions
diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index a05867bb3c3..1fb92ee733a 100644
--- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/llvm/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/llvm/utils/TableGen/AsmWriterEmitter.cpp b/llvm/utils/TableGen/AsmWriterEmitter.cpp
index 066e03d8c71..53df7dd71a0 100644
--- a/llvm/utils/TableGen/AsmWriterEmitter.cpp
+++ b/llvm/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/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
index 1930a96ad70..0fe5d0510c0 100644
--- a/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/llvm/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/llvm/utils/TableGen/CodeGenInstruction.cpp b/llvm/utils/TableGen/CodeGenInstruction.cpp
index e9557d2b4bc..5fa91be4885 100644
--- a/llvm/utils/TableGen/CodeGenInstruction.cpp
+++ b/llvm/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/llvm/utils/TableGen/CodeGenTarget.cpp b/llvm/utils/TableGen/CodeGenTarget.cpp
index 5b0b315126d..929791c3182 100644
--- a/llvm/utils/TableGen/CodeGenTarget.cpp
+++ b/llvm/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/llvm/utils/TableGen/CodeGenTarget.h b/llvm/utils/TableGen/CodeGenTarget.h
index 9bedb9ce457..143daedae83 100644
--- a/llvm/utils/TableGen/CodeGenTarget.h
+++ b/llvm/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/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/llvm/utils/TableGen/DAGISelMatcherGen.cpp
index 54553a8f17e..c5897c72d36 100644
--- a/llvm/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/llvm/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/llvm/utils/TableGen/FastISelEmitter.cpp b/llvm/utils/TableGen/FastISelEmitter.cpp
index f946ac73cac..f54e8df40f2 100644
--- a/llvm/utils/TableGen/FastISelEmitter.cpp
+++ b/llvm/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/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
index 9312fe8d02c..ba6cd863c81 100644
--- a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
+++ b/llvm/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/llvm/utils/TableGen/InstrInfoEmitter.cpp b/llvm/utils/TableGen/InstrInfoEmitter.cpp
index fc544ee658b..6a96696b24d 100644
--- a/llvm/utils/TableGen/InstrInfoEmitter.cpp
+++ b/llvm/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/llvm/utils/TableGen/Record.cpp b/llvm/utils/TableGen/Record.cpp
index 3c750da55f4..730eca1b3ca 100644
--- a/llvm/utils/TableGen/Record.cpp
+++ b/llvm/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/llvm/utils/TableGen/Record.h b/llvm/utils/TableGen/Record.h
index c8905ccde79..f24f5e66fa0 100644
--- a/llvm/utils/TableGen/Record.h
+++ b/llvm/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/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp
index ab081eb013a..f8ce3ac153d 100644
--- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/llvm/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
OpenPOWER on IntegriCloud