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