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