LLVM学习笔记(47)

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

内容简介: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方法来处理。


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

查看所有标签

猜你喜欢:

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

Chinese Authoritarianism in the Information Age

Chinese Authoritarianism in the Information Age

Routledge / 2018-2-13 / GBP 115.00

This book examines information and public opinion control by the authoritarian state in response to popular access to information and upgraded political communication channels among the citizens in co......一起来看看 《Chinese Authoritarianism in the Information Age》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

SHA 加密
SHA 加密

SHA 加密工具