Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/CallingConvEmitter.cpp
35258 views
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
441