LLVM学习笔记(47)

栏目: 服务器 · 编程工具 · 发布时间: 5年前

内容简介:3.7.3.在文件CallingConvLower.h中定义了两个基本的数据结构:CCValAssign与CCState。CCValAssign在编译期间用于记录参数或返回值向寄存器或栈赋值的细节,它定义了以下成员:

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

332      State.addLoc(CCValAssign::(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方法来处理。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

C语言接口与实现

C语言接口与实现

David R. Hanson / 郭旭 / 人民邮电出版社 / 2011-9 / 75.00元

《C语言接口与实现:创建可重用软件的技术》概念清晰、实例详尽,是一本有关设计、实现和有效使用C语言库函数,掌握创建可重用C语言软件模块技术的参考指南。书中提供了大量实例,重在阐述如何用一种与语言无关的方法将接口设计实现独立出来,从而用一种基于接口的设计途径创建可重用的API。 《C语言接口与实现:创建可重用软件的技术》是所有C语言程序员不可多得的好书,也是所有希望掌握可重用软件模块技术的人员......一起来看看 《C语言接口与实现》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

MD5 加密
MD5 加密

MD5 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具