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)
160 std::lock_guard<std::mutex> Lock(Layer.LayerMutex);
161 Plugins = Layer.Plugins;
167 if (Layer.ReturnObjectBuffer && ObjBuffer)
168 Layer.ReturnObjectBuffer(std::move(ObjBuffer));
174 for (
auto &
P : Plugins)
175 P->notifyMaterializing(*MR,
G, *
this,
176 ObjBuffer ? ObjBuffer->getMemBufferRef()
181 for (
auto &
P : Plugins)
182 Err =
joinErrors(std::move(Err),
P->notifyFailed(*MR));
183 Layer.getExecutionSession().reportError(std::move(Err));
184 MR->failMaterialization();
188 std::unique_ptr<JITLinkAsyncLookupContinuation> LC)
override {
191 MR->getTargetJITDylib().withLinkOrderDo(
194 auto &ES = Layer.getExecutionSession();
197 for (
auto &KV : Symbols) {
207 LookupSet.
add(ES.intern(KV.first), LookupFlags);
211 auto OnResolve = [LookupContinuation =
214 LookupContinuation->run(
Result.takeError());
218 LR[*KV.first] = KV.second;
219 LookupContinuation->run(std::move(LR));
227 for (
auto &[DepJD, Deps] : Deps)
228 for (
auto &DepSym : Deps)
234 auto &ES = Layer.getExecutionSession();
237 bool AutoClaim = Layer.AutoClaimObjectSymbols;
240 for (
auto *
Sym :
G.defined_symbols())
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)) {
248 "Duplicate symbol to claim?");
249 ExtraSymbolsToClaim[InternedName] = Flags;
253 for (
auto *
Sym :
G.absolute_symbols())
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)) {
261 "Duplicate symbol to claim?");
262 ExtraSymbolsToClaim[InternedName] = Flags;
266 if (!ExtraSymbolsToClaim.
empty())
267 if (
auto Err = MR->defineMaterializing(ExtraSymbolsToClaim))
277 size_t NumMaterializationSideEffectsOnlySymbols = 0;
280 for (
auto &KV : MR->getSymbols()) {
282 auto I = InternedResult.
find(KV.first);
287 if (KV.second.hasMaterializationSideEffectsOnly()) {
288 ++NumMaterializationSideEffectsOnlySymbols;
289 if (
I != InternedResult.
end())
290 ExtraSymbols.push_back(KV.first);
292 }
else if (
I == InternedResult.
end())
293 MissingSymbols.push_back(KV.first);
294 else if (Layer.OverrideObjectFlags)
295 I->second.setFlags(KV.second);
299 if (!MissingSymbols.empty())
300 return make_error<MissingSymbolDefinitions>(
301 Layer.getExecutionSession().getSymbolStringPool(),
G.getName(),
302 std::move(MissingSymbols));
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);
314 if (!ExtraSymbols.empty())
315 return make_error<UnexpectedSymbolDefinitions>(
316 Layer.getExecutionSession().getSymbolStringPool(),
G.getName(),
317 std::move(ExtraSymbols));
320 if (
auto Err = MR->notifyResolved(InternedResult))
329 Layer.getExecutionSession().reportError(std::move(Err));
330 MR->failMaterialization();
333 if (
auto Err = MR->notifyEmitted(SymbolDepGroups)) {
334 Layer.getExecutionSession().reportError(std::move(Err));
335 MR->failMaterialization();
340 return [
this](
LinkGraph &
G) {
return markResponsibilitySymbolsLive(
G); };
347 return claimOrExternalizeWeakAndCommonSymbols(
G);
350 for (
auto &
P : Plugins)
351 P->modifyPassConfig(*MR, LG,
Config);
353 Config.PreFixupPasses.push_back(
354 [
this](
LinkGraph &
G) {
return registerDependencies(
G); });
360 for (
auto &
P : Plugins)
361 P->notifyLoaded(*MR);
366 for (
auto &
P : Plugins)
367 Err =
joinErrors(std::move(Err),
P->notifyEmitted(*MR));
377 return Layer.recordFinalizedAlloc(*MR, std::move(FA));
386 struct BlockSymbolDependencies {
391 class BlockDependenciesMap {
395 : ES(ES), BlockDeps(
std::
move(BlockDeps)) {}
397 const BlockSymbolDependencies &operator[](
const Block &
B) {
399 auto I = BlockTransitiveDepsCache.find(&
B);
400 if (
I != BlockTransitiveDepsCache.end())
404 BlockSymbolDependencies BTDCacheVal;
405 auto BDI = BlockDeps.find(&
B);
406 assert(BDI != BlockDeps.end() &&
"No block dependencies");
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);
416 return BlockTransitiveDepsCache
417 .insert(std::make_pair(&
B, std::move(BTDCacheVal)))
422 auto I = NameCache.find(&
Sym);
423 if (
I != NameCache.end())
426 return NameCache.insert(std::make_pair(&
Sym, ES.intern(
Sym.
getName())))
431 BlockSymbolDependencies &getBlockImmediateDeps(
Block &
B) {
433 auto I = BlockImmediateDepsCache.find(&
B);
434 if (
I != BlockImmediateDepsCache.end())
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));
445 BIDCacheVal.Internal.insert(getInternedName(Tgt));
449 return BlockImmediateDepsCache
450 .insert(std::make_pair(&
B, std::move(BIDCacheVal)))
462 auto &ES = Layer.getExecutionSession();
465 std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym;
471 if (!MR->getSymbols().count(ES.intern(
Sym->
getName()))) {
472 NewSymbolsToClaim[
Name] =
474 NameToSym.push_back(std::make_pair(std::move(
Name),
Sym));
479 for (
auto *
Sym :
G.defined_symbols())
481 for (
auto *
Sym :
G.absolute_symbols())
487 if (
auto Err = MR->defineMaterializing(std::move(NewSymbolsToClaim)))
493 for (
auto &KV : NameToSym) {
494 if (MR->getSymbols().count(KV.first))
495 KV.second->setLive(
true);
497 G.makeExternal(*KV.second);
504 auto &ES = Layer.getExecutionSession();
505 for (
auto *
Sym :
G.defined_symbols())
512 auto &TargetJD = MR->getTargetJITDylib();
513 auto &ES = TargetJD.getExecutionSession();
514 auto BlockDeps = computeBlockNonLocalDeps(
G);
520 for (
auto *
Sym :
G.defined_symbols()) {
526 "Defined non-local jitlink::Symbol should have a name");
531 if (BDeps.Internal.empty() && BDeps.External.empty())
540 if (!BDeps.Internal.empty())
542 for (
auto &Dep : BDeps.External) {
544 if (DepSrcItr != SymbolSourceJDs.end())
552 for (
auto &
P : Plugins) {
553 auto SynthDeps =
P->getSyntheticSymbolDependencies(*MR);
554 if (SynthDeps.empty())
558 for (
auto &[
Name, DepSyms] : SynthDeps) {
560 for (
auto *
Sym : DepSyms) {
563 for (
auto &S : BDeps.Internal)
565 for (
auto &S : BDeps.External) {
568 if (DepSrcItr != SymbolSourceJDs.end())
575 "External symbol source entry missing");
588 DepGroupForBlock.
reserve(DepGroupForBlock.
size() + 1);
589 for (
auto &[
B, SDG] : DepGroupForBlock) {
592 SymbolDepGroups.push_back(std::move(SDG));
595 SymbolDepGroups.push_back(std::move(SynthSDG));
600 BlockDependenciesMap computeBlockNonLocalDeps(
LinkGraph &
G) {
605 bool DependenciesChanged =
true;
612 for (
auto *
B :
G.blocks())
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();
624 BI.Dependencies.
insert(&TgtB);
625 BlockInfos[&TgtB].Dependants.
insert(
B);
633 for (
auto &[
B, BI] : BlockInfos) {
634 if (!BI.Dependants.empty() && !BI.Dependencies.empty())
639 while (!WorkList.
empty()) {
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;
660 for (
auto &KV : BlockInfos)
661 BlockDeps[KV.first] = std::move(KV.second.Dependencies);
663 return BlockDependenciesMap(Layer.getExecutionSession(),
664 std::move(BlockDeps));
668 std::vector<std::shared_ptr<ObjectLinkingLayer::Plugin>> Plugins;
669 std::unique_ptr<MaterializationResponsibility> MR;
670 std::unique_ptr<MemoryBuffer> ObjBuffer;
674 std::vector<SymbolDependenceGroup> SymbolDepGroups;
684 :
BaseT(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) {
690 :
BaseT(ES), MemMgr(MemMgr) {
696 :
BaseT(ES), MemMgr(*MemMgr), MemMgrOwnership(
std::
move(MemMgr)) {
701 assert(Allocs.empty() &&
"Layer destroyed with resources still attached");
702 getExecutionSession().deregisterResourceManager(*
this);
706 std::unique_ptr<LinkGraph>
G) {
708 return JD.
define(LinkGraphMaterializationUnit::Create(*
this, std::move(
G)),
713 std::unique_ptr<MemoryBuffer> O) {
714 assert(O &&
"Object must not be null");
717 auto Ctx = std::make_unique<ObjectLinkingLayerJITLinkContext>(
718 *
this, std::move(R), std::move(O));
720 Ctx->notifyMaterializing(**
G);
721 link(std::move(*
G), std::move(Ctx));
723 Ctx->notifyFailed(
G.takeError());
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));
735Error ObjectLinkingLayer::recordFinalizedAlloc(
738 [&](
ResourceKey K) { Allocs[K].push_back(std::move(FA)); });
741 Err =
joinErrors(std::move(Err), MemMgr.deallocate(std::move(FA)));
750 for (
auto &
P : Plugins)
751 Err =
joinErrors(std::move(Err),
P->notifyRemovingResources(JD, K));
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);
765 if (AllocsToRemove.empty())
768 return MemMgr.deallocate(std::move(AllocsToRemove));
771void ObjectLinkingLayer::handleTransferResources(
JITDylib &JD,
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));
784 Allocs.erase(SrcKey);
787 for (
auto &
P : Plugins)
788 P->notifyTransferringResources(JD, DstKey, SrcKey);
793 : ES(ES), Registrar(
std::
move(Registrar)) {}
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};
815 std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
817 auto EHFrameRangeItr = InProcessLinks.find(&MR);
818 if (EHFrameRangeItr == InProcessLinks.end())
821 EmittedRange = EHFrameRangeItr->second;
822 assert(EmittedRange.
Start &&
"eh-frame addr to register can not be null");
823 InProcessLinks.erase(EHFrameRangeItr);
827 [&](
ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); }))
830 return Registrar->registerEHFrames(EmittedRange);
835 std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
836 InProcessLinks.erase(&MR);
842 std::vector<ExecutorAddrRange> RangesToRemove;
845 auto I = EHFrameRanges.find(K);
846 if (
I != EHFrameRanges.end()) {
847 RangesToRemove = std::move(I->second);
848 EHFrameRanges.erase(I);
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");
858 Registrar->deregisterEHFrames(RangeToRemove));
866 auto SI = EHFrameRanges.find(SrcKey);
867 if (SI == EHFrameRanges.end())
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);
881 auto Tmp = std::move(SI->second);
882 EHFrameRanges.erase(SI);
883 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.
virtual void deallocate(std::vector< FinalizedAlloc > Allocs, OnDeallocatedFunction OnDeallocated)=0
Deallocate a list of allocation objects.
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.
Error notifyEmitted(jitlink::JITLinkMemoryManager::FinalizedAlloc FA)
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