xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp (revision 8bcb0991864975618c09697b1aca10683346d9f0)
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 
11*8bcb0991SDimitry 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 
220b57cec5SDimitry Andric CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End)
230b57cec5SDimitry Andric   : InitList(
240b57cec5SDimitry Andric       GV ? dyn_cast_or_null<ConstantArray>(GV->getInitializer()) : nullptr),
250b57cec5SDimitry Andric     I((InitList && End) ? InitList->getNumOperands() : 0) {
260b57cec5SDimitry Andric }
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric bool CtorDtorIterator::operator==(const CtorDtorIterator &Other) const {
290b57cec5SDimitry Andric   assert(InitList == Other.InitList && "Incomparable iterators.");
300b57cec5SDimitry Andric   return I == Other.I;
310b57cec5SDimitry Andric }
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric bool CtorDtorIterator::operator!=(const CtorDtorIterator &Other) const {
340b57cec5SDimitry Andric   return !(*this == Other);
350b57cec5SDimitry Andric }
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric CtorDtorIterator& CtorDtorIterator::operator++() {
380b57cec5SDimitry Andric   ++I;
390b57cec5SDimitry Andric   return *this;
400b57cec5SDimitry Andric }
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric CtorDtorIterator CtorDtorIterator::operator++(int) {
430b57cec5SDimitry Andric   CtorDtorIterator Temp = *this;
440b57cec5SDimitry Andric   ++I;
450b57cec5SDimitry Andric   return Temp;
460b57cec5SDimitry Andric }
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric CtorDtorIterator::Element CtorDtorIterator::operator*() const {
490b57cec5SDimitry Andric   ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(I));
500b57cec5SDimitry Andric   assert(CS && "Unrecognized type in llvm.global_ctors/llvm.global_dtors");
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   Constant *FuncC = CS->getOperand(1);
530b57cec5SDimitry Andric   Function *Func = nullptr;
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   // Extract function pointer, pulling off any casts.
560b57cec5SDimitry Andric   while (FuncC) {
570b57cec5SDimitry Andric     if (Function *F = dyn_cast_or_null<Function>(FuncC)) {
580b57cec5SDimitry Andric       Func = F;
590b57cec5SDimitry Andric       break;
600b57cec5SDimitry Andric     } else if (ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(FuncC)) {
610b57cec5SDimitry Andric       if (CE->isCast())
620b57cec5SDimitry Andric         FuncC = dyn_cast_or_null<ConstantExpr>(CE->getOperand(0));
630b57cec5SDimitry Andric       else
640b57cec5SDimitry Andric         break;
650b57cec5SDimitry Andric     } else {
660b57cec5SDimitry Andric       // This isn't anything we recognize. Bail out with Func left set to null.
670b57cec5SDimitry Andric       break;
680b57cec5SDimitry Andric     }
690b57cec5SDimitry Andric   }
700b57cec5SDimitry Andric 
71*8bcb0991SDimitry Andric   auto *Priority = cast<ConstantInt>(CS->getOperand(0));
720b57cec5SDimitry Andric   Value *Data = CS->getNumOperands() == 3 ? CS->getOperand(2) : nullptr;
730b57cec5SDimitry Andric   if (Data && !isa<GlobalValue>(Data))
740b57cec5SDimitry Andric     Data = nullptr;
750b57cec5SDimitry Andric   return Element(Priority->getZExtValue(), Func, Data);
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric iterator_range<CtorDtorIterator> getConstructors(const Module &M) {
790b57cec5SDimitry Andric   const GlobalVariable *CtorsList = M.getNamedGlobal("llvm.global_ctors");
800b57cec5SDimitry Andric   return make_range(CtorDtorIterator(CtorsList, false),
810b57cec5SDimitry Andric                     CtorDtorIterator(CtorsList, true));
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric iterator_range<CtorDtorIterator> getDestructors(const Module &M) {
850b57cec5SDimitry Andric   const GlobalVariable *DtorsList = M.getNamedGlobal("llvm.global_dtors");
860b57cec5SDimitry Andric   return make_range(CtorDtorIterator(DtorsList, false),
870b57cec5SDimitry Andric                     CtorDtorIterator(DtorsList, true));
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric void CtorDtorRunner::add(iterator_range<CtorDtorIterator> CtorDtors) {
91*8bcb0991SDimitry Andric   if (CtorDtors.empty())
920b57cec5SDimitry Andric     return;
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   MangleAndInterner Mangle(
950b57cec5SDimitry Andric       JD.getExecutionSession(),
960b57cec5SDimitry Andric       (*CtorDtors.begin()).Func->getParent()->getDataLayout());
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   for (const auto &CtorDtor : CtorDtors) {
990b57cec5SDimitry Andric     assert(CtorDtor.Func && CtorDtor.Func->hasName() &&
1000b57cec5SDimitry Andric            "Ctor/Dtor function must be named to be runnable under the JIT");
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric     // FIXME: Maybe use a symbol promoter here instead.
1030b57cec5SDimitry Andric     if (CtorDtor.Func->hasLocalLinkage()) {
1040b57cec5SDimitry Andric       CtorDtor.Func->setLinkage(GlobalValue::ExternalLinkage);
1050b57cec5SDimitry Andric       CtorDtor.Func->setVisibility(GlobalValue::HiddenVisibility);
1060b57cec5SDimitry Andric     }
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric     if (CtorDtor.Data && cast<GlobalValue>(CtorDtor.Data)->isDeclaration()) {
1090b57cec5SDimitry Andric       dbgs() << "  Skipping because why now?\n";
1100b57cec5SDimitry Andric       continue;
1110b57cec5SDimitry Andric     }
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric     CtorDtorsByPriority[CtorDtor.Priority].push_back(
1140b57cec5SDimitry Andric         Mangle(CtorDtor.Func->getName()));
1150b57cec5SDimitry Andric   }
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric Error CtorDtorRunner::run() {
1190b57cec5SDimitry Andric   using CtorDtorTy = void (*)();
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   SymbolNameSet Names;
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric   for (auto &KV : CtorDtorsByPriority) {
1240b57cec5SDimitry Andric     for (auto &Name : KV.second) {
1250b57cec5SDimitry Andric       auto Added = Names.insert(Name).second;
1260b57cec5SDimitry Andric       (void)Added;
1270b57cec5SDimitry Andric       assert(Added && "Ctor/Dtor names clashed");
1280b57cec5SDimitry Andric     }
1290b57cec5SDimitry Andric   }
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   auto &ES = JD.getExecutionSession();
1320b57cec5SDimitry Andric   if (auto CtorDtorMap =
1330b57cec5SDimitry Andric           ES.lookup(JITDylibSearchList({{&JD, true}}), std::move(Names))) {
1340b57cec5SDimitry Andric     for (auto &KV : CtorDtorsByPriority) {
1350b57cec5SDimitry Andric       for (auto &Name : KV.second) {
1360b57cec5SDimitry Andric         assert(CtorDtorMap->count(Name) && "No entry for Name");
1370b57cec5SDimitry Andric         auto CtorDtor = reinterpret_cast<CtorDtorTy>(
1380b57cec5SDimitry Andric             static_cast<uintptr_t>((*CtorDtorMap)[Name].getAddress()));
1390b57cec5SDimitry Andric         CtorDtor();
1400b57cec5SDimitry Andric       }
1410b57cec5SDimitry Andric     }
1420b57cec5SDimitry Andric     CtorDtorsByPriority.clear();
1430b57cec5SDimitry Andric     return Error::success();
1440b57cec5SDimitry Andric   } else
1450b57cec5SDimitry Andric     return CtorDtorMap.takeError();
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric void LocalCXXRuntimeOverridesBase::runDestructors() {
1490b57cec5SDimitry Andric   auto& CXXDestructorDataPairs = DSOHandleOverride;
1500b57cec5SDimitry Andric   for (auto &P : CXXDestructorDataPairs)
1510b57cec5SDimitry Andric     P.first(P.second);
1520b57cec5SDimitry Andric   CXXDestructorDataPairs.clear();
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric int LocalCXXRuntimeOverridesBase::CXAAtExitOverride(DestructorPtr Destructor,
1560b57cec5SDimitry Andric                                                     void *Arg,
1570b57cec5SDimitry Andric                                                     void *DSOHandle) {
1580b57cec5SDimitry Andric   auto& CXXDestructorDataPairs =
1590b57cec5SDimitry Andric     *reinterpret_cast<CXXDestructorDataPairList*>(DSOHandle);
1600b57cec5SDimitry Andric   CXXDestructorDataPairs.push_back(std::make_pair(Destructor, Arg));
1610b57cec5SDimitry Andric   return 0;
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric Error LocalCXXRuntimeOverrides::enable(JITDylib &JD,
1650b57cec5SDimitry Andric                                         MangleAndInterner &Mangle) {
1660b57cec5SDimitry Andric   SymbolMap RuntimeInterposes;
1670b57cec5SDimitry Andric   RuntimeInterposes[Mangle("__dso_handle")] =
1680b57cec5SDimitry Andric     JITEvaluatedSymbol(toTargetAddress(&DSOHandleOverride),
1690b57cec5SDimitry Andric                        JITSymbolFlags::Exported);
1700b57cec5SDimitry Andric   RuntimeInterposes[Mangle("__cxa_atexit")] =
1710b57cec5SDimitry Andric     JITEvaluatedSymbol(toTargetAddress(&CXAAtExitOverride),
1720b57cec5SDimitry Andric                        JITSymbolFlags::Exported);
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric   return JD.define(absoluteSymbols(std::move(RuntimeInterposes)));
1750b57cec5SDimitry Andric }
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator(
1780b57cec5SDimitry Andric     sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow)
1790b57cec5SDimitry Andric     : Dylib(std::move(Dylib)), Allow(std::move(Allow)),
1800b57cec5SDimitry Andric       GlobalPrefix(GlobalPrefix) {}
1810b57cec5SDimitry Andric 
182*8bcb0991SDimitry Andric Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
1830b57cec5SDimitry Andric DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix,
1840b57cec5SDimitry Andric                                     SymbolPredicate Allow) {
1850b57cec5SDimitry Andric   std::string ErrMsg;
1860b57cec5SDimitry Andric   auto Lib = sys::DynamicLibrary::getPermanentLibrary(FileName, &ErrMsg);
1870b57cec5SDimitry Andric   if (!Lib.isValid())
1880b57cec5SDimitry Andric     return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
189*8bcb0991SDimitry Andric   return std::make_unique<DynamicLibrarySearchGenerator>(
190*8bcb0991SDimitry Andric       std::move(Lib), GlobalPrefix, std::move(Allow));
1910b57cec5SDimitry Andric }
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric Expected<SymbolNameSet>
194*8bcb0991SDimitry Andric DynamicLibrarySearchGenerator::tryToGenerate(JITDylib &JD,
1950b57cec5SDimitry Andric                                              const SymbolNameSet &Names) {
1960b57cec5SDimitry Andric   orc::SymbolNameSet Added;
1970b57cec5SDimitry Andric   orc::SymbolMap NewSymbols;
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric   bool HasGlobalPrefix = (GlobalPrefix != '\0');
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric   for (auto &Name : Names) {
2020b57cec5SDimitry Andric     if ((*Name).empty())
2030b57cec5SDimitry Andric       continue;
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric     if (Allow && !Allow(Name))
2060b57cec5SDimitry Andric       continue;
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric     if (HasGlobalPrefix && (*Name).front() != GlobalPrefix)
2090b57cec5SDimitry Andric       continue;
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric     std::string Tmp((*Name).data() + HasGlobalPrefix,
2120b57cec5SDimitry Andric                     (*Name).size() - HasGlobalPrefix);
2130b57cec5SDimitry Andric     if (void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str())) {
2140b57cec5SDimitry Andric       Added.insert(Name);
2150b57cec5SDimitry Andric       NewSymbols[Name] = JITEvaluatedSymbol(
2160b57cec5SDimitry Andric           static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(Addr)),
2170b57cec5SDimitry Andric           JITSymbolFlags::Exported);
2180b57cec5SDimitry Andric     }
2190b57cec5SDimitry Andric   }
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric   // Add any new symbols to JD. Since the generator is only called for symbols
2220b57cec5SDimitry Andric   // that are not already defined, this will never trigger a duplicate
2230b57cec5SDimitry Andric   // definition error, so we can wrap this call in a 'cantFail'.
2240b57cec5SDimitry Andric   if (!NewSymbols.empty())
2250b57cec5SDimitry Andric     cantFail(JD.define(absoluteSymbols(std::move(NewSymbols))));
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric   return Added;
2280b57cec5SDimitry Andric }
2290b57cec5SDimitry Andric 
230*8bcb0991SDimitry Andric Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
231*8bcb0991SDimitry Andric StaticLibraryDefinitionGenerator::Load(ObjectLayer &L, const char *FileName) {
232*8bcb0991SDimitry Andric   auto ArchiveBuffer = errorOrToExpected(MemoryBuffer::getFile(FileName));
233*8bcb0991SDimitry Andric 
234*8bcb0991SDimitry Andric   if (!ArchiveBuffer)
235*8bcb0991SDimitry Andric     return ArchiveBuffer.takeError();
236*8bcb0991SDimitry Andric 
237*8bcb0991SDimitry Andric   return Create(L, std::move(*ArchiveBuffer));
238*8bcb0991SDimitry Andric }
239*8bcb0991SDimitry Andric 
240*8bcb0991SDimitry Andric Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
241*8bcb0991SDimitry Andric StaticLibraryDefinitionGenerator::Create(
242*8bcb0991SDimitry Andric     ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer) {
243*8bcb0991SDimitry Andric   Error Err = Error::success();
244*8bcb0991SDimitry Andric 
245*8bcb0991SDimitry Andric   std::unique_ptr<StaticLibraryDefinitionGenerator> ADG(
246*8bcb0991SDimitry Andric       new StaticLibraryDefinitionGenerator(L, std::move(ArchiveBuffer), Err));
247*8bcb0991SDimitry Andric 
248*8bcb0991SDimitry Andric   if (Err)
249*8bcb0991SDimitry Andric     return std::move(Err);
250*8bcb0991SDimitry Andric 
251*8bcb0991SDimitry Andric   return std::move(ADG);
252*8bcb0991SDimitry Andric }
253*8bcb0991SDimitry Andric 
254*8bcb0991SDimitry Andric Expected<SymbolNameSet>
255*8bcb0991SDimitry Andric StaticLibraryDefinitionGenerator::tryToGenerate(JITDylib &JD,
256*8bcb0991SDimitry Andric                                                 const SymbolNameSet &Names) {
257*8bcb0991SDimitry Andric 
258*8bcb0991SDimitry Andric   DenseSet<std::pair<StringRef, StringRef>> ChildBufferInfos;
259*8bcb0991SDimitry Andric   SymbolNameSet NewDefs;
260*8bcb0991SDimitry Andric 
261*8bcb0991SDimitry Andric   for (const auto &Name : Names) {
262*8bcb0991SDimitry Andric     auto Child = Archive.findSym(*Name);
263*8bcb0991SDimitry Andric     if (!Child)
264*8bcb0991SDimitry Andric       return Child.takeError();
265*8bcb0991SDimitry Andric     if (*Child == None)
266*8bcb0991SDimitry Andric       continue;
267*8bcb0991SDimitry Andric     auto ChildBuffer = (*Child)->getMemoryBufferRef();
268*8bcb0991SDimitry Andric     if (!ChildBuffer)
269*8bcb0991SDimitry Andric       return ChildBuffer.takeError();
270*8bcb0991SDimitry Andric     ChildBufferInfos.insert(
271*8bcb0991SDimitry Andric         {ChildBuffer->getBuffer(), ChildBuffer->getBufferIdentifier()});
272*8bcb0991SDimitry Andric     NewDefs.insert(Name);
273*8bcb0991SDimitry Andric   }
274*8bcb0991SDimitry Andric 
275*8bcb0991SDimitry Andric   for (auto ChildBufferInfo : ChildBufferInfos) {
276*8bcb0991SDimitry Andric     MemoryBufferRef ChildBufferRef(ChildBufferInfo.first,
277*8bcb0991SDimitry Andric                                    ChildBufferInfo.second);
278*8bcb0991SDimitry Andric 
279*8bcb0991SDimitry Andric     if (auto Err =
280*8bcb0991SDimitry Andric             L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef), VModuleKey()))
281*8bcb0991SDimitry Andric       return std::move(Err);
282*8bcb0991SDimitry Andric 
283*8bcb0991SDimitry Andric     --UnrealizedObjects;
284*8bcb0991SDimitry Andric   }
285*8bcb0991SDimitry Andric 
286*8bcb0991SDimitry Andric   return NewDefs;
287*8bcb0991SDimitry Andric }
288*8bcb0991SDimitry Andric 
289*8bcb0991SDimitry Andric StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator(
290*8bcb0991SDimitry Andric     ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, Error &Err)
291*8bcb0991SDimitry Andric     : L(L), ArchiveBuffer(std::move(ArchiveBuffer)),
292*8bcb0991SDimitry Andric       Archive(*this->ArchiveBuffer, Err) {
293*8bcb0991SDimitry Andric 
294*8bcb0991SDimitry Andric   if (Err)
295*8bcb0991SDimitry Andric     return;
296*8bcb0991SDimitry Andric 
297*8bcb0991SDimitry Andric   Error Err2 = Error::success();
298*8bcb0991SDimitry Andric   for (auto _ : Archive.children(Err2)) {
299*8bcb0991SDimitry Andric     (void)_;
300*8bcb0991SDimitry Andric     ++UnrealizedObjects;
301*8bcb0991SDimitry Andric   }
302*8bcb0991SDimitry Andric 
303*8bcb0991SDimitry Andric   // No need to check this: We will leave it to the caller.
304*8bcb0991SDimitry Andric   Err = std::move(Err2);
305*8bcb0991SDimitry Andric }
306*8bcb0991SDimitry Andric 
3070b57cec5SDimitry Andric } // End namespace orc.
3080b57cec5SDimitry Andric } // End namespace llvm.
309