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, SymbolFlagsMap SymbolFlags,
47                         SymbolStringPtr InitSymbol,
48                         SymbolNameToDefinitionMap SymbolToDefinition);
49 
50   /// Return the ModuleIdentifier as the name for this MaterializationUnit.
51   StringRef getName() const override;
52 
53   /// Return a reference to the contained ThreadSafeModule.
54   const ThreadSafeModule &getModule() const { return TSM; }
55 
56 protected:
57   ThreadSafeModule TSM;
58   SymbolNameToDefinitionMap SymbolToDefinition;
59 
60 private:
61   static SymbolStringPtr getInitSymbol(ExecutionSession &ES,
62                                        const ThreadSafeModule &TSM);
63 
64   void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
65 };
66 
67 /// Interface for layers that accept LLVM IR.
68 class IRLayer {
69 public:
70   IRLayer(ExecutionSession &ES, const IRSymbolMapper::ManglingOptions *&MO)
71       : ES(ES), MO(MO) {}
72 
73   virtual ~IRLayer();
74 
75   /// Returns the ExecutionSession for this layer.
76   ExecutionSession &getExecutionSession() { return ES; }
77 
78   /// Get the mangling options for this layer.
79   const IRSymbolMapper::ManglingOptions *&getManglingOptions() const {
80     return MO;
81   }
82 
83   /// Sets the CloneToNewContextOnEmit flag (false by default).
84   ///
85   /// When set, IR modules added to this layer will be cloned on to a new
86   /// context before emit is called. This can be used by clients who want
87   /// to load all IR using one LLVMContext (to save memory via type and
88   /// constant uniquing), but want to move Modules to fresh contexts before
89   /// compiling them to enable concurrent compilation.
90   /// Single threaded clients, or clients who load every module on a new
91   /// context, need not set this.
92   void setCloneToNewContextOnEmit(bool CloneToNewContextOnEmit) {
93     this->CloneToNewContextOnEmit = CloneToNewContextOnEmit;
94   }
95 
96   /// Returns the current value of the CloneToNewContextOnEmit flag.
97   bool getCloneToNewContextOnEmit() const { return CloneToNewContextOnEmit; }
98 
99   /// Add a MaterializatinoUnit representing the given IR to the JITDylib
100   /// targeted by the given tracker.
101   virtual Error add(ResourceTrackerSP RT, ThreadSafeModule TSM);
102 
103   /// Adds a MaterializationUnit representing the given IR to the given
104   /// JITDylib. If RT is not specif
105   Error add(JITDylib &JD, ThreadSafeModule TSM) {
106     return add(JD.getDefaultResourceTracker(), std::move(TSM));
107   }
108 
109   /// Emit should materialize the given IR.
110   virtual void emit(std::unique_ptr<MaterializationResponsibility> R,
111                     ThreadSafeModule TSM) = 0;
112 
113 private:
114   bool CloneToNewContextOnEmit = false;
115   ExecutionSession &ES;
116   const IRSymbolMapper::ManglingOptions *&MO;
117 };
118 
119 /// MaterializationUnit that materializes modules by calling the 'emit' method
120 /// on the given IRLayer.
121 class BasicIRLayerMaterializationUnit : public IRMaterializationUnit {
122 public:
123   BasicIRLayerMaterializationUnit(IRLayer &L,
124                                   const IRSymbolMapper::ManglingOptions &MO,
125                                   ThreadSafeModule TSM);
126 
127 private:
128   void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
129 
130   IRLayer &L;
131 };
132 
133 /// Interface for Layers that accept object files.
134 class ObjectLayer : public RTTIExtends<ObjectLayer, RTTIRoot> {
135 public:
136   static char ID;
137 
138   ObjectLayer(ExecutionSession &ES);
139   virtual ~ObjectLayer();
140 
141   /// Returns the execution session for this layer.
142   ExecutionSession &getExecutionSession() { return ES; }
143 
144   /// Adds a MaterializationUnit representing the given IR to the given
145   /// JITDylib.
146   virtual Error add(ResourceTrackerSP RT, std::unique_ptr<MemoryBuffer> O);
147 
148   Error add(JITDylib &JD, std::unique_ptr<MemoryBuffer> O) {
149     return add(JD.getDefaultResourceTracker(), std::move(O));
150   }
151 
152   /// Emit should materialize the given IR.
153   virtual void emit(std::unique_ptr<MaterializationResponsibility> R,
154                     std::unique_ptr<MemoryBuffer> O) = 0;
155 
156 private:
157   ExecutionSession &ES;
158 };
159 
160 /// Materializes the given object file (represented by a MemoryBuffer
161 /// instance) by calling 'emit' on the given ObjectLayer.
162 class BasicObjectLayerMaterializationUnit : public MaterializationUnit {
163 public:
164   static Expected<std::unique_ptr<BasicObjectLayerMaterializationUnit>>
165   Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> O);
166 
167   BasicObjectLayerMaterializationUnit(ObjectLayer &L,
168                                       std::unique_ptr<MemoryBuffer> O,
169                                       SymbolFlagsMap SymbolFlags,
170                                       SymbolStringPtr InitSymbol);
171 
172   /// Return the buffer's identifier as the name for this MaterializationUnit.
173   StringRef getName() const override;
174 
175 private:
176   void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
177   void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
178 
179   ObjectLayer &L;
180   std::unique_ptr<MemoryBuffer> O;
181 };
182 
183 } // End namespace orc
184 } // End namespace llvm
185 
186 #endif // LLVM_EXECUTIONENGINE_ORC_LAYER_H
187