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