109467b48Spatrick //===---- ExecutionUtils.cpp - Utilities for executing functions in Orc ---===// 209467b48Spatrick // 309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information. 509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 609467b48Spatrick // 709467b48Spatrick //===----------------------------------------------------------------------===// 809467b48Spatrick 909467b48Spatrick #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" 1009467b48Spatrick 1109467b48Spatrick #include "llvm/ExecutionEngine/Orc/Layer.h" 1209467b48Spatrick #include "llvm/IR/Constants.h" 1309467b48Spatrick #include "llvm/IR/Function.h" 1409467b48Spatrick #include "llvm/IR/GlobalVariable.h" 1509467b48Spatrick #include "llvm/IR/Module.h" 16*097a140dSpatrick #include "llvm/Object/MachOUniversal.h" 17*097a140dSpatrick #include "llvm/Support/FormatVariadic.h" 1809467b48Spatrick #include "llvm/Support/TargetRegistry.h" 1909467b48Spatrick #include "llvm/Target/TargetMachine.h" 2009467b48Spatrick 2109467b48Spatrick namespace llvm { 2209467b48Spatrick namespace orc { 2309467b48Spatrick 2409467b48Spatrick int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args, 2509467b48Spatrick Optional<StringRef> ProgramName) { 2609467b48Spatrick std::vector<std::unique_ptr<char[]>> ArgVStorage; 2709467b48Spatrick std::vector<char *> ArgV; 2809467b48Spatrick 2909467b48Spatrick ArgVStorage.reserve(Args.size() + (ProgramName ? 1 : 0)); 3009467b48Spatrick ArgV.reserve(Args.size() + 1 + (ProgramName ? 1 : 0)); 3109467b48Spatrick 3209467b48Spatrick if (ProgramName) { 3309467b48Spatrick ArgVStorage.push_back(std::make_unique<char[]>(ProgramName->size() + 1)); 3409467b48Spatrick llvm::copy(*ProgramName, &ArgVStorage.back()[0]); 3509467b48Spatrick ArgVStorage.back()[ProgramName->size()] = '\0'; 3609467b48Spatrick ArgV.push_back(ArgVStorage.back().get()); 3709467b48Spatrick } 3809467b48Spatrick 3909467b48Spatrick for (auto &Arg : Args) { 4009467b48Spatrick ArgVStorage.push_back(std::make_unique<char[]>(Arg.size() + 1)); 4109467b48Spatrick llvm::copy(Arg, &ArgVStorage.back()[0]); 4209467b48Spatrick ArgVStorage.back()[Arg.size()] = '\0'; 4309467b48Spatrick ArgV.push_back(ArgVStorage.back().get()); 4409467b48Spatrick } 4509467b48Spatrick ArgV.push_back(nullptr); 4609467b48Spatrick 4709467b48Spatrick return Main(Args.size() + !!ProgramName, ArgV.data()); 4809467b48Spatrick } 4909467b48Spatrick 5009467b48Spatrick CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End) 5109467b48Spatrick : InitList( 5209467b48Spatrick GV ? dyn_cast_or_null<ConstantArray>(GV->getInitializer()) : nullptr), 5309467b48Spatrick I((InitList && End) ? InitList->getNumOperands() : 0) { 5409467b48Spatrick } 5509467b48Spatrick 5609467b48Spatrick bool CtorDtorIterator::operator==(const CtorDtorIterator &Other) const { 5709467b48Spatrick assert(InitList == Other.InitList && "Incomparable iterators."); 5809467b48Spatrick return I == Other.I; 5909467b48Spatrick } 6009467b48Spatrick 6109467b48Spatrick bool CtorDtorIterator::operator!=(const CtorDtorIterator &Other) const { 6209467b48Spatrick return !(*this == Other); 6309467b48Spatrick } 6409467b48Spatrick 6509467b48Spatrick CtorDtorIterator& CtorDtorIterator::operator++() { 6609467b48Spatrick ++I; 6709467b48Spatrick return *this; 6809467b48Spatrick } 6909467b48Spatrick 7009467b48Spatrick CtorDtorIterator CtorDtorIterator::operator++(int) { 7109467b48Spatrick CtorDtorIterator Temp = *this; 7209467b48Spatrick ++I; 7309467b48Spatrick return Temp; 7409467b48Spatrick } 7509467b48Spatrick 7609467b48Spatrick CtorDtorIterator::Element CtorDtorIterator::operator*() const { 7709467b48Spatrick ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(I)); 7809467b48Spatrick assert(CS && "Unrecognized type in llvm.global_ctors/llvm.global_dtors"); 7909467b48Spatrick 8009467b48Spatrick Constant *FuncC = CS->getOperand(1); 8109467b48Spatrick Function *Func = nullptr; 8209467b48Spatrick 8309467b48Spatrick // Extract function pointer, pulling off any casts. 8409467b48Spatrick while (FuncC) { 8509467b48Spatrick if (Function *F = dyn_cast_or_null<Function>(FuncC)) { 8609467b48Spatrick Func = F; 8709467b48Spatrick break; 8809467b48Spatrick } else if (ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(FuncC)) { 8909467b48Spatrick if (CE->isCast()) 9009467b48Spatrick FuncC = dyn_cast_or_null<ConstantExpr>(CE->getOperand(0)); 9109467b48Spatrick else 9209467b48Spatrick break; 9309467b48Spatrick } else { 9409467b48Spatrick // This isn't anything we recognize. Bail out with Func left set to null. 9509467b48Spatrick break; 9609467b48Spatrick } 9709467b48Spatrick } 9809467b48Spatrick 9909467b48Spatrick auto *Priority = cast<ConstantInt>(CS->getOperand(0)); 10009467b48Spatrick Value *Data = CS->getNumOperands() == 3 ? CS->getOperand(2) : nullptr; 10109467b48Spatrick if (Data && !isa<GlobalValue>(Data)) 10209467b48Spatrick Data = nullptr; 10309467b48Spatrick return Element(Priority->getZExtValue(), Func, Data); 10409467b48Spatrick } 10509467b48Spatrick 10609467b48Spatrick iterator_range<CtorDtorIterator> getConstructors(const Module &M) { 10709467b48Spatrick const GlobalVariable *CtorsList = M.getNamedGlobal("llvm.global_ctors"); 10809467b48Spatrick return make_range(CtorDtorIterator(CtorsList, false), 10909467b48Spatrick CtorDtorIterator(CtorsList, true)); 11009467b48Spatrick } 11109467b48Spatrick 11209467b48Spatrick iterator_range<CtorDtorIterator> getDestructors(const Module &M) { 11309467b48Spatrick const GlobalVariable *DtorsList = M.getNamedGlobal("llvm.global_dtors"); 11409467b48Spatrick return make_range(CtorDtorIterator(DtorsList, false), 11509467b48Spatrick CtorDtorIterator(DtorsList, true)); 11609467b48Spatrick } 11709467b48Spatrick 118*097a140dSpatrick bool StaticInitGVIterator::isStaticInitGlobal(GlobalValue &GV) { 119*097a140dSpatrick if (GV.isDeclaration()) 120*097a140dSpatrick return false; 121*097a140dSpatrick 122*097a140dSpatrick if (GV.hasName() && (GV.getName() == "llvm.global_ctors" || 123*097a140dSpatrick GV.getName() == "llvm.global_dtors")) 124*097a140dSpatrick return true; 125*097a140dSpatrick 126*097a140dSpatrick if (ObjFmt == Triple::MachO) { 127*097a140dSpatrick // FIXME: These section checks are too strict: We should match first and 128*097a140dSpatrick // second word split by comma. 129*097a140dSpatrick if (GV.hasSection() && 130*097a140dSpatrick (GV.getSection().startswith("__DATA,__objc_classlist") || 131*097a140dSpatrick GV.getSection().startswith("__DATA,__objc_selrefs"))) 132*097a140dSpatrick return true; 133*097a140dSpatrick } 134*097a140dSpatrick 135*097a140dSpatrick return false; 136*097a140dSpatrick } 137*097a140dSpatrick 13809467b48Spatrick void CtorDtorRunner::add(iterator_range<CtorDtorIterator> CtorDtors) { 13909467b48Spatrick if (CtorDtors.empty()) 14009467b48Spatrick return; 14109467b48Spatrick 14209467b48Spatrick MangleAndInterner Mangle( 14309467b48Spatrick JD.getExecutionSession(), 14409467b48Spatrick (*CtorDtors.begin()).Func->getParent()->getDataLayout()); 14509467b48Spatrick 14609467b48Spatrick for (auto CtorDtor : CtorDtors) { 14709467b48Spatrick assert(CtorDtor.Func && CtorDtor.Func->hasName() && 14809467b48Spatrick "Ctor/Dtor function must be named to be runnable under the JIT"); 14909467b48Spatrick 15009467b48Spatrick // FIXME: Maybe use a symbol promoter here instead. 15109467b48Spatrick if (CtorDtor.Func->hasLocalLinkage()) { 15209467b48Spatrick CtorDtor.Func->setLinkage(GlobalValue::ExternalLinkage); 15309467b48Spatrick CtorDtor.Func->setVisibility(GlobalValue::HiddenVisibility); 15409467b48Spatrick } 15509467b48Spatrick 15609467b48Spatrick if (CtorDtor.Data && cast<GlobalValue>(CtorDtor.Data)->isDeclaration()) { 15709467b48Spatrick dbgs() << " Skipping because why now?\n"; 15809467b48Spatrick continue; 15909467b48Spatrick } 16009467b48Spatrick 16109467b48Spatrick CtorDtorsByPriority[CtorDtor.Priority].push_back( 16209467b48Spatrick Mangle(CtorDtor.Func->getName())); 16309467b48Spatrick } 16409467b48Spatrick } 16509467b48Spatrick 16609467b48Spatrick Error CtorDtorRunner::run() { 16709467b48Spatrick using CtorDtorTy = void (*)(); 16809467b48Spatrick 16909467b48Spatrick SymbolLookupSet LookupSet; 17009467b48Spatrick for (auto &KV : CtorDtorsByPriority) 17109467b48Spatrick for (auto &Name : KV.second) 17209467b48Spatrick LookupSet.add(Name); 17309467b48Spatrick assert(!LookupSet.containsDuplicates() && 17409467b48Spatrick "Ctor/Dtor list contains duplicates"); 17509467b48Spatrick 17609467b48Spatrick auto &ES = JD.getExecutionSession(); 17709467b48Spatrick if (auto CtorDtorMap = ES.lookup( 17809467b48Spatrick makeJITDylibSearchOrder(&JD, JITDylibLookupFlags::MatchAllSymbols), 17909467b48Spatrick std::move(LookupSet))) { 18009467b48Spatrick for (auto &KV : CtorDtorsByPriority) { 18109467b48Spatrick for (auto &Name : KV.second) { 18209467b48Spatrick assert(CtorDtorMap->count(Name) && "No entry for Name"); 18309467b48Spatrick auto CtorDtor = reinterpret_cast<CtorDtorTy>( 18409467b48Spatrick static_cast<uintptr_t>((*CtorDtorMap)[Name].getAddress())); 18509467b48Spatrick CtorDtor(); 18609467b48Spatrick } 18709467b48Spatrick } 18809467b48Spatrick CtorDtorsByPriority.clear(); 18909467b48Spatrick return Error::success(); 19009467b48Spatrick } else 19109467b48Spatrick return CtorDtorMap.takeError(); 19209467b48Spatrick } 19309467b48Spatrick 19409467b48Spatrick void LocalCXXRuntimeOverridesBase::runDestructors() { 19509467b48Spatrick auto& CXXDestructorDataPairs = DSOHandleOverride; 19609467b48Spatrick for (auto &P : CXXDestructorDataPairs) 19709467b48Spatrick P.first(P.second); 19809467b48Spatrick CXXDestructorDataPairs.clear(); 19909467b48Spatrick } 20009467b48Spatrick 20109467b48Spatrick int LocalCXXRuntimeOverridesBase::CXAAtExitOverride(DestructorPtr Destructor, 20209467b48Spatrick void *Arg, 20309467b48Spatrick void *DSOHandle) { 20409467b48Spatrick auto& CXXDestructorDataPairs = 20509467b48Spatrick *reinterpret_cast<CXXDestructorDataPairList*>(DSOHandle); 20609467b48Spatrick CXXDestructorDataPairs.push_back(std::make_pair(Destructor, Arg)); 20709467b48Spatrick return 0; 20809467b48Spatrick } 20909467b48Spatrick 21009467b48Spatrick Error LocalCXXRuntimeOverrides::enable(JITDylib &JD, 21109467b48Spatrick MangleAndInterner &Mangle) { 21209467b48Spatrick SymbolMap RuntimeInterposes; 21309467b48Spatrick RuntimeInterposes[Mangle("__dso_handle")] = 21409467b48Spatrick JITEvaluatedSymbol(toTargetAddress(&DSOHandleOverride), 21509467b48Spatrick JITSymbolFlags::Exported); 21609467b48Spatrick RuntimeInterposes[Mangle("__cxa_atexit")] = 21709467b48Spatrick JITEvaluatedSymbol(toTargetAddress(&CXAAtExitOverride), 21809467b48Spatrick JITSymbolFlags::Exported); 21909467b48Spatrick 22009467b48Spatrick return JD.define(absoluteSymbols(std::move(RuntimeInterposes))); 22109467b48Spatrick } 22209467b48Spatrick 223*097a140dSpatrick void ItaniumCXAAtExitSupport::registerAtExit(void (*F)(void *), void *Ctx, 224*097a140dSpatrick void *DSOHandle) { 225*097a140dSpatrick std::lock_guard<std::mutex> Lock(AtExitsMutex); 226*097a140dSpatrick AtExitRecords[DSOHandle].push_back({F, Ctx}); 227*097a140dSpatrick } 228*097a140dSpatrick 229*097a140dSpatrick void ItaniumCXAAtExitSupport::runAtExits(void *DSOHandle) { 230*097a140dSpatrick std::vector<AtExitRecord> AtExitsToRun; 231*097a140dSpatrick 232*097a140dSpatrick { 233*097a140dSpatrick std::lock_guard<std::mutex> Lock(AtExitsMutex); 234*097a140dSpatrick auto I = AtExitRecords.find(DSOHandle); 235*097a140dSpatrick if (I != AtExitRecords.end()) { 236*097a140dSpatrick AtExitsToRun = std::move(I->second); 237*097a140dSpatrick AtExitRecords.erase(I); 238*097a140dSpatrick } 239*097a140dSpatrick } 240*097a140dSpatrick 241*097a140dSpatrick while (!AtExitsToRun.empty()) { 242*097a140dSpatrick AtExitsToRun.back().F(AtExitsToRun.back().Ctx); 243*097a140dSpatrick AtExitsToRun.pop_back(); 244*097a140dSpatrick } 245*097a140dSpatrick } 246*097a140dSpatrick 24709467b48Spatrick DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator( 24809467b48Spatrick sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow) 24909467b48Spatrick : Dylib(std::move(Dylib)), Allow(std::move(Allow)), 25009467b48Spatrick GlobalPrefix(GlobalPrefix) {} 25109467b48Spatrick 25209467b48Spatrick Expected<std::unique_ptr<DynamicLibrarySearchGenerator>> 25309467b48Spatrick DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix, 25409467b48Spatrick SymbolPredicate Allow) { 25509467b48Spatrick std::string ErrMsg; 25609467b48Spatrick auto Lib = sys::DynamicLibrary::getPermanentLibrary(FileName, &ErrMsg); 25709467b48Spatrick if (!Lib.isValid()) 25809467b48Spatrick return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()); 25909467b48Spatrick return std::make_unique<DynamicLibrarySearchGenerator>( 26009467b48Spatrick std::move(Lib), GlobalPrefix, std::move(Allow)); 26109467b48Spatrick } 26209467b48Spatrick 26309467b48Spatrick Error DynamicLibrarySearchGenerator::tryToGenerate( 26409467b48Spatrick LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags, 26509467b48Spatrick const SymbolLookupSet &Symbols) { 26609467b48Spatrick orc::SymbolMap NewSymbols; 26709467b48Spatrick 26809467b48Spatrick bool HasGlobalPrefix = (GlobalPrefix != '\0'); 26909467b48Spatrick 27009467b48Spatrick for (auto &KV : Symbols) { 27109467b48Spatrick auto &Name = KV.first; 27209467b48Spatrick 27309467b48Spatrick if ((*Name).empty()) 27409467b48Spatrick continue; 27509467b48Spatrick 27609467b48Spatrick if (Allow && !Allow(Name)) 27709467b48Spatrick continue; 27809467b48Spatrick 27909467b48Spatrick if (HasGlobalPrefix && (*Name).front() != GlobalPrefix) 28009467b48Spatrick continue; 28109467b48Spatrick 28209467b48Spatrick std::string Tmp((*Name).data() + HasGlobalPrefix, 28309467b48Spatrick (*Name).size() - HasGlobalPrefix); 28409467b48Spatrick if (void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str())) { 28509467b48Spatrick NewSymbols[Name] = JITEvaluatedSymbol( 28609467b48Spatrick static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(Addr)), 28709467b48Spatrick JITSymbolFlags::Exported); 28809467b48Spatrick } 28909467b48Spatrick } 29009467b48Spatrick 29109467b48Spatrick if (NewSymbols.empty()) 29209467b48Spatrick return Error::success(); 29309467b48Spatrick 29409467b48Spatrick return JD.define(absoluteSymbols(std::move(NewSymbols))); 29509467b48Spatrick } 29609467b48Spatrick 29709467b48Spatrick Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 29809467b48Spatrick StaticLibraryDefinitionGenerator::Load(ObjectLayer &L, const char *FileName) { 29909467b48Spatrick auto ArchiveBuffer = errorOrToExpected(MemoryBuffer::getFile(FileName)); 30009467b48Spatrick 30109467b48Spatrick if (!ArchiveBuffer) 30209467b48Spatrick return ArchiveBuffer.takeError(); 30309467b48Spatrick 30409467b48Spatrick return Create(L, std::move(*ArchiveBuffer)); 30509467b48Spatrick } 30609467b48Spatrick 30709467b48Spatrick Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 308*097a140dSpatrick StaticLibraryDefinitionGenerator::Load(ObjectLayer &L, const char *FileName, 309*097a140dSpatrick const Triple &TT) { 310*097a140dSpatrick auto B = object::createBinary(FileName); 311*097a140dSpatrick if (!B) 312*097a140dSpatrick return B.takeError(); 313*097a140dSpatrick 314*097a140dSpatrick // If this is a regular archive then create an instance from it. 315*097a140dSpatrick if (isa<object::Archive>(B->getBinary())) 316*097a140dSpatrick return Create(L, std::move(B->takeBinary().second)); 317*097a140dSpatrick 318*097a140dSpatrick // If this is a universal binary then search for a slice matching the given 319*097a140dSpatrick // Triple. 320*097a140dSpatrick if (auto *UB = cast<object::MachOUniversalBinary>(B->getBinary())) { 321*097a140dSpatrick for (const auto &Obj : UB->objects()) { 322*097a140dSpatrick auto ObjTT = Obj.getTriple(); 323*097a140dSpatrick if (ObjTT.getArch() == TT.getArch() && 324*097a140dSpatrick ObjTT.getSubArch() == TT.getSubArch() && 325*097a140dSpatrick ObjTT.getVendor() == TT.getVendor()) { 326*097a140dSpatrick // We found a match. Create an instance from a buffer covering this 327*097a140dSpatrick // slice. 328*097a140dSpatrick auto SliceBuffer = MemoryBuffer::getFileSlice(FileName, Obj.getSize(), 329*097a140dSpatrick Obj.getOffset()); 330*097a140dSpatrick if (!SliceBuffer) 331*097a140dSpatrick return make_error<StringError>( 332*097a140dSpatrick Twine("Could not create buffer for ") + TT.str() + " slice of " + 333*097a140dSpatrick FileName + ": [ " + formatv("{0:x}", Obj.getOffset()) + 334*097a140dSpatrick " .. " + formatv("{0:x}", Obj.getOffset() + Obj.getSize()) + 335*097a140dSpatrick ": " + SliceBuffer.getError().message(), 336*097a140dSpatrick SliceBuffer.getError()); 337*097a140dSpatrick return Create(L, std::move(*SliceBuffer)); 338*097a140dSpatrick } 339*097a140dSpatrick } 340*097a140dSpatrick 341*097a140dSpatrick return make_error<StringError>(Twine("Universal binary ") + FileName + 342*097a140dSpatrick " does not contain a slice for " + 343*097a140dSpatrick TT.str(), 344*097a140dSpatrick inconvertibleErrorCode()); 345*097a140dSpatrick } 346*097a140dSpatrick 347*097a140dSpatrick return make_error<StringError>(Twine("Unrecognized file type for ") + 348*097a140dSpatrick FileName, 349*097a140dSpatrick inconvertibleErrorCode()); 350*097a140dSpatrick } 351*097a140dSpatrick 352*097a140dSpatrick Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> 35309467b48Spatrick StaticLibraryDefinitionGenerator::Create( 35409467b48Spatrick ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer) { 35509467b48Spatrick Error Err = Error::success(); 35609467b48Spatrick 35709467b48Spatrick std::unique_ptr<StaticLibraryDefinitionGenerator> ADG( 35809467b48Spatrick new StaticLibraryDefinitionGenerator(L, std::move(ArchiveBuffer), Err)); 35909467b48Spatrick 36009467b48Spatrick if (Err) 36109467b48Spatrick return std::move(Err); 36209467b48Spatrick 36309467b48Spatrick return std::move(ADG); 36409467b48Spatrick } 36509467b48Spatrick 36609467b48Spatrick Error StaticLibraryDefinitionGenerator::tryToGenerate( 36709467b48Spatrick LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags, 36809467b48Spatrick const SymbolLookupSet &Symbols) { 36909467b48Spatrick 37009467b48Spatrick // Don't materialize symbols from static archives unless this is a static 37109467b48Spatrick // lookup. 37209467b48Spatrick if (K != LookupKind::Static) 37309467b48Spatrick return Error::success(); 37409467b48Spatrick 37509467b48Spatrick // Bail out early if we've already freed the archive. 37609467b48Spatrick if (!Archive) 37709467b48Spatrick return Error::success(); 37809467b48Spatrick 37909467b48Spatrick DenseSet<std::pair<StringRef, StringRef>> ChildBufferInfos; 38009467b48Spatrick 38109467b48Spatrick for (const auto &KV : Symbols) { 38209467b48Spatrick const auto &Name = KV.first; 38309467b48Spatrick auto Child = Archive->findSym(*Name); 38409467b48Spatrick if (!Child) 38509467b48Spatrick return Child.takeError(); 38609467b48Spatrick if (*Child == None) 38709467b48Spatrick continue; 38809467b48Spatrick auto ChildBuffer = (*Child)->getMemoryBufferRef(); 38909467b48Spatrick if (!ChildBuffer) 39009467b48Spatrick return ChildBuffer.takeError(); 39109467b48Spatrick ChildBufferInfos.insert( 39209467b48Spatrick {ChildBuffer->getBuffer(), ChildBuffer->getBufferIdentifier()}); 39309467b48Spatrick } 39409467b48Spatrick 39509467b48Spatrick for (auto ChildBufferInfo : ChildBufferInfos) { 39609467b48Spatrick MemoryBufferRef ChildBufferRef(ChildBufferInfo.first, 39709467b48Spatrick ChildBufferInfo.second); 39809467b48Spatrick 399*097a140dSpatrick if (auto Err = L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef, false), 400*097a140dSpatrick VModuleKey())) 40109467b48Spatrick return Err; 40209467b48Spatrick } 40309467b48Spatrick 40409467b48Spatrick return Error::success(); 40509467b48Spatrick } 40609467b48Spatrick 40709467b48Spatrick StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator( 40809467b48Spatrick ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, Error &Err) 40909467b48Spatrick : L(L), ArchiveBuffer(std::move(ArchiveBuffer)), 41009467b48Spatrick Archive(std::make_unique<object::Archive>(*this->ArchiveBuffer, Err)) {} 41109467b48Spatrick 41209467b48Spatrick } // End namespace orc. 41309467b48Spatrick } // End namespace llvm. 414