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;                                                 <- v7.0删除

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;

  bool AnalyzingMustTailForwardedRegs = false;                                                                 <- v7.0增加

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;

  SmallVector<ISD::ArgFlagsTy, 4> PendingArgFlags;                                                            <- v7.0增加

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;                                                                                                 <- v7.0删除

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) {                                                                                                   <- v7.0删除

33         // No stack is used.

34         StackOffset = 0;

35      

36         clearByValRegsInfo();

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

38       }

其中StackOffset记录所代表函数调用参数使用栈的大小,UsedRegs则记录寄存器的使用情况。

        1. 代码的生成

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表示该调用惯例由同名的定制函数处理,即CustomCallingConv派生定义),就为它输出一个函数声明,形如:

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的描述对比,可以看到明显的对应关系)(v7.0生成的代码也是按照上面的步骤生成的,因此不再列出):

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         if (unsigned Reg = State.AllocateReg(X86::ECX)) {

332           State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));

333           return false;

334         }

335       }

336    

337       if (!State.isVarArg()) {

338         if (ArgFlags.isInReg()) {

339           if (LocVT == MVT::i32) {

340             static const MCPhysReg RegList1[] = {

341               X86::EAX, X86::EDX, X86::ECX

342             };

343             if (unsigned Reg = State.AllocateReg(RegList1)) {

344               State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));

345               return false;

346             }

347           }

348         }

349       }

350    

351       if (!CC_X86_32_Common(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))

352         return false;

353    

354       return true;  // CC didn't match.

355     }

315行的CCValAssign::LocInfo是一个枚举类型,描述对所要赋值内存的占用情况。这个枚举值随后传递给CCValAssign的getReg(),用于构建CCValAssign实例。CCValAssign::getReg()用来分配一个代表寄存器赋值的CCValAssign实例。

77         static CCValAssign getReg(unsigned ValNo, MVT ValVT,

78                                   unsigned RegNo, MVT LocVT,

79                                   LocInfo HTP) {

80           CCValAssign Ret;

81           Ret.ValNo = ValNo;

82           Ret.Loc = RegNo;

83           Ret.isMem = false;

84           Ret.isCustom = false;

85           Ret.HTP = HTP;

86           Ret.ValVT = ValVT;

87           Ret.LocVT = LocVT;

88           return Ret;

89         }

CCState的addLoc()方法则只是将这个CCValAssign实例记录在Locs容器里(实际上是在构造这个CCState实例时传入的容器)。

注意343行,如果调用惯例不是可变参数,且参数是通过寄存器传递的i32类型,则需使用EAX,EDX或ECX之一。CCState成员UsedRegs来记录寄存器的使用情况,通过AllocateReg()方法在UsedRegs中标定已经被使用的寄存器。

而余下情形,则需要351行调用CC_X86_32_Common()方法来处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值