10b57cec5SDimitry Andric //===-------------------- Layer.cpp - Layer interfaces --------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/ExecutionEngine/Orc/Layer.h" 105ffd83dbSDimitry Andric 115ffd83dbSDimitry Andric #include "llvm/ExecutionEngine/Orc/DebugUtils.h" 125ffd83dbSDimitry Andric #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" 130eae32dcSDimitry Andric #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h" 1413138422SDimitry Andric #include "llvm/IR/Constants.h" 150b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #define DEBUG_TYPE "orc" 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric namespace llvm { 200b57cec5SDimitry Andric namespace orc { 210b57cec5SDimitry Andric 2281ad6265SDimitry Andric IRLayer::~IRLayer() = default; 230b57cec5SDimitry Andric 24e8d8bef9SDimitry Andric Error IRLayer::add(ResourceTrackerSP RT, ThreadSafeModule TSM) { 25e8d8bef9SDimitry Andric assert(RT && "RT can not be null"); 26e8d8bef9SDimitry Andric auto &JD = RT->getJITDylib(); 278bcb0991SDimitry Andric return JD.define(std::make_unique<BasicIRLayerMaterializationUnit>( 28e8d8bef9SDimitry Andric *this, *getManglingOptions(), std::move(TSM)), 29e8d8bef9SDimitry Andric std::move(RT)); 300b57cec5SDimitry Andric } 310b57cec5SDimitry Andric 325ffd83dbSDimitry Andric IRMaterializationUnit::IRMaterializationUnit( 335ffd83dbSDimitry Andric ExecutionSession &ES, const IRSymbolMapper::ManglingOptions &MO, 34e8d8bef9SDimitry Andric ThreadSafeModule TSM) 350eae32dcSDimitry Andric : MaterializationUnit(Interface()), TSM(std::move(TSM)) { 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric assert(this->TSM && "Module must not be null"); 380b57cec5SDimitry Andric 398bcb0991SDimitry Andric MangleAndInterner Mangle(ES, this->TSM.getModuleUnlocked()->getDataLayout()); 408bcb0991SDimitry Andric this->TSM.withModuleDo([&](Module &M) { 418bcb0991SDimitry Andric for (auto &G : M.global_values()) { 4213138422SDimitry Andric // Skip globals that don't generate symbols. 435ffd83dbSDimitry Andric 4413138422SDimitry Andric if (!G.hasName() || G.isDeclaration() || G.hasLocalLinkage() || 4513138422SDimitry Andric G.hasAvailableExternallyLinkage() || G.hasAppendingLinkage()) 4613138422SDimitry Andric continue; 4713138422SDimitry Andric 4813138422SDimitry Andric // thread locals generate different symbols depending on whether or not 4913138422SDimitry Andric // emulated TLS is enabled. 5013138422SDimitry Andric if (G.isThreadLocal() && MO.EmulatedTLS) { 5113138422SDimitry Andric auto &GV = cast<GlobalVariable>(G); 5213138422SDimitry Andric 5313138422SDimitry Andric auto Flags = JITSymbolFlags::fromGlobalValue(GV); 5413138422SDimitry Andric 5513138422SDimitry Andric auto EmuTLSV = Mangle(("__emutls_v." + GV.getName()).str()); 5613138422SDimitry Andric SymbolFlags[EmuTLSV] = Flags; 5713138422SDimitry Andric SymbolToDefinition[EmuTLSV] = &GV; 5813138422SDimitry Andric 5913138422SDimitry Andric // If this GV has a non-zero initializer we'll need to emit an 6013138422SDimitry Andric // __emutls.t symbol too. 6113138422SDimitry Andric if (GV.hasInitializer()) { 6213138422SDimitry Andric const auto *InitVal = GV.getInitializer(); 6313138422SDimitry Andric 6413138422SDimitry Andric // Skip zero-initializers. 6513138422SDimitry Andric if (isa<ConstantAggregateZero>(InitVal)) 6613138422SDimitry Andric continue; 6713138422SDimitry Andric const auto *InitIntValue = dyn_cast<ConstantInt>(InitVal); 6813138422SDimitry Andric if (InitIntValue && InitIntValue->isZero()) 6913138422SDimitry Andric continue; 7013138422SDimitry Andric 7113138422SDimitry Andric auto EmuTLST = Mangle(("__emutls_t." + GV.getName()).str()); 7213138422SDimitry Andric SymbolFlags[EmuTLST] = Flags; 7313138422SDimitry Andric } 7413138422SDimitry Andric continue; 7513138422SDimitry Andric } 7613138422SDimitry Andric 7713138422SDimitry Andric // Otherwise we just need a normal linker mangling. 780b57cec5SDimitry Andric auto MangledName = Mangle(G.getName()); 790b57cec5SDimitry Andric SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G); 80bdd1243dSDimitry Andric if (G.getComdat() && 81bdd1243dSDimitry Andric G.getComdat()->getSelectionKind() != Comdat::NoDeduplicate) 82bdd1243dSDimitry Andric SymbolFlags[MangledName] |= JITSymbolFlags::Weak; 830b57cec5SDimitry Andric SymbolToDefinition[MangledName] = &G; 840b57cec5SDimitry Andric } 855ffd83dbSDimitry Andric 865ffd83dbSDimitry Andric // If we need an init symbol for this module then create one. 87bdd1243dSDimitry Andric if (!getStaticInitGVs(M).empty()) { 885ffd83dbSDimitry Andric size_t Counter = 0; 895ffd83dbSDimitry Andric 90e8d8bef9SDimitry Andric do { 915ffd83dbSDimitry Andric std::string InitSymbolName; 925ffd83dbSDimitry Andric raw_string_ostream(InitSymbolName) 935ffd83dbSDimitry Andric << "$." << M.getModuleIdentifier() << ".__inits." << Counter++; 945ffd83dbSDimitry Andric InitSymbol = ES.intern(InitSymbolName); 95e8d8bef9SDimitry Andric } while (SymbolFlags.count(InitSymbol)); 96e8d8bef9SDimitry Andric 97e8d8bef9SDimitry Andric SymbolFlags[InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly; 985ffd83dbSDimitry Andric } 998bcb0991SDimitry Andric }); 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric IRMaterializationUnit::IRMaterializationUnit( 1030eae32dcSDimitry Andric ThreadSafeModule TSM, Interface I, 1040eae32dcSDimitry Andric SymbolNameToDefinitionMap SymbolToDefinition) 1050eae32dcSDimitry Andric : MaterializationUnit(std::move(I)), TSM(std::move(TSM)), 1060eae32dcSDimitry Andric SymbolToDefinition(std::move(SymbolToDefinition)) {} 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric StringRef IRMaterializationUnit::getName() const { 1098bcb0991SDimitry Andric if (TSM) 1108bcb0991SDimitry Andric return TSM.withModuleDo( 1118bcb0991SDimitry Andric [](const Module &M) -> StringRef { return M.getModuleIdentifier(); }); 1120b57cec5SDimitry Andric return "<null module>"; 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric void IRMaterializationUnit::discard(const JITDylib &JD, 1160b57cec5SDimitry Andric const SymbolStringPtr &Name) { 1170b57cec5SDimitry Andric LLVM_DEBUG(JD.getExecutionSession().runSessionLocked([&]() { 1180b57cec5SDimitry Andric dbgs() << "In " << JD.getName() << " discarding " << *Name << " from MU@" 1190b57cec5SDimitry Andric << this << " (" << getName() << ")\n"; 1200b57cec5SDimitry Andric });); 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric auto I = SymbolToDefinition.find(Name); 1230b57cec5SDimitry Andric assert(I != SymbolToDefinition.end() && 1240b57cec5SDimitry Andric "Symbol not provided by this MU, or previously discarded"); 1250b57cec5SDimitry Andric assert(!I->second->isDeclaration() && 1260b57cec5SDimitry Andric "Discard should only apply to definitions"); 1270b57cec5SDimitry Andric I->second->setLinkage(GlobalValue::AvailableExternallyLinkage); 1281ac55f4cSDimitry Andric // According to the IR verifier, "Declaration[s] may not be in a Comdat!" 1291ac55f4cSDimitry Andric // Remove it, if this is a GlobalObject. 1301ac55f4cSDimitry Andric if (auto *GO = dyn_cast<GlobalObject>(I->second)) 1311ac55f4cSDimitry Andric GO->setComdat(nullptr); 1320b57cec5SDimitry Andric SymbolToDefinition.erase(I); 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric BasicIRLayerMaterializationUnit::BasicIRLayerMaterializationUnit( 136e8d8bef9SDimitry Andric IRLayer &L, const IRSymbolMapper::ManglingOptions &MO, ThreadSafeModule TSM) 137e8d8bef9SDimitry Andric : IRMaterializationUnit(L.getExecutionSession(), MO, std::move(TSM)), L(L) { 138e8d8bef9SDimitry Andric } 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric void BasicIRLayerMaterializationUnit::materialize( 141e8d8bef9SDimitry Andric std::unique_ptr<MaterializationResponsibility> R) { 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric // Throw away the SymbolToDefinition map: it's not usable after we hand 1440b57cec5SDimitry Andric // off the module. 1450b57cec5SDimitry Andric SymbolToDefinition.clear(); 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric // If cloneToNewContextOnEmit is set, clone the module now. 1480b57cec5SDimitry Andric if (L.getCloneToNewContextOnEmit()) 1490b57cec5SDimitry Andric TSM = cloneToNewContext(TSM); 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric #ifndef NDEBUG 152e8d8bef9SDimitry Andric auto &ES = R->getTargetJITDylib().getExecutionSession(); 153e8d8bef9SDimitry Andric auto &N = R->getTargetJITDylib().getName(); 1540b57cec5SDimitry Andric #endif // NDEBUG 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric LLVM_DEBUG(ES.runSessionLocked( 1570b57cec5SDimitry Andric [&]() { dbgs() << "Emitting, for " << N << ", " << *this << "\n"; });); 1580b57cec5SDimitry Andric L.emit(std::move(R), std::move(TSM)); 1590b57cec5SDimitry Andric LLVM_DEBUG(ES.runSessionLocked([&]() { 1600b57cec5SDimitry Andric dbgs() << "Finished emitting, for " << N << ", " << *this << "\n"; 1610b57cec5SDimitry Andric });); 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric 164fe6060f1SDimitry Andric char ObjectLayer::ID; 165fe6060f1SDimitry Andric 1660b57cec5SDimitry Andric ObjectLayer::ObjectLayer(ExecutionSession &ES) : ES(ES) {} 1670b57cec5SDimitry Andric 16881ad6265SDimitry Andric ObjectLayer::~ObjectLayer() = default; 1690b57cec5SDimitry Andric 1700eae32dcSDimitry Andric Error ObjectLayer::add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O, 1710eae32dcSDimitry Andric MaterializationUnit::Interface I) { 172e8d8bef9SDimitry Andric assert(RT && "RT can not be null"); 173e8d8bef9SDimitry Andric auto &JD = RT->getJITDylib(); 1740eae32dcSDimitry Andric return JD.define(std::make_unique<BasicObjectLayerMaterializationUnit>( 1750eae32dcSDimitry Andric *this, std::move(O), std::move(I)), 1760eae32dcSDimitry Andric std::move(RT)); 1770eae32dcSDimitry Andric } 1780eae32dcSDimitry Andric 1790eae32dcSDimitry Andric Error ObjectLayer::add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O) { 1800eae32dcSDimitry Andric auto I = getObjectFileInterface(getExecutionSession(), O->getMemBufferRef()); 1810eae32dcSDimitry Andric if (!I) 1820eae32dcSDimitry Andric return I.takeError(); 1830eae32dcSDimitry Andric return add(std::move(RT), std::move(O), std::move(*I)); 1840eae32dcSDimitry Andric } 1850eae32dcSDimitry Andric 1860eae32dcSDimitry Andric Error ObjectLayer::add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O) { 1870eae32dcSDimitry Andric auto I = getObjectFileInterface(getExecutionSession(), O->getMemBufferRef()); 1880eae32dcSDimitry Andric if (!I) 1890eae32dcSDimitry Andric return I.takeError(); 1900eae32dcSDimitry Andric return add(JD, std::move(O), std::move(*I)); 1910b57cec5SDimitry Andric } 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>> 194e8d8bef9SDimitry Andric BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L, 1950b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> O) { 1960b57cec5SDimitry Andric 1970eae32dcSDimitry Andric auto ObjInterface = 1980eae32dcSDimitry Andric getObjectFileInterface(L.getExecutionSession(), O->getMemBufferRef()); 1995ffd83dbSDimitry Andric 2000eae32dcSDimitry Andric if (!ObjInterface) 2010eae32dcSDimitry Andric return ObjInterface.takeError(); 2020b57cec5SDimitry Andric 203*0fca6ea1SDimitry Andric return std::make_unique<BasicObjectLayerMaterializationUnit>( 204*0fca6ea1SDimitry Andric L, std::move(O), std::move(*ObjInterface)); 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric BasicObjectLayerMaterializationUnit::BasicObjectLayerMaterializationUnit( 2080eae32dcSDimitry Andric ObjectLayer &L, std::unique_ptr<MemoryBuffer> O, Interface I) 2090eae32dcSDimitry Andric : MaterializationUnit(std::move(I)), L(L), O(std::move(O)) {} 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric StringRef BasicObjectLayerMaterializationUnit::getName() const { 2120b57cec5SDimitry Andric if (O) 2130b57cec5SDimitry Andric return O->getBufferIdentifier(); 2140b57cec5SDimitry Andric return "<null object>"; 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric void BasicObjectLayerMaterializationUnit::materialize( 218e8d8bef9SDimitry Andric std::unique_ptr<MaterializationResponsibility> R) { 2190b57cec5SDimitry Andric L.emit(std::move(R), std::move(O)); 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric void BasicObjectLayerMaterializationUnit::discard(const JITDylib &JD, 2230b57cec5SDimitry Andric const SymbolStringPtr &Name) { 2245ffd83dbSDimitry Andric // This is a no-op for object files: Having removed 'Name' from SymbolFlags 2255ffd83dbSDimitry Andric // the symbol will be dead-stripped by the JIT linker. 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric } // End namespace orc. 2290b57cec5SDimitry Andric } // End namespace llvm. 230