内容简介: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/深度学习/机器学习面试笔记
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
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》 这本书的介绍吧!