Vendor import of llvm trunk r307894:

https://llvm.org/svn/llvm-project/llvm/trunk@307894
This commit is contained in:
Dimitry Andric 2017-07-13 19:25:18 +00:00
parent 9df3605dea
commit ca089b24d4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/llvm/dist/; revision=320957
svn path=/vendor/llvm/llvm-trunk-r307894/; revision=320958; tag=vendor/llvm/llvm-trunk-r307894
1199 changed files with 98409 additions and 18934 deletions

View File

@ -288,6 +288,10 @@ set(LLVM_LIBDIR_SUFFIX "" CACHE STRING "Define suffix of library directory name
set(LLVM_TOOLS_INSTALL_DIR "bin" CACHE STRING "Path for binary subdirectory (defaults to 'bin')")
mark_as_advanced(LLVM_TOOLS_INSTALL_DIR)
set(LLVM_UTILS_INSTALL_DIR "bin" CACHE STRING
"Path to install LLVM utilities (enabled by LLVM_INSTALL_UTILS=ON) (defaults to LLVM_TOOLS_INSTALL_DIR)")
mark_as_advanced(LLVM_TOOLS_INSTALL_DIR)
# They are used as destination of target generators.
set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin)
set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX})

View File

@ -91,7 +91,7 @@ function(add_llvm_symbol_exports target_name export_file)
DEPENDS ${export_file}
VERBATIM
COMMENT "Creating export file for ${target_name}")
if (${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
if (${LLVM_LINKER_IS_SOLARISLD})
set_property(TARGET ${target_name} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,-M,${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}")
else()
@ -148,13 +148,28 @@ function(add_llvm_symbol_exports target_name export_file)
endfunction(add_llvm_symbol_exports)
if(NOT WIN32 AND NOT APPLE)
# Detect what linker we have here
execute_process(
COMMAND ${CMAKE_C_COMPILER} -Wl,--version
OUTPUT_VARIABLE stdout
ERROR_QUIET
ERROR_VARIABLE stderr
)
set(LLVM_LINKER_DETECTED ON)
if("${stdout}" MATCHES "GNU gold")
set(LLVM_LINKER_IS_GOLD ON)
message(STATUS "Linker detection: GNU Gold")
elseif("${stdout}" MATCHES "^LLD")
set(LLVM_LINKER_IS_LLD ON)
message(STATUS "Linker detection: LLD")
elseif("${stdout}" MATCHES "GNU ld")
set(LLVM_LINKER_IS_GNULD ON)
message(STATUS "Linker detection: GNU ld")
elseif("${stderr}" MATCHES "Solaris Link Editors")
set(LLVM_LINKER_IS_SOLARISLD ON)
message(STATUS "Linker detection: Solaris ld")
else()
set(LLVM_LINKER_DETECTED OFF)
message(STATUS "Linker detection: unknown")
endif()
endif()
@ -865,7 +880,7 @@ macro(add_llvm_utility name)
set_target_properties(${name} PROPERTIES FOLDER "Utils")
if( LLVM_INSTALL_UTILS AND LLVM_BUILD_UTILS )
install (TARGETS ${name}
RUNTIME DESTINATION bin
RUNTIME DESTINATION ${LLVM_UTILS_INSTALL_DIR}
COMPONENT ${name})
if (NOT CMAKE_CONFIGURATION_TYPES)
add_custom_target(install-${name}
@ -1159,11 +1174,6 @@ function(add_lit_target target comment)
list(APPEND LIT_ARGS --param build_mode=${CMAKE_CFG_INTDIR})
endif ()
if (EXISTS ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py)
# reset cache after erraneous r283029
# TODO: remove this once all buildbots run
if (LIT_COMMAND STREQUAL "${PYTHON_EXECUTABLE} ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py")
unset(LIT_COMMAND CACHE)
endif()
set (LIT_COMMAND "${PYTHON_EXECUTABLE};${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py"
CACHE STRING "Command used to spawn llvm-lit")
else()

View File

@ -686,8 +686,8 @@ endif()
# lld doesn't print colored diagnostics when invoked from Ninja
if (UNIX AND CMAKE_GENERATOR STREQUAL "Ninja")
include(CheckLinkerFlag)
check_linker_flag("-Wl,-color-diagnostics" LINKER_SUPPORTS_COLOR_DIAGNOSTICS)
append_if(LINKER_SUPPORTS_COLOR_DIAGNOSTICS "-Wl,-color-diagnostics"
check_linker_flag("-Wl,--color-diagnostics" LINKER_SUPPORTS_COLOR_DIAGNOSTICS)
append_if(LINKER_SUPPORTS_COLOR_DIAGNOSTICS "-Wl,--color-diagnostics"
CMAKE_EXE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS)
endif()

View File

@ -195,8 +195,16 @@ function(llvm_ExternalProject_Add name source_dir)
# Add top-level targets
foreach(target ${ARG_EXTRA_TARGETS})
string(REPLACE ":" ";" target_list ${target})
list(GET target_list 0 target)
list(LENGTH target_list target_list_len)
if(${target_list_len} GREATER 1)
list(GET target_list 1 target_name)
else()
set(target_name "${target}")
endif()
llvm_ExternalProject_BuildCmd(build_runtime_cmd ${target} ${BINARY_DIR})
add_custom_target(${target}
add_custom_target(${target_name}
COMMAND ${build_runtime_cmd}
DEPENDS ${name}-configure
WORKING_DIRECTORY ${BINARY_DIR}

View File

@ -190,9 +190,7 @@ names from both the *Processor* and *Alternative Processor* can be used.
gfx810 - stoney amdgcn APU
**GCN GFX9**
--------------------------------------------------------------------
gfx900 amdgcn dGPU - FirePro W9500
- FirePro S9500
- FirePro S9500x2
gfx900 amdgcn dGPU - Radeon Vega Frontier Edition
gfx901 amdgcn dGPU ROCm Same as gfx900
except XNACK is
enabled

View File

@ -536,6 +536,11 @@ LLVM-specific variables
during the build. Enabling this option can significantly speed up build times
especially when building LLVM in Debug configurations.
**LLVM_REVERSE_ITERATION**:BOOL
If enabled, all supported unordered llvm containers would be iterated in
reverse order. This is useful for uncovering non-determinism caused by
iteration of unordered containers.
CMake Caches
============

View File

@ -112,33 +112,6 @@ In this example the ``extra_sources`` variable is only defined if you're
targeting an Apple platform. For all other targets the ``extra_sources`` will be
evaluated as empty before add_executable is given its arguments.
One big "Gotcha" with variable dereferencing is that ``if`` commands implicitly
dereference values. This has some unexpected results. For example:
.. code-block:: cmake
if("${SOME_VAR}" STREQUAL "MSVC")
In this code sample MSVC will be implicitly dereferenced, which will result in
the if command comparing the value of the dereferenced variables ``SOME_VAR``
and ``MSVC``. A common workaround to this solution is to prepend strings being
compared with an ``x``.
.. code-block:: cmake
if("x${SOME_VAR}" STREQUAL "xMSVC")
This works because while ``MSVC`` is a defined variable, ``xMSVC`` is not. This
pattern is uncommon, but it does occur in LLVM's CMake scripts.
.. note::
Once the LLVM project upgrades its minimum CMake version to 3.1 or later we
can prevent this behavior by setting CMP0054 to new. For more information on
CMake policies please see the cmake-policies manpage or the `cmake-policies
online documentation
<https://cmake.org/cmake/help/v3.4/manual/cmake-policies.7.html>`_.
Lists
-----

View File

@ -169,6 +169,13 @@ SELECTION OPTIONS
must be in the range ``1..M``. The environment variable
``LIT_RUN_SHARD`` can also be used in place of this option.
.. option:: --filter=REGEXP
Run only those tests whose name matches the regular expression specified in
``REGEXP``. The environment variable ``LIT_FILTER`` can be also used in place
of this option, which is especially useful in environments where the call
to ``lit`` is issued indirectly.
ADDITIONAL OPTIONS
------------------

View File

@ -262,6 +262,12 @@ OPTIONS
The demangler is expected to read a newline-separated list of symbols from
stdin and write a newline-separated list of the same length to stdout.
.. option:: -num-threads=N, -j=N
Use N threads to write file reports (only applicable when -output-dir is
specified). When N=0, llvm-cov auto-detects an appropriate number of threads to
use. This is the default.
.. option:: -line-coverage-gt=<N>
Show code coverage only for functions with line coverage greater than the

View File

@ -192,6 +192,12 @@ OPTIONS
information is dumped in a more human readable form (also in text) with
annotations.
.. option:: -topn=n
Instruct the profile dumper to show the top ``n`` functions with the
hottest basic blocks in the summary section. By default, the topn functions
are not dumped.
.. option:: -sample
Specify that the input profile is a sample-based profile.

View File

@ -846,7 +846,7 @@ Overview:
"""""""""
The '``llvm.coro.alloc``' intrinsic returns `true` if dynamic allocation is
required to obtain a memory for the corutine frame and `false` otherwise.
required to obtain a memory for the coroutine frame and `false` otherwise.
Arguments:
""""""""""

View File

@ -88,15 +88,11 @@ compiled by the system compiler in the debian8 image:
./llvm/utils/docker/build_docker_image.sh \
--source debian8 \
--docker-repository clang-debian8 --docker-tag "staging" \
-- \
-p clang -i install-clang -i install-clang-headers \
-- \
-DCMAKE_BUILD_TYPE=Release
Note there are two levels of ``--`` indirection. First one separates
``build_docker_image.sh`` arguments from ``llvm/utils/build_install_llvm.sh``
arguments. Second one separates CMake arguments from ``build_install_llvm.sh``
arguments. Note that build like that doesn't use a 2-stage build process that
Note that a build like that doesn't use a 2-stage build process that
you probably want for clang. Running a 2-stage build is a little more intricate,
this command will do that:
@ -108,7 +104,6 @@ this command will do that:
./build_docker_image.sh \
--source debian8 \
--docker-repository clang-debian8 --docker-tag "staging" \
-- \
-p clang -i stage2-install-clang -i stage2-install-clang-headers \
-- \
-DLLVM_TARGETS_TO_BUILD=Native -DCMAKE_BUILD_TYPE=Release \
@ -178,7 +173,6 @@ debian8-based image using the latest ``google/stable`` sources for you:
./llvm/utils/docker/build_docker_image.sh \
-s debian8 --d clang-debian8 -t "staging" \
-- \
--branch branches/google/stable \
-p clang -i install-clang -i install-clang-headers \
-- \

View File

View File

@ -62,6 +62,9 @@ Here are the steps you can follow to do so:
lab.llvm.org:9990 \
<buildslave-access-name> <buildslave-access-password>
To point a slave to silent master please use lab.llvm.org:9994 instead
of lab.llvm.org:9990.
#. Fill the buildslave description and admin name/e-mail. Here is an
example of the buildslave description::

View File

@ -2209,12 +2209,21 @@ For a simpler introduction to the ordering constraints, see the
same address in this global order. This corresponds to the C++0x/C1x
``memory_order_seq_cst`` and Java volatile.
.. _singlethread:
.. _syncscope:
If an atomic operation is marked ``singlethread``, it only *synchronizes
with* or participates in modification and seq\_cst total orderings with
other operations running in the same thread (for example, in signal
handlers).
If an atomic operation is marked ``syncscope("singlethread")``, it only
*synchronizes with* and only participates in the seq\_cst total orderings of
other operations running in the same thread (for example, in signal handlers).
If an atomic operation is marked ``syncscope("<target-scope>")``, where
``<target-scope>`` is a target specific synchronization scope, then it is target
dependent if it *synchronizes with* and participates in the seq\_cst total
orderings of other operations.
Otherwise, an atomic operation that is not marked ``syncscope("singlethread")``
or ``syncscope("<target-scope>")`` *synchronizes with* and participates in the
seq\_cst total orderings of other operations that are not marked
``syncscope("singlethread")`` or ``syncscope("<target-scope>")``.
.. _fastmath:
@ -5034,7 +5043,7 @@ which is the string ``llvm.loop.licm_versioning.disable``. For example:
Loop distribution allows splitting a loop into multiple loops. Currently,
this is only performed if the entire loop cannot be vectorized due to unsafe
memory dependencies. The transformation will atempt to isolate the unsafe
memory dependencies. The transformation will attempt to isolate the unsafe
dependencies into their own loop.
This metadata can be used to selectively enable or disable distribution of the
@ -7380,7 +7389,7 @@ Syntax:
::
<result> = load [volatile] <ty>, <ty>* <pointer>[, align <alignment>][, !nontemporal !<index>][, !invariant.load !<index>][, !invariant.group !<index>][, !nonnull !<index>][, !dereferenceable !<deref_bytes_node>][, !dereferenceable_or_null !<deref_bytes_node>][, !align !<align_node>]
<result> = load atomic [volatile] <ty>, <ty>* <pointer> [singlethread] <ordering>, align <alignment> [, !invariant.group !<index>]
<result> = load atomic [volatile] <ty>, <ty>* <pointer> [syncscope("<target-scope>")] <ordering>, align <alignment> [, !invariant.group !<index>]
!<index> = !{ i32 1 }
!<deref_bytes_node> = !{i64 <dereferenceable_bytes>}
!<align_node> = !{ i64 <value_alignment> }
@ -7401,14 +7410,14 @@ modify the number or order of execution of this ``load`` with other
:ref:`volatile operations <volatile>`.
If the ``load`` is marked as ``atomic``, it takes an extra :ref:`ordering
<ordering>` and optional ``singlethread`` argument. The ``release`` and
``acq_rel`` orderings are not valid on ``load`` instructions. Atomic loads
produce :ref:`defined <memmodel>` results when they may see multiple atomic
stores. The type of the pointee must be an integer, pointer, or floating-point
type whose bit width is a power of two greater than or equal to eight and less
than or equal to a target-specific size limit. ``align`` must be explicitly
specified on atomic loads, and the load has undefined behavior if the alignment
is not set to a value which is at least the size in bytes of the
<ordering>` and optional ``syncscope("<target-scope>")`` argument. The
``release`` and ``acq_rel`` orderings are not valid on ``load`` instructions.
Atomic loads produce :ref:`defined <memmodel>` results when they may see
multiple atomic stores. The type of the pointee must be an integer, pointer, or
floating-point type whose bit width is a power of two greater than or equal to
eight and less than or equal to a target-specific size limit. ``align`` must be
explicitly specified on atomic loads, and the load has undefined behavior if the
alignment is not set to a value which is at least the size in bytes of the
pointee. ``!nontemporal`` does not have any defined semantics for atomic loads.
The optional constant ``align`` argument specifies the alignment of the
@ -7509,7 +7518,7 @@ Syntax:
::
store [volatile] <ty> <value>, <ty>* <pointer>[, align <alignment>][, !nontemporal !<index>][, !invariant.group !<index>] ; yields void
store atomic [volatile] <ty> <value>, <ty>* <pointer> [singlethread] <ordering>, align <alignment> [, !invariant.group !<index>] ; yields void
store atomic [volatile] <ty> <value>, <ty>* <pointer> [syncscope("<target-scope>")] <ordering>, align <alignment> [, !invariant.group !<index>] ; yields void
Overview:
"""""""""
@ -7529,14 +7538,14 @@ allowed to modify the number or order of execution of this ``store`` with other
structural type <t_opaque>`) can be stored.
If the ``store`` is marked as ``atomic``, it takes an extra :ref:`ordering
<ordering>` and optional ``singlethread`` argument. The ``acquire`` and
``acq_rel`` orderings aren't valid on ``store`` instructions. Atomic loads
produce :ref:`defined <memmodel>` results when they may see multiple atomic
stores. The type of the pointee must be an integer, pointer, or floating-point
type whose bit width is a power of two greater than or equal to eight and less
than or equal to a target-specific size limit. ``align`` must be explicitly
specified on atomic stores, and the store has undefined behavior if the
alignment is not set to a value which is at least the size in bytes of the
<ordering>` and optional ``syncscope("<target-scope>")`` argument. The
``acquire`` and ``acq_rel`` orderings aren't valid on ``store`` instructions.
Atomic loads produce :ref:`defined <memmodel>` results when they may see
multiple atomic stores. The type of the pointee must be an integer, pointer, or
floating-point type whose bit width is a power of two greater than or equal to
eight and less than or equal to a target-specific size limit. ``align`` must be
explicitly specified on atomic stores, and the store has undefined behavior if
the alignment is not set to a value which is at least the size in bytes of the
pointee. ``!nontemporal`` does not have any defined semantics for atomic stores.
The optional constant ``align`` argument specifies the alignment of the
@ -7597,7 +7606,7 @@ Syntax:
::
fence [singlethread] <ordering> ; yields void
fence [syncscope("<target-scope>")] <ordering> ; yields void
Overview:
"""""""""
@ -7631,17 +7640,17 @@ A ``fence`` which has ``seq_cst`` ordering, in addition to having both
``acquire`` and ``release`` semantics specified above, participates in
the global program order of other ``seq_cst`` operations and/or fences.
The optional ":ref:`singlethread <singlethread>`" argument specifies
that the fence only synchronizes with other fences in the same thread.
(This is useful for interacting with signal handlers.)
A ``fence`` instruction can also take an optional
":ref:`syncscope <syncscope>`" argument.
Example:
""""""""
.. code-block:: llvm
fence acquire ; yields void
fence singlethread seq_cst ; yields void
fence acquire ; yields void
fence syncscope("singlethread") seq_cst ; yields void
fence syncscope("agent") seq_cst ; yields void
.. _i_cmpxchg:
@ -7653,7 +7662,7 @@ Syntax:
::
cmpxchg [weak] [volatile] <ty>* <pointer>, <ty> <cmp>, <ty> <new> [singlethread] <success ordering> <failure ordering> ; yields { ty, i1 }
cmpxchg [weak] [volatile] <ty>* <pointer>, <ty> <cmp>, <ty> <new> [syncscope("<target-scope>")] <success ordering> <failure ordering> ; yields { ty, i1 }
Overview:
"""""""""
@ -7682,10 +7691,8 @@ must be at least ``monotonic``, the ordering constraint on failure must be no
stronger than that on success, and the failure ordering cannot be either
``release`` or ``acq_rel``.
The optional "``singlethread``" argument declares that the ``cmpxchg``
is only atomic with respect to code (usually signal handlers) running in
the same thread as the ``cmpxchg``. Otherwise the cmpxchg is atomic with
respect to all other code in the system.
A ``cmpxchg`` instruction can also take an optional
":ref:`syncscope <syncscope>`" argument.
The pointer passed into cmpxchg must have alignment greater than or
equal to the size in memory of the operand.
@ -7739,7 +7746,7 @@ Syntax:
::
atomicrmw [volatile] <operation> <ty>* <pointer>, <ty> <value> [singlethread] <ordering> ; yields ty
atomicrmw [volatile] <operation> <ty>* <pointer>, <ty> <value> [syncscope("<target-scope>")] <ordering> ; yields ty
Overview:
"""""""""
@ -7773,6 +7780,9 @@ be a pointer to that type. If the ``atomicrmw`` is marked as
order of execution of this ``atomicrmw`` with other :ref:`volatile
operations <volatile>`.
A ``atomicrmw`` instruction can also take an optional
":ref:`syncscope <syncscope>`" argument.
Semantics:
""""""""""
@ -10272,6 +10282,8 @@ overlap. It copies "len" bytes of memory over. If the argument is known
to be aligned to some boundary, this can be specified as the fourth
argument, otherwise it should be set to 0 or 1 (both meaning no alignment).
.. _int_memmove:
'``llvm.memmove``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -10327,6 +10339,8 @@ copies "len" bytes of memory over. If the argument is known to be
aligned to some boundary, this can be specified as the fourth argument,
otherwise it should be set to 0 or 1 (both meaning no alignment).
.. _int_memset:
'``llvm.memset.*``' Intrinsics
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -14168,4 +14182,154 @@ In the most general case call to the '``llvm.memcpy.element.unordered.atomic.*``
lowered to a call to the symbol ``__llvm_memcpy_element_unordered_atomic_*``. Where '*'
is replaced with an actual element size.
Optimizer is allowed to inline memory copy when it's profitable to do so.
'``llvm.memmove.element.unordered.atomic``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Syntax:
"""""""
This is an overloaded intrinsic. You can use
``llvm.memmove.element.unordered.atomic`` on any integer bit width and for
different address spaces. Not all targets support all bit widths however.
::
declare void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i32(i8* <dest>,
i8* <src>,
i32 <len>,
i32 <element_size>)
declare void @llvm.memmove.element.unordered.atomic.p0i8.p0i8.i64(i8* <dest>,
i8* <src>,
i64 <len>,
i32 <element_size>)
Overview:
"""""""""
The '``llvm.memmove.element.unordered.atomic.*``' intrinsic is a specialization
of the '``llvm.memmove.*``' intrinsic. It differs in that the ``dest`` and
``src`` are treated as arrays with elements that are exactly ``element_size``
bytes, and the copy between buffers uses a sequence of
:ref:`unordered atomic <ordering>` load/store operations that are a positive
integer multiple of the ``element_size`` in size.
Arguments:
""""""""""
The first three arguments are the same as they are in the
:ref:`@llvm.memmove <int_memmove>` intrinsic, with the added constraint that
``len`` is required to be a positive integer multiple of the ``element_size``.
If ``len`` is not a positive integer multiple of ``element_size``, then the
behaviour of the intrinsic is undefined.
``element_size`` must be a compile-time constant positive power of two no
greater than a target-specific atomic access size limit.
For each of the input pointers the ``align`` parameter attribute must be
specified. It must be a power of two no less than the ``element_size``. Caller
guarantees that both the source and destination pointers are aligned to that
boundary.
Semantics:
""""""""""
The '``llvm.memmove.element.unordered.atomic.*``' intrinsic copies ``len`` bytes
of memory from the source location to the destination location. These locations
are allowed to overlap. The memory copy is performed as a sequence of load/store
operations where each access is guaranteed to be a multiple of ``element_size``
bytes wide and aligned at an ``element_size`` boundary.
The order of the copy is unspecified. The same value may be read from the source
buffer many times, but only one write is issued to the destination buffer per
element. It is well defined to have concurrent reads and writes to both source
and destination provided those reads and writes are unordered atomic when
specified.
This intrinsic does not provide any additional ordering guarantees over those
provided by a set of unordered loads from the source location and stores to the
destination.
Lowering:
"""""""""
In the most general case call to the
'``llvm.memmove.element.unordered.atomic.*``' is lowered to a call to the symbol
``__llvm_memmove_element_unordered_atomic_*``. Where '*' is replaced with an
actual element size.
The optimizer is allowed to inline the memory copy when it's profitable to do so.
.. _int_memset_element_unordered_atomic:
'``llvm.memset.element.unordered.atomic``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Syntax:
"""""""
This is an overloaded intrinsic. You can use ``llvm.memset.element.unordered.atomic`` on
any integer bit width and for different address spaces. Not all targets
support all bit widths however.
::
declare void @llvm.memset.element.unordered.atomic.p0i8.i32(i8* <dest>,
i8 <value>,
i32 <len>,
i32 <element_size>)
declare void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* <dest>,
i8 <value>,
i64 <len>,
i32 <element_size>)
Overview:
"""""""""
The '``llvm.memset.element.unordered.atomic.*``' intrinsic is a specialization of the
'``llvm.memset.*``' intrinsic. It differs in that the ``dest`` is treated as an array
with elements that are exactly ``element_size`` bytes, and the assignment to that array
uses uses a sequence of :ref:`unordered atomic <ordering>` store operations
that are a positive integer multiple of the ``element_size`` in size.
Arguments:
""""""""""
The first three arguments are the same as they are in the :ref:`@llvm.memset <int_memset>`
intrinsic, with the added constraint that ``len`` is required to be a positive integer
multiple of the ``element_size``. If ``len`` is not a positive integer multiple of
``element_size``, then the behaviour of the intrinsic is undefined.
``element_size`` must be a compile-time constant positive power of two no greater than
target-specific atomic access size limit.
The ``dest`` input pointer must have the ``align`` parameter attribute specified. It
must be a power of two no less than the ``element_size``. Caller guarantees that
the destination pointer is aligned to that boundary.
Semantics:
""""""""""
The '``llvm.memset.element.unordered.atomic.*``' intrinsic sets the ``len`` bytes of
memory starting at the destination location to the given ``value``. The memory is
set with a sequence of store operations where each access is guaranteed to be a
multiple of ``element_size`` bytes wide and aligned at an ``element_size`` boundary.
The order of the assignment is unspecified. Only one write is issued to the
destination buffer per element. It is well defined to have concurrent reads and
writes to the destination provided those reads and writes are unordered atomic
when specified.
This intrinsic does not provide any additional ordering guarantees over those
provided by a set of unordered stores to the destination.
Lowering:
"""""""""
In the most general case call to the '``llvm.memset.element.unordered.atomic.*``' is
lowered to a call to the symbol ``__llvm_memset_element_unordered_atomic_*``. Where '*'
is replaced with an actual element size.
The optimizer is allowed to inline the memory assignment when it's profitable to do so.

View File

@ -587,7 +587,7 @@ The simplest way is to have a statically initialized global object inside
Alternatively, you may define an optional init function and it will receive
the program arguments that you can read and modify. Do this **only** if you
realy need to access ``argv``/``argc``.
really need to access ``argv``/``argc``.
.. code-block:: c++

View File

@ -12,7 +12,7 @@ Welcome to Chapter 1 of the "Building an ORC-based JIT in LLVM" tutorial. This
tutorial runs through the implementation of a JIT compiler using LLVM's
On-Request-Compilation (ORC) APIs. It begins with a simplified version of the
KaleidoscopeJIT class used in the
`Implementing a language with LLVM <LangImpl1.html>`_ tutorials and then
`Implementing a language with LLVM <LangImpl01.html>`_ tutorials and then
introduces new features like optimization, lazy compilation and remote
execution.
@ -41,7 +41,7 @@ The structure of the tutorial is:
a remote process with reduced privileges using the JIT Remote APIs.
To provide input for our JIT we will use the Kaleidoscope REPL from
`Chapter 7 <LangImpl7.html>`_ of the "Implementing a language in LLVM tutorial",
`Chapter 7 <LangImpl07.html>`_ of the "Implementing a language in LLVM tutorial",
with one minor modification: We will remove the FunctionPassManager from the
code for that chapter and replace it with optimization support in our JIT class
in Chapter #2.
@ -91,8 +91,8 @@ KaleidoscopeJIT
In the previous section we described our API, now we examine a simple
implementation of it: The KaleidoscopeJIT class [1]_ that was used in the
`Implementing a language with LLVM <LangImpl1.html>`_ tutorials. We will use
the REPL code from `Chapter 7 <LangImpl7.html>`_ of that tutorial to supply the
`Implementing a language with LLVM <LangImpl01.html>`_ tutorials. We will use
the REPL code from `Chapter 7 <LangImpl07.html>`_ of that tutorial to supply the
input for our JIT: Each time the user enters an expression the REPL will add a
new IR module containing the code for that expression to the JIT. If the
expression is a top-level expression like '1+1' or 'sin(x)', the REPL will also

View File

@ -25,7 +25,7 @@ IRTransformLayer, to add IR optimization support to KaleidoscopeJIT.
Optimizing Modules using the IRTransformLayer
=============================================
In `Chapter 4 <LangImpl4.html>`_ of the "Implementing a language with LLVM"
In `Chapter 4 <LangImpl04.html>`_ of the "Implementing a language with LLVM"
tutorial series the llvm *FunctionPassManager* is introduced as a means for
optimizing LLVM IR. Interested readers may read that chapter for details, but
in short: to optimize a Module we create an llvm::FunctionPassManager
@ -148,7 +148,7 @@ At the bottom of our JIT we add a private method to do the actual optimization:
*optimizeModule*. This function sets up a FunctionPassManager, adds some passes
to it, runs it over every function in the module, and then returns the mutated
module. The specific optimizations are the same ones used in
`Chapter 4 <LangImpl4.html>`_ of the "Implementing a language with LLVM"
`Chapter 4 <LangImpl04.html>`_ of the "Implementing a language with LLVM"
tutorial series. Readers may visit that chapter for a more in-depth
discussion of these, and of IR optimization in general.

View File

@ -10,7 +10,7 @@ Chapter 2 Introduction
Welcome to Chapter 2 of the "`Implementing a language with
LLVM <index.html>`_" tutorial. This chapter shows you how to use the
lexer, built in `Chapter 1 <LangImpl1.html>`_, to build a full
lexer, built in `Chapter 1 <LangImpl01.html>`_, to build a full
`parser <http://en.wikipedia.org/wiki/Parsing>`_ for our Kaleidoscope
language. Once we have a parser, we'll define and build an `Abstract
Syntax Tree <http://en.wikipedia.org/wiki/Abstract_syntax_tree>`_ (AST).

View File

@ -10,7 +10,7 @@ Chapter 3 Introduction
Welcome to Chapter 3 of the "`Implementing a language with
LLVM <index.html>`_" tutorial. This chapter shows you how to transform
the `Abstract Syntax Tree <LangImpl2.html>`_, built in Chapter 2, into
the `Abstract Syntax Tree <LangImpl02.html>`_, built in Chapter 2, into
LLVM IR. This will teach you a little bit about how LLVM does things, as
well as demonstrate how easy it is to use. It's much more work to build
a lexer and parser than it is to generate LLVM IR code. :)
@ -362,7 +362,7 @@ end of the new basic block. Basic blocks in LLVM are an important part
of functions that define the `Control Flow
Graph <http://en.wikipedia.org/wiki/Control_flow_graph>`_. Since we
don't have any control flow, our functions will only contain one block
at this point. We'll fix this in `Chapter 5 <LangImpl5.html>`_ :).
at this point. We'll fix this in `Chapter 5 <LangImpl05.html>`_ :).
Next we add the function arguments to the NamedValues map (after first clearing
it out) so that they're accessible to ``VariableExprAST`` nodes.
@ -540,7 +540,7 @@ functions referencing each other.
This wraps up the third chapter of the Kaleidoscope tutorial. Up next,
we'll describe how to `add JIT codegen and optimizer
support <LangImpl4.html>`_ to this so we can actually start running
support <LangImpl04.html>`_ to this so we can actually start running
code!
Full Code Listing

View File

@ -622,7 +622,7 @@ This completes the JIT and optimizer chapter of the Kaleidoscope
tutorial. At this point, we can compile a non-Turing-complete
programming language, optimize and JIT compile it in a user-driven way.
Next up we'll look into `extending the language with control flow
constructs <LangImpl5.html>`_, tackling some interesting LLVM IR issues
constructs <LangImpl05.html>`_, tackling some interesting LLVM IR issues
along the way.
Full Code Listing

View File

@ -269,7 +269,7 @@ Phi nodes:
#. Values that are implicit in the structure of your AST, such as the
Phi node in this case.
In `Chapter 7 <LangImpl7.html>`_ of this tutorial ("mutable variables"),
In `Chapter 7 <LangImpl07.html>`_ of this tutorial ("mutable variables"),
we'll talk about #1 in depth. For now, just believe me that you don't
need SSA construction to handle this case. For #2, you have the choice
of using the techniques that we will describe for #1, or you can insert
@ -790,7 +790,7 @@ of the tutorial. In this chapter we added two control flow constructs,
and used them to motivate a couple of aspects of the LLVM IR that are
important for front-end implementors to know. In the next chapter of our
saga, we will get a bit crazier and add `user-defined
operators <LangImpl6.html>`_ to our poor innocent language.
operators <LangImpl06.html>`_ to our poor innocent language.
Full Code Listing
=================

View File

@ -41,7 +41,7 @@ The point of going into user-defined operators in a tutorial like this
is to show the power and flexibility of using a hand-written parser.
Thus far, the parser we have been implementing uses recursive descent
for most parts of the grammar and operator precedence parsing for the
expressions. See `Chapter 2 <LangImpl2.html>`_ for details. By
expressions. See `Chapter 2 <LangImpl02.html>`_ for details. By
using operator precedence parsing, it is very easy to allow
the programmer to introduce new operators into the grammar: the grammar
is dynamically extensible as the JIT runs.
@ -734,7 +734,7 @@ side-effects, but it can't actually define and mutate a variable itself.
Strikingly, variable mutation is an important feature of some languages,
and it is not at all obvious how to `add support for mutable
variables <LangImpl7.html>`_ without having to add an "SSA construction"
variables <LangImpl07.html>`_ without having to add an "SSA construction"
phase to your front-end. In the next chapter, we will describe how you
can add variable mutation without building SSA in your front-end.

View File

@ -258,7 +258,7 @@ a truth value as a 1-bit (bool) value.
let then_bb = append_block context "then" the_function in
position_at_end then_bb builder;
As opposed to the `C++ tutorial <LangImpl5.html>`_, we have to build our
As opposed to the `C++ tutorial <LangImpl05.html>`_, we have to build our
basic blocks bottom up since we can't have dangling BasicBlocks. We
start off by saving a pointer to the first block (which might not be the
entry block), which we'll need to build a conditional branch later. We

View File

@ -48,6 +48,7 @@ class KaleidoscopeJIT {
KaleidoscopeJIT()
: TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
ObjectLayer([]() { return std::make_shared<SectionMemoryManager>(); }),
CompileLayer(ObjectLayer, SimpleCompiler(*TM)) {
llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
}
@ -74,9 +75,8 @@ class KaleidoscopeJIT {
// Add the set to the JIT with the resolver we created above and a newly
// created SectionMemoryManager.
return CompileLayer.addModule(std::move(M),
make_unique<SectionMemoryManager>(),
std::move(Resolver));
return cantFail(CompileLayer.addModule(std::move(M),
std::move(Resolver)));
}
JITSymbol findSymbol(const std::string Name) {
@ -87,7 +87,7 @@ class KaleidoscopeJIT {
}
void removeModule(ModuleHandle H) {
CompileLayer.removeModule(H);
cantFail(CompileLayer.removeModule(H));
}
};

View File

@ -1150,7 +1150,7 @@ static void HandleTopLevelExpression() {
// Get the symbol's address and cast it to the right type (takes no
// arguments, returns a double) so we can call it as a native function.
double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
fprintf(stderr, "Evaluated to %f\n", FP());
// Delete the anonymous expression module from the JIT.

View File

@ -57,6 +57,7 @@ class KaleidoscopeJIT {
KaleidoscopeJIT()
: TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
ObjectLayer([]() { return std::make_shared<SectionMemoryManager>(); }),
CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
OptimizeLayer(CompileLayer,
[this](std::shared_ptr<Module> M) {
@ -87,9 +88,8 @@ class KaleidoscopeJIT {
// Add the set to the JIT with the resolver we created above and a newly
// created SectionMemoryManager.
return OptimizeLayer.addModule(std::move(M),
make_unique<SectionMemoryManager>(),
std::move(Resolver));
return cantFail(OptimizeLayer.addModule(std::move(M),
std::move(Resolver)));
}
JITSymbol findSymbol(const std::string Name) {
@ -100,7 +100,7 @@ class KaleidoscopeJIT {
}
void removeModule(ModuleHandle H) {
OptimizeLayer.removeModule(H);
cantFail(OptimizeLayer.removeModule(H));
}
private:

View File

@ -1150,7 +1150,7 @@ static void HandleTopLevelExpression() {
// Get the symbol's address and cast it to the right type (takes no
// arguments, returns a double) so we can call it as a native function.
double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
fprintf(stderr, "Evaluated to %f\n", FP());
// Delete the anonymous expression module from the JIT.

View File

@ -63,6 +63,7 @@ class KaleidoscopeJIT {
KaleidoscopeJIT()
: TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
ObjectLayer([]() { return std::make_shared<SectionMemoryManager>(); }),
CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
OptimizeLayer(CompileLayer,
[this](std::shared_ptr<Module> M) {
@ -100,9 +101,7 @@ class KaleidoscopeJIT {
// Add the set to the JIT with the resolver we created above and a newly
// created SectionMemoryManager.
return CODLayer.addModule(std::move(M),
make_unique<SectionMemoryManager>(),
std::move(Resolver));
return cantFail(CODLayer.addModule(std::move(M), std::move(Resolver)));
}
JITSymbol findSymbol(const std::string Name) {
@ -113,7 +112,7 @@ class KaleidoscopeJIT {
}
void removeModule(ModuleHandle H) {
CODLayer.removeModule(H);
cantFail(CODLayer.removeModule(H));
}
private:

View File

@ -1150,7 +1150,7 @@ static void HandleTopLevelExpression() {
// Get the symbol's address and cast it to the right type (takes no
// arguments, returns a double) so we can call it as a native function.
double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
fprintf(stderr, "Evaluated to %f\n", FP());
// Delete the anonymous expression module from the JIT.

View File

@ -90,6 +90,7 @@ class KaleidoscopeJIT {
KaleidoscopeJIT()
: TM(EngineBuilder().selectTarget()),
DL(TM->createDataLayout()),
ObjectLayer([]() { return std::make_shared<SectionMemoryManager>(); }),
CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
OptimizeLayer(CompileLayer,
[this](std::shared_ptr<Module> M) {
@ -127,9 +128,8 @@ class KaleidoscopeJIT {
// Add the set to the JIT with the resolver we created above and a newly
// created SectionMemoryManager.
return OptimizeLayer.addModule(std::move(M),
make_unique<SectionMemoryManager>(),
std::move(Resolver));
return cantFail(OptimizeLayer.addModule(std::move(M),
std::move(Resolver)));
}
Error addFunctionAST(std::unique_ptr<FunctionAST> FnAST) {
@ -175,7 +175,7 @@ class KaleidoscopeJIT {
addModule(std::move(M));
auto Sym = findSymbol(SharedFnAST->getName() + "$impl");
assert(Sym && "Couldn't find compiled function?");
JITTargetAddress SymAddr = Sym.getAddress();
JITTargetAddress SymAddr = cantFail(Sym.getAddress());
if (auto Err =
IndirectStubsMgr->updatePointer(mangle(SharedFnAST->getName()),
SymAddr)) {
@ -195,7 +195,7 @@ class KaleidoscopeJIT {
}
void removeModule(ModuleHandle H) {
OptimizeLayer.removeModule(H);
cantFail(OptimizeLayer.removeModule(H));
}
private:

View File

@ -1153,7 +1153,7 @@ static void HandleTopLevelExpression() {
// Get the symbol's address and cast it to the right type (takes no
// arguments, returns a double) so we can call it as a native function.
double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
fprintf(stderr, "Evaluated to %f\n", FP());
// Delete the anonymous expression module from the JIT.

View File

@ -97,6 +97,15 @@ class KaleidoscopeJIT {
: TM(EngineBuilder().selectTarget(Triple(Remote.getTargetTriple()), "",
"", SmallVector<std::string, 0>())),
DL(TM->createDataLayout()),
ObjectLayer([&Remote]() {
std::unique_ptr<MyRemote::RCMemoryManager> MemMgr;
if (auto Err = Remote.createRemoteMemoryManager(MemMgr)) {
logAllUnhandledErrors(std::move(Err), errs(),
"Error creating remote memory manager:");
exit(1);
}
return MemMgr;
}),
CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
OptimizeLayer(CompileLayer,
[this](std::shared_ptr<Module> M) {
@ -146,18 +155,10 @@ class KaleidoscopeJIT {
return JITSymbol(nullptr);
});
std::unique_ptr<MyRemote::RCMemoryManager> MemMgr;
if (auto Err = Remote.createRemoteMemoryManager(MemMgr)) {
logAllUnhandledErrors(std::move(Err), errs(),
"Error creating remote memory manager:");
exit(1);
}
// Add the set to the JIT with the resolver we created above and a newly
// created SectionMemoryManager.
return OptimizeLayer.addModule(std::move(M),
std::move(MemMgr),
std::move(Resolver));
return cantFail(OptimizeLayer.addModule(std::move(M),
std::move(Resolver)));
}
Error addFunctionAST(std::unique_ptr<FunctionAST> FnAST) {
@ -203,7 +204,7 @@ class KaleidoscopeJIT {
addModule(std::move(M));
auto Sym = findSymbol(SharedFnAST->getName() + "$impl");
assert(Sym && "Couldn't find compiled function?");
JITTargetAddress SymAddr = Sym.getAddress();
JITTargetAddress SymAddr = cantFail(Sym.getAddress());
if (auto Err =
IndirectStubsMgr->updatePointer(mangle(SharedFnAST->getName()),
SymAddr)) {
@ -227,7 +228,7 @@ class KaleidoscopeJIT {
}
void removeModule(ModuleHandle H) {
OptimizeLayer.removeModule(H);
cantFail(OptimizeLayer.removeModule(H));
}
private:

View File

@ -1177,7 +1177,7 @@ static void HandleTopLevelExpression() {
// Get the symbol's address and cast it to the right type (takes no
// arguments, returns a double) so we can call it as a native function.
ExitOnErr(TheJIT->executeRemoteExpr(ExprSymbol.getAddress()));
ExitOnErr(TheJIT->executeRemoteExpr(cantFail(ExprSymbol.getAddress())));
// Delete the anonymous expression module from the JIT.
TheJIT->removeModule(H);

View File

@ -611,7 +611,7 @@ static void HandleTopLevelExpression() {
// Get the symbol's address and cast it to the right type (takes no
// arguments, returns a double) so we can call it as a native function.
double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
fprintf(stderr, "Evaluated to %f\n", FP());
// Delete the anonymous expression module from the JIT.

View File

@ -885,7 +885,7 @@ static void HandleTopLevelExpression() {
// Get the symbol's address and cast it to the right type (takes no
// arguments, returns a double) so we can call it as a native function.
double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
fprintf(stderr, "Evaluated to %f\n", FP());
// Delete the anonymous expression module from the JIT.

View File

@ -1004,7 +1004,7 @@ static void HandleTopLevelExpression() {
// Get the symbol's address and cast it to the right type (takes no
// arguments, returns a double) so we can call it as a native function.
double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
fprintf(stderr, "Evaluated to %f\n", FP());
// Delete the anonymous expression module from the JIT.

View File

@ -1173,7 +1173,7 @@ static void HandleTopLevelExpression() {
// Get the symbol's address and cast it to the right type (takes no
// arguments, returns a double) so we can call it as a native function.
double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
fprintf(stderr, "Evaluated to %f\n", FP());
// Delete the anonymous expression module from the JIT.

View File

@ -45,6 +45,7 @@ class KaleidoscopeJIT {
KaleidoscopeJIT()
: TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
ObjectLayer([]() { return std::make_shared<SectionMemoryManager>(); }),
CompileLayer(ObjectLayer, SimpleCompiler(*TM)) {
llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
}
@ -62,9 +63,8 @@ class KaleidoscopeJIT {
return JITSymbol(nullptr);
},
[](const std::string &S) { return nullptr; });
auto H = CompileLayer.addModule(std::move(M),
make_unique<SectionMemoryManager>(),
std::move(Resolver));
auto H = cantFail(CompileLayer.addModule(std::move(M),
std::move(Resolver)));
ModuleHandles.push_back(H);
return H;
@ -72,7 +72,7 @@ class KaleidoscopeJIT {
void removeModule(ModuleHandleT H) {
ModuleHandles.erase(find(ModuleHandles, H));
CompileLayer.removeModule(H);
cantFail(CompileLayer.removeModule(H));
}
JITSymbol findSymbol(const std::string Name) {
@ -115,7 +115,7 @@ class KaleidoscopeJIT {
return JITSymbol(SymAddr, JITSymbolFlags::Exported);
#ifdef LLVM_ON_WIN32
// For Windows retry without "_" at begining, as RTDyldMemoryManager uses
// For Windows retry without "_" at beginning, as RTDyldMemoryManager uses
// GetProcAddress and standard libraries like msvcrt.dll use names
// with and without "_" (for example "_itoa" but "sin").
if (Name.length() > 2 && Name[0] == '_')

View File

@ -113,8 +113,9 @@ void LLVMOrcDisposeMangledSymbol(char *MangledSymbol);
/**
* Create a lazy compile callback.
*/
LLVMOrcTargetAddress
LLVMOrcErrorCode
LLVMOrcCreateLazyCompileCallback(LLVMOrcJITStackRef JITStack,
LLVMOrcTargetAddress *RetAddr,
LLVMOrcLazyCompileCallbackFn Callback,
void *CallbackCtx);
@ -135,8 +136,9 @@ LLVMOrcErrorCode LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack,
/**
* Add module to be eagerly compiled.
*/
LLVMOrcModuleHandle
LLVMOrcErrorCode
LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle,
LLVMSharedModuleRef Mod,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx);
@ -144,8 +146,9 @@ LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack,
/**
* Add module to be lazily compiled one function at a time.
*/
LLVMOrcModuleHandle
LLVMOrcErrorCode
LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle,
LLVMSharedModuleRef Mod,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx);
@ -153,10 +156,11 @@ LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack,
/**
* Add an object file.
*/
LLVMOrcModuleHandle LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack,
LLVMSharedObjectBufferRef Obj,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx);
LLVMOrcErrorCode LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle,
LLVMSharedObjectBufferRef Obj,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx);
/**
* Remove a module set from the JIT.
@ -164,18 +168,20 @@ LLVMOrcModuleHandle LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack,
* This works for all modules that can be added via OrcAdd*, including object
* files.
*/
void LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack, LLVMOrcModuleHandle H);
LLVMOrcErrorCode LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle H);
/**
* Get symbol address from JIT instance.
*/
LLVMOrcTargetAddress LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack,
const char *SymbolName);
LLVMOrcErrorCode LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack,
LLVMOrcTargetAddress *RetAddr,
const char *SymbolName);
/**
* Dispose of an ORC JIT stack.
*/
void LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack);
LLVMOrcErrorCode LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack);
#ifdef __cplusplus
}

View File

@ -401,7 +401,11 @@ class LLVM_NODISCARD APInt {
/// \brief Determine if this is a value of 1.
///
/// This checks to see if the value of this APInt is one.
bool isOneValue() const { return getActiveBits() == 1; }
bool isOneValue() const {
if (isSingleWord())
return U.VAL == 1;
return countLeadingZerosSlowCase() == BitWidth - 1;
}
/// \brief Determine if this is the largest unsigned value.
///

View File

@ -100,6 +100,8 @@ class function_ref<Ret(Params...)> {
}
public:
function_ref() : callback(nullptr) {}
template <typename Callable>
function_ref(Callable &&callable,
typename std::enable_if<
@ -110,6 +112,8 @@ class function_ref<Ret(Params...)> {
Ret operator()(Params ...params) const {
return callback(callable, std::forward<Params>(params)...);
}
operator bool() const { return callback; }
};
// deleter - Very very very simple method that is used to invoke operator

View File

@ -15,9 +15,9 @@
#ifndef LLVM_ADT_SMALLPTRSET_H
#define LLVM_ADT_SMALLPTRSET_H
#include "llvm/Config/abi-breaking.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include "llvm/Support/ReverseIteration.h"
#include "llvm/Support/type_traits.h"
#include <cassert>
#include <cstddef>
@ -29,15 +29,6 @@
namespace llvm {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
template <class T = void> struct ReverseIterate { static bool value; };
#if LLVM_ENABLE_REVERSE_ITERATION
template <class T> bool ReverseIterate<T>::value = true;
#else
template <class T> bool ReverseIterate<T>::value = false;
#endif
#endif
/// SmallPtrSetImplBase - This is the common code shared among all the
/// SmallPtrSet<>'s, which is almost everything. SmallPtrSet has two modes, one
/// for small and one for large sets.

View File

@ -1353,4 +1353,4 @@ struct BFIDOTGraphTraitsBase : public DefaultDOTGraphTraits {
#undef DEBUG_TYPE
#endif
#endif // LLVM_ANALYSIS_BLOCKFREQUENCYINFOIMPL_H

View File

@ -577,12 +577,17 @@ class CGSCCToFunctionPassAdaptor
// analyses will eventually occur when the module pass completes.
PA.intersect(std::move(PassPA));
// Update the call graph based on this function pass. This may also
// update the current SCC to point to a smaller, more refined SCC.
CurrentC = &updateCGAndAnalysisManagerForFunctionPass(
CG, *CurrentC, *N, AM, UR, DebugLogging);
assert(CG.lookupSCC(*N) == CurrentC &&
"Current SCC not updated to the SCC containing the current node!");
// If the call graph hasn't been preserved, update it based on this
// function pass. This may also update the current SCC to point to
// a smaller, more refined SCC.
auto PAC = PA.getChecker<LazyCallGraphAnalysis>();
if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Module>>()) {
CurrentC = &updateCGAndAnalysisManagerForFunctionPass(
CG, *CurrentC, *N, AM, UR, DebugLogging);
assert(
CG.lookupSCC(*N) == CurrentC &&
"Current SCC not updated to the SCC containing the current node!");
}
}
// By definition we preserve the proxy. And we preserve all analyses on

View File

@ -160,7 +160,7 @@ InlineParams getInlineParams(int Threshold);
/// the -Oz flag.
InlineParams getInlineParams(unsigned OptLevel, unsigned SizeOptLevel);
/// Return the cost associated with a callsite, including paramater passing
/// Return the cost associated with a callsite, including parameter passing
/// and the call/return instruction.
int getCallsiteCost(CallSite CS, const DataLayout &DL);

View File

@ -652,17 +652,23 @@ class LazyCallGraph {
/// Make an existing internal ref edge into a call edge.
///
/// This may form a larger cycle and thus collapse SCCs into TargetN's SCC.
/// If that happens, the deleted SCC pointers are returned. These SCCs are
/// not in a valid state any longer but the pointers will remain valid
/// until destruction of the parent graph instance for the purpose of
/// clearing cached information.
/// If that happens, the optional callback \p MergedCB will be invoked (if
/// provided) on the SCCs being merged away prior to actually performing
/// the merge. Note that this will never include the target SCC as that
/// will be the SCC functions are merged into to resolve the cycle. Once
/// this function returns, these merged SCCs are not in a valid state but
/// the pointers will remain valid until destruction of the parent graph
/// instance for the purpose of clearing cached information. This function
/// also returns 'true' if a cycle was formed and some SCCs merged away as
/// a convenience.
///
/// After this operation, both SourceN's SCC and TargetN's SCC may move
/// position within this RefSCC's postorder list. Any SCCs merged are
/// merged into the TargetN's SCC in order to preserve reachability analyses
/// which took place on that SCC.
SmallVector<SCC *, 1> switchInternalEdgeToCall(Node &SourceN,
Node &TargetN);
bool switchInternalEdgeToCall(
Node &SourceN, Node &TargetN,
function_ref<void(ArrayRef<SCC *> MergedSCCs)> MergeCB = {});
/// Make an existing internal call edge between separate SCCs into a ref
/// edge.

View File

@ -224,6 +224,9 @@ class ObjectSizeOffsetVisitor
SizeOffsetType visitSelectInst(SelectInst &I);
SizeOffsetType visitUndefValue(UndefValue&);
SizeOffsetType visitInstruction(Instruction &I);
private:
bool CheckedZextOrTrunc(APInt &I);
};
typedef std::pair<Value*, Value*> SizeOffsetEvalType;

View File

@ -34,10 +34,10 @@
#include <type_traits>
#include <vector>
namespace llvm {
#define DEBUG_TYPE "region"
namespace llvm {
//===----------------------------------------------------------------------===//
/// RegionBase Implementation
template <class Tr>
@ -901,8 +901,8 @@ void RegionInfoBase<Tr>::calculate(FuncT &F) {
buildRegionsTree(DT->getNode(BB), TopLevelRegion);
}
#undef DEBUG_TYPE
} // end namespace llvm
#undef DEBUG_TYPE
#endif // LLVM_ANALYSIS_REGIONINFOIMPL_H

View File

@ -753,6 +753,28 @@ class TargetTransformInfo {
Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst,
Type *ExpectedType) const;
/// \returns The type to use in a loop expansion of a memcpy call.
Type *getMemcpyLoopLoweringType(LLVMContext &Context, Value *Length,
unsigned SrcAlign, unsigned DestAlign) const;
/// \param[out] OpsOut The operand types to copy RemainingBytes of memory.
/// \param RemainingBytes The number of bytes to copy.
///
/// Calculates the operand types to use when copying \p RemainingBytes of
/// memory, where source and destination alignments are \p SrcAlign and
/// \p DestAlign respectively.
void getMemcpyLoopResidualLoweringType(SmallVectorImpl<Type *> &OpsOut,
LLVMContext &Context,
unsigned RemainingBytes,
unsigned SrcAlign,
unsigned DestAlign) const;
/// \returns True if we want to test the new memcpy lowering functionality in
/// Transform/Utils.
/// Temporary. Will be removed once we move to the new functionality and
/// remove the old.
bool useWideIRMemcpyLoopLowering() const;
/// \returns True if the two functions have compatible attributes for inlining
/// purposes.
bool areInlineCompatible(const Function *Caller,
@ -953,6 +975,12 @@ class TargetTransformInfo::Concept {
virtual unsigned getAtomicMemIntrinsicMaxElementSize() const = 0;
virtual Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst,
Type *ExpectedType) = 0;
virtual Type *getMemcpyLoopLoweringType(LLVMContext &Context, Value *Length,
unsigned SrcAlign,
unsigned DestAlign) const = 0;
virtual void getMemcpyLoopResidualLoweringType(
SmallVectorImpl<Type *> &OpsOut, LLVMContext &Context,
unsigned RemainingBytes, unsigned SrcAlign, unsigned DestAlign) const = 0;
virtual bool areInlineCompatible(const Function *Caller,
const Function *Callee) const = 0;
virtual unsigned getLoadStoreVecRegBitWidth(unsigned AddrSpace) const = 0;
@ -1266,6 +1294,19 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept {
Type *ExpectedType) override {
return Impl.getOrCreateResultFromMemIntrinsic(Inst, ExpectedType);
}
Type *getMemcpyLoopLoweringType(LLVMContext &Context, Value *Length,
unsigned SrcAlign,
unsigned DestAlign) const override {
return Impl.getMemcpyLoopLoweringType(Context, Length, SrcAlign, DestAlign);
}
void getMemcpyLoopResidualLoweringType(SmallVectorImpl<Type *> &OpsOut,
LLVMContext &Context,
unsigned RemainingBytes,
unsigned SrcAlign,
unsigned DestAlign) const override {
Impl.getMemcpyLoopResidualLoweringType(OpsOut, Context, RemainingBytes,
SrcAlign, DestAlign);
}
bool areInlineCompatible(const Function *Caller,
const Function *Callee) const override {
return Impl.areInlineCompatible(Caller, Callee);

View File

@ -444,6 +444,20 @@ class TargetTransformInfoImplBase {
return nullptr;
}
Type *getMemcpyLoopLoweringType(LLVMContext &Context, Value *Length,
unsigned SrcAlign, unsigned DestAlign) const {
return Type::getInt8Ty(Context);
}
void getMemcpyLoopResidualLoweringType(SmallVectorImpl<Type *> &OpsOut,
LLVMContext &Context,
unsigned RemainingBytes,
unsigned SrcAlign,
unsigned DestAlign) const {
for (unsigned i = 0; i != RemainingBytes; ++i)
OpsOut.push_back(Type::getInt8Ty(Context));
}
bool areInlineCompatible(const Function *Caller,
const Function *Callee) const {
return (Caller->getFnAttribute("target-cpu") ==

View File

@ -523,8 +523,7 @@ template <typename T> class ArrayRef;
/// (A)
Optional<bool> isImpliedCondition(const Value *LHS, const Value *RHS,
const DataLayout &DL,
bool InvertAPred = false,
unsigned Depth = 0,
bool LHSIsFalse = false, unsigned Depth = 0,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr,
const DominatorTree *DT = nullptr);

View File

@ -94,7 +94,7 @@ struct WasmFunction {
};
struct WasmDataSegment {
uint32_t Index;
uint32_t MemoryIndex;
WasmInitExpr Offset;
ArrayRef<uint8_t> Content;
};
@ -107,7 +107,7 @@ struct WasmElemSegment {
struct WasmRelocation {
uint32_t Type; // The type of the relocation.
int32_t Index; // Index into function to global index space.
uint32_t Index; // Index into function to global index space.
uint64_t Offset; // Offset from the start of the section.
int64_t Addend; // A value to add to the symbol.
};

View File

@ -59,6 +59,8 @@ enum BlockIDs {
FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID,
SYMTAB_BLOCK_ID,
SYNC_SCOPE_NAMES_BLOCK_ID,
};
/// Identification block contains a string that describes the producer details,
@ -172,6 +174,10 @@ enum OperandBundleTagCode {
OPERAND_BUNDLE_TAG = 1, // TAG: [strchr x N]
};
enum SyncScopeNameCode {
SYNC_SCOPE_NAME = 1,
};
// Value symbol table codes.
enum ValueSymtabCodes {
VST_CODE_ENTRY = 1, // VST_ENTRY: [valueid, namechar x N]
@ -404,12 +410,6 @@ enum AtomicOrderingCodes {
ORDERING_SEQCST = 6
};
/// Encoded SynchronizationScope values.
enum AtomicSynchScopeCodes {
SYNCHSCOPE_SINGLETHREAD = 0,
SYNCHSCOPE_CROSSTHREAD = 1
};
/// Markers and flags for call instruction.
enum CallMarkersFlags {
CALL_TAIL = 0,

View File

@ -608,8 +608,8 @@ class AsmPrinter : public MachineFunctionPass {
// Internal Implementation Details
//===------------------------------------------------------------------===//
/// This emits visibility information about symbol, if this is suported by the
/// target.
/// This emits visibility information about symbol, if this is supported by
/// the target.
void EmitVisibility(MCSymbol *Sym, unsigned Visibility,
bool IsDefinition = true) const;

View File

@ -428,7 +428,7 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
std::pair<unsigned, MVT> LT = TLI->getTypeLegalizationCost(DL, Ty);
bool IsFloat = Ty->getScalarType()->isFloatingPointTy();
bool IsFloat = Ty->isFPOrFPVectorTy();
// Assume that floating point arithmetic operations cost twice as much as
// integer operations.
unsigned OpCost = (IsFloat ? 2 : 1);

View File

@ -16,14 +16,17 @@
#ifndef LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H
#define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H
#include "llvm/ADT/SmallVector.h"
#include <bitset>
#include <cstddef>
#include <cstdint>
#include <functional>
#include <initializer_list>
#include <vector>
namespace llvm {
class LLT;
class MachineInstr;
class MachineInstrBuilder;
class MachineOperand;
@ -58,6 +61,131 @@ class PredicateBitsetImpl : public std::bitset<MaxPredicates> {
}
};
enum {
/// Record the specified instruction
/// - NewInsnID - Instruction ID to define
/// - InsnID - Instruction ID
/// - OpIdx - Operand index
GIM_RecordInsn,
/// Check the feature bits
/// - Expected features
GIM_CheckFeatures,
/// Check the opcode on the specified instruction
/// - InsnID - Instruction ID
/// - Expected opcode
GIM_CheckOpcode,
/// Check the instruction has the right number of operands
/// - InsnID - Instruction ID
/// - Expected number of operands
GIM_CheckNumOperands,
/// Check the type for the specified operand
/// - InsnID - Instruction ID
/// - OpIdx - Operand index
/// - Expected type
GIM_CheckType,
/// Check the register bank for the specified operand
/// - InsnID - Instruction ID
/// - OpIdx - Operand index
/// - Expected register bank (specified as a register class)
GIM_CheckRegBankForClass,
/// Check the operand matches a complex predicate
/// - InsnID - Instruction ID
/// - OpIdx - Operand index
/// - RendererID - The renderer to hold the result
/// - Complex predicate ID
GIM_CheckComplexPattern,
/// Check the operand is a specific integer
/// - InsnID - Instruction ID
/// - OpIdx - Operand index
/// - Expected integer
GIM_CheckConstantInt,
/// Check the operand is a specific literal integer (i.e. MO.isImm() or MO.isCImm() is true).
/// - InsnID - Instruction ID
/// - OpIdx - Operand index
/// - Expected integer
GIM_CheckLiteralInt,
/// Check the operand is a specific intrinsic ID
/// - InsnID - Instruction ID
/// - OpIdx - Operand index
/// - Expected Intrinsic ID
GIM_CheckIntrinsicID,
/// Check the specified operand is an MBB
/// - InsnID - Instruction ID
/// - OpIdx - Operand index
GIM_CheckIsMBB,
/// Check if the specified operand is safe to fold into the current
/// instruction.
/// - InsnID - Instruction ID
GIM_CheckIsSafeToFold,
//=== Renderers ===
/// Mutate an instruction
/// - NewInsnID - Instruction ID to define
/// - OldInsnID - Instruction ID to mutate
/// - NewOpcode - The new opcode to use
GIR_MutateOpcode,
/// Build a new instruction
/// - InsnID - Instruction ID to define
/// - Opcode - The new opcode to use
GIR_BuildMI,
/// Copy an operand to the specified instruction
/// - NewInsnID - Instruction ID to modify
/// - OldInsnID - Instruction ID to copy from
/// - OpIdx - The operand to copy
GIR_Copy,
/// Copy an operand to the specified instruction
/// - NewInsnID - Instruction ID to modify
/// - OldInsnID - Instruction ID to copy from
/// - OpIdx - The operand to copy
/// - SubRegIdx - The subregister to copy
GIR_CopySubReg,
/// Add an implicit register def to the specified instruction
/// - InsnID - Instruction ID to modify
/// - RegNum - The register to add
GIR_AddImplicitDef,
/// Add an implicit register use to the specified instruction
/// - InsnID - Instruction ID to modify
/// - RegNum - The register to add
GIR_AddImplicitUse,
/// Add an register to the specified instruction
/// - InsnID - Instruction ID to modify
/// - RegNum - The register to add
GIR_AddRegister,
/// Add an immediate to the specified instruction
/// - InsnID - Instruction ID to modify
/// - Imm - The immediate to add
GIR_AddImm,
/// Render complex operands to the specified instruction
/// - InsnID - Instruction ID to modify
/// - RendererID - The renderer to call
GIR_ComplexRenderer,
/// Constrain an instruction operand to a register class.
/// - InsnID - Instruction ID to modify
/// - OpIdx - Operand index
/// - RCEnum - Register class enumeration value
GIR_ConstrainOperandRC,
/// Constrain an instructions operands according to the instruction
/// description.
/// - InsnID - Instruction ID to modify
GIR_ConstrainSelectedInstOperands,
/// Merge all memory operands into instruction.
/// - InsnID - Instruction ID to modify
GIR_MergeMemOperands,
/// Erase from parent.
/// - InsnID - Instruction ID to erase
GIR_EraseFromParent,
/// A successful emission
GIR_Done,
};
/// Provides the logic to select generic machine instructions.
class InstructionSelector {
public:
@ -78,9 +206,39 @@ class InstructionSelector {
protected:
using ComplexRendererFn = std::function<void(MachineInstrBuilder &)>;
using RecordedMIVector = SmallVector<MachineInstr *, 4>;
using NewMIVector = SmallVector<MachineInstrBuilder, 4>;
struct MatcherState {
std::vector<ComplexRendererFn> Renderers;
RecordedMIVector MIs;
MatcherState(unsigned MaxRenderers);
};
public:
template <class PredicateBitset, class ComplexMatcherMemFn>
struct MatcherInfoTy {
const LLT *TypeObjects;
const PredicateBitset *FeatureBitsets;
const std::vector<ComplexMatcherMemFn> ComplexPredicates;
};
protected:
InstructionSelector();
/// Execute a given matcher table and return true if the match was successful
/// and false otherwise.
template <class TgtInstructionSelector, class PredicateBitset,
class ComplexMatcherMemFn>
bool executeMatchTable(
TgtInstructionSelector &ISel, NewMIVector &OutMIs, MatcherState &State,
const MatcherInfoTy<PredicateBitset, ComplexMatcherMemFn> &MatcherInfo,
const int64_t *MatchTable, const TargetInstrInfo &TII,
MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
const RegisterBankInfo &RBI,
const PredicateBitset &AvailableFeatures) const;
/// Constrain a register operand of an instruction \p I to a specified
/// register class. This could involve inserting COPYs before (for uses) or
/// after (for defs) and may replace the operand of \p I.

View File

@ -0,0 +1,337 @@
//==-- llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h ---------*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
/// \file This file declares the API for the instruction selector.
/// This class is responsible for selecting machine instructions.
/// It's implemented by the target. It's used by the InstructionSelect pass.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H
#define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H
namespace llvm {
template <class TgtInstructionSelector, class PredicateBitset,
class ComplexMatcherMemFn>
bool InstructionSelector::executeMatchTable(
TgtInstructionSelector &ISel, NewMIVector &OutMIs, MatcherState &State,
const MatcherInfoTy<PredicateBitset, ComplexMatcherMemFn> &MatcherInfo,
const int64_t *MatchTable, const TargetInstrInfo &TII,
MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
const RegisterBankInfo &RBI,
const PredicateBitset &AvailableFeatures) const {
const int64_t *Command = MatchTable;
while (true) {
switch (*Command++) {
case GIM_RecordInsn: {
int64_t NewInsnID = *Command++;
int64_t InsnID = *Command++;
int64_t OpIdx = *Command++;
// As an optimisation we require that MIs[0] is always the root. Refuse
// any attempt to modify it.
assert(NewInsnID != 0 && "Refusing to modify MIs[0]");
(void)NewInsnID;
MachineOperand &MO = State.MIs[InsnID]->getOperand(OpIdx);
if (!MO.isReg()) {
DEBUG(dbgs() << "Rejected (not a register)\n");
return false;
}
if (TRI.isPhysicalRegister(MO.getReg())) {
DEBUG(dbgs() << "Rejected (is a physical register)\n");
return false;
}
assert((size_t)NewInsnID == State.MIs.size() &&
"Expected to store MIs in order");
State.MIs.push_back(MRI.getVRegDef(MO.getReg()));
DEBUG(dbgs() << "MIs[" << NewInsnID << "] = GIM_RecordInsn(" << InsnID
<< ", " << OpIdx << ")\n");
break;
}
case GIM_CheckFeatures: {
int64_t ExpectedBitsetID = *Command++;
DEBUG(dbgs() << "GIM_CheckFeatures(ExpectedBitsetID=" << ExpectedBitsetID
<< ")\n");
if ((AvailableFeatures & MatcherInfo.FeatureBitsets[ExpectedBitsetID]) !=
MatcherInfo.FeatureBitsets[ExpectedBitsetID]) {
DEBUG(dbgs() << "Rejected\n");
return false;
}
break;
}
case GIM_CheckOpcode: {
int64_t InsnID = *Command++;
int64_t Expected = *Command++;
unsigned Opcode = State.MIs[InsnID]->getOpcode();
DEBUG(dbgs() << "GIM_CheckOpcode(MIs[" << InsnID << "], ExpectedOpcode="
<< Expected << ") // Got=" << Opcode << "\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
if (Opcode != Expected)
return false;
break;
}
case GIM_CheckNumOperands: {
int64_t InsnID = *Command++;
int64_t Expected = *Command++;
DEBUG(dbgs() << "GIM_CheckNumOperands(MIs[" << InsnID
<< "], Expected=" << Expected << ")\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
if (State.MIs[InsnID]->getNumOperands() != Expected)
return false;
break;
}
case GIM_CheckType: {
int64_t InsnID = *Command++;
int64_t OpIdx = *Command++;
int64_t TypeID = *Command++;
DEBUG(dbgs() << "GIM_CheckType(MIs[" << InsnID << "]->getOperand("
<< OpIdx << "), TypeID=" << TypeID << ")\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
if (MRI.getType(State.MIs[InsnID]->getOperand(OpIdx).getReg()) !=
MatcherInfo.TypeObjects[TypeID])
return false;
break;
}
case GIM_CheckRegBankForClass: {
int64_t InsnID = *Command++;
int64_t OpIdx = *Command++;
int64_t RCEnum = *Command++;
DEBUG(dbgs() << "GIM_CheckRegBankForClass(MIs[" << InsnID
<< "]->getOperand(" << OpIdx << "), RCEnum=" << RCEnum
<< ")\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
if (&RBI.getRegBankFromRegClass(*TRI.getRegClass(RCEnum)) !=
RBI.getRegBank(State.MIs[InsnID]->getOperand(OpIdx).getReg(), MRI, TRI))
return false;
break;
}
case GIM_CheckComplexPattern: {
int64_t InsnID = *Command++;
int64_t OpIdx = *Command++;
int64_t RendererID = *Command++;
int64_t ComplexPredicateID = *Command++;
DEBUG(dbgs() << "State.Renderers[" << RendererID
<< "] = GIM_CheckComplexPattern(MIs[" << InsnID
<< "]->getOperand(" << OpIdx
<< "), ComplexPredicateID=" << ComplexPredicateID << ")\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
// FIXME: Use std::invoke() when it's available.
if (!(State.Renderers[RendererID] =
(ISel.*MatcherInfo.ComplexPredicates[ComplexPredicateID])(
State.MIs[InsnID]->getOperand(OpIdx))))
return false;
break;
}
case GIM_CheckConstantInt: {
int64_t InsnID = *Command++;
int64_t OpIdx = *Command++;
int64_t Value = *Command++;
DEBUG(dbgs() << "GIM_CheckConstantInt(MIs[" << InsnID << "]->getOperand("
<< OpIdx << "), Value=" << Value << ")\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
if (!isOperandImmEqual(State.MIs[InsnID]->getOperand(OpIdx), Value, MRI))
return false;
break;
}
case GIM_CheckLiteralInt: {
int64_t InsnID = *Command++;
int64_t OpIdx = *Command++;
int64_t Value = *Command++;
DEBUG(dbgs() << "GIM_CheckLiteralInt(MIs[" << InsnID << "]->getOperand(" << OpIdx
<< "), Value=" << Value << ")\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
MachineOperand &OM = State.MIs[InsnID]->getOperand(OpIdx);
if (!OM.isCImm() || !OM.getCImm()->equalsInt(Value))
return false;
break;
}
case GIM_CheckIntrinsicID: {
int64_t InsnID = *Command++;
int64_t OpIdx = *Command++;
int64_t Value = *Command++;
DEBUG(dbgs() << "GIM_CheckIntrinsicID(MIs[" << InsnID << "]->getOperand(" << OpIdx
<< "), Value=" << Value << ")\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
MachineOperand &OM = State.MIs[InsnID]->getOperand(OpIdx);
if (!OM.isIntrinsicID() || OM.getIntrinsicID() != Value)
return false;
break;
}
case GIM_CheckIsMBB: {
int64_t InsnID = *Command++;
int64_t OpIdx = *Command++;
DEBUG(dbgs() << "GIM_CheckIsMBB(MIs[" << InsnID << "]->getOperand("
<< OpIdx << "))\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
if (!State.MIs[InsnID]->getOperand(OpIdx).isMBB())
return false;
break;
}
case GIM_CheckIsSafeToFold: {
int64_t InsnID = *Command++;
DEBUG(dbgs() << "GIM_CheckIsSafeToFold(MIs[" << InsnID << "])\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
if (!isObviouslySafeToFold(*State.MIs[InsnID]))
return false;
break;
}
case GIR_MutateOpcode: {
int64_t OldInsnID = *Command++;
int64_t NewInsnID = *Command++;
int64_t NewOpcode = *Command++;
assert((size_t)NewInsnID == OutMIs.size() &&
"Expected to store MIs in order");
OutMIs.push_back(
MachineInstrBuilder(*State.MIs[OldInsnID]->getParent()->getParent(),
State.MIs[OldInsnID]));
OutMIs[NewInsnID]->setDesc(TII.get(NewOpcode));
DEBUG(dbgs() << "GIR_MutateOpcode(OutMIs[" << NewInsnID << "], MIs["
<< OldInsnID << "], " << NewOpcode << ")\n");
break;
}
case GIR_BuildMI: {
int64_t InsnID = *Command++;
int64_t Opcode = *Command++;
assert((size_t)InsnID == OutMIs.size() &&
"Expected to store MIs in order");
(void)InsnID;
OutMIs.push_back(BuildMI(*State.MIs[0]->getParent(), State.MIs[0],
State.MIs[0]->getDebugLoc(), TII.get(Opcode)));
DEBUG(dbgs() << "GIR_BuildMI(OutMIs[" << InsnID << "], " << Opcode
<< ")\n");
break;
}
case GIR_Copy: {
int64_t NewInsnID = *Command++;
int64_t OldInsnID = *Command++;
int64_t OpIdx = *Command++;
assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(OpIdx));
DEBUG(dbgs() << "GIR_Copy(OutMIs[" << NewInsnID << "], MIs[" << OldInsnID
<< "], " << OpIdx << ")\n");
break;
}
case GIR_CopySubReg: {
int64_t NewInsnID = *Command++;
int64_t OldInsnID = *Command++;
int64_t OpIdx = *Command++;
int64_t SubRegIdx = *Command++;
assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
OutMIs[NewInsnID].addReg(State.MIs[OldInsnID]->getOperand(OpIdx).getReg(),
0, SubRegIdx);
DEBUG(dbgs() << "GIR_CopySubReg(OutMIs[" << NewInsnID << "], MIs["
<< OldInsnID << "], " << OpIdx << ", " << SubRegIdx
<< ")\n");
break;
}
case GIR_AddImplicitDef: {
int64_t InsnID = *Command++;
int64_t RegNum = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
OutMIs[InsnID].addDef(RegNum, RegState::Implicit);
DEBUG(dbgs() << "GIR_AddImplicitDef(OutMIs[" << InsnID << "], " << RegNum
<< ")\n");
break;
}
case GIR_AddImplicitUse: {
int64_t InsnID = *Command++;
int64_t RegNum = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
OutMIs[InsnID].addUse(RegNum, RegState::Implicit);
DEBUG(dbgs() << "GIR_AddImplicitUse(OutMIs[" << InsnID << "], " << RegNum
<< ")\n");
break;
}
case GIR_AddRegister: {
int64_t InsnID = *Command++;
int64_t RegNum = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
OutMIs[InsnID].addReg(RegNum);
DEBUG(dbgs() << "GIR_AddRegister(OutMIs[" << InsnID << "], " << RegNum
<< ")\n");
break;
}
case GIR_AddImm: {
int64_t InsnID = *Command++;
int64_t Imm = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
OutMIs[InsnID].addImm(Imm);
DEBUG(dbgs() << "GIR_AddImm(OutMIs[" << InsnID << "], " << Imm << ")\n");
break;
}
case GIR_ComplexRenderer: {
int64_t InsnID = *Command++;
int64_t RendererID = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
State.Renderers[RendererID](OutMIs[InsnID]);
DEBUG(dbgs() << "GIR_ComplexRenderer(OutMIs[" << InsnID << "], "
<< RendererID << ")\n");
break;
}
case GIR_ConstrainOperandRC: {
int64_t InsnID = *Command++;
int64_t OpIdx = *Command++;
int64_t RCEnum = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
constrainOperandRegToRegClass(*OutMIs[InsnID].getInstr(), OpIdx,
*TRI.getRegClass(RCEnum), TII, TRI, RBI);
DEBUG(dbgs() << "GIR_ConstrainOperandRC(OutMIs[" << InsnID << "], "
<< OpIdx << ", " << RCEnum << ")\n");
break;
}
case GIR_ConstrainSelectedInstOperands: {
int64_t InsnID = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
constrainSelectedInstRegOperands(*OutMIs[InsnID].getInstr(), TII, TRI,
RBI);
DEBUG(dbgs() << "GIR_ConstrainSelectedInstOperands(OutMIs[" << InsnID
<< "])\n");
break;
}
case GIR_MergeMemOperands: {
int64_t InsnID = *Command++;
assert(OutMIs[InsnID] && "Attempted to add to undefined instruction");
for (const auto *FromMI : State.MIs)
for (const auto &MMO : FromMI->memoperands())
OutMIs[InsnID].addMemOperand(MMO);
DEBUG(dbgs() << "GIR_MergeMemOperands(OutMIs[" << InsnID << "])\n");
break;
}
case GIR_EraseFromParent: {
int64_t InsnID = *Command++;
assert(State.MIs[InsnID] &&
"Attempted to erase an undefined instruction");
State.MIs[InsnID]->eraseFromParent();
DEBUG(dbgs() << "GIR_EraseFromParent(MIs[" << InsnID << "])\n");
break;
}
case GIR_Done:
DEBUG(dbgs() << "GIR_Done");
return true;
default:
llvm_unreachable("Unexpected command");
}
}
}
} // end namespace llvm
#endif // LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H

View File

@ -101,11 +101,11 @@ class LegalizerHelper {
const LegalizerInfo &LI;
};
/// Helper function that replaces \p MI with a libcall.
/// Helper function that creates the given libcall.
LegalizerHelper::LegalizeResult
replaceWithLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder,
RTLIB::Libcall Libcall, const CallLowering::ArgInfo &Result,
ArrayRef<CallLowering::ArgInfo> Args);
createLibcall(MachineIRBuilder &MIRBuilder, RTLIB::Libcall Libcall,
const CallLowering::ArgInfo &Result,
ArrayRef<CallLowering::ArgInfo> Args);
} // End namespace llvm.

View File

@ -19,6 +19,7 @@
#include "llvm/CodeGen/LowLevelType.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugLoc.h"
@ -59,6 +60,21 @@ class MachineIRBuilder {
}
void validateTruncExt(unsigned Dst, unsigned Src, bool IsExtend);
MachineInstrBuilder buildBinaryOp(unsigned Opcode, unsigned Res, unsigned Op0, unsigned Op1);
unsigned getDestFromArg(unsigned Reg) { return Reg; }
unsigned getDestFromArg(LLT Ty) {
return getMF().getRegInfo().createGenericVirtualRegister(Ty);
}
unsigned getDestFromArg(const TargetRegisterClass *RC) {
return getMF().getRegInfo().createVirtualRegister(RC);
}
unsigned getRegFromArg(unsigned Reg) { return Reg; }
unsigned getRegFromArg(const MachineInstrBuilder &MIB) {
return MIB->getOperand(0).getReg();
}
public:
/// Getter for the function we currently build.
@ -120,6 +136,22 @@ class MachineIRBuilder {
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildInstr(unsigned Opcode);
/// DAG like Generic method for building arbitrary instructions as above.
/// \Opc opcode for the instruction.
/// \Ty Either LLT/TargetRegisterClass/unsigned types for Dst
/// \Args Variadic list of uses of types(unsigned/MachineInstrBuilder)
/// Uses of type MachineInstrBuilder will perform
/// getOperand(0).getReg() to convert to register.
template <typename DstTy, typename... UseArgsTy>
MachineInstrBuilder buildInstr(unsigned Opc, DstTy &&Ty,
UseArgsTy &&... Args) {
auto MIB = buildInstr(Opc).addDef(getDestFromArg(Ty));
unsigned It[] = {(getRegFromArg(Args))...};
for (const auto &i : It)
MIB.addUse(i);
return MIB;
}
/// Build but don't insert <empty> = \p Opcode <empty>.
///
/// \pre setMF, setBasicBlock or setMI must have been called.
@ -188,6 +220,11 @@ class MachineIRBuilder {
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildAdd(unsigned Res, unsigned Op0,
unsigned Op1);
template <typename DstTy, typename... UseArgsTy>
MachineInstrBuilder buildAdd(DstTy &&Ty, UseArgsTy &&... UseArgs) {
unsigned Res = getDestFromArg(Ty);
return buildAdd(Res, (getRegFromArg(UseArgs))...);
}
/// Build and insert \p Res<def> = G_SUB \p Op0, \p Op1
///
@ -295,6 +332,18 @@ class MachineIRBuilder {
MachineInstrBuilder buildAnd(unsigned Res, unsigned Op0,
unsigned Op1);
/// Build and insert \p Res<def> = G_OR \p Op0, \p Op1
///
/// G_OR sets \p Res to the bitwise or of integer parameters \p Op0 and \p
/// Op1.
///
/// \pre setBasicBlock or setMI must have been called.
/// \pre \p Res, \p Op0 and \p Op1 must be generic virtual registers
/// with the same (scalar or vector) type).
///
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildOr(unsigned Res, unsigned Op0, unsigned Op1);
/// Build and insert \p Res<def> = G_ANYEXT \p Op0
///
/// G_ANYEXT produces a register of the specified width, with bits 0 to
@ -416,6 +465,10 @@ class MachineIRBuilder {
/// \return The newly created instruction.
MachineInstrBuilder buildConstant(unsigned Res, int64_t Val);
template <typename DstType>
MachineInstrBuilder buildConstant(DstType &&Res, int64_t Val) {
return buildConstant(getDestFromArg(Res), Val);
}
/// Build and insert \p Res = G_FCONSTANT \p Val
///
/// G_FCONSTANT is a floating-point constant with the specified size and

View File

@ -93,12 +93,14 @@ class LiveRegUnits {
}
/// Updates liveness when stepping backwards over the instruction \p MI.
/// This removes all register units defined or clobbered in \p MI and then
/// adds the units used (as in use operands) in \p MI.
void stepBackward(const MachineInstr &MI);
/// Mark all register units live during instruction \p MI.
/// This can be used to accumulate live/unoccupied registers over a range of
/// instructions.
void accumulateBackward(const MachineInstr &MI);
/// Adds all register units used, defined or clobbered in \p MI.
/// This is useful when walking over a range of instruction to find registers
/// unused over the whole range.
void accumulate(const MachineInstr &MI);
/// Adds registers living out of block \p MBB.
/// Live out registers are the union of the live-in registers of the successor

View File

@ -650,7 +650,7 @@ class MachineFunction {
MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, uint64_t s,
unsigned base_alignment, const AAMDNodes &AAInfo = AAMDNodes(),
const MDNode *Ranges = nullptr,
SynchronizationScope SynchScope = CrossThread,
SyncScope::ID SSID = SyncScope::System,
AtomicOrdering Ordering = AtomicOrdering::NotAtomic,
AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic);

View File

@ -114,6 +114,9 @@ class MachineMemOperand {
MOInvariant = 1u << 5,
// Reserved for use by target-specific passes.
// Targets may override getSerializableMachineMemOperandTargetFlags() to
// enable MIR serialization/parsing of these flags. If more of these flags
// are added, the MIR printing/parsing code will need to be updated as well.
MOTargetFlag1 = 1u << 6,
MOTargetFlag2 = 1u << 7,
MOTargetFlag3 = 1u << 8,
@ -124,8 +127,8 @@ class MachineMemOperand {
private:
/// Atomic information for this memory operation.
struct MachineAtomicInfo {
/// Synchronization scope for this memory operation.
unsigned SynchScope : 1; // enum SynchronizationScope
/// Synchronization scope ID for this memory operation.
unsigned SSID : 8; // SyncScope::ID
/// Atomic ordering requirements for this memory operation. For cmpxchg
/// atomic operations, atomic ordering requirements when store occurs.
unsigned Ordering : 4; // enum AtomicOrdering
@ -152,7 +155,7 @@ class MachineMemOperand {
unsigned base_alignment,
const AAMDNodes &AAInfo = AAMDNodes(),
const MDNode *Ranges = nullptr,
SynchronizationScope SynchScope = CrossThread,
SyncScope::ID SSID = SyncScope::System,
AtomicOrdering Ordering = AtomicOrdering::NotAtomic,
AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic);
@ -202,9 +205,9 @@ class MachineMemOperand {
/// Return the range tag for the memory reference.
const MDNode *getRanges() const { return Ranges; }
/// Return the synchronization scope for this memory operation.
SynchronizationScope getSynchScope() const {
return static_cast<SynchronizationScope>(AtomicInfo.SynchScope);
/// Returns the synchronization scope ID for this memory operation.
SyncScope::ID getSyncScopeID() const {
return static_cast<SyncScope::ID>(AtomicInfo.SSID);
}
/// Return the atomic ordering requirements for this memory operation. For

View File

@ -340,6 +340,18 @@ namespace RTLIB {
MEMCPY_ELEMENT_UNORDERED_ATOMIC_8,
MEMCPY_ELEMENT_UNORDERED_ATOMIC_16,
MEMMOVE_ELEMENT_UNORDERED_ATOMIC_1,
MEMMOVE_ELEMENT_UNORDERED_ATOMIC_2,
MEMMOVE_ELEMENT_UNORDERED_ATOMIC_4,
MEMMOVE_ELEMENT_UNORDERED_ATOMIC_8,
MEMMOVE_ELEMENT_UNORDERED_ATOMIC_16,
MEMSET_ELEMENT_UNORDERED_ATOMIC_1,
MEMSET_ELEMENT_UNORDERED_ATOMIC_2,
MEMSET_ELEMENT_UNORDERED_ATOMIC_4,
MEMSET_ELEMENT_UNORDERED_ATOMIC_8,
MEMSET_ELEMENT_UNORDERED_ATOMIC_16,
// EXCEPTION HANDLING
UNWIND_RESUME,
@ -515,6 +527,17 @@ namespace RTLIB {
/// MEMCPY_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or
/// UNKNOW_LIBCALL if there is none.
Libcall getMEMCPY_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize);
/// getMEMMOVE_ELEMENT_UNORDERED_ATOMIC - Return
/// MEMMOVE_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or
/// UNKNOW_LIBCALL if there is none.
Libcall getMEMMOVE_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize);
/// getMEMSET_ELEMENT_UNORDERED_ATOMIC - Return
/// MEMSET_ELEMENT_UNORDERED_ATOMIC_* value for the given element size or
/// UNKNOW_LIBCALL if there is none.
Libcall getMEMSET_ELEMENT_UNORDERED_ATOMIC(uint64_t ElementSize);
}
}

View File

@ -235,6 +235,9 @@ class TargetRegisterInfo;
"SDep::Output edge cannot use the zero register!");
Contents.Reg = Reg;
}
raw_ostream &print(raw_ostream &O,
const TargetRegisterInfo *TRI = nullptr) const;
};
template <>
@ -458,7 +461,10 @@ class TargetRegisterInfo;
void dump(const ScheduleDAG *G) const;
void dumpAll(const ScheduleDAG *G) const;
void print(raw_ostream &O, const ScheduleDAG *G) const;
raw_ostream &print(raw_ostream &O,
const SUnit *N = nullptr,
const SUnit *X = nullptr) const;
raw_ostream &print(raw_ostream &O, const ScheduleDAG *G) const;
private:
void ComputeDepth();

View File

@ -927,7 +927,7 @@ class SelectionDAG {
SDValue Cmp, SDValue Swp, MachinePointerInfo PtrInfo,
unsigned Alignment, AtomicOrdering SuccessOrdering,
AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope);
SyncScope::ID SSID);
SDValue getAtomicCmpSwap(unsigned Opcode, const SDLoc &dl, EVT MemVT,
SDVTList VTs, SDValue Chain, SDValue Ptr,
SDValue Cmp, SDValue Swp, MachineMemOperand *MMO);
@ -937,7 +937,7 @@ class SelectionDAG {
SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain,
SDValue Ptr, SDValue Val, const Value *PtrVal,
unsigned Alignment, AtomicOrdering Ordering,
SynchronizationScope SynchScope);
SyncScope::ID SSID);
SDValue getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT, SDValue Chain,
SDValue Ptr, SDValue Val, MachineMemOperand *MMO);

View File

@ -1213,8 +1213,8 @@ class MemSDNode : public SDNode {
/// Returns the Ranges that describes the dereference.
const MDNode *getRanges() const { return MMO->getRanges(); }
/// Return the synchronization scope for this memory operation.
SynchronizationScope getSynchScope() const { return MMO->getSynchScope(); }
/// Returns the synchronization scope ID for this memory operation.
SyncScope::ID getSyncScopeID() const { return MMO->getSyncScopeID(); }
/// Return the atomic ordering requirements for this memory operation. For
/// cmpxchg atomic operations, return the atomic ordering requirements when
@ -1432,8 +1432,8 @@ class ConstantSDNode : public SDNode {
int64_t getSExtValue() const { return Value->getSExtValue(); }
bool isOne() const { return Value->isOne(); }
bool isNullValue() const { return Value->isNullValue(); }
bool isAllOnesValue() const { return Value->isAllOnesValue(); }
bool isNullValue() const { return Value->isZero(); }
bool isAllOnesValue() const { return Value->isMinusOne(); }
bool isOpaque() const { return ConstantSDNodeBits.IsOpaque; }

View File

@ -735,6 +735,10 @@ class Compile3Sym : public SymbolRecord {
uint16_t VersionBackendQFE;
StringRef Version;
void setLanguage(SourceLanguage Lang) {
Flags = CompileSym3Flags((uint32_t(Flags) & 0xFFFFFF00) | uint32_t(Lang));
}
uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; }
uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; }

View File

@ -10,9 +10,11 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEINDEX_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPEINDEX_H
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/Support/Endian.h"
#include <cassert>
#include <cinttypes>
#include <functional>
namespace llvm {
@ -265,6 +267,23 @@ struct TypeIndexOffset {
void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, TypeIndex TI,
TypeCollection &Types);
}
}
template <> struct DenseMapInfo<codeview::TypeIndex> {
static inline codeview::TypeIndex getEmptyKey() {
return codeview::TypeIndex{DenseMapInfo<uint32_t>::getEmptyKey()};
}
static inline codeview::TypeIndex getTombstoneKey() {
return codeview::TypeIndex{DenseMapInfo<uint32_t>::getTombstoneKey()};
}
static unsigned getHashValue(const codeview::TypeIndex &TI) {
return DenseMapInfo<uint32_t>::getHashValue(TI.getIndex());
}
static bool isEqual(const codeview::TypeIndex &LHS,
const codeview::TypeIndex &RHS) {
return LHS == RHS;
}
};
} // namespace llvm
#endif

View File

@ -204,7 +204,9 @@ class LoadedObjectInfo {
/// need to be consistent with the addresses used to query the DIContext and
/// the output of this function should be deterministic, i.e. repeated calls with
/// the same Sec should give the same address.
virtual uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const = 0;
virtual uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const {
return 0;
}
/// If conveniently available, return the content of the given Section.
///
@ -221,12 +223,28 @@ class LoadedObjectInfo {
return false;
}
// FIXME: This is untested and unused anywhere in the LLVM project, it's
// used/needed by Julia (an external project). It should have some coverage
// (at least tests, but ideally example functionality).
/// Obtain a copy of this LoadedObjectInfo.
///
/// The caller is responsible for deallocation once the copy is no longer required.
virtual std::unique_ptr<LoadedObjectInfo> clone() const = 0;
};
template <typename Derived, typename Base = LoadedObjectInfo>
struct LoadedObjectInfoHelper : Base {
protected:
LoadedObjectInfoHelper(const LoadedObjectInfoHelper &) = default;
LoadedObjectInfoHelper() = default;
public:
template <typename... Ts>
LoadedObjectInfoHelper(Ts &&... Args) : Base(std::forward<Ts>(Args)...) {}
std::unique_ptr<llvm::LoadedObjectInfo> clone() const override {
return llvm::make_unique<Derived>(static_cast<const Derived &>(*this));
}
};
} // end namespace llvm
#endif // LLVM_DEBUGINFO_DICONTEXT_H

View File

@ -226,11 +226,7 @@ class DWARFContext : public DIContext {
virtual bool isLittleEndian() const = 0;
virtual uint8_t getAddressSize() const = 0;
virtual const DWARFSection &getInfoSection() = 0;
using TypeSectionMap = MapVector<object::SectionRef, DWARFSection,
std::map<object::SectionRef, unsigned>>;
virtual const TypeSectionMap &getTypesSections() = 0;
virtual void forEachTypesSections(function_ref<void(DWARFSection &)> F) = 0;
virtual StringRef getAbbrevSection() = 0;
virtual const DWARFSection &getLocSection() = 0;
virtual StringRef getARangeSection() = 0;
@ -252,7 +248,8 @@ class DWARFContext : public DIContext {
// Sections for DWARF5 split dwarf proposal.
virtual const DWARFSection &getInfoDWOSection() = 0;
virtual const TypeSectionMap &getTypesDWOSections() = 0;
virtual void
forEachTypesDWOSections(function_ref<void(DWARFSection &)> F) = 0;
virtual StringRef getAbbrevDWOSection() = 0;
virtual const DWARFSection &getLineDWOSection() = 0;
virtual const DWARFSection &getLocDWOSection() = 0;
@ -294,6 +291,9 @@ enum class ErrorPolicy { Halt, Continue };
class DWARFContextInMemory : public DWARFContext {
virtual void anchor();
using TypeSectionMap = MapVector<object::SectionRef, DWARFSection,
std::map<object::SectionRef, unsigned>>;
StringRef FileName;
bool IsLittleEndian;
uint8_t AddressSize;
@ -338,7 +338,8 @@ class DWARFContextInMemory : public DWARFContext {
SmallVector<SmallString<32>, 4> UncompressedSections;
StringRef *MapSectionToMember(StringRef Name);
DWARFSection *mapNameToDWARFSection(StringRef Name);
StringRef *mapSectionToMember(StringRef Name);
/// If Sec is compressed section, decompresses and updates its contents
/// provided by Data. Otherwise leaves it unchanged.
@ -362,7 +363,10 @@ class DWARFContextInMemory : public DWARFContext {
bool isLittleEndian() const override { return IsLittleEndian; }
uint8_t getAddressSize() const override { return AddressSize; }
const DWARFSection &getInfoSection() override { return InfoSection; }
const TypeSectionMap &getTypesSections() override { return TypesSections; }
void forEachTypesSections(function_ref<void(DWARFSection &)> F) override {
for (auto &P : TypesSections)
F(P.second);
}
StringRef getAbbrevSection() override { return AbbrevSection; }
const DWARFSection &getLocSection() override { return LocSection; }
StringRef getARangeSection() override { return ARangeSection; }
@ -389,8 +393,9 @@ class DWARFContextInMemory : public DWARFContext {
// Sections for DWARF5 split dwarf proposal.
const DWARFSection &getInfoDWOSection() override { return InfoDWOSection; }
const TypeSectionMap &getTypesDWOSections() override {
return TypesDWOSections;
void forEachTypesDWOSections(function_ref<void(DWARFSection &)> F) override {
for (auto &P : TypesDWOSections)
F(P.second);
}
StringRef getAbbrevDWOSection() override { return AbbrevDWOSection; }

View File

@ -47,6 +47,7 @@ class DbiModuleDescriptorBuilder {
DbiModuleDescriptorBuilder &
operator=(const DbiModuleDescriptorBuilder &) = delete;
void setPdbFilePathNI(uint32_t NI);
void setObjFileName(StringRef Name);
void addSymbol(codeview::CVSymbol Symbol);
@ -68,6 +69,10 @@ class DbiModuleDescriptorBuilder {
uint32_t calculateSerializedLength() const;
/// Return the offset within the module symbol stream of the next symbol
/// record passed to addSymbol. Add four to account for the signature.
uint32_t getNextSymbolOffset() const { return SymbolByteSize + 4; }
void finalize();
Error finalizeMsfLayout();
@ -81,6 +86,7 @@ class DbiModuleDescriptorBuilder {
msf::MSFBuilder &MSF;
uint32_t SymbolByteSize = 0;
uint32_t PdbFilePathNI = 0;
std::string ModuleName;
std::string ObjFileName;
std::vector<std::string> SourceFiles;

View File

@ -83,6 +83,8 @@ class DbiStream {
FixedStreamArray<SecMapEntry> getSectionMap() const;
void visitSectionContributions(ISectionContribVisitor &Visitor) const;
Expected<StringRef> getECName(uint32_t NI) const;
private:
Error initializeSectionContributionData();
Error initializeSectionHeadersData();

View File

@ -15,6 +15,7 @@
#include "llvm/Support/Error.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include "llvm/Support/BinaryByteStream.h"
@ -54,8 +55,13 @@ class DbiStreamBuilder {
// Add given bytes as a new stream.
Error addDbgStream(pdb::DbgHeaderType Type, ArrayRef<uint8_t> Data);
uint32_t addECName(StringRef Name);
uint32_t calculateSerializedLength() const;
void setPublicsStreamIndex(uint32_t Index);
void setSymbolRecordStreamIndex(uint32_t Index);
Expected<DbiModuleDescriptorBuilder &> addModuleInfo(StringRef ModuleName);
Error addModuleSourceFile(StringRef Module, StringRef File);
Error addModuleSourceFile(DbiModuleDescriptorBuilder &Module, StringRef File);
@ -75,7 +81,7 @@ class DbiStreamBuilder {
private:
struct DebugStream {
ArrayRef<uint8_t> Data;
uint16_t StreamNumber = 0;
uint16_t StreamNumber = kInvalidStreamIndex;
};
Error finalize();
@ -87,7 +93,6 @@ class DbiStreamBuilder {
uint32_t calculateNamesBufferSize() const;
uint32_t calculateDbgStreamsSize() const;
Error generateModiSubstream();
Error generateFileInfoSubstream();
msf::MSFBuilder &Msf;
@ -100,6 +105,8 @@ class DbiStreamBuilder {
uint16_t PdbDllRbld;
uint16_t Flags;
PDB_Machine MachineType;
uint32_t PublicsStreamIndex = kInvalidStreamIndex;
uint32_t SymRecordStreamIndex = kInvalidStreamIndex;
const DbiStreamHeader *Header;
@ -108,6 +115,7 @@ class DbiStreamBuilder {
StringMap<uint32_t> SourceFileNames;
PDBStringTableBuilder ECNamesBuilder;
WritableBinaryStreamRef NamesBuffer;
MutableBinaryByteStream FileInfoBuffer;
std::vector<SectionContrib> SectionContribs;

View File

@ -44,7 +44,7 @@ class NamedStreamMap {
bool get(StringRef Stream, uint32_t &StreamNo) const;
void set(StringRef Stream, uint32_t StreamNo);
void remove(StringRef Stream);
const StringMap<uint32_t> &getStringMap() const { return Mapping; }
iterator_range<StringMapConstIterator<uint32_t>> entries() const;
private:

View File

@ -0,0 +1,49 @@
//===- NativeBuiltinSymbol.h -------------------------------------- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEBUILTINSYMBOL_H
#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEBUILTINSYMBOL_H
#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
namespace llvm {
namespace pdb {
class NativeSession;
class NativeBuiltinSymbol : public NativeRawSymbol {
public:
NativeBuiltinSymbol(NativeSession &PDBSession, SymIndexId Id,
PDB_BuiltinType T, uint64_t L);
~NativeBuiltinSymbol() override;
virtual std::unique_ptr<NativeRawSymbol> clone() const override;
void dump(raw_ostream &OS, int Indent) const override;
PDB_SymType getSymTag() const override;
PDB_BuiltinType getBuiltinType() const override;
bool isConstType() const override;
uint64_t getLength() const override;
bool isUnalignedType() const override;
bool isVolatileType() const override;
protected:
NativeSession &Session;
PDB_BuiltinType Type;
uint64_t Length;
};
} // namespace pdb
} // namespace llvm
#endif

View File

@ -18,7 +18,7 @@ namespace pdb {
class NativeCompilandSymbol : public NativeRawSymbol {
public:
NativeCompilandSymbol(NativeSession &Session, uint32_t SymbolId,
NativeCompilandSymbol(NativeSession &Session, SymIndexId SymbolId,
DbiModuleDescriptor MI);
std::unique_ptr<NativeRawSymbol> clone() const override;

View File

@ -18,7 +18,7 @@ namespace pdb {
class NativeExeSymbol : public NativeRawSymbol {
public:
NativeExeSymbol(NativeSession &Session, uint32_t SymbolId);
NativeExeSymbol(NativeSession &Session, SymIndexId SymbolId);
std::unique_ptr<NativeRawSymbol> clone() const override;

View File

@ -19,9 +19,11 @@ namespace pdb {
class NativeSession;
typedef uint32_t SymIndexId;
class NativeRawSymbol : public IPDBRawSymbol {
public:
NativeRawSymbol(NativeSession &PDBSession, uint32_t SymbolId);
NativeRawSymbol(NativeSession &PDBSession, SymIndexId SymbolId);
virtual std::unique_ptr<NativeRawSymbol> clone() const = 0;
@ -205,7 +207,7 @@ class NativeRawSymbol : public IPDBRawSymbol {
protected:
NativeSession &Session;
uint32_t SymbolId;
SymIndexId SymbolId;
};
} // end namespace pdb

View File

@ -10,9 +10,13 @@
#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVESESSION_H
#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVESESSION_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
#include "llvm/DebugInfo/PDB/Native/NativeBuiltinSymbol.h"
#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Error.h"
@ -35,6 +39,8 @@ class NativeSession : public IPDBSession {
std::unique_ptr<PDBSymbolCompiland>
createCompilandSymbol(DbiModuleDescriptor MI);
SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI);
uint64_t getLoadAddress() const override;
void setLoadAddress(uint64_t Address) override;
std::unique_ptr<PDBSymbolExe> getGlobalScope() override;
@ -77,6 +83,7 @@ class NativeSession : public IPDBSession {
std::unique_ptr<PDBFile> Pdb;
std::unique_ptr<BumpPtrAllocator> Allocator;
std::vector<std::unique_ptr<NativeRawSymbol>> SymbolCache;
DenseMap<codeview::TypeIndex, SymIndexId> TypeIndexToSymbolId;
};
}
}

View File

@ -31,11 +31,13 @@ class MSFBuilder;
namespace pdb {
class DbiStreamBuilder;
class InfoStreamBuilder;
class PublicsStreamBuilder;
class TpiStreamBuilder;
class PDBFileBuilder {
public:
explicit PDBFileBuilder(BumpPtrAllocator &Allocator);
~PDBFileBuilder();
PDBFileBuilder(const PDBFileBuilder &) = delete;
PDBFileBuilder &operator=(const PDBFileBuilder &) = delete;
@ -47,6 +49,7 @@ class PDBFileBuilder {
TpiStreamBuilder &getTpiBuilder();
TpiStreamBuilder &getIpiBuilder();
PDBStringTableBuilder &getStringTableBuilder();
PublicsStreamBuilder &getPublicsBuilder();
Error commit(StringRef Filename);
@ -61,6 +64,7 @@ class PDBFileBuilder {
std::unique_ptr<msf::MSFBuilder> Msf;
std::unique_ptr<InfoStreamBuilder> Info;
std::unique_ptr<DbiStreamBuilder> Dbi;
std::unique_ptr<PublicsStreamBuilder> Publics;
std::unique_ptr<TpiStreamBuilder> Tpi;
std::unique_ptr<TpiStreamBuilder> Ipi;

View File

@ -56,7 +56,6 @@ class PDBStringTable {
const PDBStringTableHeader *Header = nullptr;
codeview::DebugStringTableSubsectionRef Strings;
FixedStreamArray<support::ulittle32_t> IDs;
uint32_t ByteSize = 0;
uint32_t NameCount = 0;
};

View File

@ -25,8 +25,6 @@ struct GSIHashHeader;
class PDBFile;
class PublicsStream {
struct HeaderInfo;
public:
PublicsStream(PDBFile &File, std::unique_ptr<msf::MappedBlockStream> Stream);
~PublicsStream();
@ -65,7 +63,7 @@ class PublicsStream {
FixedStreamArray<support::ulittle32_t> ThunkMap;
FixedStreamArray<SectionOffset> SectionOffsets;
const HeaderInfo *Header;
const PublicsStreamHeader *Header;
const GSIHashHeader *HashHdr;
};
}

View File

@ -0,0 +1,54 @@
//===- PublicsStreamBuilder.h - PDB Publics Stream Creation -----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBPUBLICSTREAMBUILDER_H
#define LLVM_DEBUGINFO_PDB_RAW_PDBPUBLICSTREAMBUILDER_H
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/BinaryStreamWriter.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
namespace llvm {
namespace msf {
class MSFBuilder;
}
namespace pdb {
class PublicsStream;
struct PublicsStreamHeader;
class PublicsStreamBuilder {
public:
explicit PublicsStreamBuilder(msf::MSFBuilder &Msf);
~PublicsStreamBuilder();
PublicsStreamBuilder(const PublicsStreamBuilder &) = delete;
PublicsStreamBuilder &operator=(const PublicsStreamBuilder &) = delete;
Error finalizeMsfLayout();
uint32_t calculateSerializedLength() const;
Error commit(BinaryStreamWriter &PublicsWriter);
uint32_t getStreamIndex() const { return StreamIdx; }
uint32_t getRecordStreamIdx() const { return RecordStreamIdx; }
private:
uint32_t StreamIdx = kInvalidStreamIndex;
uint32_t RecordStreamIdx = kInvalidStreamIndex;
std::vector<PSHashRecord> HashRecords;
msf::MSFBuilder &Msf;
};
} // namespace pdb
} // namespace llvm
#endif

View File

@ -255,6 +255,19 @@ struct ModuleInfoHeader {
/// char ObjFileName[];
};
// This is PSGSIHDR struct defined in
// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
struct PublicsStreamHeader {
support::ulittle32_t SymHash;
support::ulittle32_t AddrMap;
support::ulittle32_t NumThunks;
support::ulittle32_t SizeOfThunk;
support::ulittle16_t ISectThunkTable;
char Padding[2];
support::ulittle32_t OffThunkTable;
support::ulittle32_t NumSections;
};
/// Defines a 128-bit unique identifier. This maps to a GUID on Windows, but
/// is abstracted here for the purposes of non-Windows platforms that don't have
/// the GUID structure defined.

View File

@ -21,6 +21,8 @@
#include <functional>
#include <string>
#include "llvm/Support/Error.h"
namespace llvm {
class GlobalValue;
@ -41,10 +43,11 @@ class JITSymbolFlags {
enum FlagNames : UnderlyingType {
None = 0,
Weak = 1U << 0,
Common = 1U << 1,
Absolute = 1U << 2,
Exported = 1U << 3
HasError = 1U << 0,
Weak = 1U << 1,
Common = 1U << 2,
Absolute = 1U << 3,
Exported = 1U << 4
};
/// @brief Default-construct a JITSymbolFlags instance.
@ -53,6 +56,11 @@ class JITSymbolFlags {
/// @brief Construct a JITSymbolFlags instance from the given flags.
JITSymbolFlags(FlagNames Flags) : Flags(Flags) {}
/// @brief Return true if there was an error retrieving this symbol.
bool hasError() const {
return (Flags & HasError) == HasError;
}
/// @brief Returns true is the Weak flag is set.
bool isWeak() const {
return (Flags & Weak) == Weak;
@ -113,11 +121,17 @@ class JITEvaluatedSymbol {
/// @brief Represents a symbol in the JIT.
class JITSymbol {
public:
using GetAddressFtor = std::function<JITTargetAddress()>;
using GetAddressFtor = std::function<Expected<JITTargetAddress>()>;
/// @brief Create a 'null' symbol that represents failure to find a symbol
/// definition.
JITSymbol(std::nullptr_t) {}
/// @brief Create a 'null' symbol, used to represent a "symbol not found"
/// result from a successful (non-erroneous) lookup.
JITSymbol(std::nullptr_t)
: CachedAddr(0) {}
/// @brief Create a JITSymbol representing an error in the symbol lookup
/// process (e.g. a network failure during a remote lookup).
JITSymbol(Error Err)
: Err(std::move(Err)), Flags(JITSymbolFlags::HasError) {}
/// @brief Create a symbol for a definition with a known address.
JITSymbol(JITTargetAddress Addr, JITSymbolFlags Flags)
@ -137,18 +151,59 @@ class JITSymbol {
/// user can materialize the definition at any time by calling the getAddress
/// method.
JITSymbol(GetAddressFtor GetAddress, JITSymbolFlags Flags)
: GetAddress(std::move(GetAddress)), Flags(Flags) {}
: GetAddress(std::move(GetAddress)), CachedAddr(0), Flags(Flags) {}
JITSymbol(const JITSymbol&) = delete;
JITSymbol& operator=(const JITSymbol&) = delete;
JITSymbol(JITSymbol &&Other)
: GetAddress(std::move(Other.GetAddress)), Flags(std::move(Other.Flags)) {
if (Flags.hasError())
Err = std::move(Other.Err);
else
CachedAddr = std::move(Other.CachedAddr);
}
JITSymbol& operator=(JITSymbol &&Other) {
GetAddress = std::move(Other.GetAddress);
Flags = std::move(Other.Flags);
if (Flags.hasError())
Err = std::move(Other.Err);
else
CachedAddr = std::move(Other.CachedAddr);
return *this;
}
~JITSymbol() {
if (Flags.hasError())
Err.~Error();
else
CachedAddr.~JITTargetAddress();
}
/// @brief Returns true if the symbol exists, false otherwise.
explicit operator bool() const { return CachedAddr || GetAddress; }
explicit operator bool() const {
return !Flags.hasError() && (CachedAddr || GetAddress);
}
/// @brief Move the error field value out of this JITSymbol.
Error takeError() {
if (Flags.hasError())
return std::move(Err);
return Error::success();
}
/// @brief Get the address of the symbol in the target address space. Returns
/// '0' if the symbol does not exist.
JITTargetAddress getAddress() {
Expected<JITTargetAddress> getAddress() {
assert(!Flags.hasError() && "getAddress called on error value");
if (GetAddress) {
CachedAddr = GetAddress();
assert(CachedAddr && "Symbol could not be materialized.");
GetAddress = nullptr;
if (auto CachedAddrOrErr = GetAddress()) {
GetAddress = nullptr;
CachedAddr = *CachedAddrOrErr;
assert(CachedAddr && "Symbol could not be materialized.");
} else
return CachedAddrOrErr.takeError();
}
return CachedAddr;
}
@ -157,7 +212,10 @@ class JITSymbol {
private:
GetAddressFtor GetAddress;
JITTargetAddress CachedAddr = 0;
union {
JITTargetAddress CachedAddr;
Error Err;
};
JITSymbolFlags Flags;
};

View File

@ -146,7 +146,7 @@ class CompileOnDemandLayer {
std::unique_ptr<JITSymbolResolver>)>;
struct SourceModuleEntry {
std::unique_ptr<ResourceOwner<Module>> SourceMod;
std::shared_ptr<Module> SourceMod;
std::set<Function*> StubsToClone;
};
@ -154,7 +154,7 @@ class CompileOnDemandLayer {
using SourceModuleHandle = typename SourceModulesList::size_type;
SourceModuleHandle
addSourceModule(std::unique_ptr<ResourceOwner<Module>> M) {
addSourceModule(std::shared_ptr<Module> M) {
SourceModuleHandle H = SourceModules.size();
SourceModules.push_back(SourceModuleEntry());
SourceModules.back().SourceMod = std::move(M);
@ -162,7 +162,7 @@ class CompileOnDemandLayer {
}
Module& getSourceModule(SourceModuleHandle H) {
return SourceModules[H].SourceMod->getResource();
return *SourceModules[H].SourceMod;
}
std::set<Function*>& getStubsToClone(SourceModuleHandle H) {
@ -176,19 +176,21 @@ class CompileOnDemandLayer {
for (auto BLH : BaseLayerHandles)
if (auto Sym = BaseLayer.findSymbolIn(BLH, Name, ExportedSymbolsOnly))
return Sym;
else if (auto Err = Sym.takeError())
return std::move(Err);
return nullptr;
}
void removeModulesFromBaseLayer(BaseLayerT &BaseLayer) {
Error removeModulesFromBaseLayer(BaseLayerT &BaseLayer) {
for (auto &BLH : BaseLayerHandles)
BaseLayer.removeModule(BLH);
if (auto Err = BaseLayer.removeModule(BLH))
return Err;
return Error::success();
}
std::unique_ptr<JITSymbolResolver> ExternalSymbolResolver;
std::unique_ptr<ResourceOwner<RuntimeDyld::MemoryManager>> MemMgr;
std::shared_ptr<JITSymbolResolver> ExternalSymbolResolver;
std::unique_ptr<IndirectStubsMgrT> StubsMgr;
StaticGlobalRenamer StaticRenamer;
ModuleAdderFtor ModuleAdder;
SourceModulesList SourceModules;
std::vector<BaseLayerModuleHandleT> BaseLayerHandles;
};
@ -196,6 +198,7 @@ class CompileOnDemandLayer {
using LogicalDylibList = std::list<LogicalDylib>;
public:
/// @brief Handle to loaded module.
using ModuleHandleT = typename LogicalDylibList::iterator;
@ -217,48 +220,41 @@ class CompileOnDemandLayer {
CloneStubsIntoPartitions(CloneStubsIntoPartitions) {}
~CompileOnDemandLayer() {
// FIXME: Report error on log.
while (!LogicalDylibs.empty())
removeModule(LogicalDylibs.begin());
consumeError(removeModule(LogicalDylibs.begin()));
}
/// @brief Add a module to the compile-on-demand layer.
template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
ModuleHandleT addModule(std::shared_ptr<Module> M,
MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver) {
Expected<ModuleHandleT>
addModule(std::shared_ptr<Module> M,
std::shared_ptr<JITSymbolResolver> Resolver) {
LogicalDylibs.push_back(LogicalDylib());
auto &LD = LogicalDylibs.back();
LD.ExternalSymbolResolver = std::move(Resolver);
LD.StubsMgr = CreateIndirectStubsManager();
auto &MemMgrRef = *MemMgr;
LD.MemMgr = wrapOwnership<RuntimeDyld::MemoryManager>(std::move(MemMgr));
LD.ModuleAdder =
[&MemMgrRef](BaseLayerT &B, std::unique_ptr<Module> M,
std::unique_ptr<JITSymbolResolver> R) {
return B.addModule(std::move(M), &MemMgrRef, std::move(R));
};
// Process each of the modules in this module set.
addLogicalModule(LogicalDylibs.back(), std::move(M));
if (auto Err = addLogicalModule(LD, std::move(M)))
return std::move(Err);
return std::prev(LogicalDylibs.end());
}
/// @brief Add extra modules to an existing logical module.
void addExtraModule(ModuleHandleT H, std::shared_ptr<Module> M) {
addLogicalModule(*H, std::move(M));
Error addExtraModule(ModuleHandleT H, std::shared_ptr<Module> M) {
return addLogicalModule(*H, std::move(M));
}
/// @brief Remove the module represented by the given handle.
///
/// This will remove all modules in the layers below that were derived from
/// the module represented by H.
void removeModule(ModuleHandleT H) {
H->removeModulesFromBaseLayer(BaseLayer);
Error removeModule(ModuleHandleT H) {
auto Err = H->removeModulesFromBaseLayer(BaseLayer);
LogicalDylibs.erase(H);
return Err;
}
/// @brief Search for the given named symbol.
@ -272,6 +268,8 @@ class CompileOnDemandLayer {
return Sym;
if (auto Sym = findSymbolIn(LDI, Name, ExportedSymbolsOnly))
return Sym;
else if (auto Err = Sym.takeError())
return std::move(Err);
}
return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
}
@ -309,8 +307,9 @@ class CompileOnDemandLayer {
}
private:
template <typename ModulePtrT>
void addLogicalModule(LogicalDylib &LD, ModulePtrT SrcMPtr) {
Error addLogicalModule(LogicalDylib &LD, std::shared_ptr<Module> SrcMPtr) {
// Rename all static functions / globals to $static.X :
// This will unique the names across all modules in the logical dylib,
// simplifying symbol lookup.
@ -322,7 +321,7 @@ class CompileOnDemandLayer {
// Create a logical module handle for SrcM within the logical dylib.
Module &SrcM = *SrcMPtr;
auto LMId = LD.addSourceModule(wrapOwnership<Module>(std::move(SrcMPtr)));
auto LMId = LD.addSourceModule(std::move(SrcMPtr));
// Create stub functions.
const DataLayout &DL = SrcM.getDataLayout();
@ -335,9 +334,12 @@ class CompileOnDemandLayer {
// Skip weak functions for which we already have definitions.
auto MangledName = mangle(F.getName(), DL);
if (F.hasWeakLinkage() || F.hasLinkOnceLinkage())
if (F.hasWeakLinkage() || F.hasLinkOnceLinkage()) {
if (auto Sym = LD.findSymbol(BaseLayer, MangledName, false))
continue;
else if (auto Err = Sym.takeError())
return std::move(Err);
}
// Record all functions defined by this module.
if (CloneStubsIntoPartitions)
@ -350,9 +352,15 @@ class CompileOnDemandLayer {
StubInits[MangledName] =
std::make_pair(CCInfo.getAddress(),
JITSymbolFlags::fromGlobalValue(F));
CCInfo.setCompileAction([this, &LD, LMId, &F]() {
return this->extractAndCompile(LD, LMId, F);
});
CCInfo.setCompileAction([this, &LD, LMId, &F]() -> JITTargetAddress {
if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F))
return *FnImplAddrOrErr;
else {
// FIXME: Report error, return to 'abort' or something similar.
consumeError(FnImplAddrOrErr.takeError());
return 0;
}
});
}
auto EC = LD.StubsMgr->createStubs(StubInits);
@ -367,7 +375,7 @@ class CompileOnDemandLayer {
// empty globals module.
if (SrcM.global_empty() && SrcM.alias_empty() &&
!SrcM.getModuleFlagsMetadata())
return;
return Error::success();
// Create the GlobalValues module.
auto GVsM = llvm::make_unique<Module>((SrcM.getName() + ".globals").str(),
@ -393,8 +401,9 @@ class CompileOnDemandLayer {
// Initializers may refer to functions declared (but not defined) in this
// module. Build a materializer to clone decls on demand.
Error MaterializerErrors = Error::success();
auto Materializer = createLambdaMaterializer(
[&LD, &GVsM](Value *V) -> Value* {
[&LD, &GVsM, &MaterializerErrors](Value *V) -> Value* {
if (auto *F = dyn_cast<Function>(V)) {
// Decls in the original module just get cloned.
if (F->isDeclaration())
@ -405,13 +414,24 @@ class CompileOnDemandLayer {
// instead.
const DataLayout &DL = GVsM->getDataLayout();
std::string FName = mangle(F->getName(), DL);
auto StubSym = LD.StubsMgr->findStub(FName, false);
unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType());
ConstantInt *StubAddr =
ConstantInt::get(GVsM->getContext(),
APInt(PtrBitWidth, StubSym.getAddress()));
JITTargetAddress StubAddr = 0;
// Get the address for the stub. If we encounter an error while
// doing so, stash it in the MaterializerErrors variable and use a
// null address as a placeholder.
if (auto StubSym = LD.StubsMgr->findStub(FName, false)) {
if (auto StubAddrOrErr = StubSym.getAddress())
StubAddr = *StubAddrOrErr;
else
MaterializerErrors = joinErrors(std::move(MaterializerErrors),
StubAddrOrErr.takeError());
}
ConstantInt *StubAddrCI =
ConstantInt::get(GVsM->getContext(), APInt(PtrBitWidth, StubAddr));
Constant *Init = ConstantExpr::getCast(Instruction::IntToPtr,
StubAddr, F->getType());
StubAddrCI, F->getType());
return GlobalAlias::create(F->getFunctionType(),
F->getType()->getAddressSpace(),
F->getLinkage(), F->getName(),
@ -435,22 +455,31 @@ class CompileOnDemandLayer {
NewA->setAliasee(cast<Constant>(Init));
}
if (MaterializerErrors)
return MaterializerErrors;
// Build a resolver for the globals module and add it to the base layer.
auto GVsResolver = createLambdaResolver(
[this, &LD](const std::string &Name) {
[this, &LD](const std::string &Name) -> JITSymbol {
if (auto Sym = LD.StubsMgr->findStub(Name, false))
return Sym;
if (auto Sym = LD.findSymbol(BaseLayer, Name, false))
return Sym;
else if (auto Err = Sym.takeError())
return std::move(Err);
return LD.ExternalSymbolResolver->findSymbolInLogicalDylib(Name);
},
[&LD](const std::string &Name) {
return LD.ExternalSymbolResolver->findSymbol(Name);
});
auto GVsH = LD.ModuleAdder(BaseLayer, std::move(GVsM),
std::move(GVsResolver));
LD.BaseLayerHandles.push_back(GVsH);
if (auto GVsHOrErr =
BaseLayer.addModule(std::move(GVsM), std::move(GVsResolver)))
LD.BaseLayerHandles.push_back(*GVsHOrErr);
else
return GVsHOrErr.takeError();
return Error::success();
}
static std::string mangle(StringRef Name, const DataLayout &DL) {
@ -462,7 +491,7 @@ class CompileOnDemandLayer {
return MangledName;
}
JITTargetAddress
Expected<JITTargetAddress>
extractAndCompile(LogicalDylib &LD,
typename LogicalDylib::SourceModuleHandle LMId,
Function &F) {
@ -475,34 +504,42 @@ class CompileOnDemandLayer {
// Grab the name of the function being called here.
std::string CalledFnName = mangle(F.getName(), SrcM.getDataLayout());
auto Part = Partition(F);
auto PartH = emitPartition(LD, LMId, Part);
JITTargetAddress CalledAddr = 0;
for (auto *SubF : Part) {
std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout());
auto FnBodySym = BaseLayer.findSymbolIn(PartH, FnName, false);
assert(FnBodySym && "Couldn't find function body.");
auto Part = Partition(F);
if (auto PartHOrErr = emitPartition(LD, LMId, Part)) {
auto &PartH = *PartHOrErr;
for (auto *SubF : Part) {
std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout());
if (auto FnBodySym = BaseLayer.findSymbolIn(PartH, FnName, false)) {
if (auto FnBodyAddrOrErr = FnBodySym.getAddress()) {
JITTargetAddress FnBodyAddr = *FnBodyAddrOrErr;
JITTargetAddress FnBodyAddr = FnBodySym.getAddress();
// If this is the function we're calling record the address so we can
// return it from this function.
if (SubF == &F)
CalledAddr = FnBodyAddr;
// If this is the function we're calling record the address so we can
// return it from this function.
if (SubF == &F)
CalledAddr = FnBodyAddr;
// Update the function body pointer for the stub.
if (auto EC = LD.StubsMgr->updatePointer(FnName, FnBodyAddr))
return 0;
// Update the function body pointer for the stub.
if (auto EC = LD.StubsMgr->updatePointer(FnName, FnBodyAddr))
return 0;
}
} else
return FnBodyAddrOrErr.takeError();
} else if (auto Err = FnBodySym.takeError())
return std::move(Err);
else
llvm_unreachable("Function not emitted for partition");
}
LD.BaseLayerHandles.push_back(PartH);
LD.BaseLayerHandles.push_back(PartH);
} else
return PartHOrErr.takeError();
return CalledAddr;
}
template <typename PartitionT>
BaseLayerModuleHandleT
Expected<BaseLayerModuleHandleT>
emitPartition(LogicalDylib &LD,
typename LogicalDylib::SourceModuleHandle LMId,
const PartitionT &Part) {
@ -566,16 +603,18 @@ class CompileOnDemandLayer {
// Create memory manager and symbol resolver.
auto Resolver = createLambdaResolver(
[this, &LD](const std::string &Name) {
[this, &LD](const std::string &Name) -> JITSymbol {
if (auto Sym = LD.findSymbol(BaseLayer, Name, false))
return Sym;
else if (auto Err = Sym.takeError())
return std::move(Err);
return LD.ExternalSymbolResolver->findSymbolInLogicalDylib(Name);
},
[&LD](const std::string &Name) {
return LD.ExternalSymbolResolver->findSymbol(Name);
});
return LD.ModuleAdder(BaseLayer, std::move(M), std::move(Resolver));
return BaseLayer.addModule(std::move(M), std::move(Resolver));
}
BaseLayerT &BaseLayer;

View File

@ -17,6 +17,8 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/ExecutionEngine/Orc/OrcError.h"
#include <algorithm>
#include <cstdint>
#include <string>
@ -99,19 +101,24 @@ class CtorDtorRunner {
/// @brief Run the recorded constructors/destructors through the given JIT
/// layer.
bool runViaLayer(JITLayerT &JITLayer) const {
Error runViaLayer(JITLayerT &JITLayer) const {
using CtorDtorTy = void (*)();
bool Error = false;
for (const auto &CtorDtorName : CtorDtorNames)
if (auto CtorDtorSym = JITLayer.findSymbolIn(H, CtorDtorName, false)) {
CtorDtorTy CtorDtor =
reinterpret_cast<CtorDtorTy>(
static_cast<uintptr_t>(CtorDtorSym.getAddress()));
CtorDtor();
} else
Error = true;
return !Error;
if (auto AddrOrErr = CtorDtorSym.getAddress()) {
CtorDtorTy CtorDtor =
reinterpret_cast<CtorDtorTy>(static_cast<uintptr_t>(*AddrOrErr));
CtorDtor();
} else
return AddrOrErr.takeError();
} else {
if (auto Err = CtorDtorSym.takeError())
return Err;
else
return make_error<JITSymbolNotFound>(CtorDtorName);
}
return Error::success();
}
private:

View File

@ -17,9 +17,14 @@
#include "llvm/ExecutionEngine/JITSymbol.h"
#include <map>
#include <memory>
#include <string>
namespace llvm {
class Module;
class JITSymbolResolver;
namespace orc {
/// @brief Global mapping layer.
@ -32,25 +37,22 @@ namespace orc {
template <typename BaseLayerT>
class GlobalMappingLayer {
public:
/// @brief Handle to a set of added modules.
using ModuleSetHandleT = typename BaseLayerT::ModuleSetHandleT;
/// @brief Handle to an added module.
using ModuleHandleT = typename BaseLayerT::ModuleHandleT;
/// @brief Construct an GlobalMappingLayer with the given BaseLayer
GlobalMappingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
/// @brief Add the given module set to the JIT.
/// @brief Add the given module to the JIT.
/// @return A handle for the added modules.
template <typename ModuleSetT, typename MemoryManagerPtrT,
typename SymbolResolverPtrT>
ModuleSetHandleT addModuleSet(ModuleSetT Ms,
MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver) {
return BaseLayer.addModuleSet(std::move(Ms), std::move(MemMgr),
std::move(Resolver));
ModuleHandleT addModule(std::shared_ptr<Module> M,
std::shared_ptr<JITSymbolResolver> Resolver) {
return BaseLayer.addModule(std::move(M), std::move(Resolver));
}
/// @brief Remove the module set associated with the handle H.
void removeModuleSet(ModuleSetHandleT H) { BaseLayer.removeModuleSet(H); }
void removeModule(ModuleHandleT H) { BaseLayer.removeModule(H); }
/// @brief Manually set the address to return for the given symbol.
void setGlobalMapping(const std::string &Name, JITTargetAddress Addr) {
@ -78,15 +80,15 @@ class GlobalMappingLayer {
return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
}
/// @brief Get the address of the given symbol in the context of the set of
/// modules represented by the handle H. This call is forwarded to the
/// @brief Get the address of the given symbol in the context of the of the
/// module represented by the handle H. This call is forwarded to the
/// base layer's implementation.
/// @param H The handle for the module set to search in.
/// @param H The handle for the module to search in.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it is found in the
/// given module set.
JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
/// given module.
JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
bool ExportedSymbolsOnly) {
return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly);
}
@ -94,7 +96,7 @@ class GlobalMappingLayer {
/// @brief Immediately emit and finalize the module set represented by the
/// given handle.
/// @param H Handle for module set to emit/finalize.
void emitAndFinalize(ModuleSetHandleT H) {
void emitAndFinalize(ModuleHandleT H) {
BaseLayer.emitAndFinalize(H);
}

View File

@ -50,18 +50,18 @@ class IRCompileLayer {
/// along with the given memory manager and symbol resolver.
///
/// @return A handle for the added module.
template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
ModuleHandleT addModule(std::shared_ptr<Module> M,
MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver) {
Expected<ModuleHandleT>
addModule(std::shared_ptr<Module> M,
std::shared_ptr<JITSymbolResolver> Resolver) {
using CompileResult = decltype(Compile(*M));
auto Obj = std::make_shared<CompileResult>(Compile(*M));
return BaseLayer.addObject(std::move(Obj), std::move(MemMgr),
std::move(Resolver));
return BaseLayer.addObject(std::move(Obj), std::move(Resolver));
}
/// @brief Remove the module associated with the handle H.
void removeModule(ModuleHandleT H) { BaseLayer.removeObject(H); }
Error removeModule(ModuleHandleT H) {
return BaseLayer.removeObject(H);
}
/// @brief Search for the given named symbol.
/// @param Name The name of the symbol to search for.
@ -87,8 +87,8 @@ class IRCompileLayer {
/// @brief Immediately emit and finalize the module represented by the given
/// handle.
/// @param H Handle for module to emit/finalize.
void emitAndFinalize(ModuleHandleT H) {
BaseLayer.emitAndFinalize(H);
Error emitAndFinalize(ModuleHandleT H) {
return BaseLayer.emitAndFinalize(H);
}
private:

View File

@ -42,16 +42,14 @@ class IRTransformLayer {
/// the layer below, along with the memory manager and symbol resolver.
///
/// @return A handle for the added modules.
template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
ModuleHandleT addModule(std::shared_ptr<Module> M,
MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver) {
return BaseLayer.addModule(Transform(std::move(M)), std::move(MemMgr),
std::move(Resolver));
Expected<ModuleHandleT>
addModule(std::shared_ptr<Module> M,
std::shared_ptr<JITSymbolResolver> Resolver) {
return BaseLayer.addModule(Transform(std::move(M)), std::move(Resolver));
}
/// @brief Remove the module associated with the handle H.
void removeModule(ModuleHandleT H) { BaseLayer.removeModule(H); }
Error removeModule(ModuleHandleT H) { return BaseLayer.removeModule(H); }
/// @brief Search for the given named symbol.
/// @param Name The name of the symbol to search for.
@ -77,8 +75,8 @@ class IRTransformLayer {
/// @brief Immediately emit and finalize the module represented by the given
/// handle.
/// @param H Handle for module to emit/finalize.
void emitAndFinalize(ModuleHandleT H) {
BaseLayer.emitAndFinalize(H);
Error emitAndFinalize(ModuleHandleT H) {
return BaseLayer.emitAndFinalize(H);
}
/// @brief Access the transform functor directly.

View File

@ -45,7 +45,7 @@ class LambdaResolver : public JITSymbolResolver {
template <typename DylibLookupFtorT,
typename ExternalLookupFtorT>
std::unique_ptr<LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT>>
std::shared_ptr<LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT>>
createLambdaResolver(DylibLookupFtorT DylibLookupFtor,
ExternalLookupFtorT ExternalLookupFtor) {
using LR = LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT>;

View File

@ -46,8 +46,9 @@ template <typename BaseLayerT> class LazyEmittingLayer {
private:
class EmissionDeferredModule {
public:
EmissionDeferredModule() = default;
virtual ~EmissionDeferredModule() = default;
EmissionDeferredModule(std::shared_ptr<Module> M,
std::shared_ptr<JITSymbolResolver> Resolver)
: M(std::move(M)), Resolver(std::move(Resolver)) {}
JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) {
switch (EmitState) {
@ -59,16 +60,24 @@ template <typename BaseLayerT> class LazyEmittingLayer {
std::string PName = Name;
JITSymbolFlags Flags = JITSymbolFlags::fromGlobalValue(*GV);
auto GetAddress =
[this, ExportedSymbolsOnly, PName, &B]() -> JITTargetAddress {
[this, ExportedSymbolsOnly, PName, &B]() -> Expected<JITTargetAddress> {
if (this->EmitState == Emitting)
return 0;
else if (this->EmitState == NotEmitted) {
this->EmitState = Emitting;
Handle = this->emitToBaseLayer(B);
if (auto HandleOrErr = this->emitToBaseLayer(B))
Handle = std::move(*HandleOrErr);
else
return HandleOrErr.takeError();
this->EmitState = Emitted;
}
auto Sym = B.findSymbolIn(Handle, PName, ExportedSymbolsOnly);
return Sym.getAddress();
if (auto Sym = B.findSymbolIn(Handle, PName, ExportedSymbolsOnly))
return Sym.getAddress();
else if (auto Err = Sym.takeError())
return std::move(Err);
else
llvm_unreachable("Successful symbol lookup should return "
"definition address here");
};
return JITSymbol(std::move(GetAddress), Flags);
} else
@ -101,33 +110,10 @@ template <typename BaseLayerT> class LazyEmittingLayer {
BaseLayer.emitAndFinalize(Handle);
}
template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
static std::unique_ptr<EmissionDeferredModule>
create(BaseLayerT &B, std::shared_ptr<Module> M, MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver);
protected:
virtual const GlobalValue* searchGVs(StringRef Name,
bool ExportedSymbolsOnly) const = 0;
virtual BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) = 0;
private:
enum { NotEmitted, Emitting, Emitted } EmitState = NotEmitted;
BaseLayerHandleT Handle;
};
template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
class EmissionDeferredModuleImpl : public EmissionDeferredModule {
public:
EmissionDeferredModuleImpl(std::shared_ptr<Module> M,
MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver)
: M(std::move(M)), MemMgr(std::move(MemMgr)),
Resolver(std::move(Resolver)) {}
protected:
const GlobalValue* searchGVs(StringRef Name,
bool ExportedSymbolsOnly) const override {
bool ExportedSymbolsOnly) const {
// FIXME: We could clean all this up if we had a way to reliably demangle
// names: We could just demangle name and search, rather than
// mangling everything else.
@ -149,15 +135,13 @@ template <typename BaseLayerT> class LazyEmittingLayer {
return buildMangledSymbols(Name, ExportedSymbolsOnly);
}
BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) override {
Expected<BaseLayerHandleT> emitToBaseLayer(BaseLayerT &BaseLayer) {
// We don't need the mangled names set any more: Once we've emitted this
// to the base layer we'll just look for symbols there.
MangledSymbols.reset();
return BaseLayer.addModule(std::move(M), std::move(MemMgr),
std::move(Resolver));
return BaseLayer.addModule(std::move(M), std::move(Resolver));
}
private:
// If the mangled name of the given GlobalValue matches the given search
// name (and its visibility conforms to the ExportedSymbolsOnly flag) then
// return the symbol. Otherwise, add the mangled name to the Names map and
@ -207,9 +191,10 @@ template <typename BaseLayerT> class LazyEmittingLayer {
return nullptr;
}
enum { NotEmitted, Emitting, Emitted } EmitState = NotEmitted;
BaseLayerHandleT Handle;
std::shared_ptr<Module> M;
MemoryManagerPtrT MemMgr;
SymbolResolverPtrT Resolver;
std::shared_ptr<JITSymbolResolver> Resolver;
mutable std::unique_ptr<StringMap<const GlobalValue*>> MangledSymbols;
};
@ -219,6 +204,7 @@ template <typename BaseLayerT> class LazyEmittingLayer {
ModuleListT ModuleList;
public:
/// @brief Handle to a loaded module.
using ModuleHandleT = typename ModuleListT::iterator;
@ -226,24 +212,23 @@ template <typename BaseLayerT> class LazyEmittingLayer {
LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
/// @brief Add the given module to the lazy emitting layer.
template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
ModuleHandleT addModule(std::shared_ptr<Module> M,
MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver) {
Expected<ModuleHandleT>
addModule(std::shared_ptr<Module> M,
std::shared_ptr<JITSymbolResolver> Resolver) {
return ModuleList.insert(
ModuleList.end(),
EmissionDeferredModule::create(BaseLayer, std::move(M),
std::move(MemMgr),
std::move(Resolver)));
llvm::make_unique<EmissionDeferredModule>(std::move(M),
std::move(Resolver)));
}
/// @brief Remove the module represented by the given handle.
///
/// This method will free the memory associated with the given module, both
/// in this layer, and the base layer.
void removeModule(ModuleHandleT H) {
Error removeModule(ModuleHandleT H) {
(*H)->removeModuleFromBaseLayer(BaseLayer);
ModuleList.erase(H);
return Error::success();
}
/// @brief Search for the given named symbol.
@ -276,22 +261,11 @@ template <typename BaseLayerT> class LazyEmittingLayer {
/// @brief Immediately emit and finalize the module represented by the given
/// handle.
/// @param H Handle for module to emit/finalize.
void emitAndFinalize(ModuleHandleT H) {
(*H)->emitAndFinalize(BaseLayer);
Error emitAndFinalize(ModuleHandleT H) {
return (*H)->emitAndFinalize(BaseLayer);
}
};
template <typename BaseLayerT>
template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
std::unique_ptr<typename LazyEmittingLayer<BaseLayerT>::EmissionDeferredModule>
LazyEmittingLayer<BaseLayerT>::EmissionDeferredModule::create(
BaseLayerT &B, std::shared_ptr<Module> M, MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver) {
using EDS = EmissionDeferredModuleImpl<MemoryManagerPtrT, SymbolResolverPtrT>;
return llvm::make_unique<EDS>(std::move(M), std::move(MemMgr),
std::move(Resolver));
}
} // end namespace orc
} // end namespace llvm

View File

@ -16,6 +16,7 @@
#include "llvm/ExecutionEngine/JITSymbol.h"
#include <algorithm>
#include <memory>
#include <string>
namespace llvm {
@ -42,16 +43,14 @@ class ObjectTransformLayer {
/// memory manager and symbol resolver.
///
/// @return A handle for the added objects.
template <typename ObjPtrT, typename MemoryManagerPtrT,
typename SymbolResolverPtrT>
ObjHandleT addObject(ObjPtrT Obj, MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver) {
return BaseLayer.addObject(Transform(std::move(Obj)), std::move(MemMgr),
std::move(Resolver));
template <typename ObjectPtr>
Expected<ObjHandleT> addObject(ObjectPtr Obj,
std::shared_ptr<JITSymbolResolver> Resolver) {
return BaseLayer.addObject(Transform(std::move(Obj)), std::move(Resolver));
}
/// @brief Remove the object set associated with the handle H.
void removeObject(ObjHandleT H) { BaseLayer.removeObject(H); }
Error removeObject(ObjHandleT H) { return BaseLayer.removeObject(H); }
/// @brief Search for the given named symbol.
/// @param Name The name of the symbol to search for.
@ -77,7 +76,9 @@ class ObjectTransformLayer {
/// @brief Immediately emit and finalize the object set represented by the
/// given handle.
/// @param H Handle for object set to emit/finalize.
void emitAndFinalize(ObjHandleT H) { BaseLayer.emitAndFinalize(H); }
Error emitAndFinalize(ObjHandleT H) {
return BaseLayer.emitAndFinalize(H);
}
/// @brief Map section addresses for the objects associated with the handle H.
void mapSectionAddress(ObjHandleT H, const void *LocalAddress,

View File

@ -22,7 +22,8 @@ namespace orc {
enum class OrcErrorCode : int {
// RPC Errors
RemoteAllocatorDoesNotExist = 1,
JITSymbolNotFound = 1,
RemoteAllocatorDoesNotExist,
RemoteAllocatorIdAlreadyInUse,
RemoteMProtectAddrUnrecognized,
RemoteIndirectStubsOwnerDoesNotExist,
@ -37,6 +38,18 @@ enum class OrcErrorCode : int {
std::error_code orcError(OrcErrorCode ErrCode);
class JITSymbolNotFound : public ErrorInfo<JITSymbolNotFound> {
public:
static char ID;
JITSymbolNotFound(std::string SymbolName);
std::error_code convertToErrorCode() const override;
void log(raw_ostream &OS) const override;
const std::string &getSymbolName() const;
private:
std::string SymbolName;
};
} // End namespace orc.
} // End namespace llvm.

View File

@ -228,13 +228,20 @@ class RTDyldObjectLinkingLayer : public RTDyldObjectLinkingLayerBase {
public:
/// @brief Functor for creating memory managers.
using MemoryManagerGetter =
std::function<std::shared_ptr<RuntimeDyld::MemoryManager>()>;
/// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
/// and NotifyFinalized functors.
RTDyldObjectLinkingLayer(
MemoryManagerGetter GetMemMgr,
NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
: NotifyLoaded(std::move(NotifyLoaded)),
NotifyFinalized(std::move(NotifyFinalized)) {}
: GetMemMgr(GetMemMgr),
NotifyLoaded(std::move(NotifyLoaded)),
NotifyFinalized(std::move(NotifyFinalized)),
ProcessAllSections(false) {}
/// @brief Set the 'ProcessAllSections' flag.
///
@ -251,12 +258,8 @@ class RTDyldObjectLinkingLayer : public RTDyldObjectLinkingLayerBase {
///
/// @return A handle that can be used to refer to the loaded objects (for
/// symbol searching, finalization, freeing memory, etc.).
template <typename MemoryManagerPtrT,
typename SymbolResolverPtrT>
ObjHandleT addObject(ObjectPtr Obj,
MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver) {
Expected<ObjHandleT> addObject(ObjectPtr Obj,
std::shared_ptr<JITSymbolResolver> Resolver) {
auto Finalizer = [&](ObjHandleT H, RuntimeDyld &RTDyld,
const ObjectPtr &ObjToLoad,
std::function<void()> LOSHandleLoad) {
@ -275,8 +278,9 @@ class RTDyldObjectLinkingLayer : public RTDyldObjectLinkingLayerBase {
};
auto LO =
createLinkedObject(std::move(Obj), std::move(MemMgr), std::move(Resolver),
std::move(Finalizer), ProcessAllSections);
createLinkedObject(std::move(Obj), GetMemMgr(),
std::move(Resolver), std::move(Finalizer),
ProcessAllSections);
// LOS is an owning-ptr. Keep a non-owning one so that we can set the handle
// below.
auto *LOPtr = LO.get();
@ -295,9 +299,10 @@ class RTDyldObjectLinkingLayer : public RTDyldObjectLinkingLayerBase {
/// indirectly) will result in undefined behavior. If dependence tracking is
/// required to detect or resolve such issues it should be added at a higher
/// layer.
void removeObject(ObjHandleT H) {
Error removeObject(ObjHandleT H) {
// How do we invalidate the symbols in H?
LinkedObjList.erase(H);
return Error::success();
}
/// @brief Search for the given named symbol.
@ -334,13 +339,15 @@ class RTDyldObjectLinkingLayer : public RTDyldObjectLinkingLayerBase {
/// @brief Immediately emit and finalize the object set represented by the
/// given handle.
/// @param H Handle for object set to emit/finalize.
void emitAndFinalize(ObjHandleT H) {
Error emitAndFinalize(ObjHandleT H) {
(*H)->finalize();
return Error::success();
}
private:
LinkedObjectListT LinkedObjList;
MemoryManagerGetter GetMemMgr;
NotifyLoadedFtor NotifyLoaded;
NotifyFinalizedFtor NotifyFinalized;
bool ProcessAllSections = false;

View File

@ -88,21 +88,6 @@ class RuntimeDyld {
ObjSectionToIDMap ObjSecToIDMap;
};
template <typename Derived> struct LoadedObjectInfoHelper : LoadedObjectInfo {
protected:
LoadedObjectInfoHelper(const LoadedObjectInfoHelper &) = default;
LoadedObjectInfoHelper() = default;
public:
LoadedObjectInfoHelper(RuntimeDyldImpl &RTDyld,
LoadedObjectInfo::ObjSectionToIDMap ObjSecToIDMap)
: LoadedObjectInfo(RTDyld, std::move(ObjSecToIDMap)) {}
std::unique_ptr<llvm::LoadedObjectInfo> clone() const override {
return llvm::make_unique<Derived>(static_cast<const Derived &>(*this));
}
};
/// \brief Memory Management.
class MemoryManager {
friend class RuntimeDyld;

View File

@ -680,11 +680,6 @@ class ConstantDataArray final : public ConstantDataSequential {
explicit ConstantDataArray(Type *ty, const char *Data)
: ConstantDataSequential(ty, ConstantDataArrayVal, Data) {}
/// Allocate space for exactly zero operands.
void *operator new(size_t s) {
return User::operator new(s, 0);
}
public:
ConstantDataArray(const ConstantDataArray &) = delete;
@ -739,11 +734,6 @@ class ConstantDataVector final : public ConstantDataSequential {
explicit ConstantDataVector(Type *ty, const char *Data)
: ConstantDataSequential(ty, ConstantDataVectorVal, Data) {}
// allocate space for exactly zero operands.
void *operator new(size_t s) {
return User::operator new(s, 0);
}
public:
ConstantDataVector(const ConstantDataVector &) = delete;

View File

@ -1062,7 +1062,7 @@ class IRBuilder : public IRBuilderBase, public Inserter {
Value *CreateAnd(Value *LHS, Value *RHS, const Twine &Name = "") {
if (Constant *RC = dyn_cast<Constant>(RHS)) {
if (isa<ConstantInt>(RC) && cast<ConstantInt>(RC)->isAllOnesValue())
if (isa<ConstantInt>(RC) && cast<ConstantInt>(RC)->isMinusOne())
return LHS; // LHS & -1 -> LHS
if (Constant *LC = dyn_cast<Constant>(LHS))
return Insert(Folder.CreateAnd(LC, RC), Name);
@ -1203,22 +1203,22 @@ class IRBuilder : public IRBuilderBase, public Inserter {
return SI;
}
FenceInst *CreateFence(AtomicOrdering Ordering,
SynchronizationScope SynchScope = CrossThread,
SyncScope::ID SSID = SyncScope::System,
const Twine &Name = "") {
return Insert(new FenceInst(Context, Ordering, SynchScope), Name);
return Insert(new FenceInst(Context, Ordering, SSID), Name);
}
AtomicCmpXchgInst *
CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New,
AtomicOrdering SuccessOrdering,
AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope = CrossThread) {
SyncScope::ID SSID = SyncScope::System) {
return Insert(new AtomicCmpXchgInst(Ptr, Cmp, New, SuccessOrdering,
FailureOrdering, SynchScope));
FailureOrdering, SSID));
}
AtomicRMWInst *CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val,
AtomicOrdering Ordering,
SynchronizationScope SynchScope = CrossThread) {
return Insert(new AtomicRMWInst(Op, Ptr, Val, Ordering, SynchScope));
SyncScope::ID SSID = SyncScope::System) {
return Insert(new AtomicRMWInst(Op, Ptr, Val, Ordering, SSID));
}
Value *CreateGEP(Value *Ptr, ArrayRef<Value *> IdxList,
const Twine &Name = "") {
@ -1517,11 +1517,9 @@ class IRBuilder : public IRBuilderBase, public Inserter {
const Twine &Name = "") {
if (V->getType() == DestTy)
return V;
if (V->getType()->getScalarType()->isPointerTy() &&
DestTy->getScalarType()->isIntegerTy())
if (V->getType()->isPtrOrPtrVectorTy() && DestTy->isIntOrIntVectorTy())
return CreatePtrToInt(V, DestTy, Name);
if (V->getType()->getScalarType()->isIntegerTy() &&
DestTy->getScalarType()->isPointerTy())
if (V->getType()->isIntOrIntVectorTy() && DestTy->isPtrOrPtrVectorTy())
return CreateIntToPtr(V, DestTy, Name);
return CreateBitCast(V, DestTy, Name);

View File

@ -52,11 +52,6 @@ class ConstantInt;
class DataLayout;
class LLVMContext;
enum SynchronizationScope {
SingleThread = 0,
CrossThread = 1
};
//===----------------------------------------------------------------------===//
// AllocaInst Class
//===----------------------------------------------------------------------===//
@ -195,17 +190,16 @@ class LoadInst : public UnaryInstruction {
LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile,
unsigned Align, BasicBlock *InsertAtEnd);
LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align,
AtomicOrdering Order, SynchronizationScope SynchScope = CrossThread,
AtomicOrdering Order, SyncScope::ID SSID = SyncScope::System,
Instruction *InsertBefore = nullptr)
: LoadInst(cast<PointerType>(Ptr->getType())->getElementType(), Ptr,
NameStr, isVolatile, Align, Order, SynchScope, InsertBefore) {}
NameStr, isVolatile, Align, Order, SSID, InsertBefore) {}
LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, bool isVolatile,
unsigned Align, AtomicOrdering Order,
SynchronizationScope SynchScope = CrossThread,
SyncScope::ID SSID = SyncScope::System,
Instruction *InsertBefore = nullptr);
LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile,
unsigned Align, AtomicOrdering Order,
SynchronizationScope SynchScope,
unsigned Align, AtomicOrdering Order, SyncScope::ID SSID,
BasicBlock *InsertAtEnd);
LoadInst(Value *Ptr, const char *NameStr, Instruction *InsertBefore);
LoadInst(Value *Ptr, const char *NameStr, BasicBlock *InsertAtEnd);
@ -235,34 +229,34 @@ class LoadInst : public UnaryInstruction {
void setAlignment(unsigned Align);
/// Returns the ordering effect of this fence.
/// Returns the ordering constraint of this load instruction.
AtomicOrdering getOrdering() const {
return AtomicOrdering((getSubclassDataFromInstruction() >> 7) & 7);
}
/// Set the ordering constraint on this load. May not be Release or
/// AcquireRelease.
/// Sets the ordering constraint of this load instruction. May not be Release
/// or AcquireRelease.
void setOrdering(AtomicOrdering Ordering) {
setInstructionSubclassData((getSubclassDataFromInstruction() & ~(7 << 7)) |
((unsigned)Ordering << 7));
}
SynchronizationScope getSynchScope() const {
return SynchronizationScope((getSubclassDataFromInstruction() >> 6) & 1);
/// Returns the synchronization scope ID of this load instruction.
SyncScope::ID getSyncScopeID() const {
return SSID;
}
/// Specify whether this load is ordered with respect to all
/// concurrently executing threads, or only with respect to signal handlers
/// executing in the same thread.
void setSynchScope(SynchronizationScope xthread) {
setInstructionSubclassData((getSubclassDataFromInstruction() & ~(1 << 6)) |
(xthread << 6));
/// Sets the synchronization scope ID of this load instruction.
void setSyncScopeID(SyncScope::ID SSID) {
this->SSID = SSID;
}
/// Sets the ordering constraint and the synchronization scope ID of this load
/// instruction.
void setAtomic(AtomicOrdering Ordering,
SynchronizationScope SynchScope = CrossThread) {
SyncScope::ID SSID = SyncScope::System) {
setOrdering(Ordering);
setSynchScope(SynchScope);
setSyncScopeID(SSID);
}
bool isSimple() const { return !isAtomic() && !isVolatile(); }
@ -297,6 +291,11 @@ class LoadInst : public UnaryInstruction {
void setInstructionSubclassData(unsigned short D) {
Instruction::setInstructionSubclassData(D);
}
/// The synchronization scope ID of this load instruction. Not quite enough
/// room in SubClassData for everything, so synchronization scope ID gets its
/// own field.
SyncScope::ID SSID;
};
//===----------------------------------------------------------------------===//
@ -325,11 +324,10 @@ class StoreInst : public Instruction {
unsigned Align, BasicBlock *InsertAtEnd);
StoreInst(Value *Val, Value *Ptr, bool isVolatile,
unsigned Align, AtomicOrdering Order,
SynchronizationScope SynchScope = CrossThread,
SyncScope::ID SSID = SyncScope::System,
Instruction *InsertBefore = nullptr);
StoreInst(Value *Val, Value *Ptr, bool isVolatile,
unsigned Align, AtomicOrdering Order,
SynchronizationScope SynchScope,
unsigned Align, AtomicOrdering Order, SyncScope::ID SSID,
BasicBlock *InsertAtEnd);
// allocate space for exactly two operands
@ -356,34 +354,34 @@ class StoreInst : public Instruction {
void setAlignment(unsigned Align);
/// Returns the ordering effect of this store.
/// Returns the ordering constraint of this store instruction.
AtomicOrdering getOrdering() const {
return AtomicOrdering((getSubclassDataFromInstruction() >> 7) & 7);
}
/// Set the ordering constraint on this store. May not be Acquire or
/// AcquireRelease.
/// Sets the ordering constraint of this store instruction. May not be
/// Acquire or AcquireRelease.
void setOrdering(AtomicOrdering Ordering) {
setInstructionSubclassData((getSubclassDataFromInstruction() & ~(7 << 7)) |
((unsigned)Ordering << 7));
}
SynchronizationScope getSynchScope() const {
return SynchronizationScope((getSubclassDataFromInstruction() >> 6) & 1);
/// Returns the synchronization scope ID of this store instruction.
SyncScope::ID getSyncScopeID() const {
return SSID;
}
/// Specify whether this store instruction is ordered with respect to all
/// concurrently executing threads, or only with respect to signal handlers
/// executing in the same thread.
void setSynchScope(SynchronizationScope xthread) {
setInstructionSubclassData((getSubclassDataFromInstruction() & ~(1 << 6)) |
(xthread << 6));
/// Sets the synchronization scope ID of this store instruction.
void setSyncScopeID(SyncScope::ID SSID) {
this->SSID = SSID;
}
/// Sets the ordering constraint and the synchronization scope ID of this
/// store instruction.
void setAtomic(AtomicOrdering Ordering,
SynchronizationScope SynchScope = CrossThread) {
SyncScope::ID SSID = SyncScope::System) {
setOrdering(Ordering);
setSynchScope(SynchScope);
setSyncScopeID(SSID);
}
bool isSimple() const { return !isAtomic() && !isVolatile(); }
@ -421,6 +419,11 @@ class StoreInst : public Instruction {
void setInstructionSubclassData(unsigned short D) {
Instruction::setInstructionSubclassData(D);
}
/// The synchronization scope ID of this store instruction. Not quite enough
/// room in SubClassData for everything, so synchronization scope ID gets its
/// own field.
SyncScope::ID SSID;
};
template <>
@ -435,7 +438,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(StoreInst, Value)
/// An instruction for ordering other memory operations.
class FenceInst : public Instruction {
void Init(AtomicOrdering Ordering, SynchronizationScope SynchScope);
void Init(AtomicOrdering Ordering, SyncScope::ID SSID);
protected:
// Note: Instruction needs to be a friend here to call cloneImpl.
@ -447,10 +450,9 @@ class FenceInst : public Instruction {
// Ordering may only be Acquire, Release, AcquireRelease, or
// SequentiallyConsistent.
FenceInst(LLVMContext &C, AtomicOrdering Ordering,
SynchronizationScope SynchScope = CrossThread,
SyncScope::ID SSID = SyncScope::System,
Instruction *InsertBefore = nullptr);
FenceInst(LLVMContext &C, AtomicOrdering Ordering,
SynchronizationScope SynchScope,
FenceInst(LLVMContext &C, AtomicOrdering Ordering, SyncScope::ID SSID,
BasicBlock *InsertAtEnd);
// allocate space for exactly zero operands
@ -458,28 +460,26 @@ class FenceInst : public Instruction {
return User::operator new(s, 0);
}
/// Returns the ordering effect of this fence.
/// Returns the ordering constraint of this fence instruction.
AtomicOrdering getOrdering() const {
return AtomicOrdering(getSubclassDataFromInstruction() >> 1);
}
/// Set the ordering constraint on this fence. May only be Acquire, Release,
/// AcquireRelease, or SequentiallyConsistent.
/// Sets the ordering constraint of this fence instruction. May only be
/// Acquire, Release, AcquireRelease, or SequentiallyConsistent.
void setOrdering(AtomicOrdering Ordering) {
setInstructionSubclassData((getSubclassDataFromInstruction() & 1) |
((unsigned)Ordering << 1));
}
SynchronizationScope getSynchScope() const {
return SynchronizationScope(getSubclassDataFromInstruction() & 1);
/// Returns the synchronization scope ID of this fence instruction.
SyncScope::ID getSyncScopeID() const {
return SSID;
}
/// Specify whether this fence orders other operations with respect to all
/// concurrently executing threads, or only with respect to signal handlers
/// executing in the same thread.
void setSynchScope(SynchronizationScope xthread) {
setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) |
xthread);
/// Sets the synchronization scope ID of this fence instruction.
void setSyncScopeID(SyncScope::ID SSID) {
this->SSID = SSID;
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
@ -496,6 +496,11 @@ class FenceInst : public Instruction {
void setInstructionSubclassData(unsigned short D) {
Instruction::setInstructionSubclassData(D);
}
/// The synchronization scope ID of this fence instruction. Not quite enough
/// room in SubClassData for everything, so synchronization scope ID gets its
/// own field.
SyncScope::ID SSID;
};
//===----------------------------------------------------------------------===//
@ -509,7 +514,7 @@ class FenceInst : public Instruction {
class AtomicCmpXchgInst : public Instruction {
void Init(Value *Ptr, Value *Cmp, Value *NewVal,
AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope);
SyncScope::ID SSID);
protected:
// Note: Instruction needs to be a friend here to call cloneImpl.
@ -521,13 +526,11 @@ class AtomicCmpXchgInst : public Instruction {
AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal,
AtomicOrdering SuccessOrdering,
AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope,
Instruction *InsertBefore = nullptr);
SyncScope::ID SSID, Instruction *InsertBefore = nullptr);
AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal,
AtomicOrdering SuccessOrdering,
AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope,
BasicBlock *InsertAtEnd);
SyncScope::ID SSID, BasicBlock *InsertAtEnd);
// allocate space for exactly three operands
void *operator new(size_t s) {
@ -561,7 +564,12 @@ class AtomicCmpXchgInst : public Instruction {
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
/// Set the ordering constraint on this cmpxchg.
/// Returns the success ordering constraint of this cmpxchg instruction.
AtomicOrdering getSuccessOrdering() const {
return AtomicOrdering((getSubclassDataFromInstruction() >> 2) & 7);
}
/// Sets the success ordering constraint of this cmpxchg instruction.
void setSuccessOrdering(AtomicOrdering Ordering) {
assert(Ordering != AtomicOrdering::NotAtomic &&
"CmpXchg instructions can only be atomic.");
@ -569,6 +577,12 @@ class AtomicCmpXchgInst : public Instruction {
((unsigned)Ordering << 2));
}
/// Returns the failure ordering constraint of this cmpxchg instruction.
AtomicOrdering getFailureOrdering() const {
return AtomicOrdering((getSubclassDataFromInstruction() >> 5) & 7);
}
/// Sets the failure ordering constraint of this cmpxchg instruction.
void setFailureOrdering(AtomicOrdering Ordering) {
assert(Ordering != AtomicOrdering::NotAtomic &&
"CmpXchg instructions can only be atomic.");
@ -576,28 +590,14 @@ class AtomicCmpXchgInst : public Instruction {
((unsigned)Ordering << 5));
}
/// Specify whether this cmpxchg is atomic and orders other operations with
/// respect to all concurrently executing threads, or only with respect to
/// signal handlers executing in the same thread.
void setSynchScope(SynchronizationScope SynchScope) {
setInstructionSubclassData((getSubclassDataFromInstruction() & ~2) |
(SynchScope << 1));
/// Returns the synchronization scope ID of this cmpxchg instruction.
SyncScope::ID getSyncScopeID() const {
return SSID;
}
/// Returns the ordering constraint on this cmpxchg.
AtomicOrdering getSuccessOrdering() const {
return AtomicOrdering((getSubclassDataFromInstruction() >> 2) & 7);
}
/// Returns the ordering constraint on this cmpxchg.
AtomicOrdering getFailureOrdering() const {
return AtomicOrdering((getSubclassDataFromInstruction() >> 5) & 7);
}
/// Returns whether this cmpxchg is atomic between threads or only within a
/// single thread.
SynchronizationScope getSynchScope() const {
return SynchronizationScope((getSubclassDataFromInstruction() & 2) >> 1);
/// Sets the synchronization scope ID of this cmpxchg instruction.
void setSyncScopeID(SyncScope::ID SSID) {
this->SSID = SSID;
}
Value *getPointerOperand() { return getOperand(0); }
@ -652,6 +652,11 @@ class AtomicCmpXchgInst : public Instruction {
void setInstructionSubclassData(unsigned short D) {
Instruction::setInstructionSubclassData(D);
}
/// The synchronization scope ID of this cmpxchg instruction. Not quite
/// enough room in SubClassData for everything, so synchronization scope ID
/// gets its own field.
SyncScope::ID SSID;
};
template <>
@ -711,10 +716,10 @@ class AtomicRMWInst : public Instruction {
};
AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val,
AtomicOrdering Ordering, SynchronizationScope SynchScope,
AtomicOrdering Ordering, SyncScope::ID SSID,
Instruction *InsertBefore = nullptr);
AtomicRMWInst(BinOp Operation, Value *Ptr, Value *Val,
AtomicOrdering Ordering, SynchronizationScope SynchScope,
AtomicOrdering Ordering, SyncScope::ID SSID,
BasicBlock *InsertAtEnd);
// allocate space for exactly two operands
@ -748,7 +753,12 @@ class AtomicRMWInst : public Instruction {
/// Transparently provide more efficient getOperand methods.
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
/// Set the ordering constraint on this RMW.
/// Returns the ordering constraint of this rmw instruction.
AtomicOrdering getOrdering() const {
return AtomicOrdering((getSubclassDataFromInstruction() >> 2) & 7);
}
/// Sets the ordering constraint of this rmw instruction.
void setOrdering(AtomicOrdering Ordering) {
assert(Ordering != AtomicOrdering::NotAtomic &&
"atomicrmw instructions can only be atomic.");
@ -756,23 +766,14 @@ class AtomicRMWInst : public Instruction {
((unsigned)Ordering << 2));
}
/// Specify whether this RMW orders other operations with respect to all
/// concurrently executing threads, or only with respect to signal handlers
/// executing in the same thread.
void setSynchScope(SynchronizationScope SynchScope) {
setInstructionSubclassData((getSubclassDataFromInstruction() & ~2) |
(SynchScope << 1));
/// Returns the synchronization scope ID of this rmw instruction.
SyncScope::ID getSyncScopeID() const {
return SSID;
}
/// Returns the ordering constraint on this RMW.
AtomicOrdering getOrdering() const {
return AtomicOrdering((getSubclassDataFromInstruction() >> 2) & 7);
}
/// Returns whether this RMW is atomic between threads or only within a
/// single thread.
SynchronizationScope getSynchScope() const {
return SynchronizationScope((getSubclassDataFromInstruction() & 2) >> 1);
/// Sets the synchronization scope ID of this rmw instruction.
void setSyncScopeID(SyncScope::ID SSID) {
this->SSID = SSID;
}
Value *getPointerOperand() { return getOperand(0); }
@ -797,13 +798,18 @@ class AtomicRMWInst : public Instruction {
private:
void Init(BinOp Operation, Value *Ptr, Value *Val,
AtomicOrdering Ordering, SynchronizationScope SynchScope);
AtomicOrdering Ordering, SyncScope::ID SSID);
// Shadow Instruction::setInstructionSubclassData with a private forwarding
// method so that subclasses cannot accidentally use it.
void setInstructionSubclassData(unsigned short D) {
Instruction::setInstructionSubclassData(D);
}
/// The synchronization scope ID of this rmw instruction. Not quite enough
/// room in SubClassData for everything, so synchronization scope ID gets its
/// own field.
SyncScope::ID SSID;
};
template <>
@ -1101,8 +1107,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrInst, Value)
/// Represent an integer comparison operator.
class ICmpInst: public CmpInst {
void AssertOK() {
assert(getPredicate() >= CmpInst::FIRST_ICMP_PREDICATE &&
getPredicate() <= CmpInst::LAST_ICMP_PREDICATE &&
assert(isIntPredicate() &&
"Invalid ICmp predicate value");
assert(getOperand(0)->getType() == getOperand(1)->getType() &&
"Both operands to ICmp instruction are not of the same type!");
@ -1244,8 +1249,7 @@ class ICmpInst: public CmpInst {
/// Represents a floating point comparison operator.
class FCmpInst: public CmpInst {
void AssertOK() {
assert(getPredicate() <= FCmpInst::LAST_FCMP_PREDICATE &&
"Invalid FCmp predicate value");
assert(isFPPredicate() && "Invalid FCmp predicate value");
assert(getOperand(0)->getType() == getOperand(1)->getType() &&
"Both operands to FCmp instruction are not of the same type!");
// Check that the operands are the right type

Some files were not shown because too many files have changed in this diff Show More