xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Layer.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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