Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===------ Core.h -- Core ORC APIs (Layer, JITDylib, etc.) -----*- 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 core ORC APIs.
10
//
11
//===----------------------------------------------------------------------===//
12
 
13
#ifndef LLVM_EXECUTIONENGINE_ORC_CORE_H
14
#define LLVM_EXECUTIONENGINE_ORC_CORE_H
15
 
16
#include "llvm/ADT/BitmaskEnum.h"
17
#include "llvm/ADT/DenseSet.h"
18
#include "llvm/ADT/FunctionExtras.h"
19
#include "llvm/ADT/IntrusiveRefCntPtr.h"
20
#include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h"
21
#include "llvm/ExecutionEngine/JITSymbol.h"
22
#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
23
#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
24
#include "llvm/ExecutionEngine/Orc/TaskDispatch.h"
25
#include "llvm/Support/Debug.h"
26
#include "llvm/Support/ExtensibleRTTI.h"
27
 
28
#include <atomic>
29
#include <future>
30
#include <memory>
31
#include <vector>
32
 
33
namespace llvm {
34
namespace orc {
35
 
36
// Forward declare some classes.
37
class AsynchronousSymbolQuery;
38
class ExecutionSession;
39
class MaterializationUnit;
40
class MaterializationResponsibility;
41
class JITDylib;
42
class ResourceTracker;
43
class InProgressLookupState;
44
 
45
enum class SymbolState : uint8_t;
46
 
47
using ResourceTrackerSP = IntrusiveRefCntPtr<ResourceTracker>;
48
using JITDylibSP = IntrusiveRefCntPtr<JITDylib>;
49
 
50
using ResourceKey = uintptr_t;
51
 
52
/// API to remove / transfer ownership of JIT resources.
53
class ResourceTracker : public ThreadSafeRefCountedBase<ResourceTracker> {
54
private:
55
  friend class ExecutionSession;
56
  friend class JITDylib;
57
  friend class MaterializationResponsibility;
58
 
59
public:
60
  ResourceTracker(const ResourceTracker &) = delete;
61
  ResourceTracker &operator=(const ResourceTracker &) = delete;
62
  ResourceTracker(ResourceTracker &&) = delete;
63
  ResourceTracker &operator=(ResourceTracker &&) = delete;
64
 
65
  ~ResourceTracker();
66
 
67
  /// Return the JITDylib targeted by this tracker.
68
  JITDylib &getJITDylib() const {
69
    return *reinterpret_cast<JITDylib *>(JDAndFlag.load() &
70
                                         ~static_cast<uintptr_t>(1));
71
  }
72
 
73
  /// Runs the given callback under the session lock, passing in the associated
74
  /// ResourceKey. This is the safe way to associate resources with trackers.
75
  template <typename Func> Error withResourceKeyDo(Func &&F);
76
 
77
  /// Remove all resources associated with this key.
78
  Error remove();
79
 
80
  /// Transfer all resources associated with this key to the given
81
  /// tracker, which must target the same JITDylib as this one.
82
  void transferTo(ResourceTracker &DstRT);
83
 
84
  /// Return true if this tracker has become defunct.
85
  bool isDefunct() const { return JDAndFlag.load() & 0x1; }
86
 
87
  /// Returns the key associated with this tracker.
88
  /// This method should not be used except for debug logging: there is no
89
  /// guarantee that the returned value will remain valid.
90
  ResourceKey getKeyUnsafe() const { return reinterpret_cast<uintptr_t>(this); }
91
 
92
private:
93
  ResourceTracker(JITDylibSP JD);
94
 
95
  void makeDefunct();
96
 
97
  std::atomic_uintptr_t JDAndFlag;
98
};
99
 
100
/// Listens for ResourceTracker operations.
101
class ResourceManager {
102
public:
103
  virtual ~ResourceManager();
104
  virtual Error handleRemoveResources(JITDylib &JD, ResourceKey K) = 0;
105
  virtual void handleTransferResources(JITDylib &JD, ResourceKey DstK,
106
                                       ResourceKey SrcK) = 0;
107
};
108
 
109
/// A set of symbol names (represented by SymbolStringPtrs for
110
//         efficiency).
111
using SymbolNameSet = DenseSet<SymbolStringPtr>;
112
 
113
/// A vector of symbol names.
114
using SymbolNameVector = std::vector<SymbolStringPtr>;
115
 
116
/// A map from symbol names (as SymbolStringPtrs) to JITSymbols
117
/// (address/flags pairs).
118
using SymbolMap = DenseMap<SymbolStringPtr, JITEvaluatedSymbol>;
119
 
120
/// A map from symbol names (as SymbolStringPtrs) to JITSymbolFlags.
121
using SymbolFlagsMap = DenseMap<SymbolStringPtr, JITSymbolFlags>;
122
 
123
/// A map from JITDylibs to sets of symbols.
124
using SymbolDependenceMap = DenseMap<JITDylib *, SymbolNameSet>;
125
 
126
/// Lookup flags that apply to each dylib in the search order for a lookup.
127
///
128
/// If MatchHiddenSymbolsOnly is used (the default) for a given dylib, then
129
/// only symbols in that Dylib's interface will be searched. If
130
/// MatchHiddenSymbols is used then symbols with hidden visibility will match
131
/// as well.
132
enum class JITDylibLookupFlags { MatchExportedSymbolsOnly, MatchAllSymbols };
133
 
134
/// Lookup flags that apply to each symbol in a lookup.
135
///
136
/// If RequiredSymbol is used (the default) for a given symbol then that symbol
137
/// must be found during the lookup or the lookup will fail returning a
138
/// SymbolNotFound error. If WeaklyReferencedSymbol is used and the given
139
/// symbol is not found then the query will continue, and no result for the
140
/// missing symbol will be present in the result (assuming the rest of the
141
/// lookup succeeds).
142
enum class SymbolLookupFlags { RequiredSymbol, WeaklyReferencedSymbol };
143
 
144
/// Describes the kind of lookup being performed. The lookup kind is passed to
145
/// symbol generators (if they're invoked) to help them determine what
146
/// definitions to generate.
147
///
148
/// Static -- Lookup is being performed as-if at static link time (e.g.
149
///           generators representing static archives should pull in new
150
///           definitions).
151
///
152
/// DLSym -- Lookup is being performed as-if at runtime (e.g. generators
153
///          representing static archives should not pull in new definitions).
154
enum class LookupKind { Static, DLSym };
155
 
156
/// A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search
157
/// order during symbol lookup.
158
using JITDylibSearchOrder =
159
    std::vector<std::pair<JITDylib *, JITDylibLookupFlags>>;
160
 
161
/// Convenience function for creating a search order from an ArrayRef of
162
/// JITDylib*, all with the same flags.
163
inline JITDylibSearchOrder makeJITDylibSearchOrder(
164
    ArrayRef<JITDylib *> JDs,
165
    JITDylibLookupFlags Flags = JITDylibLookupFlags::MatchExportedSymbolsOnly) {
166
  JITDylibSearchOrder O;
167
  O.reserve(JDs.size());
168
  for (auto *JD : JDs)
169
    O.push_back(std::make_pair(JD, Flags));
170
  return O;
171
}
172
 
173
/// A set of symbols to look up, each associated with a SymbolLookupFlags
174
/// value.
175
///
176
/// This class is backed by a vector and optimized for fast insertion,
177
/// deletion and iteration. It does not guarantee a stable order between
178
/// operations, and will not automatically detect duplicate elements (they
179
/// can be manually checked by calling the validate method).
180
class SymbolLookupSet {
181
public:
182
  using value_type = std::pair<SymbolStringPtr, SymbolLookupFlags>;
183
  using UnderlyingVector = std::vector<value_type>;
184
  using iterator = UnderlyingVector::iterator;
185
  using const_iterator = UnderlyingVector::const_iterator;
186
 
187
  SymbolLookupSet() = default;
188
 
189
  explicit SymbolLookupSet(
190
      SymbolStringPtr Name,
191
      SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
192
    add(std::move(Name), Flags);
193
  }
194
 
195
  /// Construct a SymbolLookupSet from an initializer list of SymbolStringPtrs.
196
  explicit SymbolLookupSet(
197
      std::initializer_list<SymbolStringPtr> Names,
198
      SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
199
    Symbols.reserve(Names.size());
200
    for (const auto &Name : Names)
201
      add(std::move(Name), Flags);
202
  }
203
 
204
  /// Construct a SymbolLookupSet from a SymbolNameSet with the given
205
  /// Flags used for each value.
206
  explicit SymbolLookupSet(
207
      const SymbolNameSet &Names,
208
      SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
209
    Symbols.reserve(Names.size());
210
    for (const auto &Name : Names)
211
      add(Name, Flags);
212
  }
213
 
214
  /// Construct a SymbolLookupSet from a vector of symbols with the given Flags
215
  /// used for each value.
216
  /// If the ArrayRef contains duplicates it is up to the client to remove these
217
  /// before using this instance for lookup.
218
  explicit SymbolLookupSet(
219
      ArrayRef<SymbolStringPtr> Names,
220
      SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
221
    Symbols.reserve(Names.size());
222
    for (const auto &Name : Names)
223
      add(Name, Flags);
224
  }
225
 
226
  /// Construct a SymbolLookupSet from DenseMap keys.
227
  template <typename KeyT>
228
  static SymbolLookupSet
229
  fromMapKeys(const DenseMap<SymbolStringPtr, KeyT> &M,
230
              SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
231
    SymbolLookupSet Result;
232
    Result.Symbols.reserve(M.size());
233
    for (const auto &KV : M)
234
      Result.add(KV.first, Flags);
235
    return Result;
236
  }
237
 
238
  /// Add an element to the set. The client is responsible for checking that
239
  /// duplicates are not added.
240
  SymbolLookupSet &
241
  add(SymbolStringPtr Name,
242
      SymbolLookupFlags Flags = SymbolLookupFlags::RequiredSymbol) {
243
    Symbols.push_back(std::make_pair(std::move(Name), Flags));
244
    return *this;
245
  }
246
 
247
  /// Quickly append one lookup set to another.
248
  SymbolLookupSet &append(SymbolLookupSet Other) {
249
    Symbols.reserve(Symbols.size() + Other.size());
250
    for (auto &KV : Other)
251
      Symbols.push_back(std::move(KV));
252
    return *this;
253
  }
254
 
255
  bool empty() const { return Symbols.empty(); }
256
  UnderlyingVector::size_type size() const { return Symbols.size(); }
257
  iterator begin() { return Symbols.begin(); }
258
  iterator end() { return Symbols.end(); }
259
  const_iterator begin() const { return Symbols.begin(); }
260
  const_iterator end() const { return Symbols.end(); }
261
 
262
  /// Removes the Ith element of the vector, replacing it with the last element.
263
  void remove(UnderlyingVector::size_type I) {
264
    std::swap(Symbols[I], Symbols.back());
265
    Symbols.pop_back();
266
  }
267
 
268
  /// Removes the element pointed to by the given iterator. This iterator and
269
  /// all subsequent ones (including end()) are invalidated.
270
  void remove(iterator I) { remove(I - begin()); }
271
 
272
  /// Removes all elements matching the given predicate, which must be callable
273
  /// as bool(const SymbolStringPtr &, SymbolLookupFlags Flags).
274
  template <typename PredFn> void remove_if(PredFn &&Pred) {
275
    UnderlyingVector::size_type I = 0;
276
    while (I != Symbols.size()) {
277
      const auto &Name = Symbols[I].first;
278
      auto Flags = Symbols[I].second;
279
      if (Pred(Name, Flags))
280
        remove(I);
281
      else
282
        ++I;
283
    }
284
  }
285
 
286
  /// Loop over the elements of this SymbolLookupSet, applying the Body function
287
  /// to each one. Body must be callable as
288
  /// bool(const SymbolStringPtr &, SymbolLookupFlags).
289
  /// If Body returns true then the element just passed in is removed from the
290
  /// set. If Body returns false then the element is retained.
291
  template <typename BodyFn>
292
  auto forEachWithRemoval(BodyFn &&Body) -> std::enable_if_t<
293
      std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
294
                                 std::declval<SymbolLookupFlags>())),
295
                   bool>::value> {
296
    UnderlyingVector::size_type I = 0;
297
    while (I != Symbols.size()) {
298
      const auto &Name = Symbols[I].first;
299
      auto Flags = Symbols[I].second;
300
      if (Body(Name, Flags))
301
        remove(I);
302
      else
303
        ++I;
304
    }
305
  }
306
 
307
  /// Loop over the elements of this SymbolLookupSet, applying the Body function
308
  /// to each one. Body must be callable as
309
  /// Expected<bool>(const SymbolStringPtr &, SymbolLookupFlags).
310
  /// If Body returns a failure value, the loop exits immediately. If Body
311
  /// returns true then the element just passed in is removed from the set. If
312
  /// Body returns false then the element is retained.
313
  template <typename BodyFn>
314
  auto forEachWithRemoval(BodyFn &&Body) -> std::enable_if_t<
315
      std::is_same<decltype(Body(std::declval<const SymbolStringPtr &>(),
316
                                 std::declval<SymbolLookupFlags>())),
317
                   Expected<bool>>::value,
318
      Error> {
319
    UnderlyingVector::size_type I = 0;
320
    while (I != Symbols.size()) {
321
      const auto &Name = Symbols[I].first;
322
      auto Flags = Symbols[I].second;
323
      auto Remove = Body(Name, Flags);
324
      if (!Remove)
325
        return Remove.takeError();
326
      if (*Remove)
327
        remove(I);
328
      else
329
        ++I;
330
    }
331
    return Error::success();
332
  }
333
 
334
  /// Construct a SymbolNameVector from this instance by dropping the Flags
335
  /// values.
336
  SymbolNameVector getSymbolNames() const {
337
    SymbolNameVector Names;
338
    Names.reserve(Symbols.size());
339
    for (const auto &KV : Symbols)
340
      Names.push_back(KV.first);
341
    return Names;
342
  }
343
 
344
  /// Sort the lookup set by pointer value. This sort is fast but sensitive to
345
  /// allocation order and so should not be used where a consistent order is
346
  /// required.
347
  void sortByAddress() { llvm::sort(Symbols, llvm::less_first()); }
348
 
349
  /// Sort the lookup set lexicographically. This sort is slow but the order
350
  /// is unaffected by allocation order.
351
  void sortByName() {
352
    llvm::sort(Symbols, [](const value_type &LHS, const value_type &RHS) {
353
      return *LHS.first < *RHS.first;
354
    });
355
  }
356
 
357
  /// Remove any duplicate elements. If a SymbolLookupSet is not duplicate-free
358
  /// by construction, this method can be used to turn it into a proper set.
359
  void removeDuplicates() {
360
    sortByAddress();
361
    auto LastI = std::unique(Symbols.begin(), Symbols.end());
362
    Symbols.erase(LastI, Symbols.end());
363
  }
364
 
365
#ifndef NDEBUG
366
  /// Returns true if this set contains any duplicates. This should only be used
367
  /// in assertions.
368
  bool containsDuplicates() {
369
    if (Symbols.size() < 2)
370
      return false;
371
    sortByAddress();
372
    for (UnderlyingVector::size_type I = 1; I != Symbols.size(); ++I)
373
      if (Symbols[I].first == Symbols[I - 1].first)
374
        return true;
375
    return false;
376
  }
377
#endif
378
 
379
private:
380
  UnderlyingVector Symbols;
381
};
382
 
383
struct SymbolAliasMapEntry {
384
  SymbolAliasMapEntry() = default;
385
  SymbolAliasMapEntry(SymbolStringPtr Aliasee, JITSymbolFlags AliasFlags)
386
      : Aliasee(std::move(Aliasee)), AliasFlags(AliasFlags) {}
387
 
388
  SymbolStringPtr Aliasee;
389
  JITSymbolFlags AliasFlags;
390
};
391
 
392
/// A map of Symbols to (Symbol, Flags) pairs.
393
using SymbolAliasMap = DenseMap<SymbolStringPtr, SymbolAliasMapEntry>;
394
 
395
/// Callback to notify client that symbols have been resolved.
396
using SymbolsResolvedCallback = unique_function<void(Expected<SymbolMap>)>;
397
 
398
/// Callback to register the dependencies for a given query.
399
using RegisterDependenciesFunction =
400
    std::function<void(const SymbolDependenceMap &)>;
401
 
402
/// This can be used as the value for a RegisterDependenciesFunction if there
403
/// are no dependants to register with.
404
extern RegisterDependenciesFunction NoDependenciesToRegister;
405
 
406
class ResourceTrackerDefunct : public ErrorInfo<ResourceTrackerDefunct> {
407
public:
408
  static char ID;
409
 
410
  ResourceTrackerDefunct(ResourceTrackerSP RT);
411
  std::error_code convertToErrorCode() const override;
412
  void log(raw_ostream &OS) const override;
413
 
414
private:
415
  ResourceTrackerSP RT;
416
};
417
 
418
/// Used to notify a JITDylib that the given set of symbols failed to
419
/// materialize.
420
class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> {
421
public:
422
  static char ID;
423
 
424
  FailedToMaterialize(std::shared_ptr<SymbolStringPool> SSP,
425
                      std::shared_ptr<SymbolDependenceMap> Symbols);
426
  ~FailedToMaterialize();
427
  std::error_code convertToErrorCode() const override;
428
  void log(raw_ostream &OS) const override;
429
  const SymbolDependenceMap &getSymbols() const { return *Symbols; }
430
 
431
private:
432
  std::shared_ptr<SymbolStringPool> SSP;
433
  std::shared_ptr<SymbolDependenceMap> Symbols;
434
};
435
 
436
/// Used to notify clients when symbols can not be found during a lookup.
437
class SymbolsNotFound : public ErrorInfo<SymbolsNotFound> {
438
public:
439
  static char ID;
440
 
441
  SymbolsNotFound(std::shared_ptr<SymbolStringPool> SSP, SymbolNameSet Symbols);
442
  SymbolsNotFound(std::shared_ptr<SymbolStringPool> SSP,
443
                  SymbolNameVector Symbols);
444
  std::error_code convertToErrorCode() const override;
445
  void log(raw_ostream &OS) const override;
446
  std::shared_ptr<SymbolStringPool> getSymbolStringPool() { return SSP; }
447
  const SymbolNameVector &getSymbols() const { return Symbols; }
448
 
449
private:
450
  std::shared_ptr<SymbolStringPool> SSP;
451
  SymbolNameVector Symbols;
452
};
453
 
454
/// Used to notify clients that a set of symbols could not be removed.
455
class SymbolsCouldNotBeRemoved : public ErrorInfo<SymbolsCouldNotBeRemoved> {
456
public:
457
  static char ID;
458
 
459
  SymbolsCouldNotBeRemoved(std::shared_ptr<SymbolStringPool> SSP,
460
                           SymbolNameSet Symbols);
461
  std::error_code convertToErrorCode() const override;
462
  void log(raw_ostream &OS) const override;
463
  std::shared_ptr<SymbolStringPool> getSymbolStringPool() { return SSP; }
464
  const SymbolNameSet &getSymbols() const { return Symbols; }
465
 
466
private:
467
  std::shared_ptr<SymbolStringPool> SSP;
468
  SymbolNameSet Symbols;
469
};
470
 
471
/// Errors of this type should be returned if a module fails to include
472
/// definitions that are claimed by the module's associated
473
/// MaterializationResponsibility. If this error is returned it is indicative of
474
/// a broken transformation / compiler / object cache.
475
class MissingSymbolDefinitions : public ErrorInfo<MissingSymbolDefinitions> {
476
public:
477
  static char ID;
478
 
479
  MissingSymbolDefinitions(std::shared_ptr<SymbolStringPool> SSP,
480
                           std::string ModuleName, SymbolNameVector Symbols)
481
      : SSP(std::move(SSP)), ModuleName(std::move(ModuleName)),
482
        Symbols(std::move(Symbols)) {}
483
  std::error_code convertToErrorCode() const override;
484
  void log(raw_ostream &OS) const override;
485
  std::shared_ptr<SymbolStringPool> getSymbolStringPool() { return SSP; }
486
  const std::string &getModuleName() const { return ModuleName; }
487
  const SymbolNameVector &getSymbols() const { return Symbols; }
488
private:
489
  std::shared_ptr<SymbolStringPool> SSP;
490
  std::string ModuleName;
491
  SymbolNameVector Symbols;
492
};
493
 
494
/// Errors of this type should be returned if a module contains definitions for
495
/// symbols that are not claimed by the module's associated
496
/// MaterializationResponsibility. If this error is returned it is indicative of
497
/// a broken transformation / compiler / object cache.
498
class UnexpectedSymbolDefinitions : public ErrorInfo<UnexpectedSymbolDefinitions> {
499
public:
500
  static char ID;
501
 
502
  UnexpectedSymbolDefinitions(std::shared_ptr<SymbolStringPool> SSP,
503
                              std::string ModuleName, SymbolNameVector Symbols)
504
      : SSP(std::move(SSP)), ModuleName(std::move(ModuleName)),
505
        Symbols(std::move(Symbols)) {}
506
  std::error_code convertToErrorCode() const override;
507
  void log(raw_ostream &OS) const override;
508
  std::shared_ptr<SymbolStringPool> getSymbolStringPool() { return SSP; }
509
  const std::string &getModuleName() const { return ModuleName; }
510
  const SymbolNameVector &getSymbols() const { return Symbols; }
511
private:
512
  std::shared_ptr<SymbolStringPool> SSP;
513
  std::string ModuleName;
514
  SymbolNameVector Symbols;
515
};
516
 
517
/// Tracks responsibility for materialization, and mediates interactions between
518
/// MaterializationUnits and JDs.
519
///
520
/// An instance of this class is passed to MaterializationUnits when their
521
/// materialize method is called. It allows MaterializationUnits to resolve and
522
/// emit symbols, or abandon materialization by notifying any unmaterialized
523
/// symbols of an error.
524
class MaterializationResponsibility {
525
  friend class ExecutionSession;
526
  friend class JITDylib;
527
 
528
public:
529
  MaterializationResponsibility(MaterializationResponsibility &&) = delete;
530
  MaterializationResponsibility &
531
  operator=(MaterializationResponsibility &&) = delete;
532
 
533
  /// Destruct a MaterializationResponsibility instance. In debug mode
534
  ///        this asserts that all symbols being tracked have been either
535
  ///        emitted or notified of an error.
536
  ~MaterializationResponsibility();
537
 
538
  /// Runs the given callback under the session lock, passing in the associated
539
  /// ResourceKey. This is the safe way to associate resources with trackers.
540
  template <typename Func> Error withResourceKeyDo(Func &&F) const {
541
    return RT->withResourceKeyDo(std::forward<Func>(F));
542
  }
543
 
544
  /// Returns the target JITDylib that these symbols are being materialized
545
  ///        into.
546
  JITDylib &getTargetJITDylib() const { return JD; }
547
 
548
  /// Returns the ExecutionSession for this instance.
549
  ExecutionSession &getExecutionSession() const;
550
 
551
  /// Returns the symbol flags map for this responsibility instance.
552
  /// Note: The returned flags may have transient flags (Lazy, Materializing)
553
  /// set. These should be stripped with JITSymbolFlags::stripTransientFlags
554
  /// before using.
555
  const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
556
 
557
  /// Returns the initialization pseudo-symbol, if any. This symbol will also
558
  /// be present in the SymbolFlagsMap for this MaterializationResponsibility
559
  /// object.
560
  const SymbolStringPtr &getInitializerSymbol() const { return InitSymbol; }
561
 
562
  /// Returns the names of any symbols covered by this
563
  /// MaterializationResponsibility object that have queries pending. This
564
  /// information can be used to return responsibility for unrequested symbols
565
  /// back to the JITDylib via the delegate method.
566
  SymbolNameSet getRequestedSymbols() const;
567
 
568
  /// Notifies the target JITDylib that the given symbols have been resolved.
569
  /// This will update the given symbols' addresses in the JITDylib, and notify
570
  /// any pending queries on the given symbols of their resolution. The given
571
  /// symbols must be ones covered by this MaterializationResponsibility
572
  /// instance. Individual calls to this method may resolve a subset of the
573
  /// symbols, but all symbols must have been resolved prior to calling emit.
574
  ///
575
  /// This method will return an error if any symbols being resolved have been
576
  /// moved to the error state due to the failure of a dependency. If this
577
  /// method returns an error then clients should log it and call
578
  /// failMaterialize. If no dependencies have been registered for the
579
  /// symbols covered by this MaterializationResponsibiility then this method
580
  /// is guaranteed to return Error::success() and can be wrapped with cantFail.
581
  Error notifyResolved(const SymbolMap &Symbols);
582
 
583
  /// Notifies the target JITDylib (and any pending queries on that JITDylib)
584
  /// that all symbols covered by this MaterializationResponsibility instance
585
  /// have been emitted.
586
  ///
587
  /// This method will return an error if any symbols being resolved have been
588
  /// moved to the error state due to the failure of a dependency. If this
589
  /// method returns an error then clients should log it and call
590
  /// failMaterialize. If no dependencies have been registered for the
591
  /// symbols covered by this MaterializationResponsibiility then this method
592
  /// is guaranteed to return Error::success() and can be wrapped with cantFail.
593
  Error notifyEmitted();
594
 
595
  /// Attempt to claim responsibility for new definitions. This method can be
596
  /// used to claim responsibility for symbols that are added to a
597
  /// materialization unit during the compilation process (e.g. literal pool
598
  /// symbols). Symbol linkage rules are the same as for symbols that are
599
  /// defined up front: duplicate strong definitions will result in errors.
600
  /// Duplicate weak definitions will be discarded (in which case they will
601
  /// not be added to this responsibility instance).
602
  ///
603
  ///   This method can be used by materialization units that want to add
604
  /// additional symbols at materialization time (e.g. stubs, compile
605
  /// callbacks, metadata).
606
  Error defineMaterializing(SymbolFlagsMap SymbolFlags);
607
 
608
  /// Define the given symbols as non-existent, removing it from the symbol
609
  /// table and notifying any pending queries. Queries that lookup up the
610
  /// symbol using the SymbolLookupFlags::WeaklyReferencedSymbol flag will
611
  /// behave as if the symbol had not been matched in the first place. Queries
612
  /// that required this symbol will fail with a missing symbol definition
613
  /// error.
614
  ///
615
  /// This method is intended to support cleanup of special symbols like
616
  /// initializer symbols: Queries using
617
  /// SymbolLookupFlags::WeaklyReferencedSymbol can be used to trigger their
618
  /// emission, and this method can be used to remove them from the JITDylib
619
  /// once materialization is complete.
620
  void defineNonExistent(ArrayRef<SymbolStringPtr> Symbols);
621
 
622
  /// Notify all not-yet-emitted covered by this MaterializationResponsibility
623
  /// instance that an error has occurred.
624
  /// This will remove all symbols covered by this MaterializationResponsibilty
625
  /// from the target JITDylib, and send an error to any queries waiting on
626
  /// these symbols.
627
  void failMaterialization();
628
 
629
  /// Transfers responsibility to the given MaterializationUnit for all
630
  /// symbols defined by that MaterializationUnit. This allows
631
  /// materializers to break up work based on run-time information (e.g.
632
  /// by introspecting which symbols have actually been looked up and
633
  /// materializing only those).
634
  Error replace(std::unique_ptr<MaterializationUnit> MU);
635
 
636
  /// Delegates responsibility for the given symbols to the returned
637
  /// materialization responsibility. Useful for breaking up work between
638
  /// threads, or different kinds of materialization processes.
639
  Expected<std::unique_ptr<MaterializationResponsibility>>
640
  delegate(const SymbolNameSet &Symbols);
641
 
642
  void addDependencies(const SymbolStringPtr &Name,
643
                       const SymbolDependenceMap &Dependencies);
644
 
645
  /// Add dependencies that apply to all symbols covered by this instance.
646
  void addDependenciesForAll(const SymbolDependenceMap &Dependencies);
647
 
648
private:
649
  /// Create a MaterializationResponsibility for the given JITDylib and
650
  ///        initial symbols.
651
  MaterializationResponsibility(ResourceTrackerSP RT,
652
                                SymbolFlagsMap SymbolFlags,
653
                                SymbolStringPtr InitSymbol)
654
      : JD(RT->getJITDylib()), RT(std::move(RT)),
655
        SymbolFlags(std::move(SymbolFlags)), InitSymbol(std::move(InitSymbol)) {
656
    assert(!this->SymbolFlags.empty() && "Materializing nothing?");
657
  }
658
 
659
  JITDylib &JD;
660
  ResourceTrackerSP RT;
661
  SymbolFlagsMap SymbolFlags;
662
  SymbolStringPtr InitSymbol;
663
};
664
 
665
/// A MaterializationUnit represents a set of symbol definitions that can
666
///        be materialized as a group, or individually discarded (when
667
///        overriding definitions are encountered).
668
///
669
/// MaterializationUnits are used when providing lazy definitions of symbols to
670
/// JITDylibs. The JITDylib will call materialize when the address of a symbol
671
/// is requested via the lookup method. The JITDylib will call discard if a
672
/// stronger definition is added or already present.
673
class MaterializationUnit {
674
  friend class ExecutionSession;
675
  friend class JITDylib;
676
 
677
public:
678
  static char ID;
679
 
680
  struct Interface {
681
    Interface() = default;
682
    Interface(SymbolFlagsMap InitalSymbolFlags, SymbolStringPtr InitSymbol)
683
        : SymbolFlags(std::move(InitalSymbolFlags)),
684
          InitSymbol(std::move(InitSymbol)) {
685
      assert((!this->InitSymbol || this->SymbolFlags.count(this->InitSymbol)) &&
686
             "If set, InitSymbol should appear in InitialSymbolFlags map");
687
    }
688
 
689
    SymbolFlagsMap SymbolFlags;
690
    SymbolStringPtr InitSymbol;
691
  };
692
 
693
  MaterializationUnit(Interface I)
694
      : SymbolFlags(std::move(I.SymbolFlags)),
695
        InitSymbol(std::move(I.InitSymbol)) {}
696
  virtual ~MaterializationUnit() = default;
697
 
698
  /// Return the name of this materialization unit. Useful for debugging
699
  /// output.
700
  virtual StringRef getName() const = 0;
701
 
702
  /// Return the set of symbols that this source provides.
703
  const SymbolFlagsMap &getSymbols() const { return SymbolFlags; }
704
 
705
  /// Returns the initialization symbol for this MaterializationUnit (if any).
706
  const SymbolStringPtr &getInitializerSymbol() const { return InitSymbol; }
707
 
708
  /// Implementations of this method should materialize all symbols
709
  ///        in the materialzation unit, except for those that have been
710
  ///        previously discarded.
711
  virtual void
712
  materialize(std::unique_ptr<MaterializationResponsibility> R) = 0;
713
 
714
  /// Called by JITDylibs to notify MaterializationUnits that the given symbol
715
  /// has been overridden.
716
  void doDiscard(const JITDylib &JD, const SymbolStringPtr &Name) {
717
    SymbolFlags.erase(Name);
718
    if (InitSymbol == Name) {
719
      DEBUG_WITH_TYPE("orc", {
720
        dbgs() << "In " << getName() << ": discarding init symbol \""
721
               << *Name << "\"\n";
722
      });
723
      InitSymbol = nullptr;
724
    }
725
    discard(JD, std::move(Name));
726
  }
727
 
728
protected:
729
  SymbolFlagsMap SymbolFlags;
730
  SymbolStringPtr InitSymbol;
731
 
732
private:
733
  virtual void anchor();
734
 
735
  /// Implementations of this method should discard the given symbol
736
  ///        from the source (e.g. if the source is an LLVM IR Module and the
737
  ///        symbol is a function, delete the function body or mark it available
738
  ///        externally).
739
  virtual void discard(const JITDylib &JD, const SymbolStringPtr &Name) = 0;
740
};
741
 
742
/// A MaterializationUnit implementation for pre-existing absolute symbols.
743
///
744
/// All symbols will be resolved and marked ready as soon as the unit is
745
/// materialized.
746
class AbsoluteSymbolsMaterializationUnit : public MaterializationUnit {
747
public:
748
  AbsoluteSymbolsMaterializationUnit(SymbolMap Symbols);
749
 
750
  StringRef getName() const override;
751
 
752
private:
753
  void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
754
  void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
755
  static MaterializationUnit::Interface extractFlags(const SymbolMap &Symbols);
756
 
757
  SymbolMap Symbols;
758
};
759
 
760
/// Create an AbsoluteSymbolsMaterializationUnit with the given symbols.
761
/// Useful for inserting absolute symbols into a JITDylib. E.g.:
762
/// \code{.cpp}
763
///   JITDylib &JD = ...;
764
///   SymbolStringPtr Foo = ...;
765
///   JITEvaluatedSymbol FooSym = ...;
766
///   if (auto Err = JD.define(absoluteSymbols({{Foo, FooSym}})))
767
///     return Err;
768
/// \endcode
769
///
770
inline std::unique_ptr<AbsoluteSymbolsMaterializationUnit>
771
absoluteSymbols(SymbolMap Symbols) {
772
  return std::make_unique<AbsoluteSymbolsMaterializationUnit>(
773
      std::move(Symbols));
774
}
775
 
776
/// A materialization unit for symbol aliases. Allows existing symbols to be
777
/// aliased with alternate flags.
778
class ReExportsMaterializationUnit : public MaterializationUnit {
779
public:
780
  /// SourceJD is allowed to be nullptr, in which case the source JITDylib is
781
  /// taken to be whatever JITDylib these definitions are materialized in (and
782
  /// MatchNonExported has no effect). This is useful for defining aliases
783
  /// within a JITDylib.
784
  ///
785
  /// Note: Care must be taken that no sets of aliases form a cycle, as such
786
  ///       a cycle will result in a deadlock when any symbol in the cycle is
787
  ///       resolved.
788
  ReExportsMaterializationUnit(JITDylib *SourceJD,
789
                               JITDylibLookupFlags SourceJDLookupFlags,
790
                               SymbolAliasMap Aliases);
791
 
792
  StringRef getName() const override;
793
 
794
private:
795
  void materialize(std::unique_ptr<MaterializationResponsibility> R) override;
796
  void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
797
  static MaterializationUnit::Interface
798
  extractFlags(const SymbolAliasMap &Aliases);
799
 
800
  JITDylib *SourceJD = nullptr;
801
  JITDylibLookupFlags SourceJDLookupFlags;
802
  SymbolAliasMap Aliases;
803
};
804
 
805
/// Create a ReExportsMaterializationUnit with the given aliases.
806
/// Useful for defining symbol aliases.: E.g., given a JITDylib JD containing
807
/// symbols "foo" and "bar", we can define aliases "baz" (for "foo") and "qux"
808
/// (for "bar") with: \code{.cpp}
809
///   SymbolStringPtr Baz = ...;
810
///   SymbolStringPtr Qux = ...;
811
///   if (auto Err = JD.define(symbolAliases({
812
///       {Baz, { Foo, JITSymbolFlags::Exported }},
813
///       {Qux, { Bar, JITSymbolFlags::Weak }}}))
814
///     return Err;
815
/// \endcode
816
inline std::unique_ptr<ReExportsMaterializationUnit>
817
symbolAliases(SymbolAliasMap Aliases) {
818
  return std::make_unique<ReExportsMaterializationUnit>(
819
      nullptr, JITDylibLookupFlags::MatchAllSymbols, std::move(Aliases));
820
}
821
 
822
/// Create a materialization unit for re-exporting symbols from another JITDylib
823
/// with alternative names/flags.
824
/// SourceJD will be searched using the given JITDylibLookupFlags.
825
inline std::unique_ptr<ReExportsMaterializationUnit>
826
reexports(JITDylib &SourceJD, SymbolAliasMap Aliases,
827
          JITDylibLookupFlags SourceJDLookupFlags =
828
              JITDylibLookupFlags::MatchExportedSymbolsOnly) {
829
  return std::make_unique<ReExportsMaterializationUnit>(
830
      &SourceJD, SourceJDLookupFlags, std::move(Aliases));
831
}
832
 
833
/// Build a SymbolAliasMap for the common case where you want to re-export
834
/// symbols from another JITDylib with the same linkage/flags.
835
Expected<SymbolAliasMap>
836
buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols);
837
 
838
/// Represents the state that a symbol has reached during materialization.
839
enum class SymbolState : uint8_t {
840
  Invalid,       /// No symbol should be in this state.
841
  NeverSearched, /// Added to the symbol table, never queried.
842
  Materializing, /// Queried, materialization begun.
843
  Resolved,      /// Assigned address, still materializing.
844
  Emitted,       /// Emitted to memory, but waiting on transitive dependencies.
845
  Ready = 0x3f   /// Ready and safe for clients to access.
846
};
847
 
848
/// A symbol query that returns results via a callback when results are
849
///        ready.
850
///
851
/// makes a callback when all symbols are available.
852
class AsynchronousSymbolQuery {
853
  friend class ExecutionSession;
854
  friend class InProgressFullLookupState;
855
  friend class JITDylib;
856
  friend class JITSymbolResolverAdapter;
857
  friend class MaterializationResponsibility;
858
 
859
public:
860
  /// Create a query for the given symbols. The NotifyComplete
861
  /// callback will be called once all queried symbols reach the given
862
  /// minimum state.
863
  AsynchronousSymbolQuery(const SymbolLookupSet &Symbols,
864
                          SymbolState RequiredState,
865
                          SymbolsResolvedCallback NotifyComplete);
866
 
867
  /// Notify the query that a requested symbol has reached the required state.
868
  void notifySymbolMetRequiredState(const SymbolStringPtr &Name,
869
                                    JITEvaluatedSymbol Sym);
870
 
871
  /// Returns true if all symbols covered by this query have been
872
  ///        resolved.
873
  bool isComplete() const { return OutstandingSymbolsCount == 0; }
874
 
875
 
876
private:
877
  void handleComplete(ExecutionSession &ES);
878
 
879
  SymbolState getRequiredState() { return RequiredState; }
880
 
881
  void addQueryDependence(JITDylib &JD, SymbolStringPtr Name);
882
 
883
  void removeQueryDependence(JITDylib &JD, const SymbolStringPtr &Name);
884
 
885
  void dropSymbol(const SymbolStringPtr &Name);
886
 
887
  void handleFailed(Error Err);
888
 
889
  void detach();
890
 
891
  SymbolsResolvedCallback NotifyComplete;
892
  SymbolDependenceMap QueryRegistrations;
893
  SymbolMap ResolvedSymbols;
894
  size_t OutstandingSymbolsCount;
895
  SymbolState RequiredState;
896
};
897
 
898
/// Wraps state for a lookup-in-progress.
899
/// DefinitionGenerators can optionally take ownership of a LookupState object
900
/// to suspend a lookup-in-progress while they search for definitions.
901
class LookupState {
902
  friend class OrcV2CAPIHelper;
903
  friend class ExecutionSession;
904
 
905
public:
906
  LookupState();
907
  LookupState(LookupState &&);
908
  LookupState &operator=(LookupState &&);
909
  ~LookupState();
910
 
911
  /// Continue the lookup. This can be called by DefinitionGenerators
912
  /// to re-start a captured query-application operation.
913
  void continueLookup(Error Err);
914
 
915
private:
916
  LookupState(std::unique_ptr<InProgressLookupState> IPLS);
917
 
918
  // For C API.
919
  void reset(InProgressLookupState *IPLS);
920
 
921
  std::unique_ptr<InProgressLookupState> IPLS;
922
};
923
 
924
/// Definition generators can be attached to JITDylibs to generate new
925
/// definitions for otherwise unresolved symbols during lookup.
926
class DefinitionGenerator {
927
public:
928
  virtual ~DefinitionGenerator();
929
 
930
  /// DefinitionGenerators should override this method to insert new
931
  /// definitions into the parent JITDylib. K specifies the kind of this
932
  /// lookup. JD specifies the target JITDylib being searched, and
933
  /// JDLookupFlags specifies whether the search should match against
934
  /// hidden symbols. Finally, Symbols describes the set of unresolved
935
  /// symbols and their associated lookup flags.
936
  virtual Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
937
                              JITDylibLookupFlags JDLookupFlags,
938
                              const SymbolLookupSet &LookupSet) = 0;
939
};
940
 
941
/// Represents a JIT'd dynamic library.
942
///
943
/// This class aims to mimic the behavior of a regular dylib or shared object,
944
/// but without requiring the contained program representations to be compiled
945
/// up-front. The JITDylib's content is defined by adding MaterializationUnits,
946
/// and contained MaterializationUnits will typically rely on the JITDylib's
947
/// links-against order to resolve external references (similar to a regular
948
/// dylib).
949
///
950
/// The JITDylib object is a thin wrapper that references state held by the
951
/// ExecutionSession. JITDylibs can be removed, clearing this underlying state
952
/// and leaving the JITDylib object in a defunct state. In this state the
953
/// JITDylib's name is guaranteed to remain accessible. If the ExecutionSession
954
/// is still alive then other operations are callable but will return an Error
955
/// or null result (depending on the API). It is illegal to call any operation
956
/// other than getName on a JITDylib after the ExecutionSession has been torn
957
/// down.
958
///
959
/// JITDylibs cannot be moved or copied. Their address is stable, and useful as
960
/// a key in some JIT data structures.
961
class JITDylib : public ThreadSafeRefCountedBase<JITDylib>,
962
                 public jitlink::JITLinkDylib {
963
  friend class AsynchronousSymbolQuery;
964
  friend class ExecutionSession;
965
  friend class Platform;
966
  friend class MaterializationResponsibility;
967
public:
968
 
969
  JITDylib(const JITDylib &) = delete;
970
  JITDylib &operator=(const JITDylib &) = delete;
971
  JITDylib(JITDylib &&) = delete;
972
  JITDylib &operator=(JITDylib &&) = delete;
973
  ~JITDylib();
974
 
975
  /// Get a reference to the ExecutionSession for this JITDylib.
976
  ///
977
  /// It is legal to call this method on a defunct JITDylib, however the result
978
  /// will only usable if the ExecutionSession is still alive. If this JITDylib
979
  /// is held by an error that may have torn down the JIT then the result
980
  /// should not be used.
981
  ExecutionSession &getExecutionSession() const { return ES; }
982
 
983
  /// Dump current JITDylib state to OS.
984
  ///
985
  /// It is legal to call this method on a defunct JITDylib.
986
  void dump(raw_ostream &OS);
987
 
988
  /// Calls remove on all trackers currently associated with this JITDylib.
989
  /// Does not run static deinits.
990
  ///
991
  /// Note that removal happens outside the session lock, so new code may be
992
  /// added concurrently while the clear is underway, and the newly added
993
  /// code will *not* be cleared. Adding new code concurrently with a clear
994
  /// is usually a bug and should be avoided.
995
  ///
996
  /// It is illegal to call this method on a defunct JITDylib and the client
997
  /// is responsible for ensuring that they do not do so.
998
  Error clear();
999
 
1000
  /// Get the default resource tracker for this JITDylib.
1001
  ///
1002
  /// It is illegal to call this method on a defunct JITDylib and the client
1003
  /// is responsible for ensuring that they do not do so.
1004
  ResourceTrackerSP getDefaultResourceTracker();
1005
 
1006
  /// Create a resource tracker for this JITDylib.
1007
  ///
1008
  /// It is illegal to call this method on a defunct JITDylib and the client
1009
  /// is responsible for ensuring that they do not do so.
1010
  ResourceTrackerSP createResourceTracker();
1011
 
1012
  /// Adds a definition generator to this JITDylib and returns a referenece to
1013
  /// it.
1014
  ///
1015
  /// When JITDylibs are searched during lookup, if no existing definition of
1016
  /// a symbol is found, then any generators that have been added are run (in
1017
  /// the order that they were added) to potentially generate a definition.
1018
  ///
1019
  /// It is illegal to call this method on a defunct JITDylib and the client
1020
  /// is responsible for ensuring that they do not do so.
1021
  template <typename GeneratorT>
1022
  GeneratorT &addGenerator(std::unique_ptr<GeneratorT> DefGenerator);
1023
 
1024
  /// Remove a definition generator from this JITDylib.
1025
  ///
1026
  /// The given generator must exist in this JITDylib's generators list (i.e.
1027
  /// have been added and not yet removed).
1028
  ///
1029
  /// It is illegal to call this method on a defunct JITDylib and the client
1030
  /// is responsible for ensuring that they do not do so.
1031
  void removeGenerator(DefinitionGenerator &G);
1032
 
1033
  /// Set the link order to be used when fixing up definitions in JITDylib.
1034
  /// This will replace the previous link order, and apply to any symbol
1035
  /// resolutions made for definitions in this JITDylib after the call to
1036
  /// setLinkOrder (even if the definition itself was added before the
1037
  /// call).
1038
  ///
1039
  /// If LinkAgainstThisJITDylibFirst is true (the default) then this JITDylib
1040
  /// will add itself to the beginning of the LinkOrder (Clients should not
1041
  /// put this JITDylib in the list in this case, to avoid redundant lookups).
1042
  ///
1043
  /// If LinkAgainstThisJITDylibFirst is false then the link order will be used
1044
  /// as-is. The primary motivation for this feature is to support deliberate
1045
  /// shadowing of symbols in this JITDylib by a facade JITDylib. For example,
1046
  /// the facade may resolve function names to stubs, and the stubs may compile
1047
  /// lazily by looking up symbols in this dylib. Adding the facade dylib
1048
  /// as the first in the link order (instead of this dylib) ensures that
1049
  /// definitions within this dylib resolve to the lazy-compiling stubs,
1050
  /// rather than immediately materializing the definitions in this dylib.
1051
  ///
1052
  /// It is illegal to call this method on a defunct JITDylib and the client
1053
  /// is responsible for ensuring that they do not do so.
1054
  void setLinkOrder(JITDylibSearchOrder NewSearchOrder,
1055
                    bool LinkAgainstThisJITDylibFirst = true);
1056
 
1057
  /// Add the given JITDylib to the link order for definitions in this
1058
  /// JITDylib.
1059
  ///
1060
  /// It is illegal to call this method on a defunct JITDylib and the client
1061
  /// is responsible for ensuring that they do not do so.
1062
  void addToLinkOrder(JITDylib &JD,
1063
                      JITDylibLookupFlags JDLookupFlags =
1064
                          JITDylibLookupFlags::MatchExportedSymbolsOnly);
1065
 
1066
  /// Replace OldJD with NewJD in the link order if OldJD is present.
1067
  /// Otherwise this operation is a no-op.
1068
  ///
1069
  /// It is illegal to call this method on a defunct JITDylib and the client
1070
  /// is responsible for ensuring that they do not do so.
1071
  void replaceInLinkOrder(JITDylib &OldJD, JITDylib &NewJD,
1072
                          JITDylibLookupFlags JDLookupFlags =
1073
                              JITDylibLookupFlags::MatchExportedSymbolsOnly);
1074
 
1075
  /// Remove the given JITDylib from the link order for this JITDylib if it is
1076
  /// present. Otherwise this operation is a no-op.
1077
  ///
1078
  /// It is illegal to call this method on a defunct JITDylib and the client
1079
  /// is responsible for ensuring that they do not do so.
1080
  void removeFromLinkOrder(JITDylib &JD);
1081
 
1082
  /// Do something with the link order (run under the session lock).
1083
  ///
1084
  /// It is illegal to call this method on a defunct JITDylib and the client
1085
  /// is responsible for ensuring that they do not do so.
1086
  template <typename Func>
1087
  auto withLinkOrderDo(Func &&F)
1088
      -> decltype(F(std::declval<const JITDylibSearchOrder &>()));
1089
 
1090
  /// Define all symbols provided by the materialization unit to be part of this
1091
  /// JITDylib.
1092
  ///
1093
  /// If RT is not specified then the default resource tracker will be used.
1094
  ///
1095
  /// This overload always takes ownership of the MaterializationUnit. If any
1096
  /// errors occur, the MaterializationUnit consumed.
1097
  ///
1098
  /// It is illegal to call this method on a defunct JITDylib and the client
1099
  /// is responsible for ensuring that they do not do so.
1100
  template <typename MaterializationUnitType>
1101
  Error define(std::unique_ptr<MaterializationUnitType> &&MU,
1102
               ResourceTrackerSP RT = nullptr);
1103
 
1104
  /// Define all symbols provided by the materialization unit to be part of this
1105
  /// JITDylib.
1106
  ///
1107
  /// This overload only takes ownership of the MaterializationUnit no error is
1108
  /// generated. If an error occurs, ownership remains with the caller. This
1109
  /// may allow the caller to modify the MaterializationUnit to correct the
1110
  /// issue, then re-call define.
1111
  ///
1112
  /// It is illegal to call this method on a defunct JITDylib and the client
1113
  /// is responsible for ensuring that they do not do so.
1114
  template <typename MaterializationUnitType>
1115
  Error define(std::unique_ptr<MaterializationUnitType> &MU,
1116
               ResourceTrackerSP RT = nullptr);
1117
 
1118
  /// Tries to remove the given symbols.
1119
  ///
1120
  /// If any symbols are not defined in this JITDylib this method will return
1121
  /// a SymbolsNotFound error covering the missing symbols.
1122
  ///
1123
  /// If all symbols are found but some symbols are in the process of being
1124
  /// materialized this method will return a SymbolsCouldNotBeRemoved error.
1125
  ///
1126
  /// On success, all symbols are removed. On failure, the JITDylib state is
1127
  /// left unmodified (no symbols are removed).
1128
  ///
1129
  /// It is illegal to call this method on a defunct JITDylib and the client
1130
  /// is responsible for ensuring that they do not do so.
1131
  Error remove(const SymbolNameSet &Names);
1132
 
1133
  /// Returns the given JITDylibs and all of their transitive dependencies in
1134
  /// DFS order (based on linkage relationships). Each JITDylib will appear
1135
  /// only once.
1136
  ///
1137
  /// If any JITDylib in the order is defunct then this method will return an
1138
  /// error, otherwise returns the order.
1139
  static Expected<std::vector<JITDylibSP>>
1140
  getDFSLinkOrder(ArrayRef<JITDylibSP> JDs);
1141
 
1142
  /// Returns the given JITDylibs and all of their transitive dependencies in
1143
  /// reverse DFS order (based on linkage relationships). Each JITDylib will
1144
  /// appear only once.
1145
  ///
1146
  /// If any JITDylib in the order is defunct then this method will return an
1147
  /// error, otherwise returns the order.
1148
  static Expected<std::vector<JITDylibSP>>
1149
  getReverseDFSLinkOrder(ArrayRef<JITDylibSP> JDs);
1150
 
1151
  /// Return this JITDylib and its transitive dependencies in DFS order
1152
  /// based on linkage relationships.
1153
  ///
1154
  /// If any JITDylib in the order is defunct then this method will return an
1155
  /// error, otherwise returns the order.
1156
  Expected<std::vector<JITDylibSP>> getDFSLinkOrder();
1157
 
1158
  /// Rteurn this JITDylib and its transitive dependencies in reverse DFS order
1159
  /// based on linkage relationships.
1160
  ///
1161
  /// If any JITDylib in the order is defunct then this method will return an
1162
  /// error, otherwise returns the order.
1163
  Expected<std::vector<JITDylibSP>> getReverseDFSLinkOrder();
1164
 
1165
private:
1166
  using AsynchronousSymbolQuerySet =
1167
    std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
1168
 
1169
  using AsynchronousSymbolQueryList =
1170
      std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
1171
 
1172
  struct UnmaterializedInfo {
1173
    UnmaterializedInfo(std::unique_ptr<MaterializationUnit> MU,
1174
                       ResourceTracker *RT)
1175
        : MU(std::move(MU)), RT(RT) {}
1176
 
1177
    std::unique_ptr<MaterializationUnit> MU;
1178
    ResourceTracker *RT;
1179
  };
1180
 
1181
  using UnmaterializedInfosMap =
1182
      DenseMap<SymbolStringPtr, std::shared_ptr<UnmaterializedInfo>>;
1183
 
1184
  using UnmaterializedInfosList =
1185
      std::vector<std::shared_ptr<UnmaterializedInfo>>;
1186
 
1187
  struct MaterializingInfo {
1188
    SymbolDependenceMap Dependants;
1189
    SymbolDependenceMap UnemittedDependencies;
1190
 
1191
    void addQuery(std::shared_ptr<AsynchronousSymbolQuery> Q);
1192
    void removeQuery(const AsynchronousSymbolQuery &Q);
1193
    AsynchronousSymbolQueryList takeQueriesMeeting(SymbolState RequiredState);
1194
    AsynchronousSymbolQueryList takeAllPendingQueries() {
1195
      return std::move(PendingQueries);
1196
    }
1197
    bool hasQueriesPending() const { return !PendingQueries.empty(); }
1198
    const AsynchronousSymbolQueryList &pendingQueries() const {
1199
      return PendingQueries;
1200
    }
1201
  private:
1202
    AsynchronousSymbolQueryList PendingQueries;
1203
  };
1204
 
1205
  using MaterializingInfosMap = DenseMap<SymbolStringPtr, MaterializingInfo>;
1206
 
1207
  class SymbolTableEntry {
1208
  public:
1209
    SymbolTableEntry() = default;
1210
    SymbolTableEntry(JITSymbolFlags Flags)
1211
        : Flags(Flags), State(static_cast<uint8_t>(SymbolState::NeverSearched)),
1212
          MaterializerAttached(false), PendingRemoval(false) {}
1213
 
1214
    JITTargetAddress getAddress() const { return Addr; }
1215
    JITSymbolFlags getFlags() const { return Flags; }
1216
    SymbolState getState() const { return static_cast<SymbolState>(State); }
1217
 
1218
    bool hasMaterializerAttached() const { return MaterializerAttached; }
1219
    bool isPendingRemoval() const { return PendingRemoval; }
1220
 
1221
    void setAddress(JITTargetAddress Addr) { this->Addr = Addr; }
1222
    void setFlags(JITSymbolFlags Flags) { this->Flags = Flags; }
1223
    void setState(SymbolState State) {
1224
      assert(static_cast<uint8_t>(State) < (1 << 6) &&
1225
             "State does not fit in bitfield");
1226
      this->State = static_cast<uint8_t>(State);
1227
    }
1228
 
1229
    void setMaterializerAttached(bool MaterializerAttached) {
1230
      this->MaterializerAttached = MaterializerAttached;
1231
    }
1232
 
1233
    void setPendingRemoval(bool PendingRemoval) {
1234
      this->PendingRemoval = PendingRemoval;
1235
    }
1236
 
1237
    JITEvaluatedSymbol getSymbol() const {
1238
      return JITEvaluatedSymbol(Addr, Flags);
1239
    }
1240
 
1241
  private:
1242
    JITTargetAddress Addr = 0;
1243
    JITSymbolFlags Flags;
1244
    uint8_t State : 6;
1245
    uint8_t MaterializerAttached : 1;
1246
    uint8_t PendingRemoval : 1;
1247
  };
1248
 
1249
  using SymbolTable = DenseMap<SymbolStringPtr, SymbolTableEntry>;
1250
 
1251
  JITDylib(ExecutionSession &ES, std::string Name);
1252
 
1253
  std::pair<AsynchronousSymbolQuerySet, std::shared_ptr<SymbolDependenceMap>>
1254
  removeTracker(ResourceTracker &RT);
1255
 
1256
  void transferTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT);
1257
 
1258
  Error defineImpl(MaterializationUnit &MU);
1259
 
1260
  void installMaterializationUnit(std::unique_ptr<MaterializationUnit> MU,
1261
                                  ResourceTracker &RT);
1262
 
1263
  void detachQueryHelper(AsynchronousSymbolQuery &Q,
1264
                         const SymbolNameSet &QuerySymbols);
1265
 
1266
  void transferEmittedNodeDependencies(MaterializingInfo &DependantMI,
1267
                                       const SymbolStringPtr &DependantName,
1268
                                       MaterializingInfo &EmittedMI);
1269
 
1270
  Expected<SymbolFlagsMap> defineMaterializing(SymbolFlagsMap SymbolFlags);
1271
 
1272
  Error replace(MaterializationResponsibility &FromMR,
1273
                std::unique_ptr<MaterializationUnit> MU);
1274
 
1275
  Expected<std::unique_ptr<MaterializationResponsibility>>
1276
  delegate(MaterializationResponsibility &FromMR, SymbolFlagsMap SymbolFlags,
1277
           SymbolStringPtr InitSymbol);
1278
 
1279
  SymbolNameSet getRequestedSymbols(const SymbolFlagsMap &SymbolFlags) const;
1280
 
1281
  void addDependencies(const SymbolStringPtr &Name,
1282
                       const SymbolDependenceMap &Dependants);
1283
 
1284
  Error resolve(MaterializationResponsibility &MR, const SymbolMap &Resolved);
1285
 
1286
  Error emit(MaterializationResponsibility &MR, const SymbolFlagsMap &Emitted);
1287
 
1288
  void unlinkMaterializationResponsibility(MaterializationResponsibility &MR);
1289
 
1290
  using FailedSymbolsWorklist =
1291
      std::vector<std::pair<JITDylib *, SymbolStringPtr>>;
1292
 
1293
  static std::pair<AsynchronousSymbolQuerySet,
1294
                   std::shared_ptr<SymbolDependenceMap>>
1295
      failSymbols(FailedSymbolsWorklist);
1296
 
1297
  ExecutionSession &ES;
1298
  enum { Open, Closing, Closed } State = Open;
1299
  std::mutex GeneratorsMutex;
1300
  SymbolTable Symbols;
1301
  UnmaterializedInfosMap UnmaterializedInfos;
1302
  MaterializingInfosMap MaterializingInfos;
1303
  std::vector<std::shared_ptr<DefinitionGenerator>> DefGenerators;
1304
  JITDylibSearchOrder LinkOrder;
1305
  ResourceTrackerSP DefaultTracker;
1306
 
1307
  // Map trackers to sets of symbols tracked.
1308
  DenseMap<ResourceTracker *, SymbolNameVector> TrackerSymbols;
1309
  DenseMap<ResourceTracker *, DenseSet<MaterializationResponsibility *>>
1310
      TrackerMRs;
1311
};
1312
 
1313
/// Platforms set up standard symbols and mediate interactions between dynamic
1314
/// initializers (e.g. C++ static constructors) and ExecutionSession state.
1315
/// Note that Platforms do not automatically run initializers: clients are still
1316
/// responsible for doing this.
1317
class Platform {
1318
public:
1319
  virtual ~Platform();
1320
 
1321
  /// This method will be called outside the session lock each time a JITDylib
1322
  /// is created (unless it is created with EmptyJITDylib set) to allow the
1323
  /// Platform to install any JITDylib specific standard symbols (e.g
1324
  /// __dso_handle).
1325
  virtual Error setupJITDylib(JITDylib &JD) = 0;
1326
 
1327
  /// This method will be called outside the session lock each time a JITDylib
1328
  /// is removed to allow the Platform to remove any JITDylib-specific data.
1329
  virtual Error teardownJITDylib(JITDylib &JD) = 0;
1330
 
1331
  /// This method will be called under the ExecutionSession lock each time a
1332
  /// MaterializationUnit is added to a JITDylib.
1333
  virtual Error notifyAdding(ResourceTracker &RT,
1334
                             const MaterializationUnit &MU) = 0;
1335
 
1336
  /// This method will be called under the ExecutionSession lock when a
1337
  /// ResourceTracker is removed.
1338
  virtual Error notifyRemoving(ResourceTracker &RT) = 0;
1339
 
1340
  /// A utility function for looking up initializer symbols. Performs a blocking
1341
  /// lookup for the given symbols in each of the given JITDylibs.
1342
  ///
1343
  /// Note: This function is deprecated and will be removed in the near future.
1344
  static Expected<DenseMap<JITDylib *, SymbolMap>>
1345
  lookupInitSymbols(ExecutionSession &ES,
1346
                    const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms);
1347
 
1348
  /// Performs an async lookup for the given symbols in each of the given
1349
  /// JITDylibs, calling the given handler once all lookups have completed.
1350
  static void
1351
  lookupInitSymbolsAsync(unique_function<void(Error)> OnComplete,
1352
                         ExecutionSession &ES,
1353
                         const DenseMap<JITDylib *, SymbolLookupSet> &InitSyms);
1354
};
1355
 
1356
/// A materialization task.
1357
class MaterializationTask : public RTTIExtends<MaterializationTask, Task> {
1358
public:
1359
  static char ID;
1360
 
1361
  MaterializationTask(std::unique_ptr<MaterializationUnit> MU,
1362
                      std::unique_ptr<MaterializationResponsibility> MR)
1363
      : MU(std::move(MU)), MR(std::move(MR)) {}
1364
  void printDescription(raw_ostream &OS) override;
1365
  void run() override;
1366
 
1367
private:
1368
  std::unique_ptr<MaterializationUnit> MU;
1369
  std::unique_ptr<MaterializationResponsibility> MR;
1370
};
1371
 
1372
/// An ExecutionSession represents a running JIT program.
1373
class ExecutionSession {
1374
  friend class InProgressLookupFlagsState;
1375
  friend class InProgressFullLookupState;
1376
  friend class JITDylib;
1377
  friend class LookupState;
1378
  friend class MaterializationResponsibility;
1379
  friend class ResourceTracker;
1380
 
1381
public:
1382
  /// For reporting errors.
1383
  using ErrorReporter = std::function<void(Error)>;
1384
 
1385
  /// Send a result to the remote.
1386
  using SendResultFunction = unique_function<void(shared::WrapperFunctionResult)>;
1387
 
1388
  /// For dispatching ORC tasks (typically materialization tasks).
1389
  using DispatchTaskFunction = unique_function<void(std::unique_ptr<Task> T)>;
1390
 
1391
  /// An asynchronous wrapper-function callable from the executor via
1392
  /// jit-dispatch.
1393
  using JITDispatchHandlerFunction = unique_function<void(
1394
      SendResultFunction SendResult,
1395
      const char *ArgData, size_t ArgSize)>;
1396
 
1397
  /// A map associating tag names with asynchronous wrapper function
1398
  /// implementations in the JIT.
1399
  using JITDispatchHandlerAssociationMap =
1400
      DenseMap<SymbolStringPtr, JITDispatchHandlerFunction>;
1401
 
1402
  /// Construct an ExecutionSession with the given ExecutorProcessControl
1403
  /// object.
1404
  ExecutionSession(std::unique_ptr<ExecutorProcessControl> EPC);
1405
 
1406
  /// Destroy an ExecutionSession. Verifies that endSession was called prior to
1407
  /// destruction.
1408
  ~ExecutionSession();
1409
 
1410
  /// End the session. Closes all JITDylibs and disconnects from the
1411
  /// executor. Clients must call this method before destroying the session.
1412
  Error endSession();
1413
 
1414
  /// Get the ExecutorProcessControl object associated with this
1415
  /// ExecutionSession.
1416
  ExecutorProcessControl &getExecutorProcessControl() { return *EPC; }
1417
 
1418
  /// Get the SymbolStringPool for this instance.
1419
  std::shared_ptr<SymbolStringPool> getSymbolStringPool() {
1420
    return EPC->getSymbolStringPool();
1421
  }
1422
 
1423
  /// Add a symbol name to the SymbolStringPool and return a pointer to it.
1424
  SymbolStringPtr intern(StringRef SymName) { return EPC->intern(SymName); }
1425
 
1426
  /// Set the Platform for this ExecutionSession.
1427
  void setPlatform(std::unique_ptr<Platform> P) { this->P = std::move(P); }
1428
 
1429
  /// Get the Platform for this session.
1430
  /// Will return null if no Platform has been set for this ExecutionSession.
1431
  Platform *getPlatform() { return P.get(); }
1432
 
1433
  /// Run the given lambda with the session mutex locked.
1434
  template <typename Func> decltype(auto) runSessionLocked(Func &&F) {
1435
    std::lock_guard<std::recursive_mutex> Lock(SessionMutex);
1436
    return F();
1437
  }
1438
 
1439
  /// Register the given ResourceManager with this ExecutionSession.
1440
  /// Managers will be notified of events in reverse order of registration.
1441
  void registerResourceManager(ResourceManager &RM);
1442
 
1443
  /// Deregister the given ResourceManager with this ExecutionSession.
1444
  /// Manager must have been previously registered.
1445
  void deregisterResourceManager(ResourceManager &RM);
1446
 
1447
  /// Return a pointer to the "name" JITDylib.
1448
  /// Ownership of JITDylib remains within Execution Session
1449
  JITDylib *getJITDylibByName(StringRef Name);
1450
 
1451
  /// Add a new bare JITDylib to this ExecutionSession.
1452
  ///
1453
  /// The JITDylib Name is required to be unique. Clients should verify that
1454
  /// names are not being re-used (E.g. by calling getJITDylibByName) if names
1455
  /// are based on user input.
1456
  ///
1457
  /// This call does not install any library code or symbols into the newly
1458
  /// created JITDylib. The client is responsible for all configuration.
1459
  JITDylib &createBareJITDylib(std::string Name);
1460
 
1461
  /// Add a new JITDylib to this ExecutionSession.
1462
  ///
1463
  /// The JITDylib Name is required to be unique. Clients should verify that
1464
  /// names are not being re-used (e.g. by calling getJITDylibByName) if names
1465
  /// are based on user input.
1466
  ///
1467
  /// If a Platform is attached then Platform::setupJITDylib will be called to
1468
  /// install standard platform symbols (e.g. standard library interposes).
1469
  /// If no Platform is attached this call is equivalent to createBareJITDylib.
1470
  Expected<JITDylib &> createJITDylib(std::string Name);
1471
 
1472
  /// Closes the given JITDylib.
1473
  ///
1474
  /// This method clears all resources held for the JITDylib, puts it in the
1475
  /// closed state, and clears all references held by the ExecutionSession and
1476
  /// other JITDylibs. No further code can be added to the JITDylib, and the
1477
  /// object will be freed once any remaining JITDylibSPs to it are destroyed.
1478
  ///
1479
  /// This method does *not* run static destructors.
1480
  ///
1481
  /// This method can only be called once for each JITDylib.
1482
  Error removeJITDylib(JITDylib &JD);
1483
 
1484
  /// Set the error reporter function.
1485
  ExecutionSession &setErrorReporter(ErrorReporter ReportError) {
1486
    this->ReportError = std::move(ReportError);
1487
    return *this;
1488
  }
1489
 
1490
  /// Report a error for this execution session.
1491
  ///
1492
  /// Unhandled errors can be sent here to log them.
1493
  void reportError(Error Err) { ReportError(std::move(Err)); }
1494
 
1495
  /// Set the task dispatch function.
1496
  ExecutionSession &setDispatchTask(DispatchTaskFunction DispatchTask) {
1497
    this->DispatchTask = std::move(DispatchTask);
1498
    return *this;
1499
  }
1500
 
1501
  /// Search the given JITDylibs to find the flags associated with each of the
1502
  /// given symbols.
1503
  void lookupFlags(LookupKind K, JITDylibSearchOrder SearchOrder,
1504
                   SymbolLookupSet Symbols,
1505
                   unique_function<void(Expected<SymbolFlagsMap>)> OnComplete);
1506
 
1507
  /// Blocking version of lookupFlags.
1508
  Expected<SymbolFlagsMap> lookupFlags(LookupKind K,
1509
                                       JITDylibSearchOrder SearchOrder,
1510
                                       SymbolLookupSet Symbols);
1511
 
1512
  /// Search the given JITDylibs for the given symbols.
1513
  ///
1514
  /// SearchOrder lists the JITDylibs to search. For each dylib, the associated
1515
  /// boolean indicates whether the search should match against non-exported
1516
  /// (hidden visibility) symbols in that dylib (true means match against
1517
  /// non-exported symbols, false means do not match).
1518
  ///
1519
  /// The NotifyComplete callback will be called once all requested symbols
1520
  /// reach the required state.
1521
  ///
1522
  /// If all symbols are found, the RegisterDependencies function will be called
1523
  /// while the session lock is held. This gives clients a chance to register
1524
  /// dependencies for on the queried symbols for any symbols they are
1525
  /// materializing (if a MaterializationResponsibility instance is present,
1526
  /// this can be implemented by calling
1527
  /// MaterializationResponsibility::addDependencies). If there are no
1528
  /// dependenant symbols for this query (e.g. it is being made by a top level
1529
  /// client to get an address to call) then the value NoDependenciesToRegister
1530
  /// can be used.
1531
  void lookup(LookupKind K, const JITDylibSearchOrder &SearchOrder,
1532
              SymbolLookupSet Symbols, SymbolState RequiredState,
1533
              SymbolsResolvedCallback NotifyComplete,
1534
              RegisterDependenciesFunction RegisterDependencies);
1535
 
1536
  /// Blocking version of lookup above. Returns the resolved symbol map.
1537
  /// If WaitUntilReady is true (the default), will not return until all
1538
  /// requested symbols are ready (or an error occurs). If WaitUntilReady is
1539
  /// false, will return as soon as all requested symbols are resolved,
1540
  /// or an error occurs. If WaitUntilReady is false and an error occurs
1541
  /// after resolution, the function will return a success value, but the
1542
  /// error will be reported via reportErrors.
1543
  Expected<SymbolMap> lookup(const JITDylibSearchOrder &SearchOrder,
1544
                             SymbolLookupSet Symbols,
1545
                             LookupKind K = LookupKind::Static,
1546
                             SymbolState RequiredState = SymbolState::Ready,
1547
                             RegisterDependenciesFunction RegisterDependencies =
1548
                                 NoDependenciesToRegister);
1549
 
1550
  /// Convenience version of blocking lookup.
1551
  /// Searches each of the JITDylibs in the search order in turn for the given
1552
  /// symbol.
1553
  Expected<JITEvaluatedSymbol>
1554
  lookup(const JITDylibSearchOrder &SearchOrder, SymbolStringPtr Symbol,
1555
         SymbolState RequiredState = SymbolState::Ready);
1556
 
1557
  /// Convenience version of blocking lookup.
1558
  /// Searches each of the JITDylibs in the search order in turn for the given
1559
  /// symbol. The search will not find non-exported symbols.
1560
  Expected<JITEvaluatedSymbol>
1561
  lookup(ArrayRef<JITDylib *> SearchOrder, SymbolStringPtr Symbol,
1562
         SymbolState RequiredState = SymbolState::Ready);
1563
 
1564
  /// Convenience version of blocking lookup.
1565
  /// Searches each of the JITDylibs in the search order in turn for the given
1566
  /// symbol. The search will not find non-exported symbols.
1567
  Expected<JITEvaluatedSymbol>
1568
  lookup(ArrayRef<JITDylib *> SearchOrder, StringRef Symbol,
1569
         SymbolState RequiredState = SymbolState::Ready);
1570
 
1571
  /// Materialize the given unit.
1572
  void dispatchTask(std::unique_ptr<Task> T) {
1573
    assert(T && "T must be non-null");
1574
    DEBUG_WITH_TYPE("orc", dumpDispatchInfo(*T));
1575
    DispatchTask(std::move(T));
1576
  }
1577
 
1578
  /// Run a wrapper function in the executor.
1579
  ///
1580
  /// The wrapper function should be callable as:
1581
  ///
1582
  /// \code{.cpp}
1583
  ///   CWrapperFunctionResult fn(uint8_t *Data, uint64_t Size);
1584
  /// \endcode{.cpp}
1585
  ///
1586
  /// The given OnComplete function will be called to return the result.
1587
  template <typename... ArgTs>
1588
  void callWrapperAsync(ArgTs &&... Args) {
1589
    EPC->callWrapperAsync(std::forward<ArgTs>(Args)...);
1590
  }
1591
 
1592
  /// Run a wrapper function in the executor. The wrapper function should be
1593
  /// callable as:
1594
  ///
1595
  /// \code{.cpp}
1596
  ///   CWrapperFunctionResult fn(uint8_t *Data, uint64_t Size);
1597
  /// \endcode{.cpp}
1598
  shared::WrapperFunctionResult callWrapper(ExecutorAddr WrapperFnAddr,
1599
                                            ArrayRef<char> ArgBuffer) {
1600
    return EPC->callWrapper(WrapperFnAddr, ArgBuffer);
1601
  }
1602
 
1603
  /// Run a wrapper function using SPS to serialize the arguments and
1604
  /// deserialize the results.
1605
  template <typename SPSSignature, typename SendResultT, typename... ArgTs>
1606
  void callSPSWrapperAsync(ExecutorAddr WrapperFnAddr, SendResultT &&SendResult,
1607
                           const ArgTs &...Args) {
1608
    EPC->callSPSWrapperAsync<SPSSignature, SendResultT, ArgTs...>(
1609
        WrapperFnAddr, std::forward<SendResultT>(SendResult), Args...);
1610
  }
1611
 
1612
  /// Run a wrapper function using SPS to serialize the arguments and
1613
  /// deserialize the results.
1614
  ///
1615
  /// If SPSSignature is a non-void function signature then the second argument
1616
  /// (the first in the Args list) should be a reference to a return value.
1617
  template <typename SPSSignature, typename... WrapperCallArgTs>
1618
  Error callSPSWrapper(ExecutorAddr WrapperFnAddr,
1619
                       WrapperCallArgTs &&...WrapperCallArgs) {
1620
    return EPC->callSPSWrapper<SPSSignature, WrapperCallArgTs...>(
1621
        WrapperFnAddr, std::forward<WrapperCallArgTs>(WrapperCallArgs)...);
1622
  }
1623
 
1624
  /// Wrap a handler that takes concrete argument types (and a sender for a
1625
  /// concrete return type) to produce an AsyncHandlerWrapperFunction. Uses SPS
1626
  /// to unpack the arguments and pack the result.
1627
  ///
1628
  /// This function is intended to support easy construction of
1629
  /// AsyncHandlerWrapperFunctions that can be associated with a tag
1630
  /// (using registerJITDispatchHandler) and called from the executor.
1631
  template <typename SPSSignature, typename HandlerT>
1632
  static JITDispatchHandlerFunction wrapAsyncWithSPS(HandlerT &&H) {
1633
    return [H = std::forward<HandlerT>(H)](
1634
               SendResultFunction SendResult,
1635
               const char *ArgData, size_t ArgSize) mutable {
1636
      shared::WrapperFunction<SPSSignature>::handleAsync(ArgData, ArgSize, H,
1637
                                                         std::move(SendResult));
1638
    };
1639
  }
1640
 
1641
  /// Wrap a class method that takes concrete argument types (and a sender for
1642
  /// a concrete return type) to produce an AsyncHandlerWrapperFunction. Uses
1643
  /// SPS to unpack teh arguments and pack the result.
1644
  ///
1645
  /// This function is intended to support easy construction of
1646
  /// AsyncHandlerWrapperFunctions that can be associated with a tag
1647
  /// (using registerJITDispatchHandler) and called from the executor.
1648
  template <typename SPSSignature, typename ClassT, typename... MethodArgTs>
1649
  static JITDispatchHandlerFunction
1650
  wrapAsyncWithSPS(ClassT *Instance, void (ClassT::*Method)(MethodArgTs...)) {
1651
    return wrapAsyncWithSPS<SPSSignature>(
1652
        [Instance, Method](MethodArgTs &&...MethodArgs) {
1653
          (Instance->*Method)(std::forward<MethodArgTs>(MethodArgs)...);
1654
        });
1655
  }
1656
 
1657
  /// For each tag symbol name, associate the corresponding
1658
  /// AsyncHandlerWrapperFunction with the address of that symbol. The
1659
  /// handler becomes callable from the executor using the ORC runtime
1660
  /// __orc_rt_jit_dispatch function and the given tag.
1661
  ///
1662
  /// Tag symbols will be looked up in JD using LookupKind::Static,
1663
  /// JITDylibLookupFlags::MatchAllSymbols (hidden tags will be found), and
1664
  /// LookupFlags::WeaklyReferencedSymbol. Missing tag definitions will not
1665
  /// cause an error, the handler will simply be dropped.
1666
  Error registerJITDispatchHandlers(JITDylib &JD,
1667
                                    JITDispatchHandlerAssociationMap WFs);
1668
 
1669
  /// Run a registered jit-side wrapper function.
1670
  /// This should be called by the ExecutorProcessControl instance in response
1671
  /// to incoming jit-dispatch requests from the executor.
1672
  void
1673
  runJITDispatchHandler(SendResultFunction SendResult,
1674
                        JITTargetAddress HandlerFnTagAddr,
1675
                        ArrayRef<char> ArgBuffer);
1676
 
1677
  /// Dump the state of all the JITDylibs in this session.
1678
  void dump(raw_ostream &OS);
1679
 
1680
private:
1681
  static void logErrorsToStdErr(Error Err) {
1682
    logAllUnhandledErrors(std::move(Err), errs(), "JIT session error: ");
1683
  }
1684
 
1685
  static void runOnCurrentThread(std::unique_ptr<Task> T) { T->run(); }
1686
 
1687
  void dispatchOutstandingMUs();
1688
 
1689
  static std::unique_ptr<MaterializationResponsibility>
1690
  createMaterializationResponsibility(ResourceTracker &RT,
1691
                                      SymbolFlagsMap Symbols,
1692
                                      SymbolStringPtr InitSymbol) {
1693
    auto &JD = RT.getJITDylib();
1694
    std::unique_ptr<MaterializationResponsibility> MR(
1695
        new MaterializationResponsibility(&RT, std::move(Symbols),
1696
                                          std::move(InitSymbol)));
1697
    JD.TrackerMRs[&RT].insert(MR.get());
1698
    return MR;
1699
  }
1700
 
1701
  Error removeResourceTracker(ResourceTracker &RT);
1702
  void transferResourceTracker(ResourceTracker &DstRT, ResourceTracker &SrcRT);
1703
  void destroyResourceTracker(ResourceTracker &RT);
1704
 
1705
  // State machine functions for query application..
1706
 
1707
  /// IL_updateCandidatesFor is called to remove already-defined symbols that
1708
  /// match a given query from the set of candidate symbols to generate
1709
  /// definitions for (no need to generate a definition if one already exists).
1710
  Error IL_updateCandidatesFor(JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
1711
                               SymbolLookupSet &Candidates,
1712
                               SymbolLookupSet *NonCandidates);
1713
 
1714
  /// OL_applyQueryPhase1 is an optionally re-startable loop for triggering
1715
  /// definition generation. It is called when a lookup is performed, and again
1716
  /// each time that LookupState::continueLookup is called.
1717
  void OL_applyQueryPhase1(std::unique_ptr<InProgressLookupState> IPLS,
1718
                           Error Err);
1719
 
1720
  /// OL_completeLookup is run once phase 1 successfully completes for a lookup
1721
  /// call. It attempts to attach the symbol to all symbol table entries and
1722
  /// collect all MaterializationUnits to dispatch. If this method fails then
1723
  /// all MaterializationUnits will be left un-materialized.
1724
  void OL_completeLookup(std::unique_ptr<InProgressLookupState> IPLS,
1725
                         std::shared_ptr<AsynchronousSymbolQuery> Q,
1726
                         RegisterDependenciesFunction RegisterDependencies);
1727
 
1728
  /// OL_completeLookupFlags is run once phase 1 successfully completes for a
1729
  /// lookupFlags call.
1730
  void OL_completeLookupFlags(
1731
      std::unique_ptr<InProgressLookupState> IPLS,
1732
      unique_function<void(Expected<SymbolFlagsMap>)> OnComplete);
1733
 
1734
  // State machine functions for MaterializationResponsibility.
1735
  void OL_destroyMaterializationResponsibility(
1736
      MaterializationResponsibility &MR);
1737
  SymbolNameSet OL_getRequestedSymbols(const MaterializationResponsibility &MR);
1738
  Error OL_notifyResolved(MaterializationResponsibility &MR,
1739
                          const SymbolMap &Symbols);
1740
  Error OL_notifyEmitted(MaterializationResponsibility &MR);
1741
  Error OL_defineMaterializing(MaterializationResponsibility &MR,
1742
                               SymbolFlagsMap SymbolFlags);
1743
  void OL_notifyFailed(MaterializationResponsibility &MR);
1744
  Error OL_replace(MaterializationResponsibility &MR,
1745
                   std::unique_ptr<MaterializationUnit> MU);
1746
  Expected<std::unique_ptr<MaterializationResponsibility>>
1747
  OL_delegate(MaterializationResponsibility &MR, const SymbolNameSet &Symbols);
1748
  void OL_addDependencies(MaterializationResponsibility &MR,
1749
                          const SymbolStringPtr &Name,
1750
                          const SymbolDependenceMap &Dependencies);
1751
  void OL_addDependenciesForAll(MaterializationResponsibility &MR,
1752
                                const SymbolDependenceMap &Dependencies);
1753
 
1754
#ifndef NDEBUG
1755
  void dumpDispatchInfo(Task &T);
1756
#endif // NDEBUG
1757
 
1758
  mutable std::recursive_mutex SessionMutex;
1759
  bool SessionOpen = true;
1760
  std::unique_ptr<ExecutorProcessControl> EPC;
1761
  std::unique_ptr<Platform> P;
1762
  ErrorReporter ReportError = logErrorsToStdErr;
1763
  DispatchTaskFunction DispatchTask = runOnCurrentThread;
1764
 
1765
  std::vector<ResourceManager *> ResourceManagers;
1766
 
1767
  std::vector<JITDylibSP> JDs;
1768
 
1769
  // FIXME: Remove this (and runOutstandingMUs) once the linking layer works
1770
  //        with callbacks from asynchronous queries.
1771
  mutable std::recursive_mutex OutstandingMUsMutex;
1772
  std::vector<std::pair<std::unique_ptr<MaterializationUnit>,
1773
                        std::unique_ptr<MaterializationResponsibility>>>
1774
      OutstandingMUs;
1775
 
1776
  mutable std::mutex JITDispatchHandlersMutex;
1777
  DenseMap<JITTargetAddress, std::shared_ptr<JITDispatchHandlerFunction>>
1778
      JITDispatchHandlers;
1779
};
1780
 
1781
template <typename Func> Error ResourceTracker::withResourceKeyDo(Func &&F) {
1782
  return getJITDylib().getExecutionSession().runSessionLocked([&]() -> Error {
1783
    if (isDefunct())
1784
      return make_error<ResourceTrackerDefunct>(this);
1785
    F(getKeyUnsafe());
1786
    return Error::success();
1787
  });
1788
}
1789
 
1790
inline ExecutionSession &
1791
MaterializationResponsibility::getExecutionSession() const {
1792
  return JD.getExecutionSession();
1793
}
1794
 
1795
template <typename GeneratorT>
1796
GeneratorT &JITDylib::addGenerator(std::unique_ptr<GeneratorT> DefGenerator) {
1797
  auto &G = *DefGenerator;
1798
  ES.runSessionLocked([&] {
1799
    assert(State == Open && "Cannot add generator to closed JITDylib");
1800
    DefGenerators.push_back(std::move(DefGenerator));
1801
  });
1802
  return G;
1803
}
1804
 
1805
template <typename Func>
1806
auto JITDylib::withLinkOrderDo(Func &&F)
1807
    -> decltype(F(std::declval<const JITDylibSearchOrder &>())) {
1808
  assert(State == Open && "Cannot use link order of closed JITDylib");
1809
  return ES.runSessionLocked([&]() { return F(LinkOrder); });
1810
}
1811
 
1812
template <typename MaterializationUnitType>
1813
Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU,
1814
                       ResourceTrackerSP RT) {
1815
  assert(MU && "Can not define with a null MU");
1816
 
1817
  if (MU->getSymbols().empty()) {
1818
    // Empty MUs are allowable but pathological, so issue a warning.
1819
    DEBUG_WITH_TYPE("orc", {
1820
      dbgs() << "Warning: Discarding empty MU " << MU->getName() << " for "
1821
             << getName() << "\n";
1822
    });
1823
    return Error::success();
1824
  } else
1825
    DEBUG_WITH_TYPE("orc", {
1826
      dbgs() << "Defining MU " << MU->getName() << " for " << getName()
1827
             << " (tracker: ";
1828
      if (RT == getDefaultResourceTracker())
1829
        dbgs() << "default)";
1830
      else if (RT)
1831
        dbgs() << RT.get() << ")\n";
1832
      else
1833
        dbgs() << "0x0, default will be used)\n";
1834
    });
1835
 
1836
  return ES.runSessionLocked([&, this]() -> Error {
1837
    assert(State == Open && "JD is defunct");
1838
 
1839
    if (auto Err = defineImpl(*MU))
1840
      return Err;
1841
 
1842
    if (!RT)
1843
      RT = getDefaultResourceTracker();
1844
 
1845
    if (auto *P = ES.getPlatform()) {
1846
      if (auto Err = P->notifyAdding(*RT, *MU))
1847
        return Err;
1848
    }
1849
 
1850
    installMaterializationUnit(std::move(MU), *RT);
1851
    return Error::success();
1852
  });
1853
}
1854
 
1855
template <typename MaterializationUnitType>
1856
Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU,
1857
                       ResourceTrackerSP RT) {
1858
  assert(MU && "Can not define with a null MU");
1859
 
1860
  if (MU->getSymbols().empty()) {
1861
    // Empty MUs are allowable but pathological, so issue a warning.
1862
    DEBUG_WITH_TYPE("orc", {
1863
      dbgs() << "Warning: Discarding empty MU " << MU->getName() << getName()
1864
             << "\n";
1865
    });
1866
    return Error::success();
1867
  } else
1868
    DEBUG_WITH_TYPE("orc", {
1869
      dbgs() << "Defining MU " << MU->getName() << " for " << getName()
1870
             << " (tracker: ";
1871
      if (RT == getDefaultResourceTracker())
1872
        dbgs() << "default)";
1873
      else if (RT)
1874
        dbgs() << RT.get() << ")\n";
1875
      else
1876
        dbgs() << "0x0, default will be used)\n";
1877
    });
1878
 
1879
  return ES.runSessionLocked([&, this]() -> Error {
1880
    assert(State == Open && "JD is defunct");
1881
 
1882
    if (auto Err = defineImpl(*MU))
1883
      return Err;
1884
 
1885
    if (!RT)
1886
      RT = getDefaultResourceTracker();
1887
 
1888
    if (auto *P = ES.getPlatform()) {
1889
      if (auto Err = P->notifyAdding(*RT, *MU))
1890
        return Err;
1891
    }
1892
 
1893
    installMaterializationUnit(std::move(MU), *RT);
1894
    return Error::success();
1895
  });
1896
}
1897
 
1898
/// ReexportsGenerator can be used with JITDylib::addGenerator to automatically
1899
/// re-export a subset of the source JITDylib's symbols in the target.
1900
class ReexportsGenerator : public DefinitionGenerator {
1901
public:
1902
  using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
1903
 
1904
  /// Create a reexports generator. If an Allow predicate is passed, only
1905
  /// symbols for which the predicate returns true will be reexported. If no
1906
  /// Allow predicate is passed, all symbols will be exported.
1907
  ReexportsGenerator(JITDylib &SourceJD,
1908
                     JITDylibLookupFlags SourceJDLookupFlags,
1909
                     SymbolPredicate Allow = SymbolPredicate());
1910
 
1911
  Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
1912
                      JITDylibLookupFlags JDLookupFlags,
1913
                      const SymbolLookupSet &LookupSet) override;
1914
 
1915
private:
1916
  JITDylib &SourceJD;
1917
  JITDylibLookupFlags SourceJDLookupFlags;
1918
  SymbolPredicate Allow;
1919
};
1920
 
1921
// --------------- IMPLEMENTATION --------------
1922
// Implementations for inline functions/methods.
1923
// ---------------------------------------------
1924
 
1925
inline MaterializationResponsibility::~MaterializationResponsibility() {
1926
  getExecutionSession().OL_destroyMaterializationResponsibility(*this);
1927
}
1928
 
1929
inline SymbolNameSet MaterializationResponsibility::getRequestedSymbols() const {
1930
  return getExecutionSession().OL_getRequestedSymbols(*this);
1931
}
1932
 
1933
inline Error MaterializationResponsibility::notifyResolved(
1934
    const SymbolMap &Symbols) {
1935
  return getExecutionSession().OL_notifyResolved(*this, Symbols);
1936
}
1937
 
1938
inline Error MaterializationResponsibility::notifyEmitted() {
1939
  return getExecutionSession().OL_notifyEmitted(*this);
1940
}
1941
 
1942
inline Error MaterializationResponsibility::defineMaterializing(
1943
    SymbolFlagsMap SymbolFlags) {
1944
  return getExecutionSession().OL_defineMaterializing(*this,
1945
                                                      std::move(SymbolFlags));
1946
}
1947
 
1948
inline void MaterializationResponsibility::failMaterialization() {
1949
  getExecutionSession().OL_notifyFailed(*this);
1950
}
1951
 
1952
inline Error MaterializationResponsibility::replace(
1953
    std::unique_ptr<MaterializationUnit> MU) {
1954
  return getExecutionSession().OL_replace(*this, std::move(MU));
1955
}
1956
 
1957
inline Expected<std::unique_ptr<MaterializationResponsibility>>
1958
MaterializationResponsibility::delegate(const SymbolNameSet &Symbols) {
1959
  return getExecutionSession().OL_delegate(*this, Symbols);
1960
}
1961
 
1962
inline void MaterializationResponsibility::addDependencies(
1963
    const SymbolStringPtr &Name, const SymbolDependenceMap &Dependencies) {
1964
  getExecutionSession().OL_addDependencies(*this, Name, Dependencies);
1965
}
1966
 
1967
inline void MaterializationResponsibility::addDependenciesForAll(
1968
    const SymbolDependenceMap &Dependencies) {
1969
  getExecutionSession().OL_addDependenciesForAll(*this, Dependencies);
1970
}
1971
 
1972
} // End namespace orc
1973
} // End namespace llvm
1974
 
1975
#endif // LLVM_EXECUTIONENGINE_ORC_CORE_H