xref: /freebsd/contrib/llvm-project/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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