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