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, VModuleKey K, ThreadSafeModule TSM) { 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) 29 : MaterializationUnit(SymbolFlagsMap()), 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, SymbolFlagsMap SymbolFlags, 46 SymbolNameToDefinitionMap SymbolToDefinition) 47 : MaterializationUnit(std::move(SymbolFlags)), TSM(std::move(TSM)), 48 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)), L(L), 75 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(K), 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, VModuleKey K, 109 std::unique_ptr<MemoryBuffer> O) { 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)), L(L), K(std::move(K)), 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(K), 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