20#define DEBUG_TYPE "orc"
29 bool IsMachO =
G.getTargetTriple().isOSBinFormatMachO();
30 bool IsElf =
G.getTargetTriple().isOSBinFormatELF();
31 if (!IsMachO && !IsElf)
34 for (
auto &Sec :
G.sections()) {
45 switch (TT.getArch()) {
79 static std::unique_ptr<LinkGraphMaterializationUnit>
81 auto LGI = scanLinkGraph(ObjLinkingLayer.getExecutionSession(), *
G);
82 return std::unique_ptr<LinkGraphMaterializationUnit>(
83 new LinkGraphMaterializationUnit(ObjLinkingLayer, std::move(
G),
88 void materialize(std::unique_ptr<MaterializationResponsibility> MR)
override {
89 ObjLinkingLayer.
emit(std::move(MR), std::move(
G));
104 getJITSymbolFlagsForSymbol(*
Sym);
107 for (
auto *
Sym :
G.defined_symbols())
109 for (
auto *
Sym :
G.absolute_symbols())
112 if (hasInitializerSection(
G))
113 LGI.InitSymbol = makeInitSymbol(ES,
G);
119 std::string InitSymString;
121 <<
"$." <<
G.getName() <<
".__inits" << Counter++;
122 return ES.
intern(InitSymString);
126 std::unique_ptr<LinkGraph>
G, Interface LGI)
131 for (
auto *
Sym :
G->defined_symbols())
134 "Discarding non-weak definition");
135 G->makeExternal(*
Sym);
141 std::unique_ptr<LinkGraph>
G;
142 static std::atomic<uint64_t> Counter;
145std::atomic<uint64_t> LinkGraphMaterializationUnit::Counter{0};
156 std::unique_ptr<MaterializationResponsibility> MR,
157 std::unique_ptr<MemoryBuffer> ObjBuffer)
164 if (Layer.ReturnObjectBuffer && ObjBuffer)
165 Layer.ReturnObjectBuffer(std::move(ObjBuffer));
171 for (
auto &
P : Layer.Plugins)
172 P->notifyMaterializing(*MR,
G, *
this,
173 ObjBuffer ? ObjBuffer->getMemBufferRef()
178 for (
auto &
P : Layer.Plugins)
179 Err =
joinErrors(std::move(Err),
P->notifyFailed(*MR));
180 Layer.getExecutionSession().reportError(std::move(Err));
181 MR->failMaterialization();
185 std::unique_ptr<JITLinkAsyncLookupContinuation> LC)
override {
188 MR->getTargetJITDylib().withLinkOrderDo(
191 auto &ES = Layer.getExecutionSession();
194 for (
auto &KV : Symbols) {
204 LookupSet.
add(ES.intern(KV.first), LookupFlags);
208 auto OnResolve = [LookupContinuation =
211 LookupContinuation->run(
Result.takeError());
215 LR[*KV.first] = KV.second;
216 LookupContinuation->run(std::move(LR));
224 for (
auto &[DepJD, Deps] : Deps)
225 for (
auto &DepSym : Deps)
231 auto &ES = Layer.getExecutionSession();
234 bool AutoClaim = Layer.AutoClaimObjectSymbols;
237 for (
auto *
Sym :
G.defined_symbols())
239 auto InternedName = ES.intern(
Sym->
getName());
240 auto Ptr = getJITSymbolPtrForSymbol(*
Sym,
G.getTargetTriple());
241 auto Flags = getJITSymbolFlagsForSymbol(*
Sym);
242 InternedResult[InternedName] = {
Ptr, Flags};
243 if (AutoClaim && !MR->getSymbols().count(InternedName)) {
245 "Duplicate symbol to claim?");
246 ExtraSymbolsToClaim[InternedName] = Flags;
250 for (
auto *
Sym :
G.absolute_symbols())
252 auto InternedName = ES.intern(
Sym->
getName());
253 auto Ptr = getJITSymbolPtrForSymbol(*
Sym,
G.getTargetTriple());
254 auto Flags = getJITSymbolFlagsForSymbol(*
Sym);
255 InternedResult[InternedName] = {
Ptr, Flags};
256 if (AutoClaim && !MR->getSymbols().count(InternedName)) {
258 "Duplicate symbol to claim?");
259 ExtraSymbolsToClaim[InternedName] = Flags;
263 if (!ExtraSymbolsToClaim.
empty())
264 if (
auto Err = MR->defineMaterializing(ExtraSymbolsToClaim))
274 size_t NumMaterializationSideEffectsOnlySymbols = 0;
277 for (
auto &KV : MR->getSymbols()) {
279 auto I = InternedResult.
find(KV.first);
284 if (KV.second.hasMaterializationSideEffectsOnly()) {
285 ++NumMaterializationSideEffectsOnlySymbols;
286 if (
I != InternedResult.
end())
287 ExtraSymbols.push_back(KV.first);
289 }
else if (
I == InternedResult.
end())
290 MissingSymbols.push_back(KV.first);
291 else if (Layer.OverrideObjectFlags)
292 I->second.setFlags(KV.second);
296 if (!MissingSymbols.empty())
297 return make_error<MissingSymbolDefinitions>(
298 Layer.getExecutionSession().getSymbolStringPool(),
G.getName(),
299 std::move(MissingSymbols));
303 if (InternedResult.
size() >
304 MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) {
305 for (
auto &KV : InternedResult)
306 if (!MR->getSymbols().count(KV.first))
307 ExtraSymbols.push_back(KV.first);
311 if (!ExtraSymbols.empty())
312 return make_error<UnexpectedSymbolDefinitions>(
313 Layer.getExecutionSession().getSymbolStringPool(),
G.getName(),
314 std::move(ExtraSymbols));
317 if (
auto Err = MR->notifyResolved(InternedResult))
320 Layer.notifyLoaded(*MR);
325 if (
auto Err = Layer.notifyEmitted(*MR, std::move(
A))) {
326 Layer.getExecutionSession().reportError(std::move(Err));
327 MR->failMaterialization();
330 if (
auto Err = MR->notifyEmitted(SymbolDepGroups)) {
331 Layer.getExecutionSession().reportError(std::move(Err));
332 MR->failMaterialization();
337 return [
this](
LinkGraph &
G) {
return markResponsibilitySymbolsLive(
G); };
344 return claimOrExternalizeWeakAndCommonSymbols(
G);
347 Layer.modifyPassConfig(*MR, LG,
Config);
349 Config.PreFixupPasses.push_back(
350 [
this](
LinkGraph &
G) {
return registerDependencies(
G); });
359 struct BlockSymbolDependencies {
364 class BlockDependenciesMap {
368 : ES(ES), BlockDeps(
std::
move(BlockDeps)) {}
370 const BlockSymbolDependencies &operator[](
const Block &
B) {
372 auto I = BlockTransitiveDepsCache.find(&
B);
373 if (
I != BlockTransitiveDepsCache.end())
377 BlockSymbolDependencies BTDCacheVal;
378 auto BDI = BlockDeps.find(&
B);
379 assert(BDI != BlockDeps.end() &&
"No block dependencies");
381 for (
auto *BDep : BDI->second) {
382 auto &BID = getBlockImmediateDeps(*BDep);
383 for (
auto &ExternalDep : BID.External)
384 BTDCacheVal.External.insert(ExternalDep);
385 for (
auto &InternalDep : BID.Internal)
386 BTDCacheVal.Internal.insert(InternalDep);
389 return BlockTransitiveDepsCache
390 .insert(std::make_pair(&
B, std::move(BTDCacheVal)))
395 auto I = NameCache.find(&
Sym);
396 if (
I != NameCache.end())
399 return NameCache.insert(std::make_pair(&
Sym, ES.intern(
Sym.
getName())))
404 BlockSymbolDependencies &getBlockImmediateDeps(
Block &
B) {
406 auto I = BlockImmediateDepsCache.find(&
B);
407 if (
I != BlockImmediateDepsCache.end())
410 BlockSymbolDependencies BIDCacheVal;
411 for (
auto &E :
B.edges()) {
412 auto &Tgt = E.getTarget();
413 if (Tgt.getScope() != Scope::Local) {
414 if (Tgt.isExternal()) {
415 if (Tgt.getAddress() || !Tgt.isWeaklyReferenced())
416 BIDCacheVal.External.insert(getInternedName(Tgt));
418 BIDCacheVal.Internal.insert(getInternedName(Tgt));
422 return BlockImmediateDepsCache
423 .insert(std::make_pair(&
B, std::move(BIDCacheVal)))
435 auto &ES = Layer.getExecutionSession();
438 std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym;
444 if (!MR->getSymbols().count(ES.intern(
Sym->
getName()))) {
445 NewSymbolsToClaim[
Name] =
447 NameToSym.push_back(std::make_pair(std::move(
Name),
Sym));
452 for (
auto *
Sym :
G.defined_symbols())
454 for (
auto *
Sym :
G.absolute_symbols())
460 if (
auto Err = MR->defineMaterializing(std::move(NewSymbolsToClaim)))
466 for (
auto &KV : NameToSym) {
467 if (MR->getSymbols().count(KV.first))
468 KV.second->setLive(
true);
470 G.makeExternal(*KV.second);
477 auto &ES = Layer.getExecutionSession();
478 for (
auto *
Sym :
G.defined_symbols())
485 auto &TargetJD = MR->getTargetJITDylib();
486 auto &ES = TargetJD.getExecutionSession();
487 auto BlockDeps = computeBlockNonLocalDeps(
G);
493 for (
auto *
Sym :
G.defined_symbols()) {
499 "Defined non-local jitlink::Symbol should have a name");
504 if (BDeps.Internal.empty() && BDeps.External.empty())
513 if (!BDeps.Internal.empty())
515 for (
auto &Dep : BDeps.External) {
517 if (DepSrcItr != SymbolSourceJDs.end())
525 for (
auto &
P : Layer.Plugins) {
526 auto SynthDeps =
P->getSyntheticSymbolDependencies(*MR);
527 if (SynthDeps.empty())
531 for (
auto &[
Name, DepSyms] : SynthDeps) {
533 for (
auto *
Sym : DepSyms) {
536 for (
auto &S : BDeps.Internal)
538 for (
auto &S : BDeps.External) {
541 if (DepSrcItr != SymbolSourceJDs.end())
548 "External symbol source entry missing");
561 DepGroupForBlock.
reserve(DepGroupForBlock.
size() + 1);
562 for (
auto &[
B, SDG] : DepGroupForBlock) {
565 SymbolDepGroups.push_back(std::move(SDG));
568 SymbolDepGroups.push_back(std::move(SynthSDG));
573 BlockDependenciesMap computeBlockNonLocalDeps(
LinkGraph &
G) {
578 bool DependenciesChanged =
true;
585 for (
auto *
B :
G.blocks())
590 for (
auto *
B :
G.blocks()) {
591 auto &BI = BlockInfos[
B];
592 for (
auto &E :
B->edges()) {
593 if (E.getTarget().getScope() == Scope::Local &&
594 !E.getTarget().isAbsolute()) {
595 auto &TgtB = E.getTarget().getBlock();
597 BI.Dependencies.
insert(&TgtB);
598 BlockInfos[&TgtB].Dependants.
insert(
B);
605 if (!BI.Dependants.empty() && !BI.Dependencies.empty())
610 while (!WorkList.
empty()) {
613 auto &BI = BlockInfos[
B];
614 assert(BI.DependenciesChanged &&
615 "Block in worklist has unchanged dependencies");
616 BI.DependenciesChanged =
false;
617 for (
auto *Dependant : BI.Dependants) {
618 auto &DependantBI = BlockInfos[Dependant];
619 for (
auto *Dependency : BI.Dependencies) {
620 if (Dependant != Dependency &&
621 DependantBI.Dependencies.insert(Dependency).second)
622 if (!DependantBI.DependenciesChanged) {
623 DependantBI.DependenciesChanged =
true;
631 for (
auto &KV : BlockInfos)
632 BlockDeps[KV.first] = std::move(KV.second.Dependencies);
634 return BlockDependenciesMap(Layer.getExecutionSession(),
635 std::move(BlockDeps));
639 std::unique_ptr<MaterializationResponsibility> MR;
640 std::unique_ptr<MemoryBuffer> ObjBuffer;
644 std::vector<SymbolDependenceGroup> SymbolDepGroups;
654 :
BaseT(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) {
660 :
BaseT(ES), MemMgr(MemMgr) {
666 :
BaseT(ES), MemMgr(*MemMgr), MemMgrOwnership(
std::
move(MemMgr)) {
671 assert(Allocs.empty() &&
"Layer destroyed with resources still attached");
672 getExecutionSession().deregisterResourceManager(*
this);
676 std::unique_ptr<LinkGraph>
G) {
678 return JD.
define(LinkGraphMaterializationUnit::Create(*
this, std::move(
G)),
683 std::unique_ptr<MemoryBuffer> O) {
684 assert(O &&
"Object must not be null");
687 auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
688 *
this, std::move(R), std::move(O));
690 Ctx->notifyMaterializing(**
G);
691 link(std::move(*
G), std::move(Ctx));
693 Ctx->notifyFailed(
G.takeError());
698 std::unique_ptr<LinkGraph>
G) {
699 auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
700 *
this, std::move(R),
nullptr);
701 Ctx->notifyMaterializing(*
G);
702 link(std::move(
G), std::move(Ctx));
708 for (
auto &
P : Plugins)
709 P->modifyPassConfig(MR,
G, PassConfig);
713 for (
auto &
P : Plugins)
720 for (
auto &
P : Plugins)
721 Err =
joinErrors(std::move(Err),
P->notifyEmitted(MR));
725 Err =
joinErrors(std::move(Err), MemMgr.deallocate(std::move(FA)));
733 [&](
ResourceKey K) { Allocs[
K].push_back(std::move(FA)); });
736 Err =
joinErrors(std::move(Err), MemMgr.deallocate(std::move(FA)));
745 for (
auto &
P : Plugins)
746 Err =
joinErrors(std::move(Err),
P->notifyRemovingResources(JD, K));
751 std::vector<FinalizedAlloc> AllocsToRemove;
752 getExecutionSession().runSessionLocked([&] {
753 auto I = Allocs.find(K);
754 if (
I != Allocs.end()) {
755 std::swap(AllocsToRemove, I->second);
760 if (AllocsToRemove.empty())
763 return MemMgr.deallocate(std::move(AllocsToRemove));
766void ObjectLinkingLayer::handleTransferResources(
JITDylib &JD,
769 auto I = Allocs.find(SrcKey);
770 if (
I != Allocs.end()) {
771 auto &SrcAllocs =
I->second;
772 auto &DstAllocs = Allocs[DstKey];
773 DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size());
774 for (
auto &
Alloc : SrcAllocs)
775 DstAllocs.push_back(std::move(
Alloc));
779 Allocs.erase(SrcKey);
782 for (
auto &
P : Plugins)
783 P->notifyTransferringResources(JD, DstKey, SrcKey);
788 : ES(ES), Registrar(
std::
move(Registrar)) {}
797 std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
798 assert(!InProcessLinks.count(&MR) &&
799 "Link for MR already being tracked?");
800 InProcessLinks[&MR] = {Addr, Size};
810 std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
812 auto EHFrameRangeItr = InProcessLinks.find(&MR);
813 if (EHFrameRangeItr == InProcessLinks.end())
816 EmittedRange = EHFrameRangeItr->second;
817 assert(EmittedRange.
Start &&
"eh-frame addr to register can not be null");
818 InProcessLinks.erase(EHFrameRangeItr);
822 [&](
ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); }))
825 return Registrar->registerEHFrames(EmittedRange);
830 std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
831 InProcessLinks.erase(&MR);
837 std::vector<ExecutorAddrRange> RangesToRemove;
840 auto I = EHFrameRanges.find(K);
841 if (
I != EHFrameRanges.end()) {
842 RangesToRemove = std::move(I->second);
843 EHFrameRanges.erase(I);
848 while (!RangesToRemove.empty()) {
849 auto RangeToRemove = RangesToRemove.back();
850 RangesToRemove.pop_back();
851 assert(RangeToRemove.Start &&
"Untracked eh-frame range must not be null");
853 Registrar->deregisterEHFrames(RangeToRemove));
861 auto SI = EHFrameRanges.find(SrcKey);
862 if (SI == EHFrameRanges.end())
865 auto DI = EHFrameRanges.find(DstKey);
866 if (DI != EHFrameRanges.end()) {
867 auto &SrcRanges = SI->second;
868 auto &DstRanges = DI->second;
869 DstRanges.reserve(DstRanges.size() + SrcRanges.size());
870 for (
auto &SrcRange : SrcRanges)
871 DstRanges.push_back(std::move(SrcRange));
872 EHFrameRanges.erase(SI);
876 auto Tmp = std::move(SI->second);
877 EHFrameRanges.erase(SI);
878 EHFrameRanges[DstKey] = std::move(Tmp);
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
iterator find(const_arg_type_t< KeyT > Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
void reserve(size_type NumEntries)
Grow the densemap so that it can contain at least NumEntries items before resizing again.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Flags for symbols in the JIT.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Triple - Helper class for working with autoconf configuration names.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
An Addressable with content and edges.
Holds context for a single jitLink invocation.
Represents a finalized allocation.
Manages allocations of JIT memory.
bool isExternal() const
Returns true if the underlying addressable is an unresolved external.
bool isCallable() const
Returns true is this symbol is callable.
StringRef getName() const
Returns the name of this symbol (empty if the symbol is anonymous).
Scope getScope() const
Get the visibility for this Symbol.
Linkage getLinkage() const
Get the linkage for this Symbol.
orc::ExecutorAddr getAddress() const
Returns the address of this symbol.
void setLive(bool IsLive)
Set this symbol's live bit.
Block & getBlock()
Return the Block for this Symbol (Symbol must be defined).
bool hasName() const
Returns true if this symbol has a name.
void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) override
Error notifyEmitted(MaterializationResponsibility &MR) override
Error notifyFailed(MaterializationResponsibility &MR) override
EHFrameRegistrationPlugin(ExecutionSession &ES, std::unique_ptr< jitlink::EHFrameRegistrar > Registrar)
Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override
void modifyPassConfig(MaterializationResponsibility &MR, jitlink::LinkGraph &G, jitlink::PassConfiguration &PassConfig) override
An ExecutionSession represents a running JIT program.
SymbolStringPtr intern(StringRef SymName)
Add a symbol name to the SymbolStringPool and return a pointer to it.
void registerResourceManager(ResourceManager &RM)
Register the given ResourceManager with this ExecutionSession.
decltype(auto) runSessionLocked(Func &&F)
Run the given lambda with the session mutex locked.
Represents an address in the executor process.
uint64_t getValue() const
Represents a JIT'd dynamic library.
Error define(std::unique_ptr< MaterializationUnitType > &&MU, ResourceTrackerSP RT=nullptr)
Define all symbols provided by the materialization unit to be part of this JITDylib.
Tracks responsibility for materialization, and mediates interactions between MaterializationUnits and...
Error withResourceKeyDo(Func &&F) const
Runs the given callback under the session lock, passing in the associated ResourceKey.
A MaterializationUnit represents a set of symbol definitions that can be materialized as a group,...
virtual StringRef getName() const =0
Return the name of this materialization unit.
virtual void materialize(std::unique_ptr< MaterializationResponsibility > R)=0
Implementations of this method should materialize all symbols in the materialzation unit,...
Non-owning SymbolStringPool entry pointer.
ObjectLinkingLayerJITLinkContext(ObjectLinkingLayer &Layer, std::unique_ptr< MaterializationResponsibility > MR, std::unique_ptr< MemoryBuffer > ObjBuffer)
void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override
Called by JITLink to notify the context that the object has been finalized (i.e.
void notifyFailed(Error Err) override
Notify this context that linking failed.
void lookup(const LookupMap &Symbols, std::unique_ptr< JITLinkAsyncLookupContinuation > LC) override
Called by JITLink to resolve external symbols.
Error notifyResolved(LinkGraph &G) override
Called by JITLink once all defined symbols in the graph have been assigned their final memory locatio...
~ObjectLinkingLayerJITLinkContext()
void notifyMaterializing(LinkGraph &G)
JITLinkMemoryManager & getMemoryManager() override
Return the MemoryManager to be used for this link.
LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override
Returns the mark-live pass to be used for this link.
Error modifyPassConfig(LinkGraph &LG, PassConfiguration &Config) override
Called by JITLink to modify the pass pipeline prior to linking.
An ObjectLayer implementation built on JITLink.
ObjectLinkingLayer(ExecutionSession &ES)
Construct an ObjectLinkingLayer using the ExecutorProcessControl instance's memory manager.
Error add(ResourceTrackerSP, std::unique_ptr< jitlink::LinkGraph > G)
Add a LinkGraph to the JITDylib targeted by the given tracker.
void emit(std::unique_ptr< MaterializationResponsibility > R, std::unique_ptr< MemoryBuffer > O) override
Emit an object file.
~ObjectLinkingLayer()
Destruct an ObjectLinkingLayer.
JITDylib & getJITDylib() const
Return the JITDylib targeted by this tracker.
A set of symbols to look up, each associated with a SymbolLookupFlags value.
SymbolLookupSet & add(SymbolStringPtr Name, SymbolLookupFlags Flags=SymbolLookupFlags::RequiredSymbol)
Add an element to the set.
Pointer to a pooled string representing a symbol name.
A raw_ostream that writes to an std::string.
unique_function is a type-erasing functor similar to std::function.
LinkGraphPassFunction createEHFrameRecorderPass(const Triple &TT, StoreFrameRangeFunction StoreFrameRange)
Creates a pass that records the address and size of the EH frame section.
Expected< std::unique_ptr< LinkGraph > > createLinkGraphFromObject(MemoryBufferRef ObjectBuffer)
Create a LinkGraph from the given object buffer.
void link(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
Link the given graph.
std::vector< std::pair< JITDylib *, JITDylibLookupFlags > > JITDylibSearchOrder
A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search order during symbol lookup.
SymbolLookupFlags
Lookup flags that apply to each symbol in a lookup.
bool isMachOInitializerSection(StringRef SegName, StringRef SecName)
std::vector< SymbolStringPtr > SymbolNameVector
A vector of symbol names.
@ Resolved
Queried, materialization begun.
bool isELFInitializerSection(StringRef SecName)
This is an optimization pass for GlobalISel generic memory operations.
Error joinErrors(Error E1, Error E2)
Concatenate errors.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Implement std::hash so that hash_code can be used in STL containers.
An LinkGraph pass configuration, consisting of a list of pre-prune, post-prune, and post-fixup passes...
LinkGraphPassList PostFixupPasses
Post-fixup passes.
Represents an address range in the exceutor process.
A set of symbols and the their dependencies.
SymbolDependenceMap Dependencies