94 lines · cpp
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-exception6//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("RuntimeLibcall");17 18 RuntimeLibcallDefList.reserve(AllRuntimeLibcalls.size());19 20 size_t CallTypeEnumVal = 0;21 for (const Record *RuntimeLibcallDef : AllRuntimeLibcalls) {22 RuntimeLibcallDefList.emplace_back(RuntimeLibcallDef, 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("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(AllRuntimeLibcallImpls, [](const Record *A, const Record *B) {37 return std::pair(A->getValueAsString("LibCallFuncName"), A->getName()) <38 std::pair(B->getValueAsString("LibCallFuncName"), B->getName());39 });40 41 RuntimeLibcallImplDefList.reserve(AllRuntimeLibcallImpls.size());42 43 size_t LibCallImplEnumVal = 1;44 for (const Record *LibCallImplDef : AllRuntimeLibcallImpls) {45 RuntimeLibcallImplDefList.emplace_back(LibCallImplDef, Def2RuntimeLibcall,46 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(LibCallImplDef->getLoc(),55 "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(Def->getValueInit("MemberList"), TmpElts, Def->getLoc());68 69 Elts.insert(TmpElts.begin(), TmpElts.end());70 71 AvailabilityPredicate AP(Def->getValueAsDef("AvailabilityPredicate"));72 const Record *CCClass = Def->getValueAsOptionalDef("CallingConv");73 74 // This is assuming we aren't conditionally applying a calling convention to75 // 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(LibcallImplDef);80 if (!AP.isAlwaysAvailable() || CCClass) {81 auto [It, Inserted] = Func2Preds.insert({LibcallImpl, {{}, CCClass}});82 if (!Inserted) {83 PrintError(84 Def,85 "combining nested libcall set predicates currently unhandled: '" +86 LibcallImpl->getLibcallFuncName() + "'");87 }88 89 It->second.first.push_back(AP.getDef());90 It->second.second = CCClass;91 }92 }93}94