Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
35266 views
1
//===------- ObjectLinkingLayer.cpp - JITLink backed ORC ObjectLayer ------===//
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
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
10
#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
11
#include "llvm/ExecutionEngine/JITLink/aarch32.h"
12
#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
13
#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
14
#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
15
#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
16
#include "llvm/Support/MemoryBuffer.h"
17
#include <string>
18
#include <vector>
19
20
#define DEBUG_TYPE "orc"
21
22
using namespace llvm;
23
using namespace llvm::jitlink;
24
using namespace llvm::orc;
25
26
namespace {
27
28
bool hasInitializerSection(jitlink::LinkGraph &G) {
29
bool IsMachO = G.getTargetTriple().isOSBinFormatMachO();
30
bool IsElf = G.getTargetTriple().isOSBinFormatELF();
31
if (!IsMachO && !IsElf)
32
return false;
33
34
for (auto &Sec : G.sections()) {
35
if (IsMachO && isMachOInitializerSection(Sec.getName()))
36
return true;
37
if (IsElf && isELFInitializerSection(Sec.getName()))
38
return true;
39
}
40
41
return false;
42
}
43
44
ExecutorAddr getJITSymbolPtrForSymbol(Symbol &Sym, const Triple &TT) {
45
switch (TT.getArch()) {
46
case Triple::arm:
47
case Triple::armeb:
48
case Triple::thumb:
49
case Triple::thumbeb:
50
if (hasTargetFlags(Sym, aarch32::ThumbSymbol)) {
51
// Set LSB to indicate thumb target
52
assert(Sym.isCallable() && "Only callable symbols can have thumb flag");
53
assert((Sym.getAddress().getValue() & 0x01) == 0 && "LSB is clear");
54
return Sym.getAddress() + 0x01;
55
}
56
return Sym.getAddress();
57
default:
58
return Sym.getAddress();
59
}
60
}
61
62
JITSymbolFlags getJITSymbolFlagsForSymbol(Symbol &Sym) {
63
JITSymbolFlags Flags;
64
65
if (Sym.getLinkage() == Linkage::Weak)
66
Flags |= JITSymbolFlags::Weak;
67
68
if (Sym.getScope() == Scope::Default)
69
Flags |= JITSymbolFlags::Exported;
70
71
if (Sym.isCallable())
72
Flags |= JITSymbolFlags::Callable;
73
74
return Flags;
75
}
76
77
class LinkGraphMaterializationUnit : public MaterializationUnit {
78
public:
79
static std::unique_ptr<LinkGraphMaterializationUnit>
80
Create(ObjectLinkingLayer &ObjLinkingLayer, std::unique_ptr<LinkGraph> G) {
81
auto LGI = scanLinkGraph(ObjLinkingLayer.getExecutionSession(), *G);
82
return std::unique_ptr<LinkGraphMaterializationUnit>(
83
new LinkGraphMaterializationUnit(ObjLinkingLayer, std::move(G),
84
std::move(LGI)));
85
}
86
87
StringRef getName() const override { return G->getName(); }
88
void materialize(std::unique_ptr<MaterializationResponsibility> MR) override {
89
ObjLinkingLayer.emit(std::move(MR), std::move(G));
90
}
91
92
private:
93
static Interface scanLinkGraph(ExecutionSession &ES, LinkGraph &G) {
94
95
Interface LGI;
96
97
auto AddSymbol = [&](Symbol *Sym) {
98
// Skip local symbols.
99
if (Sym->getScope() == Scope::Local)
100
return;
101
assert(Sym->hasName() && "Anonymous non-local symbol?");
102
103
LGI.SymbolFlags[ES.intern(Sym->getName())] =
104
getJITSymbolFlagsForSymbol(*Sym);
105
};
106
107
for (auto *Sym : G.defined_symbols())
108
AddSymbol(Sym);
109
for (auto *Sym : G.absolute_symbols())
110
AddSymbol(Sym);
111
112
if (hasInitializerSection(G))
113
LGI.InitSymbol = makeInitSymbol(ES, G);
114
115
return LGI;
116
}
117
118
static SymbolStringPtr makeInitSymbol(ExecutionSession &ES, LinkGraph &G) {
119
std::string InitSymString;
120
raw_string_ostream(InitSymString)
121
<< "$." << G.getName() << ".__inits" << Counter++;
122
return ES.intern(InitSymString);
123
}
124
125
LinkGraphMaterializationUnit(ObjectLinkingLayer &ObjLinkingLayer,
126
std::unique_ptr<LinkGraph> G, Interface LGI)
127
: MaterializationUnit(std::move(LGI)), ObjLinkingLayer(ObjLinkingLayer),
128
G(std::move(G)) {}
129
130
void discard(const JITDylib &JD, const SymbolStringPtr &Name) override {
131
for (auto *Sym : G->defined_symbols())
132
if (Sym->getName() == *Name) {
133
assert(Sym->getLinkage() == Linkage::Weak &&
134
"Discarding non-weak definition");
135
G->makeExternal(*Sym);
136
break;
137
}
138
}
139
140
ObjectLinkingLayer &ObjLinkingLayer;
141
std::unique_ptr<LinkGraph> G;
142
static std::atomic<uint64_t> Counter;
143
};
144
145
std::atomic<uint64_t> LinkGraphMaterializationUnit::Counter{0};
146
147
} // end anonymous namespace
148
149
namespace llvm {
150
namespace orc {
151
152
class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {
153
public:
154
ObjectLinkingLayerJITLinkContext(
155
ObjectLinkingLayer &Layer,
156
std::unique_ptr<MaterializationResponsibility> MR,
157
std::unique_ptr<MemoryBuffer> ObjBuffer)
158
: JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer),
159
MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {
160
std::lock_guard<std::mutex> Lock(Layer.LayerMutex);
161
Plugins = Layer.Plugins;
162
}
163
164
~ObjectLinkingLayerJITLinkContext() {
165
// If there is an object buffer return function then use it to
166
// return ownership of the buffer.
167
if (Layer.ReturnObjectBuffer && ObjBuffer)
168
Layer.ReturnObjectBuffer(std::move(ObjBuffer));
169
}
170
171
JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }
172
173
void notifyMaterializing(LinkGraph &G) {
174
for (auto &P : Plugins)
175
P->notifyMaterializing(*MR, G, *this,
176
ObjBuffer ? ObjBuffer->getMemBufferRef()
177
: MemoryBufferRef());
178
}
179
180
void notifyFailed(Error Err) override {
181
for (auto &P : Plugins)
182
Err = joinErrors(std::move(Err), P->notifyFailed(*MR));
183
Layer.getExecutionSession().reportError(std::move(Err));
184
MR->failMaterialization();
185
}
186
187
void lookup(const LookupMap &Symbols,
188
std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override {
189
190
JITDylibSearchOrder LinkOrder;
191
MR->getTargetJITDylib().withLinkOrderDo(
192
[&](const JITDylibSearchOrder &LO) { LinkOrder = LO; });
193
194
auto &ES = Layer.getExecutionSession();
195
196
SymbolLookupSet LookupSet;
197
for (auto &KV : Symbols) {
198
orc::SymbolLookupFlags LookupFlags;
199
switch (KV.second) {
200
case jitlink::SymbolLookupFlags::RequiredSymbol:
201
LookupFlags = orc::SymbolLookupFlags::RequiredSymbol;
202
break;
203
case jitlink::SymbolLookupFlags::WeaklyReferencedSymbol:
204
LookupFlags = orc::SymbolLookupFlags::WeaklyReferencedSymbol;
205
break;
206
}
207
LookupSet.add(ES.intern(KV.first), LookupFlags);
208
}
209
210
// OnResolve -- De-intern the symbols and pass the result to the linker.
211
auto OnResolve = [LookupContinuation =
212
std::move(LC)](Expected<SymbolMap> Result) mutable {
213
if (!Result)
214
LookupContinuation->run(Result.takeError());
215
else {
216
AsyncLookupResult LR;
217
for (auto &KV : *Result)
218
LR[*KV.first] = KV.second;
219
LookupContinuation->run(std::move(LR));
220
}
221
};
222
223
ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet),
224
SymbolState::Resolved, std::move(OnResolve),
225
[this](const SymbolDependenceMap &Deps) {
226
// Translate LookupDeps map to SymbolSourceJD.
227
for (auto &[DepJD, Deps] : Deps)
228
for (auto &DepSym : Deps)
229
SymbolSourceJDs[NonOwningSymbolStringPtr(DepSym)] = DepJD;
230
});
231
}
232
233
Error notifyResolved(LinkGraph &G) override {
234
auto &ES = Layer.getExecutionSession();
235
236
SymbolFlagsMap ExtraSymbolsToClaim;
237
bool AutoClaim = Layer.AutoClaimObjectSymbols;
238
239
SymbolMap InternedResult;
240
for (auto *Sym : G.defined_symbols())
241
if (Sym->hasName() && Sym->getScope() != Scope::Local) {
242
auto InternedName = ES.intern(Sym->getName());
243
auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple());
244
auto Flags = getJITSymbolFlagsForSymbol(*Sym);
245
InternedResult[InternedName] = {Ptr, Flags};
246
if (AutoClaim && !MR->getSymbols().count(InternedName)) {
247
assert(!ExtraSymbolsToClaim.count(InternedName) &&
248
"Duplicate symbol to claim?");
249
ExtraSymbolsToClaim[InternedName] = Flags;
250
}
251
}
252
253
for (auto *Sym : G.absolute_symbols())
254
if (Sym->hasName() && Sym->getScope() != Scope::Local) {
255
auto InternedName = ES.intern(Sym->getName());
256
auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple());
257
auto Flags = getJITSymbolFlagsForSymbol(*Sym);
258
InternedResult[InternedName] = {Ptr, Flags};
259
if (AutoClaim && !MR->getSymbols().count(InternedName)) {
260
assert(!ExtraSymbolsToClaim.count(InternedName) &&
261
"Duplicate symbol to claim?");
262
ExtraSymbolsToClaim[InternedName] = Flags;
263
}
264
}
265
266
if (!ExtraSymbolsToClaim.empty())
267
if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim))
268
return Err;
269
270
{
271
272
// Check that InternedResult matches up with MR->getSymbols(), overriding
273
// flags if requested.
274
// This guards against faulty transformations / compilers / object caches.
275
276
// First check that there aren't any missing symbols.
277
size_t NumMaterializationSideEffectsOnlySymbols = 0;
278
SymbolNameVector ExtraSymbols;
279
SymbolNameVector MissingSymbols;
280
for (auto &KV : MR->getSymbols()) {
281
282
auto I = InternedResult.find(KV.first);
283
284
// If this is a materialization-side-effects only symbol then bump
285
// the counter and make sure it's *not* defined, otherwise make
286
// sure that it is defined.
287
if (KV.second.hasMaterializationSideEffectsOnly()) {
288
++NumMaterializationSideEffectsOnlySymbols;
289
if (I != InternedResult.end())
290
ExtraSymbols.push_back(KV.first);
291
continue;
292
} else if (I == InternedResult.end())
293
MissingSymbols.push_back(KV.first);
294
else if (Layer.OverrideObjectFlags)
295
I->second.setFlags(KV.second);
296
}
297
298
// If there were missing symbols then report the error.
299
if (!MissingSymbols.empty())
300
return make_error<MissingSymbolDefinitions>(
301
Layer.getExecutionSession().getSymbolStringPool(), G.getName(),
302
std::move(MissingSymbols));
303
304
// If there are more definitions than expected, add them to the
305
// ExtraSymbols vector.
306
if (InternedResult.size() >
307
MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) {
308
for (auto &KV : InternedResult)
309
if (!MR->getSymbols().count(KV.first))
310
ExtraSymbols.push_back(KV.first);
311
}
312
313
// If there were extra definitions then report the error.
314
if (!ExtraSymbols.empty())
315
return make_error<UnexpectedSymbolDefinitions>(
316
Layer.getExecutionSession().getSymbolStringPool(), G.getName(),
317
std::move(ExtraSymbols));
318
}
319
320
if (auto Err = MR->notifyResolved(InternedResult))
321
return Err;
322
323
notifyLoaded();
324
return Error::success();
325
}
326
327
void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override {
328
if (auto Err = notifyEmitted(std::move(A))) {
329
Layer.getExecutionSession().reportError(std::move(Err));
330
MR->failMaterialization();
331
return;
332
}
333
if (auto Err = MR->notifyEmitted(SymbolDepGroups)) {
334
Layer.getExecutionSession().reportError(std::move(Err));
335
MR->failMaterialization();
336
}
337
}
338
339
LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override {
340
return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); };
341
}
342
343
Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override {
344
// Add passes to mark duplicate defs as should-discard, and to walk the
345
// link graph to build the symbol dependence graph.
346
Config.PrePrunePasses.push_back([this](LinkGraph &G) {
347
return claimOrExternalizeWeakAndCommonSymbols(G);
348
});
349
350
for (auto &P : Plugins)
351
P->modifyPassConfig(*MR, LG, Config);
352
353
Config.PreFixupPasses.push_back(
354
[this](LinkGraph &G) { return registerDependencies(G); });
355
356
return Error::success();
357
}
358
359
void notifyLoaded() {
360
for (auto &P : Plugins)
361
P->notifyLoaded(*MR);
362
}
363
364
Error notifyEmitted(jitlink::JITLinkMemoryManager::FinalizedAlloc FA) {
365
Error Err = Error::success();
366
for (auto &P : Plugins)
367
Err = joinErrors(std::move(Err), P->notifyEmitted(*MR));
368
369
if (Err) {
370
if (FA)
371
Err =
372
joinErrors(std::move(Err), Layer.MemMgr.deallocate(std::move(FA)));
373
return Err;
374
}
375
376
if (FA)
377
return Layer.recordFinalizedAlloc(*MR, std::move(FA));
378
379
return Error::success();
380
}
381
382
private:
383
// Symbol name dependencies:
384
// Internal: Defined in this graph.
385
// External: Defined externally.
386
struct BlockSymbolDependencies {
387
SymbolNameSet Internal, External;
388
};
389
390
// Lazily populated map of blocks to BlockSymbolDependencies values.
391
class BlockDependenciesMap {
392
public:
393
BlockDependenciesMap(ExecutionSession &ES,
394
DenseMap<const Block *, DenseSet<Block *>> BlockDeps)
395
: ES(ES), BlockDeps(std::move(BlockDeps)) {}
396
397
const BlockSymbolDependencies &operator[](const Block &B) {
398
// Check the cache first.
399
auto I = BlockTransitiveDepsCache.find(&B);
400
if (I != BlockTransitiveDepsCache.end())
401
return I->second;
402
403
// No value. Populate the cache.
404
BlockSymbolDependencies BTDCacheVal;
405
auto BDI = BlockDeps.find(&B);
406
assert(BDI != BlockDeps.end() && "No block dependencies");
407
408
for (auto *BDep : BDI->second) {
409
auto &BID = getBlockImmediateDeps(*BDep);
410
for (auto &ExternalDep : BID.External)
411
BTDCacheVal.External.insert(ExternalDep);
412
for (auto &InternalDep : BID.Internal)
413
BTDCacheVal.Internal.insert(InternalDep);
414
}
415
416
return BlockTransitiveDepsCache
417
.insert(std::make_pair(&B, std::move(BTDCacheVal)))
418
.first->second;
419
}
420
421
SymbolStringPtr &getInternedName(Symbol &Sym) {
422
auto I = NameCache.find(&Sym);
423
if (I != NameCache.end())
424
return I->second;
425
426
return NameCache.insert(std::make_pair(&Sym, ES.intern(Sym.getName())))
427
.first->second;
428
}
429
430
private:
431
BlockSymbolDependencies &getBlockImmediateDeps(Block &B) {
432
// Check the cache first.
433
auto I = BlockImmediateDepsCache.find(&B);
434
if (I != BlockImmediateDepsCache.end())
435
return I->second;
436
437
BlockSymbolDependencies BIDCacheVal;
438
for (auto &E : B.edges()) {
439
auto &Tgt = E.getTarget();
440
if (Tgt.getScope() != Scope::Local) {
441
if (Tgt.isExternal()) {
442
if (Tgt.getAddress() || !Tgt.isWeaklyReferenced())
443
BIDCacheVal.External.insert(getInternedName(Tgt));
444
} else
445
BIDCacheVal.Internal.insert(getInternedName(Tgt));
446
}
447
}
448
449
return BlockImmediateDepsCache
450
.insert(std::make_pair(&B, std::move(BIDCacheVal)))
451
.first->second;
452
}
453
454
ExecutionSession &ES;
455
DenseMap<const Block *, DenseSet<Block *>> BlockDeps;
456
DenseMap<const Symbol *, SymbolStringPtr> NameCache;
457
DenseMap<const Block *, BlockSymbolDependencies> BlockImmediateDepsCache;
458
DenseMap<const Block *, BlockSymbolDependencies> BlockTransitiveDepsCache;
459
};
460
461
Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) {
462
auto &ES = Layer.getExecutionSession();
463
464
SymbolFlagsMap NewSymbolsToClaim;
465
std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym;
466
467
auto ProcessSymbol = [&](Symbol *Sym) {
468
if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak &&
469
Sym->getScope() != Scope::Local) {
470
auto Name = ES.intern(Sym->getName());
471
if (!MR->getSymbols().count(ES.intern(Sym->getName()))) {
472
NewSymbolsToClaim[Name] =
473
getJITSymbolFlagsForSymbol(*Sym) | JITSymbolFlags::Weak;
474
NameToSym.push_back(std::make_pair(std::move(Name), Sym));
475
}
476
}
477
};
478
479
for (auto *Sym : G.defined_symbols())
480
ProcessSymbol(Sym);
481
for (auto *Sym : G.absolute_symbols())
482
ProcessSymbol(Sym);
483
484
// Attempt to claim all weak defs that we're not already responsible for.
485
// This may fail if the resource tracker has become defunct, but should
486
// always succeed otherwise.
487
if (auto Err = MR->defineMaterializing(std::move(NewSymbolsToClaim)))
488
return Err;
489
490
// Walk the list of symbols that we just tried to claim. Symbols that we're
491
// responsible for are marked live. Symbols that we're not responsible for
492
// are turned into external references.
493
for (auto &KV : NameToSym) {
494
if (MR->getSymbols().count(KV.first))
495
KV.second->setLive(true);
496
else
497
G.makeExternal(*KV.second);
498
}
499
500
return Error::success();
501
}
502
503
Error markResponsibilitySymbolsLive(LinkGraph &G) const {
504
auto &ES = Layer.getExecutionSession();
505
for (auto *Sym : G.defined_symbols())
506
if (Sym->hasName() && MR->getSymbols().count(ES.intern(Sym->getName())))
507
Sym->setLive(true);
508
return Error::success();
509
}
510
511
Error registerDependencies(LinkGraph &G) {
512
auto &TargetJD = MR->getTargetJITDylib();
513
auto &ES = TargetJD.getExecutionSession();
514
auto BlockDeps = computeBlockNonLocalDeps(G);
515
516
DenseSet<Block *> BlockDepsProcessed;
517
DenseMap<Block *, SymbolDependenceGroup> DepGroupForBlock;
518
519
// Compute dependencies for symbols defined in the JITLink graph.
520
for (auto *Sym : G.defined_symbols()) {
521
522
// Skip local symbols.
523
if (Sym->getScope() == Scope::Local)
524
continue;
525
assert(Sym->hasName() &&
526
"Defined non-local jitlink::Symbol should have a name");
527
528
auto &BDeps = BlockDeps[Sym->getBlock()];
529
530
// Skip symbols in blocks that don't depend on anything.
531
if (BDeps.Internal.empty() && BDeps.External.empty())
532
continue;
533
534
SymbolDependenceGroup &SDG = DepGroupForBlock[&Sym->getBlock()];
535
SDG.Symbols.insert(ES.intern(Sym->getName()));
536
537
if (!BlockDepsProcessed.count(&Sym->getBlock())) {
538
BlockDepsProcessed.insert(&Sym->getBlock());
539
540
if (!BDeps.Internal.empty())
541
SDG.Dependencies[&TargetJD] = BDeps.Internal;
542
for (auto &Dep : BDeps.External) {
543
auto DepSrcItr = SymbolSourceJDs.find(NonOwningSymbolStringPtr(Dep));
544
if (DepSrcItr != SymbolSourceJDs.end())
545
SDG.Dependencies[DepSrcItr->second].insert(Dep);
546
}
547
}
548
}
549
550
SymbolDependenceGroup SynthSDG;
551
552
for (auto &P : Plugins) {
553
auto SynthDeps = P->getSyntheticSymbolDependencies(*MR);
554
if (SynthDeps.empty())
555
continue;
556
557
DenseSet<Block *> BlockVisited;
558
for (auto &[Name, DepSyms] : SynthDeps) {
559
SynthSDG.Symbols.insert(Name);
560
for (auto *Sym : DepSyms) {
561
if (Sym->getScope() == Scope::Local) {
562
auto &BDeps = BlockDeps[Sym->getBlock()];
563
for (auto &S : BDeps.Internal)
564
SynthSDG.Dependencies[&TargetJD].insert(S);
565
for (auto &S : BDeps.External) {
566
auto DepSrcItr =
567
SymbolSourceJDs.find(NonOwningSymbolStringPtr(S));
568
if (DepSrcItr != SymbolSourceJDs.end())
569
SynthSDG.Dependencies[DepSrcItr->second].insert(S);
570
}
571
} else {
572
auto SymName = ES.intern(Sym->getName());
573
if (Sym->isExternal()) {
574
assert(SymbolSourceJDs.count(NonOwningSymbolStringPtr(SymName)) &&
575
"External symbol source entry missing");
576
SynthSDG
577
.Dependencies[SymbolSourceJDs[NonOwningSymbolStringPtr(
578
SymName)]]
579
.insert(SymName);
580
} else
581
SynthSDG.Dependencies[&TargetJD].insert(SymName);
582
}
583
}
584
}
585
}
586
587
// Transfer SDGs to SymbolDepGroups.
588
DepGroupForBlock.reserve(DepGroupForBlock.size() + 1);
589
for (auto &[B, SDG] : DepGroupForBlock) {
590
assert(!SDG.Symbols.empty() && "SymbolDependenceGroup covers no symbols");
591
if (!SDG.Dependencies.empty())
592
SymbolDepGroups.push_back(std::move(SDG));
593
}
594
if (!SynthSDG.Symbols.empty() && !SynthSDG.Dependencies.empty())
595
SymbolDepGroups.push_back(std::move(SynthSDG));
596
597
return Error::success();
598
}
599
600
BlockDependenciesMap computeBlockNonLocalDeps(LinkGraph &G) {
601
// First calculate the reachable-via-non-local-symbol blocks for each block.
602
struct BlockInfo {
603
DenseSet<Block *> Dependencies;
604
DenseSet<Block *> Dependants;
605
bool DependenciesChanged = true;
606
};
607
DenseMap<Block *, BlockInfo> BlockInfos;
608
SmallVector<Block *> WorkList;
609
610
// Pre-allocate map entries. This prevents any iterator/reference
611
// invalidation in the next loop.
612
for (auto *B : G.blocks())
613
(void)BlockInfos[B];
614
615
// Build initial worklist, record block dependencies/dependants and
616
// non-local symbol dependencies.
617
for (auto *B : G.blocks()) {
618
auto &BI = BlockInfos[B];
619
for (auto &E : B->edges()) {
620
if (E.getTarget().getScope() == Scope::Local &&
621
!E.getTarget().isAbsolute()) {
622
auto &TgtB = E.getTarget().getBlock();
623
if (&TgtB != B) {
624
BI.Dependencies.insert(&TgtB);
625
BlockInfos[&TgtB].Dependants.insert(B);
626
}
627
}
628
}
629
}
630
631
// Add blocks with both dependants and dependencies to the worklist to
632
// propagate dependencies to dependants.
633
for (auto &[B, BI] : BlockInfos) {
634
if (!BI.Dependants.empty() && !BI.Dependencies.empty())
635
WorkList.push_back(B);
636
}
637
638
// Propagate block-level dependencies through the block-dependence graph.
639
while (!WorkList.empty()) {
640
auto *B = WorkList.pop_back_val();
641
642
auto &BI = BlockInfos[B];
643
assert(BI.DependenciesChanged &&
644
"Block in worklist has unchanged dependencies");
645
BI.DependenciesChanged = false;
646
for (auto *Dependant : BI.Dependants) {
647
auto &DependantBI = BlockInfos[Dependant];
648
for (auto *Dependency : BI.Dependencies) {
649
if (Dependant != Dependency &&
650
DependantBI.Dependencies.insert(Dependency).second)
651
if (!DependantBI.DependenciesChanged) {
652
DependantBI.DependenciesChanged = true;
653
WorkList.push_back(Dependant);
654
}
655
}
656
}
657
}
658
659
DenseMap<const Block *, DenseSet<Block *>> BlockDeps;
660
for (auto &KV : BlockInfos)
661
BlockDeps[KV.first] = std::move(KV.second.Dependencies);
662
663
return BlockDependenciesMap(Layer.getExecutionSession(),
664
std::move(BlockDeps));
665
}
666
667
ObjectLinkingLayer &Layer;
668
std::vector<std::shared_ptr<ObjectLinkingLayer::Plugin>> Plugins;
669
std::unique_ptr<MaterializationResponsibility> MR;
670
std::unique_ptr<MemoryBuffer> ObjBuffer;
671
DenseMap<Block *, SymbolNameSet> ExternalBlockDeps;
672
DenseMap<Block *, SymbolNameSet> InternalBlockDeps;
673
DenseMap<NonOwningSymbolStringPtr, JITDylib *> SymbolSourceJDs;
674
std::vector<SymbolDependenceGroup> SymbolDepGroups;
675
};
676
677
ObjectLinkingLayer::Plugin::~Plugin() = default;
678
679
char ObjectLinkingLayer::ID;
680
681
using BaseT = RTTIExtends<ObjectLinkingLayer, ObjectLayer>;
682
683
ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES)
684
: BaseT(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) {
685
ES.registerResourceManager(*this);
686
}
687
688
ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES,
689
JITLinkMemoryManager &MemMgr)
690
: BaseT(ES), MemMgr(MemMgr) {
691
ES.registerResourceManager(*this);
692
}
693
694
ObjectLinkingLayer::ObjectLinkingLayer(
695
ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr)
696
: BaseT(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) {
697
ES.registerResourceManager(*this);
698
}
699
700
ObjectLinkingLayer::~ObjectLinkingLayer() {
701
assert(Allocs.empty() && "Layer destroyed with resources still attached");
702
getExecutionSession().deregisterResourceManager(*this);
703
}
704
705
Error ObjectLinkingLayer::add(ResourceTrackerSP RT,
706
std::unique_ptr<LinkGraph> G) {
707
auto &JD = RT->getJITDylib();
708
return JD.define(LinkGraphMaterializationUnit::Create(*this, std::move(G)),
709
std::move(RT));
710
}
711
712
void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
713
std::unique_ptr<MemoryBuffer> O) {
714
assert(O && "Object must not be null");
715
MemoryBufferRef ObjBuffer = O->getMemBufferRef();
716
717
auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
718
*this, std::move(R), std::move(O));
719
if (auto G = createLinkGraphFromObject(ObjBuffer)) {
720
Ctx->notifyMaterializing(**G);
721
link(std::move(*G), std::move(Ctx));
722
} else {
723
Ctx->notifyFailed(G.takeError());
724
}
725
}
726
727
void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
728
std::unique_ptr<LinkGraph> G) {
729
auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
730
*this, std::move(R), nullptr);
731
Ctx->notifyMaterializing(*G);
732
link(std::move(G), std::move(Ctx));
733
}
734
735
Error ObjectLinkingLayer::recordFinalizedAlloc(
736
MaterializationResponsibility &MR, FinalizedAlloc FA) {
737
auto Err = MR.withResourceKeyDo(
738
[&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); });
739
740
if (Err)
741
Err = joinErrors(std::move(Err), MemMgr.deallocate(std::move(FA)));
742
743
return Err;
744
}
745
746
Error ObjectLinkingLayer::handleRemoveResources(JITDylib &JD, ResourceKey K) {
747
748
{
749
Error Err = Error::success();
750
for (auto &P : Plugins)
751
Err = joinErrors(std::move(Err), P->notifyRemovingResources(JD, K));
752
if (Err)
753
return Err;
754
}
755
756
std::vector<FinalizedAlloc> AllocsToRemove;
757
getExecutionSession().runSessionLocked([&] {
758
auto I = Allocs.find(K);
759
if (I != Allocs.end()) {
760
std::swap(AllocsToRemove, I->second);
761
Allocs.erase(I);
762
}
763
});
764
765
if (AllocsToRemove.empty())
766
return Error::success();
767
768
return MemMgr.deallocate(std::move(AllocsToRemove));
769
}
770
771
void ObjectLinkingLayer::handleTransferResources(JITDylib &JD,
772
ResourceKey DstKey,
773
ResourceKey SrcKey) {
774
auto I = Allocs.find(SrcKey);
775
if (I != Allocs.end()) {
776
auto &SrcAllocs = I->second;
777
auto &DstAllocs = Allocs[DstKey];
778
DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size());
779
for (auto &Alloc : SrcAllocs)
780
DstAllocs.push_back(std::move(Alloc));
781
782
// Erase SrcKey entry using value rather than iterator I: I may have been
783
// invalidated when we looked up DstKey.
784
Allocs.erase(SrcKey);
785
}
786
787
for (auto &P : Plugins)
788
P->notifyTransferringResources(JD, DstKey, SrcKey);
789
}
790
791
EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
792
ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar)
793
: ES(ES), Registrar(std::move(Registrar)) {}
794
795
void EHFrameRegistrationPlugin::modifyPassConfig(
796
MaterializationResponsibility &MR, LinkGraph &G,
797
PassConfiguration &PassConfig) {
798
799
PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass(
800
G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) {
801
if (Addr) {
802
std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
803
assert(!InProcessLinks.count(&MR) &&
804
"Link for MR already being tracked?");
805
InProcessLinks[&MR] = {Addr, Size};
806
}
807
}));
808
}
809
810
Error EHFrameRegistrationPlugin::notifyEmitted(
811
MaterializationResponsibility &MR) {
812
813
ExecutorAddrRange EmittedRange;
814
{
815
std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
816
817
auto EHFrameRangeItr = InProcessLinks.find(&MR);
818
if (EHFrameRangeItr == InProcessLinks.end())
819
return Error::success();
820
821
EmittedRange = EHFrameRangeItr->second;
822
assert(EmittedRange.Start && "eh-frame addr to register can not be null");
823
InProcessLinks.erase(EHFrameRangeItr);
824
}
825
826
if (auto Err = MR.withResourceKeyDo(
827
[&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); }))
828
return Err;
829
830
return Registrar->registerEHFrames(EmittedRange);
831
}
832
833
Error EHFrameRegistrationPlugin::notifyFailed(
834
MaterializationResponsibility &MR) {
835
std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
836
InProcessLinks.erase(&MR);
837
return Error::success();
838
}
839
840
Error EHFrameRegistrationPlugin::notifyRemovingResources(JITDylib &JD,
841
ResourceKey K) {
842
std::vector<ExecutorAddrRange> RangesToRemove;
843
844
ES.runSessionLocked([&] {
845
auto I = EHFrameRanges.find(K);
846
if (I != EHFrameRanges.end()) {
847
RangesToRemove = std::move(I->second);
848
EHFrameRanges.erase(I);
849
}
850
});
851
852
Error Err = Error::success();
853
while (!RangesToRemove.empty()) {
854
auto RangeToRemove = RangesToRemove.back();
855
RangesToRemove.pop_back();
856
assert(RangeToRemove.Start && "Untracked eh-frame range must not be null");
857
Err = joinErrors(std::move(Err),
858
Registrar->deregisterEHFrames(RangeToRemove));
859
}
860
861
return Err;
862
}
863
864
void EHFrameRegistrationPlugin::notifyTransferringResources(
865
JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) {
866
auto SI = EHFrameRanges.find(SrcKey);
867
if (SI == EHFrameRanges.end())
868
return;
869
870
auto DI = EHFrameRanges.find(DstKey);
871
if (DI != EHFrameRanges.end()) {
872
auto &SrcRanges = SI->second;
873
auto &DstRanges = DI->second;
874
DstRanges.reserve(DstRanges.size() + SrcRanges.size());
875
for (auto &SrcRange : SrcRanges)
876
DstRanges.push_back(std::move(SrcRange));
877
EHFrameRanges.erase(SI);
878
} else {
879
// We need to move SrcKey's ranges over without invalidating the SI
880
// iterator.
881
auto Tmp = std::move(SI->second);
882
EHFrameRanges.erase(SI);
883
EHFrameRanges[DstKey] = std::move(Tmp);
884
}
885
}
886
887
} // End namespace orc.
888
} // End namespace llvm.
889
890