//===----------------------------------------------------------------------===// // // 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 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 AllRuntimeLibcallImplsRaw = Records.getAllDerivedDefinitions("RuntimeLibcallImpl"); SmallVector 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; } } }