1*0b57cec5SDimitry Andric //===------- ObjectLinkingLayer.cpp - JITLink backed ORC ObjectLayer ------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" 10*0b57cec5SDimitry Andric 11*0b57cec5SDimitry Andric #include "llvm/ADT/Optional.h" 12*0b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h" 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andric #include <vector> 15*0b57cec5SDimitry Andric 16*0b57cec5SDimitry Andric #define DEBUG_TYPE "orc" 17*0b57cec5SDimitry Andric 18*0b57cec5SDimitry Andric using namespace llvm; 19*0b57cec5SDimitry Andric using namespace llvm::jitlink; 20*0b57cec5SDimitry Andric using namespace llvm::orc; 21*0b57cec5SDimitry Andric 22*0b57cec5SDimitry Andric namespace llvm { 23*0b57cec5SDimitry Andric namespace orc { 24*0b57cec5SDimitry Andric 25*0b57cec5SDimitry Andric class ObjectLinkingLayerJITLinkContext final : public JITLinkContext { 26*0b57cec5SDimitry Andric public: 27*0b57cec5SDimitry Andric ObjectLinkingLayerJITLinkContext(ObjectLinkingLayer &Layer, 28*0b57cec5SDimitry Andric MaterializationResponsibility MR, 29*0b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> ObjBuffer) 30*0b57cec5SDimitry Andric : Layer(Layer), MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {} 31*0b57cec5SDimitry Andric 32*0b57cec5SDimitry Andric JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; } 33*0b57cec5SDimitry Andric 34*0b57cec5SDimitry Andric MemoryBufferRef getObjectBuffer() const override { 35*0b57cec5SDimitry Andric return ObjBuffer->getMemBufferRef(); 36*0b57cec5SDimitry Andric } 37*0b57cec5SDimitry Andric 38*0b57cec5SDimitry Andric void notifyFailed(Error Err) override { 39*0b57cec5SDimitry Andric Layer.getExecutionSession().reportError(std::move(Err)); 40*0b57cec5SDimitry Andric MR.failMaterialization(); 41*0b57cec5SDimitry Andric } 42*0b57cec5SDimitry Andric 43*0b57cec5SDimitry Andric void lookup(const DenseSet<StringRef> &Symbols, 44*0b57cec5SDimitry Andric JITLinkAsyncLookupContinuation LookupContinuation) override { 45*0b57cec5SDimitry Andric 46*0b57cec5SDimitry Andric JITDylibSearchList SearchOrder; 47*0b57cec5SDimitry Andric MR.getTargetJITDylib().withSearchOrderDo( 48*0b57cec5SDimitry Andric [&](const JITDylibSearchList &JDs) { SearchOrder = JDs; }); 49*0b57cec5SDimitry Andric 50*0b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 51*0b57cec5SDimitry Andric 52*0b57cec5SDimitry Andric SymbolNameSet InternedSymbols; 53*0b57cec5SDimitry Andric for (auto &S : Symbols) 54*0b57cec5SDimitry Andric InternedSymbols.insert(ES.intern(S)); 55*0b57cec5SDimitry Andric 56*0b57cec5SDimitry Andric // OnResolve -- De-intern the symbols and pass the result to the linker. 57*0b57cec5SDimitry Andric // FIXME: Capture LookupContinuation by move once we have c++14. 58*0b57cec5SDimitry Andric auto SharedLookupContinuation = 59*0b57cec5SDimitry Andric std::make_shared<JITLinkAsyncLookupContinuation>( 60*0b57cec5SDimitry Andric std::move(LookupContinuation)); 61*0b57cec5SDimitry Andric auto OnResolve = [SharedLookupContinuation](Expected<SymbolMap> Result) { 62*0b57cec5SDimitry Andric if (!Result) 63*0b57cec5SDimitry Andric (*SharedLookupContinuation)(Result.takeError()); 64*0b57cec5SDimitry Andric else { 65*0b57cec5SDimitry Andric AsyncLookupResult LR; 66*0b57cec5SDimitry Andric for (auto &KV : *Result) 67*0b57cec5SDimitry Andric LR[*KV.first] = KV.second; 68*0b57cec5SDimitry Andric (*SharedLookupContinuation)(std::move(LR)); 69*0b57cec5SDimitry Andric } 70*0b57cec5SDimitry Andric }; 71*0b57cec5SDimitry Andric 72*0b57cec5SDimitry Andric ES.lookup(SearchOrder, std::move(InternedSymbols), SymbolState::Resolved, 73*0b57cec5SDimitry Andric std::move(OnResolve), [this](const SymbolDependenceMap &Deps) { 74*0b57cec5SDimitry Andric registerDependencies(Deps); 75*0b57cec5SDimitry Andric }); 76*0b57cec5SDimitry Andric } 77*0b57cec5SDimitry Andric 78*0b57cec5SDimitry Andric void notifyResolved(AtomGraph &G) override { 79*0b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 80*0b57cec5SDimitry Andric 81*0b57cec5SDimitry Andric SymbolFlagsMap ExtraSymbolsToClaim; 82*0b57cec5SDimitry Andric bool AutoClaim = Layer.AutoClaimObjectSymbols; 83*0b57cec5SDimitry Andric 84*0b57cec5SDimitry Andric SymbolMap InternedResult; 85*0b57cec5SDimitry Andric for (auto *DA : G.defined_atoms()) 86*0b57cec5SDimitry Andric if (DA->hasName() && DA->isGlobal()) { 87*0b57cec5SDimitry Andric auto InternedName = ES.intern(DA->getName()); 88*0b57cec5SDimitry Andric JITSymbolFlags Flags; 89*0b57cec5SDimitry Andric 90*0b57cec5SDimitry Andric if (DA->isExported()) 91*0b57cec5SDimitry Andric Flags |= JITSymbolFlags::Exported; 92*0b57cec5SDimitry Andric if (DA->isWeak()) 93*0b57cec5SDimitry Andric Flags |= JITSymbolFlags::Weak; 94*0b57cec5SDimitry Andric if (DA->isCallable()) 95*0b57cec5SDimitry Andric Flags |= JITSymbolFlags::Callable; 96*0b57cec5SDimitry Andric if (DA->isCommon()) 97*0b57cec5SDimitry Andric Flags |= JITSymbolFlags::Common; 98*0b57cec5SDimitry Andric 99*0b57cec5SDimitry Andric InternedResult[InternedName] = 100*0b57cec5SDimitry Andric JITEvaluatedSymbol(DA->getAddress(), Flags); 101*0b57cec5SDimitry Andric if (AutoClaim && !MR.getSymbols().count(InternedName)) { 102*0b57cec5SDimitry Andric assert(!ExtraSymbolsToClaim.count(InternedName) && 103*0b57cec5SDimitry Andric "Duplicate symbol to claim?"); 104*0b57cec5SDimitry Andric ExtraSymbolsToClaim[InternedName] = Flags; 105*0b57cec5SDimitry Andric } 106*0b57cec5SDimitry Andric } 107*0b57cec5SDimitry Andric 108*0b57cec5SDimitry Andric for (auto *A : G.absolute_atoms()) 109*0b57cec5SDimitry Andric if (A->hasName()) { 110*0b57cec5SDimitry Andric auto InternedName = ES.intern(A->getName()); 111*0b57cec5SDimitry Andric JITSymbolFlags Flags; 112*0b57cec5SDimitry Andric Flags |= JITSymbolFlags::Absolute; 113*0b57cec5SDimitry Andric if (A->isWeak()) 114*0b57cec5SDimitry Andric Flags |= JITSymbolFlags::Weak; 115*0b57cec5SDimitry Andric if (A->isCallable()) 116*0b57cec5SDimitry Andric Flags |= JITSymbolFlags::Callable; 117*0b57cec5SDimitry Andric InternedResult[InternedName] = 118*0b57cec5SDimitry Andric JITEvaluatedSymbol(A->getAddress(), Flags); 119*0b57cec5SDimitry Andric if (AutoClaim && !MR.getSymbols().count(InternedName)) { 120*0b57cec5SDimitry Andric assert(!ExtraSymbolsToClaim.count(InternedName) && 121*0b57cec5SDimitry Andric "Duplicate symbol to claim?"); 122*0b57cec5SDimitry Andric ExtraSymbolsToClaim[InternedName] = Flags; 123*0b57cec5SDimitry Andric } 124*0b57cec5SDimitry Andric } 125*0b57cec5SDimitry Andric 126*0b57cec5SDimitry Andric if (!ExtraSymbolsToClaim.empty()) 127*0b57cec5SDimitry Andric if (auto Err = MR.defineMaterializing(ExtraSymbolsToClaim)) 128*0b57cec5SDimitry Andric return notifyFailed(std::move(Err)); 129*0b57cec5SDimitry Andric 130*0b57cec5SDimitry Andric MR.notifyResolved(InternedResult); 131*0b57cec5SDimitry Andric 132*0b57cec5SDimitry Andric Layer.notifyLoaded(MR); 133*0b57cec5SDimitry Andric } 134*0b57cec5SDimitry Andric 135*0b57cec5SDimitry Andric void notifyFinalized( 136*0b57cec5SDimitry Andric std::unique_ptr<JITLinkMemoryManager::Allocation> A) override { 137*0b57cec5SDimitry Andric 138*0b57cec5SDimitry Andric if (auto Err = Layer.notifyEmitted(MR, std::move(A))) { 139*0b57cec5SDimitry Andric Layer.getExecutionSession().reportError(std::move(Err)); 140*0b57cec5SDimitry Andric MR.failMaterialization(); 141*0b57cec5SDimitry Andric 142*0b57cec5SDimitry Andric return; 143*0b57cec5SDimitry Andric } 144*0b57cec5SDimitry Andric MR.notifyEmitted(); 145*0b57cec5SDimitry Andric } 146*0b57cec5SDimitry Andric 147*0b57cec5SDimitry Andric AtomGraphPassFunction getMarkLivePass(const Triple &TT) const override { 148*0b57cec5SDimitry Andric return [this](AtomGraph &G) { return markResponsibilitySymbolsLive(G); }; 149*0b57cec5SDimitry Andric } 150*0b57cec5SDimitry Andric 151*0b57cec5SDimitry Andric Error modifyPassConfig(const Triple &TT, PassConfiguration &Config) override { 152*0b57cec5SDimitry Andric // Add passes to mark duplicate defs as should-discard, and to walk the 153*0b57cec5SDimitry Andric // atom graph to build the symbol dependence graph. 154*0b57cec5SDimitry Andric Config.PrePrunePasses.push_back( 155*0b57cec5SDimitry Andric [this](AtomGraph &G) { return markSymbolsToDiscard(G); }); 156*0b57cec5SDimitry Andric Config.PostPrunePasses.push_back( 157*0b57cec5SDimitry Andric [this](AtomGraph &G) { return computeNamedSymbolDependencies(G); }); 158*0b57cec5SDimitry Andric 159*0b57cec5SDimitry Andric Layer.modifyPassConfig(MR, TT, Config); 160*0b57cec5SDimitry Andric 161*0b57cec5SDimitry Andric return Error::success(); 162*0b57cec5SDimitry Andric } 163*0b57cec5SDimitry Andric 164*0b57cec5SDimitry Andric private: 165*0b57cec5SDimitry Andric using AnonAtomNamedDependenciesMap = 166*0b57cec5SDimitry Andric DenseMap<const DefinedAtom *, SymbolNameSet>; 167*0b57cec5SDimitry Andric 168*0b57cec5SDimitry Andric Error markSymbolsToDiscard(AtomGraph &G) { 169*0b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 170*0b57cec5SDimitry Andric for (auto *DA : G.defined_atoms()) 171*0b57cec5SDimitry Andric if (DA->isWeak() && DA->hasName()) { 172*0b57cec5SDimitry Andric auto S = ES.intern(DA->getName()); 173*0b57cec5SDimitry Andric auto I = MR.getSymbols().find(S); 174*0b57cec5SDimitry Andric if (I == MR.getSymbols().end()) 175*0b57cec5SDimitry Andric DA->setShouldDiscard(true); 176*0b57cec5SDimitry Andric } 177*0b57cec5SDimitry Andric 178*0b57cec5SDimitry Andric for (auto *A : G.absolute_atoms()) 179*0b57cec5SDimitry Andric if (A->isWeak() && A->hasName()) { 180*0b57cec5SDimitry Andric auto S = ES.intern(A->getName()); 181*0b57cec5SDimitry Andric auto I = MR.getSymbols().find(S); 182*0b57cec5SDimitry Andric if (I == MR.getSymbols().end()) 183*0b57cec5SDimitry Andric A->setShouldDiscard(true); 184*0b57cec5SDimitry Andric } 185*0b57cec5SDimitry Andric 186*0b57cec5SDimitry Andric return Error::success(); 187*0b57cec5SDimitry Andric } 188*0b57cec5SDimitry Andric 189*0b57cec5SDimitry Andric Error markResponsibilitySymbolsLive(AtomGraph &G) const { 190*0b57cec5SDimitry Andric auto &ES = Layer.getExecutionSession(); 191*0b57cec5SDimitry Andric for (auto *DA : G.defined_atoms()) 192*0b57cec5SDimitry Andric if (DA->hasName() && 193*0b57cec5SDimitry Andric MR.getSymbols().count(ES.intern(DA->getName()))) 194*0b57cec5SDimitry Andric DA->setLive(true); 195*0b57cec5SDimitry Andric return Error::success(); 196*0b57cec5SDimitry Andric } 197*0b57cec5SDimitry Andric 198*0b57cec5SDimitry Andric Error computeNamedSymbolDependencies(AtomGraph &G) { 199*0b57cec5SDimitry Andric auto &ES = MR.getTargetJITDylib().getExecutionSession(); 200*0b57cec5SDimitry Andric auto AnonDeps = computeAnonDeps(G); 201*0b57cec5SDimitry Andric 202*0b57cec5SDimitry Andric for (auto *DA : G.defined_atoms()) { 203*0b57cec5SDimitry Andric 204*0b57cec5SDimitry Andric // Skip anonymous and non-global atoms: we do not need dependencies for 205*0b57cec5SDimitry Andric // these. 206*0b57cec5SDimitry Andric if (!DA->hasName() || !DA->isGlobal()) 207*0b57cec5SDimitry Andric continue; 208*0b57cec5SDimitry Andric 209*0b57cec5SDimitry Andric auto DAName = ES.intern(DA->getName()); 210*0b57cec5SDimitry Andric SymbolNameSet &DADeps = NamedSymbolDeps[DAName]; 211*0b57cec5SDimitry Andric 212*0b57cec5SDimitry Andric for (auto &E : DA->edges()) { 213*0b57cec5SDimitry Andric auto &TA = E.getTarget(); 214*0b57cec5SDimitry Andric 215*0b57cec5SDimitry Andric if (TA.hasName()) 216*0b57cec5SDimitry Andric DADeps.insert(ES.intern(TA.getName())); 217*0b57cec5SDimitry Andric else { 218*0b57cec5SDimitry Andric assert(TA.isDefined() && "Anonymous atoms must be defined"); 219*0b57cec5SDimitry Andric auto &DTA = static_cast<DefinedAtom &>(TA); 220*0b57cec5SDimitry Andric auto I = AnonDeps.find(&DTA); 221*0b57cec5SDimitry Andric if (I != AnonDeps.end()) 222*0b57cec5SDimitry Andric for (auto &S : I->second) 223*0b57cec5SDimitry Andric DADeps.insert(S); 224*0b57cec5SDimitry Andric } 225*0b57cec5SDimitry Andric } 226*0b57cec5SDimitry Andric } 227*0b57cec5SDimitry Andric 228*0b57cec5SDimitry Andric return Error::success(); 229*0b57cec5SDimitry Andric } 230*0b57cec5SDimitry Andric 231*0b57cec5SDimitry Andric AnonAtomNamedDependenciesMap computeAnonDeps(AtomGraph &G) { 232*0b57cec5SDimitry Andric 233*0b57cec5SDimitry Andric auto &ES = MR.getTargetJITDylib().getExecutionSession(); 234*0b57cec5SDimitry Andric AnonAtomNamedDependenciesMap DepMap; 235*0b57cec5SDimitry Andric 236*0b57cec5SDimitry Andric // For all anonymous atoms: 237*0b57cec5SDimitry Andric // (1) Add their named dependencies. 238*0b57cec5SDimitry Andric // (2) Add them to the worklist for further iteration if they have any 239*0b57cec5SDimitry Andric // depend on any other anonymous atoms. 240*0b57cec5SDimitry Andric struct WorklistEntry { 241*0b57cec5SDimitry Andric WorklistEntry(DefinedAtom *DA, DenseSet<DefinedAtom *> DAAnonDeps) 242*0b57cec5SDimitry Andric : DA(DA), DAAnonDeps(std::move(DAAnonDeps)) {} 243*0b57cec5SDimitry Andric 244*0b57cec5SDimitry Andric DefinedAtom *DA = nullptr; 245*0b57cec5SDimitry Andric DenseSet<DefinedAtom *> DAAnonDeps; 246*0b57cec5SDimitry Andric }; 247*0b57cec5SDimitry Andric std::vector<WorklistEntry> Worklist; 248*0b57cec5SDimitry Andric for (auto *DA : G.defined_atoms()) 249*0b57cec5SDimitry Andric if (!DA->hasName()) { 250*0b57cec5SDimitry Andric auto &DANamedDeps = DepMap[DA]; 251*0b57cec5SDimitry Andric DenseSet<DefinedAtom *> DAAnonDeps; 252*0b57cec5SDimitry Andric 253*0b57cec5SDimitry Andric for (auto &E : DA->edges()) { 254*0b57cec5SDimitry Andric auto &TA = E.getTarget(); 255*0b57cec5SDimitry Andric if (TA.hasName()) 256*0b57cec5SDimitry Andric DANamedDeps.insert(ES.intern(TA.getName())); 257*0b57cec5SDimitry Andric else { 258*0b57cec5SDimitry Andric assert(TA.isDefined() && "Anonymous atoms must be defined"); 259*0b57cec5SDimitry Andric DAAnonDeps.insert(static_cast<DefinedAtom *>(&TA)); 260*0b57cec5SDimitry Andric } 261*0b57cec5SDimitry Andric } 262*0b57cec5SDimitry Andric 263*0b57cec5SDimitry Andric if (!DAAnonDeps.empty()) 264*0b57cec5SDimitry Andric Worklist.push_back(WorklistEntry(DA, std::move(DAAnonDeps))); 265*0b57cec5SDimitry Andric } 266*0b57cec5SDimitry Andric 267*0b57cec5SDimitry Andric // Loop over all anonymous atoms with anonymous dependencies, propagating 268*0b57cec5SDimitry Andric // their respective *named* dependencies. Iterate until we hit a stable 269*0b57cec5SDimitry Andric // state. 270*0b57cec5SDimitry Andric bool Changed; 271*0b57cec5SDimitry Andric do { 272*0b57cec5SDimitry Andric Changed = false; 273*0b57cec5SDimitry Andric for (auto &WLEntry : Worklist) { 274*0b57cec5SDimitry Andric auto *DA = WLEntry.DA; 275*0b57cec5SDimitry Andric auto &DANamedDeps = DepMap[DA]; 276*0b57cec5SDimitry Andric auto &DAAnonDeps = WLEntry.DAAnonDeps; 277*0b57cec5SDimitry Andric 278*0b57cec5SDimitry Andric for (auto *TA : DAAnonDeps) { 279*0b57cec5SDimitry Andric auto I = DepMap.find(TA); 280*0b57cec5SDimitry Andric if (I != DepMap.end()) 281*0b57cec5SDimitry Andric for (const auto &S : I->second) 282*0b57cec5SDimitry Andric Changed |= DANamedDeps.insert(S).second; 283*0b57cec5SDimitry Andric } 284*0b57cec5SDimitry Andric } 285*0b57cec5SDimitry Andric } while (Changed); 286*0b57cec5SDimitry Andric 287*0b57cec5SDimitry Andric return DepMap; 288*0b57cec5SDimitry Andric } 289*0b57cec5SDimitry Andric 290*0b57cec5SDimitry Andric void registerDependencies(const SymbolDependenceMap &QueryDeps) { 291*0b57cec5SDimitry Andric for (auto &NamedDepsEntry : NamedSymbolDeps) { 292*0b57cec5SDimitry Andric auto &Name = NamedDepsEntry.first; 293*0b57cec5SDimitry Andric auto &NameDeps = NamedDepsEntry.second; 294*0b57cec5SDimitry Andric SymbolDependenceMap SymbolDeps; 295*0b57cec5SDimitry Andric 296*0b57cec5SDimitry Andric for (const auto &QueryDepsEntry : QueryDeps) { 297*0b57cec5SDimitry Andric JITDylib &SourceJD = *QueryDepsEntry.first; 298*0b57cec5SDimitry Andric const SymbolNameSet &Symbols = QueryDepsEntry.second; 299*0b57cec5SDimitry Andric auto &DepsForJD = SymbolDeps[&SourceJD]; 300*0b57cec5SDimitry Andric 301*0b57cec5SDimitry Andric for (const auto &S : Symbols) 302*0b57cec5SDimitry Andric if (NameDeps.count(S)) 303*0b57cec5SDimitry Andric DepsForJD.insert(S); 304*0b57cec5SDimitry Andric 305*0b57cec5SDimitry Andric if (DepsForJD.empty()) 306*0b57cec5SDimitry Andric SymbolDeps.erase(&SourceJD); 307*0b57cec5SDimitry Andric } 308*0b57cec5SDimitry Andric 309*0b57cec5SDimitry Andric MR.addDependencies(Name, SymbolDeps); 310*0b57cec5SDimitry Andric } 311*0b57cec5SDimitry Andric } 312*0b57cec5SDimitry Andric 313*0b57cec5SDimitry Andric ObjectLinkingLayer &Layer; 314*0b57cec5SDimitry Andric MaterializationResponsibility MR; 315*0b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> ObjBuffer; 316*0b57cec5SDimitry Andric DenseMap<SymbolStringPtr, SymbolNameSet> NamedSymbolDeps; 317*0b57cec5SDimitry Andric }; 318*0b57cec5SDimitry Andric 319*0b57cec5SDimitry Andric ObjectLinkingLayer::Plugin::~Plugin() {} 320*0b57cec5SDimitry Andric 321*0b57cec5SDimitry Andric ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES, 322*0b57cec5SDimitry Andric JITLinkMemoryManager &MemMgr) 323*0b57cec5SDimitry Andric : ObjectLayer(ES), MemMgr(MemMgr) {} 324*0b57cec5SDimitry Andric 325*0b57cec5SDimitry Andric ObjectLinkingLayer::~ObjectLinkingLayer() { 326*0b57cec5SDimitry Andric if (auto Err = removeAllModules()) 327*0b57cec5SDimitry Andric getExecutionSession().reportError(std::move(Err)); 328*0b57cec5SDimitry Andric } 329*0b57cec5SDimitry Andric 330*0b57cec5SDimitry Andric void ObjectLinkingLayer::emit(MaterializationResponsibility R, 331*0b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> O) { 332*0b57cec5SDimitry Andric assert(O && "Object must not be null"); 333*0b57cec5SDimitry Andric jitLink(llvm::make_unique<ObjectLinkingLayerJITLinkContext>( 334*0b57cec5SDimitry Andric *this, std::move(R), std::move(O))); 335*0b57cec5SDimitry Andric } 336*0b57cec5SDimitry Andric 337*0b57cec5SDimitry Andric void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR, 338*0b57cec5SDimitry Andric const Triple &TT, 339*0b57cec5SDimitry Andric PassConfiguration &PassConfig) { 340*0b57cec5SDimitry Andric for (auto &P : Plugins) 341*0b57cec5SDimitry Andric P->modifyPassConfig(MR, TT, PassConfig); 342*0b57cec5SDimitry Andric } 343*0b57cec5SDimitry Andric 344*0b57cec5SDimitry Andric void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) { 345*0b57cec5SDimitry Andric for (auto &P : Plugins) 346*0b57cec5SDimitry Andric P->notifyLoaded(MR); 347*0b57cec5SDimitry Andric } 348*0b57cec5SDimitry Andric 349*0b57cec5SDimitry Andric Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR, 350*0b57cec5SDimitry Andric AllocPtr Alloc) { 351*0b57cec5SDimitry Andric Error Err = Error::success(); 352*0b57cec5SDimitry Andric for (auto &P : Plugins) 353*0b57cec5SDimitry Andric Err = joinErrors(std::move(Err), P->notifyEmitted(MR)); 354*0b57cec5SDimitry Andric 355*0b57cec5SDimitry Andric if (Err) 356*0b57cec5SDimitry Andric return Err; 357*0b57cec5SDimitry Andric 358*0b57cec5SDimitry Andric { 359*0b57cec5SDimitry Andric std::lock_guard<std::mutex> Lock(LayerMutex); 360*0b57cec5SDimitry Andric UntrackedAllocs.push_back(std::move(Alloc)); 361*0b57cec5SDimitry Andric } 362*0b57cec5SDimitry Andric 363*0b57cec5SDimitry Andric return Error::success(); 364*0b57cec5SDimitry Andric } 365*0b57cec5SDimitry Andric 366*0b57cec5SDimitry Andric Error ObjectLinkingLayer::removeModule(VModuleKey K) { 367*0b57cec5SDimitry Andric Error Err = Error::success(); 368*0b57cec5SDimitry Andric 369*0b57cec5SDimitry Andric for (auto &P : Plugins) 370*0b57cec5SDimitry Andric Err = joinErrors(std::move(Err), P->notifyRemovingModule(K)); 371*0b57cec5SDimitry Andric 372*0b57cec5SDimitry Andric AllocPtr Alloc; 373*0b57cec5SDimitry Andric 374*0b57cec5SDimitry Andric { 375*0b57cec5SDimitry Andric std::lock_guard<std::mutex> Lock(LayerMutex); 376*0b57cec5SDimitry Andric auto AllocItr = TrackedAllocs.find(K); 377*0b57cec5SDimitry Andric Alloc = std::move(AllocItr->second); 378*0b57cec5SDimitry Andric TrackedAllocs.erase(AllocItr); 379*0b57cec5SDimitry Andric } 380*0b57cec5SDimitry Andric 381*0b57cec5SDimitry Andric assert(Alloc && "No allocation for key K"); 382*0b57cec5SDimitry Andric 383*0b57cec5SDimitry Andric return joinErrors(std::move(Err), Alloc->deallocate()); 384*0b57cec5SDimitry Andric } 385*0b57cec5SDimitry Andric 386*0b57cec5SDimitry Andric Error ObjectLinkingLayer::removeAllModules() { 387*0b57cec5SDimitry Andric 388*0b57cec5SDimitry Andric Error Err = Error::success(); 389*0b57cec5SDimitry Andric 390*0b57cec5SDimitry Andric for (auto &P : Plugins) 391*0b57cec5SDimitry Andric Err = joinErrors(std::move(Err), P->notifyRemovingAllModules()); 392*0b57cec5SDimitry Andric 393*0b57cec5SDimitry Andric std::vector<AllocPtr> Allocs; 394*0b57cec5SDimitry Andric { 395*0b57cec5SDimitry Andric std::lock_guard<std::mutex> Lock(LayerMutex); 396*0b57cec5SDimitry Andric Allocs = std::move(UntrackedAllocs); 397*0b57cec5SDimitry Andric 398*0b57cec5SDimitry Andric for (auto &KV : TrackedAllocs) 399*0b57cec5SDimitry Andric Allocs.push_back(std::move(KV.second)); 400*0b57cec5SDimitry Andric 401*0b57cec5SDimitry Andric TrackedAllocs.clear(); 402*0b57cec5SDimitry Andric } 403*0b57cec5SDimitry Andric 404*0b57cec5SDimitry Andric while (!Allocs.empty()) { 405*0b57cec5SDimitry Andric Err = joinErrors(std::move(Err), Allocs.back()->deallocate()); 406*0b57cec5SDimitry Andric Allocs.pop_back(); 407*0b57cec5SDimitry Andric } 408*0b57cec5SDimitry Andric 409*0b57cec5SDimitry Andric return Err; 410*0b57cec5SDimitry Andric } 411*0b57cec5SDimitry Andric 412*0b57cec5SDimitry Andric EHFrameRegistrationPlugin::EHFrameRegistrationPlugin( 413*0b57cec5SDimitry Andric jitlink::EHFrameRegistrar &Registrar) 414*0b57cec5SDimitry Andric : Registrar(Registrar) {} 415*0b57cec5SDimitry Andric 416*0b57cec5SDimitry Andric void EHFrameRegistrationPlugin::modifyPassConfig( 417*0b57cec5SDimitry Andric MaterializationResponsibility &MR, const Triple &TT, 418*0b57cec5SDimitry Andric PassConfiguration &PassConfig) { 419*0b57cec5SDimitry Andric assert(!InProcessLinks.count(&MR) && "Link for MR already being tracked?"); 420*0b57cec5SDimitry Andric 421*0b57cec5SDimitry Andric PassConfig.PostFixupPasses.push_back( 422*0b57cec5SDimitry Andric createEHFrameRecorderPass(TT, [this, &MR](JITTargetAddress Addr) { 423*0b57cec5SDimitry Andric if (Addr) 424*0b57cec5SDimitry Andric InProcessLinks[&MR] = Addr; 425*0b57cec5SDimitry Andric })); 426*0b57cec5SDimitry Andric } 427*0b57cec5SDimitry Andric 428*0b57cec5SDimitry Andric Error EHFrameRegistrationPlugin::notifyEmitted( 429*0b57cec5SDimitry Andric MaterializationResponsibility &MR) { 430*0b57cec5SDimitry Andric 431*0b57cec5SDimitry Andric auto EHFrameAddrItr = InProcessLinks.find(&MR); 432*0b57cec5SDimitry Andric if (EHFrameAddrItr == InProcessLinks.end()) 433*0b57cec5SDimitry Andric return Error::success(); 434*0b57cec5SDimitry Andric 435*0b57cec5SDimitry Andric auto EHFrameAddr = EHFrameAddrItr->second; 436*0b57cec5SDimitry Andric assert(EHFrameAddr && "eh-frame addr to register can not be null"); 437*0b57cec5SDimitry Andric 438*0b57cec5SDimitry Andric InProcessLinks.erase(EHFrameAddrItr); 439*0b57cec5SDimitry Andric if (auto Key = MR.getVModuleKey()) 440*0b57cec5SDimitry Andric TrackedEHFrameAddrs[Key] = EHFrameAddr; 441*0b57cec5SDimitry Andric else 442*0b57cec5SDimitry Andric UntrackedEHFrameAddrs.push_back(EHFrameAddr); 443*0b57cec5SDimitry Andric 444*0b57cec5SDimitry Andric return Registrar.registerEHFrames(EHFrameAddr); 445*0b57cec5SDimitry Andric } 446*0b57cec5SDimitry Andric 447*0b57cec5SDimitry Andric Error EHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) { 448*0b57cec5SDimitry Andric auto EHFrameAddrItr = TrackedEHFrameAddrs.find(K); 449*0b57cec5SDimitry Andric if (EHFrameAddrItr == TrackedEHFrameAddrs.end()) 450*0b57cec5SDimitry Andric return Error::success(); 451*0b57cec5SDimitry Andric 452*0b57cec5SDimitry Andric auto EHFrameAddr = EHFrameAddrItr->second; 453*0b57cec5SDimitry Andric assert(EHFrameAddr && "Tracked eh-frame addr must not be null"); 454*0b57cec5SDimitry Andric 455*0b57cec5SDimitry Andric TrackedEHFrameAddrs.erase(EHFrameAddrItr); 456*0b57cec5SDimitry Andric 457*0b57cec5SDimitry Andric return Registrar.deregisterEHFrames(EHFrameAddr); 458*0b57cec5SDimitry Andric } 459*0b57cec5SDimitry Andric 460*0b57cec5SDimitry Andric Error EHFrameRegistrationPlugin::notifyRemovingAllModules() { 461*0b57cec5SDimitry Andric 462*0b57cec5SDimitry Andric std::vector<JITTargetAddress> EHFrameAddrs = std::move(UntrackedEHFrameAddrs); 463*0b57cec5SDimitry Andric EHFrameAddrs.reserve(EHFrameAddrs.size() + TrackedEHFrameAddrs.size()); 464*0b57cec5SDimitry Andric 465*0b57cec5SDimitry Andric for (auto &KV : TrackedEHFrameAddrs) 466*0b57cec5SDimitry Andric EHFrameAddrs.push_back(KV.second); 467*0b57cec5SDimitry Andric 468*0b57cec5SDimitry Andric TrackedEHFrameAddrs.clear(); 469*0b57cec5SDimitry Andric 470*0b57cec5SDimitry Andric Error Err = Error::success(); 471*0b57cec5SDimitry Andric 472*0b57cec5SDimitry Andric while (!EHFrameAddrs.empty()) { 473*0b57cec5SDimitry Andric auto EHFrameAddr = EHFrameAddrs.back(); 474*0b57cec5SDimitry Andric assert(EHFrameAddr && "Untracked eh-frame addr must not be null"); 475*0b57cec5SDimitry Andric EHFrameAddrs.pop_back(); 476*0b57cec5SDimitry Andric Err = joinErrors(std::move(Err), Registrar.deregisterEHFrames(EHFrameAddr)); 477*0b57cec5SDimitry Andric } 478*0b57cec5SDimitry Andric 479*0b57cec5SDimitry Andric return Err; 480*0b57cec5SDimitry Andric } 481*0b57cec5SDimitry Andric 482*0b57cec5SDimitry Andric } // End namespace orc. 483*0b57cec5SDimitry Andric } // End namespace llvm. 484