1 //===- CallingConvEmitter.cpp - Generate calling conventions --------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This tablegen backend is responsible for emitting descriptions of the calling
10 // conventions supported by this target.
12 //===----------------------------------------------------------------------===//
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"
25 class CallingConvEmitter
{
26 const RecordKeeper
&Records
;
27 unsigned Counter
= 0u;
28 std::string CurrentAction
;
29 bool SwiftAction
= false;
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
;
36 explicit CallingConvEmitter(const RecordKeeper
&R
) : Records(R
) {}
38 void run(raw_ostream
&O
);
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
);
45 } // End anonymous namespace
47 void CallingConvEmitter::run(raw_ostream
&O
) {
48 emitSourceFileHeader("Calling Convention Implementation Fragment", O
);
50 ArrayRef
<const Record
*> CCs
=
51 Records
.getAllDerivedDefinitions("CallingConv");
53 // Emit prototypes for all of the non-custom CC's so that they can forward ref
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")) {
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";
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
);
82 emitArgRegisterLists(O
);
84 O
<< "\n#endif // CC_REGISTER_LIST\n";
87 void CallingConvEmitter::emitCallingConv(const Record
*CC
, raw_ostream
&O
) {
88 const ListInit
*CCActions
= CC
->getValueAsListInit("Actions");
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
95 AssignedRegsMap
[CurrentAction
] = {};
98 unsigned Pad
= CurrentAction
.size();
99 if (CC
->getValueAsBit("Entry")) {
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
);
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");
120 emitAction(Action
, indent(2), O
);
123 O
<< "\n return true; // CC didn't match.\n";
127 void CallingConvEmitter::emitAction(const Record
*Action
, indent Indent
,
129 if (Action
->isSubClassOf("CCPredicateAction")) {
130 O
<< Indent
<< "if (";
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
);
137 O
<< " ||\n " << Indent
;
138 O
<< "LocVT == " << getEnumName(getValueType(VT
));
141 } else if (Action
->isSubClassOf("CCIf")) {
142 O
<< Action
->getValueAsString("Predicate");
145 PrintFatalError(Action
->getLoc(), "Unknown CCPredicateAction!");
149 emitAction(Action
->getValueAsDef("SubAction"), Indent
+ 2, O
);
150 O
<< Indent
<< "}\n";
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
166 AssignedSwiftRegsMap
[CurrentAction
].insert(Name
);
168 AssignedRegsMap
[CurrentAction
].insert(Name
);
170 O
<< Indent
<< "static const MCPhysReg RegList" << ++Counter
174 for (unsigned I
= 0, E
= RegList
->size(); I
!= E
; ++I
) {
175 std::string Name
= getQualifiedName(RegList
->getElementAsRecord(I
));
177 AssignedSwiftRegsMap
[CurrentAction
].insert(Name
);
179 AssignedRegsMap
[CurrentAction
].insert(Name
);
182 O
<< "\n" << Indent
<< "};\n";
183 O
<< Indent
<< "if (MCRegister Reg = State.AllocateReg(RegList"
184 << Counter
<< ")) {\n";
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(";
197 << " State.getMachineFunction().getDataLayout()."
198 "getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())),"
201 O
<< "Align(" << Align
<< ")";
205 << " State.getMachineFunction().getDataLayout()."
206 "getABITypeAlign(EVT(LocVT).getTypeForEVT(State.getContext()"
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");
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));
226 unsigned RegListNumber
= ++Counter
;
227 unsigned ShadowRegListNumber
= ++Counter
;
229 O
<< Indent
<< "static const MCPhysReg RegList" << RegListNumber
233 for (unsigned I
= 0, E
= RegList
->size(); I
!= E
; ++I
)
234 O
<< LS
<< getQualifiedName(RegList
->getElementAsRecord(I
));
235 O
<< "\n" << Indent
<< "};\n";
237 O
<< Indent
<< "static const MCPhysReg RegList" << ShadowRegListNumber
241 for (unsigned I
= 0, E
= ShadowRegList
->size(); I
!= E
; ++I
)
242 O
<< LSS
<< getQualifiedName(ShadowRegList
->getElementAsRecord(I
));
243 O
<< "\n" << Indent
<< "};\n";
245 O
<< Indent
<< "if (MCRegister Reg = State.AllocateReg(RegList"
246 << RegListNumber
<< ", "
247 << "RegList" << ShadowRegListNumber
<< ")) {\n";
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");
257 O
<< Indent
<< "int64_t Offset" << ++Counter
<< " = State.AllocateStack(";
263 << " State.getMachineFunction().getDataLayout()."
264 "getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())),"
267 O
<< "Align(" << Align
<< ")";
271 << " State.getMachineFunction().getDataLayout()."
272 "getABITypeAlign(EVT(LocVT).getTypeForEVT(State.getContext()"
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");
284 unsigned ShadowRegListNumber
= ++Counter
;
286 O
<< Indent
<< "static const MCPhysReg ShadowRegList"
287 << ShadowRegListNumber
<< "[] = {\n";
290 for (unsigned I
= 0, E
= ShadowRegList
->size(); I
!= E
; ++I
)
291 O
<< LS
<< getQualifiedName(ShadowRegList
->getElementAsRecord(I
));
292 O
<< "\n" << Indent
<< "};\n";
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";
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";
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 "
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";
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")
351 << "LocVT, LocInfo, ArgFlags, State))\n";
352 O
<< Indent
<< " return false;\n";
355 PrintFatalError(Action
->getLoc(), "Unknown CCAction!");
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
>>;
366 std::deque
<EntryTy
> Worklist(DelegateToMap
.begin(), DelegateToMap
.end());
368 while (!Worklist
.empty()) {
369 EntryTy Entry
= Worklist
.front();
370 Worklist
.pop_front();
372 const std::string
&CCName
= Entry
.first
;
373 std::set
<std::string
> &Registers
= Entry
.second
;
374 if (!Registers
.empty())
377 for (auto &InnerEntry
: Worklist
) {
378 const std::string
&InnerCCName
= InnerEntry
.first
;
379 std::set
<std::string
> &InnerRegisters
= InnerEntry
.second
;
381 if (InnerRegisters
.find(CCName
) != InnerRegisters
.end()) {
382 AssignedRegsMap
[InnerCCName
].insert(AssignedRegsMap
[CCName
].begin(),
383 AssignedRegsMap
[CCName
].end());
384 InnerRegisters
.erase(CCName
);
388 DelegateToMap
.erase(CCName
);
393 if (AssignedRegsMap
.empty())
398 for (auto &Entry
: AssignedRegsMap
) {
399 const std::string
&RegName
= Entry
.first
;
400 std::set
<std::string
> &Registers
= Entry
.second
;
405 O
<< "const MCRegister " << Entry
.first
<< "_ArgRegs[] = { ";
407 if (Registers
.empty()) {
411 for (const std::string
&Reg
: Registers
)
418 if (AssignedSwiftRegsMap
.empty())
421 O
<< "\n// Registers used by Swift.\n";
422 for (auto &Entry
: AssignedSwiftRegsMap
) {
423 const std::string
&RegName
= Entry
.first
;
424 std::set
<std::string
> &Registers
= Entry
.second
;
426 O
<< "const MCRegister " << RegName
<< "_Swift_ArgRegs[] = { ";
429 for (const std::string
&Reg
: Registers
)
436 static TableGen::Emitter::OptClass
<CallingConvEmitter
>
437 X("gen-callingconv", "Generate calling convention descriptions");