| //===----------------------------------------------------------------------===// | |
| // | |
| // 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 "PredicateExpanderDag.h" | |
| #include "llvm/ADT/STLExtras.h" | |
| #include "llvm/Support/raw_ostream.h" | |
| #include "llvm/TableGen/Error.h" | |
| using namespace llvm; | |
| std::string AvailabilityPredicate::lowerCondDag(const Record *Owner, | |
| const Init *Val, | |
| bool ParenIfBinOp) { | |
| // Leaf: a LibcallPredicate whose Cond is a C++ boolean over `TT`. | |
| auto EmitLeaf = [&](const Init &Leaf, raw_ostream &OS) -> bool { | |
| const auto *DI = dyn_cast<DefInit>(&Leaf); | |
| if (!DI || !DI->getDef()->isSubClassOf("LibcallPredicate")) | |
| PrintFatalError(Owner, "predicate dag leaf '" + Leaf.getAsString() + | |
| "' is not a LibcallPredicate"); | |
| OS << DI->getDef()->getValueAsString("Cond"); | |
| return false; | |
| }; | |
| std::string Result; | |
| raw_string_ostream OS(Result); | |
| emitPredicateDag(Owner, *Val, ParenIfBinOp, OS, EmitLeaf); | |
| return Result; | |
| } | |
| 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; | |
| } | |
| FuncArgTypeList = Records.getAllDerivedDefinitions("FuncArgType"); | |
| } | |
| 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; | |
| } | |
| } | |
| } |