LLVM学习笔记(14)补3

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.0277

                     X86MCRegisterClasses, 80,                        <-- v7.086

                     X86RegUnitRoots,

                     131,                                                                <-- v7.0162

                     X86RegDiffLists,

                     X86LaneMaskLists,

                     X86RegStrings,

                     X86RegClassStrings,

                     X86SubRegIdxLists,

                     7,                                                                     <-- v7.09

                     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.07995)。看来TableGen在后端代码自动化生成方面,还是有比较大的进步的。

猜你喜欢

转载自blog.csdn.net/wuhui_gdnt/article/details/88737212