1 //===-------------------- Layer.cpp - Layer interfaces --------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/ExecutionEngine/Orc/Layer.h" 11 #include "llvm/Object/ObjectFile.h" 12 #include "llvm/Support/Debug.h" 13 14 #define DEBUG_TYPE "orc" 15 16 namespace llvm { 17 namespace orc { 18 19 IRLayer::IRLayer(ExecutionSession &ES) : ES(ES) {} 20 IRLayer::~IRLayer() {} 21 22 Error IRLayer::add(JITDylib &JD, ThreadSafeModule TSM, VModuleKey K) { 23 return JD.define(llvm::make_unique<BasicIRLayerMaterializationUnit>( 24 *this, std::move(K), std::move(TSM))); 25 } 26 27 IRMaterializationUnit::IRMaterializationUnit(ExecutionSession &ES, 28 ThreadSafeModule TSM, VModuleKey K) 29 : MaterializationUnit(SymbolFlagsMap(), std::move(K)), TSM(std::move(TSM)) { 30 31 assert(this->TSM && "Module must not be null"); 32 33 MangleAndInterner Mangle(ES, this->TSM.getModule()->getDataLayout()); 34 for (auto &G : this->TSM.getModule()->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 IRMaterializationUnit::IRMaterializationUnit( 45 ThreadSafeModule TSM, VModuleKey K, SymbolFlagsMap SymbolFlags, 46 SymbolNameToDefinitionMap SymbolToDefinition) 47 : MaterializationUnit(std::move(SymbolFlags), std::move(K)), 48 TSM(std::move(TSM)), SymbolToDefinition(std::move(SymbolToDefinition)) {} 49 50 StringRef IRMaterializationUnit::getName() const { 51 if (TSM.getModule()) 52 return TSM.getModule()->getModuleIdentifier(); 53 return "<null module>"; 54 } 55 56 void IRMaterializationUnit::discard(const JITDylib &JD, 57 const SymbolStringPtr &Name) { 58 LLVM_DEBUG(JD.getExecutionSession().runSessionLocked([&]() { 59 dbgs() << "In " << JD.getName() << " discarding " << *Name << " from MU@" 60 << this << " (" << getName() << ")\n"; 61 });); 62 63 auto I = SymbolToDefinition.find(Name); 64 assert(I != SymbolToDefinition.end() && 65 "Symbol not provided by this MU, or previously discarded"); 66 assert(!I->second->isDeclaration() && 67 "Discard should only apply to definitions"); 68 I->second->setLinkage(GlobalValue::AvailableExternallyLinkage); 69 SymbolToDefinition.erase(I); 70 } 71 72 BasicIRLayerMaterializationUnit::BasicIRLayerMaterializationUnit( 73 IRLayer &L, VModuleKey K, ThreadSafeModule TSM) 74 : IRMaterializationUnit(L.getExecutionSession(), std::move(TSM), 75 std::move(K)), 76 L(L), K(std::move(K)) {} 77 78 void BasicIRLayerMaterializationUnit::materialize( 79 MaterializationResponsibility R) { 80 81 // Throw away the SymbolToDefinition map: it's not usable after we hand 82 // off the module. 83 SymbolToDefinition.clear(); 84 85 // If cloneToNewContextOnEmit is set, clone the module now. 86 if (L.getCloneToNewContextOnEmit()) 87 TSM = cloneToNewContext(TSM); 88 89 #ifndef NDEBUG 90 auto &ES = R.getTargetJITDylib().getExecutionSession(); 91 #endif // NDEBUG 92 93 auto Lock = TSM.getContextLock(); 94 LLVM_DEBUG(ES.runSessionLocked([&]() { 95 dbgs() << "Emitting, for " << R.getTargetJITDylib().getName() << ", " 96 << *this << "\n"; 97 });); 98 L.emit(std::move(R), std::move(TSM)); 99 LLVM_DEBUG(ES.runSessionLocked([&]() { 100 dbgs() << "Finished emitting, for " << R.getTargetJITDylib().getName() 101 << ", " << *this << "\n"; 102 });); 103 } 104 105 ObjectLayer::ObjectLayer(ExecutionSession &ES) : ES(ES) {} 106 107 ObjectLayer::~ObjectLayer() {} 108 109 Error ObjectLayer::add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O, 110 VModuleKey K) { 111 auto ObjMU = BasicObjectLayerMaterializationUnit::Create(*this, std::move(K), 112 std::move(O)); 113 if (!ObjMU) 114 return ObjMU.takeError(); 115 return JD.define(std::move(*ObjMU)); 116 } 117 118 Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>> 119 BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L, VModuleKey K, 120 std::unique_ptr<MemoryBuffer> O) { 121 auto SymbolFlags = 122 getObjectSymbolFlags(L.getExecutionSession(), O->getMemBufferRef()); 123 124 if (!SymbolFlags) 125 return SymbolFlags.takeError(); 126 127 return std::unique_ptr<BasicObjectLayerMaterializationUnit>( 128 new BasicObjectLayerMaterializationUnit(L, K, std::move(O), 129 std::move(*SymbolFlags))); 130 } 131 132 BasicObjectLayerMaterializationUnit::BasicObjectLayerMaterializationUnit( 133 ObjectLayer &L, VModuleKey K, std::unique_ptr<MemoryBuffer> O, 134 SymbolFlagsMap SymbolFlags) 135 : MaterializationUnit(std::move(SymbolFlags), std::move(K)), L(L), 136 O(std::move(O)) {} 137 138 StringRef BasicObjectLayerMaterializationUnit::getName() const { 139 if (O) 140 return O->getBufferIdentifier(); 141 return "<null object>"; 142 } 143 144 void BasicObjectLayerMaterializationUnit::materialize( 145 MaterializationResponsibility R) { 146 L.emit(std::move(R), std::move(O)); 147 } 148 149 void BasicObjectLayerMaterializationUnit::discard(const JITDylib &JD, 150 const SymbolStringPtr &Name) { 151 // FIXME: Support object file level discard. This could be done by building a 152 // filter to pass to the object layer along with the object itself. 153 } 154 155 Expected<SymbolFlagsMap> getObjectSymbolFlags(ExecutionSession &ES, 156 MemoryBufferRef ObjBuffer) { 157 auto Obj = object::ObjectFile::createObjectFile(ObjBuffer); 158 159 if (!Obj) 160 return Obj.takeError(); 161 162 SymbolFlagsMap SymbolFlags; 163 for (auto &Sym : (*Obj)->symbols()) { 164 // Skip symbols not defined in this object file. 165 if (Sym.getFlags() & object::BasicSymbolRef::SF_Undefined) 166 continue; 167 168 // Skip symbols that are not global. 169 if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global)) 170 continue; 171 172 auto Name = Sym.getName(); 173 if (!Name) 174 return Name.takeError(); 175 auto InternedName = ES.intern(*Name); 176 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym); 177 if (!SymFlags) 178 return SymFlags.takeError(); 179 SymbolFlags[InternedName] = std::move(*SymFlags); 180 } 181 182 return SymbolFlags; 183 } 184 185 } // End namespace orc. 186 } // End namespace llvm. 187