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 11 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" 12 #include "llvm/IR/Constants.h" 13 #include "llvm/Object/MachO.h" 14 #include "llvm/Object/ObjectFile.h" 15 #include "llvm/Support/Debug.h" 16 17 #define DEBUG_TYPE "orc" 18 19 namespace llvm { 20 namespace orc { 21 22 IRLayer::~IRLayer() {} 23 24 Error IRLayer::add(JITDylib &JD, ThreadSafeModule TSM, VModuleKey K) { 25 return JD.define(std::make_unique<BasicIRLayerMaterializationUnit>( 26 *this, *getManglingOptions(), std::move(TSM), std::move(K))); 27 } 28 29 IRMaterializationUnit::IRMaterializationUnit( 30 ExecutionSession &ES, const IRSymbolMapper::ManglingOptions &MO, 31 ThreadSafeModule TSM, VModuleKey K) 32 : MaterializationUnit(SymbolFlagsMap(), nullptr, std::move(K)), 33 TSM(std::move(TSM)) { 34 35 assert(this->TSM && "Module must not be null"); 36 37 MangleAndInterner Mangle(ES, this->TSM.getModuleUnlocked()->getDataLayout()); 38 this->TSM.withModuleDo([&](Module &M) { 39 for (auto &G : M.global_values()) { 40 // Skip globals that don't generate symbols. 41 42 if (!G.hasName() || G.isDeclaration() || G.hasLocalLinkage() || 43 G.hasAvailableExternallyLinkage() || G.hasAppendingLinkage()) 44 continue; 45 46 // thread locals generate different symbols depending on whether or not 47 // emulated TLS is enabled. 48 if (G.isThreadLocal() && MO.EmulatedTLS) { 49 auto &GV = cast<GlobalVariable>(G); 50 51 auto Flags = JITSymbolFlags::fromGlobalValue(GV); 52 53 auto EmuTLSV = Mangle(("__emutls_v." + GV.getName()).str()); 54 SymbolFlags[EmuTLSV] = Flags; 55 SymbolToDefinition[EmuTLSV] = &GV; 56 57 // If this GV has a non-zero initializer we'll need to emit an 58 // __emutls.t symbol too. 59 if (GV.hasInitializer()) { 60 const auto *InitVal = GV.getInitializer(); 61 62 // Skip zero-initializers. 63 if (isa<ConstantAggregateZero>(InitVal)) 64 continue; 65 const auto *InitIntValue = dyn_cast<ConstantInt>(InitVal); 66 if (InitIntValue && InitIntValue->isZero()) 67 continue; 68 69 auto EmuTLST = Mangle(("__emutls_t." + GV.getName()).str()); 70 SymbolFlags[EmuTLST] = Flags; 71 } 72 continue; 73 } 74 75 // Otherwise we just need a normal linker mangling. 76 auto MangledName = Mangle(G.getName()); 77 SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G); 78 SymbolToDefinition[MangledName] = &G; 79 } 80 81 // If we need an init symbol for this module then create one. 82 if (!llvm::empty(getStaticInitGVs(M))) { 83 std::string InitSymbolName; 84 raw_string_ostream(InitSymbolName) 85 << "$." << M.getModuleIdentifier() << ".__inits"; 86 InitSymbol = ES.intern(InitSymbolName); 87 SymbolFlags[InitSymbol] = JITSymbolFlags(); 88 } 89 }); 90 } 91 92 IRMaterializationUnit::IRMaterializationUnit( 93 ThreadSafeModule TSM, VModuleKey K, SymbolFlagsMap SymbolFlags, 94 SymbolStringPtr InitSymbol, SymbolNameToDefinitionMap SymbolToDefinition) 95 : MaterializationUnit(std::move(SymbolFlags), std::move(InitSymbol), 96 std::move(K)), 97 TSM(std::move(TSM)), SymbolToDefinition(std::move(SymbolToDefinition)) {} 98 99 StringRef IRMaterializationUnit::getName() const { 100 if (TSM) 101 return TSM.withModuleDo( 102 [](const Module &M) -> StringRef { return M.getModuleIdentifier(); }); 103 return "<null module>"; 104 } 105 106 void IRMaterializationUnit::discard(const JITDylib &JD, 107 const SymbolStringPtr &Name) { 108 LLVM_DEBUG(JD.getExecutionSession().runSessionLocked([&]() { 109 dbgs() << "In " << JD.getName() << " discarding " << *Name << " from MU@" 110 << this << " (" << getName() << ")\n"; 111 });); 112 113 auto I = SymbolToDefinition.find(Name); 114 assert(I != SymbolToDefinition.end() && 115 "Symbol not provided by this MU, or previously discarded"); 116 assert(!I->second->isDeclaration() && 117 "Discard should only apply to definitions"); 118 I->second->setLinkage(GlobalValue::AvailableExternallyLinkage); 119 SymbolToDefinition.erase(I); 120 } 121 122 BasicIRLayerMaterializationUnit::BasicIRLayerMaterializationUnit( 123 IRLayer &L, const IRSymbolMapper::ManglingOptions &MO, ThreadSafeModule TSM, 124 VModuleKey K) 125 : IRMaterializationUnit(L.getExecutionSession(), MO, std::move(TSM), 126 std::move(K)), 127 L(L), K(std::move(K)) {} 128 129 void BasicIRLayerMaterializationUnit::materialize( 130 MaterializationResponsibility R) { 131 132 // Throw away the SymbolToDefinition map: it's not usable after we hand 133 // off the module. 134 SymbolToDefinition.clear(); 135 136 // If cloneToNewContextOnEmit is set, clone the module now. 137 if (L.getCloneToNewContextOnEmit()) 138 TSM = cloneToNewContext(TSM); 139 140 #ifndef NDEBUG 141 auto &ES = R.getTargetJITDylib().getExecutionSession(); 142 auto &N = R.getTargetJITDylib().getName(); 143 #endif // NDEBUG 144 145 LLVM_DEBUG(ES.runSessionLocked( 146 [&]() { dbgs() << "Emitting, for " << N << ", " << *this << "\n"; });); 147 L.emit(std::move(R), std::move(TSM)); 148 LLVM_DEBUG(ES.runSessionLocked([&]() { 149 dbgs() << "Finished emitting, for " << N << ", " << *this << "\n"; 150 });); 151 } 152 153 ObjectLayer::ObjectLayer(ExecutionSession &ES) : ES(ES) {} 154 155 ObjectLayer::~ObjectLayer() {} 156 157 Error ObjectLayer::add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O, 158 VModuleKey K) { 159 auto ObjMU = BasicObjectLayerMaterializationUnit::Create(*this, std::move(K), 160 std::move(O)); 161 if (!ObjMU) 162 return ObjMU.takeError(); 163 return JD.define(std::move(*ObjMU)); 164 } 165 166 Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>> 167 BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L, VModuleKey K, 168 std::unique_ptr<MemoryBuffer> O) { 169 auto ObjSymInfo = 170 getObjectSymbolInfo(L.getExecutionSession(), O->getMemBufferRef()); 171 172 if (!ObjSymInfo) 173 return ObjSymInfo.takeError(); 174 175 auto &SymbolFlags = ObjSymInfo->first; 176 auto &InitSymbol = ObjSymInfo->second; 177 178 return std::unique_ptr<BasicObjectLayerMaterializationUnit>( 179 new BasicObjectLayerMaterializationUnit( 180 L, K, std::move(O), std::move(SymbolFlags), std::move(InitSymbol))); 181 } 182 183 BasicObjectLayerMaterializationUnit::BasicObjectLayerMaterializationUnit( 184 ObjectLayer &L, VModuleKey K, std::unique_ptr<MemoryBuffer> O, 185 SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol) 186 : MaterializationUnit(std::move(SymbolFlags), std::move(InitSymbol), 187 std::move(K)), 188 L(L), O(std::move(O)) {} 189 190 StringRef BasicObjectLayerMaterializationUnit::getName() const { 191 if (O) 192 return O->getBufferIdentifier(); 193 return "<null object>"; 194 } 195 196 void BasicObjectLayerMaterializationUnit::materialize( 197 MaterializationResponsibility R) { 198 L.emit(std::move(R), std::move(O)); 199 } 200 201 void BasicObjectLayerMaterializationUnit::discard(const JITDylib &JD, 202 const SymbolStringPtr &Name) { 203 // FIXME: Support object file level discard. This could be done by building a 204 // filter to pass to the object layer along with the object itself. 205 } 206 207 } // End namespace orc. 208 } // End namespace llvm. 209