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