1b1cd98a1SLang Hames //===---- ExecutionUtils.cpp - Utilities for executing functions in Orc ---===//
2b1cd98a1SLang Hames //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b1cd98a1SLang Hames //
7b1cd98a1SLang Hames //===----------------------------------------------------------------------===//
8b1cd98a1SLang Hames 
9b1cd98a1SLang Hames #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
1052a34a78SLang Hames #include "llvm/ExecutionEngine/Orc/Layer.h"
1102fc8d5cSLang Hames #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
12b1cd98a1SLang Hames #include "llvm/IR/Constants.h"
13b1cd98a1SLang Hames #include "llvm/IR/Function.h"
14b1cd98a1SLang Hames #include "llvm/IR/GlobalVariable.h"
15b1cd98a1SLang Hames #include "llvm/IR/Module.h"
1689b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
171b39c6f6SLang Hames #include "llvm/Object/MachOUniversal.h"
181b39c6f6SLang Hames #include "llvm/Support/FormatVariadic.h"
196a94134bSLang Hames #include "llvm/Target/TargetMachine.h"
20367ec775SSimon Pilgrim #include <string>
21b1cd98a1SLang Hames 
22b1cd98a1SLang Hames namespace llvm {
23b1cd98a1SLang Hames namespace orc {
24b1cd98a1SLang Hames 
CtorDtorIterator(const GlobalVariable * GV,bool End)25b1cd98a1SLang Hames CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End)
26b1cd98a1SLang Hames   : InitList(
27b1cd98a1SLang Hames       GV ? dyn_cast_or_null<ConstantArray>(GV->getInitializer()) : nullptr),
28b1cd98a1SLang Hames     I((InitList && End) ? InitList->getNumOperands() : 0) {
29b1cd98a1SLang Hames }
30b1cd98a1SLang Hames 
operator ==(const CtorDtorIterator & Other) const31b1cd98a1SLang Hames bool CtorDtorIterator::operator==(const CtorDtorIterator &Other) const {
32b1cd98a1SLang Hames   assert(InitList == Other.InitList && "Incomparable iterators.");
33b1cd98a1SLang Hames   return I == Other.I;
34b1cd98a1SLang Hames }
35b1cd98a1SLang Hames 
operator !=(const CtorDtorIterator & Other) const36b1cd98a1SLang Hames bool CtorDtorIterator::operator!=(const CtorDtorIterator &Other) const {
37b1cd98a1SLang Hames   return !(*this == Other);
38b1cd98a1SLang Hames }
39b1cd98a1SLang Hames 
operator ++()40b1cd98a1SLang Hames CtorDtorIterator& CtorDtorIterator::operator++() {
41b1cd98a1SLang Hames   ++I;
42b1cd98a1SLang Hames   return *this;
43b1cd98a1SLang Hames }
44b1cd98a1SLang Hames 
operator ++(int)45b1cd98a1SLang Hames CtorDtorIterator CtorDtorIterator::operator++(int) {
46b1cd98a1SLang Hames   CtorDtorIterator Temp = *this;
47b1cd98a1SLang Hames   ++I;
48b1cd98a1SLang Hames   return Temp;
49b1cd98a1SLang Hames }
50b1cd98a1SLang Hames 
operator *() const51b1cd98a1SLang Hames CtorDtorIterator::Element CtorDtorIterator::operator*() const {
52b1cd98a1SLang Hames   ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(I));
53b1cd98a1SLang Hames   assert(CS && "Unrecognized type in llvm.global_ctors/llvm.global_dtors");
54b1cd98a1SLang Hames 
55b1cd98a1SLang Hames   Constant *FuncC = CS->getOperand(1);
56b1cd98a1SLang Hames   Function *Func = nullptr;
57b1cd98a1SLang Hames 
58b1cd98a1SLang Hames   // Extract function pointer, pulling off any casts.
59b1cd98a1SLang Hames   while (FuncC) {
60b1cd98a1SLang Hames     if (Function *F = dyn_cast_or_null<Function>(FuncC)) {
61b1cd98a1SLang Hames       Func = F;
62b1cd98a1SLang Hames       break;
63b1cd98a1SLang Hames     } else if (ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(FuncC)) {
64b1cd98a1SLang Hames       if (CE->isCast())
65a76209c2SLang Hames         FuncC = CE->getOperand(0);
66b1cd98a1SLang Hames       else
67b1cd98a1SLang Hames         break;
68b1cd98a1SLang Hames     } else {
69b1cd98a1SLang Hames       // This isn't anything we recognize. Bail out with Func left set to null.
70b1cd98a1SLang Hames       break;
71b1cd98a1SLang Hames     }
72b1cd98a1SLang Hames   }
73b1cd98a1SLang Hames 
747efa6e31SSimon Pilgrim   auto *Priority = cast<ConstantInt>(CS->getOperand(0));
755721ee48SLang Hames   Value *Data = CS->getNumOperands() == 3 ? CS->getOperand(2) : nullptr;
762f178244SLang Hames   if (Data && !isa<GlobalValue>(Data))
776a94134bSLang Hames     Data = nullptr;
78b1cd98a1SLang Hames   return Element(Priority->getZExtValue(), Func, Data);
79b1cd98a1SLang Hames }
80b1cd98a1SLang Hames 
getConstructors(const Module & M)81b1cd98a1SLang Hames iterator_range<CtorDtorIterator> getConstructors(const Module &M) {
82b1cd98a1SLang Hames   const GlobalVariable *CtorsList = M.getNamedGlobal("llvm.global_ctors");
83b1cd98a1SLang Hames   return make_range(CtorDtorIterator(CtorsList, false),
84b1cd98a1SLang Hames                     CtorDtorIterator(CtorsList, true));
85b1cd98a1SLang Hames }
86b1cd98a1SLang Hames 
getDestructors(const Module & M)87b1cd98a1SLang Hames iterator_range<CtorDtorIterator> getDestructors(const Module &M) {
88b1cd98a1SLang Hames   const GlobalVariable *DtorsList = M.getNamedGlobal("llvm.global_dtors");
89b1cd98a1SLang Hames   return make_range(CtorDtorIterator(DtorsList, false),
90b1cd98a1SLang Hames                     CtorDtorIterator(DtorsList, true));
91b1cd98a1SLang Hames }
92b1cd98a1SLang Hames 
isStaticInitGlobal(GlobalValue & GV)9385fb9976SLang Hames bool StaticInitGVIterator::isStaticInitGlobal(GlobalValue &GV) {
9485fb9976SLang Hames   if (GV.isDeclaration())
9585fb9976SLang Hames     return false;
9685fb9976SLang Hames 
9785fb9976SLang Hames   if (GV.hasName() && (GV.getName() == "llvm.global_ctors" ||
9885fb9976SLang Hames                        GV.getName() == "llvm.global_dtors"))
9985fb9976SLang Hames     return true;
10085fb9976SLang Hames 
10185fb9976SLang Hames   if (ObjFmt == Triple::MachO) {
10285fb9976SLang Hames     // FIXME: These section checks are too strict: We should match first and
10385fb9976SLang Hames     // second word split by comma.
10485fb9976SLang Hames     if (GV.hasSection() &&
10585fb9976SLang Hames         (GV.getSection().startswith("__DATA,__objc_classlist") ||
10685fb9976SLang Hames          GV.getSection().startswith("__DATA,__objc_selrefs")))
10785fb9976SLang Hames       return true;
10885fb9976SLang Hames   }
10985fb9976SLang Hames 
11085fb9976SLang Hames   return false;
11185fb9976SLang Hames }
11285fb9976SLang Hames 
add(iterator_range<CtorDtorIterator> CtorDtors)113079df9abSLang Hames void CtorDtorRunner::add(iterator_range<CtorDtorIterator> CtorDtors) {
114fdaa7421SJordan Rose   if (CtorDtors.empty())
1156a94134bSLang Hames     return;
1166a94134bSLang Hames 
1176a94134bSLang Hames   MangleAndInterner Mangle(
118d5f56c59SLang Hames       JD.getExecutionSession(),
1196a94134bSLang Hames       (*CtorDtors.begin()).Func->getParent()->getDataLayout());
1206a94134bSLang Hames 
1218dc7b982SMark de Wever   for (auto CtorDtor : CtorDtors) {
1226a94134bSLang Hames     assert(CtorDtor.Func && CtorDtor.Func->hasName() &&
1236a94134bSLang Hames            "Ctor/Dtor function must be named to be runnable under the JIT");
1246a94134bSLang Hames 
125bf6603e9SLang Hames     // FIXME: Maybe use a symbol promoter here instead.
126bf6603e9SLang Hames     if (CtorDtor.Func->hasLocalLinkage()) {
127bf6603e9SLang Hames       CtorDtor.Func->setLinkage(GlobalValue::ExternalLinkage);
128bf6603e9SLang Hames       CtorDtor.Func->setVisibility(GlobalValue::HiddenVisibility);
129bf6603e9SLang Hames     }
130bf6603e9SLang Hames 
1316a94134bSLang Hames     if (CtorDtor.Data && cast<GlobalValue>(CtorDtor.Data)->isDeclaration()) {
1326a94134bSLang Hames       dbgs() << "  Skipping because why now?\n";
1336a94134bSLang Hames       continue;
1346a94134bSLang Hames     }
1356a94134bSLang Hames 
1366a94134bSLang Hames     CtorDtorsByPriority[CtorDtor.Priority].push_back(
1376a94134bSLang Hames         Mangle(CtorDtor.Func->getName()));
1386a94134bSLang Hames   }
1396a94134bSLang Hames }
1406a94134bSLang Hames 
run()141079df9abSLang Hames Error CtorDtorRunner::run() {
1426a94134bSLang Hames   using CtorDtorTy = void (*)();
1436a94134bSLang Hames 
144674df13bSLang Hames   SymbolLookupSet LookupSet;
145674df13bSLang Hames   for (auto &KV : CtorDtorsByPriority)
146674df13bSLang Hames     for (auto &Name : KV.second)
147674df13bSLang Hames       LookupSet.add(Name);
148674df13bSLang Hames   assert(!LookupSet.containsDuplicates() &&
149674df13bSLang Hames          "Ctor/Dtor list contains duplicates");
1506a94134bSLang Hames 
1517899ccbcSLang Hames   auto &ES = JD.getExecutionSession();
152674df13bSLang Hames   if (auto CtorDtorMap = ES.lookup(
153674df13bSLang Hames           makeJITDylibSearchOrder(&JD, JITDylibLookupFlags::MatchAllSymbols),
154674df13bSLang Hames           std::move(LookupSet))) {
1556a94134bSLang Hames     for (auto &KV : CtorDtorsByPriority) {
1566a94134bSLang Hames       for (auto &Name : KV.second) {
1576a94134bSLang Hames         assert(CtorDtorMap->count(Name) && "No entry for Name");
1586a94134bSLang Hames         auto CtorDtor = reinterpret_cast<CtorDtorTy>(
1596a94134bSLang Hames             static_cast<uintptr_t>((*CtorDtorMap)[Name].getAddress()));
1606a94134bSLang Hames         CtorDtor();
1616a94134bSLang Hames       }
1626a94134bSLang Hames     }
1630dcf69ebSLang Hames     CtorDtorsByPriority.clear();
1646a94134bSLang Hames     return Error::success();
1656a94134bSLang Hames   } else
1666a94134bSLang Hames     return CtorDtorMap.takeError();
1676a94134bSLang Hames }
1686a94134bSLang Hames 
runDestructors()1696a94134bSLang Hames void LocalCXXRuntimeOverridesBase::runDestructors() {
170b1cd98a1SLang Hames   auto& CXXDestructorDataPairs = DSOHandleOverride;
171b1cd98a1SLang Hames   for (auto &P : CXXDestructorDataPairs)
172b1cd98a1SLang Hames     P.first(P.second);
173b1cd98a1SLang Hames   CXXDestructorDataPairs.clear();
174b1cd98a1SLang Hames }
175b1cd98a1SLang Hames 
CXAAtExitOverride(DestructorPtr Destructor,void * Arg,void * DSOHandle)1766a94134bSLang Hames int LocalCXXRuntimeOverridesBase::CXAAtExitOverride(DestructorPtr Destructor,
1776a94134bSLang Hames                                                     void *Arg,
1786a94134bSLang Hames                                                     void *DSOHandle) {
179b1cd98a1SLang Hames   auto& CXXDestructorDataPairs =
180b1cd98a1SLang Hames     *reinterpret_cast<CXXDestructorDataPairList*>(DSOHandle);
181b1cd98a1SLang Hames   CXXDestructorDataPairs.push_back(std::make_pair(Destructor, Arg));
182b1cd98a1SLang Hames   return 0;
183b1cd98a1SLang Hames }
184b1cd98a1SLang Hames 
enable(JITDylib & JD,MangleAndInterner & Mangle)185079df9abSLang Hames Error LocalCXXRuntimeOverrides::enable(JITDylib &JD,
186d5f56c59SLang Hames                                         MangleAndInterner &Mangle) {
1876e66b2a6SLang Hames   SymbolMap RuntimeInterposes;
1886e66b2a6SLang Hames   RuntimeInterposes[Mangle("__dso_handle")] =
1896a94134bSLang Hames     JITEvaluatedSymbol(toTargetAddress(&DSOHandleOverride),
1906e66b2a6SLang Hames                        JITSymbolFlags::Exported);
1916e66b2a6SLang Hames   RuntimeInterposes[Mangle("__cxa_atexit")] =
1926a94134bSLang Hames     JITEvaluatedSymbol(toTargetAddress(&CXAAtExitOverride),
1936e66b2a6SLang Hames                        JITSymbolFlags::Exported);
1946a94134bSLang Hames 
195d5f56c59SLang Hames   return JD.define(absoluteSymbols(std::move(RuntimeInterposes)));
1966a94134bSLang Hames }
1976a94134bSLang Hames 
registerAtExit(void (* F)(void *),void * Ctx,void * DSOHandle)19885fb9976SLang Hames void ItaniumCXAAtExitSupport::registerAtExit(void (*F)(void *), void *Ctx,
19985fb9976SLang Hames                                              void *DSOHandle) {
20085fb9976SLang Hames   std::lock_guard<std::mutex> Lock(AtExitsMutex);
20185fb9976SLang Hames   AtExitRecords[DSOHandle].push_back({F, Ctx});
20285fb9976SLang Hames }
20385fb9976SLang Hames 
runAtExits(void * DSOHandle)20485fb9976SLang Hames void ItaniumCXAAtExitSupport::runAtExits(void *DSOHandle) {
20585fb9976SLang Hames   std::vector<AtExitRecord> AtExitsToRun;
20685fb9976SLang Hames 
20785fb9976SLang Hames   {
20885fb9976SLang Hames     std::lock_guard<std::mutex> Lock(AtExitsMutex);
20985fb9976SLang Hames     auto I = AtExitRecords.find(DSOHandle);
21085fb9976SLang Hames     if (I != AtExitRecords.end()) {
21185fb9976SLang Hames       AtExitsToRun = std::move(I->second);
21285fb9976SLang Hames       AtExitRecords.erase(I);
21385fb9976SLang Hames     }
21485fb9976SLang Hames   }
21585fb9976SLang Hames 
21685fb9976SLang Hames   while (!AtExitsToRun.empty()) {
21785fb9976SLang Hames     AtExitsToRun.back().F(AtExitsToRun.back().Ctx);
21885fb9976SLang Hames     AtExitsToRun.pop_back();
21985fb9976SLang Hames   }
22085fb9976SLang Hames }
22185fb9976SLang Hames 
DynamicLibrarySearchGenerator(sys::DynamicLibrary Dylib,char GlobalPrefix,SymbolPredicate Allow)222a5157d6fSLang Hames DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator(
22311c8dfa5SLang Hames     sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow)
2246a94134bSLang Hames     : Dylib(std::move(Dylib)), Allow(std::move(Allow)),
22511c8dfa5SLang Hames       GlobalPrefix(GlobalPrefix) {}
2266a94134bSLang Hames 
22752a34a78SLang Hames Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
Load(const char * FileName,char GlobalPrefix,SymbolPredicate Allow)22811c8dfa5SLang Hames DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix,
229a5157d6fSLang Hames                                     SymbolPredicate Allow) {
23047d0a377SLang Hames   std::string ErrMsg;
23147d0a377SLang Hames   auto Lib = sys::DynamicLibrary::getPermanentLibrary(FileName, &ErrMsg);
23247d0a377SLang Hames   if (!Lib.isValid())
23347d0a377SLang Hames     return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
2340eaee545SJonas Devlieghere   return std::make_unique<DynamicLibrarySearchGenerator>(
23552a34a78SLang Hames       std::move(Lib), GlobalPrefix, std::move(Allow));
23647d0a377SLang Hames }
23747d0a377SLang Hames 
tryToGenerate(LookupState & LS,LookupKind K,JITDylib & JD,JITDylibLookupFlags JDLookupFlags,const SymbolLookupSet & Symbols)238674df13bSLang Hames Error DynamicLibrarySearchGenerator::tryToGenerate(
239069919c9SLang Hames     LookupState &LS, LookupKind K, JITDylib &JD,
240069919c9SLang Hames     JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
2416a94134bSLang Hames   orc::SymbolMap NewSymbols;
2426a94134bSLang Hames 
2436a94134bSLang Hames   bool HasGlobalPrefix = (GlobalPrefix != '\0');
2446a94134bSLang Hames 
245674df13bSLang Hames   for (auto &KV : Symbols) {
246674df13bSLang Hames     auto &Name = KV.first;
247674df13bSLang Hames 
248a5157d6fSLang Hames     if ((*Name).empty())
249a5157d6fSLang Hames       continue;
250a5157d6fSLang Hames 
251a5157d6fSLang Hames     if (Allow && !Allow(Name))
2526a94134bSLang Hames       continue;
2536a94134bSLang Hames 
2546a94134bSLang Hames     if (HasGlobalPrefix && (*Name).front() != GlobalPrefix)
2556a94134bSLang Hames       continue;
2566a94134bSLang Hames 
25711c8dfa5SLang Hames     std::string Tmp((*Name).data() + HasGlobalPrefix,
25811c8dfa5SLang Hames                     (*Name).size() - HasGlobalPrefix);
2596a94134bSLang Hames     if (void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str())) {
2606a94134bSLang Hames       NewSymbols[Name] = JITEvaluatedSymbol(
2616a94134bSLang Hames           static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(Addr)),
2626a94134bSLang Hames           JITSymbolFlags::Exported);
2636a94134bSLang Hames     }
2646a94134bSLang Hames   }
2656a94134bSLang Hames 
266674df13bSLang Hames   if (NewSymbols.empty())
267674df13bSLang Hames     return Error::success();
2686a94134bSLang Hames 
269674df13bSLang Hames   return JD.define(absoluteSymbols(std::move(NewSymbols)));
2706a94134bSLang Hames }
2716a94134bSLang Hames 
27252a34a78SLang Hames Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
Load(ObjectLayer & L,const char * FileName,GetObjectFileInterface GetObjFileInterface)27302fc8d5cSLang Hames StaticLibraryDefinitionGenerator::Load(
27402fc8d5cSLang Hames     ObjectLayer &L, const char *FileName,
27502fc8d5cSLang Hames     GetObjectFileInterface GetObjFileInterface) {
276*45e390cfSLang Hames   auto ArchiveBuffer = MemoryBuffer::getFile(FileName);
27752a34a78SLang Hames 
27852a34a78SLang Hames   if (!ArchiveBuffer)
279*45e390cfSLang Hames     return createFileError(FileName, ArchiveBuffer.getError());
28052a34a78SLang Hames 
28102fc8d5cSLang Hames   return Create(L, std::move(*ArchiveBuffer), std::move(GetObjFileInterface));
28252a34a78SLang Hames }
28352a34a78SLang Hames 
28452a34a78SLang Hames Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
Load(ObjectLayer & L,const char * FileName,const Triple & TT,GetObjectFileInterface GetObjFileInterface)28502fc8d5cSLang Hames StaticLibraryDefinitionGenerator::Load(
28602fc8d5cSLang Hames     ObjectLayer &L, const char *FileName, const Triple &TT,
28702fc8d5cSLang Hames     GetObjectFileInterface GetObjFileInterface) {
28802fc8d5cSLang Hames 
2891b39c6f6SLang Hames   auto B = object::createBinary(FileName);
2901b39c6f6SLang Hames   if (!B)
291*45e390cfSLang Hames     return createFileError(FileName, B.takeError());
2921b39c6f6SLang Hames 
2931b39c6f6SLang Hames   // If this is a regular archive then create an instance from it.
2941b39c6f6SLang Hames   if (isa<object::Archive>(B->getBinary()))
29502fc8d5cSLang Hames     return Create(L, std::move(B->takeBinary().second),
29602fc8d5cSLang Hames                   std::move(GetObjFileInterface));
2971b39c6f6SLang Hames 
2981b39c6f6SLang Hames   // If this is a universal binary then search for a slice matching the given
2991b39c6f6SLang Hames   // Triple.
3001b39c6f6SLang Hames   if (auto *UB = cast<object::MachOUniversalBinary>(B->getBinary())) {
3011b39c6f6SLang Hames     for (const auto &Obj : UB->objects()) {
3021b39c6f6SLang Hames       auto ObjTT = Obj.getTriple();
3031b39c6f6SLang Hames       if (ObjTT.getArch() == TT.getArch() &&
3041b39c6f6SLang Hames           ObjTT.getSubArch() == TT.getSubArch() &&
305777824b4SLang Hames           (TT.getVendor() == Triple::UnknownVendor ||
306777824b4SLang Hames            ObjTT.getVendor() == TT.getVendor())) {
3071b39c6f6SLang Hames         // We found a match. Create an instance from a buffer covering this
3081b39c6f6SLang Hames         // slice.
3091b39c6f6SLang Hames         auto SliceBuffer = MemoryBuffer::getFileSlice(FileName, Obj.getSize(),
3101b39c6f6SLang Hames                                                       Obj.getOffset());
3111b39c6f6SLang Hames         if (!SliceBuffer)
3121b39c6f6SLang Hames           return make_error<StringError>(
3131b39c6f6SLang Hames               Twine("Could not create buffer for ") + TT.str() + " slice of " +
3141b39c6f6SLang Hames                   FileName + ": [ " + formatv("{0:x}", Obj.getOffset()) +
3151b39c6f6SLang Hames                   " .. " + formatv("{0:x}", Obj.getOffset() + Obj.getSize()) +
3161b39c6f6SLang Hames                   ": " + SliceBuffer.getError().message(),
3171b39c6f6SLang Hames               SliceBuffer.getError());
31802fc8d5cSLang Hames         return Create(L, std::move(*SliceBuffer),
31902fc8d5cSLang Hames                       std::move(GetObjFileInterface));
3201b39c6f6SLang Hames       }
3211b39c6f6SLang Hames     }
3221b39c6f6SLang Hames 
3231b39c6f6SLang Hames     return make_error<StringError>(Twine("Universal binary ") + FileName +
3241b39c6f6SLang Hames                                        " does not contain a slice for " +
3251b39c6f6SLang Hames                                        TT.str(),
3261b39c6f6SLang Hames                                    inconvertibleErrorCode());
3271b39c6f6SLang Hames   }
3281b39c6f6SLang Hames 
3291b39c6f6SLang Hames   return make_error<StringError>(Twine("Unrecognized file type for ") +
3301b39c6f6SLang Hames                                      FileName,
3311b39c6f6SLang Hames                                  inconvertibleErrorCode());
3321b39c6f6SLang Hames }
3331b39c6f6SLang Hames 
3341b39c6f6SLang Hames Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
Create(ObjectLayer & L,std::unique_ptr<MemoryBuffer> ArchiveBuffer,GetObjectFileInterface GetObjFileInterface)33552a34a78SLang Hames StaticLibraryDefinitionGenerator::Create(
33602fc8d5cSLang Hames     ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
33702fc8d5cSLang Hames     GetObjectFileInterface GetObjFileInterface) {
33852a34a78SLang Hames   Error Err = Error::success();
33952a34a78SLang Hames 
34052a34a78SLang Hames   std::unique_ptr<StaticLibraryDefinitionGenerator> ADG(
34102fc8d5cSLang Hames       new StaticLibraryDefinitionGenerator(
34202fc8d5cSLang Hames           L, std::move(ArchiveBuffer), std::move(GetObjFileInterface), Err));
34352a34a78SLang Hames 
34452a34a78SLang Hames   if (Err)
345c55cf4afSBill Wendling     return std::move(Err);
34652a34a78SLang Hames 
347c55cf4afSBill Wendling   return std::move(ADG);
34852a34a78SLang Hames }
34952a34a78SLang Hames 
tryToGenerate(LookupState & LS,LookupKind K,JITDylib & JD,JITDylibLookupFlags JDLookupFlags,const SymbolLookupSet & Symbols)350674df13bSLang Hames Error StaticLibraryDefinitionGenerator::tryToGenerate(
351069919c9SLang Hames     LookupState &LS, LookupKind K, JITDylib &JD,
352069919c9SLang Hames     JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
353674df13bSLang Hames 
354674df13bSLang Hames   // Don't materialize symbols from static archives unless this is a static
355674df13bSLang Hames   // lookup.
356674df13bSLang Hames   if (K != LookupKind::Static)
357674df13bSLang Hames     return Error::success();
358674df13bSLang Hames 
359674df13bSLang Hames   // Bail out early if we've already freed the archive.
360674df13bSLang Hames   if (!Archive)
361674df13bSLang Hames     return Error::success();
36252a34a78SLang Hames 
36352a34a78SLang Hames   DenseSet<std::pair<StringRef, StringRef>> ChildBufferInfos;
36452a34a78SLang Hames 
365674df13bSLang Hames   for (const auto &KV : Symbols) {
366674df13bSLang Hames     const auto &Name = KV.first;
367674df13bSLang Hames     auto Child = Archive->findSym(*Name);
36852a34a78SLang Hames     if (!Child)
36952a34a78SLang Hames       return Child.takeError();
37052a34a78SLang Hames     if (*Child == None)
37152a34a78SLang Hames       continue;
37252a34a78SLang Hames     auto ChildBuffer = (*Child)->getMemoryBufferRef();
37352a34a78SLang Hames     if (!ChildBuffer)
37452a34a78SLang Hames       return ChildBuffer.takeError();
37552a34a78SLang Hames     ChildBufferInfos.insert(
37652a34a78SLang Hames         {ChildBuffer->getBuffer(), ChildBuffer->getBufferIdentifier()});
37752a34a78SLang Hames   }
37852a34a78SLang Hames 
37952a34a78SLang Hames   for (auto ChildBufferInfo : ChildBufferInfos) {
38052a34a78SLang Hames     MemoryBufferRef ChildBufferRef(ChildBufferInfo.first,
38152a34a78SLang Hames                                    ChildBufferInfo.second);
38252a34a78SLang Hames 
38302fc8d5cSLang Hames     auto I = GetObjFileInterface(L.getExecutionSession(), ChildBufferRef);
38402fc8d5cSLang Hames     if (!I)
38502fc8d5cSLang Hames       return I.takeError();
38602fc8d5cSLang Hames 
38702fc8d5cSLang Hames     if (auto Err = L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef, false),
38802fc8d5cSLang Hames                          std::move(*I)))
389674df13bSLang Hames       return Err;
39052a34a78SLang Hames   }
39152a34a78SLang Hames 
392674df13bSLang Hames   return Error::success();
39352a34a78SLang Hames }
39452a34a78SLang Hames 
StaticLibraryDefinitionGenerator(ObjectLayer & L,std::unique_ptr<MemoryBuffer> ArchiveBuffer,GetObjectFileInterface GetObjFileInterface,Error & Err)39552a34a78SLang Hames StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator(
39602fc8d5cSLang Hames     ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
39702fc8d5cSLang Hames     GetObjectFileInterface GetObjFileInterface, Error &Err)
39802fc8d5cSLang Hames     : L(L), GetObjFileInterface(std::move(GetObjFileInterface)),
39902fc8d5cSLang Hames       ArchiveBuffer(std::move(ArchiveBuffer)),
40002fc8d5cSLang Hames       Archive(std::make_unique<object::Archive>(*this->ArchiveBuffer, Err)) {
40102fc8d5cSLang Hames 
40202fc8d5cSLang Hames   if (!this->GetObjFileInterface)
40302fc8d5cSLang Hames     this->GetObjFileInterface = getObjectFileInterface;
40402fc8d5cSLang Hames }
40552a34a78SLang Hames 
406b1cd98a1SLang Hames } // End namespace orc.
407b1cd98a1SLang Hames } // End namespace llvm.
408