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 #endif // NDEBUG 91 92 auto Lock = TSM.getContextLock(); 93 LLVM_DEBUG(ES.runSessionLocked([&]() { 94 dbgs() << "Emitting, for " << R.getTargetJITDylib().getName() << ", " 95 << *this << "\n"; 96 });); 97 L.emit(std::move(R), std::move(TSM)); 98 LLVM_DEBUG(ES.runSessionLocked([&]() { 99 dbgs() << "Finished emitting, for " << R.getTargetJITDylib().getName() 100 << ", " << *this << "\n"; 101 });); 102 } 103 104 ObjectLayer::ObjectLayer(ExecutionSession &ES) : ES(ES) {} 105 106 ObjectLayer::~ObjectLayer() {} 107 108 Error ObjectLayer::add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O, 109 VModuleKey K) { 110 auto ObjMU = BasicObjectLayerMaterializationUnit::Create(*this, std::move(K), 111 std::move(O)); 112 if (!ObjMU) 113 return ObjMU.takeError(); 114 return JD.define(std::move(*ObjMU)); 115 } 116 117 Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>> 118 BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L, VModuleKey K, 119 std::unique_ptr<MemoryBuffer> O) { 120 auto SymbolFlags = 121 getObjectSymbolFlags(L.getExecutionSession(), O->getMemBufferRef()); 122 123 if (!SymbolFlags) 124 return SymbolFlags.takeError(); 125 126 return std::unique_ptr<BasicObjectLayerMaterializationUnit>( 127 new BasicObjectLayerMaterializationUnit(L, K, std::move(O), 128 std::move(*SymbolFlags))); 129 } 130 131 BasicObjectLayerMaterializationUnit::BasicObjectLayerMaterializationUnit( 132 ObjectLayer &L, VModuleKey K, std::unique_ptr<MemoryBuffer> O, 133 SymbolFlagsMap SymbolFlags) 134 : MaterializationUnit(std::move(SymbolFlags), std::move(K)), L(L), 135 O(std::move(O)) {} 136 137 StringRef BasicObjectLayerMaterializationUnit::getName() const { 138 if (O) 139 return O->getBufferIdentifier(); 140 return "<null object>"; 141 } 142 143 void BasicObjectLayerMaterializationUnit::materialize( 144 MaterializationResponsibility R) { 145 L.emit(std::move(R), std::move(O)); 146 } 147 148 void BasicObjectLayerMaterializationUnit::discard(const JITDylib &JD, 149 const SymbolStringPtr &Name) { 150 // FIXME: Support object file level discard. This could be done by building a 151 // filter to pass to the object layer along with the object itself. 152 } 153 154 Expected<SymbolFlagsMap> getObjectSymbolFlags(ExecutionSession &ES, 155 MemoryBufferRef ObjBuffer) { 156 auto Obj = object::ObjectFile::createObjectFile(ObjBuffer); 157 158 if (!Obj) 159 return Obj.takeError(); 160 161 SymbolFlagsMap SymbolFlags; 162 for (auto &Sym : (*Obj)->symbols()) { 163 // Skip symbols not defined in this object file. 164 if (Sym.getFlags() & object::BasicSymbolRef::SF_Undefined) 165 continue; 166 167 // Skip symbols that are not global. 168 if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global)) 169 continue; 170 171 auto Name = Sym.getName(); 172 if (!Name) 173 return Name.takeError(); 174 auto InternedName = ES.intern(*Name); 175 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 176 if (!SymFlags) 177 return SymFlags.takeError(); 178 SymbolFlags[InternedName] = std::move(*SymFlags); 179 } 180 181 return SymbolFlags; 182 } 183 184 } // End namespace orc. 185 } // End namespace llvm. 186