diff options
Diffstat (limited to 'contrib/llvm/utils')
41 files changed, 1862 insertions, 1098 deletions
diff --git a/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp b/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp index 62bd1c6..8a5dc8b 100644 --- a/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp +++ b/contrib/llvm/utils/TableGen/ARMDecoderEmitter.cpp @@ -421,6 +421,9 @@ public: protected: // Populates the insn given the uid. void insnWithID(insn_t &Insn, unsigned Opcode) const { + if (AllInstructions[Opcode]->isPseudo) + return; + BitsInit &Bits = getBitsField(*AllInstructions[Opcode]->TheDef, "Inst"); for (unsigned i = 0; i < BIT_WIDTH; ++i) @@ -1592,10 +1595,6 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI, // The following special cases are for conflict resolutions. // - // RSCSri and RSCSrs set the 's' bit, but are not predicated. We are - // better off using the generic RSCri and RSCrs instructions. - if (Name == "RSCSri" || Name == "RSCSrs") return false; - // A8-598: VEXT // Vector Extract extracts elements from the bottom end of the second // operand vector and the top end of the first, concatenates them and @@ -1628,10 +1627,6 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI, if (Name == "tBX_RET" || Name == "tBX_RET_vararg") return false; - // Ignore the TPsoft (TLS) instructions, which conflict with tBLr9. - if (Name == "tTPsoft" || Name == "t2TPsoft") - return false; - // Ignore tADR, prefer tADDrPCi. if (Name == "tADR") return false; @@ -1644,12 +1639,8 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI, // Ignore tADDrSP, tADDspr, and tPICADD, prefer the generic tADDhirr. // Ignore t2SUBrSPs, prefer the t2SUB[S]r[r|s]. // Ignore t2ADDrSPs, prefer the t2ADD[S]r[r|s]. - // Ignore t2ADDrSPi/t2SUBrSPi, which have more generic couterparts. - // Ignore t2ADDrSPi12/t2SUBrSPi12, which have more generic couterparts if (Name == "tADDrSP" || Name == "tADDspr" || Name == "tPICADD" || - Name == "t2SUBrSPs" || Name == "t2ADDrSPs" || - Name == "t2ADDrSPi" || Name == "t2SUBrSPi" || - Name == "t2ADDrSPi12" || Name == "t2SUBrSPi12") + Name == "t2SUBrSPs" || Name == "t2ADDrSPs") return false; // FIXME: Use ldr.n to work around a Darwin assembler bug. @@ -1664,17 +1655,15 @@ ARMDEBackend::populateInstruction(const CodeGenInstruction &CGI, // Resolve conflicts: // // tBfar conflicts with tBLr9 - // tPOP_RET/t2LDMIA_RET conflict with tPOP/t2LDM (ditto) + // t2LDMIA_RET conflict with t2LDM (ditto) // tMOVCCi conflicts with tMOVi8 // tMOVCCr conflicts with tMOVgpr2gpr - // tSpill conflicts with tSTRspi // tLDRcp conflicts with tLDRspi - // tRestore conflicts with tLDRspi // t2MOVCCi16 conflicts with tMOVi16 if (Name == "tBfar" || - Name == "tPOP_RET" || Name == "t2LDMIA_RET" || + Name == "t2LDMIA_RET" || Name == "tMOVCCi" || Name == "tMOVCCr" || - Name == "tSpill" || Name == "tLDRcp" || Name == "tRestore" || + Name == "tLDRcp" || Name == "t2MOVCCi16") return false; } diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp index bbe4349..a6a4fec 100644 --- a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp +++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp @@ -98,6 +98,7 @@ #include "AsmMatcherEmitter.h" #include "CodeGenTarget.h" +#include "Error.h" #include "Record.h" #include "StringMatcher.h" #include "llvm/ADT/OwningPtr.h" @@ -870,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; @@ -886,7 +912,8 @@ AsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI, void AsmMatcherInfo:: BuildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { - const std::vector<CodeGenRegister> &Registers = Target.getRegisters(); + const std::vector<CodeGenRegister*> &Registers = + Target.getRegBank().getRegisters(); const std::vector<CodeGenRegisterClass> &RegClassList = Target.getRegisterClasses(); @@ -896,8 +923,8 @@ BuildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { // Gather the defined sets. for (std::vector<CodeGenRegisterClass>::const_iterator it = RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) - RegisterSets.insert(std::set<Record*>(it->Elements.begin(), - it->Elements.end())); + RegisterSets.insert(std::set<Record*>(it->getOrder().begin(), + it->getOrder().end())); // Add any required singleton sets. for (SmallPtrSet<Record*, 16>::iterator it = SingletonRegisters.begin(), @@ -910,9 +937,9 @@ BuildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { // a unique register set class), and build the mapping of registers to the set // they should classify to. std::map<Record*, std::set<Record*> > RegisterMap; - for (std::vector<CodeGenRegister>::const_iterator it = Registers.begin(), + for (std::vector<CodeGenRegister*>::const_iterator it = Registers.begin(), ie = Registers.end(); it != ie; ++it) { - const CodeGenRegister &CGR = *it; + const CodeGenRegister &CGR = **it; // Compute the intersection of all sets containing this register. std::set<Record*> ContainingSet; @@ -971,8 +998,8 @@ BuildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) { // Name the register classes which correspond to a user defined RegisterClass. for (std::vector<CodeGenRegisterClass>::const_iterator it = RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) { - ClassInfo *CI = RegisterSetClasses[std::set<Record*>(it->Elements.begin(), - it->Elements.end())]; + ClassInfo *CI = RegisterSetClasses[std::set<Record*>(it->getOrder().begin(), + it->getOrder().end())]; if (CI->ValueName.empty()) { CI->ClassName = it->getName(); CI->Name = "MCK_" + it->getName(); @@ -1126,7 +1153,7 @@ void AsmMatcherInfo::BuildInfo() { assert(FeatureNo < 32 && "Too many subtarget features!"); } - StringRef CommentDelimiter = AsmParser->getValueAsString("CommentDelimiter"); + std::string CommentDelimiter = AsmParser->getValueAsString("CommentDelimiter"); // Parse the instructions; we need to do this first so that we can gather the // singleton register classes. @@ -1629,6 +1656,10 @@ static void EmitValidateOperandClass(AsmMatcherInfo &Info, OS << " " << Info.Target.getName() << "Operand &Operand = *(" << Info.Target.getName() << "Operand*)GOp;\n"; + // The InvalidMatchClass is not to match any operand. + OS << " if (Kind == InvalidMatchClass)\n"; + OS << " return false;\n\n"; + // Check for Token operands first. OS << " if (Operand.isToken())\n"; OS << " return MatchTokenString(Operand.getToken()) == Kind;\n\n"; @@ -1745,14 +1776,16 @@ static void EmitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser, raw_ostream &OS) { // Construct the match list. std::vector<StringMatcher::StringPair> Matches; - for (unsigned i = 0, e = Target.getRegisters().size(); i != e; ++i) { - const CodeGenRegister &Reg = Target.getRegisters()[i]; - if (Reg.TheDef->getValueAsString("AsmName").empty()) + const std::vector<CodeGenRegister*> &Regs = + Target.getRegBank().getRegisters(); + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister *Reg = Regs[i]; + if (Reg->TheDef->getValueAsString("AsmName").empty()) continue; Matches.push_back(StringMatcher::StringPair( - Reg.TheDef->getValueAsString("AsmName"), - "return " + utostr(i + 1) + ";")); + Reg->TheDef->getValueAsString("AsmName"), + "return " + utostr(Reg->EnumValue) + ";")); } OS << "static unsigned MatchRegisterName(StringRef Name) {\n"; @@ -1788,15 +1821,44 @@ static void EmitComputeAvailableFeatures(AsmMatcherInfo &Info, Info.AsmParser->getValueAsString("AsmParserClassName"); OS << "unsigned " << Info.Target.getName() << ClassName << "::\n" - << "ComputeAvailableFeatures(const " << Info.Target.getName() - << "Subtarget *Subtarget) const {\n"; + << "ComputeAvailableFeatures(uint64_t FB) const {\n"; OS << " unsigned Features = 0;\n"; for (std::map<Record*, SubtargetFeatureInfo*>::const_iterator it = Info.SubtargetFeatures.begin(), ie = Info.SubtargetFeatures.end(); it != ie; ++it) { SubtargetFeatureInfo &SFI = *it->second; - OS << " if (" << SFI.TheDef->getValueAsString("CondString") - << ")\n"; + + OS << " if ("; + std::string CondStorage = SFI.TheDef->getValueAsString("AssemblerCondString"); + StringRef Conds = CondStorage; + std::pair<StringRef,StringRef> Comma = Conds.split(','); + bool First = true; + do { + if (!First) + OS << " && "; + + bool Neg = false; + StringRef Cond = Comma.first; + if (Cond[0] == '!') { + Neg = true; + Cond = Cond.substr(1); + } + + OS << "((FB & " << Info.Target.getName() << "::" << Cond << ")"; + if (Neg) + OS << " == 0"; + else + OS << " != 0"; + OS << ")"; + + if (Comma.second.empty()) + break; + + First = false; + Comma = Comma.second.split(','); + } while (true); + + OS << ")\n"; OS << " Features |= " << SFI.getEnumName() << ";\n"; } OS << " return Features;\n"; @@ -2111,8 +2173,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "#undef GET_ASSEMBLER_HEADER\n"; OS << " // This should be included into the middle of the declaration of\n"; OS << " // your subclasses implementation of TargetAsmParser.\n"; - OS << " unsigned ComputeAvailableFeatures(const " << - Target.getName() << "Subtarget *Subtarget) const;\n"; + OS << " unsigned ComputeAvailableFeatures(uint64_t FeatureBits) const;\n"; OS << " enum MatchResultTy {\n"; OS << " Match_ConversionFail,\n"; OS << " Match_InvalidOperand,\n"; 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(); diff --git a/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp b/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp index acaa1f8..0a48e75 100644 --- a/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp +++ b/contrib/llvm/utils/TableGen/ClangDiagnosticsEmitter.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/VectorExtras.h" #include <map> #include <algorithm> @@ -195,6 +196,15 @@ void ClangDiagsDefsEmitter::run(raw_ostream &OS) { // Warning Group Tables generation //===----------------------------------------------------------------------===// +static std::string getDiagCategoryEnum(llvm::StringRef name) { + if (name.empty()) + return "DiagCat_None"; + llvm::SmallString<256> enumName = llvm::StringRef("DiagCat_"); + for (llvm::StringRef::iterator I = name.begin(), E = name.end(); I != E; ++I) + enumName += isalnum(*I) ? *I : '_'; + return enumName.str(); +} + namespace { struct GroupInfo { std::vector<const Record*> DiagsInGroup; @@ -301,7 +311,7 @@ void ClangDiagGroupsEmitter::run(raw_ostream &OS) { OS << "\n#ifdef GET_CATEGORY_TABLE\n"; for (DiagCategoryIDMap::iterator I = CategoriesByID.begin(), E = CategoriesByID.end(); I != E; ++I) - OS << "CATEGORY(\"" << *I << "\")\n"; + OS << "CATEGORY(\"" << *I << "\", " << getDiagCategoryEnum(*I) << ")\n"; OS << "#endif // GET_CATEGORY_TABLE\n\n"; } diff --git a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp index 9d4dc5c4..d828dfc 100644 --- a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp +++ b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp @@ -34,7 +34,8 @@ void CodeEmitterGen::reverseBits(std::vector<Record*> &Insts) { for (std::vector<Record*>::iterator I = Insts.begin(), E = Insts.end(); I != E; ++I) { Record *R = *I; - if (R->getValueAsString("Namespace") == "TargetOpcode") + if (R->getValueAsString("Namespace") == "TargetOpcode" || + R->getValueAsBit("isPseudo")) continue; BitsInit *BI = R->getValueAsBitsInit("Inst"); @@ -231,7 +232,8 @@ void CodeEmitterGen::run(raw_ostream &o) { const CodeGenInstruction *CGI = *IN; Record *R = CGI->TheDef; - if (R->getValueAsString("Namespace") == "TargetOpcode") { + if (R->getValueAsString("Namespace") == "TargetOpcode" || + R->getValueAsBit("isPseudo")) { o << " 0U,\n"; continue; } @@ -255,7 +257,8 @@ void CodeEmitterGen::run(raw_ostream &o) { for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end(); IC != EC; ++IC) { Record *R = *IC; - if (R->getValueAsString("Namespace") == "TargetOpcode") + if (R->getValueAsString("Namespace") == "TargetOpcode" || + R->getValueAsBit("isPseudo")) continue; const std::string &InstName = R->getValueAsString("Namespace") + "::" + R->getName(); diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp index a08cde6..072893f 100644 --- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "CodeGenDAGPatterns.h" +#include "Error.h" #include "Record.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" @@ -1241,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!"); @@ -1523,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 { @@ -1581,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); @@ -1723,7 +1744,7 @@ TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){ Record *R = DI->getDef(); // Direct reference to a leaf DagNode or PatFrag? Turn it into a - // TreePatternNode if its own. For example: + // TreePatternNode of its own. For example: /// (foo GPR, imm) -> (foo GPR, (imm)) if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag")) return ParseTreePattern(new DagInit(DI, "", @@ -1927,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; } @@ -2210,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; @@ -2317,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/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h index e4e8574..936fd01 100644 --- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h +++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h @@ -26,7 +26,7 @@ namespace llvm { class Record; - struct Init; + class Init; class ListInit; class DagInit; class SDNodeInfo; diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp index 5b0aedf..a52ce86 100644 --- a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp @@ -13,6 +13,7 @@ #include "CodeGenInstruction.h" #include "CodeGenTarget.h" +#include "Error.h" #include "Record.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" @@ -66,10 +67,14 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { Record *Rec = Arg->getDef(); std::string PrintMethod = "printOperand"; std::string EncoderMethod; + std::string OperandType = "OPERAND_UNKNOWN"; 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"); + OperandType = Rec->getValueAsString("OperandType"); // If there is an explicit encoder method, use it. EncoderMethod = Rec->getValueAsString("EncoderMethod"); MIOpInfo = Rec->getValueAsDag("MIOperandInfo"); @@ -93,8 +98,9 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { } else if (Rec->getName() == "variable_ops") { isVariadic = true; continue; - } else if (!Rec->isSubClassOf("RegisterClass") && - !Rec->isSubClassOf("PointerLikeRegClass") && + } else if (Rec->isSubClassOf("RegisterClass")) { + OperandType = "OPERAND_REGISTER"; + } else if (!Rec->isSubClassOf("PointerLikeRegClass") && Rec->getName() != "unknown") throw "Unknown operand class '" + Rec->getName() + "' in '" + R->getName() + "' instruction!"; @@ -108,7 +114,8 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { " has the same name as a previous operand!"; OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, EncoderMethod, - MIOperandNo, NumOps, MIOpInfo)); + OperandType, MIOperandNo, NumOps, + MIOpInfo)); MIOperandNo += NumOps; } @@ -308,6 +315,8 @@ CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R), Operands(R) { isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove"); hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq"); hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq"); + isCodeGenOnly = R->getValueAsBit("isCodeGenOnly"); + isPseudo = R->getValueAsBit("isPseudo"); ImplicitDefs = R->getValueAsListOfDefs("Defs"); ImplicitUses = R->getValueAsListOfDefs("Uses"); @@ -414,10 +423,14 @@ 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; - if (!T.getRegisterClass(InstOpRec).containsRegister(ADI->getDef())) + if (!T.getRegisterClass(InstOpRec) + .contains(T.getRegBank().getReg(ADI->getDef()))) throw TGError(Loc, "fixed register " +ADI->getDef()->getName() + " is not a member of the " + InstOpRec->getName() + " register class!"); diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.h b/contrib/llvm/utils/TableGen/CodeGenInstruction.h index 5f1e0be..8d7669a 100644 --- a/contrib/llvm/utils/TableGen/CodeGenInstruction.h +++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.h @@ -78,6 +78,10 @@ namespace llvm { /// for binary encoding. "getMachineOpValue" by default. std::string EncoderMethodName; + /// OperandType - A value from MCOI::OperandType representing the type of + /// the operand. + std::string OperandType; + /// MIOperandNo - Currently (this is meant to be phased out), some logical /// operands correspond to multiple MachineInstr operands. In the X86 /// target for example, one address operand is represented as 4 @@ -101,10 +105,11 @@ namespace llvm { std::vector<ConstraintInfo> Constraints; OperandInfo(Record *R, const std::string &N, const std::string &PMN, - const std::string &EMN, unsigned MION, unsigned MINO, - DagInit *MIOI) + const std::string &EMN, const std::string &OT, unsigned MION, + unsigned MINO, DagInit *MIOI) : Rec(R), Name(N), PrinterMethodName(PMN), EncoderMethodName(EMN), - MIOperandNo(MION), MINumOperands(MINO), MIOperandInfo(MIOI) {} + OperandType(OT), MIOperandNo(MION), MINumOperands(MINO), + MIOperandInfo(MIOI) {} /// getTiedOperand - If this operand is tied to another one, return the @@ -235,6 +240,8 @@ namespace llvm { bool isAsCheapAsAMove; bool hasExtraSrcRegAllocReq; bool hasExtraDefRegAllocReq; + bool isCodeGenOnly; + bool isPseudo; CodeGenInstruction(Record *R); diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp index a4504e4..1acf3a8 100644 --- a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp @@ -14,6 +14,7 @@ #include "CodeGenRegisters.h" #include "CodeGenTarget.h" +#include "Error.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" @@ -72,10 +73,21 @@ CodeGenRegister::getSubRegs(CodeGenRegBank &RegBank) { for (unsigned i = 0, e = SubList.size(); i != e; ++i) { CodeGenRegister *SR = RegBank.getReg(SubList[i]); const SubRegMap &Map = SR->getSubRegs(RegBank); + + // Add this as a super-register of SR now all sub-registers are in the list. + // This creates a topological ordering, the exact order depends on the + // order getSubRegs is called on all registers. + SR->SuperRegs.push_back(this); + for (SubRegMap::const_iterator SI = Map.begin(), SE = Map.end(); SI != SE; - ++SI) + ++SI) { if (!SubRegs.insert(*SI).second) Orphans.push_back(Orphan(SI->second, Indices[i], SI->first)); + + // Noop sub-register indexes are possible, so avoid duplicates. + if (SI->second != SR) + SI->second->SuperRegs.push_back(this); + } } // Process the composites. @@ -128,11 +140,122 @@ CodeGenRegister::getSubRegs(CodeGenRegBank &RegBank) { return SubRegs; } +void +CodeGenRegister::addSubRegsPreOrder(SetVector<CodeGenRegister*> &OSet) const { + assert(SubRegsComplete && "Must precompute sub-registers"); + std::vector<Record*> Indices = TheDef->getValueAsListOfDefs("SubRegIndices"); + for (unsigned i = 0, e = Indices.size(); i != e; ++i) { + CodeGenRegister *SR = SubRegs.find(Indices[i])->second; + if (OSet.insert(SR)) + SR->addSubRegsPreOrder(OSet); + } +} + +//===----------------------------------------------------------------------===// +// RegisterTuples +//===----------------------------------------------------------------------===// + +// A RegisterTuples def is used to generate pseudo-registers from lists of +// sub-registers. We provide a SetTheory expander class that returns the new +// registers. +namespace { +struct TupleExpander : SetTheory::Expander { + void expand(SetTheory &ST, Record *Def, SetTheory::RecSet &Elts) { + std::vector<Record*> Indices = Def->getValueAsListOfDefs("SubRegIndices"); + unsigned Dim = Indices.size(); + ListInit *SubRegs = Def->getValueAsListInit("SubRegs"); + if (Dim != SubRegs->getSize()) + throw TGError(Def->getLoc(), "SubRegIndices and SubRegs size mismatch"); + if (Dim < 2) + throw TGError(Def->getLoc(), "Tuples must have at least 2 sub-registers"); + + // Evaluate the sub-register lists to be zipped. + unsigned Length = ~0u; + SmallVector<SetTheory::RecSet, 4> Lists(Dim); + for (unsigned i = 0; i != Dim; ++i) { + ST.evaluate(SubRegs->getElement(i), Lists[i]); + Length = std::min(Length, unsigned(Lists[i].size())); + } + + if (Length == 0) + return; + + // Precompute some types. + Record *RegisterCl = Def->getRecords().getClass("Register"); + RecTy *RegisterRecTy = new RecordRecTy(RegisterCl); + StringInit *BlankName = new StringInit(""); + + // Zip them up. + for (unsigned n = 0; n != Length; ++n) { + std::string Name; + Record *Proto = Lists[0][n]; + std::vector<Init*> Tuple; + unsigned CostPerUse = 0; + for (unsigned i = 0; i != Dim; ++i) { + Record *Reg = Lists[i][n]; + if (i) Name += '_'; + Name += Reg->getName(); + Tuple.push_back(new DefInit(Reg)); + CostPerUse = std::max(CostPerUse, + unsigned(Reg->getValueAsInt("CostPerUse"))); + } + + // Create a new Record representing the synthesized register. This record + // is only for consumption by CodeGenRegister, it is not added to the + // RecordKeeper. + Record *NewReg = new Record(Name, Def->getLoc(), Def->getRecords()); + Elts.insert(NewReg); + + // Copy Proto super-classes. + for (unsigned i = 0, e = Proto->getSuperClasses().size(); i != e; ++i) + NewReg->addSuperClass(Proto->getSuperClasses()[i]); + + // Copy Proto fields. + for (unsigned i = 0, e = Proto->getValues().size(); i != e; ++i) { + RecordVal RV = Proto->getValues()[i]; + + // Replace the sub-register list with Tuple. + if (RV.getName() == "SubRegs") + RV.setValue(new ListInit(Tuple, RegisterRecTy)); + + // Provide a blank AsmName. MC hacks are required anyway. + if (RV.getName() == "AsmName") + RV.setValue(BlankName); + + // CostPerUse is aggregated from all Tuple members. + if (RV.getName() == "CostPerUse") + RV.setValue(new IntInit(CostPerUse)); + + // Copy fields from the RegisterTuples def. + if (RV.getName() == "SubRegIndices" || + RV.getName() == "CompositeIndices") { + NewReg->addValue(*Def->getValue(RV.getName())); + continue; + } + + // Some fields get their default uninitialized value. + if (RV.getName() == "DwarfNumbers" || + RV.getName() == "DwarfAlias" || + RV.getName() == "Aliases") { + if (const RecordVal *DefRV = RegisterCl->getValue(RV.getName())) + NewReg->addValue(*DefRV); + continue; + } + + // Everything else is copied from Proto. + NewReg->addValue(RV); + } + } + } +}; +} + //===----------------------------------------------------------------------===// // CodeGenRegisterClass //===----------------------------------------------------------------------===// -CodeGenRegisterClass::CodeGenRegisterClass(Record *R) : TheDef(R) { +CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) + : TheDef(R) { // Rename anonymous register classes. if (R->getName().size() > 9 && R->getName()[9] == '.') { static unsigned AnonCounter = 0; @@ -149,13 +272,26 @@ CodeGenRegisterClass::CodeGenRegisterClass(Record *R) : TheDef(R) { } assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!"); - std::vector<Record*> RegList = R->getValueAsListOfDefs("MemberList"); - for (unsigned i = 0, e = RegList.size(); i != e; ++i) { - Record *Reg = RegList[i]; - if (!Reg->isSubClassOf("Register")) - throw "Register Class member '" + Reg->getName() + - "' does not derive from the Register class!"; - Elements.push_back(Reg); + // Default allocation order always contains all registers. + Elements = RegBank.getSets().expand(R); + for (unsigned i = 0, e = Elements->size(); i != e; ++i) + Members.insert(RegBank.getReg((*Elements)[i])); + + // Alternative allocation orders may be subsets. + ListInit *Alts = R->getValueAsListInit("AltOrders"); + AltOrders.resize(Alts->size()); + SetTheory::RecSet Order; + for (unsigned i = 0, e = Alts->size(); i != e; ++i) { + RegBank.getSets().evaluate(Alts->getElement(i), Order); + AltOrders[i].append(Order.begin(), Order.end()); + // Verify that all altorder members are regclass members. + while (!Order.empty()) { + CodeGenRegister *Reg = RegBank.getReg(Order.back()); + Order.pop_back(); + if (!contains(Reg)) + throw TGError(R->getLoc(), " AltOrder register " + Reg->getName() + + " is not a class member"); + } } // SubRegClasses is a list<dag> containing (RC, subregindex, ...) dags. @@ -189,8 +325,28 @@ CodeGenRegisterClass::CodeGenRegisterClass(Record *R) : TheDef(R) { SpillAlignment = R->getValueAsInt("Alignment"); CopyCost = R->getValueAsInt("CopyCost"); Allocatable = R->getValueAsBit("isAllocatable"); - MethodBodies = R->getValueAsCode("MethodBodies"); - MethodProtos = R->getValueAsCode("MethodProtos"); + AltOrderSelect = R->getValueAsCode("AltOrderSelect"); +} + +bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const { + return Members.count(Reg); +} + +// Returns true if RC is a strict subclass. +// RC is a sub-class of this class if it is a valid replacement for any +// instruction operand where a register of this classis required. It must +// satisfy these conditions: +// +// 1. All RC registers are also in this. +// 2. The RC spill size must not be smaller than our spill size. +// 3. RC spill alignment must be compatible with ours. +// +bool CodeGenRegisterClass::hasSubClass(const CodeGenRegisterClass *RC) const { + return SpillAlignment && RC->SpillAlignment % SpillAlignment == 0 && + SpillSize <= RC->SpillSize && + std::includes(Members.begin(), Members.end(), + RC->Members.begin(), RC->Members.end(), + CodeGenRegister::Less()); } const std::string &CodeGenRegisterClass::getName() const { @@ -202,6 +358,10 @@ const std::string &CodeGenRegisterClass::getName() const { //===----------------------------------------------------------------------===// CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) : Records(Records) { + // Configure register Sets to understand register classes and tuples. + Sets.addFieldExpander("RegisterClass", "MemberList"); + Sets.addExpander("RegisterTuples", new TupleExpander()); + // Read in the user-defined (named) sub-register indices. // More indices will be synthesized later. SubRegIndices = Records.getAllDerivedDefinitions("SubRegIndex"); @@ -214,18 +374,45 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) : Records(Records) { Registers.reserve(Regs.size()); // Assign the enumeration values. for (unsigned i = 0, e = Regs.size(); i != e; ++i) - Registers.push_back(CodeGenRegister(Regs[i], i + 1)); + getReg(Regs[i]); + + // Expand tuples and number the new registers. + std::vector<Record*> Tups = + Records.getAllDerivedDefinitions("RegisterTuples"); + for (unsigned i = 0, e = Tups.size(); i != e; ++i) { + const std::vector<Record*> *TupRegs = Sets.expand(Tups[i]); + for (unsigned j = 0, je = TupRegs->size(); j != je; ++j) + getReg((*TupRegs)[j]); + } + + // Read in register class definitions. + std::vector<Record*> RCs = Records.getAllDerivedDefinitions("RegisterClass"); + if (RCs.empty()) + throw std::string("No 'RegisterClass' subclasses defined!"); + + RegClasses.reserve(RCs.size()); + for (unsigned i = 0, e = RCs.size(); i != e; ++i) + RegClasses.push_back(CodeGenRegisterClass(*this, RCs[i])); } CodeGenRegister *CodeGenRegBank::getReg(Record *Def) { - if (Def2Reg.empty()) - for (unsigned i = 0, e = Registers.size(); i != e; ++i) - Def2Reg[Registers[i].TheDef] = &Registers[i]; - - if (CodeGenRegister *Reg = Def2Reg[Def]) + CodeGenRegister *&Reg = Def2Reg[Def]; + if (Reg) return Reg; + Reg = new CodeGenRegister(Def, Registers.size() + 1); + Registers.push_back(Reg); + return Reg; +} - throw TGError(Def->getLoc(), "Not a known Register!"); +CodeGenRegisterClass *CodeGenRegBank::getRegClass(Record *Def) { + if (Def2RC.empty()) + for (unsigned i = 0, e = RegClasses.size(); i != e; ++i) + Def2RC[RegClasses[i].TheDef] = &RegClasses[i]; + + if (CodeGenRegisterClass *RC = Def2RC[Def]) + return RC; + + throw TGError(Def->getLoc(), "Not a known RegisterClass!"); } Record *CodeGenRegBank::getCompositeSubRegIndex(Record *A, Record *B, @@ -254,11 +441,11 @@ void CodeGenRegBank::computeComposites() { // Precompute all sub-register maps. This will create Composite entries for // all inferred sub-register indices. for (unsigned i = 0, e = Registers.size(); i != e; ++i) - Registers[i].getSubRegs(*this); + Registers[i]->getSubRegs(*this); for (unsigned i = 0, e = Registers.size(); i != e; ++i) { - CodeGenRegister *Reg1 = &Registers[i]; - const CodeGenRegister::SubRegMap &SRM1 = Reg1->getSubRegs(*this); + CodeGenRegister *Reg1 = Registers[i]; + const CodeGenRegister::SubRegMap &SRM1 = Reg1->getSubRegs(); for (CodeGenRegister::SubRegMap::const_iterator i1 = SRM1.begin(), e1 = SRM1.end(); i1 != e1; ++i1) { Record *Idx1 = i1->first; @@ -266,7 +453,7 @@ void CodeGenRegBank::computeComposites() { // Ignore identity compositions. if (Reg1 == Reg2) continue; - const CodeGenRegister::SubRegMap &SRM2 = Reg2->getSubRegs(*this); + const CodeGenRegister::SubRegMap &SRM2 = Reg2->getSubRegs(); // Try composing Idx1 with another SubRegIndex. for (CodeGenRegister::SubRegMap::const_iterator i2 = SRM2.begin(), e2 = SRM2.end(); i2 != e2; ++i2) { @@ -306,7 +493,127 @@ void CodeGenRegBank::computeComposites() { } } +// Compute sets of overlapping registers. +// +// The standard set is all super-registers and all sub-registers, but the +// target description can add arbitrary overlapping registers via the 'Aliases' +// field. This complicates things, but we can compute overlapping sets using +// the following rules: +// +// 1. The relation overlap(A, B) is reflexive and symmetric but not transitive. +// +// 2. overlap(A, B) implies overlap(A, S) for all S in supers(B). +// +// Alternatively: +// +// overlap(A, B) iff there exists: +// A' in { A, subregs(A) } and B' in { B, subregs(B) } such that: +// A' = B' or A' in aliases(B') or B' in aliases(A'). +// +// Here subregs(A) is the full flattened sub-register set returned by +// A.getSubRegs() while aliases(A) is simply the special 'Aliases' field in the +// description of register A. +// +// This also implies that registers with a common sub-register are considered +// overlapping. This can happen when forming register pairs: +// +// P0 = (R0, R1) +// P1 = (R1, R2) +// P2 = (R2, R3) +// +// In this case, we will infer an overlap between P0 and P1 because of the +// shared sub-register R1. There is no overlap between P0 and P2. +// +void CodeGenRegBank:: +computeOverlaps(std::map<const CodeGenRegister*, CodeGenRegister::Set> &Map) { + assert(Map.empty()); + + // Collect overlaps that don't follow from rule 2. + for (unsigned i = 0, e = Registers.size(); i != e; ++i) { + CodeGenRegister *Reg = Registers[i]; + CodeGenRegister::Set &Overlaps = Map[Reg]; + + // Reg overlaps itself. + Overlaps.insert(Reg); + + // All super-registers overlap. + const CodeGenRegister::SuperRegList &Supers = Reg->getSuperRegs(); + Overlaps.insert(Supers.begin(), Supers.end()); + + // Form symmetrical relations from the special Aliases[] lists. + std::vector<Record*> RegList = Reg->TheDef->getValueAsListOfDefs("Aliases"); + for (unsigned i2 = 0, e2 = RegList.size(); i2 != e2; ++i2) { + CodeGenRegister *Reg2 = getReg(RegList[i2]); + CodeGenRegister::Set &Overlaps2 = Map[Reg2]; + const CodeGenRegister::SuperRegList &Supers2 = Reg2->getSuperRegs(); + // Reg overlaps Reg2 which implies it overlaps supers(Reg2). + Overlaps.insert(Reg2); + Overlaps.insert(Supers2.begin(), Supers2.end()); + Overlaps2.insert(Reg); + Overlaps2.insert(Supers.begin(), Supers.end()); + } + } + + // Apply rule 2. and inherit all sub-register overlaps. + for (unsigned i = 0, e = Registers.size(); i != e; ++i) { + CodeGenRegister *Reg = Registers[i]; + CodeGenRegister::Set &Overlaps = Map[Reg]; + const CodeGenRegister::SubRegMap &SRM = Reg->getSubRegs(); + for (CodeGenRegister::SubRegMap::const_iterator i2 = SRM.begin(), + e2 = SRM.end(); i2 != e2; ++i2) { + CodeGenRegister::Set &Overlaps2 = Map[i2->second]; + Overlaps.insert(Overlaps2.begin(), Overlaps2.end()); + } + } +} + void CodeGenRegBank::computeDerivedInfo() { computeComposites(); } +/// getRegisterClassForRegister - Find the register class that contains the +/// specified physical register. If the register is not in a register class, +/// return null. If the register is in multiple classes, and the classes have a +/// superset-subset relationship and the same set of types, return the +/// superclass. Otherwise return null. +const CodeGenRegisterClass* +CodeGenRegBank::getRegClassForRegister(Record *R) { + const CodeGenRegister *Reg = getReg(R); + const std::vector<CodeGenRegisterClass> &RCs = getRegClasses(); + const CodeGenRegisterClass *FoundRC = 0; + for (unsigned i = 0, e = RCs.size(); i != e; ++i) { + const CodeGenRegisterClass &RC = RCs[i]; + if (!RC.contains(Reg)) + continue; + + // If this is the first class that contains the register, + // make a note of it and go on to the next class. + if (!FoundRC) { + FoundRC = &RC; + continue; + } + + // If a register's classes have different types, return null. + if (RC.getValueTypes() != FoundRC->getValueTypes()) + return 0; + + // Check to see if the previously found class that contains + // the register is a subclass of the current class. If so, + // prefer the superclass. + if (RC.hasSubClass(FoundRC)) { + FoundRC = &RC; + continue; + } + + // Check to see if the previously found class that contains + // the register is a superclass of the current class. If so, + // prefer the superclass. + if (FoundRC->hasSubClass(&RC)) + continue; + + // Multiple classes, and neither is a superclass of the other. + // Return null. + return 0; + } + return FoundRC; +} diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.h b/contrib/llvm/utils/TableGen/CodeGenRegisters.h index 09341f0..5edbf47 100644 --- a/contrib/llvm/utils/TableGen/CodeGenRegisters.h +++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.h @@ -16,8 +16,11 @@ #define CODEGEN_REGISTERS_H #include "Record.h" +#include "SetTheory.h" #include "llvm/CodeGen/ValueTypes.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SetVector.h" #include <cstdlib> #include <map> #include <string> @@ -49,16 +52,44 @@ namespace llvm { return SubRegs; } + // Add sub-registers to OSet following a pre-order defined by the .td file. + void addSubRegsPreOrder(SetVector<CodeGenRegister*> &OSet) const; + + // List of super-registers in topological order, small to large. + typedef std::vector<CodeGenRegister*> SuperRegList; + + // Get the list of super-registers. + // This is only valid after computeDerivedInfo has visited all registers. + const SuperRegList &getSuperRegs() const { + assert(SubRegsComplete && "Must precompute sub-registers"); + return SuperRegs; + } + + // Order CodeGenRegister pointers by EnumValue. + struct Less { + bool operator()(const CodeGenRegister *A, + const CodeGenRegister *B) const { + return A->EnumValue < B->EnumValue; + } + }; + + // Canonically ordered set. + typedef std::set<const CodeGenRegister*, Less> Set; + private: bool SubRegsComplete; SubRegMap SubRegs; + SuperRegList SuperRegs; }; - struct CodeGenRegisterClass { + class CodeGenRegisterClass { + CodeGenRegister::Set Members; + const std::vector<Record*> *Elements; + std::vector<SmallVector<Record*, 16> > AltOrders; + public: Record *TheDef; std::string Namespace; - std::vector<Record*> Elements; std::vector<MVT::SimpleValueType> VTs; unsigned SpillSize; unsigned SpillAlignment; @@ -66,7 +97,7 @@ namespace llvm { bool Allocatable; // Map SubRegIndex -> RegisterClass DenseMap<Record*,Record*> SubRegClasses; - std::string MethodProtos, MethodBodies; + std::string AltOrderSelect; const std::string &getName() const; const std::vector<MVT::SimpleValueType> &getValueTypes() const {return VTs;} @@ -79,13 +110,10 @@ namespace llvm { abort(); } - bool containsRegister(Record *R) const { - for (unsigned i = 0, e = Elements.size(); i != e; ++i) - if (Elements[i] == R) return true; - return false; - } + // Return true if this this class contains the register. + bool contains(const CodeGenRegister*) const; - // Returns true if RC is a strict subclass. + // Returns true if RC is a subclass. // RC is a sub-class of this class if it is a valid replacement for any // instruction operand where a register of this classis required. It must // satisfy these conditions: @@ -94,40 +122,38 @@ namespace llvm { // 2. The RC spill size must not be smaller than our spill size. // 3. RC spill alignment must be compatible with ours. // - bool hasSubClass(const CodeGenRegisterClass *RC) const { - - if (RC->Elements.size() > Elements.size() || - (SpillAlignment && RC->SpillAlignment % SpillAlignment) || - SpillSize > RC->SpillSize) - return false; - - std::set<Record*> RegSet; - for (unsigned i = 0, e = Elements.size(); i != e; ++i) { - Record *Reg = Elements[i]; - RegSet.insert(Reg); - } - - for (unsigned i = 0, e = RC->Elements.size(); i != e; ++i) { - Record *Reg = RC->Elements[i]; - if (!RegSet.count(Reg)) - return false; - } - - return true; + bool hasSubClass(const CodeGenRegisterClass *RC) const; + + // Returns an ordered list of class members. + // The order of registers is the same as in the .td file. + // No = 0 is the default allocation order, No = 1 is the first alternative. + ArrayRef<Record*> getOrder(unsigned No = 0) const { + if (No == 0) + return *Elements; + else + return AltOrders[No - 1]; } - CodeGenRegisterClass(Record *R); + // Return the total number of allocation orders available. + unsigned getNumOrders() const { return 1 + AltOrders.size(); } + + CodeGenRegisterClass(CodeGenRegBank&, Record *R); }; // CodeGenRegBank - Represent a target's registers and the relations between // them. class CodeGenRegBank { RecordKeeper &Records; + SetTheory Sets; + std::vector<Record*> SubRegIndices; unsigned NumNamedIndices; - std::vector<CodeGenRegister> Registers; + std::vector<CodeGenRegister*> Registers; DenseMap<Record*, CodeGenRegister*> Def2Reg; + std::vector<CodeGenRegisterClass> RegClasses; + DenseMap<Record*, CodeGenRegisterClass*> Def2RC; + // Composite SubRegIndex instances. // Map (SubRegIndex, SubRegIndex) -> SubRegIndex. typedef DenseMap<std::pair<Record*, Record*>, Record*> CompositeMap; @@ -139,6 +165,8 @@ namespace llvm { public: CodeGenRegBank(RecordKeeper&); + SetTheory &getSets() { return Sets; } + // Sub-register indices. The first NumNamedIndices are defined by the user // in the .td files. The rest are synthesized such that all sub-registers // have a unique name. @@ -151,13 +179,36 @@ namespace llvm { // Find or create a sub-register index representing the A+B composition. Record *getCompositeSubRegIndex(Record *A, Record *B, bool create = false); - const std::vector<CodeGenRegister> &getRegisters() { return Registers; } + const std::vector<CodeGenRegister*> &getRegisters() { return Registers; } // Find a register from its Record def. CodeGenRegister *getReg(Record*); + const std::vector<CodeGenRegisterClass> &getRegClasses() { + return RegClasses; + } + + // Find a register class from its def. + CodeGenRegisterClass *getRegClass(Record*); + + /// getRegisterClassForRegister - Find the register class that contains the + /// specified physical register. If the register is not in a register + /// class, return null. If the register is in multiple classes, and the + /// classes have a superset-subset relationship and the same set of types, + /// return the superclass. Otherwise return null. + const CodeGenRegisterClass* getRegClassForRegister(Record *R); + // Computed derived records such as missing sub-register indices. void computeDerivedInfo(); + + // Compute full overlap sets for every register. These sets include the + // rarely used aliases that are neither sub nor super-registers. + // + // Map[R1].count(R2) is reflexive and symmetric, but not transitive. + // + // If R1 is a sub-register of R2, Map[R1] is a subset of Map[R2]. + void computeOverlaps(std::map<const CodeGenRegister*, + CodeGenRegister::Set> &Map); }; } diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp index a0c64ff..929791c 100644 --- a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp @@ -90,6 +90,7 @@ std::string llvm::getEnumName(MVT::SimpleValueType T) { case MVT::Metadata: return "MVT::Metadata"; case MVT::iPTR: return "MVT::iPTR"; case MVT::iPTRAny: return "MVT::iPTRAny"; + case MVT::untyped: return "MVT::untyped"; default: assert(0 && "ILLEGAL VALUE TYPE!"); return ""; } } @@ -163,40 +164,32 @@ CodeGenRegBank &CodeGenTarget::getRegBank() const { return *RegBank; } -void CodeGenTarget::ReadRegisterClasses() const { - std::vector<Record*> RegClasses = - Records.getAllDerivedDefinitions("RegisterClass"); - if (RegClasses.empty()) - throw std::string("No 'RegisterClass' subclasses defined!"); - - RegisterClasses.reserve(RegClasses.size()); - RegisterClasses.assign(RegClasses.begin(), RegClasses.end()); +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 { - const std::vector<CodeGenRegister> &Regs = getRegBank().getRegisters(); - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister &Reg = Regs[i]; - if (Reg.TheDef->getValueAsString("AsmName") == Name) - return &Reg; - } + const std::vector<CodeGenRegister*> &Regs = getRegBank().getRegisters(); + for (unsigned i = 0, e = Regs.size(); i != e; ++i) + if (Regs[i]->TheDef->getValueAsString("AsmName") == Name) + return Regs[i]; return 0; } std::vector<MVT::SimpleValueType> CodeGenTarget:: getRegisterVTs(Record *R) const { + const CodeGenRegister *Reg = getRegBank().getReg(R); std::vector<MVT::SimpleValueType> Result; const std::vector<CodeGenRegisterClass> &RCs = getRegisterClasses(); for (unsigned i = 0, e = RCs.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = RegisterClasses[i]; - for (unsigned ei = 0, ee = RC.Elements.size(); ei != ee; ++ei) { - if (R == RC.Elements[ei]) { - const std::vector<MVT::SimpleValueType> &InVTs = RC.getValueTypes(); - Result.insert(Result.end(), InVTs.begin(), InVTs.end()); - } + const CodeGenRegisterClass &RC = RCs[i]; + if (RC.contains(Reg)) { + const std::vector<MVT::SimpleValueType> &InVTs = RC.getValueTypes(); + Result.insert(Result.end(), InVTs.begin(), InVTs.end()); } } diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.h b/contrib/llvm/utils/TableGen/CodeGenTarget.h index 1f1c34c..143daed 100644 --- a/contrib/llvm/utils/TableGen/CodeGenTarget.h +++ b/contrib/llvm/utils/TableGen/CodeGenTarget.h @@ -66,9 +66,9 @@ class CodeGenTarget { mutable DenseMap<const Record*, CodeGenInstruction*> Instructions; mutable CodeGenRegBank *RegBank; - mutable std::vector<CodeGenRegisterClass> RegisterClasses; + mutable std::vector<Record*> RegAltNameIndices; mutable std::vector<MVT::SimpleValueType> LegalValueTypes; - void ReadRegisterClasses() const; + void ReadRegAltNameIndices() const; void ReadInstructions() const; void ReadLegalValueTypes() const; @@ -98,80 +98,21 @@ public: /// getRegBank - Return the register bank description. CodeGenRegBank &getRegBank() const; - const std::vector<CodeGenRegister> &getRegisters() const { - return getRegBank().getRegisters(); - } - /// getRegisterByName - If there is a register with the specific AsmName, /// return it. const CodeGenRegister *getRegisterByName(StringRef Name) const; - const std::vector<CodeGenRegisterClass> &getRegisterClasses() const { - if (RegisterClasses.empty()) ReadRegisterClasses(); - return RegisterClasses; + const std::vector<Record*> &getRegAltNameIndices() const { + if (RegAltNameIndices.empty()) ReadRegAltNameIndices(); + return RegAltNameIndices; } - const CodeGenRegisterClass &getRegisterClass(Record *R) const { - const std::vector<CodeGenRegisterClass> &RC = getRegisterClasses(); - for (unsigned i = 0, e = RC.size(); i != e; ++i) - if (RC[i].TheDef == R) - return RC[i]; - assert(0 && "Didn't find the register class"); - abort(); + const std::vector<CodeGenRegisterClass> &getRegisterClasses() const { + return getRegBank().getRegClasses(); } - /// getRegisterClassForRegister - Find the register class that contains the - /// specified physical register. If the register is not in a register - /// class, return null. If the register is in multiple classes, and the - /// classes have a superset-subset relationship and the same set of - /// types, return the superclass. Otherwise return null. - const CodeGenRegisterClass *getRegisterClassForRegister(Record *R) const { - const std::vector<CodeGenRegisterClass> &RCs = getRegisterClasses(); - const CodeGenRegisterClass *FoundRC = 0; - for (unsigned i = 0, e = RCs.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = RegisterClasses[i]; - for (unsigned ei = 0, ee = RC.Elements.size(); ei != ee; ++ei) { - if (R != RC.Elements[ei]) - continue; - - // If a register's classes have different types, return null. - if (FoundRC && RC.getValueTypes() != FoundRC->getValueTypes()) - return 0; - - // If this is the first class that contains the register, - // make a note of it and go on to the next class. - if (!FoundRC) { - FoundRC = &RC; - break; - } - - std::vector<Record *> Elements(RC.Elements); - std::vector<Record *> FoundElements(FoundRC->Elements); - std::sort(Elements.begin(), Elements.end()); - std::sort(FoundElements.begin(), FoundElements.end()); - - // Check to see if the previously found class that contains - // the register is a subclass of the current class. If so, - // prefer the superclass. - if (std::includes(Elements.begin(), Elements.end(), - FoundElements.begin(), FoundElements.end())) { - FoundRC = &RC; - break; - } - - // Check to see if the previously found class that contains - // the register is a superclass of the current class. If so, - // prefer the superclass. - if (std::includes(FoundElements.begin(), FoundElements.end(), - Elements.begin(), Elements.end())) - break; - - // Multiple classes, and neither is a superclass of the other. - // Return null. - return 0; - } - } - return FoundRC; + const CodeGenRegisterClass &getRegisterClass(Record *R) const { + return *getRegBank().getRegClass(R); } /// getRegisterVTs - Find the union of all possible SimpleValueTypes for the diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp index 402a239..c5897c7 100644 --- a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp +++ b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp @@ -25,12 +25,12 @@ static MVT::SimpleValueType getRegisterValueType(Record *R, const CodeGenTarget &T) { bool FoundRC = false; MVT::SimpleValueType VT = MVT::Other; + const CodeGenRegister *Reg = T.getRegBank().getReg(R); const std::vector<CodeGenRegisterClass> &RCs = T.getRegisterClasses(); - std::vector<Record*>::const_iterator Element; for (unsigned rc = 0, e = RCs.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = RCs[rc]; - if (!std::count(RC.Elements.begin(), RC.Elements.end(), R)) + if (!RC.contains(Reg)) continue; if (!FoundRC) { @@ -93,10 +93,6 @@ namespace { /// CurPredicate - As we emit matcher nodes, this points to the latest check /// which should have future checks stuck into its Next position. Matcher *CurPredicate; - - /// RegisterDefMap - A map of register record definitions to the - /// corresponding target CodeGenRegister entry. - DenseMap<const Record *, const CodeGenRegister *> RegisterDefMap; public: MatcherGen(const PatternToMatch &pattern, const CodeGenDAGPatterns &cgp); @@ -165,12 +161,6 @@ MatcherGen::MatcherGen(const PatternToMatch &pattern, // If there are types that are manifestly known, infer them. InferPossibleTypes(); - - // Populate the map from records to CodeGenRegister entries. - const CodeGenTarget &CGT = CGP.getTargetInfo(); - const std::vector<CodeGenRegister> &Registers = CGT.getRegisters(); - for (unsigned i = 0, e = Registers.size(); i != e; ++i) - RegisterDefMap[Registers[i].TheDef] = &Registers[i]; } /// InferPossibleTypes - As we emit the pattern, we end up generating type @@ -234,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. @@ -589,14 +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")) { - AddMatcher(new EmitRegisterMatcher(RegisterDefMap[DI->getDef()], - N->getType(0))); + Record *Def = DI->getDef(); + if (Def->isSubClassOf("Register")) { + const CodeGenRegister *Reg = + 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; @@ -604,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/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp index d68d3b0..07313d1 100644 --- a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp +++ b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp @@ -9,6 +9,7 @@ #include "DisassemblerEmitter.h" #include "CodeGenTarget.h" +#include "Error.h" #include "Record.h" #include "X86DisassemblerTables.h" #include "X86RecognizableInstr.h" diff --git a/contrib/llvm/utils/TableGen/EDEmitter.cpp b/contrib/llvm/utils/TableGen/EDEmitter.cpp index daf9617..2f9814a 100644 --- a/contrib/llvm/utils/TableGen/EDEmitter.cpp +++ b/contrib/llvm/utils/TableGen/EDEmitter.cpp @@ -588,7 +588,11 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, IMM("imm0_31"); IMM("imm0_31_m1"); IMM("nModImm"); + IMM("imm0_7"); + IMM("imm0_15"); + IMM("imm0_255"); IMM("imm0_4095"); + IMM("imm0_65535"); IMM("jt2block_operand"); IMM("t_imm_s4"); IMM("pclabel"); @@ -652,12 +656,12 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, MISC("t2am_imm8s4_offset", "kOperandTypeThumb2AddrModeImm8s4Offset"); // R, I MISC("tb_addrmode", "kOperandTypeARMTBAddrMode"); // I - MISC("t_addrmode_rrs1", "kOperandTypeThumbAddrModeRegS"); // R, R - MISC("t_addrmode_rrs2", "kOperandTypeThumbAddrModeRegS"); // R, R - MISC("t_addrmode_rrs4", "kOperandTypeThumbAddrModeRegS"); // R, R - MISC("t_addrmode_is1", "kOperandTypeThumbAddrModeImmS"); // R, I - MISC("t_addrmode_is2", "kOperandTypeThumbAddrModeImmS"); // R, I - MISC("t_addrmode_is4", "kOperandTypeThumbAddrModeImmS"); // R, I + MISC("t_addrmode_rrs1", "kOperandTypeThumbAddrModeRegS1"); // R, R + MISC("t_addrmode_rrs2", "kOperandTypeThumbAddrModeRegS2"); // R, R + MISC("t_addrmode_rrs4", "kOperandTypeThumbAddrModeRegS4"); // R, R + MISC("t_addrmode_is1", "kOperandTypeThumbAddrModeImmS1"); // R, I + MISC("t_addrmode_is2", "kOperandTypeThumbAddrModeImmS2"); // R, I + MISC("t_addrmode_is4", "kOperandTypeThumbAddrModeImmS4"); // R, I MISC("t_addrmode_rr", "kOperandTypeThumbAddrModeRR"); // R, R MISC("t_addrmode_sp", "kOperandTypeThumbAddrModeSP"); // R, I MISC("t_addrmode_pc", "kOperandTypeThumbAddrModePC"); // R, I @@ -665,14 +669,9 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, return 1; } -#undef SOREG -#undef SOIMM -#undef PRED #undef REG #undef MEM -#undef LEA -#undef IMM -#undef PCR +#undef MISC #undef SET @@ -773,6 +772,11 @@ static void populateInstInfo(CompoundConstantEmitter &infoArray, for (index = 0; index < numInstructions; ++index) { const CodeGenInstruction& inst = *numberedInstructions[index]; + // We don't need to do anything for pseudo-instructions, as we'll never + // see them here. We'll only see real instructions. + if (inst.isPseudo) + continue; + CompoundConstantEmitter *infoStruct = new CompoundConstantEmitter; infoArray.addEntry(infoStruct); @@ -868,8 +872,12 @@ static void emitCommonEnums(raw_ostream &o, unsigned int &i) { operandTypes.addEntry("kOperandTypeARMSPRRegisterList"); operandTypes.addEntry("kOperandTypeARMTBAddrMode"); operandTypes.addEntry("kOperandTypeThumbITMask"); - operandTypes.addEntry("kOperandTypeThumbAddrModeRegS"); - operandTypes.addEntry("kOperandTypeThumbAddrModeImmS"); + operandTypes.addEntry("kOperandTypeThumbAddrModeImmS1"); + operandTypes.addEntry("kOperandTypeThumbAddrModeImmS2"); + operandTypes.addEntry("kOperandTypeThumbAddrModeImmS4"); + operandTypes.addEntry("kOperandTypeThumbAddrModeRegS1"); + operandTypes.addEntry("kOperandTypeThumbAddrModeRegS2"); + operandTypes.addEntry("kOperandTypeThumbAddrModeRegS4"); operandTypes.addEntry("kOperandTypeThumbAddrModeRR"); operandTypes.addEntry("kOperandTypeThumbAddrModeSP"); operandTypes.addEntry("kOperandTypeThumbAddrModePC"); diff --git a/contrib/llvm/utils/TableGen/Error.cpp b/contrib/llvm/utils/TableGen/Error.cpp new file mode 100644 index 0000000..3f6cda8 --- /dev/null +++ b/contrib/llvm/utils/TableGen/Error.cpp @@ -0,0 +1,39 @@ +//===- Error.cpp - tblgen error handling helper routines --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains error handling helper routines to pretty-print diagnostic +// messages from tblgen. +// +//===----------------------------------------------------------------------===// + +#include "Error.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +SourceMgr SrcMgr; + +void PrintError(SMLoc ErrorLoc, const Twine &Msg) { + SrcMgr.PrintMessage(ErrorLoc, Msg, "error"); +} + +void PrintError(const char *Loc, const Twine &Msg) { + SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), Msg, "error"); +} + +void PrintError(const Twine &Msg) { + errs() << "error:" << Msg << "\n"; +} + +void PrintError(const TGError &Error) { + PrintError(Error.getLoc(), Error.getMessage()); +} + +} // end namespace llvm diff --git a/contrib/llvm/utils/TableGen/Error.h b/contrib/llvm/utils/TableGen/Error.h new file mode 100644 index 0000000..b3a0146 --- /dev/null +++ b/contrib/llvm/utils/TableGen/Error.h @@ -0,0 +1,43 @@ +//===- Error.h - tblgen error handling helper routines ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains error handling helper routines to pretty-print diagnostic +// messages from tblgen. +// +//===----------------------------------------------------------------------===// + +#ifndef ERROR_H +#define ERROR_H + +#include "llvm/Support/SourceMgr.h" + +namespace llvm { + +class TGError { + SMLoc Loc; + std::string Message; +public: + TGError(SMLoc loc, const std::string &message) : Loc(loc), Message(message) {} + + SMLoc getLoc() const { return Loc; } + const std::string &getMessage() const { return Message; } +}; + +void PrintError(SMLoc ErrorLoc, const Twine &Msg); +void PrintError(const char *Loc, const Twine &Msg); +void PrintError(const Twine &Msg); +void PrintError(const TGError &Error); + + +extern SourceMgr SrcMgr; + + +} // end namespace "llvm" + +#endif diff --git a/contrib/llvm/utils/TableGen/FastISelEmitter.cpp b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp index 78ac556..f54e8df 100644 --- a/contrib/llvm/utils/TableGen/FastISelEmitter.cpp +++ b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp @@ -18,6 +18,7 @@ //===----------------------------------------------------------------------===// #include "FastISelEmitter.h" +#include "Error.h" #include "Record.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/VectorExtras.h" @@ -247,10 +248,12 @@ 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")) - RC = Target.getRegisterClassForRegister(OpLeafRec); + RC = Target.getRegBank().getRegClassForRegister(OpLeafRec); else return false; @@ -406,15 +409,7 @@ static std::string PhyRegForNode(TreePatternNode *Op, PhysReg += static_cast<StringInit*>(OpLeafRec->getValue( \ "Namespace")->getValue())->getValue(); PhysReg += "::"; - - std::vector<CodeGenRegister> Regs = Target.getRegisters(); - for (unsigned i = 0; i < Regs.size(); ++i) { - if (Regs[i].TheDef == OpLeafRec) { - PhysReg += Regs[i].getName(); - break; - } - } - + PhysReg += Target.getRegBank().getReg(OpLeafRec)->getName(); return PhysReg; } @@ -461,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/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp index 9312fe8..c9dcb01 100644 --- a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -1225,14 +1225,14 @@ bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI, // // This also removes pseudo instructions from considerations of disassembly, // which is a better design and less fragile than the name matchings. - BitsInit &Bits = getBitsField(Def, "Inst"); - if (Bits.allInComplete()) return false; - // Ignore "asm parser only" instructions. if (Def.getValueAsBit("isAsmParserOnly") || Def.getValueAsBit("isCodeGenOnly")) return false; + BitsInit &Bits = getBitsField(Def, "Inst"); + if (Bits.allInComplete()) return false; + std::vector<OperandInfo> InsnOperands; // If the instruction has specified a custom decoding hook, use that instead @@ -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; } @@ -1352,7 +1354,8 @@ bool FixedLenDecoderEmitter::populateInstruction(const CodeGenInstruction &CGI, void FixedLenDecoderEmitter::populateInstructions() { for (unsigned i = 0, e = NumberedInstructions.size(); i < e; ++i) { Record *R = NumberedInstructions[i]->TheDef; - if (R->getValueAsString("Namespace") == "TargetOpcode") + if (R->getValueAsString("Namespace") == "TargetOpcode" || + R->getValueAsBit("isPseudo")) continue; if (populateInstruction(*NumberedInstructions[i], i)) diff --git a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp index 67cce0e..5ebaf17 100644 --- a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp +++ b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp @@ -27,14 +27,6 @@ static void PrintDefList(const std::vector<Record*> &Uses, OS << "0 };\n"; } -static void PrintBarriers(std::vector<Record*> &Barriers, - unsigned Num, raw_ostream &OS) { - OS << "static const TargetRegisterClass* Barriers" << Num << "[] = { "; - for (unsigned i = 0, e = Barriers.size(); i != e; ++i) - OS << "&" << getQualifiedName(Barriers[i]) << "RegClass, "; - OS << "NULL };\n"; -} - //===----------------------------------------------------------------------===// // Instruction Itinerary Information. //===----------------------------------------------------------------------===// @@ -43,10 +35,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 +51,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 +62,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 +78,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,39 +88,44 @@ 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)"; + Res += "|(1<<MCOI::LookupPtrRegClass)"; // Predicate operands. Check to see if the original unexpanded operand // was of type PredicateOperand. if (Inst.Operands[i].Rec->isSubClassOf("PredicateOperand")) - Res += "|(1<<TOI::Predicate)"; - + Res += "|(1<<MCOI::Predicate)"; + // Optional def operands. Check to see if the original unexpanded operand // was of type OptionalDefOperand. if (Inst.Operands[i].Rec->isSubClassOf("OptionalDefOperand")) - Res += "|(1<<TOI::OptionalDef)"; + Res += "|(1<<MCOI::OptionalDef)"; // Fill in constraint info. Res += ", "; - + const CGIOperandList::ConstraintInfo &Constraint = Inst.Operands[i].Constraints[j]; if (Constraint.isNone()) Res += "0"; else if (Constraint.isEarlyClobber()) - Res += "(1 << TOI::EARLY_CLOBBER)"; + Res += "(1 << MCOI::EARLY_CLOBBER)"; else { assert(Constraint.isTied()); Res += "((" + utostr(Constraint.getTiedOperand()) + - " << 16) | (1 << TOI::TIED_TO))"; + " << 16) | (1 << MCOI::TIED_TO))"; } - + + // Fill in operand type. + Res += ", MCOI::"; + assert(!Inst.Operands[i].OperandType.empty() && "Invalid operand type."); + Res += Inst.Operands[i].OperandType; + Result.push_back(Res); } } @@ -134,12 +133,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,65 +146,40 @@ 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 << "[] = { "; + OS << "static const MCOperandInfo OperandInfo" << N << "[] = { "; for (unsigned i = 0, e = OperandInfo.size(); i != e; ++i) OS << "{ " << OperandInfo[i] << " }, "; OS << "};\n"; } } -void InstrInfoEmitter::DetectRegisterClassBarriers(std::vector<Record*> &Defs, - const std::vector<CodeGenRegisterClass> &RCs, - std::vector<Record*> &Barriers) { - std::set<Record*> DefSet; - unsigned NumDefs = Defs.size(); - for (unsigned i = 0; i < NumDefs; ++i) - DefSet.insert(Defs[i]); - - for (unsigned i = 0, e = RCs.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = RCs[i]; - unsigned NumRegs = RC.Elements.size(); - if (NumRegs > NumDefs) - continue; // Can't possibly clobber this RC. - - bool Clobber = true; - for (unsigned j = 0; j < NumRegs; ++j) { - Record *Reg = RC.Elements[j]; - if (!DefSet.count(Reg)) { - Clobber = false; - break; - } - } - if (Clobber) - Barriers.push_back(RC.TheDef); - } -} - //===----------------------------------------------------------------------===// // Main Output. //===----------------------------------------------------------------------===// // run - Emit the main instruction description records for the target... void InstrInfoEmitter::run(raw_ostream &OS) { + emitEnums(OS); + GatherItinClasses(); EmitSourceFileHeader("Target Instruction Descriptors", OS); + + OS << "\n#ifdef GET_INSTRINFO_MC_DESC\n"; + OS << "#undef GET_INSTRINFO_MC_DESC\n"; + OS << "namespace llvm {\n\n"; CodeGenTarget &Target = CDP.getTargetInfo(); const std::string &TargetName = Target.getName(); Record *InstrInfo = Target.getInstructionSet(); - const std::vector<CodeGenRegisterClass> &RCs = Target.getRegisterClasses(); // Keep track of all of the def lists we have emitted already. std::map<std::vector<Record*>, unsigned> EmittedLists; unsigned ListNumber = 0; - 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) { @@ -217,42 +191,67 @@ void InstrInfoEmitter::run(raw_ostream &OS) { } std::vector<Record*> Defs = Inst->getValueAsListOfDefs("Defs"); if (!Defs.empty()) { - std::vector<Record*> RCBarriers; - DetectRegisterClassBarriers(Defs, RCs, RCBarriers); - if (!RCBarriers.empty()) { - unsigned &IB = EmittedBarriers[RCBarriers]; - if (!IB) PrintBarriers(RCBarriers, IB = ++BarrierNumber, OS); - BarriersMap.insert(std::make_pair(Inst, IB)); - } - unsigned &IL = EmittedLists[Defs]; if (!IL) PrintDefList(Defs, IL = ++ListNumber, OS); } } OperandInfoMapTy OperandInfoIDs; - + // Emit all of the operand info records. EmitOperandInfo(OS, OperandInfoIDs); - - // Emit all of the TargetInstrDesc records in their ENUM ordering. + + // Emit all of the MCInstrDesc records in their ENUM ordering. // - OS << "\nstatic const TargetInstrDesc " << TargetName - << "Insts[] = {\n"; + OS << "\nMCInstrDesc " << TargetName << "Insts[] = {\n"; const std::vector<const CodeGenInstruction*> &NumberedInstructions = Target.getInstructionsByEnumValue(); for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) emitRecord(*NumberedInstructions[i], i, InstrInfo, EmittedLists, - BarriersMap, OperandInfoIDs, OS); - OS << "};\n"; + OperandInfoIDs, OS); + OS << "};\n\n"; + + // MCInstrInfo initialization routine. + OS << "static inline void Init" << TargetName + << "MCInstrInfo(MCInstrInfo *II) {\n"; + OS << " II->InitMCInstrInfo(" << TargetName << "Insts, " + << NumberedInstructions.size() << ");\n}\n\n"; + + OS << "} // End llvm namespace \n"; + + OS << "#endif // GET_INSTRINFO_MC_DESC\n\n"; + + // Create a TargetInstrInfo subclass to hide the MC layer initialization. + OS << "\n#ifdef GET_INSTRINFO_HEADER\n"; + OS << "#undef GET_INSTRINFO_HEADER\n"; + + std::string ClassName = TargetName + "GenInstrInfo"; + OS << "namespace llvm {\n"; + OS << "struct " << ClassName << " : public TargetInstrInfoImpl {\n" + << " explicit " << ClassName << "(int SO = -1, int DO = -1);\n" + << "};\n"; + OS << "} // End llvm namespace \n"; + + OS << "#endif // GET_INSTRINFO_HEADER\n\n"; + + OS << "\n#ifdef GET_INSTRINFO_CTOR\n"; + OS << "#undef GET_INSTRINFO_CTOR\n"; + + OS << "namespace llvm {\n"; + OS << "extern MCInstrDesc " << TargetName << "Insts[];\n"; + OS << ClassName << "::" << ClassName << "(int SO, int DO)\n" + << " : TargetInstrInfoImpl(SO, DO) {\n" + << " InitMCInstrInfo(" << TargetName << "Insts, " + << NumberedInstructions.size() << ");\n}\n"; OS << "} // End llvm namespace \n"; + + OS << "#endif // GET_INSTRINFO_CTOR\n\n"; } void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo, std::map<std::vector<Record*>, unsigned> &EmittedLists, - std::map<Record*, unsigned> &BarriersMap, const OperandInfoMapTy &OpInfo, raw_ostream &OS) { int MinOperands = 0; @@ -263,35 +262,37 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, OS << " { "; OS << Num << ",\t" << MinOperands << ",\t" - << Inst.Operands.NumDefs << ",\t" << getItinClassNumber(Inst.TheDef) - << ",\t\"" << Inst.TheDef->getName() << "\", 0"; + << Inst.Operands.NumDefs << ",\t" + << getItinClassNumber(Inst.TheDef) << ",\t" + << Inst.TheDef->getValueAsInt("Size") << ",\t\"" + << Inst.TheDef->getName() << "\", 0"; // Emit all of the target indepedent flags... - if (Inst.isReturn) OS << "|(1<<TID::Return)"; - if (Inst.isBranch) OS << "|(1<<TID::Branch)"; - if (Inst.isIndirectBranch) OS << "|(1<<TID::IndirectBranch)"; - if (Inst.isCompare) OS << "|(1<<TID::Compare)"; - if (Inst.isMoveImm) OS << "|(1<<TID::MoveImm)"; - if (Inst.isBitcast) OS << "|(1<<TID::Bitcast)"; - if (Inst.isBarrier) OS << "|(1<<TID::Barrier)"; - if (Inst.hasDelaySlot) OS << "|(1<<TID::DelaySlot)"; - if (Inst.isCall) OS << "|(1<<TID::Call)"; - if (Inst.canFoldAsLoad) OS << "|(1<<TID::FoldableAsLoad)"; - if (Inst.mayLoad) OS << "|(1<<TID::MayLoad)"; - if (Inst.mayStore) OS << "|(1<<TID::MayStore)"; - if (Inst.isPredicable) OS << "|(1<<TID::Predicable)"; - if (Inst.isConvertibleToThreeAddress) OS << "|(1<<TID::ConvertibleTo3Addr)"; - if (Inst.isCommutable) OS << "|(1<<TID::Commutable)"; - if (Inst.isTerminator) OS << "|(1<<TID::Terminator)"; - if (Inst.isReMaterializable) OS << "|(1<<TID::Rematerializable)"; - if (Inst.isNotDuplicable) OS << "|(1<<TID::NotDuplicable)"; - if (Inst.Operands.hasOptionalDef) OS << "|(1<<TID::HasOptionalDef)"; - if (Inst.usesCustomInserter) OS << "|(1<<TID::UsesCustomInserter)"; - if (Inst.Operands.isVariadic)OS << "|(1<<TID::Variadic)"; - if (Inst.hasSideEffects) OS << "|(1<<TID::UnmodeledSideEffects)"; - if (Inst.isAsCheapAsAMove) OS << "|(1<<TID::CheapAsAMove)"; - if (Inst.hasExtraSrcRegAllocReq) OS << "|(1<<TID::ExtraSrcRegAllocReq)"; - if (Inst.hasExtraDefRegAllocReq) OS << "|(1<<TID::ExtraDefRegAllocReq)"; + if (Inst.isReturn) OS << "|(1<<MCID::Return)"; + if (Inst.isBranch) OS << "|(1<<MCID::Branch)"; + if (Inst.isIndirectBranch) OS << "|(1<<MCID::IndirectBranch)"; + if (Inst.isCompare) OS << "|(1<<MCID::Compare)"; + if (Inst.isMoveImm) OS << "|(1<<MCID::MoveImm)"; + if (Inst.isBitcast) OS << "|(1<<MCID::Bitcast)"; + if (Inst.isBarrier) OS << "|(1<<MCID::Barrier)"; + if (Inst.hasDelaySlot) OS << "|(1<<MCID::DelaySlot)"; + if (Inst.isCall) OS << "|(1<<MCID::Call)"; + if (Inst.canFoldAsLoad) OS << "|(1<<MCID::FoldableAsLoad)"; + if (Inst.mayLoad) OS << "|(1<<MCID::MayLoad)"; + if (Inst.mayStore) OS << "|(1<<MCID::MayStore)"; + if (Inst.isPredicable) OS << "|(1<<MCID::Predicable)"; + if (Inst.isConvertibleToThreeAddress) OS << "|(1<<MCID::ConvertibleTo3Addr)"; + if (Inst.isCommutable) OS << "|(1<<MCID::Commutable)"; + if (Inst.isTerminator) OS << "|(1<<MCID::Terminator)"; + if (Inst.isReMaterializable) OS << "|(1<<MCID::Rematerializable)"; + if (Inst.isNotDuplicable) OS << "|(1<<MCID::NotDuplicable)"; + if (Inst.Operands.hasOptionalDef) OS << "|(1<<MCID::HasOptionalDef)"; + if (Inst.usesCustomInserter) OS << "|(1<<MCID::UsesCustomInserter)"; + if (Inst.Operands.isVariadic)OS << "|(1<<MCID::Variadic)"; + if (Inst.hasSideEffects) OS << "|(1<<MCID::UnmodeledSideEffects)"; + if (Inst.isAsCheapAsAMove) OS << "|(1<<MCID::CheapAsAMove)"; + if (Inst.hasExtraSrcRegAllocReq) OS << "|(1<<MCID::ExtraSrcRegAllocReq)"; + if (Inst.hasExtraDefRegAllocReq) OS << "|(1<<MCID::ExtraDefRegAllocReq)"; // Emit all of the target-specific flags... BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags"); @@ -320,12 +321,6 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, else OS << "ImplicitList" << EmittedLists[DefList] << ", "; - std::map<Record*, unsigned>::iterator BI = BarriersMap.find(Inst.TheDef); - if (BI == BarriersMap.end()) - OS << "NULL, "; - else - OS << "Barriers" << BI->second << ", "; - // Emit the operand info. std::vector<std::string> OperandInfo = GetOperandInfo(Inst); if (OperandInfo.empty()) @@ -335,3 +330,38 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n"; } + +// emitEnums - Print out enum values for all of the instructions. +void InstrInfoEmitter::emitEnums(raw_ostream &OS) { + EmitSourceFileHeader("Target Instruction Enum Values", OS); + + OS << "\n#ifdef GET_INSTRINFO_ENUM\n"; + OS << "#undef GET_INSTRINFO_ENUM\n"; + + OS << "namespace llvm {\n\n"; + + CodeGenTarget Target(Records); + + // We must emit the PHI opcode first... + std::string Namespace = Target.getInstNamespace(); + + if (Namespace.empty()) { + fprintf(stderr, "No instructions defined!\n"); + exit(1); + } + + const std::vector<const CodeGenInstruction*> &NumberedInstructions = + Target.getInstructionsByEnumValue(); + + OS << "namespace " << Namespace << " {\n"; + OS << " enum {\n"; + for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { + OS << " " << NumberedInstructions[i]->TheDef->getName() + << "\t= " << i << ",\n"; + } + OS << " INSTRUCTION_LIST_END = " << NumberedInstructions.size() << "\n"; + OS << " };\n}\n"; + OS << "} // End llvm namespace \n"; + + OS << "#endif // GET_INSTRINFO_ENUM\n\n"; +} diff --git a/contrib/llvm/utils/TableGen/InstrInfoEmitter.h b/contrib/llvm/utils/TableGen/InstrInfoEmitter.h index abb1c6b..165ce42 100644 --- a/contrib/llvm/utils/TableGen/InstrInfoEmitter.h +++ b/contrib/llvm/utils/TableGen/InstrInfoEmitter.h @@ -39,12 +39,12 @@ public: void run(raw_ostream &OS); private: - typedef std::map<std::vector<std::string>, unsigned> OperandInfoMapTy; - + void emitEnums(raw_ostream &OS); + + typedef std::map<std::vector<std::string>, unsigned> OperandInfoMapTy; void emitRecord(const CodeGenInstruction &Inst, unsigned Num, Record *InstrInfo, std::map<std::vector<Record*>, unsigned> &EL, - std::map<Record*, unsigned> &BM, const OperandInfoMapTy &OpInfo, raw_ostream &OS); @@ -55,10 +55,6 @@ private: // Operand information. void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs); std::vector<std::string> GetOperandInfo(const CodeGenInstruction &Inst); - - void DetectRegisterClassBarriers(std::vector<Record*> &Defs, - const std::vector<CodeGenRegisterClass> &RCs, - std::vector<Record*> &Barriers); }; } // End llvm namespace diff --git a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp index 39eb3bd..e5e7cea 100644 --- a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp +++ b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp @@ -214,7 +214,7 @@ static void EmitTypeGenerate(raw_ostream &OS, if (ArgTypes.size() == 1) return EmitTypeGenerate(OS, ArgTypes.front(), ArgNo); - OS << "StructType::get(Context, "; + OS << "StructType::get("; for (std::vector<Record*>::const_iterator I = ArgTypes.begin(), E = ArgTypes.end(); I != E; ++I) { @@ -259,7 +259,7 @@ static void EmitTypeGenerate(raw_ostream &OS, const Record *ArgType, } else if (VT == MVT::iPTRAny) { // Make sure the user has passed us an argument type to overload. If not, // treat it as an ordinary (not overloaded) intrinsic. - OS << "(" << ArgNo << " < numTys) ? Tys[" << ArgNo + OS << "(" << ArgNo << " < Tys.size()) ? Tys[" << ArgNo << "] : PointerType::getUnqual("; EmitTypeGenerate(OS, ArgType->getValueAsDef("ElTy"), ArgNo); OS << ")"; diff --git a/contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp b/contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp index 090faf5..cd0cbeb 100644 --- a/contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp +++ b/contrib/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp @@ -2969,8 +2969,8 @@ void EmitHookDeclarations(const ToolDescriptions& ToolDescs, for (HookInfoMap::const_iterator B = HookNames.begin(), E = HookNames.end(); B != E; ++B) { - const char* HookName = B->first(); - const HookInfo& Info = B->second; + StringRef HookName = B->first(); + const HookInfo &Info = B->second; O.indent(Indent1) << "std::string " << HookName << "("; diff --git a/contrib/llvm/utils/TableGen/NeonEmitter.cpp b/contrib/llvm/utils/TableGen/NeonEmitter.cpp index 23fdbde..ef977443 100644 --- a/contrib/llvm/utils/TableGen/NeonEmitter.cpp +++ b/contrib/llvm/utils/TableGen/NeonEmitter.cpp @@ -24,6 +24,7 @@ //===----------------------------------------------------------------------===// #include "NeonEmitter.h" +#include "Error.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" diff --git a/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp new file mode 100644 index 0000000..db33c1f --- /dev/null +++ b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp @@ -0,0 +1,243 @@ +//===- PseudoLoweringEmitter.cpp - PseudoLowering Generator -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "pseudo-lowering" +#include "Error.h" +#include "CodeGenInstruction.h" +#include "PseudoLoweringEmitter.h" +#include "Record.h" +#include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Debug.h" +#include <vector> +using namespace llvm; + +// FIXME: This pass currently can only expand a pseudo to a single instruction. +// The pseudo expansion really should take a list of dags, not just +// a single dag, so we can do fancier things. + +unsigned PseudoLoweringEmitter:: +addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Insn, + IndexedMap<OpData> &OperandMap, unsigned BaseIdx) { + unsigned OpsAdded = 0; + for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) { + if (DefInit *DI = dynamic_cast<DefInit*>(Dag->getArg(i))) { + // Physical register reference. Explicit check for the special case + // "zero_reg" definition. + if (DI->getDef()->isSubClassOf("Register") || + DI->getDef()->getName() == "zero_reg") { + OperandMap[BaseIdx + i].Kind = OpData::Reg; + OperandMap[BaseIdx + i].Data.Reg = DI->getDef(); + ++OpsAdded; + continue; + } + + // Normal operands should always have the same type, or we have a + // problem. + // FIXME: We probably shouldn't ever get a non-zero BaseIdx here. + assert(BaseIdx == 0 && "Named subargument in pseudo expansion?!"); + if (DI->getDef() != Insn.Operands[BaseIdx + i].Rec) + throw TGError(Rec->getLoc(), + "Pseudo operand type '" + DI->getDef()->getName() + + "' does not match expansion operand type '" + + Insn.Operands[BaseIdx + i].Rec->getName() + "'"); + // Source operand maps to destination operand. The Data element + // will be filled in later, just set the Kind for now. Do it + // for each corresponding MachineInstr operand, not just the first. + for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I) + OperandMap[BaseIdx + i + I].Kind = OpData::Operand; + OpsAdded += Insn.Operands[i].MINumOperands; + } else if (IntInit *II = dynamic_cast<IntInit*>(Dag->getArg(i))) { + OperandMap[BaseIdx + i].Kind = OpData::Imm; + OperandMap[BaseIdx + i].Data.Imm = II->getValue(); + ++OpsAdded; + } else if (DagInit *SubDag = dynamic_cast<DagInit*>(Dag->getArg(i))) { + // Just add the operands recursively. This is almost certainly + // a constant value for a complex operand (> 1 MI operand). + unsigned NewOps = + addDagOperandMapping(Rec, SubDag, Insn, OperandMap, BaseIdx + i); + OpsAdded += NewOps; + // Since we added more than one, we also need to adjust the base. + BaseIdx += NewOps - 1; + } else + assert(0 && "Unhandled pseudo-expansion argument type!"); + } + return OpsAdded; +} + +void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) { + DEBUG(dbgs() << "Pseudo definition: " << Rec->getName() << "\n"); + + // Validate that the result pattern has the corrent number and types + // of arguments for the instruction it references. + DagInit *Dag = Rec->getValueAsDag("ResultInst"); + assert(Dag && "Missing result instruction in pseudo expansion!"); + DEBUG(dbgs() << " Result: " << *Dag << "\n"); + + DefInit *OpDef = dynamic_cast<DefInit*>(Dag->getOperator()); + if (!OpDef) + throw TGError(Rec->getLoc(), Rec->getName() + + " has unexpected operator type!"); + Record *Operator = OpDef->getDef(); + if (!Operator->isSubClassOf("Instruction")) + throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + + "' is not an instruction!"); + + CodeGenInstruction Insn(Operator); + + if (Insn.isCodeGenOnly || Insn.isPseudo) + throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + + "' cannot be another pseudo instruction!"); + + if (Insn.Operands.size() != Dag->getNumArgs()) + throw TGError(Rec->getLoc(), "Pseudo result '" + Operator->getName() + + "' operand count mismatch"); + + IndexedMap<OpData> OperandMap; + OperandMap.grow(Insn.Operands.size()); + + addDagOperandMapping(Rec, Dag, Insn, OperandMap, 0); + + // If there are more operands that weren't in the DAG, they have to + // be operands that have default values, or we have an error. Currently, + // PredicateOperand and OptionalDefOperand both have default values. + + + // Validate that each result pattern argument has a matching (by name) + // argument in the source instruction, in either the (outs) or (ins) list. + // Also check that the type of the arguments match. + // + // Record the mapping of the source to result arguments for use by + // the lowering emitter. + CodeGenInstruction SourceInsn(Rec); + StringMap<unsigned> SourceOperands; + for (unsigned i = 0, e = SourceInsn.Operands.size(); i != e; ++i) + SourceOperands[SourceInsn.Operands[i].Name] = i; + + DEBUG(dbgs() << " Operand mapping:\n"); + for (unsigned i = 0, e = Insn.Operands.size(); i != e; ++i) { + // We've already handled constant values. Just map instruction operands + // here. + if (OperandMap[Insn.Operands[i].MIOperandNo].Kind != OpData::Operand) + continue; + StringMap<unsigned>::iterator SourceOp = + SourceOperands.find(Dag->getArgName(i)); + if (SourceOp == SourceOperands.end()) + throw TGError(Rec->getLoc(), + "Pseudo output operand '" + Dag->getArgName(i) + + "' has no matching source operand."); + // Map the source operand to the destination operand index for each + // MachineInstr operand. + for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I) + OperandMap[Insn.Operands[i].MIOperandNo + I].Data.Operand = + SourceOp->getValue(); + + DEBUG(dbgs() << " " << SourceOp->getValue() << " ==> " << i << "\n"); + } + + Expansions.push_back(PseudoExpansion(SourceInsn, Insn, OperandMap)); +} + +void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) { + // Emit file header. + EmitSourceFileHeader("Pseudo-instruction MC lowering Source Fragment", o); + + o << "bool " << Target.getName() + "AsmPrinter" << "::\n" + << "emitPseudoExpansionLowering(MCStreamer &OutStreamer,\n" + << " const MachineInstr *MI) {\n" + << " switch (MI->getOpcode()) {\n" + << " default: return false;\n"; + for (unsigned i = 0, e = Expansions.size(); i != e; ++i) { + PseudoExpansion &Expansion = Expansions[i]; + CodeGenInstruction &Source = Expansion.Source; + CodeGenInstruction &Dest = Expansion.Dest; + o << " case " << Source.Namespace << "::" + << Source.TheDef->getName() << ": {\n" + << " MCInst TmpInst;\n" + << " MCOperand MCOp;\n" + << " TmpInst.setOpcode(" << Dest.Namespace << "::" + << Dest.TheDef->getName() << ");\n"; + + // Copy the operands from the source instruction. + // FIXME: Instruction operands with defaults values (predicates and cc_out + // in ARM, for example shouldn't need explicit values in the + // expansion DAG. + unsigned MIOpNo = 0; + for (unsigned OpNo = 0, E = Dest.Operands.size(); OpNo != E; + ++OpNo) { + o << " // Operand: " << Dest.Operands[OpNo].Name << "\n"; + for (unsigned i = 0, e = Dest.Operands[OpNo].MINumOperands; + i != e; ++i) { + switch (Expansion.OperandMap[MIOpNo + i].Kind) { + default: + llvm_unreachable("Unknown operand type?!"); + case OpData::Operand: + o << " lowerOperand(MI->getOperand(" + << Source.Operands[Expansion.OperandMap[MIOpNo].Data + .Operand].MIOperandNo + i + << "), MCOp);\n" + << " TmpInst.addOperand(MCOp);\n"; + break; + case OpData::Imm: + o << " TmpInst.addOperand(MCOperand::CreateImm(" + << Expansion.OperandMap[MIOpNo + i].Data.Imm << "));\n"; + break; + case OpData::Reg: { + Record *Reg = Expansion.OperandMap[MIOpNo + i].Data.Reg; + o << " TmpInst.addOperand(MCOperand::CreateReg("; + // "zero_reg" is special. + if (Reg->getName() == "zero_reg") + o << "0"; + else + o << Reg->getValueAsString("Namespace") << "::" << Reg->getName(); + o << "));\n"; + break; + } + } + } + MIOpNo += Dest.Operands[OpNo].MINumOperands; + } + if (Dest.Operands.isVariadic) { + o << " // variable_ops\n"; + o << " for (unsigned i = " << MIOpNo + << ", e = MI->getNumOperands(); i != e; ++i)\n" + << " if (lowerOperand(MI->getOperand(i), MCOp))\n" + << " TmpInst.addOperand(MCOp);\n"; + } + o << " OutStreamer.EmitInstruction(TmpInst);\n" + << " break;\n" + << " }\n"; + } + o << " }\n return true;\n}\n\n"; +} + +void PseudoLoweringEmitter::run(raw_ostream &o) { + Record *ExpansionClass = Records.getClass("PseudoInstExpansion"); + Record *InstructionClass = Records.getClass("PseudoInstExpansion"); + assert(ExpansionClass && "PseudoInstExpansion class definition missing!"); + assert(InstructionClass && "Instruction class definition missing!"); + + std::vector<Record*> Insts; + for (std::map<std::string, Record*>::const_iterator I = + Records.getDefs().begin(), E = Records.getDefs().end(); I != E; ++I) { + if (I->second->isSubClassOf(ExpansionClass) && + I->second->isSubClassOf(InstructionClass)) + Insts.push_back(I->second); + } + + // Process the pseudo expansion definitions, validating them as we do so. + for (unsigned i = 0, e = Insts.size(); i != e; ++i) + evaluateExpansion(Insts[i]); + + // Generate expansion code to lower the pseudo to an MCInst of the real + // instruction. + emitLoweringEmitter(o); +} + diff --git a/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.h b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.h new file mode 100644 index 0000000..2749280 --- /dev/null +++ b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.h @@ -0,0 +1,65 @@ +//===- PseudoLoweringEmitter.h - PseudoLowering Generator -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef PSEUDOLOWERINGEMITTER_H +#define PSEUDOLOWERINGEMITTER_H + +#include "CodeGenInstruction.h" +#include "CodeGenTarget.h" +#include "TableGenBackend.h" +#include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +class PseudoLoweringEmitter : public TableGenBackend { + struct OpData { + enum MapKind { Operand, Imm, Reg }; + MapKind Kind; + union { + unsigned Operand; // Operand number mapped to. + uint64_t Imm; // Integer immedate value. + Record *Reg; // Physical register. + } Data; + }; + struct PseudoExpansion { + CodeGenInstruction Source; // The source pseudo instruction definition. + CodeGenInstruction Dest; // The destination instruction to lower to. + IndexedMap<OpData> OperandMap; + + PseudoExpansion(CodeGenInstruction &s, CodeGenInstruction &d, + IndexedMap<OpData> &m) : + Source(s), Dest(d), OperandMap(m) {} + }; + + RecordKeeper &Records; + + // It's overkill to have an instance of the full CodeGenTarget object, + // but it loads everything on demand, not in the constructor, so it's + // lightweight in performance, so it works out OK. + CodeGenTarget Target; + + SmallVector<PseudoExpansion, 64> Expansions; + + unsigned addDagOperandMapping(Record *Rec, DagInit *Dag, + CodeGenInstruction &Insn, + IndexedMap<OpData> &OperandMap, + unsigned BaseIdx); + void evaluateExpansion(Record *Pseudo); + void emitLoweringEmitter(raw_ostream &o); +public: + PseudoLoweringEmitter(RecordKeeper &R) : Records(R), Target(R) {} + + /// run - Output the pseudo-lowerings. + void run(raw_ostream &o); +}; + +} // end llvm namespace + +#endif diff --git a/contrib/llvm/utils/TableGen/Record.cpp b/contrib/llvm/utils/TableGen/Record.cpp index 8ac8cd9..730eca1 100644 --- a/contrib/llvm/utils/TableGen/Record.cpp +++ b/contrib/llvm/utils/TableGen/Record.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "Record.h" +#include "Error.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/Format.h" #include "llvm/ADT/StringExtras.h" @@ -1442,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/contrib/llvm/utils/TableGen/Record.h b/contrib/llvm/utils/TableGen/Record.h index 522b719..2f4080b 100644 --- a/contrib/llvm/utils/TableGen/Record.h +++ b/contrib/llvm/utils/TableGen/Record.h @@ -34,7 +34,7 @@ class DagRecTy; class RecordRecTy; // Init subclasses. -struct Init; +class Init; class UnsetInit; class BitInit; class BitsInit; @@ -453,7 +453,8 @@ RecTy *resolveTypes(RecTy *T1, RecTy *T2); // Initializer Classes //===----------------------------------------------------------------------===// -struct Init { +class Init { +public: virtual ~Init() {} /// isComplete - This virtual method should be overridden by values that may @@ -1368,6 +1369,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. @@ -1486,22 +1493,8 @@ struct LessRecordFieldName { } }; - -class TGError { - SMLoc Loc; - std::string Message; -public: - TGError(SMLoc loc, const std::string &message) : Loc(loc), Message(message) {} - - SMLoc getLoc() const { return Loc; } - const std::string &getMessage() const { return Message; } -}; - - raw_ostream &operator<<(raw_ostream &OS, const RecordKeeper &RK); -void PrintError(SMLoc ErrorLoc, const Twine &Msg); - } // End llvm namespace #endif diff --git a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp index 5a441e2..65d4a9b 100644 --- a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp +++ b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp @@ -19,19 +19,24 @@ #include "Record.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Format.h" #include <algorithm> #include <set> using namespace llvm; // runEnums - Print out enum values for all of the registers. -void RegisterInfoEmitter::runEnums(raw_ostream &OS) { - CodeGenTarget Target(Records); - CodeGenRegBank &Bank = Target.getRegBank(); - const std::vector<CodeGenRegister> &Registers = Target.getRegisters(); +void +RegisterInfoEmitter::runEnums(raw_ostream &OS, + CodeGenTarget &Target, CodeGenRegBank &Bank) { + const std::vector<CodeGenRegister*> &Registers = Bank.getRegisters(); - std::string Namespace = Registers[0].TheDef->getValueAsString("Namespace"); + std::string Namespace = Registers[0]->TheDef->getValueAsString("Namespace"); EmitSourceFileHeader("Target Register Enum Values", OS); + + OS << "\n#ifdef GET_REGINFO_ENUM\n"; + OS << "#undef GET_REGINFO_ENUM\n"; + OS << "namespace llvm {\n\n"; if (!Namespace.empty()) @@ -39,35 +44,166 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS) { OS << "enum {\n NoRegister,\n"; for (unsigned i = 0, e = Registers.size(); i != e; ++i) - OS << " " << Registers[i].getName() << " = " << - Registers[i].EnumValue << ",\n"; - assert(Registers.size() == Registers[Registers.size()-1].EnumValue && + OS << " " << Registers[i]->getName() << " = " << + Registers[i]->EnumValue << ",\n"; + assert(Registers.size() == Registers[Registers.size()-1]->EnumValue && "Register enum value mismatch!"); OS << " NUM_TARGET_REGS \t// " << Registers.size()+1 << "\n"; OS << "};\n"; if (!Namespace.empty()) OS << "}\n"; - const std::vector<Record*> &SubRegIndices = Bank.getSubRegIndices(); - if (!SubRegIndices.empty()) { - OS << "\n// Subregister indices\n"; - Namespace = SubRegIndices[0]->getValueAsString("Namespace"); + const std::vector<CodeGenRegisterClass> &RegisterClasses = + Target.getRegisterClasses(); + if (!RegisterClasses.empty()) { + OS << "\n// Register classes\n"; if (!Namespace.empty()) OS << "namespace " << Namespace << " {\n"; - OS << "enum {\n NoSubRegister,\n"; - for (unsigned i = 0, e = Bank.getNumNamedIndices(); i != e; ++i) - OS << " " << SubRegIndices[i]->getName() << ",\t// " << i+1 << "\n"; - OS << " NUM_TARGET_NAMED_SUBREGS = " << SubRegIndices.size()+1 << "\n"; + OS << "enum {\n"; + for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { + if (i) OS << ",\n"; + OS << " " << RegisterClasses[i].getName() << "RegClassID"; + OS << " = " << i; + } + OS << "\n };\n"; + if (!Namespace.empty()) + OS << "}\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"; + if (!Namespace.empty()) + OS << "namespace " << Namespace << " {\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"; if (!Namespace.empty()) OS << "}\n"; } + + OS << "} // End llvm namespace \n"; + OS << "#endif // GET_REGINFO_ENUM\n\n"; } -void RegisterInfoEmitter::runHeader(raw_ostream &OS) { +// +// runMCDesc - Print out MC register descriptions. +// +void +RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, + CodeGenRegBank &RegBank) { + EmitSourceFileHeader("MC Register Information", OS); + + OS << "\n#ifdef GET_REGINFO_MC_DESC\n"; + OS << "#undef GET_REGINFO_MC_DESC\n"; + + std::map<const CodeGenRegister*, CodeGenRegister::Set> Overlaps; + RegBank.computeOverlaps(Overlaps); + + OS << "namespace llvm {\n\n"; + + const std::string &TargetName = Target.getName(); + std::string ClassName = TargetName + "GenMCRegisterInfo"; + OS << "struct " << ClassName << " : public MCRegisterInfo {\n" + << " explicit " << ClassName << "(const MCRegisterDesc *D);\n"; + OS << "};\n"; + + OS << "\nnamespace {\n"; + + const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters(); + + // Emit an overlap list for all registers. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister *Reg = Regs[i]; + const CodeGenRegister::Set &O = Overlaps[Reg]; + // Move Reg to the front so TRI::getAliasSet can share the list. + OS << " const unsigned " << Reg->getName() << "_Overlaps[] = { " + << getQualifiedName(Reg->TheDef) << ", "; + for (CodeGenRegister::Set::const_iterator I = O.begin(), E = O.end(); + I != E; ++I) + if (*I != Reg) + OS << getQualifiedName((*I)->TheDef) << ", "; + OS << "0 };\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 + // sub-registers list to memory. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister &Reg = *Regs[i]; + if (Reg.getSubRegs().empty()) + continue; + // getSubRegs() orders by SubRegIndex. We want a topological order. + SetVector<CodeGenRegister*> SR; + Reg.addSubRegsPreOrder(SR); + OS << " const unsigned " << Reg.getName() << "_SubRegsSet[] = { "; + for (unsigned j = 0, je = SR.size(); j != je; ++j) + OS << getQualifiedName(SR[j]->TheDef) << ", "; + OS << "0 };\n"; + } + + // Emit the empty super-registers list + OS << " const unsigned Empty_SuperRegsSet[] = { 0 };\n"; + // Loop over all of the registers which have super-registers, emitting the + // super-registers list to memory. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister &Reg = *Regs[i]; + const CodeGenRegister::SuperRegList &SR = Reg.getSuperRegs(); + if (SR.empty()) + continue; + OS << " const unsigned " << Reg.getName() << "_SuperRegsSet[] = { "; + for (unsigned j = 0, je = SR.size(); j != je; ++j) + OS << getQualifiedName(SR[j]->TheDef) << ", "; + OS << "0 };\n"; + } + OS << "}\n"; // End of anonymous namespace... + + OS << "\nMCRegisterDesc " << TargetName + << "RegDesc[] = { // Descriptors\n"; + OS << " { \"NOREG\",\t0,\t0,\t0 },\n"; + + // Now that register alias and sub-registers sets have been emitted, emit the + // register descriptors now. + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + const CodeGenRegister &Reg = *Regs[i]; + OS << " { \""; + OS << Reg.getName() << "\",\t" << Reg.getName() << "_Overlaps,\t"; + if (!Reg.getSubRegs().empty()) + OS << Reg.getName() << "_SubRegsSet,\t"; + else + OS << "Empty_SubRegsSet,\t"; + if (!Reg.getSuperRegs().empty()) + OS << Reg.getName() << "_SuperRegsSet"; + else + OS << "Empty_SuperRegsSet"; + OS << " },\n"; + } + OS << "};\n\n"; // End of register descriptors... + + // MCRegisterInfo initialization routine. + OS << "static inline void Init" << TargetName + << "MCRegisterInfo(MCRegisterInfo *RI) {\n"; + OS << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " + << Regs.size()+1 << ");\n}\n\n"; + + OS << "} // End llvm namespace \n"; + OS << "#endif // GET_REGINFO_MC_DESC\n\n"; +} + +void +RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, + CodeGenRegBank &RegBank) { EmitSourceFileHeader("Register Information Header Fragment", OS); - CodeGenTarget Target(Records); + + OS << "\n#ifdef GET_REGINFO_HEADER\n"; + OS << "#undef GET_REGINFO_HEADER\n"; + const std::string &TargetName = Target.getName(); std::string ClassName = TargetName + "GenRegisterInfo"; @@ -77,8 +213,7 @@ void RegisterInfoEmitter::runHeader(raw_ostream &OS) { OS << "namespace llvm {\n\n"; OS << "struct " << ClassName << " : public TargetRegisterInfo {\n" - << " explicit " << ClassName - << "(int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1);\n" + << " explicit " << ClassName << "();\n" << " virtual int getDwarfRegNumFull(unsigned RegNum, " << "unsigned Flavour) const;\n" << " virtual int getLLVMRegNumFull(unsigned DwarfRegNum, " @@ -91,6 +226,21 @@ void RegisterInfoEmitter::runHeader(raw_ostream &OS) { << " unsigned composeSubRegIndices(unsigned, unsigned) const;\n" << "};\n\n"; + const std::vector<Record*> &SubRegIndices = RegBank.getSubRegIndices(); + if (!SubRegIndices.empty()) { + OS << "\n// Subregister indices\n"; + std::string Namespace = SubRegIndices[0]->getValueAsString("Namespace"); + if (!Namespace.empty()) + OS << "namespace " << Namespace << " {\n"; + OS << "enum {\n NoSubRegister,\n"; + for (unsigned i = 0, e = RegBank.getNumNamedIndices(); i != e; ++i) + OS << " " << SubRegIndices[i]->getName() << ",\t// " << i+1 << "\n"; + OS << " NUM_TARGET_NAMED_SUBREGS = " << SubRegIndices.size()+1 << "\n"; + OS << "};\n"; + if (!Namespace.empty()) + OS << "}\n"; + } + const std::vector<CodeGenRegisterClass> &RegisterClasses = Target.getRegisterClasses(); @@ -98,21 +248,17 @@ void RegisterInfoEmitter::runHeader(raw_ostream &OS) { OS << "namespace " << RegisterClasses[0].Namespace << " { // Register classes\n"; - OS << " enum {\n"; - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { - if (i) OS << ",\n"; - OS << " " << RegisterClasses[i].getName() << "RegClassID"; - OS << " = " << i; - } - OS << "\n };\n\n"; - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { - const std::string &Name = RegisterClasses[i].getName(); + const CodeGenRegisterClass &RC = RegisterClasses[i]; + const std::string &Name = RC.getName(); // Output the register class definition. OS << " struct " << Name << "Class : public TargetRegisterClass {\n" - << " " << Name << "Class();\n" - << RegisterClasses[i].MethodProtos << " };\n"; + << " " << Name << "Class();\n"; + if (!RC.AltOrderSelect.empty()) + OS << " ArrayRef<unsigned> " + "getRawAllocationOrder(const MachineFunction&) const;\n"; + OS << " };\n"; // Output the extern for the instance. OS << " extern " << Name << "Class\t" << Name << "RegClass;\n"; @@ -123,72 +269,19 @@ void RegisterInfoEmitter::runHeader(raw_ostream &OS) { OS << "} // end of namespace " << TargetName << "\n\n"; } OS << "} // End llvm namespace \n"; + OS << "#endif // GET_REGINFO_HEADER\n\n"; } -static void addSuperReg(Record *R, Record *S, - std::map<Record*, std::set<Record*>, LessRecord> &SubRegs, - std::map<Record*, std::set<Record*>, LessRecord> &SuperRegs, - std::map<Record*, std::set<Record*>, LessRecord> &Aliases) { - if (R == S) { - errs() << "Error: recursive sub-register relationship between" - << " register " << getQualifiedName(R) - << " and its sub-registers?\n"; - abort(); - } - if (!SuperRegs[R].insert(S).second) - return; - SubRegs[S].insert(R); - Aliases[R].insert(S); - Aliases[S].insert(R); - if (SuperRegs.count(S)) - for (std::set<Record*>::iterator I = SuperRegs[S].begin(), - E = SuperRegs[S].end(); I != E; ++I) - addSuperReg(R, *I, SubRegs, SuperRegs, Aliases); -} - -static void addSubSuperReg(Record *R, Record *S, - std::map<Record*, std::set<Record*>, LessRecord> &SubRegs, - std::map<Record*, std::set<Record*>, LessRecord> &SuperRegs, - std::map<Record*, std::set<Record*>, LessRecord> &Aliases) { - if (R == S) { - errs() << "Error: recursive sub-register relationship between" - << " register " << getQualifiedName(R) - << " and its sub-registers?\n"; - abort(); - } - - if (!SubRegs[R].insert(S).second) - return; - addSuperReg(S, R, SubRegs, SuperRegs, Aliases); - Aliases[R].insert(S); - Aliases[S].insert(R); - if (SubRegs.count(S)) - for (std::set<Record*>::iterator I = SubRegs[S].begin(), - E = SubRegs[S].end(); I != E; ++I) - addSubSuperReg(R, *I, SubRegs, SuperRegs, Aliases); -} - -class RegisterSorter { -private: - std::map<Record*, std::set<Record*>, LessRecord> &RegisterSubRegs; - -public: - RegisterSorter(std::map<Record*, std::set<Record*>, LessRecord> &RS) - : RegisterSubRegs(RS) {} - - bool operator()(Record *RegA, Record *RegB) { - // B is sub-register of A. - return RegisterSubRegs.count(RegA) && RegisterSubRegs[RegA].count(RegB); - } -}; - -// RegisterInfoEmitter::run - Main register file description emitter. // -void RegisterInfoEmitter::run(raw_ostream &OS) { - CodeGenTarget Target(Records); - CodeGenRegBank &RegBank = Target.getRegBank(); - RegBank.computeDerivedInfo(); - EmitSourceFileHeader("Register Information Source Fragment", OS); +// runTargetDesc - Output the target register and register file descriptions. +// +void +RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, + CodeGenRegBank &RegBank){ + EmitSourceFileHeader("Target Register and Register Classes Information", OS); + + OS << "\n#ifdef GET_REGINFO_TARGET_DESC\n"; + OS << "#undef GET_REGINFO_TARGET_DESC\n"; OS << "namespace llvm {\n\n"; @@ -205,20 +298,21 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { // Emit the register enum value arrays for each RegisterClass for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { const CodeGenRegisterClass &RC = RegisterClasses[rc]; + ArrayRef<Record*> Order = RC.getOrder(); // Collect allocatable registers. if (RC.Allocatable) - AllocatableRegs.insert(RC.Elements.begin(), RC.Elements.end()); + AllocatableRegs.insert(Order.begin(), Order.end()); // Give the register class a legal C name if it's anonymous. - std::string Name = RC.TheDef->getName(); + std::string Name = RC.getName(); // Emit the register list now. OS << " // " << Name << " Register Class...\n" << " static const unsigned " << Name << "[] = {\n "; - for (unsigned i = 0, e = RC.Elements.size(); i != e; ++i) { - Record *Reg = RC.Elements[i]; + for (unsigned i = 0, e = Order.size(); i != e; ++i) { + Record *Reg = Order[i]; OS << getQualifiedName(Reg) << ", "; } OS << "\n };\n\n"; @@ -229,7 +323,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { const CodeGenRegisterClass &RC = RegisterClasses[rc]; // Give the register class a legal C name if it's anonymous. - std::string Name = RC.TheDef->getName() + "VTs"; + std::string Name = RC.getName() + "VTs"; // Emit the register list now. OS << " // " << Name @@ -397,10 +491,9 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { OS << "\n };\n\n"; } - + // Emit methods. for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { const CodeGenRegisterClass &RC = RegisterClasses[i]; - OS << RC.MethodBodies << "\n"; OS << RC.getName() << "Class::" << RC.getName() << "Class() : TargetRegisterClass(" << RC.getName() + "RegClassID" << ", " @@ -416,8 +509,30 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { << RC.SpillAlignment/8 << ", " << RC.CopyCost << ", " << RC.Allocatable << ", " - << RC.getName() << ", " << RC.getName() << " + " << RC.Elements.size() + << RC.getName() << ", " << RC.getName() << " + " + << RC.getOrder().size() << ") {}\n"; + if (!RC.AltOrderSelect.empty()) { + OS << "\nstatic inline unsigned " << RC.getName() + << "AltOrderSelect(const MachineFunction &MF) {" + << RC.AltOrderSelect << "}\n\nArrayRef<unsigned> " + << RC.getName() << "Class::" + << "getRawAllocationOrder(const MachineFunction &MF) const {\n"; + for (unsigned oi = 1 , oe = RC.getNumOrders(); oi != oe; ++oi) { + ArrayRef<Record*> Elems = RC.getOrder(oi); + OS << " static const unsigned AltOrder" << oi << "[] = {"; + for (unsigned elem = 0; elem != Elems.size(); ++elem) + OS << (elem ? ", " : " ") << getQualifiedName(Elems[elem]); + OS << " };\n"; + } + OS << " static const ArrayRef<unsigned> Order[] = {\n" + << " ArrayRef<unsigned>(" << RC.getName(); + for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi) + OS << "),\n ArrayRef<unsigned>(AltOrder" << oi; + OS << ")\n };\n const unsigned Select = " << RC.getName() + << "AltOrderSelect(MF);\n assert(Select < " << RC.getNumOrders() + << ");\n return Order[Select];\n}\n"; + } } OS << "}\n"; @@ -429,295 +544,33 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { OS << " &" << getQualifiedName(RegisterClasses[i].TheDef) << "RegClass,\n"; OS << " };\n"; + OS << "}\n"; // End of anonymous namespace... - // Emit register sub-registers / super-registers, aliases... - std::map<Record*, std::set<Record*>, LessRecord> RegisterSubRegs; - std::map<Record*, std::set<Record*>, LessRecord> RegisterSuperRegs; - std::map<Record*, std::set<Record*>, LessRecord> RegisterAliases; - typedef std::map<Record*, std::vector<int64_t>, LessRecord> DwarfRegNumsMapTy; - DwarfRegNumsMapTy DwarfRegNums; - - const std::vector<CodeGenRegister> &Regs = Target.getRegisters(); - - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record *R = Regs[i].TheDef; - std::vector<Record*> LI = Regs[i].TheDef->getValueAsListOfDefs("Aliases"); - // Add information that R aliases all of the elements in the list... and - // that everything in the list aliases R. - for (unsigned j = 0, e = LI.size(); j != e; ++j) { - Record *Reg = LI[j]; - if (RegisterAliases[R].count(Reg)) - errs() << "Warning: register alias between " << getQualifiedName(R) - << " and " << getQualifiedName(Reg) - << " specified multiple times!\n"; - RegisterAliases[R].insert(Reg); - - if (RegisterAliases[Reg].count(R)) - errs() << "Warning: register alias between " << getQualifiedName(R) - << " and " << getQualifiedName(Reg) - << " specified multiple times!\n"; - RegisterAliases[Reg].insert(R); - } - } - - // Process sub-register sets. - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record *R = Regs[i].TheDef; - std::vector<Record*> LI = Regs[i].TheDef->getValueAsListOfDefs("SubRegs"); - // Process sub-register set and add aliases information. - for (unsigned j = 0, e = LI.size(); j != e; ++j) { - Record *SubReg = LI[j]; - if (RegisterSubRegs[R].count(SubReg)) - errs() << "Warning: register " << getQualifiedName(SubReg) - << " specified as a sub-register of " << getQualifiedName(R) - << " multiple times!\n"; - addSubSuperReg(R, SubReg, RegisterSubRegs, RegisterSuperRegs, - RegisterAliases); - } - } - - // Print the SubregHashTable, a simple quadratically probed - // hash table for determining if a register is a subregister - // of another register. - unsigned NumSubRegs = 0; - std::map<Record*, unsigned> RegNo; - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - RegNo[Regs[i].TheDef] = i; - NumSubRegs += RegisterSubRegs[Regs[i].TheDef].size(); - } - - unsigned SubregHashTableSize = 2 * NextPowerOf2(2 * NumSubRegs); - unsigned* SubregHashTable = new unsigned[2 * SubregHashTableSize]; - std::fill(SubregHashTable, SubregHashTable + 2 * SubregHashTableSize, ~0U); - - unsigned hashMisses = 0; - - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record* R = Regs[i].TheDef; - for (std::set<Record*>::iterator I = RegisterSubRegs[R].begin(), - E = RegisterSubRegs[R].end(); I != E; ++I) { - Record* RJ = *I; - // We have to increase the indices of both registers by one when - // computing the hash because, in the generated code, there - // will be an extra empty slot at register 0. - size_t index = ((i+1) + (RegNo[RJ]+1) * 37) & (SubregHashTableSize-1); - unsigned ProbeAmt = 2; - while (SubregHashTable[index*2] != ~0U && - SubregHashTable[index*2+1] != ~0U) { - index = (index + ProbeAmt) & (SubregHashTableSize-1); - ProbeAmt += 2; - - hashMisses++; - } - - SubregHashTable[index*2] = i; - SubregHashTable[index*2+1] = RegNo[RJ]; - } - } - - OS << "\n\n // Number of hash collisions: " << hashMisses << "\n"; - - if (SubregHashTableSize) { - std::string Namespace = Regs[0].TheDef->getValueAsString("Namespace"); - - OS << " const unsigned SubregHashTable[] = { "; - for (unsigned i = 0; i < SubregHashTableSize - 1; ++i) { - if (i != 0) - // Insert spaces for nice formatting. - OS << " "; - - if (SubregHashTable[2*i] != ~0U) { - OS << getQualifiedName(Regs[SubregHashTable[2*i]].TheDef) << ", " - << getQualifiedName(Regs[SubregHashTable[2*i+1]].TheDef) << ", \n"; - } else { - OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister, \n"; - } - } - - unsigned Idx = SubregHashTableSize*2-2; - if (SubregHashTable[Idx] != ~0U) { - OS << " " - << getQualifiedName(Regs[SubregHashTable[Idx]].TheDef) << ", " - << getQualifiedName(Regs[SubregHashTable[Idx+1]].TheDef) << " };\n"; - } else { - OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister };\n"; - } - - OS << " const unsigned SubregHashTableSize = " - << SubregHashTableSize << ";\n"; - } else { - OS << " const unsigned SubregHashTable[] = { ~0U, ~0U };\n" - << " const unsigned SubregHashTableSize = 1;\n"; - } - - delete [] SubregHashTable; - - - // Print the AliasHashTable, a simple quadratically probed - // hash table for determining if a register aliases another register. - unsigned NumAliases = 0; - RegNo.clear(); - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - RegNo[Regs[i].TheDef] = i; - NumAliases += RegisterAliases[Regs[i].TheDef].size(); - } - - unsigned AliasesHashTableSize = 2 * NextPowerOf2(2 * NumAliases); - unsigned* AliasesHashTable = new unsigned[2 * AliasesHashTableSize]; - std::fill(AliasesHashTable, AliasesHashTable + 2 * AliasesHashTableSize, ~0U); - - hashMisses = 0; - - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record* R = Regs[i].TheDef; - for (std::set<Record*>::iterator I = RegisterAliases[R].begin(), - E = RegisterAliases[R].end(); I != E; ++I) { - Record* RJ = *I; - // We have to increase the indices of both registers by one when - // computing the hash because, in the generated code, there - // will be an extra empty slot at register 0. - size_t index = ((i+1) + (RegNo[RJ]+1) * 37) & (AliasesHashTableSize-1); - unsigned ProbeAmt = 2; - while (AliasesHashTable[index*2] != ~0U && - AliasesHashTable[index*2+1] != ~0U) { - index = (index + ProbeAmt) & (AliasesHashTableSize-1); - ProbeAmt += 2; - - hashMisses++; - } - - AliasesHashTable[index*2] = i; - AliasesHashTable[index*2+1] = RegNo[RJ]; - } - } - - OS << "\n\n // Number of hash collisions: " << hashMisses << "\n"; - - if (AliasesHashTableSize) { - std::string Namespace = Regs[0].TheDef->getValueAsString("Namespace"); - - OS << " const unsigned AliasesHashTable[] = { "; - for (unsigned i = 0; i < AliasesHashTableSize - 1; ++i) { - if (i != 0) - // Insert spaces for nice formatting. - OS << " "; - - if (AliasesHashTable[2*i] != ~0U) { - OS << getQualifiedName(Regs[AliasesHashTable[2*i]].TheDef) << ", " - << getQualifiedName(Regs[AliasesHashTable[2*i+1]].TheDef) << ", \n"; - } else { - OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister, \n"; - } - } - - unsigned Idx = AliasesHashTableSize*2-2; - if (AliasesHashTable[Idx] != ~0U) { - OS << " " - << getQualifiedName(Regs[AliasesHashTable[Idx]].TheDef) << ", " - << getQualifiedName(Regs[AliasesHashTable[Idx+1]].TheDef) << " };\n"; - } else { - OS << Namespace << "::NoRegister, " << Namespace << "::NoRegister };\n"; - } - - OS << " const unsigned AliasesHashTableSize = " - << AliasesHashTableSize << ";\n"; - } else { - OS << " const unsigned AliasesHashTable[] = { ~0U, ~0U };\n" - << " const unsigned AliasesHashTableSize = 1;\n"; - } - - delete [] AliasesHashTable; - - if (!RegisterAliases.empty()) - OS << "\n\n // Register Overlap Lists...\n"; - - // Emit an overlap list for all registers. - for (std::map<Record*, std::set<Record*>, LessRecord >::iterator - I = RegisterAliases.begin(), E = RegisterAliases.end(); I != E; ++I) { - OS << " const unsigned " << I->first->getName() << "_Overlaps[] = { " - << getQualifiedName(I->first) << ", "; - for (std::set<Record*>::iterator ASI = I->second.begin(), - E = I->second.end(); ASI != E; ++ASI) - OS << getQualifiedName(*ASI) << ", "; - OS << "0 };\n"; - } - - if (!RegisterSubRegs.empty()) - OS << "\n\n // Register Sub-registers Sets...\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 - // sub-registers list to memory. - for (std::map<Record*, std::set<Record*>, LessRecord>::iterator - I = RegisterSubRegs.begin(), E = RegisterSubRegs.end(); I != E; ++I) { - if (I->second.empty()) - continue; - OS << " const unsigned " << I->first->getName() << "_SubRegsSet[] = { "; - std::vector<Record*> SubRegsVector; - for (std::set<Record*>::iterator ASI = I->second.begin(), - E = I->second.end(); ASI != E; ++ASI) - SubRegsVector.push_back(*ASI); - RegisterSorter RS(RegisterSubRegs); - std::stable_sort(SubRegsVector.begin(), SubRegsVector.end(), RS); - for (unsigned i = 0, e = SubRegsVector.size(); i != e; ++i) - OS << getQualifiedName(SubRegsVector[i]) << ", "; - OS << "0 };\n"; - } - - if (!RegisterSuperRegs.empty()) - OS << "\n\n // Register Super-registers Sets...\n"; - - // Emit the empty super-registers list - OS << " const unsigned Empty_SuperRegsSet[] = { 0 };\n"; - // Loop over all of the registers which have super-registers, emitting the - // super-registers list to memory. - for (std::map<Record*, std::set<Record*>, LessRecord >::iterator - I = RegisterSuperRegs.begin(), E = RegisterSuperRegs.end(); I != E; ++I) { - if (I->second.empty()) - continue; - OS << " const unsigned " << I->first->getName() << "_SuperRegsSet[] = { "; - - std::vector<Record*> SuperRegsVector; - for (std::set<Record*>::iterator ASI = I->second.begin(), - E = I->second.end(); ASI != E; ++ASI) - SuperRegsVector.push_back(*ASI); - RegisterSorter RS(RegisterSubRegs); - std::stable_sort(SuperRegsVector.begin(), SuperRegsVector.end(), RS); - for (unsigned i = 0, e = SuperRegsVector.size(); i != e; ++i) - OS << getQualifiedName(SuperRegsVector[i]) << ", "; - OS << "0 };\n"; - } - - OS<<"\n const TargetRegisterDesc RegisterDescriptors[] = { // Descriptors\n"; - OS << " { \"NOREG\",\t0,\t0,\t0,\t0,\t0 },\n"; + // Emit extra information about registers. + const std::string &TargetName = Target.getName(); + OS << "\n static const TargetRegisterInfoDesc " + << TargetName << "RegInfoDesc[] = " + << "{ // Extra Descriptors\n"; + OS << " { 0, 0 },\n"; - // Now that register alias and sub-registers sets have been emitted, emit the - // register descriptors now. + const std::vector<CodeGenRegister*> &Regs = RegBank.getRegisters(); for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister &Reg = Regs[i]; - OS << " { \""; - OS << Reg.getName() << "\",\t" << Reg.getName() << "_Overlaps,\t"; - if (!RegisterSubRegs[Reg.TheDef].empty()) - OS << Reg.getName() << "_SubRegsSet,\t"; - else - OS << "Empty_SubRegsSet,\t"; - if (!RegisterSuperRegs[Reg.TheDef].empty()) - OS << Reg.getName() << "_SuperRegsSet,\t"; - else - OS << "Empty_SuperRegsSet,\t"; - OS << Reg.CostPerUse << ",\t" + const CodeGenRegister &Reg = *Regs[i]; + OS << " { "; + OS << Reg.CostPerUse << ", " << int(AllocatableRegs.count(Reg.TheDef)) << " },\n"; } OS << " };\n"; // End of register descriptors... + // Calculate the mapping of subregister+index pairs to physical registers. // This will also create further anonymous indexes. unsigned NamedIndices = RegBank.getNumNamedIndices(); // Emit SubRegIndex names, skipping 0 const std::vector<Record*> &SubRegIndices = RegBank.getSubRegIndices(); - OS << "\n const char *const SubRegIndexTable[] = { \""; + OS << "\n static const char *const " << TargetName + << "SubRegIndexTable[] = { \""; for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { OS << SubRegIndices[i]->getName(); if (i+1 != e) @@ -735,7 +588,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { } OS << "\n };\n\n"; } - OS << "}\n\n"; // End of anonymous namespace... + OS << "\n"; std::string ClassName = Target.getName() + "GenRegisterInfo"; @@ -746,10 +599,10 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { << " switch (RegNo) {\n" << " default:\n return 0;\n"; for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister::SubRegMap &SRM = Regs[i].getSubRegs(); + const CodeGenRegister::SubRegMap &SRM = Regs[i]->getSubRegs(); if (SRM.empty()) continue; - OS << " case " << getQualifiedName(Regs[i].TheDef) << ":\n"; + OS << " case " << getQualifiedName(Regs[i]->TheDef) << ":\n"; OS << " switch (Index) {\n"; OS << " default: return 0;\n"; for (CodeGenRegister::SubRegMap::const_iterator ii = SRM.begin(), @@ -767,10 +620,10 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { << " switch (RegNo) {\n" << " default:\n return 0;\n"; for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister::SubRegMap &SRM = Regs[i].getSubRegs(); + const CodeGenRegister::SubRegMap &SRM = Regs[i]->getSubRegs(); if (SRM.empty()) continue; - OS << " case " << getQualifiedName(Regs[i].TheDef) << ":\n"; + OS << " case " << getQualifiedName(Regs[i]->TheDef) << ":\n"; for (CodeGenRegister::SubRegMap::const_iterator ii = SRM.begin(), ie = SRM.end(); ii != ie; ++ii) OS << " if (SubRegNo == " << getQualifiedName(ii->second->TheDef) @@ -806,22 +659,25 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { OS << " }\n}\n\n"; // Emit the constructor of the class... + OS << "extern MCRegisterDesc " << TargetName << "RegDesc[];\n"; + OS << ClassName << "::" << ClassName - << "(int CallFrameSetupOpcode, int CallFrameDestroyOpcode)\n" - << " : TargetRegisterInfo(RegisterDescriptors, " << Regs.size()+1 + << "()\n" + << " : TargetRegisterInfo(" << TargetName << "RegInfoDesc" << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n" - << " SubRegIndexTable,\n" - << " CallFrameSetupOpcode, CallFrameDestroyOpcode,\n" - << " SubregHashTable, SubregHashTableSize,\n" - << " AliasesHashTable, AliasesHashTableSize) {\n" + << " " << TargetName << "SubRegIndexTable) {\n" + << " InitMCRegisterInfo(" << TargetName << "RegDesc, " + << Regs.size()+1 << ");\n" << "}\n\n"; // Collect all information about dwarf register numbers + typedef std::map<Record*, std::vector<int64_t>, LessRecord> DwarfRegNumsMapTy; + DwarfRegNumsMapTy DwarfRegNums; // First, just pull all provided information to the map unsigned maxLength = 0; for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record *Reg = Regs[i].TheDef; + Record *Reg = Regs[i]->TheDef; std::vector<int64_t> RegNums = Reg->getValueAsListOfInts("DwarfNumbers"); maxLength = std::max((size_t)maxLength, RegNums.size()); if (DwarfRegNums.count(Reg)) @@ -864,7 +720,7 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { OS << " };\n}\n\n"; for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record *Reg = Regs[i].TheDef; + Record *Reg = Regs[i]->TheDef; const RecordVal *V = Reg->getValue("DwarfAlias"); if (!V || !V->getValue()) continue; @@ -904,4 +760,16 @@ void RegisterInfoEmitter::run(raw_ostream &OS) { OS << " };\n}\n\n"; OS << "} // End llvm namespace \n"; + OS << "#endif // GET_REGINFO_TARGET_DESC\n\n"; +} + +void RegisterInfoEmitter::run(raw_ostream &OS) { + CodeGenTarget Target(Records); + CodeGenRegBank &RegBank = Target.getRegBank(); + RegBank.computeDerivedInfo(); + + runEnums(OS, Target, RegBank); + runMCDesc(OS, Target, RegBank); + runTargetHeader(OS, Target, RegBank); + runTargetDesc(OS, Target, RegBank); } diff --git a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.h b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.h index 1456b4f..2c01b5c 100644 --- a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.h +++ b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.h @@ -20,19 +20,30 @@ namespace llvm { +class CodeGenRegBank; +class CodeGenTarget; + class RegisterInfoEmitter : public TableGenBackend { RecordKeeper &Records; public: RegisterInfoEmitter(RecordKeeper &R) : Records(R) {} - // run - Output the register file description, returning true on failure. - void run(raw_ostream &o); + // runEnums - Print out enum values for all of the registers. + void runEnums(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank); - // runHeader - Emit a header fragment for the register info emitter. - void runHeader(raw_ostream &o); + // runMCDesc - Print out MC register descriptions. + void runMCDesc(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank); - // runEnums - Print out enum values for all of the registers. - void runEnums(raw_ostream &o); + // runTargetHeader - Emit a header fragment for the register info emitter. + void runTargetHeader(raw_ostream &o, CodeGenTarget &Target, + CodeGenRegBank &Bank); + + // runTargetDesc - Output the target register and register file descriptions. + void runTargetDesc(raw_ostream &o, CodeGenTarget &Target, + CodeGenRegBank &Bank); + + // run - Output the register file description. + void run(raw_ostream &o); }; } // End llvm namespace diff --git a/contrib/llvm/utils/TableGen/SetTheory.cpp b/contrib/llvm/utils/TableGen/SetTheory.cpp index ade1825..21ac09c 100644 --- a/contrib/llvm/utils/TableGen/SetTheory.cpp +++ b/contrib/llvm/utils/TableGen/SetTheory.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "SetTheory.h" +#include "Error.h" #include "Record.h" #include "llvm/Support/Format.h" @@ -155,10 +156,15 @@ struct SequenceOp : public SetTheory::Operator { From = II->getValue(); else throw "From must be an integer: " + Expr->getAsString(); + if (From < 0 || From >= (1 << 30)) + throw "From out of range"; + if (IntInit *II = dynamic_cast<IntInit*>(Expr->arg_begin()[2])) To = II->getValue(); else throw "From must be an integer: " + Expr->getAsString(); + if (To < 0 || To >= (1 << 30)) + throw "To out of range"; RecordKeeper &Records = dynamic_cast<DefInit&>(*Expr->getOperator()).getDef()->getRecords(); @@ -167,7 +173,7 @@ struct SequenceOp : public SetTheory::Operator { for (To += Step; From != To; From += Step) { std::string Name; raw_string_ostream OS(Name); - OS << format(Format.c_str(), From); + OS << format(Format.c_str(), unsigned(From)); Record *Rec = Records.getDef(OS.str()); if (!Rec) throw "No def named '" + Name + "': " + Expr->getAsString(); diff --git a/contrib/llvm/utils/TableGen/SetTheory.h b/contrib/llvm/utils/TableGen/SetTheory.h index e37a76e..6e8313b 100644 --- a/contrib/llvm/utils/TableGen/SetTheory.h +++ b/contrib/llvm/utils/TableGen/SetTheory.h @@ -55,7 +55,7 @@ namespace llvm { class DagInit; -struct Init; +class Init; class Record; class RecordKeeper; diff --git a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp index 928fa4b..978e91a 100644 --- a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp +++ b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp @@ -29,16 +29,20 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS, std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName); std::sort(DefList.begin(), DefList.end(), LessRecord()); - // Open enumeration - OS << "enum {\n"; - - // For each record unsigned N = DefList.size(); + if (N == 0) + return; if (N > 64) { errs() << "Too many (> 64) subtarget features!\n"; exit(1); } + OS << "namespace " << Target << " {\n"; + + // Open enumeration + OS << "enum {\n"; + + // For each record for (unsigned i = 0; i < N;) { // Next record Record *Def = DefList[i]; @@ -57,23 +61,30 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS, // Close enumeration OS << "};\n"; + + OS << "}\n"; } // // FeatureKeyValues - Emit data of all the subtarget features. Used by the // command line. // -void SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { +unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { // Gather and sort all the features std::vector<Record*> FeatureList = Records.getAllDerivedDefinitions("SubtargetFeature"); + + if (FeatureList.empty()) + return 0; + std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName()); // Begin feature table OS << "// Sorted (by key) array of values for CPU features.\n" - << "static const llvm::SubtargetFeatureKV FeatureKV[] = {\n"; + << "llvm::SubtargetFeatureKV " << Target << "FeatureKV[] = {\n"; // For each feature + unsigned NumFeatures = 0; for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) { // Next feature Record *Feature = FeatureList[i]; @@ -88,7 +99,7 @@ void SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { OS << " { " << "\"" << CommandLineName << "\", " << "\"" << Desc << "\", " - << Name << ", "; + << Target << "::" << Name << ", "; const std::vector<Record*> &ImpliesList = Feature->getValueAsListOfDefs("Implies"); @@ -97,12 +108,13 @@ void SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { OS << "0ULL"; } else { for (unsigned j = 0, M = ImpliesList.size(); j < M;) { - OS << ImpliesList[j]->getName(); + OS << Target << "::" << ImpliesList[j]->getName(); if (++j < M) OS << " | "; } } OS << " }"; + ++NumFeatures; // Depending on 'if more in the list' emit comma if ((i + 1) < N) OS << ","; @@ -113,17 +125,14 @@ void SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) { // End feature table OS << "};\n"; - // Emit size of table - OS<<"\nenum {\n"; - OS<<" FeatureKVSize = sizeof(FeatureKV)/sizeof(llvm::SubtargetFeatureKV)\n"; - OS<<"};\n"; + return NumFeatures; } // // CPUKeyValues - Emit data of all the subtarget processors. Used by command // line. // -void SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { +unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { // Gather and sort processor information std::vector<Record*> ProcessorList = Records.getAllDerivedDefinitions("Processor"); @@ -131,7 +140,7 @@ void SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { // Begin processor table OS << "// Sorted (by key) array of values for CPU subtype.\n" - << "static const llvm::SubtargetFeatureKV SubTypeKV[] = {\n"; + << "llvm::SubtargetFeatureKV " << Target << "SubTypeKV[] = {\n"; // For each processor for (unsigned i = 0, N = ProcessorList.size(); i < N;) { @@ -151,7 +160,7 @@ void SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { OS << "0ULL"; } else { for (unsigned j = 0, M = FeatureList.size(); j < M;) { - OS << FeatureList[j]->getName(); + OS << Target << "::" << FeatureList[j]->getName(); if (++j < M) OS << " | "; } } @@ -168,10 +177,7 @@ void SubtargetEmitter::CPUKeyValues(raw_ostream &OS) { // End processor table OS << "};\n"; - // Emit size of table - OS<<"\nenum {\n"; - OS<<" SubTypeKVSize = sizeof(SubTypeKV)/sizeof(llvm::SubtargetFeatureKV)\n"; - OS<<"};\n"; + return ProcessorList.size(); } // @@ -192,11 +198,6 @@ CollectAllItinClasses(raw_ostream &OS, ItinClassesMap[ItinClass->getName()] = i; } - // Emit size of table - OS<<"\nenum {\n"; - OS<<" ItinClassesSize = " << N << "\n"; - OS<<"};\n"; - // Return itinerary class count return N; } @@ -326,9 +327,9 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name << "\"\n" << "namespace " << Name << "Bypass {\n"; - OS << " const unsigned NoBypass = 0;\n"; + OS << " unsigned NoBypass = 0;\n"; for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j) - OS << " const unsigned " << BPs[j]->getName() + OS << " unsigned " << BPs[j]->getName() << " = 1 << " << j << ";\n"; OS << "}\n"; @@ -336,15 +337,17 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, } // Begin stages table - std::string StageTable = "\nstatic const llvm::InstrStage Stages[] = {\n"; + std::string StageTable = "\nllvm::InstrStage " + Target + "Stages[] = {\n"; StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n"; // Begin operand cycle table - std::string OperandCycleTable = "static const unsigned OperandCycles[] = {\n"; + std::string OperandCycleTable = "unsigned " + Target + + "OperandCycles[] = {\n"; OperandCycleTable += " 0, // No itinerary\n"; // Begin pipeline bypass table - std::string BypassTable = "static const unsigned ForwardingPathes[] = {\n"; + std::string BypassTable = "unsigned " + Target + + "ForwardingPathes[] = {\n"; BypassTable += " 0, // No itinerary\n"; unsigned StageCount = 1, OperandCycleCount = 1; @@ -457,12 +460,6 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS, OS << StageTable; OS << OperandCycleTable; OS << BypassTable; - - // Emit size of tables - OS<<"\nenum {\n"; - OS<<" StagesSize = sizeof(Stages)/sizeof(llvm::InstrStage),\n"; - OS<<" OperandCyclesSize = sizeof(OperandCycles)/sizeof(unsigned)\n"; - OS<<"};\n"; } // @@ -491,7 +488,7 @@ EmitProcessorData(raw_ostream &OS, // Begin processor itinerary table OS << "\n"; - OS << "static const llvm::InstrItinerary " << Name << "[] = {\n"; + OS << "llvm::InstrItinerary " << Name << "[] = {\n"; // For each itinerary class std::vector<InstrItinerary> &ItinList = *ProcListIter++; @@ -533,7 +530,8 @@ void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) { // Begin processor table OS << "\n"; OS << "// Sorted (by key) array of itineraries for CPU subtype.\n" - << "static const llvm::SubtargetInfoKV ProcItinKV[] = {\n"; + << "llvm::SubtargetInfoKV " + << Target << "ProcItinKV[] = {\n"; // For each processor for (unsigned i = 0, N = ProcessorList.size(); i < N;) { @@ -559,12 +557,6 @@ void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) { // End processor table OS << "};\n"; - - // Emit size of table - OS<<"\nenum {\n"; - OS<<" ProcItinKVSize = sizeof(ProcItinKV)/" - "sizeof(llvm::SubtargetInfoKV)\n"; - OS<<"};\n"; } // @@ -599,23 +591,27 @@ void SubtargetEmitter::EmitData(raw_ostream &OS) { // ParseFeaturesFunction - Produces a subtarget specific function for parsing // the subtarget features string. // -void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) { +void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS, + unsigned NumFeatures, + unsigned NumProcs) { std::vector<Record*> Features = Records.getAllDerivedDefinitions("SubtargetFeature"); std::sort(Features.begin(), Features.end(), LessRecord()); OS << "// ParseSubtargetFeatures - Parses features string setting specified\n" << "// subtarget options.\n" - << "std::string llvm::"; + << "void llvm::"; OS << Target; - OS << "Subtarget::ParseSubtargetFeatures(const std::string &FS,\n" - << " const std::string &CPU) {\n" + OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n" << " DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n" - << " DEBUG(dbgs() << \"\\nCPU:\" << CPU);\n" - << " SubtargetFeatures Features(FS);\n" - << " Features.setCPUIfNone(CPU);\n" - << " uint64_t Bits = Features.getBits(SubTypeKV, SubTypeKVSize,\n" - << " FeatureKV, FeatureKVSize);\n"; + << " DEBUG(dbgs() << \"\\nCPU:\" << CPU);\n"; + + if (Features.empty()) { + OS << "}\n"; + return; + } + + OS << " uint64_t Bits = ReInitMCSubtargetInfo(CPU, FS);\n"; for (unsigned i = 0; i < Features.size(); i++) { // Next record @@ -625,23 +621,17 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) { const std::string &Attribute = R->getValueAsString("Attribute"); if (Value=="true" || Value=="false") - OS << " if ((Bits & " << Instance << ") != 0) " + OS << " if ((Bits & " << Target << "::" + << Instance << ") != 0) " << Attribute << " = " << Value << ";\n"; else - OS << " if ((Bits & " << Instance << ") != 0 && " << Attribute << - " < " << Value << ") " << Attribute << " = " << Value << ";\n"; - } - - if (HasItineraries) { - OS << "\n" - << " InstrItinerary *Itinerary = (InstrItinerary *)" - << "Features.getInfo(ProcItinKV, ProcItinKVSize);\n" - << " InstrItins = InstrItineraryData(Stages, OperandCycles, " - << "ForwardingPathes, Itinerary);\n"; + OS << " if ((Bits & " << Target << "::" + << Instance << ") != 0 && " + << Attribute << " < " << Value << ") " + << Attribute << " = " << Value << ";\n"; } - OS << " return Features.getCPU();\n" - << "}\n"; + OS << "}\n"; } // @@ -652,22 +642,114 @@ void SubtargetEmitter::run(raw_ostream &OS) { EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS); - OS << "#include \"llvm/Support/Debug.h\"\n"; - OS << "#include \"llvm/Support/raw_ostream.h\"\n"; - OS << "#include \"llvm/Target/SubtargetFeature.h\"\n"; - OS << "#include \"llvm/Target/TargetInstrItineraries.h\"\n\n"; + OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n"; + OS << "#undef GET_SUBTARGETINFO_ENUM\n"; -// Enumeration(OS, "FuncUnit", true); -// OS<<"\n"; -// Enumeration(OS, "InstrItinClass", false); -// OS<<"\n"; + OS << "namespace llvm {\n"; Enumeration(OS, "SubtargetFeature", true); - OS<<"\n"; - FeatureKeyValues(OS); - OS<<"\n"; - CPUKeyValues(OS); - OS<<"\n"; + OS << "} // End llvm namespace \n"; + OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n"; + + OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n"; + OS << "#undef GET_SUBTARGETINFO_MC_DESC\n"; + + OS << "namespace llvm {\n"; +#if 0 + OS << "namespace {\n"; +#endif + unsigned NumFeatures = FeatureKeyValues(OS); + OS << "\n"; + unsigned NumProcs = CPUKeyValues(OS); + OS << "\n"; EmitData(OS); - OS<<"\n"; - ParseFeaturesFunction(OS); + OS << "\n"; +#if 0 + OS << "}\n"; +#endif + + // MCInstrInfo initialization routine. + OS << "static inline void Init" << Target + << "MCSubtargetInfo(MCSubtargetInfo *II, " + << "StringRef TT, StringRef CPU, StringRef FS) {\n"; + OS << " II->InitMCSubtargetInfo(TT, CPU, FS, "; + if (NumFeatures) + OS << Target << "FeatureKV, "; + else + OS << "0, "; + if (NumProcs) + OS << Target << "SubTypeKV, "; + else + OS << "0, "; + if (HasItineraries) { + OS << Target << "ProcItinKV, " + << Target << "Stages, " + << Target << "OperandCycles, " + << Target << "ForwardingPathes, "; + } else + OS << "0, 0, 0, 0, "; + OS << NumFeatures << ", " << NumProcs << ");\n}\n\n"; + + OS << "} // End llvm namespace \n"; + + OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n"; + + OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n"; + OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n"; + + OS << "#include \"llvm/Support/Debug.h\"\n"; + OS << "#include \"llvm/Support/raw_ostream.h\"\n"; + ParseFeaturesFunction(OS, NumFeatures, NumProcs); + + OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n"; + + // Create a TargetSubtargetInfo subclass to hide the MC layer initialization. + OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n"; + OS << "#undef GET_SUBTARGETINFO_HEADER\n"; + + std::string ClassName = Target + "GenSubtargetInfo"; + OS << "namespace llvm {\n"; + OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n" + << " explicit " << ClassName << "(StringRef TT, StringRef CPU, " + << "StringRef FS);\n" + << "};\n"; + OS << "} // End llvm namespace \n"; + + OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n"; + + OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n"; + OS << "#undef GET_SUBTARGETINFO_CTOR\n"; + + OS << "namespace llvm {\n"; + OS << "extern llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n"; + OS << "extern llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n"; + if (HasItineraries) { + OS << "extern llvm::SubtargetInfoKV " << Target << "ProcItinKV[];\n"; + OS << "extern llvm::InstrStage " << Target << "Stages[];\n"; + OS << "extern unsigned " << Target << "OperandCycles[];\n"; + OS << "extern unsigned " << Target << "ForwardingPathes[];\n"; + } + + OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, " + << "StringRef FS)\n" + << " : TargetSubtargetInfo() {\n" + << " InitMCSubtargetInfo(TT, CPU, FS, "; + if (NumFeatures) + OS << Target << "FeatureKV, "; + else + OS << "0, "; + if (NumProcs) + OS << Target << "SubTypeKV, "; + else + OS << "0, "; + if (HasItineraries) { + OS << Target << "ProcItinKV, " + << Target << "Stages, " + << Target << "OperandCycles, " + << Target << "ForwardingPathes, "; + } else + OS << "0, 0, 0, 0, "; + OS << NumFeatures << ", " << NumProcs << ");\n}\n\n"; + OS << "} // End llvm namespace \n"; + + OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n"; } diff --git a/contrib/llvm/utils/TableGen/SubtargetEmitter.h b/contrib/llvm/utils/TableGen/SubtargetEmitter.h index 93055b7..b239f3d 100644 --- a/contrib/llvm/utils/TableGen/SubtargetEmitter.h +++ b/contrib/llvm/utils/TableGen/SubtargetEmitter.h @@ -15,7 +15,7 @@ #define SUBTARGET_EMITTER_H #include "TableGenBackend.h" -#include "llvm/Target/TargetInstrItineraries.h" +#include "llvm/MC/MCInstrItineraries.h" #include <vector> #include <map> #include <string> @@ -30,8 +30,8 @@ class SubtargetEmitter : public TableGenBackend { bool HasItineraries; void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits); - void FeatureKeyValues(raw_ostream &OS); - void CPUKeyValues(raw_ostream &OS); + unsigned FeatureKeyValues(raw_ostream &OS); + unsigned CPUKeyValues(raw_ostream &OS); unsigned CollectAllItinClasses(raw_ostream &OS, std::map<std::string,unsigned> &ItinClassesMap, std::vector<Record*> &ItinClassList); @@ -52,7 +52,8 @@ class SubtargetEmitter : public TableGenBackend { std::vector<std::vector<InstrItinerary> > &ProcList); void EmitProcessorLookup(raw_ostream &OS); void EmitData(raw_ostream &OS); - void ParseFeaturesFunction(raw_ostream &OS); + void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures, + unsigned NumProcs); public: SubtargetEmitter(RecordKeeper &R) : Records(R), HasItineraries(false) {} diff --git a/contrib/llvm/utils/TableGen/TGLexer.cpp b/contrib/llvm/utils/TableGen/TGLexer.cpp index 572c36d..b4b90ff 100644 --- a/contrib/llvm/utils/TableGen/TGLexer.cpp +++ b/contrib/llvm/utils/TableGen/TGLexer.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "TGLexer.h" +#include "Error.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Config/config.h" @@ -35,7 +36,6 @@ SMLoc TGLexer::getLoc() const { return SMLoc::getFromPointer(TokStart); } - /// ReturnError - Set the error to the specified string at the specified /// location. This is defined to always return tgtok::Error. tgtok::TokKind TGLexer::ReturnError(const char *Loc, const Twine &Msg) { @@ -43,16 +43,6 @@ tgtok::TokKind TGLexer::ReturnError(const char *Loc, const Twine &Msg) { return tgtok::Error; } - -void TGLexer::PrintError(const char *Loc, const Twine &Msg) const { - SrcMgr.PrintMessage(SMLoc::getFromPointer(Loc), Msg, "error"); -} - -void TGLexer::PrintError(SMLoc Loc, const Twine &Msg) const { - SrcMgr.PrintMessage(Loc, Msg, "error"); -} - - int TGLexer::getNextChar() { char CurChar = *CurPtr++; switch (CurChar) { diff --git a/contrib/llvm/utils/TableGen/TGLexer.h b/contrib/llvm/utils/TableGen/TGLexer.h index c2a6453..84d328b 100644 --- a/contrib/llvm/utils/TableGen/TGLexer.h +++ b/contrib/llvm/utils/TableGen/TGLexer.h @@ -101,9 +101,6 @@ public: } SMLoc getLoc() const; - - void PrintError(const char *Loc, const Twine &Msg) const; - void PrintError(SMLoc Loc, const Twine &Msg) const; private: /// LexToken - Read the next token and return its code. diff --git a/contrib/llvm/utils/TableGen/TGParser.h b/contrib/llvm/utils/TableGen/TGParser.h index 419a99b..dce7e1d 100644 --- a/contrib/llvm/utils/TableGen/TGParser.h +++ b/contrib/llvm/utils/TableGen/TGParser.h @@ -15,6 +15,7 @@ #define TGPARSER_H #include "TGLexer.h" +#include "Error.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/SourceMgr.h" #include <map> @@ -24,7 +25,7 @@ namespace llvm { class RecordVal; class RecordKeeper; struct RecTy; - struct Init; + class Init; struct MultiClass; struct SubClassReference; struct SubMultiClassReference; @@ -60,7 +61,7 @@ public: bool ParseFile(); bool Error(SMLoc L, const Twine &Msg) const { - Lex.PrintError(L, Msg); + PrintError(L, Msg); return true; } bool TokError(const Twine &Msg) const { diff --git a/contrib/llvm/utils/TableGen/TableGen.cpp b/contrib/llvm/utils/TableGen/TableGen.cpp index 4e4da36..e8eacb8 100644 --- a/contrib/llvm/utils/TableGen/TableGen.cpp +++ b/contrib/llvm/utils/TableGen/TableGen.cpp @@ -26,13 +26,14 @@ #include "DAGISelEmitter.h" #include "DisassemblerEmitter.h" #include "EDEmitter.h" +#include "Error.h" #include "FastISelEmitter.h" -#include "InstrEnumEmitter.h" #include "InstrInfoEmitter.h" #include "IntrinsicEmitter.h" #include "LLVMCConfigurationEmitter.h" #include "NeonEmitter.h" #include "OptParserEmitter.h" +#include "PseudoLoweringEmitter.h" #include "Record.h" #include "RegisterInfoEmitter.h" #include "ARMDecoderEmitter.h" @@ -53,10 +54,13 @@ using namespace llvm; enum ActionType { PrintRecords, GenEmitter, - GenRegisterEnums, GenRegister, GenRegisterHeader, - GenInstrEnums, GenInstrs, GenAsmWriter, GenAsmMatcher, + GenRegisterInfo, + GenInstrInfo, + GenAsmWriter, + GenAsmMatcher, GenARMDecoder, GenDisassembler, + GenPseudoLowering, GenCallingConv, GenClangAttrClasses, GenClangAttrImpl, @@ -92,15 +96,9 @@ namespace { "Print all records to stdout (default)"), clEnumValN(GenEmitter, "gen-emitter", "Generate machine code emitter"), - clEnumValN(GenRegisterEnums, "gen-register-enums", - "Generate enum values for registers"), - clEnumValN(GenRegister, "gen-register-desc", - "Generate a register info description"), - clEnumValN(GenRegisterHeader, "gen-register-desc-header", - "Generate a register info description header"), - clEnumValN(GenInstrEnums, "gen-instr-enums", - "Generate enum values for instructions"), - clEnumValN(GenInstrs, "gen-instr-desc", + clEnumValN(GenRegisterInfo, "gen-register-info", + "Generate registers and register classes info"), + clEnumValN(GenInstrInfo, "gen-instr-info", "Generate instruction descriptions"), clEnumValN(GenCallingConv, "gen-callingconv", "Generate calling convention descriptions"), @@ -110,6 +108,8 @@ namespace { "Generate decoders for ARM/Thumb"), clEnumValN(GenDisassembler, "gen-disassembler", "Generate disassembler"), + clEnumValN(GenPseudoLowering, "gen-pseudo-lowering", + "Generate pseudo instruction lowering"), clEnumValN(GenAsmMatcher, "gen-asm-matcher", "Generate assembly instruction matcher"), clEnumValN(GenDAGISel, "gen-dag-isel", @@ -194,12 +194,6 @@ namespace { } -static SourceMgr SrcMgr; - -void llvm::PrintError(SMLoc ErrorLoc, const Twine &Msg) { - SrcMgr.PrintMessage(ErrorLoc, Msg, "error"); -} - int main(int argc, char **argv) { RecordKeeper Records; @@ -266,20 +260,10 @@ int main(int argc, char **argv) { case GenEmitter: CodeEmitterGen(Records).run(Out.os()); break; - - case GenRegisterEnums: - RegisterInfoEmitter(Records).runEnums(Out.os()); - break; - case GenRegister: + case GenRegisterInfo: RegisterInfoEmitter(Records).run(Out.os()); break; - case GenRegisterHeader: - RegisterInfoEmitter(Records).runHeader(Out.os()); - break; - case GenInstrEnums: - InstrEnumEmitter(Records).run(Out.os()); - break; - case GenInstrs: + case GenInstrInfo: InstrInfoEmitter(Records).run(Out.os()); break; case GenCallingConv: @@ -334,6 +318,9 @@ int main(int argc, char **argv) { case GenDisassembler: DisassemblerEmitter(Records).run(Out.os()); break; + case GenPseudoLowering: + PseudoLoweringEmitter(Records).run(Out.os()); + break; case GenOptParserDefs: OptParserEmitter(Records, true).run(Out.os()); break; @@ -403,13 +390,11 @@ int main(int argc, char **argv) { return 0; } catch (const TGError &Error) { - errs() << argv[0] << ": error:\n"; - PrintError(Error.getLoc(), Error.getMessage()); - + PrintError(Error); } catch (const std::string &Error) { - errs() << argv[0] << ": " << Error << "\n"; + PrintError(Error); } catch (const char *Error) { - errs() << argv[0] << ": " << Error << "\n"; + PrintError(Error); } catch (...) { errs() << argv[0] << ": Unknown unexpected exception occurred.\n"; } diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp index f7518a9..ea3bb70 100644 --- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp +++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp @@ -229,6 +229,30 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, HasFROperands = hasFROperands(); HasVEX_LPrefix = has256BitOperands() || Rec->getValueAsBit("hasVEX_L"); + // Check for 64-bit inst which does not require REX + Is64Bit = false; + // FIXME: Is there some better way to check for In64BitMode? + std::vector<Record*> Predicates = Rec->getValueAsListOfDefs("Predicates"); + for (unsigned i = 0, e = Predicates.size(); i != e; ++i) { + if (Predicates[i]->getName().find("64Bit") != Name.npos) { + Is64Bit = true; + break; + } + } + // FIXME: These instructions aren't marked as 64-bit in any way + Is64Bit |= Rec->getName() == "JMP64pcrel32" || + Rec->getName() == "MASKMOVDQU64" || + Rec->getName() == "POPFS64" || + Rec->getName() == "POPGS64" || + Rec->getName() == "PUSHFS64" || + Rec->getName() == "PUSHGS64" || + Rec->getName() == "REX64_PREFIX" || + Rec->getName().find("VMREAD64") != Name.npos || + Rec->getName().find("VMWRITE64") != Name.npos || + Rec->getName().find("MOV64") != Name.npos || + Rec->getName().find("PUSH64") != Name.npos || + Rec->getName().find("POP64") != Name.npos; + ShouldBeEmitted = true; } @@ -276,7 +300,7 @@ InstructionContext RecognizableInstr::insnContext() const { insnContext = IC_VEX_XS; else insnContext = IC_VEX; - } else if (Name.find("64") != Name.npos || HasREX_WPrefix) { + } else if (Is64Bit || HasREX_WPrefix) { if (HasREX_WPrefix && HasOpSizePrefix) insnContext = IC_64BIT_REXW_OPSIZE; else if (HasOpSizePrefix) diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h index c7ec18c..677d9f0 100644 --- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h +++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h @@ -64,6 +64,8 @@ private: bool HasLockPrefix; /// The isCodeGenOnly filed from the record bool IsCodeGenOnly; + // Whether the instruction has the predicate "Mode64Bit" + bool Is64Bit; /// The instruction name as listed in the tables std::string Name; |