Commit Graph

32 Commits

Author SHA1 Message Date
Lang Hames 27ea3f1607 [JITLink][x86-64] Rename *Relaxable edges to *REXRelaxable.
The existing relaxable edges all assume a REX prefix. ELF includes non-REX
relaxations, so rename these edges to make room for the new kinds.
2021-08-14 18:28:49 +10:00
Lang Hames 2487db1f28 [ORC] Require ExecutorProcessControl when constructing an ExecutionSession.
Wrapper function call and dispatch handler helpers are moved to
ExecutionSession, and existing EPC-based tools are re-written to take an
ExecutionSession argument instead.

Requiring an ExecutorProcessControl instance simplifies existing EPC based
utilities (which only need to take an ES now), and should encourage more
utilities to use the EPC interface. It also simplifies process termination,
since the session can automatically call ExecutorProcessControl::disconnect
(previously this had to be done manually, and carefully ordered with the
rest of JIT tear-down to work correctly).
2021-07-27 16:53:49 +10:00
Lang Hames cdcc354768 [ORC][ORC-RT] Add initial Objective-C and Swift support to MachOPlatform.
This allows ORC to execute code containing Objective-C and Swift classes and
methods (provided that the language runtime is loaded into the executor).
2021-07-26 18:02:01 +10:00
Lang Hames eda6afdad6 Re-re-re-apply "[ORC][ORC-RT] Add initial native-TLV support to MachOPlatform."
The ccache builders have recevied a config update that should eliminate the
build issues seen previously.
2021-07-24 13:16:12 +10:00
Hubert Tong af5602d369 [ORC] Work around AIX build compiler: Replace lambda; NFC
By replacing a lambda expression with a functor class instance, this
patch works around an issue encountered on AIX where the IBM XL compiler
appears to make no progress for many hours.

Reviewed By: jsji

Differential Revision: https://reviews.llvm.org/D106554
2021-07-23 10:12:26 -04:00
Lang Hames 402b681fff Re-re-revert "[ORC][ORC-RT] Add initial native-TLV support to MachOPlatform."
This reverts commit 6b2a96285b.

The ccache builders are still failing. Looks like they need to be updated to
get the llvm-zorg config change in 490633945677656ba75d42ff1ca9d4a400b7b243.

I'll re-apply this as soon as the builders are updated.
2021-07-22 10:45:24 +10:00
Lang Hames 6b2a96285b Re-re-apply "[ORC][ORC-RT] Add initial native-TLV support to MachOPlatform."
This reapplies commit a7733e9556 ("Re-apply
[ORC][ORC-RT] Add initial native-TLV support to MachOPlatform."), and
d4abdefc99 ("[ORC-RT] Rename macho_tlv.x86-64.s
to macho_tlv.x86-64.S (uppercase suffix)").

These patches were reverted in 48aa82cacb while I
investigated bot failures (e.g.
https://lab.llvm.org/buildbot/#/builders/109/builds/18981). The fix was to
disable building of the ORC runtime on buliders using ccache (which is the same
fix used for other compiler-rt projects containing assembly code). This fix was
commited to llvm-zorg in 490633945677656ba75d42ff1ca9d4a400b7b243.
2021-07-22 09:46:52 +10:00
Lang Hames 48aa82cacb [ORC][ORC-RT] Revert MachO TLV patches while I investigate more bot failures.
This reverts commit d4abdefc99 ("[ORC-RT] Rename
macho_tlv.x86-64.s to macho_tlv.x86-64.S (uppercase suffix)", and
a7733e9556 ("Re-apply "[ORC][ORC-RT] Add initial
native-TLV support to MachOPlatform."), while I investigate failures on
ccache builders (e.g. https://lab.llvm.org/buildbot/#/builders/109/builds/18981)
2021-07-21 15:52:33 +10:00
Lang Hames a7733e9556 Re-apply "[ORC][ORC-RT] Add initial native-TLV support to MachOPlatform."
Reapplies fe1fa43f16, which was reverted in
6d8c63946c, with fixes:

1. Remove .subsections_via_symbols directive from macho_tlv.x86-64.s (it's
not needed here anyway).

2. Return error from pthread_key_create to the MachOPlatform to silence unused
variable warning.
2021-07-21 15:11:22 +10:00
Lang Hames 6d8c63946c Revert "[ORC][ORC-RT] Add initial native-TLV support to MachOPlatform."
Reverts commit fe1fa43f16 while I investigate
failures on Linux.
2021-07-21 09:22:55 +10:00
Lang Hames fe1fa43f16 [ORC][ORC-RT] Add initial native-TLV support to MachOPlatform.
Adds code to LLVM (MachOPlatform) and the ORC runtime to support native MachO
thread local variables. Adding new TLVs to a JITDylib at runtime is supported.

On the LLVM side MachOPlatform is updated to:

1. Identify thread local variables in the LinkGraph and lower them to GOT
accesses to data in the __thread_data or __thread_bss sections.

2. Merge and report the address range of __thread_data and thread_bss sections
to the runtime.

On the ORC runtime a MachOTLVManager class introduced which records the address
range of thread data/bss sections, and creates thread-local instances from the
initial data on demand. An orc-runtime specific tlv_get_addr implementation is
included which saves all register state then calls the MachOTLVManager to get
the address of the requested variable for the current thread.
2021-07-21 09:10:10 +10:00
Lang Hames df47770600 [ORC] Explicitly convert to ArrayRefs to silence errors.
This aims to fix build failures like
https://lab.llvm.org/buildbot#builders/165/builds/3761.
2021-07-19 20:48:30 +10:00
Lang Hames bb5f97e3ad [ORC][ORC-RT] Introduce ORC-runtime based MachO-Platform.
Adds support for MachO static initializers/deinitializers and eh-frame
registration via the ORC runtime.

This commit introduces cooperative support code into the ORC runtime and ORC
LLVM libraries (especially the MachOPlatform class) to support macho runtime
features for JIT'd code. This commit introduces support for static
initializers, static destructors (via cxa_atexit interposition), and eh-frame
registration. Near-future commits will add support for MachO native
thread-local variables, and language runtime registration (e.g. for Objective-C
and Swift).

The llvm-jitlink tool is updated to use the ORC runtime where available, and
regression tests for the new MachOPlatform support are added to compiler-rt.

Notable changes on the ORC runtime side:

1. The new macho_platform.h / macho_platform.cpp files contain the bulk of the
runtime-side support. This includes eh-frame registration; jit versions of
dlopen, dlsym, and dlclose; a cxa_atexit interpose to record static destructors,
and an '__orc_rt_macho_run_program' function that defines running a JIT'd MachO
program in terms of the jit- dlopen/dlsym/dlclose functions.

2. Replaces JITTargetAddress (and casting operations) with ExecutorAddress
(copied from LLVM) to improve type-safety of address management.

3. Adds serialization support for ExecutorAddress and unordered_map types to
the runtime-side Simple Packed Serialization code.

4. Adds orc-runtime regression tests to ensure that static initializers and
cxa-atexit interposes work as expected.

Notable changes on the LLVM side:

1. The MachOPlatform class is updated to:

  1.1. Load the ORC runtime into the ExecutionSession.
  1.2. Set up standard aliases for macho-specific runtime functions. E.g.
       ___cxa_atexit -> ___orc_rt_macho_cxa_atexit.
  1.3. Install the MachOPlatformPlugin to scrape LinkGraphs for information
       needed to support MachO features (e.g. eh-frames, mod-inits), and
       communicate this information to the runtime.
  1.4. Provide entry-points that the runtime can call to request initializers,
       perform symbol lookup, and request deinitialiers (the latter is
       implemented as an empty placeholder as macho object deinits are rarely
       used).
  1.5. Create a MachO header object for each JITDylib (defining the __mh_header
       and __dso_handle symbols).

2. The llvm-jitlink tool (and llvm-jitlink-executor) are updated to use the
runtime when available.

3. A `lookupInitSymbolsAsync` method is added to the Platform base class. This
can be used to issue an async lookup for initializer symbols. The existing
`lookupInitSymbols` method is retained (the GenericIRPlatform code is still
using it), but is deprecated and will be removed soon.

4. JIT-dispatch support code is added to ExecutorProcessControl.

The JIT-dispatch system allows handlers in the JIT process to be associated with
'tag' symbols in the executor, and allows the executor to make remote procedure
calls back to the JIT process (via __orc_rt_jit_dispatch) using those tags.

The primary use case is ORC runtime code that needs to call bakc to handlers in
orc::Platform subclasses. E.g. __orc_rt_macho_jit_dlopen calling back to
MachOPlatform::rt_getInitializers using __orc_rt_macho_get_initializers_tag.
(The system is generic however, and could be used by non-runtime code).

The new ExecutorProcessControl::JITDispatchInfo struct provides the address
(in the executor) of the jit-dispatch function and a jit-dispatch context
object, and implementations of the dispatch function are added to
SelfExecutorProcessControl and OrcRPCExecutorProcessControl.

5. OrcRPCTPCServer is updated to support JIT-dispatch calls over ORC-RPC.

6. Serialization support for StringMap is added to the LLVM-side Simple Packed
Serialization code.

7. A JITLink::allocateBuffer operation is introduced to allocate writable memory
attached to the graph. This is used by the MachO header synthesis code, and will
be generically useful for other clients who want to create new graph content
from scratch.
2021-07-19 19:50:16 +10:00
Lang Hames 89aa11ed28 [ORC] Remove LLVM-side MachO Platform runtime support.
Support for this functionality is moving to the ORC runtime.
2021-07-17 14:25:31 +10:00
Lang Hames b8e5f91816 [ORC] Flesh out ExecutorAddress, rename CommonOrcRuntimeTypes header.
Renames CommonOrcRuntimeTypes.h to ExecutorAddress.h and moves ExecutorAddress
into the 'orc' namespace (rather than orc::shared).

Also makes ExecutorAddress a class, adds an ExecutorAddrDiff type and some
arithmetic operations on the pair (subtracting two addresses yields an addrdiff,
adding an addrdiff and an address yields an address).
2021-07-10 13:53:52 +10:00
Lang Hames 963378bd82 [ORC] Improve computeLocalDeps / computeNamedSymbolDependencies performance.
The computeNamedSymbolDependencies and computeLocalDeps methods on
ObjectLinkingLayerJITLinkContext are responsible for computing, for each symbol
in the current MaterializationResponsibility, the set of non-locally-scoped
symbols that are depended on. To calculate this we have to consider the effect
of chains of dependence through locally scoped symbols in the LinkGraph. E.g.

        .text
        .globl  foo
foo:
        callq   bar                    ## foo depneds on external 'bar'
        movq    Ltmp1(%rip), %rcx      ## foo depends on locally scoped 'Ltmp1'
        addl    (%rcx), %eax
        retq

        .data
Ltmp1:
        .quad   x                      ## Ltmp1 depends on external 'x'

In this example symbol 'foo' depends directly on 'bar', and indirectly on 'x'
via 'Ltmp1', which is locally scoped.

Performance of the existing implementations appears to have been mediocre:
Based on flame graphs posted by @drmeister (in #jit on the LLVM discord server)
the computeLocalDeps function was taking up a substantial amount of time when
starting up Clasp (https://github.com/clasp-developers/clasp).

This commit attempts to address the performance problems in three ways:

1. Using jitlink::Blocks instead of jitlink::Symbols as the nodes of the
dependencies-introduced-by-locally-scoped-symbols graph.

Using either Blocks or Symbols as nodes provides the same information, but since
there may be more than one locally scoped symbol per block the block-based
version of the dependence graph should always be a subgraph of the Symbol-based
version, and so faster to operate on.

2. Improved worklist management.

The older version of computeLocalDeps used a fixed worklist containing all
nodes, and iterated over this list propagating dependencies until no further
changes were required. The worklist was not sorted into a useful order before
the loop started.

The new version uses a variable work-stack, visiting nodes in DFS order and
only adding nodes when there is meaningful work to do on them.

Compared to the old version the new version avoids revisiting nodes which
haven't changed, and I suspect it converges more quickly (due to the DFS
ordering).

3. Laziness and caching.

Mappings of...

jitlink::Symbol* -> Interned Name (as SymbolStringPtr)
jitlink::Block* -> Immediate dependencies (as SymbolNameSet)
jitlink::Block* -> Transitive dependencies (as SymbolNameSet)

are all built lazily and cached while running computeNamedSymbolDependencies.

According to @drmeister these changes reduced Clasp startup time in his test
setup (averaged over a handful of starts) from 4.8 to 2.8 seconds (with
ORC/JITLink linking ~11,000 object files in that time), which seems like
enough to justify switching to the new algorithm in the absence of any other
perf numbers.
2021-07-08 16:31:59 +10:00
Lang Hames 5471766f9d [ORC] Replace MachOJITDylibInitializers::SectionExtent with ExecutorAddressRange
MachOJITDylibInitializers::SectionExtent represented the address range of a
section as an (address, size) pair. The new ExecutorAddressRange type
generalizes this to an address range (for any object, not necessarily a section)
represented as a (start-address, end-address) pair.

The aim is to express more of ORC (and the ORC runtime) in terms of simple types
that can be serialized/deserialized via SPS. This will simplify SPS-based RPC
involving arguments/return-values of these types.
2021-07-08 14:15:44 +10:00
Lang Hames 19e402d2b3 [JITLink][MachO] Use full <segment>,<section> names for MachO jitlink::Sections.
JITLink now requires section names to be unique. In MachO section names are only
guaranteed to be unique within their containing segment (e.g. a '__const' section
in the '__DATA' segment does not clash with a '__const' section in the '__TEXT'
segment), so we need to use the fully qualified <segment>,<section> section
names (e.g. '__DATA,__const' or '__TEXT,__const') when constructing
jitlink::Sections for MachO objects.
2021-03-25 18:31:18 -07:00
Lang Hames 4e30b20bdb [JITLink][ORC] Make the LinkGraph available to modifyPassConfig.
This makes the target triple, graph name, and full graph content available
when making decisions about how to populate the linker pass pipeline.

Also updates the LLJITWithObjectLinkingLayerPlugin example to show more
API use, including use of the API changes in this patch.
2021-03-12 18:42:51 -08:00
Lang Hames 0aec49c853 [ORC] Add support for resource tracking/removal (removable code).
This patch introduces new APIs to support resource tracking and removal in Orc.
It is intended as a thread-safe generalization of the removeModule concept from
OrcV1.

Clients can now create ResourceTracker objects (using
JITDylib::createResourceTracker) to track resources for each MaterializationUnit
(code, data, aliases, absolute symbols, etc.) added to the JIT. Every
MaterializationUnit will be associated with a ResourceTracker, and
ResourceTrackers can be re-used for multiple MaterializationUnits. Each JITDylib
has a default ResourceTracker that will be used for MaterializationUnits added
to that JITDylib if no ResourceTracker is explicitly specified.

Two operations can be performed on ResourceTrackers: transferTo and remove. The
transferTo operation transfers tracking of the resources to a different
ResourceTracker object, allowing ResourceTrackers to be merged to reduce
administrative overhead (the source tracker is invalidated in the process). The
remove operation removes all resources associated with a ResourceTracker,
including any symbols defined by MaterializationUnits associated with the
tracker, and also invalidates the tracker. These operations are thread safe, and
should work regardless of the the state of the MaterializationUnits. In the case
of resource transfer any existing resources associated with the source tracker
will be transferred to the destination tracker, and all future resources for
those units will be automatically associated with the destination tracker. In
the case of resource removal all already-allocated resources will be
deallocated, any if any program representations associated with the tracker have
not been compiled yet they will be destroyed. If any program representations are
currently being compiled then they will be prevented from completing: their
MaterializationResponsibility will return errors on any attempt to update the
JIT state.

Clients (usually Layer writers) wishing to track resources can implement the
ResourceManager API to receive notifications when ResourceTrackers are
transferred or removed. The MaterializationResponsibility::withResourceKeyDo
method can be used to create associations between the key for a ResourceTracker
and an allocated resource in a thread-safe way.

RTDyldObjectLinkingLayer and ObjectLinkingLayer are updated to use the
ResourceManager API to enable tracking and removal of memory allocated by the
JIT linker.

The new JITDylib::clear method can be used to trigger removal of every
ResourceTracker associated with the JITDylib (note that this will only
remove resources for the JITDylib, it does not run static destructors).

This patch includes unit tests showing basic usage. A follow-up patch will
update the Kaleidoscope and BuildingAJIT tutorial series to OrcV2 and will
use this API to release code associated with anonymous expressions.
2020-10-18 21:02:54 -07:00
Lang Hames bd09e0dd74 [ORC] Remove stray debugging output. 2020-09-01 20:53:49 -07:00
Lang Hames c40ce0da71 [ORC] Add an early out for MachOPlatform's init-scraper plugin setup.
If there's no initializer symbol in the current MaterializationResponsibility
then bail out without installing JITLink passes: they're going to be no-ops
anyway.
2020-09-01 20:12:23 -07:00
Lang Hames 7ff335a25f [ORC] Fix MachOPlatform's synthetic symbol dependence registration.
A think-o in the existing code meant that dependencies were never registered.
This failure could lead to crashes rather than orderly error propagation if
initialization dependencies failed to materialize.

No test case: The bug was discovered in an out-of-tree code and requires
pathalogically misconfigured JIT to generate the original error that lead to
the crash.
2020-09-01 20:12:23 -07:00
Lang Hames e1d5f7d003 [ORC] Add getDFSLinkOrder / getReverseDFSLinkOrder methods to JITDylib.
DFS and Reverse-DFS linkage orders are used to order execution of
deinitializers and initializers respectively.

This patch replaces uses of special purpose DFS order functions in
MachOPlatform and LLJIT with uses of the new methods.
2020-08-29 15:17:06 -07:00
Lang Hames c66f89005f [ORC] Rename SearchOrder operations on JITDylib to LinkOrder.
Refering to the link order of a dylib better matches the terminology used in
static compilation. As upcoming patches will increase the number of places where
link order matters (for example when closing JITDylibs) it's better to get this
name change out of the way early.
2020-05-04 16:47:52 -07:00
Lang Hames cb84e4827e [ORC] Introduce JITSymbolFlags::HasMaterializeSideEffectsOnly flag.
This flag can be used to mark a symbol as existing only for the purpose of
enabling materialization. Such a symbol can be looked up to trigger
materialization with the lookup returning only once materialization is
complete. Symbols with this flag will never resolve however (to avoid
permanently polluting the symbol table), and should only be looked up using
the SymbolLookupFlags::WeaklyReferencedSymbol flag. The primary use case for
this flag is initialization symbols.
2020-03-27 11:02:54 -07:00
Lang Hames 38a8760b99 [ORC] Move ostream operators for debugging output out of Core.h.
DebugUtils.h seems like a more appropriate home for these.
2020-03-21 18:27:28 -07:00
Lang Hames ad2da631bf [ORC] Fix indentation in debugging output. 2020-03-19 11:02:56 -07:00
Lang Hames eb918d8daf [ORC] Use finer-grained and session locking in MachOPlatform to avoid deadlock.
In MachOPlatform, obtaining the link-order for a JITDylib requires locking the
session, but also needs to be part of a larger atomic operation that collates
initializer symbols tracked by the platform. Trying to do this under a separate
platform mutex leads to potential locking order issues, e.g.

T1 locks session then tries to lock platform to register a new init symbol
meanwhile
T2 locks platform then tries to lock session to obtain link order.

Removing the platform lock and performing all these operations under the session
lock eliminates this possibility.

At the same time we also need to collate init pointers from the
MachOPlatform::InitScraperPlugin, and we don't need or want to lock the session
for that. The new InitSeqMutex has been added to guard these init pointers, and
the session mutex is never obtained while the InitSeqMutex is held.
2020-03-19 11:02:56 -07:00
Lang Hames 4b15decb60 [ORC] Remove hard dependency on libobjc when using MachOPlatform with LLJIT.
The LLJIT::MachOPlatformSupport class used to unconditionally attempt to
register __objc_selrefs and __objc_classlist sections. If libobjc had not
been loaded this resulted in an assertion, even if no objc sections were
actually present. This patch replaces this unconditional registration with
a check that no objce sections are present if libobjc has not been loaded.
This will allow clients to use MachOPlatform with LLJIT without requiring
libobjc for non-objc code.
2020-03-04 21:49:28 -08:00
Lang Hames 8363ff04af [ORC] Add some debugging output for initializers.
This output can be useful in tracking down initialization failures in the JIT.
2020-03-04 12:38:25 -08:00
Lang Hames 85fb997659 [ORC] Add generic initializer/deinitializer support.
Initializers and deinitializers are used to implement C++ static constructors
and destructors, runtime registration for some languages (e.g. with the
Objective-C runtime for Objective-C/C++ code) and other tasks that would
typically be performed when a shared-object/dylib is loaded or unloaded by a
statically compiled program.

MCJIT and ORC have historically provided limited support for discovering and
running initializers/deinitializers by scanning the llvm.global_ctors and
llvm.global_dtors variables and recording the functions to be run. This approach
suffers from several drawbacks: (1) It only works for IR inputs, not for object
files (including cached JIT'd objects). (2) It only works for initializers
described by llvm.global_ctors and llvm.global_dtors, however not all
initializers are described in this way (Objective-C, for example, describes
initializers via specially named metadata sections). (3) To make the
initializer/deinitializer functions described by llvm.global_ctors and
llvm.global_dtors searchable they must be promoted to extern linkage, polluting
the JIT symbol table (extra care must be taken to ensure this promotion does
not result in symbol name clashes).

This patch introduces several interdependent changes to ORCv2 to support the
construction of new initialization schemes, and includes an implementation of a
backwards-compatible llvm.global_ctor/llvm.global_dtor scanning scheme, and a
MachO specific scheme that handles Objective-C runtime registration (if the
Objective-C runtime is available) enabling execution of LLVM IR compiled from
Objective-C and Swift.

The major changes included in this patch are:

(1) The MaterializationUnit and MaterializationResponsibility classes are
extended to describe an optional "initializer" symbol for the module (see the
getInitializerSymbol method on each class). The presence or absence of this
symbol indicates whether the module contains any initializers or
deinitializers. The initializer symbol otherwise behaves like any other:
searching for it triggers materialization.

(2) A new Platform interface is introduced in llvm/ExecutionEngine/Orc/Core.h
which provides the following callback interface:

  - Error setupJITDylib(JITDylib &JD): Can be used to install standard symbols
    in JITDylibs upon creation. E.g. __dso_handle.

  - Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU): Generally
    used to record initializer symbols.

  - Error notifyRemoving(JITDylib &JD, VModuleKey K): Used to notify a platform
    that a module is being removed.

  Platform implementations can use these callbacks to track outstanding
initializers and implement a platform-specific approach for executing them. For
example, the MachOPlatform installs a plugin in the JIT linker to scan for both
__mod_inits sections (for C++ static constructors) and ObjC metadata sections.
If discovered, these are processed in the usual platform order: Objective-C
registration is carried out first, then static initializers are executed,
ensuring that calls to Objective-C from static initializers will be safe.

This patch updates LLJIT to use the new scheme for initialization. Two
LLJIT::PlatformSupport classes are implemented: A GenericIR platform and a MachO
platform. The GenericIR platform implements a modified version of the previous
llvm.global-ctor scraping scheme to provide support for Windows and
Linux. LLJIT's MachO platform uses the MachOPlatform class to provide MachO
specific initialization as described above.

Reviewers: sgraenitz, dblaikie

Subscribers: mgorny, hiraditya, mgrang, ributzka, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D74300
2020-02-19 13:59:32 -08:00