xref: /freebsd/contrib/llvm-project/llvm/utils/TableGen/CallingConvEmitter.cpp (revision b1879975794772ee51f0b4865753364c7d7626c3)
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 
21 using namespace llvm;
22 
23 namespace {
24 class 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 
34 public:
35   explicit CallingConvEmitter(RecordKeeper &R) : Records(R) {}
36 
37   void run(raw_ostream &o);
38 
39 private:
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 
46 void CallingConvEmitter::run(raw_ostream &O) {
47   emitSourceFileHeader("Calling Convention Implementation Fragment", O);
48 
49   std::vector<Record *> CCs = Records.getAllDerivedDefinitions("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("Emit prototypes");
54   O << "#ifndef GET_CC_REGISTER_LISTS\n\n";
55   for (Record *CC : CCs) {
56     if (!CC->getValueAsBit("Custom")) {
57       unsigned Pad = CC->getName().size();
58       if (CC->getValueAsBit("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("Emit full descriptions");
74   for (Record *CC : CCs) {
75     if (!CC->getValueAsBit("Custom")) {
76       EmitCallingConv(CC, O);
77     }
78   }
79 
80   EmitArgRegisterLists(O);
81 
82   O << "\n#endif // CC_REGISTER_LIST\n";
83 }
84 
85 void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) {
86   ListInit *CCActions = CC->getValueAsListInit("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("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(Action->getSuperClasses(),
112                      [](const std::pair<Record *, SMRange> &Class) {
113                        std::string Name = Class.first->getNameInitAsString();
114                        return StringRef(Name).starts_with("CCIfSwift");
115                      });
116 
117     O << "\n";
118     EmitAction(Action, 2, O);
119   }
120 
121   O << "\n  return true; // CC didn't match.\n";
122   O << "}\n";
123 }
124 
125 void CallingConvEmitter::EmitAction(Record *Action, unsigned Indent,
126                                     raw_ostream &O) {
127   std::string IndentStr = std::string(Indent, ' ');
128 
129   if (Action->isSubClassOf("CCPredicateAction")) {
130     O << IndentStr << "if (";
131 
132     if (Action->isSubClassOf("CCIfType")) {
133       ListInit *VTs = Action->getValueAsListInit("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(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 << IndentStr << "}\n";
151   } else {
152     if (Action->isSubClassOf("CCDelegateTo")) {
153       Record *CC = Action->getValueAsDef("CC");
154       O << IndentStr << "if (!" << CC->getName()
155         << "(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))\n"
156         << IndentStr << "  return false;\n";
157       DelegateToMap[CurrentAction].insert(CC->getName().str());
158     } else if (Action->isSubClassOf("CCAssignToReg") ||
159                Action->isSubClassOf("CCAssignToRegAndStack")) {
160       ListInit *RegList = Action->getValueAsListInit("RegList");
161       if (RegList->size() == 1) {
162         std::string Name = getQualifiedName(RegList->getElementAsRecord(0));
163         O << IndentStr << "if (unsigned Reg = State.AllocateReg(" << Name
164           << ")) {\n";
165         if (SwiftAction)
166           AssignedSwiftRegsMap[CurrentAction].insert(Name);
167         else
168           AssignedRegsMap[CurrentAction].insert(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(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" << 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("CCAssignToRegAndStack")) {
189         int Size = Action->getValueAsInt("Size");
190         int Align = Action->getValueAsInt("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("CCAssignToRegWithShadow")) {
213       ListInit *RegList = Action->getValueAsListInit("RegList");
214       ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");
215       if (!ShadowRegList->empty() && ShadowRegList->size() != RegList->size())
216         PrintFatalError(Action->getLoc(),
217                         "Invalid length of list of shadowed registers");
218 
219       if (RegList->size() == 1) {
220         O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
221         O << getQualifiedName(RegList->getElementAsRecord(0));
222         O << ", " << getQualifiedName(ShadowRegList->getElementAsRecord(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(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(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("CCAssignToStack")) {
253       int Size = Action->getValueAsInt("Size");
254       int Align = Action->getValueAsInt("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("CCAssignToStackWithShadow")) {
279       int Size = Action->getValueAsInt("Size");
280       int Align = Action->getValueAsInt("Align");
281       ListInit *ShadowRegList = Action->getValueAsListInit("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(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("CCPromoteToType")) {
300       Record *DestTy = Action->getValueAsDef("DestTy");
301       MVT::SimpleValueType DestVT = getValueType(DestTy);
302       O << IndentStr << "LocVT = " << getEnumName(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("CCPromoteToUpperBitsInType")) {
314       Record *DestTy = Action->getValueAsDef("DestTy");
315       MVT::SimpleValueType DestVT = getValueType(DestTy);
316       O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n";
317       if (MVT(DestVT).isFloatingPoint()) {
318         PrintFatalError(Action->getLoc(),
319                         "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("CCBitConvertToType")) {
330       Record *DestTy = Action->getValueAsDef("DestTy");
331       O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy))
332         << ";\n";
333       O << IndentStr << "LocInfo = CCValAssign::BCvt;\n";
334     } else if (Action->isSubClassOf("CCTruncToType")) {
335       Record *DestTy = Action->getValueAsDef("DestTy");
336       O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy))
337         << ";\n";
338       O << IndentStr << "LocInfo = CCValAssign::Trunc;\n";
339     } else if (Action->isSubClassOf("CCPassIndirect")) {
340       Record *DestTy = Action->getValueAsDef("DestTy");
341       O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy))
342         << ";\n";
343       O << IndentStr << "LocInfo = CCValAssign::Indirect;\n";
344     } else if (Action->isSubClassOf("CCPassByVal")) {
345       int Size = Action->getValueAsInt("Size");
346       int Align = Action->getValueAsInt("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("CCCustom")) {
351       O << IndentStr << "if (" << Action->getValueAsString("FuncName")
352         << "(ValNo, ValVT, "
353         << "LocVT, LocInfo, ArgFlags, State))\n";
354       O << IndentStr << "  return false;\n";
355     } else {
356       errs() << *Action;
357       PrintFatalError(Action->getLoc(), "Unknown CCAction!");
358     }
359   }
360 }
361 
362 void 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(CCName) != InnerRegisters.end()) {
384           AssignedRegsMap[InnerCCName].insert(AssignedRegsMap[CCName].begin(),
385                                               AssignedRegsMap[CCName].end());
386           InnerRegisters.erase(CCName);
387         }
388       }
389 
390       DelegateToMap.erase(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 
438 static TableGen::Emitter::OptClass<CallingConvEmitter>
439     X("gen-callingconv", "Generate calling convention descriptions");
440