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:
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 
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 
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 
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       ListInit *RegList = Action->getValueAsListInit("RegList");
154       if (RegList->size() == 1) {
155         std::string Name = getQualifiedName(RegList->getElementAsRecord(0));
156         O << IndentStr << "if (unsigned Reg = State.AllocateReg(" << Name
157           << ")) {\n";
158         if (SwiftAction)
159           AssignedSwiftRegsMap[CurrentAction].insert(Name);
160         else
161           AssignedRegsMap[CurrentAction].insert(Name);
162       } else {
163         O << IndentStr << "static const MCPhysReg RegList" << ++Counter
164           << "[] = {\n";
165         O << IndentStr << "  ";
166         ListSeparator LS;
167         for (unsigned i = 0, e = RegList->size(); i != e; ++i) {
168           std::string Name = getQualifiedName(RegList->getElementAsRecord(i));
169           if (SwiftAction)
170             AssignedSwiftRegsMap[CurrentAction].insert(Name);
171           else
172             AssignedRegsMap[CurrentAction].insert(Name);
173           O << LS << Name;
174         }
175         O << "\n" << IndentStr << "};\n";
176         O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
177           << Counter << ")) {\n";
178       }
179       O << IndentStr << "  State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
180         << "Reg, LocVT, LocInfo));\n";
181       O << IndentStr << "  return false;\n";
182       O << IndentStr << "}\n";
183     } else if (Action->isSubClassOf("CCAssignToRegWithShadow")) {
184       ListInit *RegList = Action->getValueAsListInit("RegList");
185       ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");
186       if (!ShadowRegList->empty() && ShadowRegList->size() != RegList->size())
187         PrintFatalError(Action->getLoc(),
188                         "Invalid length of list of shadowed registers");
189 
190       if (RegList->size() == 1) {
191         O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
192         O << getQualifiedName(RegList->getElementAsRecord(0));
193         O << ", " << getQualifiedName(ShadowRegList->getElementAsRecord(0));
194         O << ")) {\n";
195       } else {
196         unsigned RegListNumber = ++Counter;
197         unsigned ShadowRegListNumber = ++Counter;
198 
199         O << IndentStr << "static const MCPhysReg RegList" << RegListNumber
200           << "[] = {\n";
201         O << IndentStr << "  ";
202         ListSeparator LS;
203         for (unsigned i = 0, e = RegList->size(); i != e; ++i)
204           O << LS << getQualifiedName(RegList->getElementAsRecord(i));
205         O << "\n" << IndentStr << "};\n";
206 
207         O << IndentStr << "static const MCPhysReg RegList"
208           << ShadowRegListNumber << "[] = {\n";
209         O << IndentStr << "  ";
210         ListSeparator LSS;
211         for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i)
212           O << LSS << getQualifiedName(ShadowRegList->getElementAsRecord(i));
213         O << "\n" << IndentStr << "};\n";
214 
215         O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
216           << RegListNumber << ", " << "RegList" << ShadowRegListNumber
217           << ")) {\n";
218       }
219       O << IndentStr << "  State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
220         << "Reg, LocVT, LocInfo));\n";
221       O << IndentStr << "  return false;\n";
222       O << IndentStr << "}\n";
223     } else if (Action->isSubClassOf("CCAssignToStack")) {
224       int Size = Action->getValueAsInt("Size");
225       int Align = Action->getValueAsInt("Align");
226 
227       O << IndentStr << "unsigned Offset" << ++Counter
228         << " = State.AllocateStack(";
229       if (Size)
230         O << Size << ", ";
231       else
232         O << "\n" << IndentStr
233           << "  State.getMachineFunction().getDataLayout()."
234              "getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())),"
235              " ";
236       if (Align)
237         O << "Align(" << Align << ")";
238       else
239         O << "\n"
240           << IndentStr
241           << "  State.getMachineFunction().getDataLayout()."
242              "getABITypeAlign(EVT(LocVT).getTypeForEVT(State.getContext()"
243              "))";
244       O << ");\n" << IndentStr
245         << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
246         << Counter << ", LocVT, LocInfo));\n";
247       O << IndentStr << "return false;\n";
248     } else if (Action->isSubClassOf("CCAssignToStackWithShadow")) {
249       int Size = Action->getValueAsInt("Size");
250       int Align = Action->getValueAsInt("Align");
251       ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");
252 
253       unsigned ShadowRegListNumber = ++Counter;
254 
255       O << IndentStr << "static const MCPhysReg ShadowRegList"
256           << ShadowRegListNumber << "[] = {\n";
257       O << IndentStr << "  ";
258       ListSeparator LS;
259       for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i)
260         O << LS << getQualifiedName(ShadowRegList->getElementAsRecord(i));
261       O << "\n" << IndentStr << "};\n";
262 
263       O << IndentStr << "unsigned Offset" << ++Counter
264         << " = State.AllocateStack(" << Size << ", Align(" << Align << "), "
265         << "ShadowRegList" << ShadowRegListNumber << ");\n";
266       O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
267         << Counter << ", LocVT, LocInfo));\n";
268       O << IndentStr << "return false;\n";
269     } else if (Action->isSubClassOf("CCPromoteToType")) {
270       Record *DestTy = Action->getValueAsDef("DestTy");
271       MVT::SimpleValueType DestVT = getValueType(DestTy);
272       O << IndentStr << "LocVT = " << getEnumName(DestVT) <<";\n";
273       if (MVT(DestVT).isFloatingPoint()) {
274         O << IndentStr << "LocInfo = CCValAssign::FPExt;\n";
275       } else {
276         O << IndentStr << "if (ArgFlags.isSExt())\n"
277           << IndentStr << "  LocInfo = CCValAssign::SExt;\n"
278           << IndentStr << "else if (ArgFlags.isZExt())\n"
279           << IndentStr << "  LocInfo = CCValAssign::ZExt;\n"
280           << IndentStr << "else\n"
281           << IndentStr << "  LocInfo = CCValAssign::AExt;\n";
282       }
283     } else if (Action->isSubClassOf("CCPromoteToUpperBitsInType")) {
284       Record *DestTy = Action->getValueAsDef("DestTy");
285       MVT::SimpleValueType DestVT = getValueType(DestTy);
286       O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n";
287       if (MVT(DestVT).isFloatingPoint()) {
288         PrintFatalError(Action->getLoc(),
289                         "CCPromoteToUpperBitsInType does not handle floating "
290                         "point");
291       } else {
292         O << IndentStr << "if (ArgFlags.isSExt())\n"
293           << IndentStr << "  LocInfo = CCValAssign::SExtUpper;\n"
294           << IndentStr << "else if (ArgFlags.isZExt())\n"
295           << IndentStr << "  LocInfo = CCValAssign::ZExtUpper;\n"
296           << IndentStr << "else\n"
297           << IndentStr << "  LocInfo = CCValAssign::AExtUpper;\n";
298       }
299     } else if (Action->isSubClassOf("CCBitConvertToType")) {
300       Record *DestTy = Action->getValueAsDef("DestTy");
301       O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
302       O << IndentStr << "LocInfo = CCValAssign::BCvt;\n";
303     } else if (Action->isSubClassOf("CCTruncToType")) {
304       Record *DestTy = Action->getValueAsDef("DestTy");
305       O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
306       O << IndentStr << "LocInfo = CCValAssign::Trunc;\n";
307     } else if (Action->isSubClassOf("CCPassIndirect")) {
308       Record *DestTy = Action->getValueAsDef("DestTy");
309       O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
310       O << IndentStr << "LocInfo = CCValAssign::Indirect;\n";
311     } else if (Action->isSubClassOf("CCPassByVal")) {
312       int Size = Action->getValueAsInt("Size");
313       int Align = Action->getValueAsInt("Align");
314       O << IndentStr << "State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, "
315         << Size << ", Align(" << Align << "), ArgFlags);\n";
316       O << IndentStr << "return false;\n";
317     } else if (Action->isSubClassOf("CCCustom")) {
318       O << IndentStr
319         << "if (" << Action->getValueAsString("FuncName") << "(ValNo, ValVT, "
320         << "LocVT, LocInfo, ArgFlags, State))\n";
321       O << IndentStr << "  return false;\n";
322     } else {
323       errs() << *Action;
324       PrintFatalError(Action->getLoc(), "Unknown CCAction!");
325     }
326   }
327 }
328 
329 void CallingConvEmitter::EmitArgRegisterLists(raw_ostream &O) {
330   // Transitively merge all delegated CCs into AssignedRegsMap.
331   using EntryTy = std::pair<std::string, std::set<std::string>>;
332   bool Redo;
333   do {
334     Redo = false;
335     std::deque<EntryTy> Worklist(DelegateToMap.begin(), DelegateToMap.end());
336 
337     while (!Worklist.empty()) {
338       EntryTy Entry = Worklist.front();
339       Worklist.pop_front();
340 
341       const std::string &CCName = Entry.first;
342       std::set<std::string> &Registers = Entry.second;
343       if (!Registers.empty())
344         continue;
345 
346       for (auto &InnerEntry : Worklist) {
347         const std::string &InnerCCName = InnerEntry.first;
348         std::set<std::string> &InnerRegisters = InnerEntry.second;
349 
350         if (InnerRegisters.find(CCName) != InnerRegisters.end()) {
351           AssignedRegsMap[InnerCCName].insert(
352               AssignedRegsMap[CCName].begin(),
353               AssignedRegsMap[CCName].end());
354           InnerRegisters.erase(CCName);
355         }
356       }
357 
358       DelegateToMap.erase(CCName);
359       Redo = true;
360     }
361   } while (Redo);
362 
363   if (AssignedRegsMap.empty())
364     return;
365 
366   O << "\n#else\n\n";
367 
368   for (auto &Entry : AssignedRegsMap) {
369     const std::string &RegName = Entry.first;
370     std::set<std::string> &Registers = Entry.second;
371 
372     if (RegName.empty())
373       continue;
374 
375     O << "const MCRegister " << Entry.first << "_ArgRegs[] = { ";
376 
377     if (Registers.empty()) {
378       O << "0";
379     } else {
380       ListSeparator LS;
381       for (const std::string &Reg : Registers)
382         O << LS << Reg;
383     }
384 
385     O << " };\n";
386   }
387 
388   if (AssignedSwiftRegsMap.empty())
389     return;
390 
391   O << "\n// Registers used by Swift.\n";
392   for (auto &Entry : AssignedSwiftRegsMap) {
393     const std::string &RegName = Entry.first;
394     std::set<std::string> &Registers = Entry.second;
395 
396     O << "const MCRegister " << RegName << "_Swift_ArgRegs[] = { ";
397 
398     ListSeparator LS;
399     for (const std::string &Reg : Registers)
400       O << LS << Reg;
401 
402     O << " };\n";
403   }
404 }
405 
406 namespace llvm {
407 
408 void EmitCallingConv(RecordKeeper &RK, raw_ostream &OS) {
409   emitSourceFileHeader("Calling Convention Implementation Fragment", OS);
410   CallingConvEmitter(RK).run(OS);
411 }
412 
413 } // End llvm namespace
414