From bea6f615eefae279e53bbb63a31d2c3c67274c45 Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Mon, 27 Jun 2011 21:06:21 +0000 Subject: [PATCH] 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 --- include/llvm/Target/Target.td | 39 +++++++- utils/TableGen/AsmMatcherEmitter.cpp | 25 +++++ utils/TableGen/AsmWriterEmitter.cpp | 116 +++++++++++++++++----- utils/TableGen/CodeGenDAGPatterns.cpp | 27 ++++- utils/TableGen/CodeGenInstruction.cpp | 7 +- utils/TableGen/CodeGenTarget.cpp | 5 + utils/TableGen/CodeGenTarget.h | 7 ++ utils/TableGen/DAGISelMatcherGen.cpp | 18 ++-- utils/TableGen/FastISelEmitter.cpp | 4 + utils/TableGen/FixedLenDecoderEmitter.cpp | 4 +- utils/TableGen/InstrInfoEmitter.cpp | 34 ++++--- utils/TableGen/Record.cpp | 19 ++++ utils/TableGen/Record.h | 6 ++ utils/TableGen/RegisterInfoEmitter.cpp | 12 +++ 14 files changed, 268 insertions(+), 55 deletions(-) diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index bc8be89da8a..4d7116b53b0 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 { +class Register altNames = []> { string Namespace = ""; string AsmName = n; + list 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 { // SubRegs. list SubRegIndices = []; + // RegAltNameIndices - The alternate name indices which are valid for this + // register. + list 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 subregs> : Register { // registers by register allocators. // class RegisterClass 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 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 SubRegClasses = []; @@ -466,6 +483,24 @@ class Operand { AsmOperandClass ParserMatchClass = ImmAsmOperand; } +class RegisterOperand { + // 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; def i8imm : Operand; def i16imm : Operand; diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index a05867bb3c3..1fb92ee733a 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(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(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 066e03d8c71..53df7dd71a0 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 @@ -458,6 +459,58 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { O << "}\n"; } +static void +emitRegisterNameString(raw_ostream &O, StringRef AltName, + const std::vector &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 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 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 &Registers = Target.getRegBank().getRegisters(); + std::vector 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); - O << " return AsmStrs+RegAsmOffset[RegNo-1];\n" + 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 << " 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 1930a96ad70..0fe5d0510c0 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 > *InNamedTypes) { // def : Pat<(v1i64 (bitconvert(v2i32 DPR:$src))), (v1i64 DPR:$src)>; if (Nodes[i] == Trees[0] && Nodes[i]->isLeaf()) { DefInit *DI = dynamic_cast(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(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 e9557d2b4bc..5fa91be4885 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 5b0b315126d..929791c3182 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 9bedb9ce457..143daedae83 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -66,7 +66,9 @@ class CodeGenTarget { mutable DenseMap Instructions; mutable CodeGenRegBank *RegBank; + mutable std::vector RegAltNameIndices; mutable std::vector 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 &getRegAltNameIndices() const { + if (RegAltNameIndices.empty()) ReadRegAltNameIndices(); + return RegAltNameIndices; + } + const std::vector &getRegisterClasses() const { return getRegBank().getRegClasses(); } diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index 54553a8f17e..c5897c72d36 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(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 f946ac73cac..f54e8df40f2 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 9312fe8d02c..ba6cd863c81 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(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 fc544ee658b..6a96696b24d 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -43,10 +43,10 @@ void InstrInfoEmitter::GatherItinClasses() { std::vector 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 InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { std::vector 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<isSubClassOf("PredicateOperand")) Res += "|(1<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()] = ++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 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, unsigned> EmittedBarriers; unsigned BarrierNumber = 0; std::map 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 3c750da55f4..730eca1b3ca 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 +Record::getValueAsListOfStrings(StringRef FieldName) const { + ListInit *List = getValueAsListInit(FieldName); + std::vector Strings; + for (unsigned i = 0; i < List->getSize(); i++) { + if (StringInit *II = dynamic_cast(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 c8905ccde79..f24f5e66fa0 100644 --- a/utils/TableGen/Record.h +++ b/utils/TableGen/Record.h @@ -1368,6 +1368,12 @@ public: /// std::vector 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 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 ab081eb013a..f8ce3ac153d 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 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