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