Home | History | Annotate | Line # | Download | only in Orc
      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