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