diff options
Diffstat (limited to 'contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp')
-rw-r--r-- | contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp | 332 |
1 files changed, 148 insertions, 184 deletions
diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp index e6deb69..f44f050 100644 --- a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp +++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp @@ -14,9 +14,11 @@ #include "AsmWriterEmitter.h" #include "AsmWriterInst.h" +#include "Error.h" #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> @@ -457,46 +459,107 @@ 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]; + + std::string 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); Record *AsmWriter = Target.getAsmWriter(); std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); - const std::vector<CodeGenRegister> &Registers = Target.getRegisters(); + 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"; } @@ -543,92 +606,29 @@ void AsmWriterEmitter::EmitGetInstructionName(raw_ostream &O) { } namespace { - -/// SubtargetFeatureInfo - Helper class for storing information on a subtarget -/// feature which participates in instruction matching. -struct SubtargetFeatureInfo { - /// \brief The predicate record for this feature. - const Record *TheDef; - - /// \brief An unique index assigned to represent this feature. - unsigned Index; - - SubtargetFeatureInfo(const Record *D, unsigned Idx) : TheDef(D), Index(Idx) {} - - /// \brief The name of the enumerated constant identifying this feature. - std::string getEnumName() const { - return "Feature_" + TheDef->getName(); - } -}; - -struct AsmWriterInfo { - /// Map of Predicate records to their subtarget information. - std::map<const Record*, SubtargetFeatureInfo*> SubtargetFeatures; - - /// getSubtargetFeature - Lookup or create the subtarget feature info for the - /// given operand. - SubtargetFeatureInfo *getSubtargetFeature(const Record *Def) const { - assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!"); - std::map<const Record*, SubtargetFeatureInfo*>::const_iterator I = - SubtargetFeatures.find(Def); - return I == SubtargetFeatures.end() ? 0 : I->second; - } - - void addReqFeatures(const std::vector<Record*> &Features) { - for (std::vector<Record*>::const_iterator - I = Features.begin(), E = Features.end(); I != E; ++I) { - const Record *Pred = *I; - - // Ignore predicates that are not intended for the assembler. - if (!Pred->getValueAsBit("AssemblerMatcherPredicate")) - continue; - - if (Pred->getName().empty()) - throw TGError(Pred->getLoc(), "Predicate has no name!"); - - // Don't add the predicate again. - if (getSubtargetFeature(Pred)) - continue; - - unsigned FeatureNo = SubtargetFeatures.size(); - SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo); - assert(FeatureNo < 32 && "Too many subtarget features!"); - } - } - - const SubtargetFeatureInfo *getFeatureInfo(const Record *R) { - return SubtargetFeatures[R]; - } -}; - // IAPrinter - Holds information about an InstAlias. Two InstAliases match if // they both have the same conditionals. In which case, we cannot print out the // alias for that pattern. class IAPrinter { - AsmWriterInfo &AWI; std::vector<std::string> Conds; std::map<StringRef, unsigned> OpMap; std::string Result; std::string AsmString; std::vector<Record*> ReqFeatures; public: - IAPrinter(AsmWriterInfo &Info, std::string R, std::string AS) - : AWI(Info), Result(R), AsmString(AS) {} + IAPrinter(std::string R, std::string AS) + : Result(R), AsmString(AS) {} void addCond(const std::string &C) { Conds.push_back(C); } - void addReqFeatures(const std::vector<Record*> &Features) { - AWI.addReqFeatures(Features); - ReqFeatures = Features; - } void addOperand(StringRef Op, unsigned Idx) { OpMap[Op] = Idx; } unsigned getOpIndex(StringRef Op) { return OpMap[Op]; } bool isOpMapped(StringRef Op) { return OpMap.find(Op) != OpMap.end(); } - bool print(raw_ostream &O) { + void print(raw_ostream &O) { if (Conds.empty() && ReqFeatures.empty()) { O.indent(6) << "return true;\n"; - return false; + return; } O << "if ("; @@ -643,27 +643,6 @@ public: O << *I; } - if (!ReqFeatures.empty()) { - if (Conds.begin() != Conds.end()) { - O << " &&\n"; - O.indent(8); - } else { - O << "if ("; - } - - std::string Req; - raw_string_ostream ReqO(Req); - - for (std::vector<Record*>::iterator - I = ReqFeatures.begin(), E = ReqFeatures.end(); I != E; ++I) { - if (I != ReqFeatures.begin()) ReqO << " | "; - ReqO << AWI.getFeatureInfo(*I)->getEnumName(); - } - - O << "(AvailableFeatures & (" << ReqO.str() << ")) == (" - << ReqO.str() << ')'; - } - O << ") {\n"; O.indent(6) << "// " << Result << "\n"; O.indent(6) << "AsmString = \"" << AsmString << "\";\n"; @@ -675,7 +654,6 @@ public: O.indent(6) << "break;\n"; O.indent(4) << '}'; - return !ReqFeatures.empty(); } bool operator==(const IAPrinter &RHS) { @@ -707,53 +685,6 @@ public: } // end anonymous namespace -/// EmitSubtargetFeatureFlagEnumeration - Emit the subtarget feature flag -/// definitions. -static void EmitSubtargetFeatureFlagEnumeration(AsmWriterInfo &Info, - raw_ostream &O) { - O << "namespace {\n\n"; - O << "// Flags for subtarget features that participate in " - << "alias instruction matching.\n"; - O << "enum SubtargetFeatureFlag {\n"; - - for (std::map<const Record*, SubtargetFeatureInfo*>::const_iterator - I = Info.SubtargetFeatures.begin(), - E = Info.SubtargetFeatures.end(); I != E; ++I) { - SubtargetFeatureInfo &SFI = *I->second; - O << " " << SFI.getEnumName() << " = (1 << " << SFI.Index << "),\n"; - } - - O << " Feature_None = 0\n"; - O << "};\n\n"; - O << "} // end anonymous namespace\n\n"; -} - -/// EmitComputeAvailableFeatures - Emit the function to compute the list of -/// available features given a subtarget. -static void EmitComputeAvailableFeatures(AsmWriterInfo &Info, - Record *AsmWriter, - CodeGenTarget &Target, - raw_ostream &O) { - std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); - - O << "unsigned " << Target.getName() << ClassName << "::\n" - << "ComputeAvailableFeatures(const " << Target.getName() - << "Subtarget *Subtarget) const {\n"; - O << " unsigned Features = 0;\n"; - - for (std::map<const Record*, SubtargetFeatureInfo*>::const_iterator - I = Info.SubtargetFeatures.begin(), - E = Info.SubtargetFeatures.end(); I != E; ++I) { - SubtargetFeatureInfo &SFI = *I->second; - O << " if (" << SFI.TheDef->getValueAsString("CondString") - << ")\n"; - O << " Features |= " << SFI.getEnumName() << ";\n"; - } - - O << " return Features;\n"; - O << "}\n\n"; -} - static void EmitGetMapOperandNumber(raw_ostream &O) { O << "static unsigned getMapOperandNumber(" << "const SmallVectorImpl<std::pair<StringRef, unsigned> > &OpMap,\n"; @@ -805,16 +736,16 @@ void AsmWriterEmitter::EmitRegIsInRegClass(raw_ostream &O) { O << " case RC_" << Name << ":\n"; // Emit the register list now. - unsigned IE = RC.Elements.size(); + unsigned IE = RC.getOrder().size(); if (IE == 1) { - O << " if (Reg == " << getQualifiedName(RC.Elements[0]) << ")\n"; + O << " if (Reg == " << getQualifiedName(RC.getOrder()[0]) << ")\n"; O << " return true;\n"; } else { O << " switch (Reg) {\n"; O << " default: break;\n"; for (unsigned II = 0; II != IE; ++II) { - Record *Reg = RC.Elements[II]; + Record *Reg = RC.getOrder()[II]; O << " case " << getQualifiedName(Reg) << ":\n"; } @@ -830,10 +761,46 @@ void AsmWriterEmitter::EmitRegIsInRegClass(raw_ostream &O) { O << "}\n\n"; } +static unsigned CountNumOperands(StringRef AsmString) { + unsigned NumOps = 0; + std::pair<StringRef, StringRef> ASM = AsmString.split(' '); + + while (!ASM.second.empty()) { + ++NumOps; + ASM = ASM.second.split(' '); + } + + return NumOps; +} + +static unsigned CountResultNumOperands(StringRef AsmString) { + unsigned NumOps = 0; + std::pair<StringRef, StringRef> ASM = AsmString.split('\t'); + + if (!ASM.second.empty()) { + size_t I = ASM.second.find('{'); + StringRef Str = ASM.second; + if (I != StringRef::npos) + Str = ASM.second.substr(I, ASM.second.find('|', I)); + + ASM = Str.split(' '); + + do { + ++NumOps; + ASM = ASM.second.split(' '); + } while (!ASM.second.empty()); + } + + return NumOps; +} + void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { CodeGenTarget Target(Records); Record *AsmWriter = Target.getAsmWriter(); + if (!AsmWriter->getValueAsBit("isMCAsmWriter")) + return; + O << "\n#ifdef PRINT_ALIAS_INSTR\n"; O << "#undef PRINT_ALIAS_INSTR\n\n"; @@ -842,9 +809,6 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { // Emit the method that prints the alias instruction. std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); - bool isMC = AsmWriter->getValueAsBit("isMCAsmWriter"); - const char *MachineInstrClassName = isMC ? "MCInst" : "MachineInstr"; - std::vector<Record*> AllInstAliases = Records.getAllDerivedDefinitions("InstAlias"); @@ -864,7 +828,6 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { // A map of which conditions need to be met for each instruction operand // before it can be matched to the mnemonic. std::map<std::string, std::vector<IAPrinter*> > IAPrinterMap; - AsmWriterInfo AWI; for (std::map<std::string, std::vector<CodeGenInstAlias*> >::iterator I = AliasMap.begin(), E = AliasMap.end(); I != E; ++I) { @@ -873,12 +836,16 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { for (std::vector<CodeGenInstAlias*>::iterator II = Aliases.begin(), IE = Aliases.end(); II != IE; ++II) { const CodeGenInstAlias *CGA = *II; - IAPrinter *IAP = new IAPrinter(AWI, CGA->Result->getAsString(), - CGA->AsmString); + unsigned LastOpNo = CGA->ResultInstOperandIndex.size(); + unsigned NumResultOps = + CountResultNumOperands(CGA->ResultInst->AsmString); - IAP->addReqFeatures(CGA->TheDef->getValueAsListOfDefs("Predicates")); + // Don't emit the alias if it has more operands than what it's aliasing. + if (NumResultOps < CountNumOperands(CGA->AsmString)) + continue; - unsigned LastOpNo = CGA->ResultInstOperandIndex.size(); + IAPrinter *IAP = new IAPrinter(CGA->Result->getAsString(), + CGA->AsmString); std::string Cond; Cond = std::string("MI->getNumOperands() == ") + llvm::utostr(LastOpNo); @@ -896,6 +863,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); @@ -914,7 +884,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { } } else { assert(Rec->isSubClassOf("Operand") && "Unexpected operand!"); - // FIXME: We need to handle these situations. + // FIXME: We may need to handle these situations. delete IAP; IAP = 0; CantHandle = true; @@ -945,19 +915,15 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { } } - EmitSubtargetFeatureFlagEnumeration(AWI, O); - EmitComputeAvailableFeatures(AWI, AsmWriter, Target, O); - std::string Header; raw_string_ostream HeaderO(Header); HeaderO << "bool " << Target.getName() << ClassName - << "::printAliasInstr(const " << MachineInstrClassName + << "::printAliasInstr(const MCInst" << " *MI, raw_ostream &OS) {\n"; std::string Cases; raw_string_ostream CasesO(Cases); - bool NeedAvailableFeatures = false; for (std::map<std::string, std::vector<IAPrinter*> >::iterator I = IAPrinterMap.begin(), E = IAPrinterMap.end(); I != E; ++I) { @@ -988,14 +954,14 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { II = UniqueIAPs.begin(), IE = UniqueIAPs.end(); II != IE; ++II) { IAPrinter *IAP = *II; CasesO.indent(4); - NeedAvailableFeatures |= IAP->print(CasesO); + IAP->print(CasesO); CasesO << '\n'; } CasesO.indent(4) << "return false;\n"; } - if (CasesO.str().empty() || !isMC) { + if (CasesO.str().empty()) { O << HeaderO.str(); O << " return false;\n"; O << "}\n\n"; @@ -1008,8 +974,6 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { O << HeaderO.str(); O.indent(2) << "StringRef AsmString;\n"; O.indent(2) << "SmallVector<std::pair<StringRef, unsigned>, 4> OpMap;\n"; - if (NeedAvailableFeatures) - O.indent(2) << "unsigned AvailableFeatures = getAvailableFeatures();\n\n"; O.indent(2) << "switch (MI->getOpcode()) {\n"; O.indent(2) << "default: return false;\n"; O << CasesO.str(); |