1 //===- CallingConvEmitter.cpp - Generate calling conventions --------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This tablegen backend is responsible for emitting descriptions of the calling
10 // conventions supported by this target.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "CodeGenTarget.h"
15 #include "llvm/TableGen/Error.h"
16 #include "llvm/TableGen/Record.h"
17 #include "llvm/TableGen/TableGenBackend.h"
18 #include <deque>
19 #include <set>
20
21 using namespace llvm;
22
23 namespace {
24 class CallingConvEmitter {
25 RecordKeeper &Records;
26 unsigned Counter = 0u;
27 std::string CurrentAction;
28 bool SwiftAction = false;
29
30 std::map<std::string, std::set<std::string>> AssignedRegsMap;
31 std::map<std::string, std::set<std::string>> AssignedSwiftRegsMap;
32 std::map<std::string, std::set<std::string>> DelegateToMap;
33
34 public:
CallingConvEmitter(RecordKeeper & R)35 explicit CallingConvEmitter(RecordKeeper &R) : Records(R) {}
36
37 void run(raw_ostream &o);
38
39 private:
40 void EmitCallingConv(Record *CC, raw_ostream &O);
41 void EmitAction(Record *Action, unsigned Indent, raw_ostream &O);
42 void EmitArgRegisterLists(raw_ostream &O);
43 };
44 } // End anonymous namespace
45
run(raw_ostream & O)46 void CallingConvEmitter::run(raw_ostream &O) {
47 emitSourceFileHeader("Calling Convention Implementation Fragment", O);
48
49 std::vector<Record *> CCs = Records.getAllDerivedDefinitions("CallingConv");
50
51 // Emit prototypes for all of the non-custom CC's so that they can forward ref
52 // each other.
53 Records.startTimer("Emit prototypes");
54 O << "#ifndef GET_CC_REGISTER_LISTS\n\n";
55 for (Record *CC : CCs) {
56 if (!CC->getValueAsBit("Custom")) {
57 unsigned Pad = CC->getName().size();
58 if (CC->getValueAsBit("Entry")) {
59 O << "bool llvm::";
60 Pad += 12;
61 } else {
62 O << "static bool ";
63 Pad += 13;
64 }
65 O << CC->getName() << "(unsigned ValNo, MVT ValVT,\n"
66 << std::string(Pad, ' ') << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
67 << std::string(Pad, ' ')
68 << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n";
69 }
70 }
71
72 // Emit each non-custom calling convention description in full.
73 Records.startTimer("Emit full descriptions");
74 for (Record *CC : CCs) {
75 if (!CC->getValueAsBit("Custom")) {
76 EmitCallingConv(CC, O);
77 }
78 }
79
80 EmitArgRegisterLists(O);
81
82 O << "\n#endif // CC_REGISTER_LIST\n";
83 }
84
EmitCallingConv(Record * CC,raw_ostream & O)85 void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) {
86 ListInit *CCActions = CC->getValueAsListInit("Actions");
87 Counter = 0;
88
89 CurrentAction = CC->getName().str();
90 // Call upon the creation of a map entry from the void!
91 // We want an entry in AssignedRegsMap for every action, even if that
92 // entry is empty.
93 AssignedRegsMap[CurrentAction] = {};
94
95 O << "\n\n";
96 unsigned Pad = CurrentAction.size();
97 if (CC->getValueAsBit("Entry")) {
98 O << "bool llvm::";
99 Pad += 12;
100 } else {
101 O << "static bool ";
102 Pad += 13;
103 }
104 O << CurrentAction << "(unsigned ValNo, MVT ValVT,\n"
105 << std::string(Pad, ' ') << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
106 << std::string(Pad, ' ') << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n";
107 // Emit all of the actions, in order.
108 for (unsigned i = 0, e = CCActions->size(); i != e; ++i) {
109 Record *Action = CCActions->getElementAsRecord(i);
110 SwiftAction =
111 llvm::any_of(Action->getSuperClasses(),
112 [](const std::pair<Record *, SMRange> &Class) {
113 std::string Name = Class.first->getNameInitAsString();
114 return StringRef(Name).starts_with("CCIfSwift");
115 });
116
117 O << "\n";
118 EmitAction(Action, 2, O);
119 }
120
121 O << "\n return true; // CC didn't match.\n";
122 O << "}\n";
123 }
124
EmitAction(Record * Action,unsigned Indent,raw_ostream & O)125 void CallingConvEmitter::EmitAction(Record *Action,
126 unsigned Indent, raw_ostream &O) {
127 std::string IndentStr = std::string(Indent, ' ');
128
129 if (Action->isSubClassOf("CCPredicateAction")) {
130 O << IndentStr << "if (";
131
132 if (Action->isSubClassOf("CCIfType")) {
133 ListInit *VTs = Action->getValueAsListInit("VTs");
134 for (unsigned i = 0, e = VTs->size(); i != e; ++i) {
135 Record *VT = VTs->getElementAsRecord(i);
136 if (i != 0) O << " ||\n " << IndentStr;
137 O << "LocVT == " << getEnumName(getValueType(VT));
138 }
139
140 } else if (Action->isSubClassOf("CCIf")) {
141 O << Action->getValueAsString("Predicate");
142 } else {
143 errs() << *Action;
144 PrintFatalError(Action->getLoc(), "Unknown CCPredicateAction!");
145 }
146
147 O << ") {\n";
148 EmitAction(Action->getValueAsDef("SubAction"), Indent+2, O);
149 O << IndentStr << "}\n";
150 } else {
151 if (Action->isSubClassOf("CCDelegateTo")) {
152 Record *CC = Action->getValueAsDef("CC");
153 O << IndentStr << "if (!" << CC->getName()
154 << "(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))\n"
155 << IndentStr << " return false;\n";
156 DelegateToMap[CurrentAction].insert(CC->getName().str());
157 } else if (Action->isSubClassOf("CCAssignToReg") ||
158 Action->isSubClassOf("CCAssignToRegAndStack")) {
159 ListInit *RegList = Action->getValueAsListInit("RegList");
160 if (RegList->size() == 1) {
161 std::string Name = getQualifiedName(RegList->getElementAsRecord(0));
162 O << IndentStr << "if (unsigned Reg = State.AllocateReg(" << Name
163 << ")) {\n";
164 if (SwiftAction)
165 AssignedSwiftRegsMap[CurrentAction].insert(Name);
166 else
167 AssignedRegsMap[CurrentAction].insert(Name);
168 } else {
169 O << IndentStr << "static const MCPhysReg RegList" << ++Counter
170 << "[] = {\n";
171 O << IndentStr << " ";
172 ListSeparator LS;
173 for (unsigned i = 0, e = RegList->size(); i != e; ++i) {
174 std::string Name = getQualifiedName(RegList->getElementAsRecord(i));
175 if (SwiftAction)
176 AssignedSwiftRegsMap[CurrentAction].insert(Name);
177 else
178 AssignedRegsMap[CurrentAction].insert(Name);
179 O << LS << Name;
180 }
181 O << "\n" << IndentStr << "};\n";
182 O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
183 << Counter << ")) {\n";
184 }
185 O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
186 << "Reg, LocVT, LocInfo));\n";
187 if (Action->isSubClassOf("CCAssignToRegAndStack")) {
188 int Size = Action->getValueAsInt("Size");
189 int Align = Action->getValueAsInt("Align");
190 O << IndentStr << " (void)State.AllocateStack(";
191 if (Size)
192 O << Size << ", ";
193 else
194 O << "\n"
195 << IndentStr
196 << " State.getMachineFunction().getDataLayout()."
197 "getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())),"
198 " ";
199 if (Align)
200 O << "Align(" << Align << ")";
201 else
202 O << "\n"
203 << IndentStr
204 << " State.getMachineFunction().getDataLayout()."
205 "getABITypeAlign(EVT(LocVT).getTypeForEVT(State.getContext()"
206 "))";
207 O << ");\n";
208 }
209 O << IndentStr << " return false;\n";
210 O << IndentStr << "}\n";
211 } else if (Action->isSubClassOf("CCAssignToRegWithShadow")) {
212 ListInit *RegList = Action->getValueAsListInit("RegList");
213 ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");
214 if (!ShadowRegList->empty() && ShadowRegList->size() != RegList->size())
215 PrintFatalError(Action->getLoc(),
216 "Invalid length of list of shadowed registers");
217
218 if (RegList->size() == 1) {
219 O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
220 O << getQualifiedName(RegList->getElementAsRecord(0));
221 O << ", " << getQualifiedName(ShadowRegList->getElementAsRecord(0));
222 O << ")) {\n";
223 } else {
224 unsigned RegListNumber = ++Counter;
225 unsigned ShadowRegListNumber = ++Counter;
226
227 O << IndentStr << "static const MCPhysReg RegList" << RegListNumber
228 << "[] = {\n";
229 O << IndentStr << " ";
230 ListSeparator LS;
231 for (unsigned i = 0, e = RegList->size(); i != e; ++i)
232 O << LS << getQualifiedName(RegList->getElementAsRecord(i));
233 O << "\n" << IndentStr << "};\n";
234
235 O << IndentStr << "static const MCPhysReg RegList"
236 << ShadowRegListNumber << "[] = {\n";
237 O << IndentStr << " ";
238 ListSeparator LSS;
239 for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i)
240 O << LSS << getQualifiedName(ShadowRegList->getElementAsRecord(i));
241 O << "\n" << IndentStr << "};\n";
242
243 O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
244 << RegListNumber << ", " << "RegList" << ShadowRegListNumber
245 << ")) {\n";
246 }
247 O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
248 << "Reg, LocVT, LocInfo));\n";
249 O << IndentStr << " return false;\n";
250 O << IndentStr << "}\n";
251 } else if (Action->isSubClassOf("CCAssignToStack")) {
252 int Size = Action->getValueAsInt("Size");
253 int Align = Action->getValueAsInt("Align");
254
255 O << IndentStr << "int64_t Offset" << ++Counter
256 << " = State.AllocateStack(";
257 if (Size)
258 O << Size << ", ";
259 else
260 O << "\n" << IndentStr
261 << " State.getMachineFunction().getDataLayout()."
262 "getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())),"
263 " ";
264 if (Align)
265 O << "Align(" << Align << ")";
266 else
267 O << "\n"
268 << IndentStr
269 << " State.getMachineFunction().getDataLayout()."
270 "getABITypeAlign(EVT(LocVT).getTypeForEVT(State.getContext()"
271 "))";
272 O << ");\n" << IndentStr
273 << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
274 << Counter << ", LocVT, LocInfo));\n";
275 O << IndentStr << "return false;\n";
276 } else if (Action->isSubClassOf("CCAssignToStackWithShadow")) {
277 int Size = Action->getValueAsInt("Size");
278 int Align = Action->getValueAsInt("Align");
279 ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");
280
281 unsigned ShadowRegListNumber = ++Counter;
282
283 O << IndentStr << "static const MCPhysReg ShadowRegList"
284 << ShadowRegListNumber << "[] = {\n";
285 O << IndentStr << " ";
286 ListSeparator LS;
287 for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i)
288 O << LS << getQualifiedName(ShadowRegList->getElementAsRecord(i));
289 O << "\n" << IndentStr << "};\n";
290
291 O << IndentStr << "int64_t Offset" << ++Counter
292 << " = State.AllocateStack(" << Size << ", Align(" << Align << "), "
293 << "ShadowRegList" << ShadowRegListNumber << ");\n";
294 O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
295 << Counter << ", LocVT, LocInfo));\n";
296 O << IndentStr << "return false;\n";
297 } else if (Action->isSubClassOf("CCPromoteToType")) {
298 Record *DestTy = Action->getValueAsDef("DestTy");
299 MVT::SimpleValueType DestVT = getValueType(DestTy);
300 O << IndentStr << "LocVT = " << getEnumName(DestVT) <<";\n";
301 if (MVT(DestVT).isFloatingPoint()) {
302 O << IndentStr << "LocInfo = CCValAssign::FPExt;\n";
303 } else {
304 O << IndentStr << "if (ArgFlags.isSExt())\n"
305 << IndentStr << " LocInfo = CCValAssign::SExt;\n"
306 << IndentStr << "else if (ArgFlags.isZExt())\n"
307 << IndentStr << " LocInfo = CCValAssign::ZExt;\n"
308 << IndentStr << "else\n"
309 << IndentStr << " LocInfo = CCValAssign::AExt;\n";
310 }
311 } else if (Action->isSubClassOf("CCPromoteToUpperBitsInType")) {
312 Record *DestTy = Action->getValueAsDef("DestTy");
313 MVT::SimpleValueType DestVT = getValueType(DestTy);
314 O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n";
315 if (MVT(DestVT).isFloatingPoint()) {
316 PrintFatalError(Action->getLoc(),
317 "CCPromoteToUpperBitsInType does not handle floating "
318 "point");
319 } else {
320 O << IndentStr << "if (ArgFlags.isSExt())\n"
321 << IndentStr << " LocInfo = CCValAssign::SExtUpper;\n"
322 << IndentStr << "else if (ArgFlags.isZExt())\n"
323 << IndentStr << " LocInfo = CCValAssign::ZExtUpper;\n"
324 << IndentStr << "else\n"
325 << IndentStr << " LocInfo = CCValAssign::AExtUpper;\n";
326 }
327 } else if (Action->isSubClassOf("CCBitConvertToType")) {
328 Record *DestTy = Action->getValueAsDef("DestTy");
329 O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
330 O << IndentStr << "LocInfo = CCValAssign::BCvt;\n";
331 } else if (Action->isSubClassOf("CCTruncToType")) {
332 Record *DestTy = Action->getValueAsDef("DestTy");
333 O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
334 O << IndentStr << "LocInfo = CCValAssign::Trunc;\n";
335 } else if (Action->isSubClassOf("CCPassIndirect")) {
336 Record *DestTy = Action->getValueAsDef("DestTy");
337 O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
338 O << IndentStr << "LocInfo = CCValAssign::Indirect;\n";
339 } else if (Action->isSubClassOf("CCPassByVal")) {
340 int Size = Action->getValueAsInt("Size");
341 int Align = Action->getValueAsInt("Align");
342 O << IndentStr << "State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, "
343 << Size << ", Align(" << Align << "), ArgFlags);\n";
344 O << IndentStr << "return false;\n";
345 } else if (Action->isSubClassOf("CCCustom")) {
346 O << IndentStr
347 << "if (" << Action->getValueAsString("FuncName") << "(ValNo, ValVT, "
348 << "LocVT, LocInfo, ArgFlags, State))\n";
349 O << IndentStr << " return false;\n";
350 } else {
351 errs() << *Action;
352 PrintFatalError(Action->getLoc(), "Unknown CCAction!");
353 }
354 }
355 }
356
EmitArgRegisterLists(raw_ostream & O)357 void CallingConvEmitter::EmitArgRegisterLists(raw_ostream &O) {
358 // Transitively merge all delegated CCs into AssignedRegsMap.
359 using EntryTy = std::pair<std::string, std::set<std::string>>;
360 bool Redo;
361 do {
362 Redo = false;
363 std::deque<EntryTy> Worklist(DelegateToMap.begin(), DelegateToMap.end());
364
365 while (!Worklist.empty()) {
366 EntryTy Entry = Worklist.front();
367 Worklist.pop_front();
368
369 const std::string &CCName = Entry.first;
370 std::set<std::string> &Registers = Entry.second;
371 if (!Registers.empty())
372 continue;
373
374 for (auto &InnerEntry : Worklist) {
375 const std::string &InnerCCName = InnerEntry.first;
376 std::set<std::string> &InnerRegisters = InnerEntry.second;
377
378 if (InnerRegisters.find(CCName) != InnerRegisters.end()) {
379 AssignedRegsMap[InnerCCName].insert(
380 AssignedRegsMap[CCName].begin(),
381 AssignedRegsMap[CCName].end());
382 InnerRegisters.erase(CCName);
383 }
384 }
385
386 DelegateToMap.erase(CCName);
387 Redo = true;
388 }
389 } while (Redo);
390
391 if (AssignedRegsMap.empty())
392 return;
393
394 O << "\n#else\n\n";
395
396 for (auto &Entry : AssignedRegsMap) {
397 const std::string &RegName = Entry.first;
398 std::set<std::string> &Registers = Entry.second;
399
400 if (RegName.empty())
401 continue;
402
403 O << "const MCRegister " << Entry.first << "_ArgRegs[] = { ";
404
405 if (Registers.empty()) {
406 O << "0";
407 } else {
408 ListSeparator LS;
409 for (const std::string &Reg : Registers)
410 O << LS << Reg;
411 }
412
413 O << " };\n";
414 }
415
416 if (AssignedSwiftRegsMap.empty())
417 return;
418
419 O << "\n// Registers used by Swift.\n";
420 for (auto &Entry : AssignedSwiftRegsMap) {
421 const std::string &RegName = Entry.first;
422 std::set<std::string> &Registers = Entry.second;
423
424 O << "const MCRegister " << RegName << "_Swift_ArgRegs[] = { ";
425
426 ListSeparator LS;
427 for (const std::string &Reg : Registers)
428 O << LS << Reg;
429
430 O << " };\n";
431 }
432 }
433
434 static TableGen::Emitter::OptClass<CallingConvEmitter>
435 X("gen-callingconv", "Generate calling convention descriptions");
436