xref: /freebsd/contrib/llvm-project/llvm/utils/TableGen/CallingConvEmitter.cpp (revision 7ef62cebc2f965b0f640263e179276928885e33d)
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                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 
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 
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