aboutsummaryrefslogtreecommitdiff
path: root/llvm/utils/TableGen/Basic/RuntimeLibcalls.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/utils/TableGen/Basic/RuntimeLibcalls.cpp')
-rw-r--r--llvm/utils/TableGen/Basic/RuntimeLibcalls.cpp93
1 files changed, 93 insertions, 0 deletions
diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcalls.cpp b/llvm/utils/TableGen/Basic/RuntimeLibcalls.cpp
new file mode 100644
index 0000000..1e609a2
--- /dev/null
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcalls.cpp
@@ -0,0 +1,93 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RuntimeLibcalls.h"
+#include "llvm/TableGen/Error.h"
+
+using namespace llvm;
+
+RuntimeLibcalls::RuntimeLibcalls(const RecordKeeper &Records) {
+ ArrayRef<const Record *> AllRuntimeLibcalls =
+ Records.getAllDerivedDefinitions("RuntimeLibcall");
+
+ RuntimeLibcallDefList.reserve(AllRuntimeLibcalls.size());
+
+ size_t CallTypeEnumVal = 0;
+ for (const Record *RuntimeLibcallDef : AllRuntimeLibcalls) {
+ RuntimeLibcallDefList.emplace_back(RuntimeLibcallDef, CallTypeEnumVal++);
+ Def2RuntimeLibcall[RuntimeLibcallDef] = &RuntimeLibcallDefList.back();
+ }
+
+ for (RuntimeLibcall &LibCall : RuntimeLibcallDefList)
+ Def2RuntimeLibcall[LibCall.getDef()] = &LibCall;
+
+ ArrayRef<const Record *> AllRuntimeLibcallImplsRaw =
+ Records.getAllDerivedDefinitions("RuntimeLibcallImpl");
+
+ SmallVector<const Record *, 1024> AllRuntimeLibcallImpls(
+ AllRuntimeLibcallImplsRaw);
+
+ // Sort by libcall impl name and secondarily by the enum name.
+ sort(AllRuntimeLibcallImpls, [](const Record *A, const Record *B) {
+ return std::pair(A->getValueAsString("LibCallFuncName"), A->getName()) <
+ std::pair(B->getValueAsString("LibCallFuncName"), B->getName());
+ });
+
+ RuntimeLibcallImplDefList.reserve(AllRuntimeLibcallImpls.size());
+
+ size_t LibCallImplEnumVal = 1;
+ for (const Record *LibCallImplDef : AllRuntimeLibcallImpls) {
+ RuntimeLibcallImplDefList.emplace_back(LibCallImplDef, Def2RuntimeLibcall,
+ LibCallImplEnumVal++);
+
+ const RuntimeLibcallImpl &LibCallImpl = RuntimeLibcallImplDefList.back();
+ Def2RuntimeLibcallImpl[LibCallImplDef] = &LibCallImpl;
+
+ if (LibCallImpl.isDefault()) {
+ const RuntimeLibcall *Provides = LibCallImpl.getProvides();
+ if (!Provides)
+ PrintFatalError(LibCallImplDef->getLoc(),
+ "default implementations must provide a libcall");
+ LibCallToDefaultImpl[Provides] = &LibCallImpl;
+ }
+ }
+}
+
+void LibcallPredicateExpander::expand(SetTheory &ST, const Record *Def,
+ SetTheory::RecSet &Elts) {
+ assert(Def->isSubClassOf("LibcallImpls"));
+
+ SetTheory::RecSet TmpElts;
+
+ ST.evaluate(Def->getValueInit("MemberList"), TmpElts, Def->getLoc());
+
+ Elts.insert(TmpElts.begin(), TmpElts.end());
+
+ AvailabilityPredicate AP(Def->getValueAsDef("AvailabilityPredicate"));
+ const Record *CCClass = Def->getValueAsOptionalDef("CallingConv");
+
+ // This is assuming we aren't conditionally applying a calling convention to
+ // some subsets, and not another, but this doesn't appear to be used.
+
+ for (const Record *LibcallImplDef : TmpElts) {
+ const RuntimeLibcallImpl *LibcallImpl =
+ Libcalls.getRuntimeLibcallImpl(LibcallImplDef);
+ if (!AP.isAlwaysAvailable() || CCClass) {
+ auto [It, Inserted] = Func2Preds.insert({LibcallImpl, {{}, CCClass}});
+ if (!Inserted) {
+ PrintError(
+ Def,
+ "combining nested libcall set predicates currently unhandled: '" +
+ LibcallImpl->getLibcallFuncName() + "'");
+ }
+
+ It->second.first.push_back(AP.getDef());
+ It->second.second = CCClass;
+ }
+ }
+}