1 //===---------------- Layer.h -- Layer interfaces --------------*- C++ -*-===//
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 // Layer interfaces.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_EXECUTIONENGINE_ORC_LAYER_H
14 #define LLVM_EXECUTIONENGINE_ORC_LAYER_H
15 
16 #include "llvm/ExecutionEngine/Orc/Core.h"
17 #include "llvm/ExecutionEngine/Orc/Mangling.h"
18 #include "llvm/ExecutionEngine/Orc/ThreadSafeModule.h"
19 #include "llvm/IR/Module.h"
20 #include "llvm/Support/MemoryBuffer.h"
21 
22 namespace llvm {
23 namespace orc {
24 
25 /// IRMaterializationUnit is a convenient base class for MaterializationUnits
26 /// wrapping LLVM IR. Represents materialization responsibility for all symbols
27 /// in the given module. If symbols are overridden by other definitions, then
28 /// their linkage is changed to available-externally.
29 class IRMaterializationUnit : public MaterializationUnit {
30 public:
31   using SymbolNameToDefinitionMap = std::map<SymbolStringPtr, GlobalValue *>;
32 
33   /// Create an IRMaterializationLayer. Scans the module to build the
34   /// SymbolFlags and SymbolToDefinition maps.
35   IRMaterializationUnit(ExecutionSession &ES,
36                         const IRSymbolMapper::ManglingOptions &MO,
37                         ThreadSafeModule TSM, VModuleKey K);
38 
39   /// Create an IRMaterializationLayer from a module, and pre-existing
40   /// SymbolFlags and SymbolToDefinition maps. The maps must provide
41   /// entries for each definition in M.
42   /// This constructor is useful for delegating work from one
43   /// IRMaterializationUnit to another.
44   IRMaterializationUnit(ThreadSafeModule TSM, VModuleKey K,
45                         SymbolFlagsMap SymbolFlags, SymbolStringPtr InitSymbol,
46                         SymbolNameToDefinitionMap SymbolToDefinition);
47 
48   /// Return the ModuleIdentifier as the name for this MaterializationUnit.
49   StringRef getName() const override;
50 
51   /// Return a reference to the contained ThreadSafeModule.
52   const ThreadSafeModule &getModule() const { return TSM; }
53 
54 protected:
55   ThreadSafeModule TSM;
56   SymbolNameToDefinitionMap SymbolToDefinition;
57 
58 private:
59   static SymbolStringPtr getInitSymbol(ExecutionSession &ES,
60                                        const ThreadSafeModule &TSM);
61 
62   void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
63 };
64 
65 /// Interface for layers that accept LLVM IR.
66 class IRLayer {
67 public:
68   IRLayer(ExecutionSession &ES, const IRSymbolMapper::ManglingOptions *&MO)
69       : ES(ES), MO(MO) {}
70 
71   virtual ~IRLayer();
72 
73   /// Returns the ExecutionSession for this layer.
74   ExecutionSession &getExecutionSession() { return ES; }
75 
76   /// Get the mangling options for this layer.
77   const IRSymbolMapper::ManglingOptions *&getManglingOptions() const {
78     return MO;
79   }
80 
81   /// Sets the CloneToNewContextOnEmit flag (false by default).
82   ///
83   /// When set, IR modules added to this layer will be cloned on to a new
84   /// context before emit is called. This can be used by clients who want
85   /// to load all IR using one LLVMContext (to save memory via type and
86   /// constant uniquing), but want to move Modules to fresh contexts before
87   /// compiling them to enable concurrent compilation.
88   /// Single threaded clients, or clients who load every module on a new
89   /// context, need not set this.
90   void setCloneToNewContextOnEmit(bool CloneToNewContextOnEmit) {
91     this->CloneToNewContextOnEmit = CloneToNewContextOnEmit;
92   }
93 
94   /// Returns the current value of the CloneToNewContextOnEmit flag.
95   bool getCloneToNewContextOnEmit() const { return CloneToNewContextOnEmit; }
96 
97   /// Adds a MaterializationUnit representing the given IR to the given
98   /// JITDylib.
99   virtual Error add(JITDylib &JD, ThreadSafeModule TSM,
100                     VModuleKey K = VModuleKey());
101 
102   /// Emit should materialize the given IR.
103   virtual void emit(MaterializationResponsibility R, ThreadSafeModule TSM) = 0;
104 
105 private:
106   bool CloneToNewContextOnEmit = false;
107   ExecutionSession &ES;
108   const IRSymbolMapper::ManglingOptions *&MO;
109 };
110 
111 /// MaterializationUnit that materializes modules by calling the 'emit' method
112 /// on the given IRLayer.
113 class BasicIRLayerMaterializationUnit : public IRMaterializationUnit {
114 public:
115   BasicIRLayerMaterializationUnit(IRLayer &L,
116                                   const IRSymbolMapper::ManglingOptions &MO,
117                                   ThreadSafeModule TSM, VModuleKey K);
118 
119 private:
120 
121   void materialize(MaterializationResponsibility R) override;
122 
123   IRLayer &L;
124   VModuleKey K;
125 };
126 
127 /// Interface for Layers that accept object files.
128 class ObjectLayer {
129 public:
130   ObjectLayer(ExecutionSession &ES);
131   virtual ~ObjectLayer();
132 
133   /// Returns the execution session for this layer.
134   ExecutionSession &getExecutionSession() { return ES; }
135 
136   /// Adds a MaterializationUnit representing the given IR to the given
137   /// JITDylib.
138   virtual Error add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O,
139                     VModuleKey K = VModuleKey());
140 
141   /// Emit should materialize the given IR.
142   virtual void emit(MaterializationResponsibility R,
143                     std::unique_ptr<MemoryBuffer> O) = 0;
144 
145 private:
146   ExecutionSession &ES;
147 };
148 
149 /// Materializes the given object file (represented by a MemoryBuffer
150 /// instance) by calling 'emit' on the given ObjectLayer.
151 class BasicObjectLayerMaterializationUnit : public MaterializationUnit {
152 public:
153   static Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>>
154   Create(ObjectLayer &L, VModuleKey K, std::unique_ptr<MemoryBuffer> O);
155 
156   BasicObjectLayerMaterializationUnit(ObjectLayer &L, VModuleKey K,
157                                       std::unique_ptr<MemoryBuffer> O,
158                                       SymbolFlagsMap SymbolFlags,
159                                       SymbolStringPtr InitSymbol);
160 
161   /// Return the buffer's identifier as the name for this MaterializationUnit.
162   StringRef getName() const override;
163 
164 private:
165 
166   void materialize(MaterializationResponsibility R) override;
167   void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
168 
169   ObjectLayer &L;
170   std::unique_ptr<MemoryBuffer> O;
171 };
172 
173 } // End namespace orc
174 } // End namespace llvm
175 
176 #endif // LLVM_EXECUTIONENGINE_ORC_LAYER_H
177