diff options
author | Owen Anderson <resistor@mac.com> | 2011-06-27 21:06:21 +0000 |
---|---|---|
committer | Owen Anderson <resistor@mac.com> | 2011-06-27 21:06:21 +0000 |
commit | bea6f615eefae279e53bbb63a31d2c3c67274c45 (patch) | |
tree | 4c5b33c01d807a99de8411304c63cfdb5583b259 /utils | |
parent | d1f0bbee189ea7cd18d03c4f9f55d0a33b070814 (diff) | |
download | llvm-bea6f615eefae279e53bbb63a31d2c3c67274c45.tar.gz llvm-bea6f615eefae279e53bbb63a31d2c3c67274c45.tar.bz2 llvm-bea6f615eefae279e53bbb63a31d2c3c67274c45.tar.xz |
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.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133940 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r-- | utils/TableGen/AsmMatcherEmitter.cpp | 25 | ||||
-rw-r--r-- | utils/TableGen/AsmWriterEmitter.cpp | 116 | ||||
-rw-r--r-- | utils/TableGen/CodeGenDAGPatterns.cpp | 27 | ||||
-rw-r--r-- | utils/TableGen/CodeGenInstruction.cpp | 7 | ||||
-rw-r--r-- | utils/TableGen/CodeGenTarget.cpp | 5 | ||||
-rw-r--r-- | utils/TableGen/CodeGenTarget.h | 7 | ||||
-rw-r--r-- | utils/TableGen/DAGISelMatcherGen.cpp | 18 | ||||
-rw-r--r-- | utils/TableGen/FastISelEmitter.cpp | 4 | ||||
-rw-r--r-- | utils/TableGen/FixedLenDecoderEmitter.cpp | 4 | ||||
-rw-r--r-- | utils/TableGen/InstrInfoEmitter.cpp | 34 | ||||
-rw-r--r-- | utils/TableGen/Record.cpp | 19 | ||||
-rw-r--r-- | utils/TableGen/Record.h | 6 | ||||
-rw-r--r-- | utils/TableGen/RegisterInfoEmitter.cpp | 12 |
13 files changed, 231 insertions, 53 deletions
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 |