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