1//===----------------------------------------------------------------------===//
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 "RuntimeLibcalls.h"
10#include "llvm/TableGen/Error.h"
11
12using namespace llvm;
13
14RuntimeLibcalls::RuntimeLibcalls(const RecordKeeper &Records) {
15 ArrayRef<const Record *> AllRuntimeLibcalls =
16 Records.getAllDerivedDefinitions(ClassName: "RuntimeLibcall");
17
18 RuntimeLibcallDefList.reserve(n: AllRuntimeLibcalls.size());
19
20 size_t CallTypeEnumVal = 0;
21 for (const Record *RuntimeLibcallDef : AllRuntimeLibcalls) {
22 RuntimeLibcallDefList.emplace_back(args&: RuntimeLibcallDef, args: CallTypeEnumVal++);
23 Def2RuntimeLibcall[RuntimeLibcallDef] = &RuntimeLibcallDefList.back();
24 }
25
26 for (RuntimeLibcall &LibCall : RuntimeLibcallDefList)
27 Def2RuntimeLibcall[LibCall.getDef()] = &LibCall;
28
29 ArrayRef<const Record *> AllRuntimeLibcallImplsRaw =
30 Records.getAllDerivedDefinitions(ClassName: "RuntimeLibcallImpl");
31
32 SmallVector<const Record *, 1024> AllRuntimeLibcallImpls(
33 AllRuntimeLibcallImplsRaw);
34
35 // Sort by libcall impl name and secondarily by the enum name.
36 sort(C&: AllRuntimeLibcallImpls, Comp: [](const Record *A, const Record *B) {
37 return std::pair(A->getValueAsString(FieldName: "LibCallFuncName"), A->getName()) <
38 std::pair(B->getValueAsString(FieldName: "LibCallFuncName"), B->getName());
39 });
40
41 RuntimeLibcallImplDefList.reserve(n: AllRuntimeLibcallImpls.size());
42
43 size_t LibCallImplEnumVal = 1;
44 for (const Record *LibCallImplDef : AllRuntimeLibcallImpls) {
45 RuntimeLibcallImplDefList.emplace_back(args&: LibCallImplDef, args&: Def2RuntimeLibcall,
46 args: LibCallImplEnumVal++);
47
48 const RuntimeLibcallImpl &LibCallImpl = RuntimeLibcallImplDefList.back();
49 Def2RuntimeLibcallImpl[LibCallImplDef] = &LibCallImpl;
50
51 if (LibCallImpl.isDefault()) {
52 const RuntimeLibcall *Provides = LibCallImpl.getProvides();
53 if (!Provides)
54 PrintFatalError(ErrorLoc: LibCallImplDef->getLoc(),
55 Msg: "default implementations must provide a libcall");
56 LibCallToDefaultImpl[Provides] = &LibCallImpl;
57 }
58 }
59}
60
61void LibcallPredicateExpander::expand(SetTheory &ST, const Record *Def,
62 SetTheory::RecSet &Elts) {
63 assert(Def->isSubClassOf("LibcallImpls"));
64
65 SetTheory::RecSet TmpElts;
66
67 ST.evaluate(Expr: Def->getValueInit(FieldName: "MemberList"), Elts&: TmpElts, Loc: Def->getLoc());
68
69 Elts.insert(Start: TmpElts.begin(), End: TmpElts.end());
70
71 AvailabilityPredicate AP(Def->getValueAsDef(FieldName: "AvailabilityPredicate"));
72 const Record *CCClass = Def->getValueAsOptionalDef(FieldName: "CallingConv");
73
74 // This is assuming we aren't conditionally applying a calling convention to
75 // some subsets, and not another, but this doesn't appear to be used.
76
77 for (const Record *LibcallImplDef : TmpElts) {
78 const RuntimeLibcallImpl *LibcallImpl =
79 Libcalls.getRuntimeLibcallImpl(Def: LibcallImplDef);
80 if (!AP.isAlwaysAvailable() || CCClass) {
81 auto [It, Inserted] = Func2Preds.insert(KV: {LibcallImpl, {{}, CCClass}});
82 if (!Inserted) {
83 PrintError(
84 Rec: Def,
85 Msg: "combining nested libcall set predicates currently unhandled: '" +
86 LibcallImpl->getLibcallFuncName() + "'");
87 }
88
89 It->second.first.push_back(x: AP.getDef());
90 It->second.second = CCClass;
91 }
92 }
93}
94