3.3.6.4.6. X86GenRegisterInfo的构造函数
接下来这段代码生成目标机器的寄存器描述类型的构造函数,对于X86目标机器,这个类型是X86GenRegisterInfo。1387行的EmitRegMappingTables()方法在前面已经被调用来生成LLVM寄存器编码到GCC/GDB寄存器编码的映射表,而这次的调用参数isCtor是true,因此只产生了这些数组的一个extern的声明,像这样:
extern const MCRegisterInfo::DwarfLLVMRegPair X86DwarfFlavour0Dwarf2L[];
extern const unsigned X86DwarfFlavour0Dwarf2LSize;
之所以需要这样,是因为这两块代码由不同的#ifdef宏包含的,将会被引入到不同的源文件中,它们相互间是不可见的。
RegisterInfoEmitter::runTargetDesc(续)
1387 EmitRegMappingTables(OS, Regs, true);
1388
1389 OS << ClassName << "::\n" << ClassName
1390 << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour, unsigned PC)\n"
1391 << " : TargetRegisterInfo(" << TargetName << "RegInfoDesc"
1392 << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n"
1393 << " SubRegIndexNameTable, SubRegIndexLaneMaskTable, 0x";
1394 OS.write_hex(RegBank.CoveringLanes);
1395 OS << ") {\n"
1396 << " InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size() + 1
1397 << ", RA, PC,\n " << TargetName
1398 << "MCRegisterClasses, " << RegisterClasses.size() << ",\n"
1399 << " " << TargetName << "RegUnitRoots,\n"
1400 << " " << RegBank.getNumNativeRegUnits() << ",\n"
1401 << " " << TargetName << "RegDiffLists,\n"
1402 << " " << TargetName << "LaneMaskLists,\n"
1403 << " " << TargetName << "RegStrings,\n"
1404 << " " << TargetName << "RegClassStrings,\n"
1405 << " " << TargetName << "SubRegIdxLists,\n"
1406 << " " << SubRegIndicesSize + 1 << ",\n"
1407 << " " << TargetName << "SubRegIdxRanges,\n"
1408 << " " << TargetName << "RegEncodingTable);\n\n";
1409
1410 EmitRegMapping(OS, Regs, true);
1411
1412 OS << "}\n\n";
1410行的EmitRegMapping()之前已经调用过一次来为InitX86MCRegisterInfo()(X86为例)产生代码,这次产生的代码也是类似的。X86GenRegisterInfo的构造函数看起来就是这个样子:
X86GenRegisterInfo::
X86GenRegisterInfo(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour, unsigned PC,
unsigned HwMode) <-- v7.0增加
: TargetRegisterInfo(X86RegInfoDesc, RegisterClasses, RegisterClasses+80,
SubRegIndexNameTable, SubRegIndexLaneMaskTable, 0xfffffff8, <-- v7.0删除
LaneBitmask(0xFFFFFFE0), RegClassInfos, HwMode) { <-- v7.0增加
InitMCRegisterInfo(X86RegDesc, 246, RA, PC, <-- v7.0是277
X86MCRegisterClasses, 80, <-- v7.0是86
X86RegUnitRoots,
131, <-- v7.0是162
X86RegDiffLists,
X86LaneMaskLists,
X86RegStrings,
X86RegClassStrings,
X86SubRegIdxLists,
7, <-- v7.0是9
X86SubRegIdxRanges,
X86RegEncodingTable);
switch (DwarfFlavour) {
default:
llvm_unreachable("Unknown DWARF flavour");
case 0:
…
}
switch (EHFlavour) {
default:
llvm_unreachable("Unknown DWARF flavour");
case 0:
…
}
switch (DwarfFlavour) {
default:
llvm_unreachable("Unknown DWARF flavour");
case 0:
…
}
switch (EHFlavour) {
default:
llvm_unreachable("Unknown DWARF flavour");
case 0:
…
}
}
在MCRegisterInfo的InitMCRegisterInfo()方法里给出的各种数组都是前面已经生成好的。因此这个方法只要绑定相应的表就好了。
244 void InitMCRegisterInfo(const MCRegisterDesc *D, unsigned NR, unsigned RA,
245 unsigned PC,
246 const MCRegisterClass *C, unsigned NC,
247 const MCPhysReg (*RURoots)[2],
248 unsigned NRU,
249 const MCPhysReg *DL,
250 const unsigned *RUMS,
251 const char *Strings,
252 const char *ClassStrings,
253 const uint16_t *SubIndices,
254 unsigned NumIndices,
255 const SubRegCoveredBits *SubIdxRanges,
256 const uint16_t *RET) {
257 Desc = D;
258 NumRegs = NR;
259 RAReg = RA;
260 PCReg = PC;
261 Classes = C;
262 DiffLists = DL;
263 RegUnitMaskSequences = RUMS;
264 RegStrings = Strings;
265 RegClassStrings = ClassStrings;
266 NumClasses = NC;
267 RegUnitRoots = RURoots;
268 NumRegUnits = NRU;
269 SubRegIndices = SubIndices;
270 NumSubRegIndices = NumIndices;
271 SubRegIdxRanges = SubIdxRanges;
272 RegEncodingTable = RET;
273 }
自此,MCRegisterInfo就可以通过定制的迭代器自由访问TableGen生成的这些差分表了,引导代码生成。
3.3.6.4.7. 被调用者保存寄存器
接着,RegisterInfoEmitter::runTargetDesc()开始处理CalleeSavedRegs定义。CalleeSavedRegs定义在TargetCallingConv.td文件里,由各个目标机器继承来描述其中的调用惯例。
169 class CalleeSavedRegs<dag saves> {
170 dag SaveList = saves;
171
172 // Registers that are also preserved across function calls, but should not be
173 // included in the generated FOO_SaveList array. These registers will be
174 // included in the FOO_RegMask bit mask. This can be used for registers that
175 // are saved automatically, like the SPARC register windows.
176 dag OtherPreserved;
177 }
在X86CallingConv.td文件里定义了这些X86目标机器所支持的调用惯例(v7.0增加了若干新的调用惯例,这里不做列出):
756 def CSR_NoRegs : CalleeSavedRegs<(add)>;
757
758 def CSR_32 : CalleeSavedRegs<(add ESI, EDI, EBX, EBP)>;
759 def CSR_64 : CalleeSavedRegs<(add RBX, R12, R13, R14, R15, RBP)>;
760
761 def CSR_32EHRet : CalleeSavedRegs<(add EAX, EDX, CSR_32)>;
762 def CSR_64EHRet : CalleeSavedRegs<(add RAX, RDX, CSR_64)>;
763
764 def CSR_Win64 : CalleeSavedRegs<(add RBX, RBP, RDI, RSI, R12, R13, R14, R15,
765 (sequence "XMM%u", 6, 15))>;
766
767 // All GPRs - except r11
768 def CSR_64_RT_MostRegs : CalleeSavedRegs<(add CSR_64, RAX, RCX, RDX, RSI, RDI,
769 R8, R9, R10, RSP)>;
770
771 // All registers - except r11
772 def CSR_64_RT_AllRegs: CalleeSavedRegs<(add CSR_64_RT_MostRegs,
773 (sequence "XMM%u", 0, 15))>;
774 def CSR_64_RT_AllRegs_AVX : CalleeSavedRegs<(add CSR_64_RT_MostRegs,
775 (sequence "YMM%u", 0, 15))>;
776
777 def CSR_64_MostRegs : CalleeSavedRegs<(add RBX, RCX, RDX, RSI, RDI, R8, R9, R10,
778 R11, R12, R13, R14, R15, RBP,
779 (sequence "XMM%u", 0, 15))>;
780
781 def CSR_64_AllRegs : CalleeSavedRegs<(add CSR_64_MostRegs, RAX, RSP,
782 (sequence "XMM%u", 16, 31))>;
783 def CSR_64_AllRegs_AVX : CalleeSavedRegs<(sub (add CSR_64_MostRegs, RAX, RSP,
784 (sequence "YMM%u", 0, 31)),
785 (sequence "XMM%u", 0, 15))>;
786
787 // Standard C + YMM6-15
788 def CSR_Win64_Intel_OCL_BI_AVX : CalleeSavedRegs<(add RBX, RBP, RDI, RSI, R12,
789 R13, R14, R15,
790 (sequence "YMM%u", 6, 15))>;
791
792 def CSR_Win64_Intel_OCL_BI_AVX512 : CalleeSavedRegs<(add RBX, RBP, RDI, RSI,
793 R12, R13, R14, R15,
794 (sequence "ZMM%u", 6, 21),
795 K4, K5, K6, K7)>;
796 //Standard C + XMM 8-15
797 def CSR_64_Intel_OCL_BI : CalleeSavedRegs<(add CSR_64,
798 (sequence "XMM%u", 8, 15))>;
799
800 //Standard C + YMM 8-15
801 def CSR_64_Intel_OCL_BI_AVX : CalleeSavedRegs<(add CSR_64,
802 (sequence "YMM%u", 8, 15))>;
803
804 def CSR_64_Intel_OCL_BI_AVX512 : CalleeSavedRegs<(add RBX, RDI, RSI, R14, R15,
805 (sequence "ZMM%u", 16, 31),
806 K4, K5, K6, K7)>;
有了之前对SetTheory类的了解,上面这些定义应该都不难理解(CalleeSavedRegs的SaveList域被注册为使用FieldExpander展开)。1420行执行上面定义中出现的add,sequence等dag操作符,展开结果保存在Regs容器。
RegisterInfoEmitter::runTargetDesc(续)
1415 // Emit CalleeSavedRegs information.
1416 std::vector<Record*> CSRSets =
1417 Records.getAllDerivedDefinitions("CalleeSavedRegs");
1418 for (unsigned i = 0, e = CSRSets.size(); i != e; ++i) {
1419 Record *CSRSet = CSRSets[i];
1420 const SetTheory::RecVec *Regs = RegBank.getSets().expand(CSRSet);
1421 assert(Regs && "Cannot expand CalleeSavedRegs instance");
1422
1423 // Emit the *_SaveList list of callee-saved registers.
1424 OS << "static const MCPhysReg " << CSRSet->getName()
1425 << "_SaveList[] = { ";
1426 for (unsigned r = 0, re = Regs->size(); r != re; ++r)
1427 OS << getQualifiedName((*Regs)[r]) << ", ";
1428 OS << "0 };\n";
1429
1430 // Emit the *_RegMask bit mask of call-preserved registers.
1431 BitVector Covered = RegBank.computeCoveredRegisters(*Regs);
1432
1433 // Check for an optional OtherPreserved set.
1434 // Add those registers to RegMask, but not to SaveList.
1435 if (DagInit *OPDag =
1436 dyn_cast<DagInit>(CSRSet->getValueInit("OtherPreserved"))) {
1437 SetTheory::RecSet OPSet;
1438 RegBank.getSets().evaluate(OPDag, OPSet, CSRSet->getLoc());
1439 Covered |= RegBank.computeCoveredRegisters(
1440 ArrayRef<Record*>(OPSet.begin(), OPSet.end()));
1441 }
1442
1443 OS << "static const uint32_t " << CSRSet->getName()
1444 << "_RegMask[] = { ";
1445 printBitVectorAsHex(OS, Covered, 32);
1446 OS << "};\n";
1447 }
1448 OS << "\n\n";
1449
1450 OS << "ArrayRef<const uint32_t *> " << ClassName
1451 << "::getRegMasks() const {\n";
1452 OS << " static const uint32_t *Masks[] = {\n";
1453 for (Record *CSRSet : CSRSets)
1454 OS << " " << CSRSet->getName() << "_RegMask, \n";
1455 OS << " nullptr\n };\n";
1456 OS << " return ArrayRef<const uint32_t *>(Masks, (size_t)" << CSRSets.size()
1457 << ");\n";
1458 OS << "}\n\n";
1459
1460 OS << "ArrayRef<const char *> " << ClassName
1461 << "::getRegMaskNames() const {\n";
1462 OS << " static const char *Names[] = {\n";
1463 for (Record *CSRSet : CSRSets)
1464 OS << " " << '"' << CSRSet->getName() << '"' << ",\n";
1465 OS << " nullptr\n };\n";
1466 OS << " return ArrayRef<const char *>(Names, (size_t)" << CSRSets.size()
1467 << ");\n";
1468 OS << "}\n\n";
1469
1470 OS << "} // End llvm namespace\n";
1471 OS << "#endif // GET_REGINFO_TARGET_DESC\n\n";
1472 }
1424~1428行首先输出一个以0结尾的寄存器保存列表的定义,比如:
static const MCPhysReg CSR_32_SaveList[] = { X86::ESI, X86::EDI, X86::EBX, X86::EBP, 0 };
然后在1431行通过下面的方法找出被这组寄存器所覆盖的寄存器集合(包括子寄存器,完全覆盖的上级寄存器),这个集合由选中寄存器的EnumValue组成的位图来表示。
2082 BitVector CodeGenRegBank::computeCoveredRegisters(ArrayRef<Record*> Regs) {
2083 SetVector<const CodeGenRegister*> Set;
2084
2085 // First add Regs with all sub-registers.
2086 for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
2087 CodeGenRegister *Reg = getReg(Regs[i]);
2088 if (Set.insert(Reg))
2089 // Reg is new, add all sub-registers.
2090 // The pre-ordering is not important here.
2091 Reg->addSubRegsPreOrder(Set, *this);
2092 }
2093
2094 // Second, find all super-registers that are completely covered by the set.
2095 for (unsigned i = 0; i != Set.size(); ++i) {
2096 const CodeGenRegister::SuperRegList &SR = Set[i]->getSuperRegs();
2097 for (unsigned j = 0, e = SR.size(); j != e; ++j) {
2098 const CodeGenRegister *Super = SR[j];
2099 if (!Super->CoveredBySubRegs || Set.count(Super))
2100 continue;
2101 // This new super-register is covered by its sub-registers.
2102 bool AllSubsInSet = true;
2103 const CodeGenRegister::SubRegMap &SRM = Super->getSubRegs();
2104 for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(),
2105 E = SRM.end(); I != E; ++I)
2106 if (!Set.count(I->second)) {
2107 AllSubsInSet = false;
2108 break;
2109 }
2110 // All sub-registers in Set, add Super as well.
2111 // We will visit Super later to recheck its super-registers.
2112 if (AllSubsInSet)
2113 Set.insert(Super);
2114 }
2115 }
2116
2117 // Convert to BitVector.
2118 BitVector BV(Registers.size() + 1);
2119 for (unsigned i = 0, e = Set.size(); i != e; ++i)
2120 BV.set(Set[i]->EnumValue);
2121 return BV;
2122 }
如果CalleeSavedRegs定义中还指定了OtherPreserved,这部分内容也要考虑进来(1435~1441行)。在1443~1447行输出这个被涵盖寄存器的集合位图,比如:
static const uint32_t CSR_32_RegMask[] = { 0x20b0c1f0, 0x00006000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, };
寄存器的EnumValue值决定了该寄存器在这个位图的位置(第几个比特)。
在输出了所有调用惯例所需的SaveLists与RegMask数组后,TableGen定义了两个方法,一个绑定了上面的RegMask定义,另一个则给出这些调用惯例的名字。像这样:
ArrayRef<const uint32_t *> X86GenRegisterInfo::getRegMasks() const {
static const uint32_t *Masks[] = {
CSR_32_RegMask,
CSR_32EHRet_RegMask,
CSR_64_RegMask,
CSR_64EHRet_RegMask,
CSR_64_AllRegs_RegMask,
CSR_64_AllRegs_AVX_RegMask,
CSR_64_Intel_OCL_BI_RegMask,
CSR_64_Intel_OCL_BI_AVX_RegMask,
CSR_64_Intel_OCL_BI_AVX512_RegMask,
CSR_64_MostRegs_RegMask,
CSR_64_RT_AllRegs_RegMask,
CSR_64_RT_AllRegs_AVX_RegMask,
CSR_64_RT_MostRegs_RegMask,
CSR_NoRegs_RegMask,
CSR_Win64_RegMask,
CSR_Win64_Intel_OCL_BI_AVX_RegMask,
CSR_Win64_Intel_OCL_BI_AVX512_RegMask,
nullptr
};
return ArrayRef<const uint32_t *>(Masks, (size_t)17);
}
ArrayRef<const char *> X86GenRegisterInfo::getRegMaskNames() const {
static const char *Names[] = {
"CSR_32",
"CSR_32EHRet",
"CSR_64",
"CSR_64EHRet",
"CSR_64_AllRegs",
"CSR_64_AllRegs_AVX",
"CSR_64_Intel_OCL_BI",
"CSR_64_Intel_OCL_BI_AVX",
"CSR_64_Intel_OCL_BI_AVX512",
"CSR_64_MostRegs",
"CSR_64_RT_AllRegs",
"CSR_64_RT_AllRegs_AVX",
"CSR_64_RT_MostRegs",
"CSR_NoRegs",
"CSR_Win64",
"CSR_Win64_Intel_OCL_BI_AVX",
"CSR_Win64_Intel_OCL_BI_AVX512",
nullptr
};
return ArrayRef<const char *>(Names, (size_t)17);
}
至此,X86GenRegisterInfo.inc文件就结束了。在LLVM-3.6版本下,这个文件有7091行,对比版本3.3,那时大概是4796行(v7.0是7995行)。看来TableGen在后端代码自动化生成方面,还是有比较大的进步的。