1. 程式人生 > >LLVM學習筆記(47)

LLVM學習筆記(47)

3.7.3. TableGen的處理

3.7.3.1. 基本資料結構

在檔案CallingConvLower.h中定義了兩個基本的資料結構:CCValAssign與CCState。CCValAssign在編譯期間用於記錄引數或返回值向暫存器或棧賦值的細節,它定義了以下成員:

32        class CCValAssign {

33        public:

34       

  enum LocInfo {

35            Full,      // The value fills the full location.

36            SExt,      // The value is sign extended in the location.

37            ZExt,      // The value is zero extended in the location.

38            AExt,      // The value is extended with undefined upper bits.

39       

    SExtUpper, // The value is in the upper bits of the location and should be

40                       // sign extended when retrieved.

41            ZExtUpper, // The value is in the upper bits of the location and should be

42                       // zero extended when retrieved.

43            AExtUpper, // The value is in the upper bits of the location and should be

44                       // extended with undefined upper bits when retrieved.

45            BCvt,      // The value is bit-converted in the location.

46            VExt,      // The value is vector-widened in the location.

47                       // FIXME: Not implemented yet. Code that uses AExt to mean

48                       // vector-widen should be fixed to use VExt instead.

49            FPExt,     // The floating-point value is fp-extended in the location.

50            Indirect   // The location contains pointer to the value.

51            // TODO: a subset of the value is in the location.

52          };

53       

54        private:

55          /// ValNo - This is the value number begin assigned (e.g. an argument number).

56          unsigned ValNo;

57       

58          /// Loc is either a stack offset or a register number.

59          unsigned Loc;

60       

61          /// isMem - True if this is a memory loc, false if it is a register loc.

62          unsigned isMem : 1;

63       

64          /// isCustom - True if this arg/retval requires special handling.

65          unsigned isCustom : 1;

66       

67          /// Information about how the value is assigned.

68          LocInfo HTP : 6;

69       

70          /// ValVT - The type of the value being assigned.

71          MVT ValVT;

72       

73          /// LocVT - The type of the location being assigned to.

74          MVT LocVT;

其中列舉型別LocInfo用於描述對該記憶體的佔用形式,是否全佔滿、符號擴充套件、還是零擴充套件等。

CCState則是用於輔助引數與返回值的降級,CCState定義了以下成員:

189      typedef enum { Unknown, Prologue, Call } ParmContext;

190     

191      /// CCState - This class holds information needed while lowering arguments and

192      /// return values.  It captures which registers are already assigned and which

193      /// stack slots are used.  It provides accessors to allocate these values.

194      class CCState {

195      private:

196        CallingConv::ID CallingConv;

197        bool IsVarArg;

198        MachineFunction &MF;

199        const TargetRegisterInfo &TRI;

200        SmallVectorImpl<CCValAssign> &Locs;

201        LLVMContext &Context;

202     

203        unsigned StackOffset;

204        SmallVector<uint32_t, 16> UsedRegs;

205        SmallVector<CCValAssign, 4> PendingLocs;

206     

207        // ByValInfo and SmallVector<ByValInfo, 4> ByValRegs:

208        //

209        // Vector of ByValInfo instances (ByValRegs) is introduced for byval registers

210        // tracking.

211        // Or, in another words it tracks byval parameters that are stored in

212        // general purpose registers.

213        //

214        // For 4 byte stack alignment,

215        // instance index means byval parameter number in formal

216        // arguments set. Assume, we have some "struct_type" with size = 4 bytes,

217        // then, for function "foo":

218        //

219        // i32 foo(i32 %p, %struct_type* %r, i32 %s, %struct_type* %t)

220        //

221        // ByValRegs[0] describes how "%r" is stored (Begin == r1, End == r2)

222        // ByValRegs[1] describes how "%t" is stored (Begin == r3, End == r4).

223        //

224        // In case of 8 bytes stack alignment,

225        // ByValRegs may also contain information about wasted registers.

226        // In function shown above, r3 would be wasted according to AAPCS rules.

227        // And in that case ByValRegs[1].Waste would be "true".

228        // ByValRegs vector size still would be 2,

229        // while "%t" goes to the stack: it wouldn't be described in ByValRegs.

230        //

231        // Supposed use-case for this collection:

232        // 1. Initially ByValRegs is empty, InRegsParamsProcessed is 0.

233        // 2. HandleByVal fillups ByValRegs.

234        // 3. Argument analysis (LowerFormatArguments, for example). After

235        // some byval argument was analyzed, InRegsParamsProcessed is increased.

236        struct ByValInfo {

237          ByValInfo(unsigned B, unsigned E, bool IsWaste = false) :

238            Begin(B), End(E), Waste(IsWaste) {}

239          // First register allocated for current parameter.

240          unsigned Begin;

241     

242          // First after last register allocated for current parameter.

243          unsigned End;

244     

245         // Means that current range of registers doesn't belong to any

246          // parameters. It was wasted due to stack alignment rules.

247          // For more information see:

248          // AAPCS, 5.5 Parameter Passing, Stage C, C.3.

249          bool Waste;

250        };

251        SmallVector<ByValInfo, 4 > ByValRegs;

252     

253        // InRegsParamsProcessed - shows how many instances of ByValRegs was proceed

254        // during argument analysis.

255        unsigned InRegsParamsProcessed;

256     

257      protected:

258        ParmContext CallOrPrologue;

CCState只定義了一個建構函式,它的成員Locs必須是外面傳入容器,CCState只是代管。

28        CCState::CCState(CallingConv::ID CC, bool isVarArg, MachineFunction &mf,

29                         SmallVectorImpl<CCValAssign> &locs, LLVMContext &C)

30            : CallingConv(CC), IsVarArg(isVarArg), MF(mf),

31              TRI(*MF.getSubtarget().getRegisterInfo()), Locs(locs), Context(C),

32              CallOrPrologue(Unknown) {

33          // No stack is used.

34          StackOffset = 0;

35       

36          clearByValRegsInfo();

37          UsedRegs.resize((TRI.getNumRegs()+31)/32);

38        }

其中StackOffset記錄所代表函式呼叫引數使用棧的大小,UsedRegs則記錄暫存器的使用情況。

​​​​​​​3.7.1.2. 程式碼的生成

TableGen程式碼生成的入口是EmitCallingConv方法。

279      void EmitCallingConv(RecordKeeper &RK, raw_ostream &OS) {

280        emitSourceFileHeader("Calling Convention Implementation Fragment", OS);

281        CallingConvEmitter(RK).run(OS);

282      }

類似的,主要工作由CallingConvEmitter的run方法完成(CallingConvEmitter建構函式本身是平凡的)。

37        void CallingConvEmitter::run(raw_ostream &O) {

38          std::vector<Record*> CCs = Records.getAllDerivedDefinitions("CallingConv");

39       

40          // Emit prototypes for all of the non-custom CC's so that they can forward ref

41          // each other.

42          for (unsigned i = 0, e = CCs.size(); i != e; ++i) {

43            if (!CCs[i]->getValueAsBit("Custom")) {

44              O << "static bool " << CCs[i]->getName()

45                << "(unsigned ValNo, MVT ValVT,\n"

46                << std::string(CCs[i]->getName().size() + 13, ' ')

47                << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"

48                << std::string(CCs[i]->getName().size() + 13, ' ')

49                << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n";

50            }

51          }

52       

53          // Emit each non-custom calling convention description in full.

54          for (unsigned i = 0, e = CCs.size(); i != e; ++i) {

55            if (!CCs[i]->getValueAsBit("Custom"))

56              EmitCallingConv(CCs[i], O);

57          }

58        }

在42行迴圈,如果當前CallingConv定義中沒有設定Custom位(Custom表示該呼叫慣例由同名的定製函式處理),就為它輸出一個函式宣告,形如:

static bool CC_X86_64_C(unsigned ValNo, MVT ValVT,

                        MVT LocVT, CCValAssign::LocInfo LocInfo,

                        ISD::ArgFlagsTy ArgFlags, CCState &State);

而這些CallingConv定義的處理方法則由56行的EmitCallingConv方法輸出。

61        void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) {

62          ListInit *CCActions = CC->getValueAsListInit("Actions");

63          Counter = 0;

64       

65          O << "\n\nstatic bool " << CC->getName()

66            << "(unsigned ValNo, MVT ValVT,\n"

67            << std::string(CC->getName().size()+13, ' ')

68            << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"

69            << std::string(CC->getName().size()+13, ' ')

70            << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n";

71          // Emit all of the actions, in order.

72          for (unsigned i = 0, e = CCActions->size(); i != e; ++i) {

73            O << "\n";

74            EmitAction(CCActions->getElementAsRecord(i), 2, O);

75          }

76         

77          O << "\n  return true;  // CC didn't match.\n";

78          O << "}\n";

79        }

CallingConv定義裡最主要的部分就是Actions,它確定了對該呼叫慣例的處理方式,因此它實際決定了該處理方法的定義。因為CallingConv中Actions是一個list,因此需要在一個迴圈裡呼叫下面的EmitAction方法。

81        void CallingConvEmitter::EmitAction(Record *Action,

82                                            unsigned Indent, raw_ostream &O) {

83          std::string IndentStr = std::string(Indent, ' ');

84         

85          if (Action->isSubClassOf("CCPredicateAction")) {

86            O << IndentStr << "if (";

87           

88            if (Action->isSubClassOf("CCIfType")) {

89              ListInit *VTs = Action->getValueAsListInit("VTs");

90              for (unsigned i = 0, e = VTs->size(); i != e; ++i) {

91                Record *VT = VTs->getElementAsRecord(i);

92                if (i != 0) O << " ||\n    " << IndentStr;

93                O << "LocVT == " << getEnumName(getValueType(VT));

94              }

95       

96            } else if (Action->isSubClassOf("CCIf")) {

97              O << Action->getValueAsString("Predicate");

98            } else {

99              Action->dump();

100            PrintFatalError("Unknown CCPredicateAction!");

101          }

102         

103          O << ") {\n";

104          EmitAction(Action->getValueAsDef("SubAction"), Indent+2, O);

105          O << IndentStr << "}\n";

106        } else {

107          if (Action->isSubClassOf("CCDelegateTo")) {

108            Record *CC = Action->getValueAsDef("CC");

109            O << IndentStr << "if (!" << CC->getName()

110              << "(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))\n"

111              << IndentStr << "  return false;\n";

112          } else if (Action->isSubClassOf("CCAssignToReg")) {

113            ListInit *RegList = Action->getValueAsListInit("RegList");

114            if (RegList->size() == 1) {

115              O << IndentStr << "if (unsigned Reg = State.AllocateReg(";

116              O << getQualifiedName(RegList->getElementAsRecord(0)) << ")) {\n";

117            } else {

118              O << IndentStr << "static const MCPhysReg RegList" << ++Counter

119                << "[] = {\n";

120              O << IndentStr << "  ";

121              for (unsigned i = 0, e = RegList->size(); i != e; ++i) {

122                if (i != 0) O << ", ";

123                O << getQualifiedName(RegList->getElementAsRecord(i));

124              }

125              O << "\n" << IndentStr << "};\n";

126              O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"

127                << Counter << ")) {\n";

128            }

129            O << IndentStr << "  State.addLoc(CCValAssign::getReg(ValNo, ValVT, "

130              << "Reg, LocVT, LocInfo));\n";

131            O << IndentStr << "  return false;\n";

132            O << IndentStr << "}\n";

133          } else if (Action->isSubClassOf("CCAssignToRegWithShadow")) {

134            ListInit *RegList = Action->getValueAsListInit("RegList");

135            ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");

136            if (!ShadowRegList->empty() && ShadowRegList->size() != RegList->size())

137              PrintFatalError("Invalid length of list of shadowed registers");

138     

139            if (RegList->size() == 1) {

140              O << IndentStr << "if (unsigned Reg = State.AllocateReg(";

141              O << getQualifiedName(RegList->getElementAsRecord(0));

142              O << ", " << getQualifiedName(ShadowRegList->getElementAsRecord(0));

143              O << ")) {\n";

144            } else {

145              unsigned RegListNumber = ++Counter;

146              unsigned ShadowRegListNumber = ++Counter;

147     

148              O << IndentStr << "static const MCPhysReg RegList" << RegListNumber

149                << "[] = {\n";

150              O << IndentStr << "  ";

151              for (unsigned i = 0, e = RegList->size(); i != e; ++i) {

152                if (i != 0) O << ", ";

153                O << getQualifiedName(RegList->getElementAsRecord(i));

154              }

155              O << "\n" << IndentStr << "};\n";

156     

157              O << IndentStr << "static const MCPhysReg RegList"

158                << ShadowRegListNumber << "[] = {\n";

159              O << IndentStr << "  ";

160              for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i) {

161                if (i != 0) O << ", ";

162                O << getQualifiedName(ShadowRegList->getElementAsRecord(i));

163              }

164              O << "\n" << IndentStr << "};\n";

165     

166              O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"

167                << RegListNumber << ", " << "RegList" << ShadowRegListNumber

168                << ")) {\n";

169            }

170            O << IndentStr << "  State.addLoc(CCValAssign::getReg(ValNo, ValVT, "

171              << "Reg, LocVT, LocInfo));\n";

172            O << IndentStr << "  return false;\n";

173            O << IndentStr << "}\n";

174          } else if (Action->isSubClassOf("CCAssignToStack")) {

175            int Size = Action->getValueAsInt("Size");

176            int Align = Action->getValueAsInt("Align");

177     

178            O << IndentStr << "unsigned Offset" << ++Counter

179              << " = State.AllocateStack(";

180            if (Size)

181              O << Size << ", ";

182            else

183              O << "\n" << IndentStr

184                << "  State.getMachineFunction().getTarget().getDataLayout()"

185                   "->getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())),"

186                   " ";

187            if (Align)

188              O << Align;

189            else

190              O << "\n" << IndentStr

191                << "  State.getMachineFunction().getTarget().getDataLayout()"

192                   "->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()"

193                   "))";

194            O << ");\n" << IndentStr

195              << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"

196              << Counter << ", LocVT, LocInfo));\n";

197            O << IndentStr << "return false;\n";

198          } else if (Action->isSubClassOf("CCAssignToStackWithShadow")) {

199            int Size = Action->getValueAsInt("Size");

200            int Align = Action->getValueAsInt("Align");

201            ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");

202     

203            unsigned ShadowRegListNumber = ++Counter;

204     

205            O << IndentStr << "static const MCPhysReg ShadowRegList"

206                << ShadowRegListNumber << "[] = {\n";

207            O << IndentStr << "  ";

208            for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i) {

209              if (i != 0) O << ", ";

210              O << getQualifiedName(ShadowRegList->getElementAsRecord(i));

211            }

212            O << "\n" << IndentStr << "};\n";

213     

214            O << IndentStr << "unsigned Offset" << ++Counter

215              << " = State.AllocateStack("

216              << Size << ", " << Align << ", "

217              << "ShadowRegList" << ShadowRegListNumber << ");\n";

218            O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"

219              << Counter << ", LocVT, LocInfo));\n";

220            O << IndentStr << "return false;\n";

221          } else if (Action->isSubClassOf("CCPromoteToType")) {

222            Record *DestTy = Action->getValueAsDef("DestTy");

223            MVT::SimpleValueType DestVT = getValueType(DestTy);

224            O << IndentStr << "LocVT = " << getEnumName(DestVT) <<";\n";

225            if (MVT(DestVT).isFloatingPoint()) {

226              O << IndentStr << "LocInfo = CCValAssign::FPExt;\n";

227            } else {

228              O << IndentStr << "if (ArgFlags.isSExt())\n"

229                << IndentStr << IndentStr << "LocInfo = CCValAssign::SExt;\n"

230                << IndentStr << "else if (ArgFlags.isZExt())\n"

231                << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExt;\n"

232                << IndentStr << "else\n"

233                << IndentStr << IndentStr << "LocInfo = CCValAssign::AExt;\n";

234            }

235          } else if (Action->isSubClassOf("CCPromoteToUpperBitsInType")) {

236            Record *DestTy = Action->getValueAsDef("DestTy");

237            MVT::SimpleValueType DestVT = getValueType(DestTy);

238            O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n";

239            if (MVT(DestVT).isFloatingPoint()) {

240              PrintFatalError("CCPromoteToUpperBitsInType does not handle floating "

241                              "point");

242            } else {

243              O << IndentStr << "if (ArgFlags.isSExt())\n"

244                << IndentStr << IndentStr << "LocInfo = CCValAssign::SExtUpper;\n"

245                << IndentStr << "else if (ArgFlags.isZExt())\n"

246                << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExtUpper;\n"

247                << IndentStr << "else\n"

248                << IndentStr << IndentStr << "LocInfo = CCValAssign::AExtUpper;\n";

249            }

250          } else if (Action->isSubClassOf("CCBitConvertToType")) {

251            Record *DestTy = Action->getValueAsDef("DestTy");

252            O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";

253            O << IndentStr << "LocInfo = CCValAssign::BCvt;\n";

254          } else if (Action->isSubClassOf("CCPassIndirect")) {

255            Record *DestTy = Action->getValueAsDef("DestTy");

256            O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";

257            O << IndentStr << "LocInfo = CCValAssign::Indirect;\n";

258          } else if (Action->isSubClassOf("CCPassByVal")) {

259            int Size = Action->getValueAsInt("Size");

260            int Align = Action->getValueAsInt("Align");

261            O << IndentStr

262              << "State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, "

263              << Size << ", " << Align << ", ArgFlags);\n";

264           O << IndentStr << "return false;\n";

265          } else if (Action->isSubClassOf("CCCustom")) {

266            O << IndentStr

267              << "if (" << Action->getValueAsString("FuncName") << "(ValNo, ValVT, "

268              << "LocVT, LocInfo, ArgFlags, State))\n";

269            O << IndentStr << IndentStr << "return false;\n";

270          } else {

271            Action->dump();

272            PrintFatalError("Unknown CCAction!");

273          }

274        }

275      }

EmitAction方法雖然比較大,但邏輯並不複雜,實際上從TableGen描述到生成程式碼間的對映相當簡單。以CC_X86_32_C為例(注意它與對應的呼叫慣例定義同名),生成的函式形式如下(如果與TableGen的描述對比,可以看到明顯的對應關係):

314      static bool CC_X86_32_C(unsigned ValNo, MVT ValVT,

315                              MVT LocVT, CCValAssign::LocInfo LocInfo,

316                              ISD::ArgFlagsTy ArgFlags, CCState &State) {

317     

318        if (LocVT == MVT::i1 ||

319            LocVT == MVT::i8 ||

320            LocVT == MVT::i16) {

321          LocVT = MVT::i32;

322          if (ArgFlags.isSExt())

323              LocInfo = CCValAssign::SExt;

324          else if (ArgFlags.isZExt())

325              LocInfo = CCValAssign::ZExt;

326          else

327              LocInfo = CCValAssign::AExt;

328        }

329     

330        if (ArgFlags.isNest()) {

331 &n