CallingConvEmitter.cpp revision 360784
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#include <cassert>
19using namespace llvm;
20
21namespace {
22class CallingConvEmitter {
23  RecordKeeper &Records;
24public:
25  explicit CallingConvEmitter(RecordKeeper &R) : Records(R) {}
26
27  void run(raw_ostream &o);
28
29private:
30  void EmitCallingConv(Record *CC, raw_ostream &O);
31  void EmitAction(Record *Action, unsigned Indent, raw_ostream &O);
32  unsigned Counter;
33};
34} // End anonymous namespace
35
36void CallingConvEmitter::run(raw_ostream &O) {
37  std::vector<Record*> CCs = Records.getAllDerivedDefinitions("CallingConv");
38
39  // Emit prototypes for all of the non-custom CC's so that they can forward ref
40  // each other.
41  for (Record *CC : CCs) {
42    if (!CC->getValueAsBit("Custom")) {
43      unsigned Pad = CC->getName().size();
44      if (CC->getValueAsBit("Entry")) {
45        O << "bool llvm::";
46        Pad += 12;
47      } else {
48        O << "static bool ";
49        Pad += 13;
50      }
51      O << CC->getName() << "(unsigned ValNo, MVT ValVT,\n"
52        << std::string(Pad, ' ') << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
53        << std::string(Pad, ' ')
54        << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n";
55    }
56  }
57
58  // Emit each non-custom calling convention description in full.
59  for (Record *CC : CCs) {
60    if (!CC->getValueAsBit("Custom"))
61      EmitCallingConv(CC, O);
62  }
63}
64
65
66void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) {
67  ListInit *CCActions = CC->getValueAsListInit("Actions");
68  Counter = 0;
69
70  O << "\n\n";
71  unsigned Pad = CC->getName().size();
72  if (CC->getValueAsBit("Entry")) {
73    O << "bool llvm::";
74    Pad += 12;
75  } else {
76    O << "static bool ";
77    Pad += 13;
78  }
79  O << CC->getName() << "(unsigned ValNo, MVT ValVT,\n"
80    << std::string(Pad, ' ') << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
81    << std::string(Pad, ' ') << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n";
82  // Emit all of the actions, in order.
83  for (unsigned i = 0, e = CCActions->size(); i != e; ++i) {
84    O << "\n";
85    EmitAction(CCActions->getElementAsRecord(i), 2, O);
86  }
87
88  O << "\n  return true;  // CC didn't match.\n";
89  O << "}\n";
90}
91
92void CallingConvEmitter::EmitAction(Record *Action,
93                                    unsigned Indent, raw_ostream &O) {
94  std::string IndentStr = std::string(Indent, ' ');
95
96  if (Action->isSubClassOf("CCPredicateAction")) {
97    O << IndentStr << "if (";
98
99    if (Action->isSubClassOf("CCIfType")) {
100      ListInit *VTs = Action->getValueAsListInit("VTs");
101      for (unsigned i = 0, e = VTs->size(); i != e; ++i) {
102        Record *VT = VTs->getElementAsRecord(i);
103        if (i != 0) O << " ||\n    " << IndentStr;
104        O << "LocVT == " << getEnumName(getValueType(VT));
105      }
106
107    } else if (Action->isSubClassOf("CCIf")) {
108      O << Action->getValueAsString("Predicate");
109    } else {
110      errs() << *Action;
111      PrintFatalError(Action->getLoc(), "Unknown CCPredicateAction!");
112    }
113
114    O << ") {\n";
115    EmitAction(Action->getValueAsDef("SubAction"), Indent+2, O);
116    O << IndentStr << "}\n";
117  } else {
118    if (Action->isSubClassOf("CCDelegateTo")) {
119      Record *CC = Action->getValueAsDef("CC");
120      O << IndentStr << "if (!" << CC->getName()
121        << "(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))\n"
122        << IndentStr << "  return false;\n";
123    } else if (Action->isSubClassOf("CCAssignToReg")) {
124      ListInit *RegList = Action->getValueAsListInit("RegList");
125      if (RegList->size() == 1) {
126        O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
127        O << getQualifiedName(RegList->getElementAsRecord(0)) << ")) {\n";
128      } else {
129        O << IndentStr << "static const MCPhysReg RegList" << ++Counter
130          << "[] = {\n";
131        O << IndentStr << "  ";
132        for (unsigned i = 0, e = RegList->size(); i != e; ++i) {
133          if (i != 0) O << ", ";
134          O << getQualifiedName(RegList->getElementAsRecord(i));
135        }
136        O << "\n" << IndentStr << "};\n";
137        O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
138          << Counter << ")) {\n";
139      }
140      O << IndentStr << "  State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
141        << "Reg, LocVT, LocInfo));\n";
142      O << IndentStr << "  return false;\n";
143      O << IndentStr << "}\n";
144    } else if (Action->isSubClassOf("CCAssignToRegWithShadow")) {
145      ListInit *RegList = Action->getValueAsListInit("RegList");
146      ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");
147      if (!ShadowRegList->empty() && ShadowRegList->size() != RegList->size())
148        PrintFatalError(Action->getLoc(),
149                        "Invalid length of list of shadowed registers");
150
151      if (RegList->size() == 1) {
152        O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
153        O << getQualifiedName(RegList->getElementAsRecord(0));
154        O << ", " << getQualifiedName(ShadowRegList->getElementAsRecord(0));
155        O << ")) {\n";
156      } else {
157        unsigned RegListNumber = ++Counter;
158        unsigned ShadowRegListNumber = ++Counter;
159
160        O << IndentStr << "static const MCPhysReg RegList" << RegListNumber
161          << "[] = {\n";
162        O << IndentStr << "  ";
163        for (unsigned i = 0, e = RegList->size(); i != e; ++i) {
164          if (i != 0) O << ", ";
165          O << getQualifiedName(RegList->getElementAsRecord(i));
166        }
167        O << "\n" << IndentStr << "};\n";
168
169        O << IndentStr << "static const MCPhysReg RegList"
170          << ShadowRegListNumber << "[] = {\n";
171        O << IndentStr << "  ";
172        for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i) {
173          if (i != 0) O << ", ";
174          O << getQualifiedName(ShadowRegList->getElementAsRecord(i));
175        }
176        O << "\n" << IndentStr << "};\n";
177
178        O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
179          << RegListNumber << ", " << "RegList" << ShadowRegListNumber
180          << ")) {\n";
181      }
182      O << IndentStr << "  State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
183        << "Reg, LocVT, LocInfo));\n";
184      O << IndentStr << "  return false;\n";
185      O << IndentStr << "}\n";
186    } else if (Action->isSubClassOf("CCAssignToStack")) {
187      int Size = Action->getValueAsInt("Size");
188      int Align = Action->getValueAsInt("Align");
189
190      O << IndentStr << "unsigned Offset" << ++Counter
191        << " = State.AllocateStack(";
192      if (Size)
193        O << Size << ", ";
194      else
195        O << "\n" << IndentStr
196          << "  State.getMachineFunction().getDataLayout()."
197             "getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())),"
198             " ";
199      if (Align)
200        O << Align;
201      else
202        O << "\n" << IndentStr
203          << "  State.getMachineFunction().getDataLayout()."
204             "getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()"
205             "))";
206      O << ");\n" << IndentStr
207        << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
208        << Counter << ", LocVT, LocInfo));\n";
209      O << IndentStr << "return false;\n";
210    } else if (Action->isSubClassOf("CCAssignToStackWithShadow")) {
211      int Size = Action->getValueAsInt("Size");
212      int Align = Action->getValueAsInt("Align");
213      ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");
214
215      unsigned ShadowRegListNumber = ++Counter;
216
217      O << IndentStr << "static const MCPhysReg ShadowRegList"
218          << ShadowRegListNumber << "[] = {\n";
219      O << IndentStr << "  ";
220      for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i) {
221        if (i != 0) O << ", ";
222        O << getQualifiedName(ShadowRegList->getElementAsRecord(i));
223      }
224      O << "\n" << IndentStr << "};\n";
225
226      O << IndentStr << "unsigned Offset" << ++Counter
227        << " = State.AllocateStack("
228        << Size << ", " << Align << ", "
229        << "ShadowRegList" << ShadowRegListNumber << ");\n";
230      O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
231        << Counter << ", LocVT, LocInfo));\n";
232      O << IndentStr << "return false;\n";
233    } else if (Action->isSubClassOf("CCPromoteToType")) {
234      Record *DestTy = Action->getValueAsDef("DestTy");
235      MVT::SimpleValueType DestVT = getValueType(DestTy);
236      O << IndentStr << "LocVT = " << getEnumName(DestVT) <<";\n";
237      if (MVT(DestVT).isFloatingPoint()) {
238        O << IndentStr << "LocInfo = CCValAssign::FPExt;\n";
239      } else {
240        O << IndentStr << "if (ArgFlags.isSExt())\n"
241          << IndentStr << IndentStr << "LocInfo = CCValAssign::SExt;\n"
242          << IndentStr << "else if (ArgFlags.isZExt())\n"
243          << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExt;\n"
244          << IndentStr << "else\n"
245          << IndentStr << IndentStr << "LocInfo = CCValAssign::AExt;\n";
246      }
247    } else if (Action->isSubClassOf("CCPromoteToUpperBitsInType")) {
248      Record *DestTy = Action->getValueAsDef("DestTy");
249      MVT::SimpleValueType DestVT = getValueType(DestTy);
250      O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n";
251      if (MVT(DestVT).isFloatingPoint()) {
252        PrintFatalError(Action->getLoc(),
253                        "CCPromoteToUpperBitsInType does not handle floating "
254                        "point");
255      } else {
256        O << IndentStr << "if (ArgFlags.isSExt())\n"
257          << IndentStr << IndentStr << "LocInfo = CCValAssign::SExtUpper;\n"
258          << IndentStr << "else if (ArgFlags.isZExt())\n"
259          << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExtUpper;\n"
260          << IndentStr << "else\n"
261          << IndentStr << IndentStr << "LocInfo = CCValAssign::AExtUpper;\n";
262      }
263    } else if (Action->isSubClassOf("CCBitConvertToType")) {
264      Record *DestTy = Action->getValueAsDef("DestTy");
265      O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
266      O << IndentStr << "LocInfo = CCValAssign::BCvt;\n";
267    } else if (Action->isSubClassOf("CCTruncToType")) {
268      Record *DestTy = Action->getValueAsDef("DestTy");
269      O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
270      O << IndentStr << "LocInfo = CCValAssign::Trunc;\n";
271    } else if (Action->isSubClassOf("CCPassIndirect")) {
272      Record *DestTy = Action->getValueAsDef("DestTy");
273      O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
274      O << IndentStr << "LocInfo = CCValAssign::Indirect;\n";
275    } else if (Action->isSubClassOf("CCPassByVal")) {
276      int Size = Action->getValueAsInt("Size");
277      int Align = Action->getValueAsInt("Align");
278      O << IndentStr
279        << "State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, "
280        << Size << ", " << Align << ", ArgFlags);\n";
281      O << IndentStr << "return false;\n";
282    } else if (Action->isSubClassOf("CCCustom")) {
283      O << IndentStr
284        << "if (" << Action->getValueAsString("FuncName") << "(ValNo, ValVT, "
285        << "LocVT, LocInfo, ArgFlags, State))\n";
286      O << IndentStr << IndentStr << "return false;\n";
287    } else {
288      errs() << *Action;
289      PrintFatalError(Action->getLoc(), "Unknown CCAction!");
290    }
291  }
292}
293
294namespace llvm {
295
296void EmitCallingConv(RecordKeeper &RK, raw_ostream &OS) {
297  emitSourceFileHeader("Calling Convention Implementation Fragment", OS);
298  CallingConvEmitter(RK).run(OS);
299}
300
301} // End llvm namespace
302