11cf9987fSLang Hames //===-------------------- Layer.cpp - Layer interfaces --------------------===//
21cf9987fSLang Hames //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61cf9987fSLang Hames //
71cf9987fSLang Hames //===----------------------------------------------------------------------===//
81cf9987fSLang Hames 
91cf9987fSLang Hames #include "llvm/ExecutionEngine/Orc/Layer.h"
1085fb9976SLang Hames 
1138a8760bSLang Hames #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
1285fb9976SLang Hames #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
134299d8d0SLang Hames #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
14ce2207abSLang Hames #include "llvm/IR/Constants.h"
1546f40a71SLang Hames #include "llvm/Support/Debug.h"
1646f40a71SLang Hames 
1746f40a71SLang Hames #define DEBUG_TYPE "orc"
181cf9987fSLang Hames 
191cf9987fSLang Hames namespace llvm {
201cf9987fSLang Hames namespace orc {
211cf9987fSLang Hames 
22*3a3cb929SKazu Hirata IRLayer::~IRLayer() = default;
231cf9987fSLang Hames 
add(ResourceTrackerSP RT,ThreadSafeModule TSM)240aec49c8SLang Hames Error IRLayer::add(ResourceTrackerSP RT, ThreadSafeModule TSM) {
250aec49c8SLang Hames   assert(RT && "RT can not be null");
260aec49c8SLang Hames   auto &JD = RT->getJITDylib();
270eaee545SJonas Devlieghere   return JD.define(std::make_unique<BasicIRLayerMaterializationUnit>(
280aec49c8SLang Hames                        *this, *getManglingOptions(), std::move(TSM)),
290aec49c8SLang Hames                    std::move(RT));
301cf9987fSLang Hames }
311cf9987fSLang Hames 
IRMaterializationUnit(ExecutionSession & ES,const IRSymbolMapper::ManglingOptions & MO,ThreadSafeModule TSM)3285fb9976SLang Hames IRMaterializationUnit::IRMaterializationUnit(
3385fb9976SLang Hames     ExecutionSession &ES, const IRSymbolMapper::ManglingOptions &MO,
340aec49c8SLang Hames     ThreadSafeModule TSM)
35ae73f3fdSLang Hames     : MaterializationUnit(Interface()), TSM(std::move(TSM)) {
361cf9987fSLang Hames 
378d76c711SLang Hames   assert(this->TSM && "Module must not be null");
388d76c711SLang Hames 
39809e9d1eSLang Hames   MangleAndInterner Mangle(ES, this->TSM.getModuleUnlocked()->getDataLayout());
40809e9d1eSLang Hames   this->TSM.withModuleDo([&](Module &M) {
41809e9d1eSLang Hames     for (auto &G : M.global_values()) {
42ce2207abSLang Hames       // Skip globals that don't generate symbols.
4385fb9976SLang Hames 
44ce2207abSLang Hames       if (!G.hasName() || G.isDeclaration() || G.hasLocalLinkage() ||
45ce2207abSLang Hames           G.hasAvailableExternallyLinkage() || G.hasAppendingLinkage())
46ce2207abSLang Hames         continue;
47ce2207abSLang Hames 
48ce2207abSLang Hames       // thread locals generate different symbols depending on whether or not
49ce2207abSLang Hames       // emulated TLS is enabled.
50ce2207abSLang Hames       if (G.isThreadLocal() && MO.EmulatedTLS) {
51ce2207abSLang Hames         auto &GV = cast<GlobalVariable>(G);
52ce2207abSLang Hames 
53ce2207abSLang Hames         auto Flags = JITSymbolFlags::fromGlobalValue(GV);
54ce2207abSLang Hames 
55ce2207abSLang Hames         auto EmuTLSV = Mangle(("__emutls_v." + GV.getName()).str());
56ce2207abSLang Hames         SymbolFlags[EmuTLSV] = Flags;
57ce2207abSLang Hames         SymbolToDefinition[EmuTLSV] = &GV;
58ce2207abSLang Hames 
59ce2207abSLang Hames         // If this GV has a non-zero initializer we'll need to emit an
60ce2207abSLang Hames         // __emutls.t symbol too.
61ce2207abSLang Hames         if (GV.hasInitializer()) {
62ce2207abSLang Hames           const auto *InitVal = GV.getInitializer();
63ce2207abSLang Hames 
64ce2207abSLang Hames           // Skip zero-initializers.
65ce2207abSLang Hames           if (isa<ConstantAggregateZero>(InitVal))
66ce2207abSLang Hames             continue;
67ce2207abSLang Hames           const auto *InitIntValue = dyn_cast<ConstantInt>(InitVal);
68ce2207abSLang Hames           if (InitIntValue && InitIntValue->isZero())
69ce2207abSLang Hames             continue;
70ce2207abSLang Hames 
71ce2207abSLang Hames           auto EmuTLST = Mangle(("__emutls_t." + GV.getName()).str());
72ce2207abSLang Hames           SymbolFlags[EmuTLST] = Flags;
73ce2207abSLang Hames         }
74ce2207abSLang Hames         continue;
75ce2207abSLang Hames       }
76ce2207abSLang Hames 
77ce2207abSLang Hames       // Otherwise we just need a normal linker mangling.
781cf9987fSLang Hames       auto MangledName = Mangle(G.getName());
791cf9987fSLang Hames       SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G);
80d3a76f5bSLang Hames       SymbolToDefinition[MangledName] = &G;
811cf9987fSLang Hames     }
8285fb9976SLang Hames 
8385fb9976SLang Hames     // If we need an init symbol for this module then create one.
8485fb9976SLang Hames     if (!llvm::empty(getStaticInitGVs(M))) {
85cb84e482SLang Hames       size_t Counter = 0;
86cb84e482SLang Hames 
879a47bcaeSStefan Gränitz       do {
8885fb9976SLang Hames         std::string InitSymbolName;
8985fb9976SLang Hames         raw_string_ostream(InitSymbolName)
90cb84e482SLang Hames             << "$." << M.getModuleIdentifier() << ".__inits." << Counter++;
9185fb9976SLang Hames         InitSymbol = ES.intern(InitSymbolName);
929a47bcaeSStefan Gränitz       } while (SymbolFlags.count(InitSymbol));
939a47bcaeSStefan Gränitz 
949a47bcaeSStefan Gränitz       SymbolFlags[InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
9585fb9976SLang Hames     }
96809e9d1eSLang Hames   });
971cf9987fSLang Hames }
981cf9987fSLang Hames 
IRMaterializationUnit(ThreadSafeModule TSM,Interface I,SymbolNameToDefinitionMap SymbolToDefinition)99d6155ff0SLang Hames IRMaterializationUnit::IRMaterializationUnit(
100ae73f3fdSLang Hames     ThreadSafeModule TSM, Interface I,
101ae73f3fdSLang Hames     SymbolNameToDefinitionMap SymbolToDefinition)
102ae73f3fdSLang Hames     : MaterializationUnit(std::move(I)), TSM(std::move(TSM)),
103ae73f3fdSLang Hames       SymbolToDefinition(std::move(SymbolToDefinition)) {}
104d6155ff0SLang Hames 
getName() const10546f40a71SLang Hames StringRef IRMaterializationUnit::getName() const {
106809e9d1eSLang Hames   if (TSM)
107809e9d1eSLang Hames     return TSM.withModuleDo(
1085b3275e5SMatthias Gehre         [](const Module &M) -> StringRef { return M.getModuleIdentifier(); });
10946f40a71SLang Hames   return "<null module>";
11046f40a71SLang Hames }
11146f40a71SLang Hames 
discard(const JITDylib & JD,const SymbolStringPtr & Name)112cb5702c3SLang Hames void IRMaterializationUnit::discard(const JITDylib &JD,
113cb5702c3SLang Hames                                     const SymbolStringPtr &Name) {
11446f40a71SLang Hames   LLVM_DEBUG(JD.getExecutionSession().runSessionLocked([&]() {
11546f40a71SLang Hames     dbgs() << "In " << JD.getName() << " discarding " << *Name << " from MU@"
11646f40a71SLang Hames            << this << " (" << getName() << ")\n";
11746f40a71SLang Hames   }););
11846f40a71SLang Hames 
119d3a76f5bSLang Hames   auto I = SymbolToDefinition.find(Name);
120d3a76f5bSLang Hames   assert(I != SymbolToDefinition.end() &&
1211cf9987fSLang Hames          "Symbol not provided by this MU, or previously discarded");
122d3a76f5bSLang Hames   assert(!I->second->isDeclaration() &&
123d3a76f5bSLang Hames          "Discard should only apply to definitions");
1241cf9987fSLang Hames   I->second->setLinkage(GlobalValue::AvailableExternallyLinkage);
125d3a76f5bSLang Hames   SymbolToDefinition.erase(I);
1261cf9987fSLang Hames }
1271cf9987fSLang Hames 
BasicIRLayerMaterializationUnit(IRLayer & L,const IRSymbolMapper::ManglingOptions & MO,ThreadSafeModule TSM)1285261aa9fSLang Hames BasicIRLayerMaterializationUnit::BasicIRLayerMaterializationUnit(
1290aec49c8SLang Hames     IRLayer &L, const IRSymbolMapper::ManglingOptions &MO, ThreadSafeModule TSM)
1300aec49c8SLang Hames     : IRMaterializationUnit(L.getExecutionSession(), MO, std::move(TSM)), L(L) {
1310aec49c8SLang Hames }
1325261aa9fSLang Hames 
materialize(std::unique_ptr<MaterializationResponsibility> R)1335261aa9fSLang Hames void BasicIRLayerMaterializationUnit::materialize(
1347dcd0042SLang Hames     std::unique_ptr<MaterializationResponsibility> R) {
1358d76c711SLang Hames 
136c3053e41SLang Hames   // Throw away the SymbolToDefinition map: it's not usable after we hand
137c3053e41SLang Hames   // off the module.
138c3053e41SLang Hames   SymbolToDefinition.clear();
139c3053e41SLang Hames 
140c3053e41SLang Hames   // If cloneToNewContextOnEmit is set, clone the module now.
1418d76c711SLang Hames   if (L.getCloneToNewContextOnEmit())
1428d76c711SLang Hames     TSM = cloneToNewContext(TSM);
1438d76c711SLang Hames 
14446f40a71SLang Hames #ifndef NDEBUG
1457dcd0042SLang Hames   auto &ES = R->getTargetJITDylib().getExecutionSession();
1467dcd0042SLang Hames   auto &N = R->getTargetJITDylib().getName();
14746f40a71SLang Hames #endif // NDEBUG
14846f40a71SLang Hames 
14928e351afSNick Desaulniers   LLVM_DEBUG(ES.runSessionLocked(
15028e351afSNick Desaulniers       [&]() { dbgs() << "Emitting, for " << N << ", " << *this << "\n"; }););
1518b94274fSLang Hames   L.emit(std::move(R), std::move(TSM));
15246f40a71SLang Hames   LLVM_DEBUG(ES.runSessionLocked([&]() {
15328e351afSNick Desaulniers     dbgs() << "Finished emitting, for " << N << ", " << *this << "\n";
15446f40a71SLang Hames   }););
1555261aa9fSLang Hames }
1565261aa9fSLang Hames 
157406ef36bSStefan Gränitz char ObjectLayer::ID;
158406ef36bSStefan Gränitz 
ObjectLayer(ExecutionSession & ES)1591cf9987fSLang Hames ObjectLayer::ObjectLayer(ExecutionSession &ES) : ES(ES) {}
1601cf9987fSLang Hames 
161*3a3cb929SKazu Hirata ObjectLayer::~ObjectLayer() = default;
1621cf9987fSLang Hames 
add(ResourceTrackerSP RT,std::unique_ptr<MemoryBuffer> O,MaterializationUnit::Interface I)1634299d8d0SLang Hames Error ObjectLayer::add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O,
1644299d8d0SLang Hames                        MaterializationUnit::Interface I) {
1650aec49c8SLang Hames   assert(RT && "RT can not be null");
1660aec49c8SLang Hames   auto &JD = RT->getJITDylib();
1674299d8d0SLang Hames   return JD.define(std::make_unique<BasicObjectLayerMaterializationUnit>(
1684299d8d0SLang Hames                        *this, std::move(O), std::move(I)),
1694299d8d0SLang Hames                    std::move(RT));
1704299d8d0SLang Hames }
1714299d8d0SLang Hames 
add(ResourceTrackerSP RT,std::unique_ptr<MemoryBuffer> O)1724299d8d0SLang Hames Error ObjectLayer::add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O) {
1734299d8d0SLang Hames   auto I = getObjectFileInterface(getExecutionSession(), O->getMemBufferRef());
1744299d8d0SLang Hames   if (!I)
1754299d8d0SLang Hames     return I.takeError();
1764299d8d0SLang Hames   return add(std::move(RT), std::move(O), std::move(*I));
1774299d8d0SLang Hames }
1784299d8d0SLang Hames 
add(JITDylib & JD,std::unique_ptr<MemoryBuffer> O)1794299d8d0SLang Hames Error ObjectLayer::add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O) {
1804299d8d0SLang Hames   auto I = getObjectFileInterface(getExecutionSession(), O->getMemBufferRef());
1814299d8d0SLang Hames   if (!I)
1824299d8d0SLang Hames     return I.takeError();
1834299d8d0SLang Hames   return add(JD, std::move(O), std::move(*I));
1841cf9987fSLang Hames }
1851cf9987fSLang Hames 
186bfea8cdcSLang Hames Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>>
Create(ObjectLayer & L,std::unique_ptr<MemoryBuffer> O)1870aec49c8SLang Hames BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L,
188bfea8cdcSLang Hames                                             std::unique_ptr<MemoryBuffer> O) {
1894299d8d0SLang Hames 
190ae73f3fdSLang Hames   auto ObjInterface =
1914299d8d0SLang Hames       getObjectFileInterface(L.getExecutionSession(), O->getMemBufferRef());
192c0514f00SLang Hames 
193ae73f3fdSLang Hames   if (!ObjInterface)
194ae73f3fdSLang Hames     return ObjInterface.takeError();
195c0514f00SLang Hames 
196c0514f00SLang Hames   return std::unique_ptr<BasicObjectLayerMaterializationUnit>(
197ae73f3fdSLang Hames       new BasicObjectLayerMaterializationUnit(L, std::move(O),
198ae73f3fdSLang Hames                                               std::move(*ObjInterface)));
199c0514f00SLang Hames }
200c0514f00SLang Hames 
BasicObjectLayerMaterializationUnit(ObjectLayer & L,std::unique_ptr<MemoryBuffer> O,Interface I)201c0514f00SLang Hames BasicObjectLayerMaterializationUnit::BasicObjectLayerMaterializationUnit(
202ae73f3fdSLang Hames     ObjectLayer &L, std::unique_ptr<MemoryBuffer> O, Interface I)
203ae73f3fdSLang Hames     : MaterializationUnit(std::move(I)), L(L), O(std::move(O)) {}
204c0514f00SLang Hames 
getName() const20546f40a71SLang Hames StringRef BasicObjectLayerMaterializationUnit::getName() const {
20646f40a71SLang Hames   if (O)
20746f40a71SLang Hames     return O->getBufferIdentifier();
20846f40a71SLang Hames   return "<null object>";
20946f40a71SLang Hames }
21046f40a71SLang Hames 
materialize(std::unique_ptr<MaterializationResponsibility> R)211c0514f00SLang Hames void BasicObjectLayerMaterializationUnit::materialize(
2127dcd0042SLang Hames     std::unique_ptr<MaterializationResponsibility> R) {
2138b94274fSLang Hames   L.emit(std::move(R), std::move(O));
214c0514f00SLang Hames }
215c0514f00SLang Hames 
discard(const JITDylib & JD,const SymbolStringPtr & Name)216d5f56c59SLang Hames void BasicObjectLayerMaterializationUnit::discard(const JITDylib &JD,
217cb5702c3SLang Hames                                                   const SymbolStringPtr &Name) {
21822ed8c49SLang Hames   // This is a no-op for object files: Having removed 'Name' from SymbolFlags
21922ed8c49SLang Hames   // the symbol will be dead-stripped by the JIT linker.
220c0514f00SLang Hames }
221c0514f00SLang Hames 
2221cf9987fSLang Hames } // End namespace orc.
2231cf9987fSLang Hames } // End namespace llvm.
224