xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp (revision 480093f4440d54b30b3025afeac24b48f2ba7a2e)
10b57cec5SDimitry Andric //===---- ExecutionUtils.cpp - Utilities for executing functions in Orc ---===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
100b57cec5SDimitry Andric 
118bcb0991SDimitry Andric #include "llvm/ExecutionEngine/Orc/Layer.h"
120b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
130b57cec5SDimitry Andric #include "llvm/IR/Function.h"
140b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h"
150b57cec5SDimitry Andric #include "llvm/IR/Module.h"
160b57cec5SDimitry Andric #include "llvm/Support/TargetRegistry.h"
170b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric namespace llvm {
200b57cec5SDimitry Andric namespace orc {
210b57cec5SDimitry Andric 
22*480093f4SDimitry Andric int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args,
23*480093f4SDimitry Andric               Optional<StringRef> ProgramName) {
24*480093f4SDimitry Andric   std::vector<std::unique_ptr<char[]>> ArgVStorage;
25*480093f4SDimitry Andric   std::vector<char *> ArgV;
26*480093f4SDimitry Andric 
27*480093f4SDimitry Andric   ArgVStorage.reserve(Args.size() + (ProgramName ? 1 : 0));
28*480093f4SDimitry Andric   ArgV.reserve(Args.size() + 1 + (ProgramName ? 1 : 0));
29*480093f4SDimitry Andric 
30*480093f4SDimitry Andric   if (ProgramName) {
31*480093f4SDimitry Andric     ArgVStorage.push_back(std::make_unique<char[]>(ProgramName->size() + 1));
32*480093f4SDimitry Andric     llvm::copy(*ProgramName, &ArgVStorage.back()[0]);
33*480093f4SDimitry Andric     ArgVStorage.back()[ProgramName->size()] = '\0';
34*480093f4SDimitry Andric     ArgV.push_back(ArgVStorage.back().get());
35*480093f4SDimitry Andric   }
36*480093f4SDimitry Andric 
37*480093f4SDimitry Andric   for (auto &Arg : Args) {
38*480093f4SDimitry Andric     ArgVStorage.push_back(std::make_unique<char[]>(Arg.size() + 1));
39*480093f4SDimitry Andric     llvm::copy(Arg, &ArgVStorage.back()[0]);
40*480093f4SDimitry Andric     ArgVStorage.back()[Arg.size()] = '\0';
41*480093f4SDimitry Andric     ArgV.push_back(ArgVStorage.back().get());
42*480093f4SDimitry Andric   }
43*480093f4SDimitry Andric   ArgV.push_back(nullptr);
44*480093f4SDimitry Andric 
45*480093f4SDimitry Andric   return Main(Args.size() + !!ProgramName, ArgV.data());
46*480093f4SDimitry Andric }
47*480093f4SDimitry Andric 
480b57cec5SDimitry Andric CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End)
490b57cec5SDimitry Andric   : InitList(
500b57cec5SDimitry Andric       GV ? dyn_cast_or_null<ConstantArray>(GV->getInitializer()) : nullptr),
510b57cec5SDimitry Andric     I((InitList && End) ? InitList->getNumOperands() : 0) {
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric bool CtorDtorIterator::operator==(const CtorDtorIterator &Other) const {
550b57cec5SDimitry Andric   assert(InitList == Other.InitList && "Incomparable iterators.");
560b57cec5SDimitry Andric   return I == Other.I;
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric bool CtorDtorIterator::operator!=(const CtorDtorIterator &Other) const {
600b57cec5SDimitry Andric   return !(*this == Other);
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric CtorDtorIterator& CtorDtorIterator::operator++() {
640b57cec5SDimitry Andric   ++I;
650b57cec5SDimitry Andric   return *this;
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric CtorDtorIterator CtorDtorIterator::operator++(int) {
690b57cec5SDimitry Andric   CtorDtorIterator Temp = *this;
700b57cec5SDimitry Andric   ++I;
710b57cec5SDimitry Andric   return Temp;
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric CtorDtorIterator::Element CtorDtorIterator::operator*() const {
750b57cec5SDimitry Andric   ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(I));
760b57cec5SDimitry Andric   assert(CS && "Unrecognized type in llvm.global_ctors/llvm.global_dtors");
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   Constant *FuncC = CS->getOperand(1);
790b57cec5SDimitry Andric   Function *Func = nullptr;
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   // Extract function pointer, pulling off any casts.
820b57cec5SDimitry Andric   while (FuncC) {
830b57cec5SDimitry Andric     if (Function *F = dyn_cast_or_null<Function>(FuncC)) {
840b57cec5SDimitry Andric       Func = F;
850b57cec5SDimitry Andric       break;
860b57cec5SDimitry Andric     } else if (ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(FuncC)) {
870b57cec5SDimitry Andric       if (CE->isCast())
880b57cec5SDimitry Andric         FuncC = dyn_cast_or_null<ConstantExpr>(CE->getOperand(0));
890b57cec5SDimitry Andric       else
900b57cec5SDimitry Andric         break;
910b57cec5SDimitry Andric     } else {
920b57cec5SDimitry Andric       // This isn't anything we recognize. Bail out with Func left set to null.
930b57cec5SDimitry Andric       break;
940b57cec5SDimitry Andric     }
950b57cec5SDimitry Andric   }
960b57cec5SDimitry Andric 
978bcb0991SDimitry Andric   auto *Priority = cast<ConstantInt>(CS->getOperand(0));
980b57cec5SDimitry Andric   Value *Data = CS->getNumOperands() == 3 ? CS->getOperand(2) : nullptr;
990b57cec5SDimitry Andric   if (Data && !isa<GlobalValue>(Data))
1000b57cec5SDimitry Andric     Data = nullptr;
1010b57cec5SDimitry Andric   return Element(Priority->getZExtValue(), Func, Data);
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric iterator_range<CtorDtorIterator> getConstructors(const Module &M) {
1050b57cec5SDimitry Andric   const GlobalVariable *CtorsList = M.getNamedGlobal("llvm.global_ctors");
1060b57cec5SDimitry Andric   return make_range(CtorDtorIterator(CtorsList, false),
1070b57cec5SDimitry Andric                     CtorDtorIterator(CtorsList, true));
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric iterator_range<CtorDtorIterator> getDestructors(const Module &M) {
1110b57cec5SDimitry Andric   const GlobalVariable *DtorsList = M.getNamedGlobal("llvm.global_dtors");
1120b57cec5SDimitry Andric   return make_range(CtorDtorIterator(DtorsList, false),
1130b57cec5SDimitry Andric                     CtorDtorIterator(DtorsList, true));
1140b57cec5SDimitry Andric }
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric void CtorDtorRunner::add(iterator_range<CtorDtorIterator> CtorDtors) {
1178bcb0991SDimitry Andric   if (CtorDtors.empty())
1180b57cec5SDimitry Andric     return;
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   MangleAndInterner Mangle(
1210b57cec5SDimitry Andric       JD.getExecutionSession(),
1220b57cec5SDimitry Andric       (*CtorDtors.begin()).Func->getParent()->getDataLayout());
1230b57cec5SDimitry Andric 
124*480093f4SDimitry Andric   for (auto CtorDtor : CtorDtors) {
1250b57cec5SDimitry Andric     assert(CtorDtor.Func && CtorDtor.Func->hasName() &&
1260b57cec5SDimitry Andric            "Ctor/Dtor function must be named to be runnable under the JIT");
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric     // FIXME: Maybe use a symbol promoter here instead.
1290b57cec5SDimitry Andric     if (CtorDtor.Func->hasLocalLinkage()) {
1300b57cec5SDimitry Andric       CtorDtor.Func->setLinkage(GlobalValue::ExternalLinkage);
1310b57cec5SDimitry Andric       CtorDtor.Func->setVisibility(GlobalValue::HiddenVisibility);
1320b57cec5SDimitry Andric     }
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric     if (CtorDtor.Data && cast<GlobalValue>(CtorDtor.Data)->isDeclaration()) {
1350b57cec5SDimitry Andric       dbgs() << "  Skipping because why now?\n";
1360b57cec5SDimitry Andric       continue;
1370b57cec5SDimitry Andric     }
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric     CtorDtorsByPriority[CtorDtor.Priority].push_back(
1400b57cec5SDimitry Andric         Mangle(CtorDtor.Func->getName()));
1410b57cec5SDimitry Andric   }
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric Error CtorDtorRunner::run() {
1450b57cec5SDimitry Andric   using CtorDtorTy = void (*)();
1460b57cec5SDimitry Andric 
147*480093f4SDimitry Andric   SymbolLookupSet LookupSet;
148*480093f4SDimitry Andric   for (auto &KV : CtorDtorsByPriority)
149*480093f4SDimitry Andric     for (auto &Name : KV.second)
150*480093f4SDimitry Andric       LookupSet.add(Name);
151*480093f4SDimitry Andric   assert(!LookupSet.containsDuplicates() &&
152*480093f4SDimitry Andric          "Ctor/Dtor list contains duplicates");
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   auto &ES = JD.getExecutionSession();
155*480093f4SDimitry Andric   if (auto CtorDtorMap = ES.lookup(
156*480093f4SDimitry Andric           makeJITDylibSearchOrder(&JD, JITDylibLookupFlags::MatchAllSymbols),
157*480093f4SDimitry Andric           std::move(LookupSet))) {
1580b57cec5SDimitry Andric     for (auto &KV : CtorDtorsByPriority) {
1590b57cec5SDimitry Andric       for (auto &Name : KV.second) {
1600b57cec5SDimitry Andric         assert(CtorDtorMap->count(Name) && "No entry for Name");
1610b57cec5SDimitry Andric         auto CtorDtor = reinterpret_cast<CtorDtorTy>(
1620b57cec5SDimitry Andric             static_cast<uintptr_t>((*CtorDtorMap)[Name].getAddress()));
1630b57cec5SDimitry Andric         CtorDtor();
1640b57cec5SDimitry Andric       }
1650b57cec5SDimitry Andric     }
1660b57cec5SDimitry Andric     CtorDtorsByPriority.clear();
1670b57cec5SDimitry Andric     return Error::success();
1680b57cec5SDimitry Andric   } else
1690b57cec5SDimitry Andric     return CtorDtorMap.takeError();
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric void LocalCXXRuntimeOverridesBase::runDestructors() {
1730b57cec5SDimitry Andric   auto& CXXDestructorDataPairs = DSOHandleOverride;
1740b57cec5SDimitry Andric   for (auto &P : CXXDestructorDataPairs)
1750b57cec5SDimitry Andric     P.first(P.second);
1760b57cec5SDimitry Andric   CXXDestructorDataPairs.clear();
1770b57cec5SDimitry Andric }
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric int LocalCXXRuntimeOverridesBase::CXAAtExitOverride(DestructorPtr Destructor,
1800b57cec5SDimitry Andric                                                     void *Arg,
1810b57cec5SDimitry Andric                                                     void *DSOHandle) {
1820b57cec5SDimitry Andric   auto& CXXDestructorDataPairs =
1830b57cec5SDimitry Andric     *reinterpret_cast<CXXDestructorDataPairList*>(DSOHandle);
1840b57cec5SDimitry Andric   CXXDestructorDataPairs.push_back(std::make_pair(Destructor, Arg));
1850b57cec5SDimitry Andric   return 0;
1860b57cec5SDimitry Andric }
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric Error LocalCXXRuntimeOverrides::enable(JITDylib &JD,
1890b57cec5SDimitry Andric                                         MangleAndInterner &Mangle) {
1900b57cec5SDimitry Andric   SymbolMap RuntimeInterposes;
1910b57cec5SDimitry Andric   RuntimeInterposes[Mangle("__dso_handle")] =
1920b57cec5SDimitry Andric     JITEvaluatedSymbol(toTargetAddress(&DSOHandleOverride),
1930b57cec5SDimitry Andric                        JITSymbolFlags::Exported);
1940b57cec5SDimitry Andric   RuntimeInterposes[Mangle("__cxa_atexit")] =
1950b57cec5SDimitry Andric     JITEvaluatedSymbol(toTargetAddress(&CXAAtExitOverride),
1960b57cec5SDimitry Andric                        JITSymbolFlags::Exported);
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   return JD.define(absoluteSymbols(std::move(RuntimeInterposes)));
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator(
2020b57cec5SDimitry Andric     sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow)
2030b57cec5SDimitry Andric     : Dylib(std::move(Dylib)), Allow(std::move(Allow)),
2040b57cec5SDimitry Andric       GlobalPrefix(GlobalPrefix) {}
2050b57cec5SDimitry Andric 
2068bcb0991SDimitry Andric Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
2070b57cec5SDimitry Andric DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix,
2080b57cec5SDimitry Andric                                     SymbolPredicate Allow) {
2090b57cec5SDimitry Andric   std::string ErrMsg;
2100b57cec5SDimitry Andric   auto Lib = sys::DynamicLibrary::getPermanentLibrary(FileName, &ErrMsg);
2110b57cec5SDimitry Andric   if (!Lib.isValid())
2120b57cec5SDimitry Andric     return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
2138bcb0991SDimitry Andric   return std::make_unique<DynamicLibrarySearchGenerator>(
2148bcb0991SDimitry Andric       std::move(Lib), GlobalPrefix, std::move(Allow));
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric 
217*480093f4SDimitry Andric Error DynamicLibrarySearchGenerator::tryToGenerate(
218*480093f4SDimitry Andric     LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
219*480093f4SDimitry Andric     const SymbolLookupSet &Symbols) {
2200b57cec5SDimitry Andric   orc::SymbolMap NewSymbols;
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric   bool HasGlobalPrefix = (GlobalPrefix != '\0');
2230b57cec5SDimitry Andric 
224*480093f4SDimitry Andric   for (auto &KV : Symbols) {
225*480093f4SDimitry Andric     auto &Name = KV.first;
226*480093f4SDimitry Andric 
2270b57cec5SDimitry Andric     if ((*Name).empty())
2280b57cec5SDimitry Andric       continue;
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric     if (Allow && !Allow(Name))
2310b57cec5SDimitry Andric       continue;
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric     if (HasGlobalPrefix && (*Name).front() != GlobalPrefix)
2340b57cec5SDimitry Andric       continue;
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric     std::string Tmp((*Name).data() + HasGlobalPrefix,
2370b57cec5SDimitry Andric                     (*Name).size() - HasGlobalPrefix);
2380b57cec5SDimitry Andric     if (void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str())) {
2390b57cec5SDimitry Andric       NewSymbols[Name] = JITEvaluatedSymbol(
2400b57cec5SDimitry Andric           static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(Addr)),
2410b57cec5SDimitry Andric           JITSymbolFlags::Exported);
2420b57cec5SDimitry Andric     }
2430b57cec5SDimitry Andric   }
2440b57cec5SDimitry Andric 
245*480093f4SDimitry Andric   if (NewSymbols.empty())
246*480093f4SDimitry Andric     return Error::success();
2470b57cec5SDimitry Andric 
248*480093f4SDimitry Andric   return JD.define(absoluteSymbols(std::move(NewSymbols)));
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric 
2518bcb0991SDimitry Andric Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
2528bcb0991SDimitry Andric StaticLibraryDefinitionGenerator::Load(ObjectLayer &L, const char *FileName) {
2538bcb0991SDimitry Andric   auto ArchiveBuffer = errorOrToExpected(MemoryBuffer::getFile(FileName));
2548bcb0991SDimitry Andric 
2558bcb0991SDimitry Andric   if (!ArchiveBuffer)
2568bcb0991SDimitry Andric     return ArchiveBuffer.takeError();
2578bcb0991SDimitry Andric 
2588bcb0991SDimitry Andric   return Create(L, std::move(*ArchiveBuffer));
2598bcb0991SDimitry Andric }
2608bcb0991SDimitry Andric 
2618bcb0991SDimitry Andric Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
2628bcb0991SDimitry Andric StaticLibraryDefinitionGenerator::Create(
2638bcb0991SDimitry Andric     ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer) {
2648bcb0991SDimitry Andric   Error Err = Error::success();
2658bcb0991SDimitry Andric 
2668bcb0991SDimitry Andric   std::unique_ptr<StaticLibraryDefinitionGenerator> ADG(
2678bcb0991SDimitry Andric       new StaticLibraryDefinitionGenerator(L, std::move(ArchiveBuffer), Err));
2688bcb0991SDimitry Andric 
2698bcb0991SDimitry Andric   if (Err)
2708bcb0991SDimitry Andric     return std::move(Err);
2718bcb0991SDimitry Andric 
2728bcb0991SDimitry Andric   return std::move(ADG);
2738bcb0991SDimitry Andric }
2748bcb0991SDimitry Andric 
275*480093f4SDimitry Andric Error StaticLibraryDefinitionGenerator::tryToGenerate(
276*480093f4SDimitry Andric     LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
277*480093f4SDimitry Andric     const SymbolLookupSet &Symbols) {
278*480093f4SDimitry Andric 
279*480093f4SDimitry Andric   // Don't materialize symbols from static archives unless this is a static
280*480093f4SDimitry Andric   // lookup.
281*480093f4SDimitry Andric   if (K != LookupKind::Static)
282*480093f4SDimitry Andric     return Error::success();
283*480093f4SDimitry Andric 
284*480093f4SDimitry Andric   // Bail out early if we've already freed the archive.
285*480093f4SDimitry Andric   if (!Archive)
286*480093f4SDimitry Andric     return Error::success();
2878bcb0991SDimitry Andric 
2888bcb0991SDimitry Andric   DenseSet<std::pair<StringRef, StringRef>> ChildBufferInfos;
2898bcb0991SDimitry Andric 
290*480093f4SDimitry Andric   for (const auto &KV : Symbols) {
291*480093f4SDimitry Andric     const auto &Name = KV.first;
292*480093f4SDimitry Andric     auto Child = Archive->findSym(*Name);
2938bcb0991SDimitry Andric     if (!Child)
2948bcb0991SDimitry Andric       return Child.takeError();
2958bcb0991SDimitry Andric     if (*Child == None)
2968bcb0991SDimitry Andric       continue;
2978bcb0991SDimitry Andric     auto ChildBuffer = (*Child)->getMemoryBufferRef();
2988bcb0991SDimitry Andric     if (!ChildBuffer)
2998bcb0991SDimitry Andric       return ChildBuffer.takeError();
3008bcb0991SDimitry Andric     ChildBufferInfos.insert(
3018bcb0991SDimitry Andric         {ChildBuffer->getBuffer(), ChildBuffer->getBufferIdentifier()});
3028bcb0991SDimitry Andric   }
3038bcb0991SDimitry Andric 
3048bcb0991SDimitry Andric   for (auto ChildBufferInfo : ChildBufferInfos) {
3058bcb0991SDimitry Andric     MemoryBufferRef ChildBufferRef(ChildBufferInfo.first,
3068bcb0991SDimitry Andric                                    ChildBufferInfo.second);
3078bcb0991SDimitry Andric 
3088bcb0991SDimitry Andric     if (auto Err =
3098bcb0991SDimitry Andric             L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef), VModuleKey()))
310*480093f4SDimitry Andric       return Err;
3118bcb0991SDimitry Andric   }
3128bcb0991SDimitry Andric 
313*480093f4SDimitry Andric   return Error::success();
3148bcb0991SDimitry Andric }
3158bcb0991SDimitry Andric 
3168bcb0991SDimitry Andric StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator(
3178bcb0991SDimitry Andric     ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, Error &Err)
3188bcb0991SDimitry Andric     : L(L), ArchiveBuffer(std::move(ArchiveBuffer)),
319*480093f4SDimitry Andric       Archive(std::make_unique<object::Archive>(*this->ArchiveBuffer, Err)) {}
3208bcb0991SDimitry Andric 
3210b57cec5SDimitry Andric } // End namespace orc.
3220b57cec5SDimitry Andric } // End namespace llvm.
323