xref: /openbsd-src/gnu/llvm/llvm/lib/ExecutionEngine/Orc/Layer.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===-------------------- Layer.cpp - Layer interfaces --------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick 
909467b48Spatrick #include "llvm/ExecutionEngine/Orc/Layer.h"
10097a140dSpatrick 
11097a140dSpatrick #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
12097a140dSpatrick #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
13*d415bd75Srobert #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
1409467b48Spatrick #include "llvm/IR/Constants.h"
1509467b48Spatrick #include "llvm/Support/Debug.h"
1609467b48Spatrick 
1709467b48Spatrick #define DEBUG_TYPE "orc"
1809467b48Spatrick 
1909467b48Spatrick namespace llvm {
2009467b48Spatrick namespace orc {
2109467b48Spatrick 
22*d415bd75Srobert IRLayer::~IRLayer() = default;
2309467b48Spatrick 
add(ResourceTrackerSP RT,ThreadSafeModule TSM)2473471bf0Spatrick Error IRLayer::add(ResourceTrackerSP RT, ThreadSafeModule TSM) {
2573471bf0Spatrick   assert(RT && "RT can not be null");
2673471bf0Spatrick   auto &JD = RT->getJITDylib();
2709467b48Spatrick   return JD.define(std::make_unique<BasicIRLayerMaterializationUnit>(
2873471bf0Spatrick                        *this, *getManglingOptions(), std::move(TSM)),
2973471bf0Spatrick                    std::move(RT));
3009467b48Spatrick }
3109467b48Spatrick 
IRMaterializationUnit(ExecutionSession & ES,const IRSymbolMapper::ManglingOptions & MO,ThreadSafeModule TSM)32097a140dSpatrick IRMaterializationUnit::IRMaterializationUnit(
33097a140dSpatrick     ExecutionSession &ES, const IRSymbolMapper::ManglingOptions &MO,
3473471bf0Spatrick     ThreadSafeModule TSM)
35*d415bd75Srobert     : MaterializationUnit(Interface()), TSM(std::move(TSM)) {
3609467b48Spatrick 
3709467b48Spatrick   assert(this->TSM && "Module must not be null");
3809467b48Spatrick 
3909467b48Spatrick   MangleAndInterner Mangle(ES, this->TSM.getModuleUnlocked()->getDataLayout());
4009467b48Spatrick   this->TSM.withModuleDo([&](Module &M) {
4109467b48Spatrick     for (auto &G : M.global_values()) {
4209467b48Spatrick       // Skip globals that don't generate symbols.
43097a140dSpatrick 
4409467b48Spatrick       if (!G.hasName() || G.isDeclaration() || G.hasLocalLinkage() ||
4509467b48Spatrick           G.hasAvailableExternallyLinkage() || G.hasAppendingLinkage())
4609467b48Spatrick         continue;
4709467b48Spatrick 
4809467b48Spatrick       // thread locals generate different symbols depending on whether or not
4909467b48Spatrick       // emulated TLS is enabled.
5009467b48Spatrick       if (G.isThreadLocal() && MO.EmulatedTLS) {
5109467b48Spatrick         auto &GV = cast<GlobalVariable>(G);
5209467b48Spatrick 
5309467b48Spatrick         auto Flags = JITSymbolFlags::fromGlobalValue(GV);
5409467b48Spatrick 
5509467b48Spatrick         auto EmuTLSV = Mangle(("__emutls_v." + GV.getName()).str());
5609467b48Spatrick         SymbolFlags[EmuTLSV] = Flags;
5709467b48Spatrick         SymbolToDefinition[EmuTLSV] = &GV;
5809467b48Spatrick 
5909467b48Spatrick         // If this GV has a non-zero initializer we'll need to emit an
6009467b48Spatrick         // __emutls.t symbol too.
6109467b48Spatrick         if (GV.hasInitializer()) {
6209467b48Spatrick           const auto *InitVal = GV.getInitializer();
6309467b48Spatrick 
6409467b48Spatrick           // Skip zero-initializers.
6509467b48Spatrick           if (isa<ConstantAggregateZero>(InitVal))
6609467b48Spatrick             continue;
6709467b48Spatrick           const auto *InitIntValue = dyn_cast<ConstantInt>(InitVal);
6809467b48Spatrick           if (InitIntValue && InitIntValue->isZero())
6909467b48Spatrick             continue;
7009467b48Spatrick 
7109467b48Spatrick           auto EmuTLST = Mangle(("__emutls_t." + GV.getName()).str());
7209467b48Spatrick           SymbolFlags[EmuTLST] = Flags;
7309467b48Spatrick         }
7409467b48Spatrick         continue;
7509467b48Spatrick       }
7609467b48Spatrick 
7709467b48Spatrick       // Otherwise we just need a normal linker mangling.
7809467b48Spatrick       auto MangledName = Mangle(G.getName());
7909467b48Spatrick       SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G);
80*d415bd75Srobert       if (G.getComdat() &&
81*d415bd75Srobert           G.getComdat()->getSelectionKind() != Comdat::NoDeduplicate)
82*d415bd75Srobert         SymbolFlags[MangledName] |= JITSymbolFlags::Weak;
8309467b48Spatrick       SymbolToDefinition[MangledName] = &G;
8409467b48Spatrick     }
85097a140dSpatrick 
86097a140dSpatrick     // If we need an init symbol for this module then create one.
87*d415bd75Srobert     if (!getStaticInitGVs(M).empty()) {
88097a140dSpatrick       size_t Counter = 0;
89097a140dSpatrick 
9073471bf0Spatrick       do {
91097a140dSpatrick         std::string InitSymbolName;
92097a140dSpatrick         raw_string_ostream(InitSymbolName)
93097a140dSpatrick             << "$." << M.getModuleIdentifier() << ".__inits." << Counter++;
94097a140dSpatrick         InitSymbol = ES.intern(InitSymbolName);
9573471bf0Spatrick       } while (SymbolFlags.count(InitSymbol));
9673471bf0Spatrick 
9773471bf0Spatrick       SymbolFlags[InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
98097a140dSpatrick     }
9909467b48Spatrick   });
10009467b48Spatrick }
10109467b48Spatrick 
IRMaterializationUnit(ThreadSafeModule TSM,Interface I,SymbolNameToDefinitionMap SymbolToDefinition)10209467b48Spatrick IRMaterializationUnit::IRMaterializationUnit(
103*d415bd75Srobert     ThreadSafeModule TSM, Interface I,
104*d415bd75Srobert     SymbolNameToDefinitionMap SymbolToDefinition)
105*d415bd75Srobert     : MaterializationUnit(std::move(I)), TSM(std::move(TSM)),
106*d415bd75Srobert       SymbolToDefinition(std::move(SymbolToDefinition)) {}
10709467b48Spatrick 
getName() const10809467b48Spatrick StringRef IRMaterializationUnit::getName() const {
10909467b48Spatrick   if (TSM)
11009467b48Spatrick     return TSM.withModuleDo(
11109467b48Spatrick         [](const Module &M) -> StringRef { return M.getModuleIdentifier(); });
11209467b48Spatrick   return "<null module>";
11309467b48Spatrick }
11409467b48Spatrick 
discard(const JITDylib & JD,const SymbolStringPtr & Name)11509467b48Spatrick void IRMaterializationUnit::discard(const JITDylib &JD,
11609467b48Spatrick                                     const SymbolStringPtr &Name) {
11709467b48Spatrick   LLVM_DEBUG(JD.getExecutionSession().runSessionLocked([&]() {
11809467b48Spatrick     dbgs() << "In " << JD.getName() << " discarding " << *Name << " from MU@"
11909467b48Spatrick            << this << " (" << getName() << ")\n";
12009467b48Spatrick   }););
12109467b48Spatrick 
12209467b48Spatrick   auto I = SymbolToDefinition.find(Name);
12309467b48Spatrick   assert(I != SymbolToDefinition.end() &&
12409467b48Spatrick          "Symbol not provided by this MU, or previously discarded");
12509467b48Spatrick   assert(!I->second->isDeclaration() &&
12609467b48Spatrick          "Discard should only apply to definitions");
12709467b48Spatrick   I->second->setLinkage(GlobalValue::AvailableExternallyLinkage);
128*d415bd75Srobert   // According to the IR verifier, "Declaration[s] may not be in a Comdat!"
129*d415bd75Srobert   // Remove it, if this is a GlobalObject.
130*d415bd75Srobert   if (auto *GO = dyn_cast<GlobalObject>(I->second))
131*d415bd75Srobert     GO->setComdat(nullptr);
13209467b48Spatrick   SymbolToDefinition.erase(I);
13309467b48Spatrick }
13409467b48Spatrick 
BasicIRLayerMaterializationUnit(IRLayer & L,const IRSymbolMapper::ManglingOptions & MO,ThreadSafeModule TSM)13509467b48Spatrick BasicIRLayerMaterializationUnit::BasicIRLayerMaterializationUnit(
13673471bf0Spatrick     IRLayer &L, const IRSymbolMapper::ManglingOptions &MO, ThreadSafeModule TSM)
13773471bf0Spatrick     : IRMaterializationUnit(L.getExecutionSession(), MO, std::move(TSM)), L(L) {
13873471bf0Spatrick }
13909467b48Spatrick 
materialize(std::unique_ptr<MaterializationResponsibility> R)14009467b48Spatrick void BasicIRLayerMaterializationUnit::materialize(
14173471bf0Spatrick     std::unique_ptr<MaterializationResponsibility> R) {
14209467b48Spatrick 
14309467b48Spatrick   // Throw away the SymbolToDefinition map: it's not usable after we hand
14409467b48Spatrick   // off the module.
14509467b48Spatrick   SymbolToDefinition.clear();
14609467b48Spatrick 
14709467b48Spatrick   // If cloneToNewContextOnEmit is set, clone the module now.
14809467b48Spatrick   if (L.getCloneToNewContextOnEmit())
14909467b48Spatrick     TSM = cloneToNewContext(TSM);
15009467b48Spatrick 
15109467b48Spatrick #ifndef NDEBUG
15273471bf0Spatrick   auto &ES = R->getTargetJITDylib().getExecutionSession();
15373471bf0Spatrick   auto &N = R->getTargetJITDylib().getName();
15409467b48Spatrick #endif // NDEBUG
15509467b48Spatrick 
15609467b48Spatrick   LLVM_DEBUG(ES.runSessionLocked(
15709467b48Spatrick       [&]() { dbgs() << "Emitting, for " << N << ", " << *this << "\n"; }););
15809467b48Spatrick   L.emit(std::move(R), std::move(TSM));
15909467b48Spatrick   LLVM_DEBUG(ES.runSessionLocked([&]() {
16009467b48Spatrick     dbgs() << "Finished emitting, for " << N << ", " << *this << "\n";
16109467b48Spatrick   }););
16209467b48Spatrick }
16309467b48Spatrick 
16473471bf0Spatrick char ObjectLayer::ID;
16573471bf0Spatrick 
ObjectLayer(ExecutionSession & ES)16609467b48Spatrick ObjectLayer::ObjectLayer(ExecutionSession &ES) : ES(ES) {}
16709467b48Spatrick 
168*d415bd75Srobert ObjectLayer::~ObjectLayer() = default;
169*d415bd75Srobert 
add(ResourceTrackerSP RT,std::unique_ptr<MemoryBuffer> O,MaterializationUnit::Interface I)170*d415bd75Srobert Error ObjectLayer::add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O,
171*d415bd75Srobert                        MaterializationUnit::Interface I) {
172*d415bd75Srobert   assert(RT && "RT can not be null");
173*d415bd75Srobert   auto &JD = RT->getJITDylib();
174*d415bd75Srobert   return JD.define(std::make_unique<BasicObjectLayerMaterializationUnit>(
175*d415bd75Srobert                        *this, std::move(O), std::move(I)),
176*d415bd75Srobert                    std::move(RT));
177*d415bd75Srobert }
17809467b48Spatrick 
add(ResourceTrackerSP RT,std::unique_ptr<MemoryBuffer> O)17973471bf0Spatrick Error ObjectLayer::add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O) {
180*d415bd75Srobert   auto I = getObjectFileInterface(getExecutionSession(), O->getMemBufferRef());
181*d415bd75Srobert   if (!I)
182*d415bd75Srobert     return I.takeError();
183*d415bd75Srobert   return add(std::move(RT), std::move(O), std::move(*I));
184*d415bd75Srobert }
185*d415bd75Srobert 
add(JITDylib & JD,std::unique_ptr<MemoryBuffer> O)186*d415bd75Srobert Error ObjectLayer::add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O) {
187*d415bd75Srobert   auto I = getObjectFileInterface(getExecutionSession(), O->getMemBufferRef());
188*d415bd75Srobert   if (!I)
189*d415bd75Srobert     return I.takeError();
190*d415bd75Srobert   return add(JD, std::move(O), std::move(*I));
19109467b48Spatrick }
19209467b48Spatrick 
19309467b48Spatrick Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>>
Create(ObjectLayer & L,std::unique_ptr<MemoryBuffer> O)19473471bf0Spatrick BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L,
19509467b48Spatrick                                             std::unique_ptr<MemoryBuffer> O) {
19609467b48Spatrick 
197*d415bd75Srobert   auto ObjInterface =
198*d415bd75Srobert       getObjectFileInterface(L.getExecutionSession(), O->getMemBufferRef());
199097a140dSpatrick 
200*d415bd75Srobert   if (!ObjInterface)
201*d415bd75Srobert     return ObjInterface.takeError();
20209467b48Spatrick 
20309467b48Spatrick   return std::unique_ptr<BasicObjectLayerMaterializationUnit>(
204*d415bd75Srobert       new BasicObjectLayerMaterializationUnit(L, std::move(O),
205*d415bd75Srobert                                               std::move(*ObjInterface)));
20609467b48Spatrick }
20709467b48Spatrick 
BasicObjectLayerMaterializationUnit(ObjectLayer & L,std::unique_ptr<MemoryBuffer> O,Interface I)20809467b48Spatrick BasicObjectLayerMaterializationUnit::BasicObjectLayerMaterializationUnit(
209*d415bd75Srobert     ObjectLayer &L, std::unique_ptr<MemoryBuffer> O, Interface I)
210*d415bd75Srobert     : MaterializationUnit(std::move(I)), L(L), O(std::move(O)) {}
21109467b48Spatrick 
getName() const21209467b48Spatrick StringRef BasicObjectLayerMaterializationUnit::getName() const {
21309467b48Spatrick   if (O)
21409467b48Spatrick     return O->getBufferIdentifier();
21509467b48Spatrick   return "<null object>";
21609467b48Spatrick }
21709467b48Spatrick 
materialize(std::unique_ptr<MaterializationResponsibility> R)21809467b48Spatrick void BasicObjectLayerMaterializationUnit::materialize(
21973471bf0Spatrick     std::unique_ptr<MaterializationResponsibility> R) {
22009467b48Spatrick   L.emit(std::move(R), std::move(O));
22109467b48Spatrick }
22209467b48Spatrick 
discard(const JITDylib & JD,const SymbolStringPtr & Name)22309467b48Spatrick void BasicObjectLayerMaterializationUnit::discard(const JITDylib &JD,
22409467b48Spatrick                                                   const SymbolStringPtr &Name) {
225097a140dSpatrick   // This is a no-op for object files: Having removed 'Name' from SymbolFlags
226097a140dSpatrick   // the symbol will be dead-stripped by the JIT linker.
22709467b48Spatrick }
22809467b48Spatrick 
22909467b48Spatrick } // End namespace orc.
23009467b48Spatrick } // End namespace llvm.
231