1 //===-------------------- Layer.cpp - Layer interfaces --------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/ExecutionEngine/Orc/Layer.h" 10 #include "llvm/Object/ObjectFile.h" 11 #include "llvm/Support/Debug.h" 12 13 #define DEBUG_TYPE "orc" 14 15 namespace llvm { 16 namespace orc { 17 18 IRLayer::IRLayer(ExecutionSession &ES) : ES(ES) {} 19 IRLayer::~IRLayer() {} 20 21 Error IRLayer::add(JITDylib &JD, ThreadSafeModule TSM, VModuleKey K) { 22 return JD.define(llvm::make_unique<BasicIRLayerMaterializationUnit>( 23 *this, std::move(K), std::move(TSM))); 24 } 25 26 IRMaterializationUnit::IRMaterializationUnit(ExecutionSession &ES, 27 ThreadSafeModule TSM, VModuleKey K) 28 : MaterializationUnit(SymbolFlagsMap(), std::move(K)), TSM(std::move(TSM)) { 29 30 assert(this->TSM && "Module must not be null"); 31 32 MangleAndInterner Mangle(ES, this->TSM.getModule()->getDataLayout()); 33 for (auto &G : this->TSM.getModule()->global_values()) { 34 if (G.hasName() && !G.isDeclaration() && !G.hasLocalLinkage() && 35 !G.hasAvailableExternallyLinkage() && !G.hasAppendingLinkage()) { 36 auto MangledName = Mangle(G.getName()); 37 SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G); 38 SymbolToDefinition[MangledName] = &G; 39 } 40 } 41 } 42 43 IRMaterializationUnit::IRMaterializationUnit( 44 ThreadSafeModule TSM, VModuleKey K, SymbolFlagsMap SymbolFlags, 45 SymbolNameToDefinitionMap SymbolToDefinition) 46 : MaterializationUnit(std::move(SymbolFlags), std::move(K)), 47 TSM(std::move(TSM)), SymbolToDefinition(std::move(SymbolToDefinition)) {} 48 49 StringRef IRMaterializationUnit::getName() const { 50 if (TSM.getModule()) 51 return TSM.getModule()->getModuleIdentifier(); 52 return "<null module>"; 53 } 54 55 void IRMaterializationUnit::discard(const JITDylib &JD, 56 const SymbolStringPtr &Name) { 57 LLVM_DEBUG(JD.getExecutionSession().runSessionLocked([&]() { 58 dbgs() << "In " << JD.getName() << " discarding " << *Name << " from MU@" 59 << this << " (" << getName() << ")\n"; 60 });); 61 62 auto I = SymbolToDefinition.find(Name); 63 assert(I != SymbolToDefinition.end() && 64 "Symbol not provided by this MU, or previously discarded"); 65 assert(!I->second->isDeclaration() && 66 "Discard should only apply to definitions"); 67 I->second->setLinkage(GlobalValue::AvailableExternallyLinkage); 68 SymbolToDefinition.erase(I); 69 } 70 71 BasicIRLayerMaterializationUnit::BasicIRLayerMaterializationUnit( 72 IRLayer &L, VModuleKey K, ThreadSafeModule TSM) 73 : IRMaterializationUnit(L.getExecutionSession(), std::move(TSM), 74 std::move(K)), 75 L(L), K(std::move(K)) {} 76 77 void BasicIRLayerMaterializationUnit::materialize( 78 MaterializationResponsibility R) { 79 80 // Throw away the SymbolToDefinition map: it's not usable after we hand 81 // off the module. 82 SymbolToDefinition.clear(); 83 84 // If cloneToNewContextOnEmit is set, clone the module now. 85 if (L.getCloneToNewContextOnEmit()) 86 TSM = cloneToNewContext(TSM); 87 88 #ifndef NDEBUG 89 auto &ES = R.getTargetJITDylib().getExecutionSession(); 90 auto &N = R.getTargetJITDylib().getName(); 91 #endif // NDEBUG 92 93 auto Lock = TSM.getContextLock(); 94 LLVM_DEBUG(ES.runSessionLocked( 95 [&]() { dbgs() << "Emitting, for " << N << ", " << *this << "\n"; });); 96 L.emit(std::move(R), std::move(TSM)); 97 LLVM_DEBUG(ES.runSessionLocked([&]() { 98 dbgs() << "Finished emitting, for " << N << ", " << *this << "\n"; 99 });); 100 } 101 102 ObjectLayer::ObjectLayer(ExecutionSession &ES) : ES(ES) {} 103 104 ObjectLayer::~ObjectLayer() {} 105 106 Error ObjectLayer::add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O, 107 VModuleKey K) { 108 auto ObjMU = BasicObjectLayerMaterializationUnit::Create(*this, std::move(K), 109 std::move(O)); 110 if (!ObjMU) 111 return ObjMU.takeError(); 112 return JD.define(std::move(*ObjMU)); 113 } 114 115 Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>> 116 BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L, VModuleKey K, 117 std::unique_ptr<MemoryBuffer> O) { 118 auto SymbolFlags = 119 getObjectSymbolFlags(L.getExecutionSession(), O->getMemBufferRef()); 120 121 if (!SymbolFlags) 122 return SymbolFlags.takeError(); 123 124 return std::unique_ptr<BasicObjectLayerMaterializationUnit>( 125 new BasicObjectLayerMaterializationUnit(L, K, std::move(O), 126 std::move(*SymbolFlags))); 127 } 128 129 BasicObjectLayerMaterializationUnit::BasicObjectLayerMaterializationUnit( 130 ObjectLayer &L, VModuleKey K, std::unique_ptr<MemoryBuffer> O, 131 SymbolFlagsMap SymbolFlags) 132 : MaterializationUnit(std::move(SymbolFlags), std::move(K)), L(L), 133 O(std::move(O)) {} 134 135 StringRef BasicObjectLayerMaterializationUnit::getName() const { 136 if (O) 137 return O->getBufferIdentifier(); 138 return "<null object>"; 139 } 140 141 void BasicObjectLayerMaterializationUnit::materialize( 142 MaterializationResponsibility R) { 143 L.emit(std::move(R), std::move(O)); 144 } 145 146 void BasicObjectLayerMaterializationUnit::discard(const JITDylib &JD, 147 const SymbolStringPtr &Name) { 148 // FIXME: Support object file level discard. This could be done by building a 149 // filter to pass to the object layer along with the object itself. 150 } 151 152 Expected<SymbolFlagsMap> getObjectSymbolFlags(ExecutionSession &ES, 153 MemoryBufferRef ObjBuffer) { 154 auto Obj = object::ObjectFile::createObjectFile(ObjBuffer); 155 156 if (!Obj) 157 return Obj.takeError(); 158 159 SymbolFlagsMap SymbolFlags; 160 for (auto &Sym : (*Obj)->symbols()) { 161 // Skip symbols not defined in this object file. 162 if (Sym.getFlags() & object::BasicSymbolRef::SF_Undefined) 163 continue; 164 165 // Skip symbols that are not global. 166 if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global)) 167 continue; 168 169 auto Name = Sym.getName(); 170 if (!Name) 171 return Name.takeError(); 172 auto InternedName = ES.intern(*Name); 173 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 174 if (!SymFlags) 175 return SymFlags.takeError(); 176 SymbolFlags[InternedName] = std::move(*SymFlags); 177 } 178 179 return SymbolFlags; 180 } 181 182 } // End namespace orc. 183 } // End namespace llvm. 184