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