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