diff --git a/llvm/include/llvm/MC/MCRegisterInfo.h b/llvm/include/llvm/MC/MCRegisterInfo.h index 4d59780b5cc7..71bdef283632 100644 --- a/llvm/include/llvm/MC/MCRegisterInfo.h +++ b/llvm/include/llvm/MC/MCRegisterInfo.h @@ -127,6 +127,16 @@ struct MCRegisterDesc { class MCRegisterInfo { public: typedef const MCRegisterClass *regclass_iterator; + + /// DwarfLLVMRegPair - Emitted by tablegen so Dwarf<->LLVM reg mappings can be + /// performed with a binary search. + struct DwarfLLVMRegPair { + unsigned FromReg; + unsigned ToReg; + + bool operator==(unsigned Reg) const { return FromReg == Reg; } + bool operator<(unsigned Reg) const { return FromReg < Reg; } + }; private: const MCRegisterDesc *Desc; // Pointer to the descriptor array unsigned NumRegs; // Number of entries in the array @@ -137,10 +147,15 @@ private: const uint16_t *SubRegIndices; // Pointer to the subreg lookup // array. unsigned NumSubRegIndices; // Number of subreg indices. - DenseMap L2DwarfRegs; // LLVM to Dwarf regs mapping - DenseMap EHL2DwarfRegs; // LLVM to Dwarf regs mapping EH - DenseMap Dwarf2LRegs; // Dwarf to LLVM regs mapping - DenseMap EHDwarf2LRegs; // Dwarf to LLVM regs mapping EH + + unsigned L2DwarfRegsSize; + unsigned EHL2DwarfRegsSize; + unsigned Dwarf2LRegsSize; + unsigned EHDwarf2LRegsSize; + const DwarfLLVMRegPair *L2DwarfRegs; // LLVM to Dwarf regs mapping + const DwarfLLVMRegPair *EHL2DwarfRegs; // LLVM to Dwarf regs mapping EH + const DwarfLLVMRegPair *Dwarf2LRegs; // Dwarf to LLVM regs mapping + const DwarfLLVMRegPair *EHDwarf2LRegs; // Dwarf to LLVM regs mapping EH DenseMap L2SEHRegs; // LLVM to SEH regs mapping public: @@ -161,24 +176,32 @@ public: NumSubRegIndices = NumIndices; } - /// mapLLVMRegToDwarfReg - Used to initialize LLVM register to Dwarf + /// mapLLVMRegsToDwarfRegs - Used to initialize LLVM register to Dwarf /// register number mapping. Called by TableGen auto-generated routines. /// *DO NOT USE*. - void mapLLVMRegToDwarfReg(unsigned LLVMReg, int DwarfReg, bool isEH) { - if (isEH) - EHL2DwarfRegs[LLVMReg] = DwarfReg; - else - L2DwarfRegs[LLVMReg] = DwarfReg; + void mapLLVMRegsToDwarfRegs(const DwarfLLVMRegPair *Map, unsigned Size, + bool isEH) { + if (isEH) { + EHL2DwarfRegs = Map; + EHL2DwarfRegsSize = Size; + } else { + L2DwarfRegs = Map; + L2DwarfRegsSize = Size; + } } - /// mapDwarfRegToLLVMReg - Used to initialize Dwarf register to LLVM + /// mapDwarfRegsToLLVMRegs - Used to initialize Dwarf register to LLVM /// register number mapping. Called by TableGen auto-generated routines. /// *DO NOT USE*. - void mapDwarfRegToLLVMReg(unsigned DwarfReg, unsigned LLVMReg, bool isEH) { - if (isEH) - EHDwarf2LRegs[DwarfReg] = LLVMReg; - else - Dwarf2LRegs[DwarfReg] = LLVMReg; + void mapDwarfRegsToLLVMRegs(const DwarfLLVMRegPair *Map, unsigned Size, + bool isEH) { + if (isEH) { + EHDwarf2LRegs = Map; + EHDwarf2LRegsSize = Size; + } else { + Dwarf2LRegs = Map; + Dwarf2LRegsSize = Size; + } } /// mapLLVMRegToSEHReg - Used to initialize LLVM register to SEH register @@ -289,21 +312,24 @@ public: /// parameter allows targets to use different numberings for EH info and /// debugging info. int getDwarfRegNum(unsigned RegNum, bool isEH) const { - const DenseMap &M = isEH ? EHL2DwarfRegs : L2DwarfRegs; - const DenseMap::const_iterator I = M.find(RegNum); - if (I == M.end()) return -1; - return I->second; + const DwarfLLVMRegPair *M = isEH ? EHL2DwarfRegs : L2DwarfRegs; + unsigned Size = isEH ? EHL2DwarfRegsSize : L2DwarfRegsSize; + + const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, RegNum); + if (I == M+Size || I->FromReg != RegNum) + return -1; + return I->ToReg; } /// getLLVMRegNum - Map a dwarf register back to a target register. /// int getLLVMRegNum(unsigned RegNum, bool isEH) const { - const DenseMap &M = isEH ? EHDwarf2LRegs : Dwarf2LRegs; - const DenseMap::const_iterator I = M.find(RegNum); - if (I == M.end()) { - llvm_unreachable("Invalid RegNum"); - } - return I->second; + const DwarfLLVMRegPair *M = isEH ? EHDwarf2LRegs : Dwarf2LRegs; + unsigned Size = isEH ? EHDwarf2LRegsSize : Dwarf2LRegsSize; + + const DwarfLLVMRegPair *I = std::lower_bound(M, M+Size, RegNum); + assert(I != M+Size && I->FromReg == RegNum && "Invalid RegNum"); + return I->ToReg; } /// getSEHRegNum - Map a target register to an equivalent SEH register diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/llvm/utils/TableGen/RegisterInfoEmitter.cpp index 338e6aebdb55..a5fe7562dd95 100644 --- a/llvm/utils/TableGen/RegisterInfoEmitter.cpp +++ b/llvm/utils/TableGen/RegisterInfoEmitter.cpp @@ -118,11 +118,11 @@ RegisterInfoEmitter::runEnums(raw_ostream &OS, OS << "#endif // GET_REGINFO_ENUM\n\n"; } -void -RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS, - const std::vector &Regs, - bool isCtor) { +void +RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, + const std::vector &Regs, + bool isCtor) { // Collect all information about dwarf register numbers typedef std::map, LessRecord> DwarfRegNumsMapTy; DwarfRegNumsMapTy DwarfRegNums; @@ -148,38 +148,52 @@ RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS, for (unsigned i = I->second.size(), e = maxLength; i != e; ++i) I->second.push_back(-1); + std::string Namespace = Regs[0]->TheDef->getValueAsString("Namespace"); + + OS << "// " << Namespace << " Dwarf<->LLVM register mappings.\n"; + // Emit reverse information about the dwarf register numbers. for (unsigned j = 0; j < 2; ++j) { - OS << " switch ("; - if (j == 0) - OS << "DwarfFlavour"; - else - OS << "EHFlavour"; - OS << ") {\n" - << " default:\n" - << " llvm_unreachable(\"Unknown DWARF flavour\");\n"; - for (unsigned i = 0, e = maxLength; i != e; ++i) { - OS << " case " << i << ":\n"; - for (DwarfRegNumsMapTy::iterator - I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) { - int DwarfRegNo = I->second[i]; - if (DwarfRegNo < 0) - continue; - OS << " "; - if (!isCtor) - OS << "RI->"; - OS << "mapDwarfRegToLLVMReg(" << DwarfRegNo << ", " - << getQualifiedName(I->first) << ", "; - if (j == 0) - OS << "false"; - else - OS << "true"; - OS << " );\n"; + OS << "extern const MCRegisterInfo::DwarfLLVMRegPair " << Namespace; + OS << (j == 0 ? "DwarfFlavour" : "EHFlavour"); + OS << i << "Dwarf2L[]"; + + if (!isCtor) { + OS << " = {\n"; + + // Store the mapping sorted by the LLVM reg num so lookup can be done + // with a binary search. + std::map Dwarf2LMap; + for (DwarfRegNumsMapTy::iterator + I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) { + int DwarfRegNo = I->second[i]; + if (DwarfRegNo < 0) + continue; + Dwarf2LMap[DwarfRegNo] = I->first; + } + + for (std::map::iterator + I = Dwarf2LMap.begin(), E = Dwarf2LMap.end(); I != E; ++I) + OS << " { " << I->first << "U, " << getQualifiedName(I->second) + << " },\n"; + + OS << "};\n"; + } else { + OS << ";\n"; } - OS << " break;\n"; + + // We have to store the size in a const global, it's used in multiple + // places. + OS << "extern const unsigned " << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "Dwarf2LSize"; + if (!isCtor) + OS << " = sizeof(" << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i + << "Dwarf2L)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n"; + else + OS << ";\n\n"; } - OS << " }\n"; } for (unsigned i = 0, e = Regs.size(); i != e; ++i) { @@ -193,6 +207,93 @@ RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS, DwarfRegNums[Reg] = DwarfRegNums[Alias]; } + // Emit information about the dwarf register numbers. + for (unsigned j = 0; j < 2; ++j) { + for (unsigned i = 0, e = maxLength; i != e; ++i) { + OS << "extern const MCRegisterInfo::DwarfLLVMRegPair " << Namespace; + OS << (j == 0 ? "DwarfFlavour" : "EHFlavour"); + OS << i << "L2Dwarf[]"; + if (!isCtor) { + OS << " = {\n"; + // Store the mapping sorted by the Dwarf reg num so lookup can be done + // with a binary search. + for (DwarfRegNumsMapTy::iterator + I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) { + int RegNo = I->second[i]; + if (RegNo == -1) // -1 is the default value, don't emit a mapping. + continue; + + OS << " { " << getQualifiedName(I->first) << ", " << RegNo + << "U },\n"; + } + OS << "};\n"; + } else { + OS << ";\n"; + } + + // We have to store the size in a const global, it's used in multiple + // places. + OS << "extern const unsigned " << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2DwarfSize"; + if (!isCtor) + OS << " = sizeof(" << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i + << "L2Dwarf)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n"; + else + OS << ";\n\n"; + } + } +} + +void +RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS, + const std::vector &Regs, + bool isCtor) { + // Emit the initializer so the tables from EmitRegMappingTables get wired up + // to the MCRegisterInfo object. + unsigned maxLength = 0; + for (unsigned i = 0, e = Regs.size(); i != e; ++i) { + Record *Reg = Regs[i]->TheDef; + maxLength = std::max((size_t)maxLength, + Reg->getValueAsListOfInts("DwarfNumbers").size()); + } + + if (!maxLength) + return; + + std::string Namespace = Regs[0]->TheDef->getValueAsString("Namespace"); + + // Emit reverse information about the dwarf register numbers. + for (unsigned j = 0; j < 2; ++j) { + OS << " switch ("; + if (j == 0) + OS << "DwarfFlavour"; + else + OS << "EHFlavour"; + OS << ") {\n" + << " default:\n" + << " llvm_unreachable(\"Unknown DWARF flavour\");\n"; + + for (unsigned i = 0, e = maxLength; i != e; ++i) { + OS << " case " << i << ":\n"; + OS << " "; + if (!isCtor) + OS << "RI->"; + std::string Tmp; + raw_string_ostream(Tmp) << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i + << "Dwarf2L"; + OS << "mapDwarfRegsToLLVMRegs(" << Tmp << ", " << Tmp << "Size, "; + if (j == 0) + OS << "false"; + else + OS << "true"; + OS << ");\n"; + OS << " break;\n"; + } + OS << " }\n"; + } + // Emit information about the dwarf register numbers. for (unsigned j = 0; j < 2; ++j) { OS << " switch ("; @@ -206,24 +307,19 @@ RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS, for (unsigned i = 0, e = maxLength; i != e; ++i) { OS << " case " << i << ":\n"; - // Sort by name to get a stable order. - for (DwarfRegNumsMapTy::iterator - I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) { - int RegNo = I->second[i]; - if (RegNo == -1) // -1 is the default value, don't emit a mapping. - continue; - - OS << " "; - if (!isCtor) - OS << "RI->"; - OS << "mapLLVMRegToDwarfReg(" << getQualifiedName(I->first) << ", " - << RegNo << ", "; - if (j == 0) + OS << " "; + if (!isCtor) + OS << "RI->"; + std::string Tmp; + raw_string_ostream(Tmp) << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i + << "L2Dwarf"; + OS << "mapLLVMRegsToDwarfRegs(" << Tmp << ", " << Tmp << "Size, "; + if (j == 0) OS << "false"; else OS << "true"; - OS << " );\n"; - } + OS << ");\n"; OS << " break;\n"; } OS << " }\n"; @@ -448,6 +544,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, << "SubRegTable;\n}\n\n"; } + EmitRegMappingTables(OS, Regs, false); + // MCRegisterInfo initialization routine. OS << "static inline void Init" << TargetName << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, " @@ -872,6 +970,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "extern const uint16_t *get" << TargetName << "SubRegTable();\n"; + EmitRegMappingTables(OS, Regs, true); + OS << ClassName << "::\n" << ClassName << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour)\n" << " : TargetRegisterInfo(" << TargetName << "RegInfoDesc" diff --git a/llvm/utils/TableGen/RegisterInfoEmitter.h b/llvm/utils/TableGen/RegisterInfoEmitter.h index 0fd4d079ebc0..2e6b64aa587a 100644 --- a/llvm/utils/TableGen/RegisterInfoEmitter.h +++ b/llvm/utils/TableGen/RegisterInfoEmitter.h @@ -50,6 +50,9 @@ public: private: void EmitRegMapping(raw_ostream &o, const std::vector &Regs, bool isCtor); + void EmitRegMappingTables(raw_ostream &o, + const std::vector &Regs, + bool isCtor); void EmitRegClasses(raw_ostream &OS, CodeGenTarget &Target); };