xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/Layer.cpp (revision 82d4dc0621c92e3c05a86013eec35afbdec057a5)
1  //===-------------------- Layer.cpp - Layer interfaces --------------------===//
2  //
3  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4  // See https://llvm.org/LICENSE.txt for license information.
5  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6  //
7  //===----------------------------------------------------------------------===//
8  
9  #include "llvm/ExecutionEngine/Orc/Layer.h"
10  
11  #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
12  #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
13  #include "llvm/IR/Constants.h"
14  #include "llvm/Object/MachO.h"
15  #include "llvm/Object/ObjectFile.h"
16  #include "llvm/Support/Debug.h"
17  
18  #define DEBUG_TYPE "orc"
19  
20  namespace llvm {
21  namespace orc {
22  
23  IRLayer::~IRLayer() {}
24  
25  Error IRLayer::add(ResourceTrackerSP RT, ThreadSafeModule TSM) {
26    assert(RT && "RT can not be null");
27    auto &JD = RT->getJITDylib();
28    return JD.define(std::make_unique<BasicIRLayerMaterializationUnit>(
29                         *this, *getManglingOptions(), std::move(TSM)),
30                     std::move(RT));
31  }
32  
33  IRMaterializationUnit::IRMaterializationUnit(
34      ExecutionSession &ES, const IRSymbolMapper::ManglingOptions &MO,
35      ThreadSafeModule TSM)
36      : MaterializationUnit(SymbolFlagsMap(), nullptr), TSM(std::move(TSM)) {
37  
38    assert(this->TSM && "Module must not be null");
39  
40    MangleAndInterner Mangle(ES, this->TSM.getModuleUnlocked()->getDataLayout());
41    this->TSM.withModuleDo([&](Module &M) {
42      for (auto &G : M.global_values()) {
43        // Skip globals that don't generate symbols.
44  
45        if (!G.hasName() || G.isDeclaration() || G.hasLocalLinkage() ||
46            G.hasAvailableExternallyLinkage() || G.hasAppendingLinkage())
47          continue;
48  
49        // thread locals generate different symbols depending on whether or not
50        // emulated TLS is enabled.
51        if (G.isThreadLocal() && MO.EmulatedTLS) {
52          auto &GV = cast<GlobalVariable>(G);
53  
54          auto Flags = JITSymbolFlags::fromGlobalValue(GV);
55  
56          auto EmuTLSV = Mangle(("__emutls_v." + GV.getName()).str());
57          SymbolFlags[EmuTLSV] = Flags;
58          SymbolToDefinition[EmuTLSV] = &GV;
59  
60          // If this GV has a non-zero initializer we'll need to emit an
61          // __emutls.t symbol too.
62          if (GV.hasInitializer()) {
63            const auto *InitVal = GV.getInitializer();
64  
65            // Skip zero-initializers.
66            if (isa<ConstantAggregateZero>(InitVal))
67              continue;
68            const auto *InitIntValue = dyn_cast<ConstantInt>(InitVal);
69            if (InitIntValue && InitIntValue->isZero())
70              continue;
71  
72            auto EmuTLST = Mangle(("__emutls_t." + GV.getName()).str());
73            SymbolFlags[EmuTLST] = Flags;
74          }
75          continue;
76        }
77  
78        // Otherwise we just need a normal linker mangling.
79        auto MangledName = Mangle(G.getName());
80        SymbolFlags[MangledName] = JITSymbolFlags::fromGlobalValue(G);
81        SymbolToDefinition[MangledName] = &G;
82      }
83  
84      // If we need an init symbol for this module then create one.
85      if (!llvm::empty(getStaticInitGVs(M))) {
86        size_t Counter = 0;
87  
88        do {
89          std::string InitSymbolName;
90          raw_string_ostream(InitSymbolName)
91              << "$." << M.getModuleIdentifier() << ".__inits." << Counter++;
92          InitSymbol = ES.intern(InitSymbolName);
93        } while (SymbolFlags.count(InitSymbol));
94  
95        SymbolFlags[InitSymbol] = JITSymbolFlags::MaterializationSideEffectsOnly;
96      }
97    });
98  }
99  
100  IRMaterializationUnit::IRMaterializationUnit(
101      ThreadSafeModule TSM, SymbolFlagsMap SymbolFlags,
102      SymbolStringPtr InitSymbol, SymbolNameToDefinitionMap SymbolToDefinition)
103      : MaterializationUnit(std::move(SymbolFlags), std::move(InitSymbol)),
104        TSM(std::move(TSM)), SymbolToDefinition(std::move(SymbolToDefinition)) {}
105  
106  StringRef IRMaterializationUnit::getName() const {
107    if (TSM)
108      return TSM.withModuleDo(
109          [](const Module &M) -> StringRef { return M.getModuleIdentifier(); });
110    return "<null module>";
111  }
112  
113  void IRMaterializationUnit::discard(const JITDylib &JD,
114                                      const SymbolStringPtr &Name) {
115    LLVM_DEBUG(JD.getExecutionSession().runSessionLocked([&]() {
116      dbgs() << "In " << JD.getName() << " discarding " << *Name << " from MU@"
117             << this << " (" << getName() << ")\n";
118    }););
119  
120    auto I = SymbolToDefinition.find(Name);
121    assert(I != SymbolToDefinition.end() &&
122           "Symbol not provided by this MU, or previously discarded");
123    assert(!I->second->isDeclaration() &&
124           "Discard should only apply to definitions");
125    I->second->setLinkage(GlobalValue::AvailableExternallyLinkage);
126    SymbolToDefinition.erase(I);
127  }
128  
129  BasicIRLayerMaterializationUnit::BasicIRLayerMaterializationUnit(
130      IRLayer &L, const IRSymbolMapper::ManglingOptions &MO, ThreadSafeModule TSM)
131      : IRMaterializationUnit(L.getExecutionSession(), MO, std::move(TSM)), L(L) {
132  }
133  
134  void BasicIRLayerMaterializationUnit::materialize(
135      std::unique_ptr<MaterializationResponsibility> R) {
136  
137    // Throw away the SymbolToDefinition map: it's not usable after we hand
138    // off the module.
139    SymbolToDefinition.clear();
140  
141    // If cloneToNewContextOnEmit is set, clone the module now.
142    if (L.getCloneToNewContextOnEmit())
143      TSM = cloneToNewContext(TSM);
144  
145  #ifndef NDEBUG
146    auto &ES = R->getTargetJITDylib().getExecutionSession();
147    auto &N = R->getTargetJITDylib().getName();
148  #endif // NDEBUG
149  
150    LLVM_DEBUG(ES.runSessionLocked(
151        [&]() { dbgs() << "Emitting, for " << N << ", " << *this << "\n"; }););
152    L.emit(std::move(R), std::move(TSM));
153    LLVM_DEBUG(ES.runSessionLocked([&]() {
154      dbgs() << "Finished emitting, for " << N << ", " << *this << "\n";
155    }););
156  }
157  
158  char ObjectLayer::ID;
159  
160  ObjectLayer::ObjectLayer(ExecutionSession &ES) : ES(ES) {}
161  
162  ObjectLayer::~ObjectLayer() {}
163  
164  Error ObjectLayer::add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O) {
165    assert(RT && "RT can not be null");
166    auto ObjMU = BasicObjectLayerMaterializationUnit::Create(*this, std::move(O));
167    if (!ObjMU)
168      return ObjMU.takeError();
169    auto &JD = RT->getJITDylib();
170    return JD.define(std::move(*ObjMU), std::move(RT));
171  }
172  
173  Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>>
174  BasicObjectLayerMaterializationUnit::Create(ObjectLayer &L,
175                                              std::unique_ptr<MemoryBuffer> O) {
176    auto ObjSymInfo =
177        getObjectSymbolInfo(L.getExecutionSession(), O->getMemBufferRef());
178  
179    if (!ObjSymInfo)
180      return ObjSymInfo.takeError();
181  
182    auto &SymbolFlags = ObjSymInfo->first;
183    auto &InitSymbol = ObjSymInfo->second;
184  
185    return std::unique_ptr<BasicObjectLayerMaterializationUnit>(
186        new BasicObjectLayerMaterializationUnit(
187            L, std::move(O), std::move(SymbolFlags), std::move(InitSymbol)));
188  }
189  
190  BasicObjectLayerMaterializationUnit::BasicObjectLayerMaterializationUnit(
191      ObjectLayer &L, std::unique_ptr<MemoryBuffer> O, SymbolFlagsMap SymbolFlags,
192      SymbolStringPtr InitSymbol)
193      : MaterializationUnit(std::move(SymbolFlags), std::move(InitSymbol)), L(L),
194        O(std::move(O)) {}
195  
196  StringRef BasicObjectLayerMaterializationUnit::getName() const {
197    if (O)
198      return O->getBufferIdentifier();
199    return "<null object>";
200  }
201  
202  void BasicObjectLayerMaterializationUnit::materialize(
203      std::unique_ptr<MaterializationResponsibility> R) {
204    L.emit(std::move(R), std::move(O));
205  }
206  
207  void BasicObjectLayerMaterializationUnit::discard(const JITDylib &JD,
208                                                    const SymbolStringPtr &Name) {
209    // This is a no-op for object files: Having removed 'Name' from SymbolFlags
210    // the symbol will be dead-stripped by the JIT linker.
211  }
212  
213  } // End namespace orc.
214  } // End namespace llvm.
215