内容简介: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方法来处理。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 【每日笔记】【Go学习笔记】2019-01-04 Codis笔记
- 【每日笔记】【Go学习笔记】2019-01-02 Codis笔记
- 【每日笔记】【Go学习笔记】2019-01-07 Codis笔记
- Golang学习笔记-调度器学习
- Vue学习笔记(二)------axios学习
- 算法/NLP/深度学习/机器学习面试笔记
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
C语言接口与实现
David R. Hanson / 郭旭 / 人民邮电出版社 / 2011-9 / 75.00元
《C语言接口与实现:创建可重用软件的技术》概念清晰、实例详尽,是一本有关设计、实现和有效使用C语言库函数,掌握创建可重用C语言软件模块技术的参考指南。书中提供了大量实例,重在阐述如何用一种与语言无关的方法将接口设计实现独立出来,从而用一种基于接口的设计途径创建可重用的API。 《C语言接口与实现:创建可重用软件的技术》是所有C语言程序员不可多得的好书,也是所有希望掌握可重用软件模块技术的人员......一起来看看 《C语言接口与实现》 这本书的介绍吧!