1 //===--- LogicalDylib.h - Simulates dylib-style symbol lookup ---*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Simulates symbol resolution inside a dylib.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_EXECUTIONENGINE_ORC_LOGICALDYLIB_H
15 #define LLVM_EXECUTIONENGINE_ORC_LOGICALDYLIB_H
16 
17 #include "llvm/ExecutionEngine/Orc/JITSymbol.h"
18 #include <string>
19 #include <vector>
20 
21 namespace llvm {
22 namespace orc {
23 
24 template <typename BaseLayerT,
25           typename LogicalModuleResources,
26           typename LogicalDylibResources>
27 class LogicalDylib {
28 public:
29   typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
30 private:
31 
32   typedef std::vector<BaseLayerModuleSetHandleT> BaseLayerHandleList;
33 
34   struct LogicalModule {
35     // Make this move-only to ensure they don't get duplicated across moves of
36     // LogicalDylib or anything like that.
LogicalModuleLogicalModule37     LogicalModule(LogicalModule &&RHS)
38         : Resources(std::move(RHS.Resources)),
39           BaseLayerHandles(std::move(RHS.BaseLayerHandles)) {}
40     LogicalModule() = default;
41     LogicalModuleResources Resources;
42     BaseLayerHandleList BaseLayerHandles;
43   };
44   typedef std::vector<LogicalModule> LogicalModuleList;
45 
46 public:
47 
48   typedef typename BaseLayerHandleList::iterator BaseLayerHandleIterator;
49   typedef typename LogicalModuleList::iterator LogicalModuleHandle;
50 
LogicalDylib(BaseLayerT & BaseLayer)51   LogicalDylib(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
52 
~LogicalDylib()53   ~LogicalDylib() {
54     for (auto &LM : LogicalModules)
55       for (auto BLH : LM.BaseLayerHandles)
56         BaseLayer.removeModuleSet(BLH);
57   }
58 
59   // If possible, remove this and ~LogicalDylib once the work in the dtor is
60   // moved to members (eg: self-unregistering base layer handles).
LogicalDylib(LogicalDylib && RHS)61   LogicalDylib(LogicalDylib &&RHS)
62       : BaseLayer(std::move(RHS.BaseLayer)),
63         LogicalModules(std::move(RHS.LogicalModules)),
64         DylibResources(std::move(RHS.DylibResources)) {}
65 
createLogicalModule()66   LogicalModuleHandle createLogicalModule() {
67     LogicalModules.push_back(LogicalModule());
68     return std::prev(LogicalModules.end());
69   }
70 
addToLogicalModule(LogicalModuleHandle LMH,BaseLayerModuleSetHandleT BaseLayerHandle)71   void addToLogicalModule(LogicalModuleHandle LMH,
72                           BaseLayerModuleSetHandleT BaseLayerHandle) {
73     LMH->BaseLayerHandles.push_back(BaseLayerHandle);
74   }
75 
getLogicalModuleResources(LogicalModuleHandle LMH)76   LogicalModuleResources& getLogicalModuleResources(LogicalModuleHandle LMH) {
77     return LMH->Resources;
78   }
79 
moduleHandlesBegin(LogicalModuleHandle LMH)80   BaseLayerHandleIterator moduleHandlesBegin(LogicalModuleHandle LMH) {
81     return LMH->BaseLayerHandles.begin();
82   }
83 
moduleHandlesEnd(LogicalModuleHandle LMH)84   BaseLayerHandleIterator moduleHandlesEnd(LogicalModuleHandle LMH) {
85     return LMH->BaseLayerHandles.end();
86   }
87 
findSymbolInLogicalModule(LogicalModuleHandle LMH,const std::string & Name,bool ExportedSymbolsOnly)88   JITSymbol findSymbolInLogicalModule(LogicalModuleHandle LMH,
89                                       const std::string &Name,
90                                       bool ExportedSymbolsOnly) {
91 
92     if (auto StubSym = LMH->Resources.findSymbol(Name, ExportedSymbolsOnly))
93       return StubSym;
94 
95     for (auto BLH : LMH->BaseLayerHandles)
96       if (auto Symbol = BaseLayer.findSymbolIn(BLH, Name, ExportedSymbolsOnly))
97         return Symbol;
98     return nullptr;
99   }
100 
findSymbolInternally(LogicalModuleHandle LMH,const std::string & Name)101   JITSymbol findSymbolInternally(LogicalModuleHandle LMH,
102                                  const std::string &Name) {
103     if (auto Symbol = findSymbolInLogicalModule(LMH, Name, false))
104       return Symbol;
105 
106     for (auto LMI = LogicalModules.begin(), LME = LogicalModules.end();
107            LMI != LME; ++LMI) {
108       if (LMI != LMH)
109         if (auto Symbol = findSymbolInLogicalModule(LMI, Name, false))
110           return Symbol;
111     }
112 
113     return nullptr;
114   }
115 
findSymbol(const std::string & Name,bool ExportedSymbolsOnly)116   JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
117     for (auto LMI = LogicalModules.begin(), LME = LogicalModules.end();
118          LMI != LME; ++LMI)
119       if (auto Sym = findSymbolInLogicalModule(LMI, Name, ExportedSymbolsOnly))
120         return Sym;
121     return nullptr;
122   }
123 
getDylibResources()124   LogicalDylibResources& getDylibResources() { return DylibResources; }
125 
126 protected:
127   BaseLayerT BaseLayer;
128   LogicalModuleList LogicalModules;
129   LogicalDylibResources DylibResources;
130 };
131 
132 } // End namespace orc.
133 } // End namespace llvm.
134 
135 #endif // LLVM_EXECUTIONENGINE_ORC_LOGICALDYLIB_H
136