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