1*700637cbSDimitry Andric //===- RuntimeLibcallEmitter.cpp - Properties from RuntimeLibcalls.td -----===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric
9*700637cbSDimitry Andric #include "llvm/ADT/StringRef.h"
10*700637cbSDimitry Andric #include "llvm/Support/Debug.h"
11*700637cbSDimitry Andric #include "llvm/Support/raw_ostream.h"
12*700637cbSDimitry Andric #include "llvm/TableGen/Error.h"
13*700637cbSDimitry Andric #include "llvm/TableGen/Record.h"
14*700637cbSDimitry Andric #include "llvm/TableGen/SetTheory.h"
15*700637cbSDimitry Andric #include "llvm/TableGen/TableGenBackend.h"
16*700637cbSDimitry Andric
17*700637cbSDimitry Andric using namespace llvm;
18*700637cbSDimitry Andric
19*700637cbSDimitry Andric namespace {
20*700637cbSDimitry Andric // Pair of a RuntimeLibcallPredicate and LibcallCallingConv to use as a map key.
21*700637cbSDimitry Andric struct PredicateWithCC {
22*700637cbSDimitry Andric const Record *Predicate = nullptr;
23*700637cbSDimitry Andric const Record *CallingConv = nullptr;
24*700637cbSDimitry Andric
25*700637cbSDimitry Andric PredicateWithCC() = default;
PredicateWithCC__anonf9119db00111::PredicateWithCC26*700637cbSDimitry Andric PredicateWithCC(std::pair<const Record *, const Record *> P)
27*700637cbSDimitry Andric : Predicate(P.first), CallingConv(P.second) {}
28*700637cbSDimitry Andric
PredicateWithCC__anonf9119db00111::PredicateWithCC29*700637cbSDimitry Andric PredicateWithCC(const Record *P, const Record *C)
30*700637cbSDimitry Andric : Predicate(P), CallingConv(C) {}
31*700637cbSDimitry Andric };
32*700637cbSDimitry Andric
operator ==(PredicateWithCC LHS,PredicateWithCC RHS)33*700637cbSDimitry Andric inline bool operator==(PredicateWithCC LHS, PredicateWithCC RHS) {
34*700637cbSDimitry Andric return LHS.Predicate == RHS.Predicate && LHS.CallingConv == RHS.CallingConv;
35*700637cbSDimitry Andric }
36*700637cbSDimitry Andric } // namespace
37*700637cbSDimitry Andric
38*700637cbSDimitry Andric namespace llvm {
39*700637cbSDimitry Andric template <> struct DenseMapInfo<PredicateWithCC, void> {
getEmptyKeyllvm::DenseMapInfo40*700637cbSDimitry Andric static inline PredicateWithCC getEmptyKey() {
41*700637cbSDimitry Andric return DenseMapInfo<
42*700637cbSDimitry Andric std::pair<const Record *, const Record *>>::getEmptyKey();
43*700637cbSDimitry Andric }
44*700637cbSDimitry Andric
getTombstoneKeyllvm::DenseMapInfo45*700637cbSDimitry Andric static inline PredicateWithCC getTombstoneKey() {
46*700637cbSDimitry Andric return DenseMapInfo<
47*700637cbSDimitry Andric std::pair<const Record *, const Record *>>::getTombstoneKey();
48*700637cbSDimitry Andric }
49*700637cbSDimitry Andric
getHashValuellvm::DenseMapInfo50*700637cbSDimitry Andric static unsigned getHashValue(const PredicateWithCC Val) {
51*700637cbSDimitry Andric auto Pair = std::make_pair(Val.Predicate, Val.CallingConv);
52*700637cbSDimitry Andric return DenseMapInfo<
53*700637cbSDimitry Andric std::pair<const Record *, const Record *>>::getHashValue(Pair);
54*700637cbSDimitry Andric }
55*700637cbSDimitry Andric
isEqualllvm::DenseMapInfo56*700637cbSDimitry Andric static bool isEqual(PredicateWithCC LHS, PredicateWithCC RHS) {
57*700637cbSDimitry Andric return LHS == RHS;
58*700637cbSDimitry Andric }
59*700637cbSDimitry Andric };
60*700637cbSDimitry Andric } // namespace llvm
61*700637cbSDimitry Andric
62*700637cbSDimitry Andric namespace {
63*700637cbSDimitry Andric
64*700637cbSDimitry Andric class AvailabilityPredicate {
65*700637cbSDimitry Andric const Record *TheDef;
66*700637cbSDimitry Andric StringRef PredicateString;
67*700637cbSDimitry Andric
68*700637cbSDimitry Andric public:
AvailabilityPredicate(const Record * Def)69*700637cbSDimitry Andric AvailabilityPredicate(const Record *Def) : TheDef(Def) {
70*700637cbSDimitry Andric if (TheDef)
71*700637cbSDimitry Andric PredicateString = TheDef->getValueAsString("Cond");
72*700637cbSDimitry Andric }
73*700637cbSDimitry Andric
getDef() const74*700637cbSDimitry Andric const Record *getDef() const { return TheDef; }
75*700637cbSDimitry Andric
isAlwaysAvailable() const76*700637cbSDimitry Andric bool isAlwaysAvailable() const { return PredicateString.empty(); }
77*700637cbSDimitry Andric
emitIf(raw_ostream & OS) const78*700637cbSDimitry Andric void emitIf(raw_ostream &OS) const {
79*700637cbSDimitry Andric OS << "if (" << PredicateString << ") {\n";
80*700637cbSDimitry Andric }
81*700637cbSDimitry Andric
emitEndIf(raw_ostream & OS) const82*700637cbSDimitry Andric void emitEndIf(raw_ostream &OS) const { OS << "}\n"; }
83*700637cbSDimitry Andric
emitTableVariableNameSuffix(raw_ostream & OS) const84*700637cbSDimitry Andric void emitTableVariableNameSuffix(raw_ostream &OS) const {
85*700637cbSDimitry Andric if (TheDef)
86*700637cbSDimitry Andric OS << '_' << TheDef->getName();
87*700637cbSDimitry Andric }
88*700637cbSDimitry Andric };
89*700637cbSDimitry Andric
90*700637cbSDimitry Andric class RuntimeLibcallEmitter;
91*700637cbSDimitry Andric class RuntimeLibcallImpl;
92*700637cbSDimitry Andric
93*700637cbSDimitry Andric /// Used to apply predicates to nested sets of libcalls.
94*700637cbSDimitry Andric struct LibcallPredicateExpander : SetTheory::Expander {
95*700637cbSDimitry Andric const RuntimeLibcallEmitter &LibcallEmitter;
96*700637cbSDimitry Andric DenseMap<const RuntimeLibcallImpl *,
97*700637cbSDimitry Andric std::pair<std::vector<const Record *>, const Record *>> &Func2Preds;
98*700637cbSDimitry Andric
LibcallPredicateExpander__anonf9119db00211::LibcallPredicateExpander99*700637cbSDimitry Andric LibcallPredicateExpander(
100*700637cbSDimitry Andric const RuntimeLibcallEmitter &LibcallEmitter,
101*700637cbSDimitry Andric DenseMap<const RuntimeLibcallImpl *,
102*700637cbSDimitry Andric std::pair<std::vector<const Record *>, const Record *>>
103*700637cbSDimitry Andric &Func2Preds)
104*700637cbSDimitry Andric : LibcallEmitter(LibcallEmitter), Func2Preds(Func2Preds) {}
105*700637cbSDimitry Andric
106*700637cbSDimitry Andric void expand(SetTheory &ST, const Record *Def,
107*700637cbSDimitry Andric SetTheory::RecSet &Elts) override;
108*700637cbSDimitry Andric };
109*700637cbSDimitry Andric
110*700637cbSDimitry Andric class RuntimeLibcall {
111*700637cbSDimitry Andric const Record *TheDef = nullptr;
112*700637cbSDimitry Andric const size_t EnumVal;
113*700637cbSDimitry Andric
114*700637cbSDimitry Andric public:
115*700637cbSDimitry Andric RuntimeLibcall() = delete;
RuntimeLibcall(const Record * Def,size_t EnumVal)116*700637cbSDimitry Andric RuntimeLibcall(const Record *Def, size_t EnumVal)
117*700637cbSDimitry Andric : TheDef(Def), EnumVal(EnumVal) {
118*700637cbSDimitry Andric assert(Def);
119*700637cbSDimitry Andric }
120*700637cbSDimitry Andric
~RuntimeLibcall()121*700637cbSDimitry Andric ~RuntimeLibcall() { assert(TheDef); }
122*700637cbSDimitry Andric
getDef() const123*700637cbSDimitry Andric const Record *getDef() const { return TheDef; }
124*700637cbSDimitry Andric
getName() const125*700637cbSDimitry Andric StringRef getName() const { return TheDef->getName(); }
126*700637cbSDimitry Andric
getEnumVal() const127*700637cbSDimitry Andric size_t getEnumVal() const { return EnumVal; }
128*700637cbSDimitry Andric
emitEnumEntry(raw_ostream & OS) const129*700637cbSDimitry Andric void emitEnumEntry(raw_ostream &OS) const {
130*700637cbSDimitry Andric OS << "RTLIB::" << TheDef->getValueAsString("Name");
131*700637cbSDimitry Andric }
132*700637cbSDimitry Andric };
133*700637cbSDimitry Andric
134*700637cbSDimitry Andric class RuntimeLibcallImpl {
135*700637cbSDimitry Andric const Record *TheDef;
136*700637cbSDimitry Andric const RuntimeLibcall *Provides = nullptr;
137*700637cbSDimitry Andric const size_t EnumVal;
138*700637cbSDimitry Andric
139*700637cbSDimitry Andric public:
RuntimeLibcallImpl(const Record * Def,const DenseMap<const Record *,const RuntimeLibcall * > & ProvideMap,size_t EnumVal)140*700637cbSDimitry Andric RuntimeLibcallImpl(
141*700637cbSDimitry Andric const Record *Def,
142*700637cbSDimitry Andric const DenseMap<const Record *, const RuntimeLibcall *> &ProvideMap,
143*700637cbSDimitry Andric size_t EnumVal)
144*700637cbSDimitry Andric : TheDef(Def), EnumVal(EnumVal) {
145*700637cbSDimitry Andric if (const Record *ProvidesDef = Def->getValueAsDef("Provides"))
146*700637cbSDimitry Andric Provides = ProvideMap.lookup(ProvidesDef);
147*700637cbSDimitry Andric }
148*700637cbSDimitry Andric
~RuntimeLibcallImpl()149*700637cbSDimitry Andric ~RuntimeLibcallImpl() {}
150*700637cbSDimitry Andric
getDef() const151*700637cbSDimitry Andric const Record *getDef() const { return TheDef; }
152*700637cbSDimitry Andric
getName() const153*700637cbSDimitry Andric StringRef getName() const { return TheDef->getName(); }
154*700637cbSDimitry Andric
getEnumVal() const155*700637cbSDimitry Andric size_t getEnumVal() const { return EnumVal; }
156*700637cbSDimitry Andric
getProvides() const157*700637cbSDimitry Andric const RuntimeLibcall *getProvides() const { return Provides; }
158*700637cbSDimitry Andric
getLibcallFuncName() const159*700637cbSDimitry Andric StringRef getLibcallFuncName() const {
160*700637cbSDimitry Andric return TheDef->getValueAsString("LibCallFuncName");
161*700637cbSDimitry Andric }
162*700637cbSDimitry Andric
getCallingConv() const163*700637cbSDimitry Andric const Record *getCallingConv() const {
164*700637cbSDimitry Andric return TheDef->getValueAsOptionalDef("CallingConv");
165*700637cbSDimitry Andric }
166*700637cbSDimitry Andric
emitQuotedLibcallFuncName(raw_ostream & OS) const167*700637cbSDimitry Andric void emitQuotedLibcallFuncName(raw_ostream &OS) const {
168*700637cbSDimitry Andric OS << '\"' << getLibcallFuncName() << '\"';
169*700637cbSDimitry Andric }
170*700637cbSDimitry Andric
isDefault() const171*700637cbSDimitry Andric bool isDefault() const { return TheDef->getValueAsBit("IsDefault"); }
172*700637cbSDimitry Andric
emitEnumEntry(raw_ostream & OS) const173*700637cbSDimitry Andric void emitEnumEntry(raw_ostream &OS) const {
174*700637cbSDimitry Andric OS << "RTLIB::" << TheDef->getName();
175*700637cbSDimitry Andric }
176*700637cbSDimitry Andric
emitSetImplCall(raw_ostream & OS) const177*700637cbSDimitry Andric void emitSetImplCall(raw_ostream &OS) const {
178*700637cbSDimitry Andric OS << "setLibcallImpl(";
179*700637cbSDimitry Andric Provides->emitEnumEntry(OS);
180*700637cbSDimitry Andric OS << ", ";
181*700637cbSDimitry Andric emitEnumEntry(OS);
182*700637cbSDimitry Andric OS << "); // " << getLibcallFuncName() << '\n';
183*700637cbSDimitry Andric }
184*700637cbSDimitry Andric
emitTableEntry(raw_ostream & OS) const185*700637cbSDimitry Andric void emitTableEntry(raw_ostream &OS) const {
186*700637cbSDimitry Andric OS << '{';
187*700637cbSDimitry Andric Provides->emitEnumEntry(OS);
188*700637cbSDimitry Andric OS << ", ";
189*700637cbSDimitry Andric emitEnumEntry(OS);
190*700637cbSDimitry Andric OS << "}, // " << getLibcallFuncName() << '\n';
191*700637cbSDimitry Andric }
192*700637cbSDimitry Andric
emitSetCallingConv(raw_ostream & OS) const193*700637cbSDimitry Andric void emitSetCallingConv(raw_ostream &OS) const {}
194*700637cbSDimitry Andric };
195*700637cbSDimitry Andric
196*700637cbSDimitry Andric struct LibcallsWithCC {
197*700637cbSDimitry Andric std::vector<const RuntimeLibcallImpl *> LibcallImpls;
198*700637cbSDimitry Andric const Record *CallingConv = nullptr;
199*700637cbSDimitry Andric };
200*700637cbSDimitry Andric
201*700637cbSDimitry Andric class RuntimeLibcallEmitter {
202*700637cbSDimitry Andric private:
203*700637cbSDimitry Andric const RecordKeeper &Records;
204*700637cbSDimitry Andric DenseMap<const Record *, const RuntimeLibcall *> Def2RuntimeLibcall;
205*700637cbSDimitry Andric DenseMap<const Record *, const RuntimeLibcallImpl *> Def2RuntimeLibcallImpl;
206*700637cbSDimitry Andric
207*700637cbSDimitry Andric std::vector<RuntimeLibcall> RuntimeLibcallDefList;
208*700637cbSDimitry Andric std::vector<RuntimeLibcallImpl> RuntimeLibcallImplDefList;
209*700637cbSDimitry Andric
210*700637cbSDimitry Andric DenseMap<const RuntimeLibcall *, const RuntimeLibcallImpl *>
211*700637cbSDimitry Andric LibCallToDefaultImpl;
212*700637cbSDimitry Andric
213*700637cbSDimitry Andric private:
214*700637cbSDimitry Andric void emitGetRuntimeLibcallEnum(raw_ostream &OS) const;
215*700637cbSDimitry Andric
216*700637cbSDimitry Andric void emitGetInitRuntimeLibcallNames(raw_ostream &OS) const;
217*700637cbSDimitry Andric
218*700637cbSDimitry Andric void emitSystemRuntimeLibrarySetCalls(raw_ostream &OS) const;
219*700637cbSDimitry Andric
220*700637cbSDimitry Andric public:
RuntimeLibcallEmitter(const RecordKeeper & R)221*700637cbSDimitry Andric RuntimeLibcallEmitter(const RecordKeeper &R) : Records(R) {
222*700637cbSDimitry Andric
223*700637cbSDimitry Andric ArrayRef<const Record *> AllRuntimeLibcalls =
224*700637cbSDimitry Andric Records.getAllDerivedDefinitions("RuntimeLibcall");
225*700637cbSDimitry Andric
226*700637cbSDimitry Andric RuntimeLibcallDefList.reserve(AllRuntimeLibcalls.size());
227*700637cbSDimitry Andric
228*700637cbSDimitry Andric size_t CallTypeEnumVal = 0;
229*700637cbSDimitry Andric for (const Record *RuntimeLibcallDef : AllRuntimeLibcalls) {
230*700637cbSDimitry Andric RuntimeLibcallDefList.emplace_back(RuntimeLibcallDef, CallTypeEnumVal++);
231*700637cbSDimitry Andric Def2RuntimeLibcall[RuntimeLibcallDef] = &RuntimeLibcallDefList.back();
232*700637cbSDimitry Andric }
233*700637cbSDimitry Andric
234*700637cbSDimitry Andric for (RuntimeLibcall &LibCall : RuntimeLibcallDefList)
235*700637cbSDimitry Andric Def2RuntimeLibcall[LibCall.getDef()] = &LibCall;
236*700637cbSDimitry Andric
237*700637cbSDimitry Andric ArrayRef<const Record *> AllRuntimeLibcallImpls =
238*700637cbSDimitry Andric Records.getAllDerivedDefinitions("RuntimeLibcallImpl");
239*700637cbSDimitry Andric RuntimeLibcallImplDefList.reserve(AllRuntimeLibcallImpls.size());
240*700637cbSDimitry Andric
241*700637cbSDimitry Andric size_t LibCallImplEnumVal = 1;
242*700637cbSDimitry Andric for (const Record *LibCallImplDef : AllRuntimeLibcallImpls) {
243*700637cbSDimitry Andric RuntimeLibcallImplDefList.emplace_back(LibCallImplDef, Def2RuntimeLibcall,
244*700637cbSDimitry Andric LibCallImplEnumVal++);
245*700637cbSDimitry Andric
246*700637cbSDimitry Andric RuntimeLibcallImpl &LibCallImpl = RuntimeLibcallImplDefList.back();
247*700637cbSDimitry Andric
248*700637cbSDimitry Andric Def2RuntimeLibcallImpl[LibCallImplDef] = &LibCallImpl;
249*700637cbSDimitry Andric
250*700637cbSDimitry Andric // const RuntimeLibcallImpl &LibCallImpl =
251*700637cbSDimitry Andric // RuntimeLibcallImplDefList.back();
252*700637cbSDimitry Andric if (LibCallImpl.isDefault()) {
253*700637cbSDimitry Andric const RuntimeLibcall *Provides = LibCallImpl.getProvides();
254*700637cbSDimitry Andric if (!Provides)
255*700637cbSDimitry Andric PrintFatalError(LibCallImplDef->getLoc(),
256*700637cbSDimitry Andric "default implementations must provide a libcall");
257*700637cbSDimitry Andric LibCallToDefaultImpl[Provides] = &LibCallImpl;
258*700637cbSDimitry Andric }
259*700637cbSDimitry Andric }
260*700637cbSDimitry Andric }
261*700637cbSDimitry Andric
getRuntimeLibcall(const Record * Def) const262*700637cbSDimitry Andric const RuntimeLibcall *getRuntimeLibcall(const Record *Def) const {
263*700637cbSDimitry Andric return Def2RuntimeLibcall.lookup(Def);
264*700637cbSDimitry Andric }
265*700637cbSDimitry Andric
getRuntimeLibcallImpl(const Record * Def) const266*700637cbSDimitry Andric const RuntimeLibcallImpl *getRuntimeLibcallImpl(const Record *Def) const {
267*700637cbSDimitry Andric return Def2RuntimeLibcallImpl.lookup(Def);
268*700637cbSDimitry Andric }
269*700637cbSDimitry Andric
270*700637cbSDimitry Andric void run(raw_ostream &OS);
271*700637cbSDimitry Andric };
272*700637cbSDimitry Andric
273*700637cbSDimitry Andric } // End anonymous namespace.
274*700637cbSDimitry Andric
emitGetRuntimeLibcallEnum(raw_ostream & OS) const275*700637cbSDimitry Andric void RuntimeLibcallEmitter::emitGetRuntimeLibcallEnum(raw_ostream &OS) const {
276*700637cbSDimitry Andric OS << "#ifdef GET_RUNTIME_LIBCALL_ENUM\n"
277*700637cbSDimitry Andric "namespace llvm {\n"
278*700637cbSDimitry Andric "namespace RTLIB {\n"
279*700637cbSDimitry Andric "enum Libcall : unsigned short {\n";
280*700637cbSDimitry Andric
281*700637cbSDimitry Andric for (const RuntimeLibcall &LibCall : RuntimeLibcallDefList) {
282*700637cbSDimitry Andric StringRef Name = LibCall.getName();
283*700637cbSDimitry Andric OS << " " << Name << " = " << LibCall.getEnumVal() << ",\n";
284*700637cbSDimitry Andric }
285*700637cbSDimitry Andric
286*700637cbSDimitry Andric // TODO: Emit libcall names as string offset table.
287*700637cbSDimitry Andric
288*700637cbSDimitry Andric OS << " UNKNOWN_LIBCALL = " << RuntimeLibcallDefList.size()
289*700637cbSDimitry Andric << "\n};\n\n"
290*700637cbSDimitry Andric "enum LibcallImpl : unsigned short {\n"
291*700637cbSDimitry Andric " Unsupported = 0,\n";
292*700637cbSDimitry Andric
293*700637cbSDimitry Andric // FIXME: Emit this in a different namespace. And maybe use enum class.
294*700637cbSDimitry Andric for (const RuntimeLibcallImpl &LibCall : RuntimeLibcallImplDefList) {
295*700637cbSDimitry Andric OS << " " << LibCall.getName() << " = " << LibCall.getEnumVal() << ", // "
296*700637cbSDimitry Andric << LibCall.getLibcallFuncName() << '\n';
297*700637cbSDimitry Andric }
298*700637cbSDimitry Andric
299*700637cbSDimitry Andric OS << " NumLibcallImpls = " << RuntimeLibcallImplDefList.size() + 1
300*700637cbSDimitry Andric << "\n};\n"
301*700637cbSDimitry Andric "} // End namespace RTLIB\n"
302*700637cbSDimitry Andric "} // End namespace llvm\n"
303*700637cbSDimitry Andric "#endif\n\n";
304*700637cbSDimitry Andric }
305*700637cbSDimitry Andric
emitGetInitRuntimeLibcallNames(raw_ostream & OS) const306*700637cbSDimitry Andric void RuntimeLibcallEmitter::emitGetInitRuntimeLibcallNames(
307*700637cbSDimitry Andric raw_ostream &OS) const {
308*700637cbSDimitry Andric // TODO: Emit libcall names as string offset table.
309*700637cbSDimitry Andric
310*700637cbSDimitry Andric OS << "const RTLIB::LibcallImpl "
311*700637cbSDimitry Andric "llvm::RTLIB::RuntimeLibcallsInfo::"
312*700637cbSDimitry Andric "DefaultLibcallImpls[RTLIB::UNKNOWN_LIBCALL + 1] = {\n";
313*700637cbSDimitry Andric
314*700637cbSDimitry Andric for (const RuntimeLibcall &LibCall : RuntimeLibcallDefList) {
315*700637cbSDimitry Andric auto I = LibCallToDefaultImpl.find(&LibCall);
316*700637cbSDimitry Andric if (I == LibCallToDefaultImpl.end()) {
317*700637cbSDimitry Andric OS << " RTLIB::Unsupported,";
318*700637cbSDimitry Andric } else {
319*700637cbSDimitry Andric const RuntimeLibcallImpl *LibCallImpl = I->second;
320*700637cbSDimitry Andric OS << " ";
321*700637cbSDimitry Andric LibCallImpl->emitEnumEntry(OS);
322*700637cbSDimitry Andric OS << ',';
323*700637cbSDimitry Andric }
324*700637cbSDimitry Andric
325*700637cbSDimitry Andric OS << " // ";
326*700637cbSDimitry Andric LibCall.emitEnumEntry(OS);
327*700637cbSDimitry Andric OS << '\n';
328*700637cbSDimitry Andric }
329*700637cbSDimitry Andric
330*700637cbSDimitry Andric OS << " RTLIB::Unsupported\n"
331*700637cbSDimitry Andric "};\n\n";
332*700637cbSDimitry Andric
333*700637cbSDimitry Andric // Emit the implementation names
334*700637cbSDimitry Andric OS << "const char *const llvm::RTLIB::RuntimeLibcallsInfo::"
335*700637cbSDimitry Andric "LibCallImplNames[RTLIB::NumLibcallImpls] = {\n"
336*700637cbSDimitry Andric " nullptr, // RTLIB::Unsupported\n";
337*700637cbSDimitry Andric
338*700637cbSDimitry Andric for (const RuntimeLibcallImpl &LibCallImpl : RuntimeLibcallImplDefList) {
339*700637cbSDimitry Andric OS << " \"" << LibCallImpl.getLibcallFuncName() << "\", // ";
340*700637cbSDimitry Andric LibCallImpl.emitEnumEntry(OS);
341*700637cbSDimitry Andric OS << '\n';
342*700637cbSDimitry Andric }
343*700637cbSDimitry Andric
344*700637cbSDimitry Andric OS << "};\n\n";
345*700637cbSDimitry Andric
346*700637cbSDimitry Andric // Emit the reverse mapping from implementation libraries to RTLIB::Libcall
347*700637cbSDimitry Andric OS << "const RTLIB::Libcall llvm::RTLIB::RuntimeLibcallsInfo::"
348*700637cbSDimitry Andric "ImplToLibcall[RTLIB::NumLibcallImpls] = {\n"
349*700637cbSDimitry Andric " RTLIB::UNKNOWN_LIBCALL, // RTLIB::Unsupported\n";
350*700637cbSDimitry Andric
351*700637cbSDimitry Andric for (const RuntimeLibcallImpl &LibCallImpl : RuntimeLibcallImplDefList) {
352*700637cbSDimitry Andric const RuntimeLibcall *Provides = LibCallImpl.getProvides();
353*700637cbSDimitry Andric OS << " ";
354*700637cbSDimitry Andric Provides->emitEnumEntry(OS);
355*700637cbSDimitry Andric OS << ", // ";
356*700637cbSDimitry Andric LibCallImpl.emitEnumEntry(OS);
357*700637cbSDimitry Andric OS << '\n';
358*700637cbSDimitry Andric }
359*700637cbSDimitry Andric OS << "};\n\n";
360*700637cbSDimitry Andric }
361*700637cbSDimitry Andric
emitSystemRuntimeLibrarySetCalls(raw_ostream & OS) const362*700637cbSDimitry Andric void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
363*700637cbSDimitry Andric raw_ostream &OS) const {
364*700637cbSDimitry Andric OS << "void llvm::RTLIB::RuntimeLibcallsInfo::setTargetRuntimeLibcallSets("
365*700637cbSDimitry Andric "const llvm::Triple &TT, FloatABI::ABIType FloatABI) {\n"
366*700637cbSDimitry Andric " struct LibcallImplPair {\n"
367*700637cbSDimitry Andric " RTLIB::Libcall Func;\n"
368*700637cbSDimitry Andric " RTLIB::LibcallImpl Impl;\n"
369*700637cbSDimitry Andric " };\n";
370*700637cbSDimitry Andric ArrayRef<const Record *> AllLibs =
371*700637cbSDimitry Andric Records.getAllDerivedDefinitions("SystemRuntimeLibrary");
372*700637cbSDimitry Andric
373*700637cbSDimitry Andric for (const Record *R : AllLibs) {
374*700637cbSDimitry Andric OS << '\n';
375*700637cbSDimitry Andric
376*700637cbSDimitry Andric AvailabilityPredicate TopLevelPredicate(R->getValueAsDef("TriplePred"));
377*700637cbSDimitry Andric
378*700637cbSDimitry Andric OS << indent(2);
379*700637cbSDimitry Andric TopLevelPredicate.emitIf(OS);
380*700637cbSDimitry Andric
381*700637cbSDimitry Andric if (const Record *DefaultCCClass =
382*700637cbSDimitry Andric R->getValueAsDef("DefaultLibcallCallingConv")) {
383*700637cbSDimitry Andric StringRef DefaultCC =
384*700637cbSDimitry Andric DefaultCCClass->getValueAsString("CallingConv").trim();
385*700637cbSDimitry Andric
386*700637cbSDimitry Andric if (!DefaultCC.empty()) {
387*700637cbSDimitry Andric OS << " const CallingConv::ID DefaultCC = " << DefaultCC << ";\n"
388*700637cbSDimitry Andric << " for (CallingConv::ID &Entry : LibcallImplCallingConvs) {\n"
389*700637cbSDimitry Andric " Entry = DefaultCC;\n"
390*700637cbSDimitry Andric " }\n\n";
391*700637cbSDimitry Andric }
392*700637cbSDimitry Andric }
393*700637cbSDimitry Andric
394*700637cbSDimitry Andric SetTheory Sets;
395*700637cbSDimitry Andric
396*700637cbSDimitry Andric DenseMap<const RuntimeLibcallImpl *,
397*700637cbSDimitry Andric std::pair<std::vector<const Record *>, const Record *>>
398*700637cbSDimitry Andric Func2Preds;
399*700637cbSDimitry Andric Sets.addExpander("LibcallImpls", std::make_unique<LibcallPredicateExpander>(
400*700637cbSDimitry Andric *this, Func2Preds));
401*700637cbSDimitry Andric
402*700637cbSDimitry Andric const SetTheory::RecVec *Elements =
403*700637cbSDimitry Andric Sets.expand(R->getValueAsDef("MemberList"));
404*700637cbSDimitry Andric
405*700637cbSDimitry Andric // Sort to get deterministic output
406*700637cbSDimitry Andric SetVector<PredicateWithCC> PredicateSorter;
407*700637cbSDimitry Andric PredicateSorter.insert(
408*700637cbSDimitry Andric PredicateWithCC()); // No predicate or CC override first.
409*700637cbSDimitry Andric
410*700637cbSDimitry Andric DenseMap<PredicateWithCC, LibcallsWithCC> Pred2Funcs;
411*700637cbSDimitry Andric for (const Record *Elt : *Elements) {
412*700637cbSDimitry Andric const RuntimeLibcallImpl *LibCallImpl = getRuntimeLibcallImpl(Elt);
413*700637cbSDimitry Andric if (!LibCallImpl) {
414*700637cbSDimitry Andric PrintError(R, "entry for SystemLibrary is not a RuntimeLibcallImpl");
415*700637cbSDimitry Andric PrintNote(Elt->getLoc(), "invalid entry `" + Elt->getName() + "`");
416*700637cbSDimitry Andric continue;
417*700637cbSDimitry Andric }
418*700637cbSDimitry Andric
419*700637cbSDimitry Andric auto It = Func2Preds.find(LibCallImpl);
420*700637cbSDimitry Andric if (It == Func2Preds.end()) {
421*700637cbSDimitry Andric Pred2Funcs[PredicateWithCC()].LibcallImpls.push_back(LibCallImpl);
422*700637cbSDimitry Andric continue;
423*700637cbSDimitry Andric }
424*700637cbSDimitry Andric
425*700637cbSDimitry Andric for (const Record *Pred : It->second.first) {
426*700637cbSDimitry Andric const Record *CC = It->second.second;
427*700637cbSDimitry Andric PredicateWithCC Key(Pred, CC);
428*700637cbSDimitry Andric
429*700637cbSDimitry Andric auto &Entry = Pred2Funcs[Key];
430*700637cbSDimitry Andric Entry.LibcallImpls.push_back(LibCallImpl);
431*700637cbSDimitry Andric Entry.CallingConv = It->second.second;
432*700637cbSDimitry Andric PredicateSorter.insert(Key);
433*700637cbSDimitry Andric }
434*700637cbSDimitry Andric }
435*700637cbSDimitry Andric
436*700637cbSDimitry Andric SmallVector<PredicateWithCC, 0> SortedPredicates =
437*700637cbSDimitry Andric PredicateSorter.takeVector();
438*700637cbSDimitry Andric
439*700637cbSDimitry Andric llvm::sort(SortedPredicates, [](PredicateWithCC A, PredicateWithCC B) {
440*700637cbSDimitry Andric StringRef AName = A.Predicate ? A.Predicate->getName() : "";
441*700637cbSDimitry Andric StringRef BName = B.Predicate ? B.Predicate->getName() : "";
442*700637cbSDimitry Andric return AName < BName;
443*700637cbSDimitry Andric });
444*700637cbSDimitry Andric
445*700637cbSDimitry Andric for (PredicateWithCC Entry : SortedPredicates) {
446*700637cbSDimitry Andric AvailabilityPredicate SubsetPredicate(Entry.Predicate);
447*700637cbSDimitry Andric unsigned IndentDepth = 2;
448*700637cbSDimitry Andric
449*700637cbSDimitry Andric auto It = Pred2Funcs.find(Entry);
450*700637cbSDimitry Andric if (It == Pred2Funcs.end())
451*700637cbSDimitry Andric continue;
452*700637cbSDimitry Andric
453*700637cbSDimitry Andric if (!SubsetPredicate.isAlwaysAvailable()) {
454*700637cbSDimitry Andric IndentDepth = 4;
455*700637cbSDimitry Andric
456*700637cbSDimitry Andric OS << indent(IndentDepth);
457*700637cbSDimitry Andric SubsetPredicate.emitIf(OS);
458*700637cbSDimitry Andric }
459*700637cbSDimitry Andric
460*700637cbSDimitry Andric LibcallsWithCC &FuncsWithCC = It->second;
461*700637cbSDimitry Andric
462*700637cbSDimitry Andric std::vector<const RuntimeLibcallImpl *> &Funcs = FuncsWithCC.LibcallImpls;
463*700637cbSDimitry Andric
464*700637cbSDimitry Andric // Ensure we only emit a unique implementation per libcall in the
465*700637cbSDimitry Andric // selection table.
466*700637cbSDimitry Andric //
467*700637cbSDimitry Andric // FIXME: We need to generate separate functions for
468*700637cbSDimitry Andric // is-libcall-available and should-libcall-be-used to avoid this.
469*700637cbSDimitry Andric //
470*700637cbSDimitry Andric // This also makes it annoying to make use of the default set, since the
471*700637cbSDimitry Andric // entries from the default set may win over the replacements unless
472*700637cbSDimitry Andric // they are explicitly removed.
473*700637cbSDimitry Andric stable_sort(Funcs, [](const RuntimeLibcallImpl *A,
474*700637cbSDimitry Andric const RuntimeLibcallImpl *B) {
475*700637cbSDimitry Andric return A->getProvides()->getEnumVal() < B->getProvides()->getEnumVal();
476*700637cbSDimitry Andric });
477*700637cbSDimitry Andric
478*700637cbSDimitry Andric auto UniqueI = llvm::unique(
479*700637cbSDimitry Andric Funcs, [&](const RuntimeLibcallImpl *A, const RuntimeLibcallImpl *B) {
480*700637cbSDimitry Andric if (A->getProvides() == B->getProvides()) {
481*700637cbSDimitry Andric PrintWarning(R->getLoc(),
482*700637cbSDimitry Andric Twine("conflicting implementations for libcall " +
483*700637cbSDimitry Andric A->getProvides()->getName() + ": " +
484*700637cbSDimitry Andric A->getLibcallFuncName() + ", " +
485*700637cbSDimitry Andric B->getLibcallFuncName()));
486*700637cbSDimitry Andric return true;
487*700637cbSDimitry Andric }
488*700637cbSDimitry Andric
489*700637cbSDimitry Andric return false;
490*700637cbSDimitry Andric });
491*700637cbSDimitry Andric
492*700637cbSDimitry Andric Funcs.erase(UniqueI, Funcs.end());
493*700637cbSDimitry Andric
494*700637cbSDimitry Andric OS << indent(IndentDepth + 2)
495*700637cbSDimitry Andric << "static const LibcallImplPair LibraryCalls";
496*700637cbSDimitry Andric SubsetPredicate.emitTableVariableNameSuffix(OS);
497*700637cbSDimitry Andric OS << "[] = {\n";
498*700637cbSDimitry Andric for (const RuntimeLibcallImpl *LibCallImpl : Funcs) {
499*700637cbSDimitry Andric OS << indent(IndentDepth + 6);
500*700637cbSDimitry Andric LibCallImpl->emitTableEntry(OS);
501*700637cbSDimitry Andric }
502*700637cbSDimitry Andric
503*700637cbSDimitry Andric OS << indent(IndentDepth + 2) << "};\n\n"
504*700637cbSDimitry Andric << indent(IndentDepth + 2)
505*700637cbSDimitry Andric << "for (const auto [Func, Impl] : LibraryCalls";
506*700637cbSDimitry Andric SubsetPredicate.emitTableVariableNameSuffix(OS);
507*700637cbSDimitry Andric OS << ") {\n"
508*700637cbSDimitry Andric << indent(IndentDepth + 4) << "setLibcallImpl(Func, Impl);\n";
509*700637cbSDimitry Andric
510*700637cbSDimitry Andric if (FuncsWithCC.CallingConv) {
511*700637cbSDimitry Andric StringRef CCEnum =
512*700637cbSDimitry Andric FuncsWithCC.CallingConv->getValueAsString("CallingConv");
513*700637cbSDimitry Andric OS << indent(IndentDepth + 4) << "setLibcallImplCallingConv(Impl, "
514*700637cbSDimitry Andric << CCEnum << ");\n";
515*700637cbSDimitry Andric }
516*700637cbSDimitry Andric
517*700637cbSDimitry Andric OS << indent(IndentDepth + 2) << "}\n";
518*700637cbSDimitry Andric OS << '\n';
519*700637cbSDimitry Andric
520*700637cbSDimitry Andric if (!SubsetPredicate.isAlwaysAvailable()) {
521*700637cbSDimitry Andric OS << indent(IndentDepth);
522*700637cbSDimitry Andric SubsetPredicate.emitEndIf(OS);
523*700637cbSDimitry Andric OS << '\n';
524*700637cbSDimitry Andric }
525*700637cbSDimitry Andric }
526*700637cbSDimitry Andric
527*700637cbSDimitry Andric OS << indent(4) << "return;\n" << indent(2);
528*700637cbSDimitry Andric TopLevelPredicate.emitEndIf(OS);
529*700637cbSDimitry Andric }
530*700637cbSDimitry Andric
531*700637cbSDimitry Andric // Fallback to the old default set for manual table entries.
532*700637cbSDimitry Andric //
533*700637cbSDimitry Andric // TODO: Remove this when targets have switched to using generated tables by
534*700637cbSDimitry Andric // default.
535*700637cbSDimitry Andric OS << " initDefaultLibCallImpls();\n";
536*700637cbSDimitry Andric
537*700637cbSDimitry Andric OS << "}\n\n";
538*700637cbSDimitry Andric }
539*700637cbSDimitry Andric
run(raw_ostream & OS)540*700637cbSDimitry Andric void RuntimeLibcallEmitter::run(raw_ostream &OS) {
541*700637cbSDimitry Andric emitSourceFileHeader("Runtime LibCalls Source Fragment", OS, Records);
542*700637cbSDimitry Andric emitGetRuntimeLibcallEnum(OS);
543*700637cbSDimitry Andric
544*700637cbSDimitry Andric OS << "#ifdef GET_INIT_RUNTIME_LIBCALL_NAMES\n";
545*700637cbSDimitry Andric emitGetInitRuntimeLibcallNames(OS);
546*700637cbSDimitry Andric OS << "#endif\n\n";
547*700637cbSDimitry Andric
548*700637cbSDimitry Andric OS << "#ifdef GET_SET_TARGET_RUNTIME_LIBCALL_SETS\n";
549*700637cbSDimitry Andric emitSystemRuntimeLibrarySetCalls(OS);
550*700637cbSDimitry Andric OS << "#endif\n\n";
551*700637cbSDimitry Andric }
552*700637cbSDimitry Andric
expand(SetTheory & ST,const Record * Def,SetTheory::RecSet & Elts)553*700637cbSDimitry Andric void LibcallPredicateExpander::expand(SetTheory &ST, const Record *Def,
554*700637cbSDimitry Andric SetTheory::RecSet &Elts) {
555*700637cbSDimitry Andric assert(Def->isSubClassOf("LibcallImpls"));
556*700637cbSDimitry Andric
557*700637cbSDimitry Andric SetTheory::RecSet TmpElts;
558*700637cbSDimitry Andric
559*700637cbSDimitry Andric ST.evaluate(Def->getValueInit("MemberList"), TmpElts, Def->getLoc());
560*700637cbSDimitry Andric
561*700637cbSDimitry Andric Elts.insert(TmpElts.begin(), TmpElts.end());
562*700637cbSDimitry Andric
563*700637cbSDimitry Andric AvailabilityPredicate AP(Def->getValueAsDef("AvailabilityPredicate"));
564*700637cbSDimitry Andric const Record *CCClass = Def->getValueAsOptionalDef("CallingConv");
565*700637cbSDimitry Andric
566*700637cbSDimitry Andric // This is assuming we aren't conditionally applying a calling convention to
567*700637cbSDimitry Andric // some subsets, and not another, but this doesn't appear to be used.
568*700637cbSDimitry Andric
569*700637cbSDimitry Andric for (const Record *LibcallImplDef : TmpElts) {
570*700637cbSDimitry Andric const RuntimeLibcallImpl *LibcallImpl =
571*700637cbSDimitry Andric LibcallEmitter.getRuntimeLibcallImpl(LibcallImplDef);
572*700637cbSDimitry Andric if (!AP.isAlwaysAvailable() || CCClass) {
573*700637cbSDimitry Andric auto [It, Inserted] = Func2Preds.insert({LibcallImpl, {{}, CCClass}});
574*700637cbSDimitry Andric if (!Inserted) {
575*700637cbSDimitry Andric PrintError(
576*700637cbSDimitry Andric Def, "combining nested libcall set predicates currently unhandled");
577*700637cbSDimitry Andric }
578*700637cbSDimitry Andric
579*700637cbSDimitry Andric It->second.first.push_back(AP.getDef());
580*700637cbSDimitry Andric It->second.second = CCClass;
581*700637cbSDimitry Andric }
582*700637cbSDimitry Andric }
583*700637cbSDimitry Andric }
584*700637cbSDimitry Andric
585*700637cbSDimitry Andric static TableGen::Emitter::OptClass<RuntimeLibcallEmitter>
586*700637cbSDimitry Andric X("gen-runtime-libcalls", "Generate RuntimeLibcalls");
587