blob: f2975e29fcd6fae3da7bd5ef413d161327753e39 [file] [log] [blame]
Andrew Walbran3d2c1972020-04-07 12:24:26 +01001//===-- ObjectLinkingLayer.h - JITLink-based jit linking layer --*- 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// Contains the definition for an JITLink-based, in-process object linking
10// layer.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
15#define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
16
17#include "llvm/ADT/STLExtras.h"
18#include "llvm/ADT/StringMap.h"
19#include "llvm/ADT/StringRef.h"
20#include "llvm/ExecutionEngine/JITLink/JITLink.h"
21#include "llvm/ExecutionEngine/JITSymbol.h"
22#include "llvm/ExecutionEngine/Orc/Core.h"
23#include "llvm/ExecutionEngine/Orc/Layer.h"
24#include "llvm/Support/Error.h"
25#include <algorithm>
26#include <cassert>
27#include <functional>
28#include <list>
29#include <memory>
30#include <string>
31#include <utility>
32#include <vector>
33
34namespace llvm {
35
36namespace jitlink {
37class EHFrameRegistrar;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020038class LinkGraph;
39class Symbol;
Andrew Walbran3d2c1972020-04-07 12:24:26 +010040} // namespace jitlink
41
42namespace object {
43class ObjectFile;
44} // namespace object
45
46namespace orc {
47
48class ObjectLinkingLayerJITLinkContext;
49
50/// An ObjectLayer implementation built on JITLink.
51///
52/// Clients can use this class to add relocatable object files to an
53/// ExecutionSession, and it typically serves as the base layer (underneath
54/// a compiling layer like IRCompileLayer) for the rest of the JIT.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020055class ObjectLinkingLayer : public ObjectLayer, private ResourceManager {
Andrew Walbran3d2c1972020-04-07 12:24:26 +010056 friend class ObjectLinkingLayerJITLinkContext;
57
58public:
59 /// Plugin instances can be added to the ObjectLinkingLayer to receive
60 /// callbacks when code is loaded or emitted, and when JITLink is being
61 /// configured.
62 class Plugin {
63 public:
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020064 using JITLinkSymbolVector = std::vector<const jitlink::Symbol *>;
65 using LocalDependenciesMap = DenseMap<SymbolStringPtr, JITLinkSymbolVector>;
66
Andrew Walbran3d2c1972020-04-07 12:24:26 +010067 virtual ~Plugin();
68 virtual void modifyPassConfig(MaterializationResponsibility &MR,
69 const Triple &TT,
70 jitlink::PassConfiguration &Config) {}
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020071
Andrew Walbran3d2c1972020-04-07 12:24:26 +010072 virtual void notifyLoaded(MaterializationResponsibility &MR) {}
73 virtual Error notifyEmitted(MaterializationResponsibility &MR) {
74 return Error::success();
75 }
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020076 virtual Error notifyFailed(MaterializationResponsibility &MR) = 0;
77 virtual Error notifyRemovingResources(ResourceKey K) = 0;
78 virtual void notifyTransferringResources(ResourceKey DstKey,
79 ResourceKey SrcKey) = 0;
80
81 /// Return any dependencies that synthetic symbols (e.g. init symbols)
82 /// have on locally scoped jitlink::Symbols. This is used by the
83 /// ObjectLinkingLayer to update the dependencies for the synthetic
84 /// symbols.
85 virtual LocalDependenciesMap
86 getSyntheticSymbolLocalDependencies(MaterializationResponsibility &MR) {
87 return LocalDependenciesMap();
Andrew Walbran3d2c1972020-04-07 12:24:26 +010088 }
Andrew Walbran3d2c1972020-04-07 12:24:26 +010089 };
90
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020091 using ReturnObjectBufferFunction =
92 std::function<void(std::unique_ptr<MemoryBuffer>)>;
93
94 /// Construct an ObjectLinkingLayer.
Andrew Walbran3d2c1972020-04-07 12:24:26 +010095 ObjectLinkingLayer(ExecutionSession &ES,
96 jitlink::JITLinkMemoryManager &MemMgr);
97
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020098 /// Construct an ObjectLinkingLayer. Takes ownership of the given
99 /// JITLinkMemoryManager. This method is a temporary hack to simplify
100 /// co-existence with RTDyldObjectLinkingLayer (which also owns its
101 /// allocators).
102 ObjectLinkingLayer(ExecutionSession &ES,
103 std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr);
104
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100105 /// Destruct an ObjectLinkingLayer.
106 ~ObjectLinkingLayer();
107
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200108 /// Set an object buffer return function. By default object buffers are
109 /// deleted once the JIT has linked them. If a return function is set then
110 /// it will be called to transfer ownership of the buffer instead.
111 void setReturnObjectBuffer(ReturnObjectBufferFunction ReturnObjectBuffer) {
112 this->ReturnObjectBuffer = std::move(ReturnObjectBuffer);
113 }
114
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100115 /// Add a pass-config modifier.
116 ObjectLinkingLayer &addPlugin(std::unique_ptr<Plugin> P) {
117 std::lock_guard<std::mutex> Lock(LayerMutex);
118 Plugins.push_back(std::move(P));
119 return *this;
120 }
121
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200122 /// Emit an object file.
123 void emit(std::unique_ptr<MaterializationResponsibility> R,
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100124 std::unique_ptr<MemoryBuffer> O) override;
125
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200126 /// Emit a LinkGraph.
127 void emit(std::unique_ptr<MaterializationResponsibility> R,
128 std::unique_ptr<jitlink::LinkGraph> G);
129
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100130 /// Instructs this ObjectLinkingLayer instance to override the symbol flags
131 /// found in the AtomGraph with the flags supplied by the
132 /// MaterializationResponsibility instance. This is a workaround to support
133 /// symbol visibility in COFF, which does not use the libObject's
134 /// SF_Exported flag. Use only when generating / adding COFF object files.
135 ///
136 /// FIXME: We should be able to remove this if/when COFF properly tracks
137 /// exported symbols.
138 ObjectLinkingLayer &
139 setOverrideObjectFlagsWithResponsibilityFlags(bool OverrideObjectFlags) {
140 this->OverrideObjectFlags = OverrideObjectFlags;
141 return *this;
142 }
143
144 /// If set, this ObjectLinkingLayer instance will claim responsibility
145 /// for any symbols provided by a given object file that were not already in
146 /// the MaterializationResponsibility instance. Setting this flag allows
147 /// higher-level program representations (e.g. LLVM IR) to be added based on
148 /// only a subset of the symbols they provide, without having to write
149 /// intervening layers to scan and add the additional symbols. This trades
150 /// diagnostic quality for convenience however: If all symbols are enumerated
151 /// up-front then clashes can be detected and reported early (and usually
152 /// deterministically). If this option is set, clashes for the additional
153 /// symbols may not be detected until late, and detection may depend on
154 /// the flow of control through JIT'd code. Use with care.
155 ObjectLinkingLayer &
156 setAutoClaimResponsibilityForObjectSymbols(bool AutoClaimObjectSymbols) {
157 this->AutoClaimObjectSymbols = AutoClaimObjectSymbols;
158 return *this;
159 }
160
161private:
162 using AllocPtr = std::unique_ptr<jitlink::JITLinkMemoryManager::Allocation>;
163
164 void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
165 jitlink::PassConfiguration &PassConfig);
166 void notifyLoaded(MaterializationResponsibility &MR);
167 Error notifyEmitted(MaterializationResponsibility &MR, AllocPtr Alloc);
168
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200169 Error handleRemoveResources(ResourceKey K) override;
170 void handleTransferResources(ResourceKey DstKey, ResourceKey SrcKey) override;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100171
172 mutable std::mutex LayerMutex;
173 jitlink::JITLinkMemoryManager &MemMgr;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200174 std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgrOwnership;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100175 bool OverrideObjectFlags = false;
176 bool AutoClaimObjectSymbols = false;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200177 ReturnObjectBufferFunction ReturnObjectBuffer;
178 DenseMap<ResourceKey, std::vector<AllocPtr>> Allocs;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100179 std::vector<std::unique_ptr<Plugin>> Plugins;
180};
181
182class EHFrameRegistrationPlugin : public ObjectLinkingLayer::Plugin {
183public:
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200184 EHFrameRegistrationPlugin(
185 ExecutionSession &ES,
186 std::unique_ptr<jitlink::EHFrameRegistrar> Registrar);
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100187 void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
188 jitlink::PassConfiguration &PassConfig) override;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200189 Error notifyEmitted(MaterializationResponsibility &MR) override;
190 Error notifyFailed(MaterializationResponsibility &MR) override;
191 Error notifyRemovingResources(ResourceKey K) override;
192 void notifyTransferringResources(ResourceKey DstKey,
193 ResourceKey SrcKey) override;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100194
195private:
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200196
197 struct EHFrameRange {
198 JITTargetAddress Addr = 0;
199 size_t Size;
200 };
201
202 std::mutex EHFramePluginMutex;
203 ExecutionSession &ES;
204 std::unique_ptr<jitlink::EHFrameRegistrar> Registrar;
205 DenseMap<MaterializationResponsibility *, EHFrameRange> InProcessLinks;
206 DenseMap<ResourceKey, std::vector<EHFrameRange>> EHFrameRanges;
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100207};
208
209} // end namespace orc
210} // end namespace llvm
211
212#endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H