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(std::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.getModuleUnlocked()->getDataLayout()); 33 this->TSM.withModuleDo([&](Module &M) { 34 for (auto &G : M.global_values()) { 35 if (G.hasName() && !G.isDeclaration() && !G.hasLocalLinkage() && 36 !G.hasAvailableExternallyLinkage() && !G.hasAppendingLinkage()) { 37 auto MangledName = Mangle(G.getName()); 38 SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G); 39 SymbolToDefinition[MangledName] = &G; 40 } 41 } 42 }); 43 } 44 45 IRMaterializationUnit::IRMaterializationUnit( 46 ThreadSafeModule TSM, VModuleKey K, SymbolFlagsMap SymbolFlags, 47 SymbolNameToDefinitionMap SymbolToDefinition) 48 : MaterializationUnit(std::move(SymbolFlags), std::move(K)), 49 TSM(std::move(TSM)), SymbolToDefinition(std::move(SymbolToDefinition)) {} 50 51 StringRef IRMaterializationUnit::getName() const { 52 if (TSM) 53 return TSM.withModuleDo( 54 [](const Module &M) -> StringRef { return M.getModuleIdentifier(); }); 55 return "<null module>"; 56 } 57 58 void IRMaterializationUnit::discard(const JITDylib &JD, 59 const SymbolStringPtr &Name) { 60 LLVM_DEBUG(JD.getExecutionSession().runSessionLocked([&]() { 61 dbgs() << "In " << JD.getName() << " discarding " << *Name << " from MU@" 62 << this << " (" << getName() << ")\n"; 63 });); 64 65 auto I = SymbolToDefinition.find(Name); 66 assert(I != SymbolToDefinition.end() && 67 "Symbol not provided by this MU, or previously discarded"); 68 assert(!I->second->isDeclaration() && 69 "Discard should only apply to definitions"); 70 I->second->setLinkage(GlobalValue::AvailableExternallyLinkage); 71 SymbolToDefinition.erase(I); 72 } 73 74 BasicIRLayerMaterializationUnit::BasicIRLayerMaterializationUnit( 75 IRLayer &L, VModuleKey K, ThreadSafeModule TSM) 76 : IRMaterializationUnit(L.getExecutionSession(), std::move(TSM), 77 std::move(K)), 78 L(L), K(std::move(K)) {} 79 80 void BasicIRLayerMaterializationUnit::materialize( 81 MaterializationResponsibility R) { 82 83 // Throw away the SymbolToDefinition map: it's not usable after we hand 84 // off the module. 85 SymbolToDefinition.clear(); 86 87 // If cloneToNewContextOnEmit is set, clone the module now. 88 if (L.getCloneToNewContextOnEmit()) 89 TSM = cloneToNewContext(TSM); 90 91 #ifndef NDEBUG 92 auto &ES = R.getTargetJITDylib().getExecutionSession(); 93 auto &N = R.getTargetJITDylib().getName(); 94 #endif // NDEBUG 95 96 LLVM_DEBUG(ES.runSessionLocked( 97 [&]() { dbgs() << "Emitting, for " << N << ", " << *this << "\n"; });); 98 L.emit(std::move(R), std::move(TSM)); 99 LLVM_DEBUG(ES.runSessionLocked([&]() { 100 dbgs() << "Finished emitting, for " << N << ", " << *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