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