mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-07 13:14:51 +00:00
Vendor import of llvm trunk r306325:
https://llvm.org/svn/llvm-project/llvm/trunk@306325
This commit is contained in:
parent
7c7aba6e5f
commit
08bbd35a80
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/llvm/dist/; revision=320374 svn path=/vendor/llvm/llvm-trunk-r306325/; revision=320375; tag=vendor/llvm/llvm-trunk-r306325
@ -94,7 +94,7 @@ if(CMAKE_HOST_APPLE AND APPLE)
|
||||
set(LIBTOOL_NO_WARNING_FLAG "-no_warning_for_no_symbols")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
foreach(lang ${languages})
|
||||
set(CMAKE_${lang}_CREATE_STATIC_LIBRARY
|
||||
"${CMAKE_LIBTOOL} -static ${LIBTOOL_NO_WARNING_FLAG} -o <TARGET> \
|
||||
@ -570,6 +570,10 @@ if (LLVM_BUILD_STATIC)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
|
||||
endif()
|
||||
|
||||
# Override the default target with an environment variable named by LLVM_TARGET_TRIPLE_ENV.
|
||||
set(LLVM_TARGET_TRIPLE_ENV CACHE STRING "The name of environment variable to override default target. Disabled by blank.")
|
||||
mark_as_advanced(LLVM_TARGET_TRIPLE_ENV)
|
||||
|
||||
# All options referred to from HandleLLVMOptions have to be specified
|
||||
# BEFORE this include, otherwise options will not be correctly set on
|
||||
# first cmake run
|
||||
@ -800,7 +804,8 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "(FreeBSD|DragonFly)")
|
||||
endif(${CMAKE_SYSTEM_NAME} MATCHES "(FreeBSD|DragonFly)")
|
||||
|
||||
if( ${CMAKE_SYSTEM_NAME} MATCHES SunOS )
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -include llvm/Support/Solaris.h")
|
||||
# special hack for Solaris to handle crazy system sys/regset.h
|
||||
include_directories("${LLVM_MAIN_INCLUDE_DIR}/llvm/Support/Solaris")
|
||||
endif( ${CMAKE_SYSTEM_NAME} MATCHES SunOS )
|
||||
|
||||
# Make sure we don't get -rdynamic in every binary. For those that need it,
|
||||
|
@ -195,6 +195,7 @@ D: MemorySanitizer (LLVM part)
|
||||
|
||||
N: Craig Topper
|
||||
E: craig.topper@gmail.com
|
||||
E: craig.topper@intel.com
|
||||
D: X86 Backend
|
||||
|
||||
N: Ulrich Weigand
|
||||
|
@ -220,7 +220,7 @@ W: http://randomhacks.net/
|
||||
D: llvm-config script
|
||||
|
||||
N: Anton Korobeynikov
|
||||
E: asl@math.spbu.ru
|
||||
E: anton at korobeynikov dot info
|
||||
D: Mingw32 fixes, cross-compiling support, stdcall/fastcall calling conv.
|
||||
D: x86/linux PIC codegen, aliases, regparm/visibility attributes
|
||||
D: Switch lowering refactoring
|
||||
|
@ -1133,6 +1133,19 @@ function(configure_lit_site_cfg input output)
|
||||
|
||||
set(LIT_SITE_CFG_IN_HEADER "## Autogenerated from ${input}\n## Do not edit!")
|
||||
|
||||
# Override config_target_triple (and the env)
|
||||
if(LLVM_TARGET_TRIPLE_ENV)
|
||||
# This is expanded into the heading.
|
||||
string(CONCAT LIT_SITE_CFG_IN_HEADER "${LIT_SITE_CFG_IN_HEADER}\n\n"
|
||||
"import os\n"
|
||||
"target_env = \"${LLVM_TARGET_TRIPLE_ENV}\"\n"
|
||||
"config.target_triple = config.environment[target_env] = os.environ.get(target_env, \"${TARGET_TRIPLE}\")\n"
|
||||
)
|
||||
|
||||
# This is expanded to; config.target_triple = ""+config.target_triple+""
|
||||
set(TARGET_TRIPLE "\"+config.target_triple+\"")
|
||||
endif()
|
||||
|
||||
configure_file(${input} ${output} @ONLY)
|
||||
endfunction()
|
||||
|
||||
|
@ -642,6 +642,9 @@ if(LLVM_USE_SANITIZER)
|
||||
append_common_sanitizer_flags()
|
||||
append("-fsanitize=address,undefined -fno-sanitize=vptr,function -fno-sanitize-recover=all"
|
||||
CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
elseif (LLVM_USE_SANITIZER STREQUAL "Leaks")
|
||||
append_common_sanitizer_flags()
|
||||
append("-fsanitize=leak" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported value of LLVM_USE_SANITIZER: ${LLVM_USE_SANITIZER}")
|
||||
endif()
|
||||
|
@ -14,8 +14,31 @@ function(tablegen project ofn)
|
||||
message(FATAL_ERROR "${project}_TABLEGEN_EXE not set")
|
||||
endif()
|
||||
|
||||
file(GLOB local_tds "*.td")
|
||||
file(GLOB_RECURSE global_tds "${LLVM_MAIN_INCLUDE_DIR}/llvm/*.td")
|
||||
# Use depfile instead of globbing arbitrary *.td(s)
|
||||
# DEPFILE is available for Ninja Generator with CMake>=3.7.
|
||||
if(CMAKE_GENERATOR STREQUAL "Ninja" AND NOT CMAKE_VERSION VERSION_LESS 3.7)
|
||||
# Make output path relative to build.ninja, assuming located on
|
||||
# ${CMAKE_BINARY_DIR}.
|
||||
# CMake emits build targets as relative paths but Ninja doesn't identify
|
||||
# absolute path (in *.d) as relative path (in build.ninja)
|
||||
# Note that tblgen is executed on ${CMAKE_BINARY_DIR} as working directory.
|
||||
file(RELATIVE_PATH ofn_rel
|
||||
${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/${ofn})
|
||||
set(additional_cmdline
|
||||
-o ${ofn_rel}.tmp
|
||||
-d ${ofn_rel}.d
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.d
|
||||
)
|
||||
set(local_tds)
|
||||
set(global_tds)
|
||||
else()
|
||||
file(GLOB local_tds "*.td")
|
||||
file(GLOB_RECURSE global_tds "${LLVM_MAIN_INCLUDE_DIR}/llvm/*.td")
|
||||
set(additional_cmdline
|
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp
|
||||
)
|
||||
endif()
|
||||
|
||||
if (IS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS})
|
||||
set(LLVM_TARGET_DEFINITIONS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS})
|
||||
@ -44,7 +67,7 @@ function(tablegen project ofn)
|
||||
COMMAND ${${project}_TABLEGEN_EXE} ${ARGN} -I ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${LLVM_TABLEGEN_FLAGS}
|
||||
${LLVM_TARGET_DEFINITIONS_ABSOLUTE}
|
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/${ofn}.tmp
|
||||
${additional_cmdline}
|
||||
# The file in LLVM_TARGET_DEFINITIONS may be not in the current
|
||||
# directory and local_tds may not contain it, so we must
|
||||
# explicitly list it here:
|
||||
@ -104,7 +127,8 @@ macro(add_tablegen target project)
|
||||
set(${target}_OLD_LLVM_LINK_COMPONENTS ${LLVM_LINK_COMPONENTS})
|
||||
set(LLVM_LINK_COMPONENTS ${LLVM_LINK_COMPONENTS} TableGen)
|
||||
|
||||
if(NOT XCODE)
|
||||
# CMake-3.9 doesn't let compilation units depend on their dependent libraries.
|
||||
if(NOT (CMAKE_GENERATOR STREQUAL "Ninja" AND NOT CMAKE_VERSION VERSION_LESS 3.9) AND NOT XCODE)
|
||||
# FIXME: It leaks to user, callee of add_tablegen.
|
||||
set(LLVM_ENABLE_OBJLIB ON)
|
||||
endif()
|
||||
|
@ -587,7 +587,7 @@ Code Object Metadata
|
||||
The code object metadata is specified by the ``NT_AMD_AMDHSA_METADATA`` note
|
||||
record (see :ref:`amdgpu-note-records`).
|
||||
|
||||
The metadata is specified as a YAML formated string (see [YAML]_ and
|
||||
The metadata is specified as a YAML formatted string (see [YAML]_ and
|
||||
:doc:`YamlIO`).
|
||||
|
||||
The metadata is represented as a single YAML document comprised of the mapping
|
||||
@ -1031,11 +1031,11 @@ Global variable
|
||||
appropriate section according to if it has initialized data or is readonly.
|
||||
|
||||
If the symbol is external then its section is ``STN_UNDEF`` and the loader
|
||||
will resolve relocations using the defintion provided by another code object
|
||||
will resolve relocations using the definition provided by another code object
|
||||
or explicitly defined by the runtime.
|
||||
|
||||
All global symbols, whether defined in the compilation unit or external, are
|
||||
accessed by the machine code indirectly throught a GOT table entry. This
|
||||
accessed by the machine code indirectly through a GOT table entry. This
|
||||
allows them to be preemptable. The GOT table is only supported when the target
|
||||
triple OS is ``amdhsa`` (see :ref:`amdgpu-target-triples`).
|
||||
|
||||
@ -1160,7 +1160,7 @@ Register Mapping
|
||||
Define DWARF register enumeration.
|
||||
|
||||
If want to present a wavefront state then should expose vector registers as
|
||||
64 wide (rather than per work-item view that LLVM uses). Either as seperate
|
||||
64 wide (rather than per work-item view that LLVM uses). Either as separate
|
||||
registers, or a 64x4 byte single register. In either case use a new LANE op
|
||||
(akin to XDREF) to select the current lane usage in a location
|
||||
expression. This would also allow scalar register spilling to vector register
|
||||
@ -1653,7 +1653,7 @@ CP microcode requires the Kernel descritor to be allocated on 64 byte alignment.
|
||||
``COMPUTE_PGM_RSRC2.USER_SGPR``.
|
||||
6 1 bit enable_trap_handler Set to 1 if code contains a
|
||||
TRAP instruction which
|
||||
requires a trap hander to
|
||||
requires a trap handler to
|
||||
be enabled.
|
||||
|
||||
CP sets
|
||||
@ -2146,7 +2146,7 @@ This section describes the mapping of LLVM memory model onto AMDGPU machine code
|
||||
.. TODO
|
||||
Update when implementation complete.
|
||||
|
||||
Support more relaxed OpenCL memory model to be controled by environment
|
||||
Support more relaxed OpenCL memory model to be controlled by environment
|
||||
component of target triple.
|
||||
|
||||
The AMDGPU backend supports the memory synchronization scopes specified in
|
||||
@ -2201,7 +2201,7 @@ For GFX6-GFX9:
|
||||
can be reordered relative to each other, which can result in reordering the
|
||||
visibility of vector memory operations with respect to LDS operations of other
|
||||
wavefronts in the same work-group. A ``s_waitcnt lgkmcnt(0)`` is required to
|
||||
ensure synchonization between LDS operations and vector memory operations
|
||||
ensure synchronization between LDS operations and vector memory operations
|
||||
between waves of a work-group, but not between operations performed by the
|
||||
same wavefront.
|
||||
* The vector memory operations are performed as wavefront wide operations and
|
||||
@ -2226,7 +2226,7 @@ For GFX6-GFX9:
|
||||
scalar memory operations performed by waves executing in different work-groups
|
||||
(which may be executing on different CUs) of an agent can be reordered
|
||||
relative to each other. A ``s_waitcnt vmcnt(0)`` is required to ensure
|
||||
synchonization between vector memory operations of different CUs. It ensures a
|
||||
synchronization between vector memory operations of different CUs. It ensures a
|
||||
previous vector memory operation has completed before executing a subsequent
|
||||
vector memory or LDS operation and so can be used to meet the requirements of
|
||||
acquire and release.
|
||||
@ -2268,7 +2268,7 @@ and vector L1 caches are invalidated between kernel dispatches by CP since
|
||||
constant address space data may change between kernel dispatch executions. See
|
||||
:ref:`amdgpu-amdhsa-memory-spaces`.
|
||||
|
||||
The one exeception is if scalar writes are used to spill SGPR registers. In this
|
||||
The one execption is if scalar writes are used to spill SGPR registers. In this
|
||||
case the AMDGPU backend ensures the memory location used to spill is never
|
||||
accessed by vector memory operations at the same time. If scalar writes are used
|
||||
then a ``s_dcache_wb`` is inserted before the ``s_endpgm`` and before a function
|
||||
@ -3310,7 +3310,7 @@ table
|
||||
be moved before the acquire.
|
||||
- If a fence then same as load atomic, plus no preceding
|
||||
associated fence-paired-atomic can be moved after the fence.
|
||||
release - If a store atomic/atomicrmw then no preceeding load/load
|
||||
release - If a store atomic/atomicrmw then no preceding load/load
|
||||
atomic/store/ store atomic/atomicrmw/fence instruction can
|
||||
be moved after the release.
|
||||
- If a fence then same as store atomic, plus no following
|
||||
|
@ -27,7 +27,7 @@ questions.
|
||||
What is the first index of the GEP instruction?
|
||||
-----------------------------------------------
|
||||
|
||||
Quick answer: The index stepping through the first operand.
|
||||
Quick answer: The index stepping through the second operand.
|
||||
|
||||
The confusion with the first index usually arises from thinking about the
|
||||
GetElementPtr instruction as if it was a C index operator. They aren't the
|
||||
@ -59,7 +59,7 @@ Sometimes this question gets rephrased as:
|
||||
won't be dereferenced?*
|
||||
|
||||
The answer is simply because memory does not have to be accessed to perform the
|
||||
computation. The first operand to the GEP instruction must be a value of a
|
||||
computation. The second operand to the GEP instruction must be a value of a
|
||||
pointer type. The value of the pointer is provided directly to the GEP
|
||||
instruction as an operand without any need for accessing memory. It must,
|
||||
therefore be indexed and requires an index operand. Consider this example:
|
||||
@ -80,8 +80,8 @@ therefore be indexed and requires an index operand. Consider this example:
|
||||
|
||||
In this "C" example, the front end compiler (Clang) will generate three GEP
|
||||
instructions for the three indices through "P" in the assignment statement. The
|
||||
function argument ``P`` will be the first operand of each of these GEP
|
||||
instructions. The second operand indexes through that pointer. The third
|
||||
function argument ``P`` will be the second operand of each of these GEP
|
||||
instructions. The third operand indexes through that pointer. The fourth
|
||||
operand will be the field offset into the ``struct munger_struct`` type, for
|
||||
either the ``f1`` or ``f2`` field. So, in LLVM assembly the ``munge`` function
|
||||
looks like:
|
||||
@ -100,8 +100,8 @@ looks like:
|
||||
ret void
|
||||
}
|
||||
|
||||
In each case the first operand is the pointer through which the GEP instruction
|
||||
starts. The same is true whether the first operand is an argument, allocated
|
||||
In each case the second operand is the pointer through which the GEP instruction
|
||||
starts. The same is true whether the second operand is an argument, allocated
|
||||
memory, or a global variable.
|
||||
|
||||
To make this clear, let's consider a more obtuse example:
|
||||
@ -159,11 +159,11 @@ confusion:
|
||||
i32 }*``. That is, ``%MyStruct`` is a pointer to a structure containing a
|
||||
pointer to a ``float`` and an ``i32``.
|
||||
|
||||
#. Point #1 is evidenced by noticing the type of the first operand of the GEP
|
||||
#. Point #1 is evidenced by noticing the type of the second operand of the GEP
|
||||
instruction (``%MyStruct``) which is ``{ float*, i32 }*``.
|
||||
|
||||
#. The first index, ``i64 0`` is required to step over the global variable
|
||||
``%MyStruct``. Since the first argument to the GEP instruction must always
|
||||
``%MyStruct``. Since the second argument to the GEP instruction must always
|
||||
be a value of pointer type, the first index steps through that pointer. A
|
||||
value of 0 means 0 elements offset from that pointer.
|
||||
|
||||
@ -267,7 +267,7 @@ in the IR. In the future, it will probably be outright disallowed.
|
||||
What effect do address spaces have on GEPs?
|
||||
-------------------------------------------
|
||||
|
||||
None, except that the address space qualifier on the first operand pointer type
|
||||
None, except that the address space qualifier on the second operand pointer type
|
||||
always matches the address space qualifier on the result type.
|
||||
|
||||
How is GEP different from ``ptrtoint``, arithmetic, and ``inttoptr``?
|
||||
@ -526,7 +526,7 @@ instruction:
|
||||
#. The GEP instruction never accesses memory, it only provides pointer
|
||||
computations.
|
||||
|
||||
#. The first operand to the GEP instruction is always a pointer and it must be
|
||||
#. The second operand to the GEP instruction is always a pointer and it must be
|
||||
indexed.
|
||||
|
||||
#. There are no superfluous indices for the GEP instruction.
|
||||
|
@ -7,7 +7,7 @@ Introduction
|
||||
|
||||
Building with link time optimization requires cooperation from
|
||||
the system linker. LTO support on Linux systems requires that you use the
|
||||
`gold linker`_ which supports LTO via plugins. This is the same mechanism
|
||||
`gold linker`_ or ld.bfd from binutils >= 2.21.51.0.2, as they support LTO via plugins. This is the same mechanism
|
||||
used by the `GCC LTO`_ project.
|
||||
|
||||
The LLVM gold plugin implements the gold plugin interface on top of
|
||||
@ -23,24 +23,22 @@ The LLVM gold plugin implements the gold plugin interface on top of
|
||||
How to build it
|
||||
===============
|
||||
|
||||
You need to have gold with plugin support and build the LLVMgold plugin.
|
||||
Check whether you have gold running ``/usr/bin/ld -v``. It will report "GNU
|
||||
gold" or else "GNU ld" if not. If you have gold, check for plugin support
|
||||
by running ``/usr/bin/ld -plugin``. If it complains "missing argument" then
|
||||
you have plugin support. If not, such as an "unknown option" error then you
|
||||
will either need to build gold or install a version with plugin support.
|
||||
Check for plugin support by running ``/usr/bin/ld -plugin``. If it complains
|
||||
"missing argument" then you have plugin support. If not, such as an "unknown option"
|
||||
error then you will either need to build gold or install a recent version
|
||||
of ld.bfd with plugin support and then build gold plugin.
|
||||
|
||||
* Download, configure and build gold with plugin support:
|
||||
* Download, configure and build ld.bfd with plugin support:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ git clone --depth 1 git://sourceware.org/git/binutils-gdb.git binutils
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
$ ../binutils/configure --enable-gold --enable-plugins --disable-werror
|
||||
$ make all-gold
|
||||
$ ../binutils/configure --disable-werror # ld.bfd includes plugin support by default
|
||||
$ make all-ld
|
||||
|
||||
That should leave you with ``build/gold/ld-new`` which supports
|
||||
That should leave you with ``build/ld/ld-new`` which supports
|
||||
the ``-plugin`` option. Running ``make`` will additionally build
|
||||
``build/binutils/ar`` and ``nm-new`` binaries supporting plugins.
|
||||
|
||||
|
@ -1468,6 +1468,19 @@ example:
|
||||
This attribute by itself does not imply restrictions on
|
||||
inter-procedural optimizations. All of the semantic effects the
|
||||
patching may have to be separately conveyed via the linkage type.
|
||||
``"probe-stack"``
|
||||
This attribute indicates that the function will trigger a guard region
|
||||
in the end of the stack. It ensures that accesses to the stack must be
|
||||
no further apart than the size of the guard region to a previous
|
||||
access of the stack. It takes one required string value, the name of
|
||||
the stack probing function that will be called.
|
||||
|
||||
If a function that has a ``"probe-stack"`` attribute is inlined into
|
||||
a function with another ``"probe-stack"`` attribute, the resulting
|
||||
function has the ``"probe-stack"`` attribute of the caller. If a
|
||||
function that has a ``"probe-stack"`` attribute is inlined into a
|
||||
function that has no ``"probe-stack"`` attribute at all, the resulting
|
||||
function has the ``"probe-stack"`` attribute of the callee.
|
||||
``readnone``
|
||||
On a function, this attribute indicates that the function computes its
|
||||
result (or decides to unwind an exception) based strictly on its arguments,
|
||||
@ -1498,6 +1511,21 @@ example:
|
||||
On an argument, this attribute indicates that the function does not write
|
||||
through this pointer argument, even though it may write to the memory that
|
||||
the pointer points to.
|
||||
``"stack-probe-size"``
|
||||
This attribute controls the behavior of stack probes: either
|
||||
the ``"probe-stack"`` attribute, or ABI-required stack probes, if any.
|
||||
It defines the size of the guard region. It ensures that if the function
|
||||
may use more stack space than the size of the guard region, stack probing
|
||||
sequence will be emitted. It takes one required integer value, which
|
||||
is 4096 by default.
|
||||
|
||||
If a function that has a ``"stack-probe-size"`` attribute is inlined into
|
||||
a function with another ``"stack-probe-size"`` attribute, the resulting
|
||||
function has the ``"stack-probe-size"`` attribute that has the lower
|
||||
numeric value. If a function that has a ``"stack-probe-size"`` attribute is
|
||||
inlined into a function that has no ``"stack-probe-size"`` attribute
|
||||
at all, the resulting function has the ``"stack-probe-size"`` attribute
|
||||
of the callee.
|
||||
``writeonly``
|
||||
On a function, this attribute indicates that the function may write to but
|
||||
does not read from memory.
|
||||
@ -1989,7 +2017,7 @@ A pointer value is *based* on another pointer value according to the
|
||||
following rules:
|
||||
|
||||
- A pointer value formed from a ``getelementptr`` operation is *based*
|
||||
on the first value operand of the ``getelementptr``.
|
||||
on the second value operand of the ``getelementptr``.
|
||||
- The result value of a ``bitcast`` is *based* on the operand of the
|
||||
``bitcast``.
|
||||
- A pointer value formed by an ``inttoptr`` is *based* on all pointer
|
||||
@ -3166,7 +3194,7 @@ The following is the syntax for constant expressions:
|
||||
``getelementptr (TY, CSTPTR, IDX0, IDX1, ...)``, ``getelementptr inbounds (TY, CSTPTR, IDX0, IDX1, ...)``
|
||||
Perform the :ref:`getelementptr operation <i_getelementptr>` on
|
||||
constants. As with the :ref:`getelementptr <i_getelementptr>`
|
||||
instruction, the index list may have zero or more indexes, which are
|
||||
instruction, the index list may have one or more indexes, which are
|
||||
required to make sense for the type of "pointer to TY".
|
||||
``select (COND, VAL1, VAL2)``
|
||||
Perform the :ref:`select operation <i_select>` on constants.
|
||||
@ -7805,7 +7833,7 @@ base address to start from. The remaining arguments are indices
|
||||
that indicate which of the elements of the aggregate object are indexed.
|
||||
The interpretation of each index is dependent on the type being indexed
|
||||
into. The first index always indexes the pointer value given as the
|
||||
first argument, the second index indexes a value of the type pointed to
|
||||
second argument, the second index indexes a value of the type pointed to
|
||||
(not necessarily the value directly pointed to, since the first index
|
||||
can be non-zero), etc. The first type indexed into must be a pointer
|
||||
value, subsequent types can be arrays, vectors, and structs. Note that
|
||||
|
@ -27,7 +27,7 @@ Vectorization Workflow
|
||||
VPlan-based vectorization involves three major steps, taking a "scenario-based
|
||||
approach" to vectorization planning:
|
||||
|
||||
1. Legal Step: check if a loop can be legally vectorized; encode contraints and
|
||||
1. Legal Step: check if a loop can be legally vectorized; encode constraints and
|
||||
artifacts if so.
|
||||
2. Plan Step:
|
||||
|
||||
|
@ -150,7 +150,7 @@ variable, where we list down the options and their defaults below.
|
||||
| xray_logfile_base | ``const char*`` | ``xray-log.`` | Filename base for the |
|
||||
| | | | XRay logfile. |
|
||||
+-------------------+-----------------+---------------+------------------------+
|
||||
| xray_fdr_log | ``bool`` | ``false`` | Wheter to install the |
|
||||
| xray_fdr_log | ``bool`` | ``false`` | Whether to install the |
|
||||
| | | | Flight Data Recorder |
|
||||
| | | | (FDR) mode. |
|
||||
+-------------------+-----------------+---------------+------------------------+
|
||||
|
@ -40,11 +40,11 @@ class KaleidoscopeJIT {
|
||||
private:
|
||||
std::unique_ptr<TargetMachine> TM;
|
||||
const DataLayout DL;
|
||||
RTDyldObjectLinkingLayer<> ObjectLayer;
|
||||
IRCompileLayer<decltype(ObjectLayer)> CompileLayer;
|
||||
RTDyldObjectLinkingLayer ObjectLayer;
|
||||
IRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
|
||||
|
||||
public:
|
||||
using ModuleHandle = decltype(CompileLayer)::ModuleSetHandleT;
|
||||
using ModuleHandle = decltype(CompileLayer)::ModuleHandleT;
|
||||
|
||||
KaleidoscopeJIT()
|
||||
: TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
|
||||
@ -72,15 +72,11 @@ class KaleidoscopeJIT {
|
||||
return JITSymbol(nullptr);
|
||||
});
|
||||
|
||||
// Build a singleton module set to hold our module.
|
||||
std::vector<std::unique_ptr<Module>> Ms;
|
||||
Ms.push_back(std::move(M));
|
||||
|
||||
// Add the set to the JIT with the resolver we created above and a newly
|
||||
// created SectionMemoryManager.
|
||||
return CompileLayer.addModuleSet(std::move(Ms),
|
||||
make_unique<SectionMemoryManager>(),
|
||||
std::move(Resolver));
|
||||
return CompileLayer.addModule(std::move(M),
|
||||
make_unique<SectionMemoryManager>(),
|
||||
std::move(Resolver));
|
||||
}
|
||||
|
||||
JITSymbol findSymbol(const std::string Name) {
|
||||
@ -91,7 +87,7 @@ class KaleidoscopeJIT {
|
||||
}
|
||||
|
||||
void removeModule(ModuleHandle H) {
|
||||
CompileLayer.removeModuleSet(H);
|
||||
CompileLayer.removeModule(H);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -44,22 +44,22 @@ class KaleidoscopeJIT {
|
||||
private:
|
||||
std::unique_ptr<TargetMachine> TM;
|
||||
const DataLayout DL;
|
||||
RTDyldObjectLinkingLayer<> ObjectLayer;
|
||||
IRCompileLayer<decltype(ObjectLayer)> CompileLayer;
|
||||
RTDyldObjectLinkingLayer ObjectLayer;
|
||||
IRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
|
||||
|
||||
using OptimizeFunction =
|
||||
std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>;
|
||||
std::function<std::shared_ptr<Module>(std::shared_ptr<Module>)>;
|
||||
|
||||
IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
|
||||
|
||||
public:
|
||||
using ModuleHandle = decltype(OptimizeLayer)::ModuleSetHandleT;
|
||||
using ModuleHandle = decltype(OptimizeLayer)::ModuleHandleT;
|
||||
|
||||
KaleidoscopeJIT()
|
||||
: TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
|
||||
CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
|
||||
OptimizeLayer(CompileLayer,
|
||||
[this](std::unique_ptr<Module> M) {
|
||||
[this](std::shared_ptr<Module> M) {
|
||||
return optimizeModule(std::move(M));
|
||||
}) {
|
||||
llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
|
||||
@ -85,15 +85,11 @@ class KaleidoscopeJIT {
|
||||
return JITSymbol(nullptr);
|
||||
});
|
||||
|
||||
// Build a singleton module set to hold our module.
|
||||
std::vector<std::unique_ptr<Module>> Ms;
|
||||
Ms.push_back(std::move(M));
|
||||
|
||||
// Add the set to the JIT with the resolver we created above and a newly
|
||||
// created SectionMemoryManager.
|
||||
return OptimizeLayer.addModuleSet(std::move(Ms),
|
||||
make_unique<SectionMemoryManager>(),
|
||||
std::move(Resolver));
|
||||
return OptimizeLayer.addModule(std::move(M),
|
||||
make_unique<SectionMemoryManager>(),
|
||||
std::move(Resolver));
|
||||
}
|
||||
|
||||
JITSymbol findSymbol(const std::string Name) {
|
||||
@ -104,11 +100,11 @@ class KaleidoscopeJIT {
|
||||
}
|
||||
|
||||
void removeModule(ModuleHandle H) {
|
||||
OptimizeLayer.removeModuleSet(H);
|
||||
OptimizeLayer.removeModule(H);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Module> optimizeModule(std::unique_ptr<Module> M) {
|
||||
std::shared_ptr<Module> optimizeModule(std::shared_ptr<Module> M) {
|
||||
// Create a function pass manager.
|
||||
auto FPM = llvm::make_unique<legacy::FunctionPassManager>(M.get());
|
||||
|
||||
|
@ -47,11 +47,11 @@ class KaleidoscopeJIT {
|
||||
private:
|
||||
std::unique_ptr<TargetMachine> TM;
|
||||
const DataLayout DL;
|
||||
RTDyldObjectLinkingLayer<> ObjectLayer;
|
||||
IRCompileLayer<decltype(ObjectLayer)> CompileLayer;
|
||||
RTDyldObjectLinkingLayer ObjectLayer;
|
||||
IRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
|
||||
|
||||
using OptimizeFunction =
|
||||
std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>;
|
||||
std::function<std::shared_ptr<Module>(std::shared_ptr<Module>)>;
|
||||
|
||||
IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
|
||||
|
||||
@ -59,13 +59,13 @@ class KaleidoscopeJIT {
|
||||
CompileOnDemandLayer<decltype(OptimizeLayer)> CODLayer;
|
||||
|
||||
public:
|
||||
using ModuleHandle = decltype(CODLayer)::ModuleSetHandleT;
|
||||
using ModuleHandle = decltype(CODLayer)::ModuleHandleT;
|
||||
|
||||
KaleidoscopeJIT()
|
||||
: TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
|
||||
CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
|
||||
OptimizeLayer(CompileLayer,
|
||||
[this](std::unique_ptr<Module> M) {
|
||||
[this](std::shared_ptr<Module> M) {
|
||||
return optimizeModule(std::move(M));
|
||||
}),
|
||||
CompileCallbackManager(
|
||||
@ -98,15 +98,11 @@ class KaleidoscopeJIT {
|
||||
return JITSymbol(nullptr);
|
||||
});
|
||||
|
||||
// Build a singleton module set to hold our module.
|
||||
std::vector<std::unique_ptr<Module>> Ms;
|
||||
Ms.push_back(std::move(M));
|
||||
|
||||
// Add the set to the JIT with the resolver we created above and a newly
|
||||
// created SectionMemoryManager.
|
||||
return CODLayer.addModuleSet(std::move(Ms),
|
||||
make_unique<SectionMemoryManager>(),
|
||||
std::move(Resolver));
|
||||
return CODLayer.addModule(std::move(M),
|
||||
make_unique<SectionMemoryManager>(),
|
||||
std::move(Resolver));
|
||||
}
|
||||
|
||||
JITSymbol findSymbol(const std::string Name) {
|
||||
@ -117,11 +113,11 @@ class KaleidoscopeJIT {
|
||||
}
|
||||
|
||||
void removeModule(ModuleHandle H) {
|
||||
CODLayer.removeModuleSet(H);
|
||||
CODLayer.removeModule(H);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Module> optimizeModule(std::unique_ptr<Module> M) {
|
||||
std::shared_ptr<Module> optimizeModule(std::shared_ptr<Module> M) {
|
||||
// Create a function pass manager.
|
||||
auto FPM = llvm::make_unique<legacy::FunctionPassManager>(M.get());
|
||||
|
||||
|
@ -73,11 +73,11 @@ class KaleidoscopeJIT {
|
||||
private:
|
||||
std::unique_ptr<TargetMachine> TM;
|
||||
const DataLayout DL;
|
||||
RTDyldObjectLinkingLayer<> ObjectLayer;
|
||||
IRCompileLayer<decltype(ObjectLayer)> CompileLayer;
|
||||
RTDyldObjectLinkingLayer ObjectLayer;
|
||||
IRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
|
||||
|
||||
using OptimizeFunction =
|
||||
std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>;
|
||||
std::function<std::shared_ptr<Module>(std::shared_ptr<Module>)>;
|
||||
|
||||
IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
|
||||
|
||||
@ -85,14 +85,14 @@ class KaleidoscopeJIT {
|
||||
std::unique_ptr<IndirectStubsManager> IndirectStubsMgr;
|
||||
|
||||
public:
|
||||
using ModuleHandle = decltype(OptimizeLayer)::ModuleSetHandleT;
|
||||
using ModuleHandle = decltype(OptimizeLayer)::ModuleHandleT;
|
||||
|
||||
KaleidoscopeJIT()
|
||||
: TM(EngineBuilder().selectTarget()),
|
||||
DL(TM->createDataLayout()),
|
||||
CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
|
||||
OptimizeLayer(CompileLayer,
|
||||
[this](std::unique_ptr<Module> M) {
|
||||
[this](std::shared_ptr<Module> M) {
|
||||
return optimizeModule(std::move(M));
|
||||
}),
|
||||
CompileCallbackMgr(
|
||||
@ -125,15 +125,11 @@ class KaleidoscopeJIT {
|
||||
return JITSymbol(nullptr);
|
||||
});
|
||||
|
||||
// Build a singleton module set to hold our module.
|
||||
std::vector<std::unique_ptr<Module>> Ms;
|
||||
Ms.push_back(std::move(M));
|
||||
|
||||
// Add the set to the JIT with the resolver we created above and a newly
|
||||
// created SectionMemoryManager.
|
||||
return OptimizeLayer.addModuleSet(std::move(Ms),
|
||||
make_unique<SectionMemoryManager>(),
|
||||
std::move(Resolver));
|
||||
return OptimizeLayer.addModule(std::move(M),
|
||||
make_unique<SectionMemoryManager>(),
|
||||
std::move(Resolver));
|
||||
}
|
||||
|
||||
Error addFunctionAST(std::unique_ptr<FunctionAST> FnAST) {
|
||||
@ -199,7 +195,7 @@ class KaleidoscopeJIT {
|
||||
}
|
||||
|
||||
void removeModule(ModuleHandle H) {
|
||||
OptimizeLayer.removeModuleSet(H);
|
||||
OptimizeLayer.removeModule(H);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -210,7 +206,7 @@ class KaleidoscopeJIT {
|
||||
return MangledNameStream.str();
|
||||
}
|
||||
|
||||
std::unique_ptr<Module> optimizeModule(std::unique_ptr<Module> M) {
|
||||
std::shared_ptr<Module> optimizeModule(std::shared_ptr<Module> M) {
|
||||
// Create a function pass manager.
|
||||
auto FPM = llvm::make_unique<legacy::FunctionPassManager>(M.get());
|
||||
|
||||
|
@ -78,11 +78,11 @@ class KaleidoscopeJIT {
|
||||
private:
|
||||
std::unique_ptr<TargetMachine> TM;
|
||||
const DataLayout DL;
|
||||
RTDyldObjectLinkingLayer<> ObjectLayer;
|
||||
IRCompileLayer<decltype(ObjectLayer)> CompileLayer;
|
||||
RTDyldObjectLinkingLayer ObjectLayer;
|
||||
IRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
|
||||
|
||||
using OptimizeFunction =
|
||||
std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>;
|
||||
std::function<std::shared_ptr<Module>(std::shared_ptr<Module>)>;
|
||||
|
||||
IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
|
||||
|
||||
@ -91,7 +91,7 @@ class KaleidoscopeJIT {
|
||||
MyRemote &Remote;
|
||||
|
||||
public:
|
||||
using ModuleHandle = decltype(OptimizeLayer)::ModuleSetHandleT;
|
||||
using ModuleHandle = decltype(OptimizeLayer)::ModuleHandleT;
|
||||
|
||||
KaleidoscopeJIT(MyRemote &Remote)
|
||||
: TM(EngineBuilder().selectTarget(Triple(Remote.getTargetTriple()), "",
|
||||
@ -99,7 +99,7 @@ class KaleidoscopeJIT {
|
||||
DL(TM->createDataLayout()),
|
||||
CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
|
||||
OptimizeLayer(CompileLayer,
|
||||
[this](std::unique_ptr<Module> M) {
|
||||
[this](std::shared_ptr<Module> M) {
|
||||
return optimizeModule(std::move(M));
|
||||
}),
|
||||
Remote(Remote) {
|
||||
@ -153,15 +153,11 @@ class KaleidoscopeJIT {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Build a singleton module set to hold our module.
|
||||
std::vector<std::unique_ptr<Module>> Ms;
|
||||
Ms.push_back(std::move(M));
|
||||
|
||||
// Add the set to the JIT with the resolver we created above and a newly
|
||||
// created SectionMemoryManager.
|
||||
return OptimizeLayer.addModuleSet(std::move(Ms),
|
||||
std::move(MemMgr),
|
||||
std::move(Resolver));
|
||||
return OptimizeLayer.addModule(std::move(M),
|
||||
std::move(MemMgr),
|
||||
std::move(Resolver));
|
||||
}
|
||||
|
||||
Error addFunctionAST(std::unique_ptr<FunctionAST> FnAST) {
|
||||
@ -231,7 +227,7 @@ class KaleidoscopeJIT {
|
||||
}
|
||||
|
||||
void removeModule(ModuleHandle H) {
|
||||
OptimizeLayer.removeModuleSet(H);
|
||||
OptimizeLayer.removeModule(H);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -242,7 +238,7 @@ class KaleidoscopeJIT {
|
||||
return MangledNameStream.str();
|
||||
}
|
||||
|
||||
std::unique_ptr<Module> optimizeModule(std::unique_ptr<Module> M) {
|
||||
std::shared_ptr<Module> optimizeModule(std::shared_ptr<Module> M) {
|
||||
// Create a function pass manager.
|
||||
auto FPM = llvm::make_unique<legacy::FunctionPassManager>(M.get());
|
||||
|
||||
|
@ -39,9 +39,9 @@ namespace orc {
|
||||
|
||||
class KaleidoscopeJIT {
|
||||
public:
|
||||
using ObjLayerT = RTDyldObjectLinkingLayer<>;
|
||||
using CompileLayerT = IRCompileLayer<ObjLayerT>;
|
||||
using ModuleHandleT = CompileLayerT::ModuleSetHandleT;
|
||||
using ObjLayerT = RTDyldObjectLinkingLayer;
|
||||
using CompileLayerT = IRCompileLayer<ObjLayerT, SimpleCompiler>;
|
||||
using ModuleHandleT = CompileLayerT::ModuleHandleT;
|
||||
|
||||
KaleidoscopeJIT()
|
||||
: TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
|
||||
@ -62,9 +62,9 @@ class KaleidoscopeJIT {
|
||||
return JITSymbol(nullptr);
|
||||
},
|
||||
[](const std::string &S) { return nullptr; });
|
||||
auto H = CompileLayer.addModuleSet(singletonSet(std::move(M)),
|
||||
make_unique<SectionMemoryManager>(),
|
||||
std::move(Resolver));
|
||||
auto H = CompileLayer.addModule(std::move(M),
|
||||
make_unique<SectionMemoryManager>(),
|
||||
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.removeModuleSet(H);
|
||||
CompileLayer.removeModule(H);
|
||||
}
|
||||
|
||||
JITSymbol findSymbol(const std::string Name) {
|
||||
@ -89,12 +89,6 @@ class KaleidoscopeJIT {
|
||||
return MangledName;
|
||||
}
|
||||
|
||||
template <typename T> static std::vector<T> singletonSet(T t) {
|
||||
std::vector<T> Vec;
|
||||
Vec.push_back(std::move(t));
|
||||
return Vec;
|
||||
}
|
||||
|
||||
JITSymbol findMangledSymbol(const std::string &Name) {
|
||||
#ifdef LLVM_ON_WIN32
|
||||
// The symbol lookup of ObjectLinkingLayer uses the SymbolRef::SF_Exported
|
||||
|
@ -29,6 +29,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct LLVMOpaqueSharedModule *LLVMSharedModuleRef;
|
||||
typedef struct LLVMOpaqueSharedObjectBuffer *LLVMSharedObjectBufferRef;
|
||||
typedef struct LLVMOrcOpaqueJITStack *LLVMOrcJITStackRef;
|
||||
typedef uint32_t LLVMOrcModuleHandle;
|
||||
typedef uint64_t LLVMOrcTargetAddress;
|
||||
@ -38,6 +40,45 @@ typedef uint64_t (*LLVMOrcLazyCompileCallbackFn)(LLVMOrcJITStackRef JITStack,
|
||||
|
||||
typedef enum { LLVMOrcErrSuccess = 0, LLVMOrcErrGeneric } LLVMOrcErrorCode;
|
||||
|
||||
/**
|
||||
* Turn an LLVMModuleRef into an LLVMSharedModuleRef.
|
||||
*
|
||||
* The JIT uses shared ownership for LLVM modules, since it is generally
|
||||
* difficult to know when the JIT will be finished with a module (and the JIT
|
||||
* has no way of knowing when a user may be finished with one).
|
||||
*
|
||||
* Calling this method with an LLVMModuleRef creates a shared-pointer to the
|
||||
* module, and returns a reference to this shared pointer.
|
||||
*
|
||||
* The shared module should be disposed when finished with by calling
|
||||
* LLVMOrcDisposeSharedModule (not LLVMDisposeModule). The Module will be
|
||||
* deleted when the last shared pointer owner relinquishes it.
|
||||
*/
|
||||
|
||||
LLVMSharedModuleRef LLVMOrcMakeSharedModule(LLVMModuleRef Mod);
|
||||
|
||||
/**
|
||||
* Dispose of a shared module.
|
||||
*
|
||||
* The module should not be accessed after this call. The module will be
|
||||
* deleted once all clients (including the JIT itself) have released their
|
||||
* shared pointers.
|
||||
*/
|
||||
|
||||
void LLVMOrcDisposeSharedModuleRef(LLVMSharedModuleRef SharedMod);
|
||||
|
||||
/**
|
||||
* Get an LLVMSharedObjectBufferRef from an LLVMMemoryBufferRef.
|
||||
*/
|
||||
LLVMSharedObjectBufferRef
|
||||
LLVMOrcMakeSharedObjectBuffer(LLVMMemoryBufferRef ObjBuffer);
|
||||
|
||||
/**
|
||||
* Dispose of a shared object buffer.
|
||||
*/
|
||||
void
|
||||
LLVMOrcDisposeSharedObjectBufferRef(LLVMSharedObjectBufferRef SharedObjBuffer);
|
||||
|
||||
/**
|
||||
* Create an ORC JIT stack.
|
||||
*
|
||||
@ -95,7 +136,8 @@ LLVMOrcErrorCode LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack,
|
||||
* Add module to be eagerly compiled.
|
||||
*/
|
||||
LLVMOrcModuleHandle
|
||||
LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack, LLVMModuleRef Mod,
|
||||
LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack,
|
||||
LLVMSharedModuleRef Mod,
|
||||
LLVMOrcSymbolResolverFn SymbolResolver,
|
||||
void *SymbolResolverCtx);
|
||||
|
||||
@ -103,7 +145,8 @@ LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack, LLVMModuleRef Mod,
|
||||
* Add module to be lazily compiled one function at a time.
|
||||
*/
|
||||
LLVMOrcModuleHandle
|
||||
LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack, LLVMModuleRef Mod,
|
||||
LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack,
|
||||
LLVMSharedModuleRef Mod,
|
||||
LLVMOrcSymbolResolverFn SymbolResolver,
|
||||
void *SymbolResolverCtx);
|
||||
|
||||
@ -111,7 +154,7 @@ LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack, LLVMModuleRef Mod,
|
||||
* Add an object file.
|
||||
*/
|
||||
LLVMOrcModuleHandle LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack,
|
||||
LLVMObjectFileRef Obj,
|
||||
LLVMSharedObjectBufferRef Obj,
|
||||
LLVMOrcSymbolResolverFn SymbolResolver,
|
||||
void *SymbolResolverCtx);
|
||||
|
||||
|
@ -140,8 +140,8 @@ enum lostFraction { // Example of truncated bits:
|
||||
// implementation classes. This struct should not define any non-static data
|
||||
// members.
|
||||
struct APFloatBase {
|
||||
// TODO remove this and use APInt typedef directly.
|
||||
typedef APInt::WordType integerPart;
|
||||
static const unsigned integerPartWidth = APInt::APINT_BITS_PER_WORD;
|
||||
|
||||
/// A signed type to represent a floating point numbers unbiased exponent.
|
||||
typedef signed short ExponentType;
|
||||
|
@ -213,6 +213,12 @@ class LLVM_NODISCARD APInt {
|
||||
/// out-of-line slow case for countLeadingZeros
|
||||
unsigned countLeadingZerosSlowCase() const LLVM_READONLY;
|
||||
|
||||
/// out-of-line slow case for countLeadingOnes.
|
||||
unsigned countLeadingOnesSlowCase() const LLVM_READONLY;
|
||||
|
||||
/// out-of-line slow case for countTrailingZeros.
|
||||
unsigned countTrailingZerosSlowCase() const LLVM_READONLY;
|
||||
|
||||
/// out-of-line slow case for countTrailingOnes
|
||||
unsigned countTrailingOnesSlowCase() const LLVM_READONLY;
|
||||
|
||||
@ -383,7 +389,7 @@ class LLVM_NODISCARD APInt {
|
||||
bool isAllOnesValue() const {
|
||||
if (isSingleWord())
|
||||
return U.VAL == WORD_MAX >> (APINT_BITS_PER_WORD - BitWidth);
|
||||
return countPopulationSlowCase() == BitWidth;
|
||||
return countTrailingOnesSlowCase() == BitWidth;
|
||||
}
|
||||
|
||||
/// \brief Determine if all bits are clear
|
||||
@ -408,7 +414,9 @@ class LLVM_NODISCARD APInt {
|
||||
/// This checks to see if the value of this APInt is the maximum signed
|
||||
/// value for the APInt's bit width.
|
||||
bool isMaxSignedValue() const {
|
||||
return !isNegative() && countPopulation() == BitWidth - 1;
|
||||
if (isSingleWord())
|
||||
return U.VAL == ((WordType(1) << (BitWidth - 1)) - 1);
|
||||
return !isNegative() && countTrailingOnesSlowCase() == BitWidth - 1;
|
||||
}
|
||||
|
||||
/// \brief Determine if this is the smallest unsigned value.
|
||||
@ -422,7 +430,9 @@ class LLVM_NODISCARD APInt {
|
||||
/// This checks to see if the value of this APInt is the minimum signed
|
||||
/// value for the APInt's bit width.
|
||||
bool isMinSignedValue() const {
|
||||
return isNegative() && isPowerOf2();
|
||||
if (isSingleWord())
|
||||
return U.VAL == (WordType(1) << (BitWidth - 1));
|
||||
return isNegative() && countTrailingZerosSlowCase() == BitWidth - 1;
|
||||
}
|
||||
|
||||
/// \brief Check if this APInt has an N-bits unsigned integer value.
|
||||
@ -1574,7 +1584,11 @@ class LLVM_NODISCARD APInt {
|
||||
///
|
||||
/// \returns 0 if the high order bit is not set, otherwise returns the number
|
||||
/// of 1 bits from the most significant to the least
|
||||
unsigned countLeadingOnes() const LLVM_READONLY;
|
||||
unsigned countLeadingOnes() const {
|
||||
if (isSingleWord())
|
||||
return llvm::countLeadingOnes(U.VAL << (APINT_BITS_PER_WORD - BitWidth));
|
||||
return countLeadingOnesSlowCase();
|
||||
}
|
||||
|
||||
/// Computes the number of leading bits of this APInt that are equal to its
|
||||
/// sign bit.
|
||||
@ -1590,7 +1604,11 @@ class LLVM_NODISCARD APInt {
|
||||
///
|
||||
/// \returns BitWidth if the value is zero, otherwise returns the number of
|
||||
/// zeros from the least significant bit to the first one bit.
|
||||
unsigned countTrailingZeros() const LLVM_READONLY;
|
||||
unsigned countTrailingZeros() const {
|
||||
if (isSingleWord())
|
||||
return std::min(unsigned(llvm::countTrailingZeros(U.VAL)), BitWidth);
|
||||
return countTrailingZerosSlowCase();
|
||||
}
|
||||
|
||||
/// \brief Count the number of trailing one bits.
|
||||
///
|
||||
|
@ -15,10 +15,12 @@
|
||||
#define LLVM_ADT_STRINGEXTRAS_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
@ -129,6 +131,32 @@ template <typename N> bool to_integer(StringRef S, N &Num, unsigned Base = 0) {
|
||||
return !S.getAsInteger(Base, Num);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <typename N>
|
||||
inline bool to_float(const Twine &T, N &Num, N (*StrTo)(const char *, char **)) {
|
||||
SmallString<32> Storage;
|
||||
StringRef S = T.toNullTerminatedStringRef(Storage);
|
||||
char *End;
|
||||
N Temp = StrTo(S.data(), &End);
|
||||
if (*End != '\0')
|
||||
return false;
|
||||
Num = Temp;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool to_float(const Twine &T, float &Num) {
|
||||
return detail::to_float(T, Num, strtof);
|
||||
}
|
||||
|
||||
inline bool to_float(const Twine &T, double &Num) {
|
||||
return detail::to_float(T, Num, strtod);
|
||||
}
|
||||
|
||||
inline bool to_float(const Twine &T, long double &Num) {
|
||||
return detail::to_float(T, Num, strtold);
|
||||
}
|
||||
|
||||
static inline std::string utostr(uint64_t X, bool isNeg = false) {
|
||||
char Buffer[21];
|
||||
char *BufPtr = std::end(Buffer);
|
||||
|
@ -147,6 +147,7 @@ class Triple {
|
||||
enum OSType {
|
||||
UnknownOS,
|
||||
|
||||
Ananas,
|
||||
CloudABI,
|
||||
Darwin,
|
||||
DragonFly,
|
||||
|
@ -93,6 +93,13 @@ class LazyValueInfo {
|
||||
Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB,
|
||||
Instruction *CxtI = nullptr);
|
||||
|
||||
/// Return the ConstantRage constraint that is known to hold for the
|
||||
/// specified value on the specified edge. This may be only be called
|
||||
/// on integer-typed Values.
|
||||
ConstantRange getConstantRangeOnEdge(Value *V, BasicBlock *FromBB,
|
||||
BasicBlock *ToBB,
|
||||
Instruction *CxtI = nullptr);
|
||||
|
||||
/// Inform the analysis cache that we have threaded an edge from
|
||||
/// PredBB to OldSucc to be from PredBB to NewSucc instead.
|
||||
void threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, BasicBlock *NewSucc);
|
||||
|
@ -39,6 +39,15 @@ bool isDereferenceableAndAlignedPointer(const Value *V, unsigned Align,
|
||||
const Instruction *CtxI = nullptr,
|
||||
const DominatorTree *DT = nullptr);
|
||||
|
||||
/// Returns true if V is always dereferenceable for Size byte with alignment
|
||||
/// greater or equal than requested. If the context instruction is specified
|
||||
/// performs context-sensitive analysis and returns true if the pointer is
|
||||
/// dereferenceable at the specified instruction.
|
||||
bool isDereferenceableAndAlignedPointer(const Value *V, unsigned Align,
|
||||
const APInt &Size, const DataLayout &DL,
|
||||
const Instruction *CtxI = nullptr,
|
||||
const DominatorTree *DT = nullptr);
|
||||
|
||||
/// Return true if we know that executing a load from this value cannot trap.
|
||||
///
|
||||
/// If DT and ScanFrom are specified this method performs context-sensitive
|
||||
|
@ -91,8 +91,9 @@ getExitEdges(SmallVectorImpl<Edge> &ExitEdges) const {
|
||||
|
||||
/// getLoopPreheader - If there is a preheader for this loop, return it. A
|
||||
/// loop has a preheader if there is only one edge to the header of the loop
|
||||
/// from outside of the loop. If this is the case, the block branching to the
|
||||
/// header of the loop is the preheader node.
|
||||
/// from outside of the loop and it is legal to hoist instructions into the
|
||||
/// predecessor. If this is the case, the block branching to the header of the
|
||||
/// loop is the preheader node.
|
||||
///
|
||||
/// This method returns null if there is no preheader for the loop.
|
||||
///
|
||||
@ -102,6 +103,10 @@ BlockT *LoopBase<BlockT, LoopT>::getLoopPreheader() const {
|
||||
BlockT *Out = getLoopPredecessor();
|
||||
if (!Out) return nullptr;
|
||||
|
||||
// Make sure we are allowed to hoist instructions into the predecessor.
|
||||
if (!Out->isLegalToHoistInto())
|
||||
return nullptr;
|
||||
|
||||
// Make sure there is only one exit out of the preheader.
|
||||
typedef GraphTraits<BlockT*> BlockTraits;
|
||||
typename BlockTraits::ChildIteratorType SI = BlockTraits::child_begin(Out);
|
||||
|
@ -784,7 +784,9 @@ class ScalarEvolution {
|
||||
}
|
||||
|
||||
/// Determine the range for a particular SCEV.
|
||||
ConstantRange getRange(const SCEV *S, RangeSignHint Hint);
|
||||
/// NOTE: This returns a reference to an entry in a cache. It must be
|
||||
/// copied if its needed for longer.
|
||||
const ConstantRange &getRangeRef(const SCEV *S, RangeSignHint Hint);
|
||||
|
||||
/// Determines the range for the affine SCEVAddRecExpr {\p Start,+,\p Stop}.
|
||||
/// Helper for \c getRange.
|
||||
@ -1464,15 +1466,35 @@ class ScalarEvolution {
|
||||
uint32_t GetMinTrailingZeros(const SCEV *S);
|
||||
|
||||
/// Determine the unsigned range for a particular SCEV.
|
||||
///
|
||||
/// NOTE: This returns a copy of the reference returned by getRangeRef.
|
||||
ConstantRange getUnsignedRange(const SCEV *S) {
|
||||
return getRange(S, HINT_RANGE_UNSIGNED);
|
||||
return getRangeRef(S, HINT_RANGE_UNSIGNED);
|
||||
}
|
||||
|
||||
/// Determine the min of the unsigned range for a particular SCEV.
|
||||
APInt getUnsignedRangeMin(const SCEV *S) {
|
||||
return getRangeRef(S, HINT_RANGE_UNSIGNED).getUnsignedMin();
|
||||
}
|
||||
|
||||
/// Determine the max of the unsigned range for a particular SCEV.
|
||||
APInt getUnsignedRangeMax(const SCEV *S) {
|
||||
return getRangeRef(S, HINT_RANGE_UNSIGNED).getUnsignedMax();
|
||||
}
|
||||
|
||||
/// Determine the signed range for a particular SCEV.
|
||||
///
|
||||
/// NOTE: This returns a copy of the reference returned by getRangeRef.
|
||||
ConstantRange getSignedRange(const SCEV *S) {
|
||||
return getRange(S, HINT_RANGE_SIGNED);
|
||||
return getRangeRef(S, HINT_RANGE_SIGNED);
|
||||
}
|
||||
|
||||
/// Determine the min of the signed range for a particular SCEV.
|
||||
APInt getSignedRangeMin(const SCEV *S) {
|
||||
return getRangeRef(S, HINT_RANGE_SIGNED).getSignedMin();
|
||||
}
|
||||
|
||||
/// Determine the max of the signed range for a particular SCEV.
|
||||
APInt getSignedRangeMax(const SCEV *S) {
|
||||
return getRangeRef(S, HINT_RANGE_SIGNED).getSignedMax();
|
||||
}
|
||||
|
||||
/// Test if the given expression is known to be negative.
|
||||
|
@ -46,6 +46,12 @@ static const char ClGlObjMagic[] = {
|
||||
'\xac', '\x9b', '\xd6', '\xb6', '\x22', '\x26', '\x53', '\xc2',
|
||||
};
|
||||
|
||||
// The signature bytes that start a .res file.
|
||||
static const char WinResMagic[] = {
|
||||
'\x00', '\x00', '\x00', '\x00', '\x20', '\x00', '\x00', '\x00',
|
||||
'\xff', '\xff', '\x00', '\x00', '\xff', '\xff', '\x00', '\x00',
|
||||
};
|
||||
|
||||
// Sizes in bytes of various things in the COFF format.
|
||||
enum {
|
||||
Header16Size = 20,
|
||||
|
@ -484,7 +484,7 @@ struct PubIndexEntryDescriptor {
|
||||
};
|
||||
|
||||
/// Constants that define the DWARF format as 32 or 64 bit.
|
||||
enum DwarfFormat { DWARF32, DWARF64 };
|
||||
enum DwarfFormat : uint8_t { DWARF32, DWARF64 };
|
||||
|
||||
} // End of namespace dwarf
|
||||
|
||||
|
@ -78,7 +78,8 @@ enum {
|
||||
MH_DEAD_STRIPPABLE_DYLIB = 0x00400000u,
|
||||
MH_HAS_TLV_DESCRIPTORS = 0x00800000u,
|
||||
MH_NO_HEAP_EXECUTION = 0x01000000u,
|
||||
MH_APP_EXTENSION_SAFE = 0x02000000u
|
||||
MH_APP_EXTENSION_SAFE = 0x02000000u,
|
||||
MH_NLIST_OUTOFSYNC_WITH_DYLDINFO = 0x04000000u
|
||||
};
|
||||
|
||||
enum : uint32_t {
|
||||
|
@ -176,6 +176,11 @@ enum class ValType {
|
||||
// Linking metadata kinds.
|
||||
enum : unsigned {
|
||||
WASM_STACK_POINTER = 0x1,
|
||||
WASM_SYMBOL_INFO = 0x2,
|
||||
};
|
||||
|
||||
enum : unsigned {
|
||||
WASM_SYMBOL_FLAG_WEAK = 0x1,
|
||||
};
|
||||
|
||||
#define WASM_RELOC(name, value) name = value,
|
||||
|
@ -121,8 +121,8 @@ class DIEAbbrev : public FoldingSetNode {
|
||||
/// Print the abbreviation using the specified asm printer.
|
||||
void Emit(const AsmPrinter *AP) const;
|
||||
|
||||
void print(raw_ostream &O);
|
||||
void dump();
|
||||
void print(raw_ostream &O) const;
|
||||
void dump() const;
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
@ -780,7 +780,7 @@ class DIE : IntrusiveBackListNode, public DIEValueList {
|
||||
DIEValue findAttribute(dwarf::Attribute Attribute) const;
|
||||
|
||||
void print(raw_ostream &O, unsigned IndentCount = 0) const;
|
||||
void dump();
|
||||
void dump() const;
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
@ -29,6 +29,7 @@ class MachineOperand;
|
||||
class MachineRegisterInfo;
|
||||
class RegisterBankInfo;
|
||||
class TargetInstrInfo;
|
||||
class TargetRegisterClass;
|
||||
class TargetRegisterInfo;
|
||||
|
||||
/// Container class for CodeGen predicate results.
|
||||
@ -79,6 +80,16 @@ class InstructionSelector {
|
||||
|
||||
InstructionSelector();
|
||||
|
||||
/// 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.
|
||||
/// \returns whether operand regclass constraining succeeded.
|
||||
bool constrainOperandRegToRegClass(MachineInstr &I, unsigned OpIdx,
|
||||
const TargetRegisterClass &RC,
|
||||
const TargetInstrInfo &TII,
|
||||
const TargetRegisterInfo &TRI,
|
||||
const RegisterBankInfo &RBI) const;
|
||||
|
||||
/// Mutate the newly-selected instruction \p I to constrain its (possibly
|
||||
/// generic) virtual register operands to the instruction's register class.
|
||||
/// This could involve inserting COPYs before (for uses) or after (for defs).
|
||||
|
@ -59,7 +59,7 @@ class Legalizer : public MachineFunctionPass {
|
||||
const TargetInstrInfo &TII);
|
||||
|
||||
bool combineMerges(MachineInstr &MI, MachineRegisterInfo &MRI,
|
||||
const TargetInstrInfo &TII);
|
||||
const TargetInstrInfo &TII, MachineIRBuilder &MIRBuilder);
|
||||
|
||||
bool runOnMachineFunction(MachineFunction &MF) override;
|
||||
};
|
||||
|
@ -471,10 +471,12 @@ class MachineIRBuilder {
|
||||
/// Build and insert \p Res = IMPLICIT_DEF.
|
||||
MachineInstrBuilder buildUndef(unsigned Dst);
|
||||
|
||||
/// Build and insert \p Res<def> = G_SEQUENCE \p Op0, \p Idx0...
|
||||
/// Build and insert instructions to put \p Ops together at the specified p
|
||||
/// Indices to form a larger register.
|
||||
///
|
||||
/// G_SEQUENCE inserts each element of Ops into an IMPLICIT_DEF register,
|
||||
/// where each entry starts at the bit-index specified by \p Indices.
|
||||
/// If the types of the input registers are uniform and cover the entirity of
|
||||
/// \p Res then a G_MERGE_VALUES will be produced. Otherwise an IMPLICIT_DEF
|
||||
/// followed by a sequence of G_INSERT instructions.
|
||||
///
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
/// \pre The final element of the sequence must not extend past the end of the
|
||||
@ -482,11 +484,8 @@ class MachineIRBuilder {
|
||||
/// \pre The bits defined by each Op (derived from index and scalar size) must
|
||||
/// not overlap.
|
||||
/// \pre \p Indices must be in ascending order of bit position.
|
||||
///
|
||||
/// \return a MachineInstrBuilder for the newly created instruction.
|
||||
MachineInstrBuilder buildSequence(unsigned Res,
|
||||
ArrayRef<unsigned> Ops,
|
||||
ArrayRef<uint64_t> Indices);
|
||||
void buildSequence(unsigned Res, ArrayRef<unsigned> Ops,
|
||||
ArrayRef<uint64_t> Indices);
|
||||
|
||||
/// Build and insert \p Res<def> = G_MERGE_VALUES \p Op0, ...
|
||||
///
|
||||
@ -513,24 +512,6 @@ class MachineIRBuilder {
|
||||
/// \return a MachineInstrBuilder for the newly created instruction.
|
||||
MachineInstrBuilder buildUnmerge(ArrayRef<unsigned> Res, unsigned Op);
|
||||
|
||||
void addUsesWithIndices(MachineInstrBuilder MIB) {}
|
||||
|
||||
template <typename... ArgTys>
|
||||
void addUsesWithIndices(MachineInstrBuilder MIB, unsigned Reg,
|
||||
unsigned BitIndex, ArgTys... Args) {
|
||||
MIB.addUse(Reg).addImm(BitIndex);
|
||||
addUsesWithIndices(MIB, Args...);
|
||||
}
|
||||
|
||||
template <typename... ArgTys>
|
||||
MachineInstrBuilder buildSequence(unsigned Res, unsigned Op,
|
||||
unsigned Index, ArgTys... Args) {
|
||||
MachineInstrBuilder MIB =
|
||||
buildInstr(TargetOpcode::G_SEQUENCE).addDef(Res);
|
||||
addUsesWithIndices(MIB, Op, Index, Args...);
|
||||
return MIB;
|
||||
}
|
||||
|
||||
MachineInstrBuilder buildInsert(unsigned Res, unsigned Src,
|
||||
unsigned Op, unsigned Index);
|
||||
|
||||
|
@ -29,13 +29,26 @@ class RegisterBankInfo;
|
||||
class TargetInstrInfo;
|
||||
class TargetPassConfig;
|
||||
class TargetRegisterInfo;
|
||||
class TargetRegisterClass;
|
||||
class Twine;
|
||||
class ConstantFP;
|
||||
|
||||
/// Try to constrain Reg to the specified register class. If this fails,
|
||||
/// create a new virtual register in the correct class and insert a COPY before
|
||||
/// \p InsertPt. The debug location of \p InsertPt is used for the new copy.
|
||||
///
|
||||
/// \return The virtual register constrained to the right register class.
|
||||
unsigned constrainRegToClass(MachineRegisterInfo &MRI,
|
||||
const TargetInstrInfo &TII,
|
||||
const RegisterBankInfo &RBI,
|
||||
MachineInstr &InsertPt, unsigned Reg,
|
||||
const TargetRegisterClass &RegClass);
|
||||
|
||||
/// Try to constrain Reg so that it is usable by argument OpIdx of the
|
||||
/// provided MCInstrDesc \p II. If this fails, create a new virtual
|
||||
/// register in the correct class and insert a COPY before \p InsertPt.
|
||||
/// The debug location of \p InsertPt is used for the new copy.
|
||||
/// This is equivalent to constrainRegToClass() with RegClass obtained from the
|
||||
/// MCInstrDesc. The debug location of \p InsertPt is used for the new copy.
|
||||
///
|
||||
/// \return The virtual register constrained to the right register class.
|
||||
unsigned constrainOperandRegClass(const MachineFunction &MF,
|
||||
|
@ -196,7 +196,7 @@ class LexicalScopes {
|
||||
}
|
||||
|
||||
/// dump - Print data structures to dbgs().
|
||||
void dump();
|
||||
void dump() const;
|
||||
|
||||
/// getOrCreateAbstractScope - Find or create an abstract lexical scope.
|
||||
LexicalScope *getOrCreateAbstractScope(const DILocalScope *Scope);
|
||||
|
@ -376,6 +376,9 @@ class MachineBasicBlock
|
||||
/// Indicates if this is the entry block of a cleanup funclet.
|
||||
void setIsCleanupFuncletEntry(bool V = true) { IsCleanupFuncletEntry = V; }
|
||||
|
||||
/// Returns true if it is legal to hoist instructions into this block.
|
||||
bool isLegalToHoistInto() const;
|
||||
|
||||
// Code Layout methods.
|
||||
|
||||
/// Move 'this' block before or after the specified block. This only moves
|
||||
|
@ -59,6 +59,11 @@ struct MachinePointerInfo {
|
||||
return MachinePointerInfo(V.get<const PseudoSourceValue*>(), Offset+O);
|
||||
}
|
||||
|
||||
/// Return true if memory region [V, V+Offset+Size) is known to be
|
||||
/// dereferenceable.
|
||||
bool isDereferenceable(unsigned Size, LLVMContext &C,
|
||||
const DataLayout &DL) const;
|
||||
|
||||
/// Return the LLVM IR address space number that this pointer points into.
|
||||
unsigned getAddrSpace() const;
|
||||
|
||||
|
@ -77,33 +77,6 @@ class MachineModuleInfoELF : public MachineModuleInfoImpl {
|
||||
SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); }
|
||||
};
|
||||
|
||||
/// MachineModuleInfoWasm - This is a MachineModuleInfoImpl implementation
|
||||
/// for Wasm targets.
|
||||
class MachineModuleInfoWasm : public MachineModuleInfoImpl {
|
||||
/// WebAssembly global variables defined by CodeGen.
|
||||
std::vector<wasm::Global> Globals;
|
||||
|
||||
/// The WebAssembly global variable which is the stack pointer.
|
||||
unsigned StackPointerGlobal;
|
||||
|
||||
virtual void anchor(); // Out of line virtual method.
|
||||
public:
|
||||
MachineModuleInfoWasm(const MachineModuleInfo &)
|
||||
: StackPointerGlobal(-1U) {}
|
||||
|
||||
void addGlobal(const wasm::Global &G) { Globals.push_back(G); }
|
||||
const std::vector<wasm::Global> &getGlobals() const { return Globals; }
|
||||
|
||||
bool hasStackPointerGlobal() const {
|
||||
return StackPointerGlobal != -1U;
|
||||
}
|
||||
unsigned getStackPointerGlobal() const {
|
||||
assert(hasStackPointerGlobal() && "Stack ptr global hasn't been set");
|
||||
return StackPointerGlobal;
|
||||
}
|
||||
void setStackPointerGlobal(unsigned Global) { StackPointerGlobal = Global; }
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
@ -203,7 +203,7 @@ class MachineSchedStrategy {
|
||||
MachineBasicBlock::iterator End,
|
||||
unsigned NumRegionInstrs) {}
|
||||
|
||||
virtual void dumpPolicy() {}
|
||||
virtual void dumpPolicy() const {}
|
||||
|
||||
/// Check if pressure tracking is needed before building the DAG and
|
||||
/// initializing this strategy. Called after initPolicy.
|
||||
@ -555,7 +555,7 @@ class ReadyQueue {
|
||||
return Queue.begin() + idx;
|
||||
}
|
||||
|
||||
void dump();
|
||||
void dump() const;
|
||||
};
|
||||
|
||||
/// Summarize the unscheduled region.
|
||||
@ -756,7 +756,7 @@ class SchedBoundary {
|
||||
SUnit *pickOnlyChoice();
|
||||
|
||||
#ifndef NDEBUG
|
||||
void dumpScheduledState();
|
||||
void dumpScheduledState() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -890,7 +890,7 @@ class GenericScheduler : public GenericSchedulerBase {
|
||||
MachineBasicBlock::iterator End,
|
||||
unsigned NumRegionInstrs) override;
|
||||
|
||||
void dumpPolicy() override;
|
||||
void dumpPolicy() const override;
|
||||
|
||||
bool shouldTrackPressure() const override {
|
||||
return RegionPolicy.ShouldTrackPressure;
|
||||
|
41
include/llvm/CodeGen/MacroFusion.h
Normal file
41
include/llvm/CodeGen/MacroFusion.h
Normal file
@ -0,0 +1,41 @@
|
||||
//===- MacroFusion.h - Macro Fusion ------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
/// \file This file contains the definition of the DAG scheduling mutation to
|
||||
/// pair instructions back to back.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <functional>
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/CodeGen/MachineScheduler.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// \brief Check if the instr pair, FirstMI and SecondMI, should be fused
|
||||
/// together. Given SecondMI, when FirstMI is unspecified, then check if
|
||||
/// SecondMI may be part of a fused pair at all.
|
||||
typedef std::function<bool(const TargetInstrInfo &TII,
|
||||
const TargetSubtargetInfo &TSI,
|
||||
const MachineInstr *FirstMI,
|
||||
const MachineInstr &SecondMI)> ShouldSchedulePredTy;
|
||||
|
||||
/// \brief Create a DAG scheduling mutation to pair instructions back to back
|
||||
/// for instructions that benefit according to the target-specific
|
||||
/// shouldScheduleAdjacent predicate function.
|
||||
std::unique_ptr<ScheduleDAGMutation>
|
||||
createMacroFusionDAGMutation(ShouldSchedulePredTy shouldScheduleAdjacent);
|
||||
|
||||
/// \brief Create a DAG scheduling mutation to pair branch instructions with one
|
||||
/// of their predecessors back to back for instructions that benefit according
|
||||
/// to the target-specific shouldScheduleAdjacent predicate function.
|
||||
std::unique_ptr<ScheduleDAGMutation>
|
||||
createBranchMacroFusionDAGMutation(ShouldSchedulePredTy shouldScheduleAdjacent);
|
||||
|
||||
} // end namespace llvm
|
@ -156,12 +156,24 @@ class RegScavenger {
|
||||
/// available and do the appropriate bookkeeping. SPAdj is the stack
|
||||
/// adjustment due to call frame, it's passed along to eliminateFrameIndex().
|
||||
/// Returns the scavenged register.
|
||||
/// This is deprecated as it depends on the quality of the kill flags being
|
||||
/// present; Use scavengeRegisterBackwards() instead!
|
||||
unsigned scavengeRegister(const TargetRegisterClass *RegClass,
|
||||
MachineBasicBlock::iterator I, int SPAdj);
|
||||
unsigned scavengeRegister(const TargetRegisterClass *RegClass, int SPAdj) {
|
||||
return scavengeRegister(RegClass, MBBI, SPAdj);
|
||||
}
|
||||
|
||||
/// Make a register of the specific register class available from the current
|
||||
/// position backwards to the place before \p To. If \p RestoreAfter is true
|
||||
/// this includes the instruction following the current position.
|
||||
/// SPAdj is the stack adjustment due to call frame, it's passed along to
|
||||
/// eliminateFrameIndex().
|
||||
/// Returns the scavenged register.
|
||||
unsigned scavengeRegisterBackwards(const TargetRegisterClass &RC,
|
||||
MachineBasicBlock::iterator To,
|
||||
bool RestoreAfter, int SPAdj);
|
||||
|
||||
/// Tell the scavenger a register is used.
|
||||
void setRegUsed(unsigned Reg, LaneBitmask LaneMask = LaneBitmask::getAll());
|
||||
|
||||
@ -202,6 +214,12 @@ class RegScavenger {
|
||||
|
||||
/// Mark live-in registers of basic block as used.
|
||||
void setLiveInsUsed(const MachineBasicBlock &MBB);
|
||||
|
||||
/// Spill a register after position \p After and reload it before position
|
||||
/// \p UseMI.
|
||||
ScavengedInfo &spill(unsigned Reg, const TargetRegisterClass &RC, int SPAdj,
|
||||
MachineBasicBlock::iterator After,
|
||||
MachineBasicBlock::iterator &UseMI);
|
||||
};
|
||||
|
||||
/// Replaces all frame index virtual registers with physical registers. Uses the
|
||||
|
64
include/llvm/CodeGen/SelectionDAGAddressAnalysis.h
Normal file
64
include/llvm/CodeGen/SelectionDAGAddressAnalysis.h
Normal file
@ -0,0 +1,64 @@
|
||||
//===-- llvm/CodeGen/SelectionDAGAddressAnalysis.h ------- DAG Address Analysis
|
||||
//---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
|
||||
#ifndef LLVM_CODEGEN_SELECTIONDAGADDRESSANALYSIS_H
|
||||
#define LLVM_CODEGEN_SELECTIONDAGADDRESSANALYSIS_H
|
||||
|
||||
#include "llvm/CodeGen/ISDOpcodes.h"
|
||||
#include "llvm/CodeGen/SelectionDAG.h"
|
||||
#include "llvm/CodeGen/SelectionDAGNodes.h"
|
||||
|
||||
namespace llvm {
|
||||
/// Helper struct to parse and store a memory address as base + index + offset.
|
||||
/// We ignore sign extensions when it is safe to do so.
|
||||
/// The following two expressions are not equivalent. To differentiate we need
|
||||
/// to store whether there was a sign extension involved in the index
|
||||
/// computation.
|
||||
/// (load (i64 add (i64 copyfromreg %c)
|
||||
/// (i64 signextend (add (i8 load %index)
|
||||
/// (i8 1))))
|
||||
/// vs
|
||||
///
|
||||
/// (load (i64 add (i64 copyfromreg %c)
|
||||
/// (i64 signextend (i32 add (i32 signextend (i8 load %index))
|
||||
/// (i32 1)))))
|
||||
class BaseIndexOffset {
|
||||
private:
|
||||
SDValue Base;
|
||||
SDValue Index;
|
||||
int64_t Offset;
|
||||
bool IsIndexSignExt;
|
||||
|
||||
public:
|
||||
BaseIndexOffset() : Offset(0), IsIndexSignExt(false) {}
|
||||
|
||||
BaseIndexOffset(SDValue Base, SDValue Index, int64_t Offset,
|
||||
bool IsIndexSignExt)
|
||||
: Base(Base), Index(Index), Offset(Offset),
|
||||
IsIndexSignExt(IsIndexSignExt) {}
|
||||
|
||||
SDValue getBase() { return Base; }
|
||||
SDValue getIndex() { return Index; }
|
||||
|
||||
bool equalBaseIndex(BaseIndexOffset &Other, const SelectionDAG &DAG) {
|
||||
int64_t Off;
|
||||
return equalBaseIndex(Other, DAG, Off);
|
||||
}
|
||||
|
||||
bool equalBaseIndex(BaseIndexOffset &Other, const SelectionDAG &DAG,
|
||||
int64_t &Off);
|
||||
|
||||
/// Parses tree in Ptr for base, index, offset addresses.
|
||||
static BaseIndexOffset match(SDValue Ptr);
|
||||
};
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
@ -2107,7 +2107,7 @@ class MaskedGatherScatterSDNode : public MemSDNode {
|
||||
public:
|
||||
friend class SelectionDAG;
|
||||
|
||||
MaskedGatherScatterSDNode(ISD::NodeType NodeTy, unsigned Order,
|
||||
MaskedGatherScatterSDNode(unsigned NodeTy, unsigned Order,
|
||||
const DebugLoc &dl, SDVTList VTs, EVT MemVT,
|
||||
MachineMemOperand *MMO)
|
||||
: MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) {}
|
||||
|
@ -356,6 +356,9 @@
|
||||
/* Define if this is Win32ish platform */
|
||||
#cmakedefine LLVM_ON_WIN32 ${LLVM_ON_WIN32}
|
||||
|
||||
/* Define if overriding target triple is enabled */
|
||||
#cmakedefine LLVM_TARGET_TRIPLE_ENV "${LLVM_TARGET_TRIPLE_ENV}"
|
||||
|
||||
/* Define if we have the Intel JIT API runtime support library */
|
||||
#cmakedefine01 LLVM_USE_INTEL_JITEVENTS
|
||||
|
||||
|
@ -27,9 +27,12 @@ namespace codeview {
|
||||
|
||||
template <typename Kind> class CVRecord {
|
||||
public:
|
||||
CVRecord() = default;
|
||||
CVRecord() : Type(static_cast<Kind>(0)) {}
|
||||
|
||||
CVRecord(Kind K, ArrayRef<uint8_t> Data) : Type(K), RecordData(Data) {}
|
||||
|
||||
bool valid() const { return Type != static_cast<Kind>(0); }
|
||||
|
||||
uint32_t length() const { return RecordData.size(); }
|
||||
Kind kind() const { return Type; }
|
||||
ArrayRef<uint8_t> data() const { return RecordData; }
|
||||
|
@ -402,6 +402,16 @@ enum class LocalSymFlags : uint16_t {
|
||||
};
|
||||
CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(LocalSymFlags)
|
||||
|
||||
/// Corresponds to the CV_PUBSYMFLAGS bitfield.
|
||||
enum class PublicSymFlags : uint32_t {
|
||||
None = 0,
|
||||
Code = 1 << 0,
|
||||
Function = 1 << 1,
|
||||
Managed = 1 << 2,
|
||||
MSIL = 1 << 3,
|
||||
};
|
||||
CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(PublicSymFlags)
|
||||
|
||||
/// Corresponds to the CV_PROCFLAGS bitfield.
|
||||
enum class ProcSymFlags : uint8_t {
|
||||
None = 0,
|
||||
|
@ -51,11 +51,23 @@ class DebugSubsectionRecordBuilder {
|
||||
public:
|
||||
DebugSubsectionRecordBuilder(std::shared_ptr<DebugSubsection> Subsection,
|
||||
CodeViewContainer Container);
|
||||
|
||||
/// Use this to copy existing subsections directly from source to destination.
|
||||
/// For example, line table subsections in an object file only need to be
|
||||
/// relocated before being copied into the PDB.
|
||||
DebugSubsectionRecordBuilder(const DebugSubsectionRecord &Contents,
|
||||
CodeViewContainer Container);
|
||||
|
||||
uint32_t calculateSerializedLength();
|
||||
Error commit(BinaryStreamWriter &Writer) const;
|
||||
|
||||
private:
|
||||
/// The subsection to build. Will be null if Contents is non-empty.
|
||||
std::shared_ptr<DebugSubsection> Subsection;
|
||||
|
||||
/// The bytes of the subsection. Only non-empty if Subsection is null.
|
||||
DebugSubsectionRecord Contents;
|
||||
|
||||
CodeViewContainer Container;
|
||||
};
|
||||
|
||||
|
@ -22,6 +22,7 @@ namespace codeview {
|
||||
ArrayRef<EnumEntry<SymbolKind>> getSymbolTypeNames();
|
||||
ArrayRef<EnumEntry<TypeLeafKind>> getTypeLeafNames();
|
||||
ArrayRef<EnumEntry<uint16_t>> getRegisterNames();
|
||||
ArrayRef<EnumEntry<uint32_t>> getPublicSymFlagNames();
|
||||
ArrayRef<EnumEntry<uint8_t>> getProcSymFlagNames();
|
||||
ArrayRef<EnumEntry<uint16_t>> getLocalFlagNames();
|
||||
ArrayRef<EnumEntry<uint8_t>> getFrameCookieKindNames();
|
||||
|
@ -11,18 +11,15 @@
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/StringSaver.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
|
||||
class TypeDatabase;
|
||||
class TypeVisitorCallbacks;
|
||||
|
||||
/// \brief Provides amortized O(1) random access to a CodeView type stream.
|
||||
/// Normally to access a type from a type stream, you must know its byte
|
||||
/// offset into the type stream, because type records are variable-lengthed.
|
||||
@ -47,6 +44,11 @@ class TypeVisitorCallbacks;
|
||||
/// of O(N/M) and an amortized time of O(1).
|
||||
class LazyRandomTypeCollection : public TypeCollection {
|
||||
typedef FixedStreamArray<TypeIndexOffset> PartialOffsetArray;
|
||||
struct CacheEntry {
|
||||
CVType Type;
|
||||
uint32_t Offset;
|
||||
StringRef Name;
|
||||
};
|
||||
|
||||
public:
|
||||
explicit LazyRandomTypeCollection(uint32_t RecordCountHint);
|
||||
@ -56,8 +58,10 @@ class LazyRandomTypeCollection : public TypeCollection {
|
||||
PartialOffsetArray PartialOffsets);
|
||||
LazyRandomTypeCollection(const CVTypeArray &Types, uint32_t RecordCountHint);
|
||||
|
||||
void reset(ArrayRef<uint8_t> Data);
|
||||
void reset(StringRef Data);
|
||||
void reset(ArrayRef<uint8_t> Data, uint32_t RecordCountHint);
|
||||
void reset(StringRef Data, uint32_t RecordCountHint);
|
||||
|
||||
uint32_t getOffsetOfType(TypeIndex Index);
|
||||
|
||||
CVType getType(TypeIndex Index) override;
|
||||
StringRef getTypeName(TypeIndex Index) override;
|
||||
@ -68,27 +72,26 @@ class LazyRandomTypeCollection : public TypeCollection {
|
||||
Optional<TypeIndex> getNext(TypeIndex Prev) override;
|
||||
|
||||
private:
|
||||
const TypeDatabase &database() const { return Database; }
|
||||
Error ensureTypeExists(TypeIndex Index);
|
||||
void ensureCapacityFor(TypeIndex Index);
|
||||
|
||||
Error visitRangeForType(TypeIndex TI);
|
||||
Error fullScanForType(TypeIndex TI);
|
||||
Error visitRange(TypeIndex Begin, uint32_t BeginOffset, TypeIndex End);
|
||||
Error visitOneRecord(TypeIndex TI, uint32_t Offset, CVType &Record);
|
||||
void visitRange(TypeIndex Begin, uint32_t BeginOffset, TypeIndex End);
|
||||
|
||||
/// Visited records get automatically added to the type database.
|
||||
TypeDatabase Database;
|
||||
/// Number of actual records.
|
||||
uint32_t Count = 0;
|
||||
|
||||
/// The largest type index which we've visited.
|
||||
TypeIndex LargestTypeIndex = TypeIndex::None();
|
||||
|
||||
BumpPtrAllocator Allocator;
|
||||
StringSaver NameStorage;
|
||||
|
||||
/// The type array to allow random access visitation of.
|
||||
CVTypeArray Types;
|
||||
|
||||
/// The database visitor which adds new records to the database.
|
||||
TypeDatabaseVisitor DatabaseVisitor;
|
||||
|
||||
/// A vector mapping type indices to type offset. For every record that has
|
||||
/// been visited, contains the absolute offset of that record in the record
|
||||
/// array.
|
||||
std::vector<uint32_t> KnownOffsets;
|
||||
std::vector<CacheEntry> Records;
|
||||
|
||||
/// An array of index offsets for the given type stream, allowing log(N)
|
||||
/// lookups of a type record by index. Similar to KnownOffsets but only
|
||||
|
@ -363,7 +363,7 @@ class PublicSym32 : public SymbolRecord {
|
||||
: SymbolRecord(SymbolRecordKind::PublicSym32),
|
||||
RecordOffset(RecordOffset) {}
|
||||
|
||||
TypeIndex Index;
|
||||
PublicSymFlags Flags;
|
||||
uint32_t Offset;
|
||||
uint16_t Segment;
|
||||
StringRef Name;
|
||||
|
@ -1,84 +0,0 @@
|
||||
//===- TypeDatabase.h - A collection of CodeView type records ---*- 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_CODEVIEW_TYPEDATABASE_H
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_TYPEDATABASE_H
|
||||
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/StringSaver.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
class TypeDatabase : public TypeCollection {
|
||||
friend class RandomAccessTypeVisitor;
|
||||
|
||||
public:
|
||||
explicit TypeDatabase(uint32_t Capacity);
|
||||
|
||||
/// Records the name of a type, and reserves its type index.
|
||||
TypeIndex appendType(StringRef Name, const CVType &Data);
|
||||
|
||||
/// Records the name of a type, and reserves its type index.
|
||||
void recordType(StringRef Name, TypeIndex Index, const CVType &Data);
|
||||
|
||||
/// Saves the name in a StringSet and creates a stable StringRef.
|
||||
StringRef saveTypeName(StringRef TypeName);
|
||||
|
||||
StringRef getTypeName(TypeIndex Index) const;
|
||||
|
||||
const CVType &getTypeRecord(TypeIndex Index) const;
|
||||
CVType &getTypeRecord(TypeIndex Index);
|
||||
|
||||
bool contains(TypeIndex Index) const;
|
||||
uint32_t size() const;
|
||||
uint32_t capacity() const;
|
||||
bool empty() const;
|
||||
|
||||
CVType getType(TypeIndex Index) override;
|
||||
StringRef getTypeName(TypeIndex Index) override;
|
||||
bool contains(TypeIndex Index) override;
|
||||
uint32_t size() override;
|
||||
uint32_t capacity() override;
|
||||
|
||||
Optional<TypeIndex> getFirst() override;
|
||||
Optional<TypeIndex> getNext(TypeIndex Prev) override;
|
||||
|
||||
Optional<TypeIndex> largestTypeIndexLessThan(TypeIndex TI) const;
|
||||
|
||||
private:
|
||||
TypeIndex getAppendIndex() const;
|
||||
|
||||
void grow();
|
||||
void grow(TypeIndex Index);
|
||||
|
||||
BumpPtrAllocator Allocator;
|
||||
|
||||
uint32_t Count = 0;
|
||||
TypeIndex LargestTypeIndex;
|
||||
|
||||
/// All user defined type records in .debug$T live in here. Type indices
|
||||
/// greater than 0x1000 are user defined. Subtract 0x1000 from the index to
|
||||
/// index into this vector.
|
||||
SmallVector<StringRef, 10> CVUDTNames;
|
||||
SmallVector<CVType, 10> TypeRecords;
|
||||
|
||||
StringSaver TypeNameStorage;
|
||||
|
||||
BitVector ValidRecords;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1,62 +0,0 @@
|
||||
//===-- TypeDatabaseVisitor.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_CODEVIEW_TYPEDATABASEVISITOR_H
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_TYPEDATABASEVISITOR_H
|
||||
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
|
||||
/// Dumper for CodeView type streams found in COFF object files and PDB files.
|
||||
class TypeDatabaseVisitor : public TypeVisitorCallbacks {
|
||||
public:
|
||||
explicit TypeDatabaseVisitor(TypeDatabase &TypeDB) : TypeDB(&TypeDB) {}
|
||||
|
||||
/// Paired begin/end actions for all types. Receives all record data,
|
||||
/// including the fixed-length record prefix.
|
||||
Error visitTypeBegin(CVType &Record) override;
|
||||
Error visitTypeBegin(CVType &Record, TypeIndex Index) override;
|
||||
Error visitTypeEnd(CVType &Record) override;
|
||||
Error visitMemberBegin(CVMemberRecord &Record) override;
|
||||
Error visitMemberEnd(CVMemberRecord &Record) override;
|
||||
|
||||
#define TYPE_RECORD(EnumName, EnumVal, Name) \
|
||||
Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
|
||||
#define MEMBER_RECORD(EnumName, EnumVal, Name) \
|
||||
Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override;
|
||||
#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
|
||||
#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
|
||||
|
||||
private:
|
||||
StringRef getTypeName(TypeIndex Index) const;
|
||||
StringRef saveTypeName(StringRef Name);
|
||||
|
||||
bool IsInFieldList = false;
|
||||
|
||||
/// Name of the current type. Only valid before visitTypeEnd.
|
||||
StringRef Name;
|
||||
/// Current type index. Only valid before visitTypeEnd, and if we are
|
||||
/// visiting a random access type database.
|
||||
Optional<TypeIndex> CurrentTypeIndex;
|
||||
|
||||
TypeDatabase *TypeDB;
|
||||
};
|
||||
|
||||
} // end namespace codeview
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H
|
@ -11,6 +11,7 @@
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_TYPEINDEXDISCOVERY_H
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
@ -27,6 +28,11 @@ void discoverTypeIndices(ArrayRef<uint8_t> RecordData,
|
||||
SmallVectorImpl<TiReference> &Refs);
|
||||
void discoverTypeIndices(const CVType &Type,
|
||||
SmallVectorImpl<TiReference> &Refs);
|
||||
|
||||
/// Discover type indices in symbol records. Returns false if this is an unknown
|
||||
/// record.
|
||||
bool discoverTypeIndices(const CVSymbol &Symbol,
|
||||
SmallVectorImpl<TiReference> &Refs);
|
||||
}
|
||||
}
|
||||
|
||||
|
22
include/llvm/DebugInfo/CodeView/TypeName.h
Normal file
22
include/llvm/DebugInfo/CodeView/TypeName.h
Normal file
@ -0,0 +1,22 @@
|
||||
//===- TypeName.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_CODEVIEW_TYPENAME_H
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_TYPENAME_H
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
std::string computeTypeName(TypeCollection &Types, TypeIndex Index);
|
||||
}
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
@ -25,6 +25,7 @@ class TypeRecordMapping : public TypeVisitorCallbacks {
|
||||
explicit TypeRecordMapping(BinaryStreamReader &Reader) : IO(Reader) {}
|
||||
explicit TypeRecordMapping(BinaryStreamWriter &Writer) : IO(Writer) {}
|
||||
|
||||
using TypeVisitorCallbacks::visitTypeBegin;
|
||||
Error visitTypeBegin(CVType &Record) override;
|
||||
Error visitTypeEnd(CVType &Record) override;
|
||||
|
||||
|
@ -93,6 +93,7 @@ class TypeSerializer : public TypeVisitorCallbacks {
|
||||
TypeIndex insertRecord(const RemappedType &Record);
|
||||
Expected<TypeIndex> visitTypeEndGetIndex(CVType &Record);
|
||||
|
||||
using TypeVisitorCallbacks::visitTypeBegin;
|
||||
Error visitTypeBegin(CVType &Record) override;
|
||||
Error visitTypeEnd(CVType &Record) override;
|
||||
Error visitMemberBegin(CVMemberRecord &Record) override;
|
||||
|
@ -11,7 +11,9 @@
|
||||
#define LLVM_DEBUGINFO_CODEVIEW_TYPETABLECOLLECTION_H
|
||||
|
||||
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
|
||||
#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
|
||||
#include "llvm/Support/StringSaver.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
namespace codeview {
|
||||
@ -30,11 +32,10 @@ class TypeTableCollection : public TypeCollection {
|
||||
uint32_t capacity() override;
|
||||
|
||||
private:
|
||||
bool hasCapacityFor(TypeIndex Index) const;
|
||||
void ensureTypeExists(TypeIndex Index);
|
||||
|
||||
BumpPtrAllocator Allocator;
|
||||
StringSaver NameStorage;
|
||||
std::vector<StringRef> Names;
|
||||
ArrayRef<ArrayRef<uint8_t>> Records;
|
||||
TypeDatabase Database;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ struct DILineInfo {
|
||||
}
|
||||
};
|
||||
|
||||
typedef SmallVector<std::pair<uint64_t, DILineInfo>, 16> DILineInfoTable;
|
||||
using DILineInfoTable = SmallVector<std::pair<uint64_t, DILineInfo>, 16>;
|
||||
|
||||
/// DIInliningInfo - a format-neutral container for inlined code description.
|
||||
class DIInliningInfo {
|
||||
@ -102,7 +102,7 @@ enum class DINameKind { None, ShortName, LinkageName };
|
||||
/// should be filled with data.
|
||||
struct DILineInfoSpecifier {
|
||||
enum class FileLineInfoKind { None, Default, AbsoluteFilePath };
|
||||
typedef DINameKind FunctionNameKind;
|
||||
using FunctionNameKind = DINameKind;
|
||||
|
||||
FileLineInfoKind FLIKind;
|
||||
FunctionNameKind FNKind;
|
||||
@ -174,6 +174,7 @@ class DIContext {
|
||||
// No verifier? Just say things went well.
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual DILineInfo getLineInfoForAddress(uint64_t Address,
|
||||
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
|
||||
virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address,
|
||||
|
@ -33,6 +33,7 @@ class DWARFAbbreviationDeclaration {
|
||||
|
||||
dwarf::Attribute Attr;
|
||||
dwarf::Form Form;
|
||||
|
||||
/// The following field is used for ByteSize for non-implicit_const
|
||||
/// attributes and as value for implicit_const ones, indicated by
|
||||
/// Form == DW_FORM_implicit_const.
|
||||
@ -58,7 +59,7 @@ class DWARFAbbreviationDeclaration {
|
||||
/// the ByteSize member.
|
||||
Optional<int64_t> getByteSize(const DWARFUnit &U) const;
|
||||
};
|
||||
typedef SmallVector<AttributeSpec, 8> AttributeSpecVector;
|
||||
using AttributeSpecVector = SmallVector<AttributeSpec, 8>;
|
||||
|
||||
DWARFAbbreviationDeclaration();
|
||||
|
||||
@ -67,8 +68,8 @@ class DWARFAbbreviationDeclaration {
|
||||
dwarf::Tag getTag() const { return Tag; }
|
||||
bool hasChildren() const { return HasChildren; }
|
||||
|
||||
typedef iterator_range<AttributeSpecVector::const_iterator>
|
||||
attr_iterator_range;
|
||||
using attr_iterator_range =
|
||||
iterator_range<AttributeSpecVector::const_iterator>;
|
||||
|
||||
attr_iterator_range attributes() const {
|
||||
return attr_iterator_range(AttributeSpecs.begin(), AttributeSpecs.end());
|
||||
|
@ -32,8 +32,9 @@ class DWARFAcceleratorTable {
|
||||
};
|
||||
|
||||
struct HeaderData {
|
||||
typedef uint16_t AtomType;
|
||||
typedef dwarf::Form Form;
|
||||
using AtomType = uint16_t;
|
||||
using Form = dwarf::Form;
|
||||
|
||||
uint32_t DIEOffsetBase;
|
||||
SmallVector<std::pair<AtomType, Form>, 3> Atoms;
|
||||
};
|
||||
|
@ -10,7 +10,6 @@
|
||||
#ifndef LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
|
||||
#define LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/MapVector.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
@ -25,21 +24,24 @@
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
|
||||
#include "llvm/Object/Binary.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/Host.h"
|
||||
#include <cstdint>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class DataExtractor;
|
||||
class MemoryBuffer;
|
||||
class raw_ostream;
|
||||
|
||||
@ -73,7 +75,7 @@ class DWARFContext : public DIContext {
|
||||
std::unique_ptr<DWARFDebugLocDWO> LocDWO;
|
||||
|
||||
/// The maximum DWARF version of all units.
|
||||
unsigned MaxVersion;
|
||||
unsigned MaxVersion = 0;
|
||||
|
||||
struct DWOFile {
|
||||
object::OwningBinary<object::ObjectFile> File;
|
||||
@ -100,7 +102,7 @@ class DWARFContext : public DIContext {
|
||||
void parseDWOTypeUnits();
|
||||
|
||||
public:
|
||||
DWARFContext() : DIContext(CK_DWARF), MaxVersion(0) {}
|
||||
DWARFContext() : DIContext(CK_DWARF) {}
|
||||
DWARFContext(DWARFContext &) = delete;
|
||||
DWARFContext &operator=(DWARFContext &) = delete;
|
||||
|
||||
@ -112,9 +114,9 @@ class DWARFContext : public DIContext {
|
||||
|
||||
bool verify(raw_ostream &OS, DIDumpType DumpType = DIDT_All) override;
|
||||
|
||||
typedef DWARFUnitSection<DWARFCompileUnit>::iterator_range cu_iterator_range;
|
||||
typedef DWARFUnitSection<DWARFTypeUnit>::iterator_range tu_iterator_range;
|
||||
typedef iterator_range<decltype(TUs)::iterator> tu_section_iterator_range;
|
||||
using cu_iterator_range = DWARFUnitSection<DWARFCompileUnit>::iterator_range;
|
||||
using tu_iterator_range = DWARFUnitSection<DWARFTypeUnit>::iterator_range;
|
||||
using tu_section_iterator_range = iterator_range<decltype(TUs)::iterator>;
|
||||
|
||||
/// Get compile units in this context.
|
||||
cu_iterator_range compile_units() {
|
||||
@ -230,8 +232,10 @@ class DWARFContext : public DIContext {
|
||||
virtual bool isLittleEndian() const = 0;
|
||||
virtual uint8_t getAddressSize() const = 0;
|
||||
virtual const DWARFSection &getInfoSection() = 0;
|
||||
typedef MapVector<object::SectionRef, DWARFSection,
|
||||
std::map<object::SectionRef, unsigned>> TypeSectionMap;
|
||||
|
||||
using TypeSectionMap = MapVector<object::SectionRef, DWARFSection,
|
||||
std::map<object::SectionRef, unsigned>>;
|
||||
|
||||
virtual const TypeSectionMap &getTypesSections() = 0;
|
||||
virtual StringRef getAbbrevSection() = 0;
|
||||
virtual const DWARFSection &getLocSection() = 0;
|
||||
|
@ -18,6 +18,8 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class raw_ostream;
|
||||
|
||||
class DWARFAbbreviationDeclarationSet {
|
||||
uint32_t Offset;
|
||||
/// Code of the first abbreviation, if all abbreviations in the set have
|
||||
@ -25,8 +27,8 @@ class DWARFAbbreviationDeclarationSet {
|
||||
uint32_t FirstAbbrCode;
|
||||
std::vector<DWARFAbbreviationDeclaration> Decls;
|
||||
|
||||
typedef std::vector<DWARFAbbreviationDeclaration>::const_iterator
|
||||
const_iterator;
|
||||
using const_iterator =
|
||||
std::vector<DWARFAbbreviationDeclaration>::const_iterator;
|
||||
|
||||
public:
|
||||
DWARFAbbreviationDeclarationSet();
|
||||
@ -51,8 +53,8 @@ class DWARFAbbreviationDeclarationSet {
|
||||
};
|
||||
|
||||
class DWARFDebugAbbrev {
|
||||
typedef std::map<uint64_t, DWARFAbbreviationDeclarationSet>
|
||||
DWARFAbbreviationDeclarationSetMap;
|
||||
using DWARFAbbreviationDeclarationSetMap =
|
||||
std::map<uint64_t, DWARFAbbreviationDeclarationSet>;
|
||||
|
||||
DWARFAbbreviationDeclarationSetMap AbbrDeclSets;
|
||||
mutable DWARFAbbreviationDeclarationSetMap::const_iterator PrevAbbrOffsetPos;
|
||||
|
@ -46,8 +46,8 @@ class DWARFDebugArangeSet {
|
||||
};
|
||||
|
||||
private:
|
||||
typedef std::vector<Descriptor> DescriptorColl;
|
||||
typedef iterator_range<DescriptorColl::const_iterator> desc_iterator_range;
|
||||
using DescriptorColl = std::vector<Descriptor>;
|
||||
using desc_iterator_range = iterator_range<DescriptorColl::const_iterator>;
|
||||
|
||||
uint32_t Offset;
|
||||
Header HeaderData;
|
||||
|
@ -76,8 +76,8 @@ class DWARFDebugAranges {
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::vector<Range> RangeColl;
|
||||
typedef RangeColl::const_iterator RangeCollIterator;
|
||||
using RangeColl = std::vector<Range>;
|
||||
using RangeCollIterator = RangeColl::const_iterator;
|
||||
|
||||
std::vector<RangeEndpoint> Endpoints;
|
||||
RangeColl Aranges;
|
||||
|
@ -10,7 +10,9 @@
|
||||
#ifndef LLVM_DEBUGINFO_DWARFDEBUGLINE_H
|
||||
#define LLVM_DEBUGINFO_DWARFDEBUGLINE_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/DebugInfo/DIContext.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
|
||||
#include "llvm/Support/DataExtractor.h"
|
||||
#include <cstdint>
|
||||
@ -42,10 +44,10 @@ class DWARFDebugLine {
|
||||
/// The size in bytes of the statement information for this compilation unit
|
||||
/// (not including the total_length field itself).
|
||||
uint64_t TotalLength;
|
||||
/// Version identifier for the statement information format.
|
||||
uint16_t Version;
|
||||
/// In v5, size in bytes of an address (or segment offset).
|
||||
uint8_t AddressSize;
|
||||
/// Version, address size (starting in v5), and DWARF32/64 format; these
|
||||
/// parameters affect interpretation of forms (used in the directory and
|
||||
/// file tables starting with v5).
|
||||
DWARFFormParams FormParams;
|
||||
/// In v5, size in bytes of a segment selector.
|
||||
uint8_t SegSelectorSize;
|
||||
/// The number of bytes following the prologue_length field to the beginning
|
||||
@ -70,15 +72,18 @@ class DWARFDebugLine {
|
||||
std::vector<StringRef> IncludeDirectories;
|
||||
std::vector<FileNameEntry> FileNames;
|
||||
|
||||
bool IsDWARF64;
|
||||
const DWARFFormParams getFormParams() const { return FormParams; }
|
||||
uint16_t getVersion() const { return FormParams.Version; }
|
||||
uint8_t getAddressSize() const { return FormParams.AddrSize; }
|
||||
bool isDWARF64() const { return FormParams.Format == dwarf::DWARF64; }
|
||||
|
||||
uint32_t sizeofTotalLength() const { return IsDWARF64 ? 12 : 4; }
|
||||
uint32_t sizeofTotalLength() const { return isDWARF64() ? 12 : 4; }
|
||||
|
||||
uint32_t sizeofPrologueLength() const { return IsDWARF64 ? 8 : 4; }
|
||||
uint32_t sizeofPrologueLength() const { return isDWARF64() ? 8 : 4; }
|
||||
|
||||
/// Length of the prologue in bytes.
|
||||
uint32_t getLength() const {
|
||||
return PrologueLength + sizeofTotalLength() + sizeof(Version) +
|
||||
return PrologueLength + sizeofTotalLength() + sizeof(getVersion()) +
|
||||
sizeofPrologueLength();
|
||||
}
|
||||
|
||||
@ -104,7 +109,9 @@ class DWARFDebugLine {
|
||||
void postAppend();
|
||||
void reset(bool DefaultIsStmt);
|
||||
void dump(raw_ostream &OS) const;
|
||||
|
||||
static void dumpTableHeader(raw_ostream &OS);
|
||||
|
||||
static bool orderByAddress(const Row &LHS, const Row &RHS) {
|
||||
return LHS.Address < RHS.Address;
|
||||
}
|
||||
@ -216,11 +223,12 @@ class DWARFDebugLine {
|
||||
bool parse(DataExtractor DebugLineData, const RelocAddrMap *RMap,
|
||||
uint32_t *OffsetPtr);
|
||||
|
||||
using RowVector = std::vector<Row>;
|
||||
using RowIter = RowVector::const_iterator;
|
||||
using SequenceVector = std::vector<Sequence>;
|
||||
using SequenceIter = SequenceVector::const_iterator;
|
||||
|
||||
struct Prologue Prologue;
|
||||
typedef std::vector<Row> RowVector;
|
||||
typedef RowVector::const_iterator RowIter;
|
||||
typedef std::vector<Sequence> SequenceVector;
|
||||
typedef SequenceVector::const_iterator SequenceIter;
|
||||
RowVector Rows;
|
||||
SequenceVector Sequences;
|
||||
|
||||
@ -244,14 +252,14 @@ class DWARFDebugLine {
|
||||
struct LineTable *LineTable;
|
||||
/// The row number that starts at zero for the prologue, and increases for
|
||||
/// each row added to the matrix.
|
||||
unsigned RowNumber;
|
||||
unsigned RowNumber = 0;
|
||||
struct Row Row;
|
||||
struct Sequence Sequence;
|
||||
};
|
||||
|
||||
typedef std::map<uint32_t, LineTable> LineTableMapTy;
|
||||
typedef LineTableMapTy::iterator LineTableIter;
|
||||
typedef LineTableMapTy::const_iterator LineTableConstIter;
|
||||
using LineTableMapTy = std::map<uint32_t, LineTable>;
|
||||
using LineTableIter = LineTableMapTy::iterator;
|
||||
using LineTableConstIter = LineTableMapTy::const_iterator;
|
||||
|
||||
const RelocAddrMap *RelocMap;
|
||||
LineTableMapTy LineTableMap;
|
||||
|
@ -39,7 +39,7 @@ class DWARFDebugLoc {
|
||||
SmallVector<Entry, 2> Entries;
|
||||
};
|
||||
|
||||
typedef SmallVector<LocationList, 4> LocationLists;
|
||||
using LocationLists = SmallVector<LocationList, 4>;
|
||||
|
||||
/// A list of all the variables in the debug_loc section, each one describing
|
||||
/// the locations in which the variable is stored.
|
||||
@ -71,7 +71,7 @@ class DWARFDebugLocDWO {
|
||||
SmallVector<Entry, 2> Entries;
|
||||
};
|
||||
|
||||
typedef SmallVector<LocationList, 4> LocationLists;
|
||||
using LocationLists = SmallVector<LocationList, 4>;
|
||||
|
||||
LocationLists Locations;
|
||||
|
||||
|
@ -40,7 +40,7 @@ class DWARFDebugMacro {
|
||||
};
|
||||
};
|
||||
|
||||
typedef SmallVector<Entry, 4> MacroList;
|
||||
using MacroList = SmallVector<Entry, 4>;
|
||||
|
||||
/// A list of all the macro entries in the debug_macinfo section.
|
||||
MacroList Macros;
|
||||
|
@ -12,10 +12,8 @@
|
||||
|
||||
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
|
||||
#include "llvm/Support/DataExtractor.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
@ -29,7 +27,7 @@ struct DWARFAddressRange {
|
||||
};
|
||||
|
||||
/// DWARFAddressRangesVector - represents a set of absolute address ranges.
|
||||
typedef std::vector<DWARFAddressRange> DWARFAddressRangesVector;
|
||||
using DWARFAddressRangesVector = std::vector<DWARFAddressRange>;
|
||||
|
||||
class DWARFDebugRangeList {
|
||||
public:
|
||||
|
@ -22,6 +22,35 @@ namespace llvm {
|
||||
class DWARFUnit;
|
||||
class raw_ostream;
|
||||
|
||||
/// A helper struct for DWARFFormValue methods, providing information that
|
||||
/// allows it to know the byte size of DW_FORM values that vary in size
|
||||
/// depending on the DWARF version, address byte size, or DWARF32/DWARF64.
|
||||
struct DWARFFormParams {
|
||||
uint16_t Version;
|
||||
uint8_t AddrSize;
|
||||
dwarf::DwarfFormat Format;
|
||||
|
||||
/// The definition of the size of form DW_FORM_ref_addr depends on the
|
||||
/// version. In DWARF v2 it's the size of an address; after that, it's the
|
||||
/// size of a reference.
|
||||
uint8_t getRefAddrByteSize() const {
|
||||
if (Version == 2)
|
||||
return AddrSize;
|
||||
return getDwarfOffsetByteSize();
|
||||
}
|
||||
|
||||
/// The size of a reference is determined by the DWARF 32/64-bit format.
|
||||
uint8_t getDwarfOffsetByteSize() const {
|
||||
switch (Format) {
|
||||
case dwarf::DwarfFormat::DWARF32:
|
||||
return 4;
|
||||
case dwarf::DwarfFormat::DWARF64:
|
||||
return 8;
|
||||
}
|
||||
llvm_unreachable("Invalid Format value");
|
||||
}
|
||||
};
|
||||
|
||||
class DWARFFormValue {
|
||||
public:
|
||||
enum FormClass {
|
||||
@ -104,79 +133,43 @@ class DWARFFormValue {
|
||||
|
||||
/// Get the fixed byte size for a given form.
|
||||
///
|
||||
/// If the form always has a fixed valid byte size that doesn't depend on a
|
||||
/// DWARFUnit, then an Optional with a value will be returned. If the form
|
||||
/// can vary in size depending on the DWARFUnit (DWARF version, address byte
|
||||
/// size, or DWARF 32/64) and the DWARFUnit is valid, then an Optional with a
|
||||
/// valid value is returned. If the form is always encoded using a variable
|
||||
/// length storage format (ULEB or SLEB numbers or blocks) or the size
|
||||
/// depends on a DWARFUnit and the DWARFUnit is NULL, then None will be
|
||||
/// returned.
|
||||
/// \param Form The DWARF form to get the fixed byte size for
|
||||
/// \param U The DWARFUnit that can be used to help determine the byte size.
|
||||
/// If the form has a fixed byte size, then an Optional with a value will be
|
||||
/// returned. If the form is always encoded using a variable length storage
|
||||
/// format (ULEB or SLEB numbers or blocks) then None will be returned.
|
||||
///
|
||||
/// \returns Optional<uint8_t> value with the fixed byte size or None if
|
||||
/// \p Form doesn't have a fixed byte size or a DWARFUnit wasn't supplied
|
||||
/// and was needed to calculate the byte size.
|
||||
static Optional<uint8_t> getFixedByteSize(dwarf::Form Form,
|
||||
const DWARFUnit *U = nullptr);
|
||||
|
||||
/// Get the fixed byte size for a given form.
|
||||
///
|
||||
/// If the form has a fixed byte size given a valid DWARF version and address
|
||||
/// byte size, then an Optional with a valid value is returned. If the form
|
||||
/// is always encoded using a variable length storage format (ULEB or SLEB
|
||||
/// numbers or blocks) then None will be returned.
|
||||
///
|
||||
/// \param Form DWARF form to get the fixed byte size for
|
||||
/// \param Version DWARF version number.
|
||||
/// \param AddrSize size of an address in bytes.
|
||||
/// \param Format enum value from llvm::dwarf::DwarfFormat.
|
||||
/// \param Form DWARF form to get the fixed byte size for.
|
||||
/// \param FormParams DWARF parameters to help interpret forms.
|
||||
/// \returns Optional<uint8_t> value with the fixed byte size or None if
|
||||
/// \p Form doesn't have a fixed byte size.
|
||||
static Optional<uint8_t> getFixedByteSize(dwarf::Form Form, uint16_t Version,
|
||||
uint8_t AddrSize,
|
||||
llvm::dwarf::DwarfFormat Format);
|
||||
static Optional<uint8_t> getFixedByteSize(dwarf::Form Form,
|
||||
const DWARFFormParams FormParams);
|
||||
|
||||
/// Skip a form in \p DebugInfoData at offset specified by \p OffsetPtr.
|
||||
/// Skip a form's value in \p DebugInfoData at the offset specified by
|
||||
/// \p OffsetPtr.
|
||||
///
|
||||
/// Skips the bytes for this form in the debug info and updates the offset.
|
||||
/// Skips the bytes for the current form and updates the offset.
|
||||
///
|
||||
/// \param DebugInfoData the .debug_info data to use to skip the value.
|
||||
/// \param OffsetPtr a reference to the offset that will be updated.
|
||||
/// \param U the DWARFUnit to use when skipping the form in case the form
|
||||
/// size differs according to data in the DWARFUnit.
|
||||
/// \param DebugInfoData The data where we want to skip the value.
|
||||
/// \param OffsetPtr A reference to the offset that will be updated.
|
||||
/// \param Params DWARF parameters to help interpret forms.
|
||||
/// \returns true on success, false if the form was not skipped.
|
||||
bool skipValue(DataExtractor DebugInfoData, uint32_t *OffsetPtr,
|
||||
const DWARFUnit *U) const;
|
||||
const DWARFFormParams Params) const {
|
||||
return DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, Params);
|
||||
}
|
||||
|
||||
/// Skip a form in \p DebugInfoData at offset specified by \p OffsetPtr.
|
||||
/// Skip a form's value in \p DebugInfoData at the offset specified by
|
||||
/// \p OffsetPtr.
|
||||
///
|
||||
/// Skips the bytes for this form in the debug info and updates the offset.
|
||||
/// Skips the bytes for the specified form and updates the offset.
|
||||
///
|
||||
/// \param Form the DW_FORM enumeration that indicates the form to skip.
|
||||
/// \param DebugInfoData the .debug_info data to use to skip the value.
|
||||
/// \param OffsetPtr a reference to the offset that will be updated.
|
||||
/// \param U the DWARFUnit to use when skipping the form in case the form
|
||||
/// size differs according to data in the DWARFUnit.
|
||||
/// \param Form The DW_FORM enumeration that indicates the form to skip.
|
||||
/// \param DebugInfoData The data where we want to skip the value.
|
||||
/// \param OffsetPtr A reference to the offset that will be updated.
|
||||
/// \param FormParams DWARF parameters to help interpret forms.
|
||||
/// \returns true on success, false if the form was not skipped.
|
||||
static bool skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
|
||||
uint32_t *OffsetPtr, const DWARFUnit *U);
|
||||
|
||||
/// Skip a form in \p DebugInfoData at offset specified by \p OffsetPtr.
|
||||
///
|
||||
/// Skips the bytes for this form in the debug info and updates the offset.
|
||||
///
|
||||
/// \param Form the DW_FORM enumeration that indicates the form to skip.
|
||||
/// \param DebugInfoData the .debug_info data to use to skip the value.
|
||||
/// \param OffsetPtr a reference to the offset that will be updated.
|
||||
/// \param Version DWARF version number.
|
||||
/// \param AddrSize size of an address in bytes.
|
||||
/// \param Format enum value from llvm::dwarf::DwarfFormat.
|
||||
/// \returns true on success, false if the form was not skipped.
|
||||
static bool skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
|
||||
uint32_t *OffsetPtr, uint16_t Version, uint8_t AddrSize,
|
||||
llvm::dwarf::DwarfFormat Format);
|
||||
uint32_t *OffsetPtr, const DWARFFormParams FormParams);
|
||||
|
||||
private:
|
||||
void dumpString(raw_ostream &OS) const;
|
||||
|
@ -12,7 +12,6 @@
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -28,7 +27,7 @@ struct RelocAddrEntry {
|
||||
/// dwarf where we expect relocated values. This adds a bit of complexity to the
|
||||
/// dwarf parsing/extraction at the benefit of not allocating memory for the
|
||||
/// entire size of the debug info sections.
|
||||
typedef DenseMap<uint64_t, RelocAddrEntry> RelocAddrMap;
|
||||
using RelocAddrMap = DenseMap<uint64_t, RelocAddrEntry>;
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
|
@ -19,11 +19,10 @@
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
|
||||
#include "llvm/Object/Binary.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Support/DataExtractor.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
@ -31,6 +30,7 @@
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
@ -72,9 +72,9 @@ class DWARFUnitSection final : public SmallVector<std::unique_ptr<UnitType>, 1>,
|
||||
bool Parsed = false;
|
||||
|
||||
public:
|
||||
typedef SmallVectorImpl<std::unique_ptr<UnitType>> UnitVector;
|
||||
typedef typename UnitVector::iterator iterator;
|
||||
typedef llvm::iterator_range<typename UnitVector::iterator> iterator_range;
|
||||
using UnitVector = SmallVectorImpl<std::unique_ptr<UnitType>>;
|
||||
using iterator = typename UnitVector::iterator;
|
||||
using iterator_range = llvm::iterator_range<typename UnitVector::iterator>;
|
||||
|
||||
UnitType *getUnitForOffset(uint32_t Offset) const override {
|
||||
auto *CU = std::upper_bound(
|
||||
@ -128,12 +128,13 @@ class DWARFUnit {
|
||||
bool isDWO;
|
||||
const DWARFUnitSectionBase &UnitSection;
|
||||
|
||||
// Version, address size, and DWARF format.
|
||||
DWARFFormParams FormParams;
|
||||
|
||||
uint32_t Offset;
|
||||
uint32_t Length;
|
||||
const DWARFAbbreviationDeclarationSet *Abbrevs;
|
||||
uint16_t Version;
|
||||
uint8_t UnitType;
|
||||
uint8_t AddrSize;
|
||||
uint64_t BaseAddr;
|
||||
/// The compile unit debug information entry items.
|
||||
std::vector<DWARFDebugInfoEntry> DieArray;
|
||||
@ -142,8 +143,9 @@ class DWARFUnit {
|
||||
/// IntervalMap does not support range removal, as a result, we use the
|
||||
/// std::map::upper_bound for address range lookup.
|
||||
std::map<uint64_t, std::pair<uint64_t, DWARFDie>> AddrDieMap;
|
||||
typedef iterator_range<std::vector<DWARFDebugInfoEntry>::iterator>
|
||||
die_iterator_range;
|
||||
|
||||
using die_iterator_range =
|
||||
iterator_range<std::vector<DWARFDebugInfoEntry>::iterator>;
|
||||
|
||||
std::shared_ptr<DWARFUnit> DWO;
|
||||
|
||||
@ -159,7 +161,7 @@ class DWARFUnit {
|
||||
virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr);
|
||||
|
||||
/// Size in bytes of the unit header.
|
||||
virtual uint32_t getHeaderSize() const { return Version <= 4 ? 11 : 12; }
|
||||
virtual uint32_t getHeaderSize() const { return getVersion() <= 4 ? 11 : 12; }
|
||||
|
||||
public:
|
||||
DWARFUnit(DWARFContext &Context, const DWARFSection &Section,
|
||||
@ -197,7 +199,8 @@ class DWARFUnit {
|
||||
uint64_t getStringOffsetSectionRelocation(uint32_t Index) const;
|
||||
|
||||
DataExtractor getDebugInfoExtractor() const {
|
||||
return DataExtractor(InfoSection.Data, isLittleEndian, AddrSize);
|
||||
return DataExtractor(InfoSection.Data, isLittleEndian,
|
||||
getAddressByteSize());
|
||||
}
|
||||
|
||||
DataExtractor getStringExtractor() const {
|
||||
@ -220,10 +223,14 @@ class DWARFUnit {
|
||||
uint32_t getOffset() const { return Offset; }
|
||||
uint32_t getNextUnitOffset() const { return Offset + Length + 4; }
|
||||
uint32_t getLength() const { return Length; }
|
||||
uint16_t getVersion() const { return Version; }
|
||||
|
||||
dwarf::DwarfFormat getFormat() const {
|
||||
return dwarf::DwarfFormat::DWARF32; // FIXME: Support DWARF64.
|
||||
const DWARFFormParams &getFormParams() const { return FormParams; }
|
||||
uint16_t getVersion() const { return FormParams.Version; }
|
||||
dwarf::DwarfFormat getFormat() const { return FormParams.Format; }
|
||||
uint8_t getAddressByteSize() const { return FormParams.AddrSize; }
|
||||
uint8_t getRefAddrByteSize() const { return FormParams.getRefAddrByteSize(); }
|
||||
uint8_t getDwarfOffsetByteSize() const {
|
||||
return FormParams.getDwarfOffsetByteSize();
|
||||
}
|
||||
|
||||
const DWARFAbbreviationDeclarationSet *getAbbreviations() const {
|
||||
@ -231,19 +238,6 @@ class DWARFUnit {
|
||||
}
|
||||
|
||||
uint8_t getUnitType() const { return UnitType; }
|
||||
uint8_t getAddressByteSize() const { return AddrSize; }
|
||||
|
||||
uint8_t getRefAddrByteSize() const {
|
||||
if (Version == 2)
|
||||
return AddrSize;
|
||||
return getDwarfOffsetByteSize();
|
||||
}
|
||||
|
||||
uint8_t getDwarfOffsetByteSize() const {
|
||||
if (getFormat() == dwarf::DwarfFormat::DWARF64)
|
||||
return 8;
|
||||
return 4;
|
||||
}
|
||||
|
||||
uint64_t getBaseAddress() const { return BaseAddr; }
|
||||
|
||||
|
@ -12,18 +12,16 @@
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
|
||||
#include "llvm/DebugInfo/MSF/MSFCommon.h"
|
||||
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
namespace msf {
|
||||
|
||||
class MSFBuilder {
|
||||
public:
|
||||
/// \brief Create a new `MSFBuilder`.
|
||||
@ -122,7 +120,7 @@ class MSFBuilder {
|
||||
Error allocateBlocks(uint32_t NumBlocks, MutableArrayRef<uint32_t> Blocks);
|
||||
uint32_t computeDirectoryByteSize() const;
|
||||
|
||||
typedef std::vector<uint32_t> BlockList;
|
||||
using BlockList = std::vector<uint32_t>;
|
||||
|
||||
BumpPtrAllocator &Allocator;
|
||||
|
||||
@ -136,7 +134,8 @@ class MSFBuilder {
|
||||
std::vector<uint32_t> DirectoryBlocks;
|
||||
std::vector<std::pair<uint32_t, BlockList>> StreamData;
|
||||
};
|
||||
} // namespace msf
|
||||
} // namespace llvm
|
||||
|
||||
} // end namespace msf
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_DEBUGINFO_MSF_MSFBUILDER_H
|
||||
|
@ -12,15 +12,15 @@
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
namespace msf {
|
||||
|
||||
static const char Magic[] = {'M', 'i', 'c', 'r', 'o', 's', 'o', 'f',
|
||||
't', ' ', 'C', '/', 'C', '+', '+', ' ',
|
||||
'M', 'S', 'F', ' ', '7', '.', '0', '0',
|
||||
@ -50,8 +50,9 @@ struct SuperBlock {
|
||||
};
|
||||
|
||||
struct MSFLayout {
|
||||
MSFLayout() : SB(nullptr) {}
|
||||
const SuperBlock *SB;
|
||||
MSFLayout() = default;
|
||||
|
||||
const SuperBlock *SB = nullptr;
|
||||
BitVector FreePageMap;
|
||||
ArrayRef<support::ulittle32_t> DirectoryBlocks;
|
||||
ArrayRef<support::ulittle32_t> StreamSizes;
|
||||
@ -90,15 +91,16 @@ inline uint32_t getFpmIntervalLength(const MSFLayout &L) {
|
||||
|
||||
inline uint32_t getNumFpmIntervals(const MSFLayout &L) {
|
||||
uint32_t Length = getFpmIntervalLength(L);
|
||||
return llvm::alignTo(L.SB->NumBlocks, Length) / Length;
|
||||
return alignTo(L.SB->NumBlocks, Length) / Length;
|
||||
}
|
||||
|
||||
inline uint32_t getFullFpmByteSize(const MSFLayout &L) {
|
||||
return llvm::alignTo(L.SB->NumBlocks, 8) / 8;
|
||||
return alignTo(L.SB->NumBlocks, 8) / 8;
|
||||
}
|
||||
|
||||
Error validateSuperBlock(const SuperBlock &SB);
|
||||
} // namespace msf
|
||||
} // namespace llvm
|
||||
|
||||
} // end namespace msf
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_DEBUGINFO_MSF_MSFCOMMON_H
|
||||
|
@ -1,5 +1,4 @@
|
||||
//===- MappedBlockStream.h - Discontiguous stream data in an MSF -*- C++
|
||||
//-*-===//
|
||||
//==- MappedBlockStream.h - Discontiguous stream data in an MSF --*- C++ -*-==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -13,7 +12,6 @@
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/DebugInfo/MSF/MSFStreamLayout.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/BinaryStream.h"
|
||||
@ -21,6 +19,7 @@
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
@ -40,6 +39,7 @@ struct MSFLayout;
|
||||
/// of bytes.
|
||||
class MappedBlockStream : public BinaryStream {
|
||||
friend class WritableMappedBlockStream;
|
||||
|
||||
public:
|
||||
static std::unique_ptr<MappedBlockStream>
|
||||
createStream(uint32_t BlockSize, const MSFStreamLayout &Layout,
|
||||
@ -57,8 +57,8 @@ class MappedBlockStream : public BinaryStream {
|
||||
createDirectoryStream(const MSFLayout &Layout, BinaryStreamRef MsfData,
|
||||
BumpPtrAllocator &Allocator);
|
||||
|
||||
llvm::support::endianness getEndian() const override {
|
||||
return llvm::support::little;
|
||||
support::endianness getEndian() const override {
|
||||
return support::little;
|
||||
}
|
||||
|
||||
Error readBytes(uint32_t Offset, uint32_t Size,
|
||||
@ -68,7 +68,7 @@ class MappedBlockStream : public BinaryStream {
|
||||
|
||||
uint32_t getLength() override;
|
||||
|
||||
llvm::BumpPtrAllocator &getAllocator() { return Allocator; }
|
||||
BumpPtrAllocator &getAllocator() { return Allocator; }
|
||||
|
||||
void invalidateCache();
|
||||
|
||||
@ -92,7 +92,7 @@ class MappedBlockStream : public BinaryStream {
|
||||
const MSFStreamLayout StreamLayout;
|
||||
BinaryStreamRef MsfData;
|
||||
|
||||
typedef MutableArrayRef<uint8_t> CacheEntry;
|
||||
using CacheEntry = MutableArrayRef<uint8_t>;
|
||||
|
||||
// We just store the allocator by reference. We use this to allocate
|
||||
// contiguous memory for things like arrays or strings that cross a block
|
||||
@ -124,8 +124,8 @@ class WritableMappedBlockStream : public WritableBinaryStream {
|
||||
createFpmStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData,
|
||||
BumpPtrAllocator &Allocator);
|
||||
|
||||
llvm::support::endianness getEndian() const override {
|
||||
return llvm::support::little;
|
||||
support::endianness getEndian() const override {
|
||||
return support::little;
|
||||
}
|
||||
|
||||
Error readBytes(uint32_t Offset, uint32_t Size,
|
||||
@ -141,6 +141,7 @@ class WritableMappedBlockStream : public WritableBinaryStream {
|
||||
const MSFStreamLayout &getStreamLayout() const {
|
||||
return ReadInterface.getStreamLayout();
|
||||
}
|
||||
|
||||
uint32_t getBlockSize() const { return ReadInterface.getBlockSize(); }
|
||||
uint32_t getNumBlocks() const { return ReadInterface.getNumBlocks(); }
|
||||
uint32_t getStreamLength() const { return ReadInterface.getStreamLength(); }
|
||||
@ -153,7 +154,6 @@ class WritableMappedBlockStream : public WritableBinaryStream {
|
||||
|
||||
private:
|
||||
MappedBlockStream ReadInterface;
|
||||
|
||||
WritableBinaryStreamRef WriteInterface;
|
||||
};
|
||||
|
||||
|
@ -31,7 +31,7 @@ class DIASession : public IPDBSession {
|
||||
|
||||
uint64_t getLoadAddress() const override;
|
||||
void setLoadAddress(uint64_t Address) override;
|
||||
std::unique_ptr<PDBSymbolExe> getGlobalScope() const override;
|
||||
std::unique_ptr<PDBSymbolExe> getGlobalScope() override;
|
||||
std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const override;
|
||||
|
||||
std::unique_ptr<PDBSymbol>
|
||||
|
@ -29,7 +29,7 @@ class IPDBSession {
|
||||
|
||||
virtual uint64_t getLoadAddress() const = 0;
|
||||
virtual void setLoadAddress(uint64_t Address) = 0;
|
||||
virtual std::unique_ptr<PDBSymbolExe> getGlobalScope() const = 0;
|
||||
virtual std::unique_ptr<PDBSymbolExe> getGlobalScope() = 0;
|
||||
virtual std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const = 0;
|
||||
|
||||
template <typename T>
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
|
||||
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
|
||||
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
|
||||
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
@ -52,6 +53,9 @@ class DbiModuleDescriptorBuilder {
|
||||
void
|
||||
addDebugSubsection(std::shared_ptr<codeview::DebugSubsection> Subsection);
|
||||
|
||||
void
|
||||
addDebugSubsection(const codeview::DebugSubsectionRecord &SubsectionContents);
|
||||
|
||||
uint16_t getStreamIndex() const;
|
||||
StringRef getModuleName() const { return ModuleName; }
|
||||
StringRef getObjFileName() const { return ObjFileName; }
|
||||
|
@ -63,6 +63,13 @@ class DbiStream {
|
||||
|
||||
PDB_Machine getMachineType() const;
|
||||
|
||||
BinarySubstreamRef getSectionContributionData() const;
|
||||
BinarySubstreamRef getSecMapSubstreamData() const;
|
||||
BinarySubstreamRef getModiSubstreamData() const;
|
||||
BinarySubstreamRef getFileInfoSubstreamData() const;
|
||||
BinarySubstreamRef getTypeServerMapSubstreamData() const;
|
||||
BinarySubstreamRef getECSubstreamData() const;
|
||||
|
||||
/// If the given stream type is present, returns its stream index. If it is
|
||||
/// not present, returns InvalidStreamIndex.
|
||||
uint32_t getDebugStreamIndex(DbgHeaderType Type) const;
|
||||
@ -87,10 +94,12 @@ class DbiStream {
|
||||
|
||||
PDBStringTable ECNames;
|
||||
|
||||
BinaryStreamRef SecContrSubstream;
|
||||
BinaryStreamRef SecMapSubstream;
|
||||
BinaryStreamRef TypeServerMapSubstream;
|
||||
BinaryStreamRef ECSubstream;
|
||||
BinarySubstreamRef SecContrSubstream;
|
||||
BinarySubstreamRef SecMapSubstream;
|
||||
BinarySubstreamRef ModiSubstream;
|
||||
BinarySubstreamRef FileInfoSubstream;
|
||||
BinarySubstreamRef TypeServerMapSubstream;
|
||||
BinarySubstreamRef ECSubstream;
|
||||
|
||||
DbiModuleList Modules;
|
||||
|
||||
|
@ -58,6 +58,7 @@ class DbiStreamBuilder {
|
||||
|
||||
Expected<DbiModuleDescriptorBuilder &> addModuleInfo(StringRef ModuleName);
|
||||
Error addModuleSourceFile(StringRef Module, StringRef File);
|
||||
Error addModuleSourceFile(DbiModuleDescriptorBuilder &Module, StringRef File);
|
||||
Expected<uint32_t> getSourceFileNameIndex(StringRef FileName);
|
||||
|
||||
Error finalizeMsfLayout();
|
||||
|
@ -47,6 +47,8 @@ class InfoStream {
|
||||
|
||||
const NamedStreamMap &getNamedStreams() const;
|
||||
|
||||
BinarySubstreamRef getNamedStreamsBuffer() const;
|
||||
|
||||
uint32_t getNamedStreamIndex(llvm::StringRef Name) const;
|
||||
iterator_range<StringMapConstIterator<uint32_t>> named_streams() const;
|
||||
|
||||
@ -71,6 +73,8 @@ class InfoStream {
|
||||
// universally unique.
|
||||
PDB_UniqueId Guid;
|
||||
|
||||
BinarySubstreamRef SubNamedStreams;
|
||||
|
||||
std::vector<PdbRaw_FeatureSig> FeatureSignatures;
|
||||
PdbRaw_Features Features = PdbFeatureNone;
|
||||
|
||||
|
@ -41,9 +41,12 @@ class ModuleDebugStreamRef {
|
||||
iterator_range<codeview::CVSymbolArray::Iterator>
|
||||
symbols(bool *HadError) const;
|
||||
|
||||
const codeview::CVSymbolArray &getSymbolArray() const {
|
||||
return SymbolsSubstream;
|
||||
}
|
||||
const codeview::CVSymbolArray &getSymbolArray() const { return SymbolArray; }
|
||||
|
||||
BinarySubstreamRef getSymbolsSubstream() const;
|
||||
BinarySubstreamRef getC11LinesSubstream() const;
|
||||
BinarySubstreamRef getC13LinesSubstream() const;
|
||||
BinarySubstreamRef getGlobalRefsSubstream() const;
|
||||
|
||||
ModuleDebugStreamRef &operator=(ModuleDebugStreamRef &&Other) = default;
|
||||
|
||||
@ -63,10 +66,12 @@ class ModuleDebugStreamRef {
|
||||
|
||||
std::shared_ptr<msf::MappedBlockStream> Stream;
|
||||
|
||||
codeview::CVSymbolArray SymbolsSubstream;
|
||||
BinaryStreamRef C11LinesSubstream;
|
||||
BinaryStreamRef C13LinesSubstream;
|
||||
BinaryStreamRef GlobalRefsSubstream;
|
||||
codeview::CVSymbolArray SymbolArray;
|
||||
|
||||
BinarySubstreamRef SymbolsSubstream;
|
||||
BinarySubstreamRef C11LinesSubstream;
|
||||
BinarySubstreamRef C13LinesSubstream;
|
||||
BinarySubstreamRef GlobalRefsSubstream;
|
||||
|
||||
codeview::DebugSubsectionArray Subsections;
|
||||
};
|
||||
|
@ -18,7 +18,11 @@ namespace pdb {
|
||||
|
||||
class NativeCompilandSymbol : public NativeRawSymbol {
|
||||
public:
|
||||
NativeCompilandSymbol(NativeSession &Session, DbiModuleDescriptor MI);
|
||||
NativeCompilandSymbol(NativeSession &Session, uint32_t SymbolId,
|
||||
DbiModuleDescriptor MI);
|
||||
|
||||
std::unique_ptr<NativeRawSymbol> clone() const override;
|
||||
|
||||
PDB_SymType getSymTag() const override;
|
||||
bool isEditAndContinueEnabled() const override;
|
||||
uint32_t getLexicalParentId() const override;
|
||||
|
@ -18,7 +18,9 @@ namespace pdb {
|
||||
|
||||
class NativeExeSymbol : public NativeRawSymbol {
|
||||
public:
|
||||
NativeExeSymbol(NativeSession &Session);
|
||||
NativeExeSymbol(NativeSession &Session, uint32_t SymbolId);
|
||||
|
||||
std::unique_ptr<NativeRawSymbol> clone() const override;
|
||||
|
||||
std::unique_ptr<IPDBEnumSymbols>
|
||||
findChildren(PDB_SymType Type) const override;
|
||||
|
@ -19,7 +19,9 @@ class NativeSession;
|
||||
|
||||
class NativeRawSymbol : public IPDBRawSymbol {
|
||||
public:
|
||||
explicit NativeRawSymbol(NativeSession &PDBSession);
|
||||
NativeRawSymbol(NativeSession &PDBSession, uint32_t SymbolId);
|
||||
|
||||
virtual std::unique_ptr<NativeRawSymbol> clone() const = 0;
|
||||
|
||||
void dump(raw_ostream &OS, int Indent) const override;
|
||||
|
||||
@ -201,6 +203,7 @@ class NativeRawSymbol : public IPDBRawSymbol {
|
||||
|
||||
protected:
|
||||
NativeSession &Session;
|
||||
uint32_t SymbolId;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ class NativeSession : public IPDBSession {
|
||||
|
||||
uint64_t getLoadAddress() const override;
|
||||
void setLoadAddress(uint64_t Address) override;
|
||||
std::unique_ptr<PDBSymbolExe> getGlobalScope() const override;
|
||||
std::unique_ptr<PDBSymbolExe> getGlobalScope() override;
|
||||
std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const override;
|
||||
|
||||
std::unique_ptr<PDBSymbol>
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/DebugInfo/MSF/IMSFFile.h"
|
||||
#include "llvm/DebugInfo/MSF/MSFCommon.h"
|
||||
#include "llvm/DebugInfo/MSF/MSFStreamLayout.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/BinaryStreamRef.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
@ -85,6 +86,8 @@ class PDBFile : public msf::IMSFFile {
|
||||
|
||||
ArrayRef<support::ulittle32_t> getDirectoryBlockArray() const;
|
||||
|
||||
msf::MSFStreamLayout getStreamLayout(uint32_t StreamIdx) const;
|
||||
|
||||
Error parseFileHeaders();
|
||||
Error parseStreamData();
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
|
||||
#include "llvm/DebugInfo/PDB/PDBTypes.h"
|
||||
#include "llvm/Support/BinaryStreamArray.h"
|
||||
#include "llvm/Support/BinaryStreamRef.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include "llvm/Support/Error.h"
|
||||
@ -57,6 +58,8 @@ class TpiStream {
|
||||
|
||||
codeview::LazyRandomTypeCollection &typeCollection() { return *Types; }
|
||||
|
||||
BinarySubstreamRef getTypeRecordsSubstream() const;
|
||||
|
||||
Error commit();
|
||||
|
||||
private:
|
||||
@ -65,6 +68,8 @@ class TpiStream {
|
||||
|
||||
std::unique_ptr<codeview::LazyRandomTypeCollection> Types;
|
||||
|
||||
BinarySubstreamRef TypeRecordsSubstream;
|
||||
|
||||
codeview::CVTypeArray TypeRecords;
|
||||
|
||||
std::unique_ptr<BinaryStream> HashStream;
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- SymbolizableModule.h ------------------------------------ C++ -----===//
|
||||
//===- SymbolizableModule.h -------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -14,12 +14,7 @@
|
||||
#define LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZABLEMODULE_H
|
||||
|
||||
#include "llvm/DebugInfo/DIContext.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace object {
|
||||
class ObjectFile;
|
||||
}
|
||||
}
|
||||
#include <cstdint>
|
||||
|
||||
namespace llvm {
|
||||
namespace symbolize {
|
||||
@ -28,7 +23,8 @@ using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind;
|
||||
|
||||
class SymbolizableModule {
|
||||
public:
|
||||
virtual ~SymbolizableModule() {}
|
||||
virtual ~SymbolizableModule() = default;
|
||||
|
||||
virtual DILineInfo symbolizeCode(uint64_t ModuleOffset,
|
||||
FunctionNameKind FNKind,
|
||||
bool UseSymbolTable) const = 0;
|
||||
@ -45,7 +41,7 @@ class SymbolizableModule {
|
||||
virtual uint64_t getModulePreferredBase() const = 0;
|
||||
};
|
||||
|
||||
} // namespace symbolize
|
||||
} // namespace llvm
|
||||
} // end namespace symbolize
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZABLEMODULE_H
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- Symbolize.h --------------------------------------------- C++ -----===//
|
||||
//===- Symbolize.h ----------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -10,21 +10,27 @@
|
||||
// Header for LLVM symbolization library.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZE_H
|
||||
#define LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZE_H
|
||||
|
||||
#include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
|
||||
#include "llvm/Object/Binary.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
namespace symbolize {
|
||||
|
||||
using namespace object;
|
||||
|
||||
using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind;
|
||||
|
||||
class LLVMSymbolizer {
|
||||
@ -36,6 +42,7 @@ class LLVMSymbolizer {
|
||||
bool RelativeAddresses : 1;
|
||||
std::string DefaultArch;
|
||||
std::vector<std::string> DsymHints;
|
||||
|
||||
Options(FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName,
|
||||
bool UseSymbolTable = true, bool Demangle = true,
|
||||
bool RelativeAddresses = false, std::string DefaultArch = "")
|
||||
@ -45,6 +52,7 @@ class LLVMSymbolizer {
|
||||
};
|
||||
|
||||
LLVMSymbolizer(const Options &Opts = Options()) : Opts(Opts) {}
|
||||
|
||||
~LLVMSymbolizer() {
|
||||
flush();
|
||||
}
|
||||
@ -56,6 +64,7 @@ class LLVMSymbolizer {
|
||||
Expected<DIGlobal> symbolizeData(const std::string &ModuleName,
|
||||
uint64_t ModuleOffset);
|
||||
void flush();
|
||||
|
||||
static std::string
|
||||
DemangleName(const std::string &Name,
|
||||
const SymbolizableModule *DbiModuleDescriptor);
|
||||
@ -63,7 +72,7 @@ class LLVMSymbolizer {
|
||||
private:
|
||||
// Bundles together object file with code/data and object file with
|
||||
// corresponding debug info. These objects can be the same.
|
||||
typedef std::pair<ObjectFile*, ObjectFile*> ObjectPair;
|
||||
using ObjectPair = std::pair<ObjectFile *, ObjectFile *>;
|
||||
|
||||
/// Returns a SymbolizableModule or an error if loading debug info failed.
|
||||
/// Only one attempt is made to load a module, and errors during loading are
|
||||
@ -106,7 +115,7 @@ class LLVMSymbolizer {
|
||||
Options Opts;
|
||||
};
|
||||
|
||||
} // namespace symbolize
|
||||
} // namespace llvm
|
||||
} // end namespace symbolize
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
#endif // LLVM_DEBUGINFO_SYMBOLIZE_SYMBOLIZE_H
|
||||
|
@ -15,54 +15,58 @@
|
||||
#ifndef LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H
|
||||
#define LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H
|
||||
|
||||
#include "RuntimeDyld.h"
|
||||
#include "llvm-c/ExecutionEngine.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/Optional.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ExecutionEngine/JITSymbol.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/ValueHandle.h"
|
||||
#include "llvm/IR/ValueMap.h"
|
||||
#include "llvm/Object/Binary.h"
|
||||
#include "llvm/Support/CBindingWrapping.h"
|
||||
#include "llvm/Support/CodeGen.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/Mutex.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
struct GenericValue;
|
||||
class Constant;
|
||||
class DataLayout;
|
||||
class ExecutionEngine;
|
||||
class Function;
|
||||
class GlobalVariable;
|
||||
struct GenericValue;
|
||||
class GlobalValue;
|
||||
class GlobalVariable;
|
||||
class JITEventListener;
|
||||
class MachineCodeInfo;
|
||||
class MCJITMemoryManager;
|
||||
class MutexGuard;
|
||||
class ObjectCache;
|
||||
class RTDyldMemoryManager;
|
||||
class Triple;
|
||||
class Type;
|
||||
|
||||
namespace object {
|
||||
class Archive;
|
||||
class ObjectFile;
|
||||
}
|
||||
|
||||
class Archive;
|
||||
class ObjectFile;
|
||||
|
||||
} // end namespace object
|
||||
|
||||
/// \brief Helper class for helping synchronize access to the global address map
|
||||
/// table. Access to this class should be serialized under a mutex.
|
||||
class ExecutionEngineState {
|
||||
public:
|
||||
typedef StringMap<uint64_t> GlobalAddressMapTy;
|
||||
using GlobalAddressMapTy = StringMap<uint64_t>;
|
||||
|
||||
private:
|
||||
|
||||
/// GlobalAddressMap - A mapping between LLVM global symbol names values and
|
||||
/// their actualized version...
|
||||
GlobalAddressMapTy GlobalAddressMap;
|
||||
@ -74,7 +78,6 @@ class ExecutionEngineState {
|
||||
std::map<uint64_t, std::string> GlobalAddressReverseMap;
|
||||
|
||||
public:
|
||||
|
||||
GlobalAddressMapTy &getGlobalAddressMap() {
|
||||
return GlobalAddressMap;
|
||||
}
|
||||
@ -509,13 +512,15 @@ class ExecutionEngine {
|
||||
};
|
||||
|
||||
namespace EngineKind {
|
||||
|
||||
// These are actually bitmasks that get or-ed together.
|
||||
enum Kind {
|
||||
JIT = 0x1,
|
||||
Interpreter = 0x2
|
||||
};
|
||||
const static Kind Either = (Kind)(JIT | Interpreter);
|
||||
}
|
||||
|
||||
} // end namespace EngineKind
|
||||
|
||||
/// Builder class for ExecutionEngines. Use this by stack-allocating a builder,
|
||||
/// chaining the various set* methods, and terminating it with a .create()
|
||||
@ -655,6 +660,6 @@ class EngineBuilder {
|
||||
// Create wrappers for C Binding types (see CBindingWrapping.h).
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ExecutionEngine, LLVMExecutionEngineRef)
|
||||
|
||||
} // End llvm namespace
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
#endif // LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- GenericValue.h - Represent any type of LLVM value -------*- C++ -*-===//
|
||||
//===- GenericValue.h - Represent any type of LLVM value --------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -11,18 +11,15 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#ifndef LLVM_EXECUTIONENGINE_GENERICVALUE_H
|
||||
#define LLVM_EXECUTIONENGINE_GENERICVALUE_H
|
||||
|
||||
#include "llvm/ADT/APInt.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
typedef void* PointerTy;
|
||||
class APInt;
|
||||
using PointerTy = void *;
|
||||
|
||||
struct GenericValue {
|
||||
struct IntPair {
|
||||
@ -30,25 +27,29 @@ struct GenericValue {
|
||||
unsigned int second;
|
||||
};
|
||||
union {
|
||||
double DoubleVal;
|
||||
float FloatVal;
|
||||
PointerTy PointerVal;
|
||||
struct IntPair UIntPairVal;
|
||||
unsigned char Untyped[8];
|
||||
double DoubleVal;
|
||||
float FloatVal;
|
||||
PointerTy PointerVal;
|
||||
struct IntPair UIntPairVal;
|
||||
unsigned char Untyped[8];
|
||||
};
|
||||
APInt IntVal; // also used for long doubles.
|
||||
APInt IntVal; // also used for long doubles.
|
||||
// For aggregate data types.
|
||||
std::vector<GenericValue> AggregateVal;
|
||||
|
||||
// to make code faster, set GenericValue to zero could be omitted, but it is
|
||||
// potentially can cause problems, since GenericValue to store garbage
|
||||
// instead of zero.
|
||||
GenericValue() : IntVal(1,0) {UIntPairVal.first = 0; UIntPairVal.second = 0;}
|
||||
explicit GenericValue(void *V) : PointerVal(V), IntVal(1,0) { }
|
||||
GenericValue() : IntVal(1, 0) {
|
||||
UIntPairVal.first = 0;
|
||||
UIntPairVal.second = 0;
|
||||
}
|
||||
explicit GenericValue(void *V) : PointerVal(V), IntVal(1, 0) {}
|
||||
};
|
||||
|
||||
inline GenericValue PTOGV(void *P) { return GenericValue(P); }
|
||||
inline void* GVTOP(const GenericValue &GV) { return GV.PointerVal; }
|
||||
inline void *GVTOP(const GenericValue &GV) { return GV.PointerVal; }
|
||||
|
||||
} // End llvm namespace.
|
||||
#endif
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_EXECUTIONENGINE_GENERICVALUE_H
|
||||
|
@ -15,8 +15,8 @@
|
||||
#ifndef LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H
|
||||
#define LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H
|
||||
|
||||
#include "RuntimeDyld.h"
|
||||
#include "llvm/Config/llvm-config.h"
|
||||
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||
#include "llvm/IR/DebugLoc.h"
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
@ -28,7 +28,9 @@ class MachineFunction;
|
||||
class OProfileWrapper;
|
||||
|
||||
namespace object {
|
||||
class ObjectFile;
|
||||
|
||||
class ObjectFile;
|
||||
|
||||
} // end namespace object
|
||||
|
||||
/// JITEvent_EmittedFunctionDetails - Helper struct for containing information
|
||||
@ -57,7 +59,7 @@ struct JITEvent_EmittedFunctionDetails {
|
||||
/// The default implementation of each method does nothing.
|
||||
class JITEventListener {
|
||||
public:
|
||||
typedef JITEvent_EmittedFunctionDetails EmittedFunctionDetails;
|
||||
using EmittedFunctionDetails = JITEvent_EmittedFunctionDetails;
|
||||
|
||||
public:
|
||||
JITEventListener() = default;
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===----------- JITSymbol.h - JIT symbol abstraction -----------*- C++ -*-===//
|
||||
//===- JITSymbol.h - JIT symbol abstraction ---------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -26,16 +26,18 @@ namespace llvm {
|
||||
class GlobalValue;
|
||||
|
||||
namespace object {
|
||||
class BasicSymbolRef;
|
||||
|
||||
class BasicSymbolRef;
|
||||
|
||||
} // end namespace object
|
||||
|
||||
/// @brief Represents an address in the target process's address space.
|
||||
typedef uint64_t JITTargetAddress;
|
||||
using JITTargetAddress = uint64_t;
|
||||
|
||||
/// @brief Flags for symbols in the JIT.
|
||||
class JITSymbolFlags {
|
||||
public:
|
||||
typedef uint8_t UnderlyingType;
|
||||
using UnderlyingType = uint8_t;
|
||||
|
||||
enum FlagNames : UnderlyingType {
|
||||
None = 0,
|
||||
@ -46,7 +48,7 @@ class JITSymbolFlags {
|
||||
};
|
||||
|
||||
/// @brief Default-construct a JITSymbolFlags instance.
|
||||
JITSymbolFlags() : Flags(None) {}
|
||||
JITSymbolFlags() = default;
|
||||
|
||||
/// @brief Construct a JITSymbolFlags instance from the given flags.
|
||||
JITSymbolFlags(FlagNames Flags) : Flags(Flags) {}
|
||||
@ -81,15 +83,14 @@ class JITSymbolFlags {
|
||||
static JITSymbolFlags fromObjectSymbol(const object::BasicSymbolRef &Symbol);
|
||||
|
||||
private:
|
||||
UnderlyingType Flags;
|
||||
UnderlyingType Flags = None;
|
||||
};
|
||||
|
||||
/// @brief Represents a symbol that has been evaluated to an address already.
|
||||
class JITEvaluatedSymbol {
|
||||
public:
|
||||
/// @brief Create a 'null' symbol.
|
||||
JITEvaluatedSymbol(std::nullptr_t)
|
||||
: Address(0) {}
|
||||
JITEvaluatedSymbol(std::nullptr_t) {}
|
||||
|
||||
/// @brief Create a symbol for the given address and flags.
|
||||
JITEvaluatedSymbol(JITTargetAddress Address, JITSymbolFlags Flags)
|
||||
@ -105,19 +106,18 @@ class JITEvaluatedSymbol {
|
||||
JITSymbolFlags getFlags() const { return Flags; }
|
||||
|
||||
private:
|
||||
JITTargetAddress Address;
|
||||
JITTargetAddress Address = 0;
|
||||
JITSymbolFlags Flags;
|
||||
};
|
||||
|
||||
/// @brief Represents a symbol in the JIT.
|
||||
class JITSymbol {
|
||||
public:
|
||||
typedef std::function<JITTargetAddress()> GetAddressFtor;
|
||||
using GetAddressFtor = std::function<JITTargetAddress()>;
|
||||
|
||||
/// @brief Create a 'null' symbol that represents failure to find a symbol
|
||||
/// definition.
|
||||
JITSymbol(std::nullptr_t)
|
||||
: CachedAddr(0) {}
|
||||
JITSymbol(std::nullptr_t) {}
|
||||
|
||||
/// @brief Create a symbol for a definition with a known address.
|
||||
JITSymbol(JITTargetAddress Addr, JITSymbolFlags Flags)
|
||||
@ -137,7 +137,7 @@ class JITSymbol {
|
||||
/// user can materialize the definition at any time by calling the getAddress
|
||||
/// method.
|
||||
JITSymbol(GetAddressFtor GetAddress, JITSymbolFlags Flags)
|
||||
: GetAddress(std::move(GetAddress)), CachedAddr(0), Flags(Flags) {}
|
||||
: GetAddress(std::move(GetAddress)), Flags(Flags) {}
|
||||
|
||||
/// @brief Returns true if the symbol exists, false otherwise.
|
||||
explicit operator bool() const { return CachedAddr || GetAddress; }
|
||||
@ -157,7 +157,7 @@ class JITSymbol {
|
||||
|
||||
private:
|
||||
GetAddressFtor GetAddress;
|
||||
JITTargetAddress CachedAddr;
|
||||
JITTargetAddress CachedAddr = 0;
|
||||
JITSymbolFlags Flags;
|
||||
};
|
||||
|
||||
|
@ -24,16 +24,20 @@
|
||||
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
|
||||
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||
#include "llvm/IR/Attributes.h"
|
||||
#include "llvm/IR/Constant.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/GlobalAlias.h"
|
||||
#include "llvm/IR/GlobalValue.h"
|
||||
#include "llvm/IR/GlobalVariable.h"
|
||||
#include "llvm/IR/Instruction.h"
|
||||
#include "llvm/IR/Mangler.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Transforms/Utils/ValueMapper.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <functional>
|
||||
@ -46,6 +50,9 @@
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Value;
|
||||
|
||||
namespace orc {
|
||||
|
||||
/// @brief Compile-on-demand layer.
|
||||
@ -77,15 +84,15 @@ class CompileOnDemandLayer {
|
||||
return LambdaMaterializer<MaterializerFtor>(std::move(M));
|
||||
}
|
||||
|
||||
typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
|
||||
using BaseLayerModuleHandleT = typename BaseLayerT::ModuleHandleT;
|
||||
|
||||
// Provide type-erasure for the Modules and MemoryManagers.
|
||||
template <typename ResourceT>
|
||||
class ResourceOwner {
|
||||
public:
|
||||
ResourceOwner() = default;
|
||||
ResourceOwner(const ResourceOwner&) = delete;
|
||||
ResourceOwner& operator=(const ResourceOwner&) = delete;
|
||||
ResourceOwner(const ResourceOwner &) = delete;
|
||||
ResourceOwner &operator=(const ResourceOwner &) = delete;
|
||||
virtual ~ResourceOwner() = default;
|
||||
|
||||
virtual ResourceT& getResource() const = 0;
|
||||
@ -106,7 +113,7 @@ class CompileOnDemandLayer {
|
||||
template <typename ResourceT, typename ResourcePtrT>
|
||||
std::unique_ptr<ResourceOwner<ResourceT>>
|
||||
wrapOwnership(ResourcePtrT ResourcePtr) {
|
||||
typedef ResourceOwnerImpl<ResourceT, ResourcePtrT> RO;
|
||||
using RO = ResourceOwnerImpl<ResourceT, ResourcePtrT>;
|
||||
return llvm::make_unique<RO>(std::move(ResourcePtr));
|
||||
}
|
||||
|
||||
@ -130,21 +137,21 @@ class CompileOnDemandLayer {
|
||||
};
|
||||
|
||||
struct LogicalDylib {
|
||||
typedef std::function<JITSymbol(const std::string&)> SymbolResolverFtor;
|
||||
using SymbolResolverFtor = std::function<JITSymbol(const std::string&)>;
|
||||
|
||||
typedef std::function<typename BaseLayerT::ModuleSetHandleT(
|
||||
BaseLayerT&,
|
||||
std::unique_ptr<Module>,
|
||||
std::unique_ptr<JITSymbolResolver>)>
|
||||
ModuleAdderFtor;
|
||||
using ModuleAdderFtor =
|
||||
std::function<typename BaseLayerT::ModuleHandleT(
|
||||
BaseLayerT&,
|
||||
std::unique_ptr<Module>,
|
||||
std::unique_ptr<JITSymbolResolver>)>;
|
||||
|
||||
struct SourceModuleEntry {
|
||||
std::unique_ptr<ResourceOwner<Module>> SourceMod;
|
||||
std::set<Function*> StubsToClone;
|
||||
};
|
||||
|
||||
typedef std::vector<SourceModuleEntry> SourceModulesList;
|
||||
typedef typename SourceModulesList::size_type SourceModuleHandle;
|
||||
using SourceModulesList = std::vector<SourceModuleEntry>;
|
||||
using SourceModuleHandle = typename SourceModulesList::size_type;
|
||||
|
||||
SourceModuleHandle
|
||||
addSourceModule(std::unique_ptr<ResourceOwner<Module>> M) {
|
||||
@ -174,7 +181,7 @@ class CompileOnDemandLayer {
|
||||
|
||||
void removeModulesFromBaseLayer(BaseLayerT &BaseLayer) {
|
||||
for (auto &BLH : BaseLayerHandles)
|
||||
BaseLayer.removeModuleSet(BLH);
|
||||
BaseLayer.removeModule(BLH);
|
||||
}
|
||||
|
||||
std::unique_ptr<JITSymbolResolver> ExternalSymbolResolver;
|
||||
@ -183,21 +190,21 @@ class CompileOnDemandLayer {
|
||||
StaticGlobalRenamer StaticRenamer;
|
||||
ModuleAdderFtor ModuleAdder;
|
||||
SourceModulesList SourceModules;
|
||||
std::vector<BaseLayerModuleSetHandleT> BaseLayerHandles;
|
||||
std::vector<BaseLayerModuleHandleT> BaseLayerHandles;
|
||||
};
|
||||
|
||||
typedef std::list<LogicalDylib> LogicalDylibList;
|
||||
using LogicalDylibList = std::list<LogicalDylib>;
|
||||
|
||||
public:
|
||||
/// @brief Handle to a set of loaded modules.
|
||||
typedef typename LogicalDylibList::iterator ModuleSetHandleT;
|
||||
/// @brief Handle to loaded module.
|
||||
using ModuleHandleT = typename LogicalDylibList::iterator;
|
||||
|
||||
/// @brief Module partitioning functor.
|
||||
typedef std::function<std::set<Function*>(Function&)> PartitioningFtor;
|
||||
using PartitioningFtor = std::function<std::set<Function*>(Function&)>;
|
||||
|
||||
/// @brief Builder for IndirectStubsManagers.
|
||||
typedef std::function<std::unique_ptr<IndirectStubsMgrT>()>
|
||||
IndirectStubsManagerBuilderT;
|
||||
using IndirectStubsManagerBuilderT =
|
||||
std::function<std::unique_ptr<IndirectStubsMgrT>()>;
|
||||
|
||||
/// @brief Construct a compile-on-demand layer instance.
|
||||
CompileOnDemandLayer(BaseLayerT &BaseLayer, PartitioningFtor Partition,
|
||||
@ -211,15 +218,14 @@ class CompileOnDemandLayer {
|
||||
|
||||
~CompileOnDemandLayer() {
|
||||
while (!LogicalDylibs.empty())
|
||||
removeModuleSet(LogicalDylibs.begin());
|
||||
removeModule(LogicalDylibs.begin());
|
||||
}
|
||||
|
||||
|
||||
/// @brief Add a module to the compile-on-demand layer.
|
||||
template <typename ModuleSetT, typename MemoryManagerPtrT,
|
||||
typename SymbolResolverPtrT>
|
||||
ModuleSetHandleT addModuleSet(ModuleSetT Ms,
|
||||
MemoryManagerPtrT MemMgr,
|
||||
SymbolResolverPtrT Resolver) {
|
||||
template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
|
||||
ModuleHandleT addModule(std::shared_ptr<Module> M,
|
||||
MemoryManagerPtrT MemMgr,
|
||||
SymbolResolverPtrT Resolver) {
|
||||
|
||||
LogicalDylibs.push_back(LogicalDylib());
|
||||
auto &LD = LogicalDylibs.back();
|
||||
@ -232,23 +238,25 @@ class CompileOnDemandLayer {
|
||||
LD.ModuleAdder =
|
||||
[&MemMgrRef](BaseLayerT &B, std::unique_ptr<Module> M,
|
||||
std::unique_ptr<JITSymbolResolver> R) {
|
||||
std::vector<std::unique_ptr<Module>> Ms;
|
||||
Ms.push_back(std::move(M));
|
||||
return B.addModuleSet(std::move(Ms), &MemMgrRef, std::move(R));
|
||||
return B.addModule(std::move(M), &MemMgrRef, std::move(R));
|
||||
};
|
||||
|
||||
// Process each of the modules in this module set.
|
||||
for (auto &M : Ms)
|
||||
addLogicalModule(LogicalDylibs.back(), std::move(M));
|
||||
addLogicalModule(LogicalDylibs.back(), std::move(M));
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
/// @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 removeModuleSet(ModuleSetHandleT H) {
|
||||
void removeModule(ModuleHandleT H) {
|
||||
H->removeModulesFromBaseLayer(BaseLayer);
|
||||
LogicalDylibs.erase(H);
|
||||
}
|
||||
@ -270,7 +278,7 @@ class CompileOnDemandLayer {
|
||||
|
||||
/// @brief Get the address of a symbol provided by this layer, or some layer
|
||||
/// below this one.
|
||||
JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
|
||||
JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
|
||||
bool ExportedSymbolsOnly) {
|
||||
return H->findSymbol(BaseLayer, Name, ExportedSymbolsOnly);
|
||||
}
|
||||
@ -303,7 +311,6 @@ class CompileOnDemandLayer {
|
||||
private:
|
||||
template <typename ModulePtrT>
|
||||
void addLogicalModule(LogicalDylib &LD, ModulePtrT SrcMPtr) {
|
||||
|
||||
// Rename all static functions / globals to $static.X :
|
||||
// This will unique the names across all modules in the logical dylib,
|
||||
// simplifying symbol lookup.
|
||||
@ -495,7 +502,7 @@ class CompileOnDemandLayer {
|
||||
}
|
||||
|
||||
template <typename PartitionT>
|
||||
BaseLayerModuleSetHandleT
|
||||
BaseLayerModuleHandleT
|
||||
emitPartition(LogicalDylib &LD,
|
||||
typename LogicalDylib::SourceModuleHandle LMId,
|
||||
const PartitionT &Part) {
|
||||
@ -581,6 +588,7 @@ class CompileOnDemandLayer {
|
||||
};
|
||||
|
||||
} // end namespace orc
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- CompileUtils.h - Utilities for compiling IR in the JIT --*- C++ -*-===//
|
||||
//===- CompileUtils.h - Utilities for compiling IR in the JIT ---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -14,24 +14,47 @@
|
||||
#ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H
|
||||
#define LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ExecutionEngine/ObjectCache.h"
|
||||
#include "llvm/ExecutionEngine/ObjectMemoryBuffer.h"
|
||||
#include "llvm/IR/LegacyPassManager.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/Object/Binary.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MCContext;
|
||||
class Module;
|
||||
|
||||
namespace orc {
|
||||
|
||||
/// @brief Simple compile functor: Takes a single IR module and returns an
|
||||
/// ObjectFile.
|
||||
class SimpleCompiler {
|
||||
public:
|
||||
|
||||
using CompileResult = object::OwningBinary<object::ObjectFile>;
|
||||
|
||||
/// @brief Construct a simple compile functor with the given target.
|
||||
SimpleCompiler(TargetMachine &TM) : TM(TM) {}
|
||||
SimpleCompiler(TargetMachine &TM, ObjectCache *ObjCache = nullptr)
|
||||
: TM(TM), ObjCache(ObjCache) {}
|
||||
|
||||
/// @brief Set an ObjectCache to query before compiling.
|
||||
void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; }
|
||||
|
||||
/// @brief Compile a Module to an ObjectFile.
|
||||
object::OwningBinary<object::ObjectFile> operator()(Module &M) const {
|
||||
CompileResult operator()(Module &M) {
|
||||
CompileResult CachedObject = tryToLoadFromObjectCache(M);
|
||||
if (CachedObject.getBinary())
|
||||
return CachedObject;
|
||||
|
||||
SmallVector<char, 0> ObjBufferSV;
|
||||
raw_svector_ostream ObjStream(ObjBufferSV);
|
||||
|
||||
@ -44,19 +67,47 @@ class SimpleCompiler {
|
||||
new ObjectMemoryBuffer(std::move(ObjBufferSV)));
|
||||
Expected<std::unique_ptr<object::ObjectFile>> Obj =
|
||||
object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
|
||||
typedef object::OwningBinary<object::ObjectFile> OwningObj;
|
||||
if (Obj)
|
||||
return OwningObj(std::move(*Obj), std::move(ObjBuffer));
|
||||
if (Obj) {
|
||||
notifyObjectCompiled(M, *ObjBuffer);
|
||||
return CompileResult(std::move(*Obj), std::move(ObjBuffer));
|
||||
}
|
||||
// TODO: Actually report errors helpfully.
|
||||
consumeError(Obj.takeError());
|
||||
return OwningObj(nullptr, nullptr);
|
||||
return CompileResult(nullptr, nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
CompileResult tryToLoadFromObjectCache(const Module &M) {
|
||||
if (!ObjCache)
|
||||
return CompileResult();
|
||||
|
||||
std::unique_ptr<MemoryBuffer> ObjBuffer = ObjCache->getObject(&M);
|
||||
if (!ObjBuffer)
|
||||
return CompileResult();
|
||||
|
||||
Expected<std::unique_ptr<object::ObjectFile>> Obj =
|
||||
object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
|
||||
if (!Obj) {
|
||||
// TODO: Actually report errors helpfully.
|
||||
consumeError(Obj.takeError());
|
||||
return CompileResult();
|
||||
}
|
||||
|
||||
return CompileResult(std::move(*Obj), std::move(ObjBuffer));
|
||||
}
|
||||
|
||||
void notifyObjectCompiled(const Module &M, const MemoryBuffer &ObjBuffer) {
|
||||
if (ObjCache)
|
||||
ObjCache->notifyObjectCompiled(&M, ObjBuffer.getMemBufferRef());
|
||||
}
|
||||
|
||||
TargetMachine &TM;
|
||||
ObjectCache *ObjCache = nullptr;
|
||||
};
|
||||
|
||||
} // End namespace orc.
|
||||
} // End namespace llvm.
|
||||
} // end namespace orc
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_EXECUTIONENGINE_ORC_COMPILEUTILS_H
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- ExecutionUtils.h - Utilities for executing code in Orc --*- C++ -*-===//
|
||||
//===- ExecutionUtils.h - Utilities for executing code in Orc ---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -17,8 +17,11 @@
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/ExecutionEngine/JITSymbol.h"
|
||||
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -37,7 +40,6 @@ namespace orc {
|
||||
/// getConstructors/getDestructors functions.
|
||||
class CtorDtorIterator {
|
||||
public:
|
||||
|
||||
/// @brief Accessor for an element of the global_ctors/global_dtors array.
|
||||
///
|
||||
/// This class provides a read-only view of the element with any casts on
|
||||
@ -89,17 +91,16 @@ iterator_range<CtorDtorIterator> getDestructors(const Module &M);
|
||||
template <typename JITLayerT>
|
||||
class CtorDtorRunner {
|
||||
public:
|
||||
|
||||
/// @brief Construct a CtorDtorRunner for the given range using the given
|
||||
/// name mangling function.
|
||||
CtorDtorRunner(std::vector<std::string> CtorDtorNames,
|
||||
typename JITLayerT::ModuleSetHandleT H)
|
||||
typename JITLayerT::ModuleHandleT H)
|
||||
: CtorDtorNames(std::move(CtorDtorNames)), H(H) {}
|
||||
|
||||
/// @brief Run the recorded constructors/destructors through the given JIT
|
||||
/// layer.
|
||||
bool runViaLayer(JITLayerT &JITLayer) const {
|
||||
typedef void (*CtorDtorTy)();
|
||||
using CtorDtorTy = void (*)();
|
||||
|
||||
bool Error = false;
|
||||
for (const auto &CtorDtorName : CtorDtorNames)
|
||||
@ -115,7 +116,7 @@ class CtorDtorRunner {
|
||||
|
||||
private:
|
||||
std::vector<std::string> CtorDtorNames;
|
||||
typename JITLayerT::ModuleSetHandleT H;
|
||||
typename JITLayerT::ModuleHandleT H;
|
||||
};
|
||||
|
||||
/// @brief Support class for static dtor execution. For hosted (in-process) JITs
|
||||
@ -135,7 +136,6 @@ class CtorDtorRunner {
|
||||
/// called.
|
||||
class LocalCXXRuntimeOverrides {
|
||||
public:
|
||||
|
||||
/// Create a runtime-overrides class.
|
||||
template <typename MangleFtorT>
|
||||
LocalCXXRuntimeOverrides(const MangleFtorT &Mangle) {
|
||||
@ -156,7 +156,6 @@ class LocalCXXRuntimeOverrides {
|
||||
void runDestructors();
|
||||
|
||||
private:
|
||||
|
||||
template <typename PtrTy>
|
||||
JITTargetAddress toTargetAddress(PtrTy* P) {
|
||||
return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(P));
|
||||
@ -168,15 +167,16 @@ class LocalCXXRuntimeOverrides {
|
||||
|
||||
StringMap<JITTargetAddress> CXXRuntimeOverrides;
|
||||
|
||||
typedef void (*DestructorPtr)(void*);
|
||||
typedef std::pair<DestructorPtr, void*> CXXDestructorDataPair;
|
||||
typedef std::vector<CXXDestructorDataPair> CXXDestructorDataPairList;
|
||||
using DestructorPtr = void (*)(void *);
|
||||
using CXXDestructorDataPair = std::pair<DestructorPtr, void *>;
|
||||
using CXXDestructorDataPairList = std::vector<CXXDestructorDataPair>;
|
||||
CXXDestructorDataPairList DSOHandleOverride;
|
||||
static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg,
|
||||
void *DSOHandle);
|
||||
};
|
||||
|
||||
} // End namespace orc.
|
||||
} // End namespace llvm.
|
||||
} // end namespace orc
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===---- GlobalMappingLayer.h - Run all IR through a functor ---*- C++ -*-===//
|
||||
//===- GlobalMappingLayer.h - Run all IR through a functor ------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -17,6 +17,7 @@
|
||||
|
||||
#include "llvm/ExecutionEngine/JITSymbol.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
namespace orc {
|
||||
@ -32,7 +33,7 @@ template <typename BaseLayerT>
|
||||
class GlobalMappingLayer {
|
||||
public:
|
||||
/// @brief Handle to a set of added modules.
|
||||
typedef typename BaseLayerT::ModuleSetHandleT ModuleSetHandleT;
|
||||
using ModuleSetHandleT = typename BaseLayerT::ModuleSetHandleT;
|
||||
|
||||
/// @brief Construct an GlobalMappingLayer with the given BaseLayer
|
||||
GlobalMappingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
|
||||
@ -102,7 +103,7 @@ class GlobalMappingLayer {
|
||||
std::map<std::string, JITTargetAddress> SymbolTable;
|
||||
};
|
||||
|
||||
} // End namespace orc.
|
||||
} // End namespace llvm.
|
||||
} // end namespace orc
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_EXECUTIONENGINE_ORC_GLOBALMAPPINGLAYER_H
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===------ IRCompileLayer.h -- Eagerly compile IR for JIT ------*- C++ -*-===//
|
||||
//===- IRCompileLayer.h -- Eagerly compile IR for JIT -----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -14,79 +14,54 @@
|
||||
#ifndef LLVM_EXECUTIONENGINE_ORC_IRCOMPILELAYER_H
|
||||
#define LLVM_EXECUTIONENGINE_ORC_IRCOMPILELAYER_H
|
||||
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ExecutionEngine/JITSymbol.h"
|
||||
#include "llvm/ExecutionEngine/ObjectCache.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Module;
|
||||
|
||||
namespace orc {
|
||||
|
||||
/// @brief Eager IR compiling layer.
|
||||
///
|
||||
/// This layer accepts sets of LLVM IR Modules (via addModuleSet). It
|
||||
/// immediately compiles each IR module to an object file (each IR Module is
|
||||
/// compiled separately). The resulting set of object files is then added to
|
||||
/// the layer below, which must implement the object layer concept.
|
||||
template <typename BaseLayerT> class IRCompileLayer {
|
||||
/// This layer immediately compiles each IR module added via addModule to an
|
||||
/// object file and adds this module file to the layer below, which must
|
||||
/// implement the object layer concept.
|
||||
template <typename BaseLayerT, typename CompileFtor>
|
||||
class IRCompileLayer {
|
||||
public:
|
||||
typedef std::function<object::OwningBinary<object::ObjectFile>(Module &)>
|
||||
CompileFtor;
|
||||
|
||||
private:
|
||||
typedef typename BaseLayerT::ObjSetHandleT ObjSetHandleT;
|
||||
|
||||
public:
|
||||
/// @brief Handle to a set of compiled modules.
|
||||
typedef ObjSetHandleT ModuleSetHandleT;
|
||||
/// @brief Handle to a compiled module.
|
||||
using ModuleHandleT = typename BaseLayerT::ObjHandleT;
|
||||
|
||||
/// @brief Construct an IRCompileLayer with the given BaseLayer, which must
|
||||
/// implement the ObjectLayer concept.
|
||||
IRCompileLayer(BaseLayerT &BaseLayer, CompileFtor Compile)
|
||||
: BaseLayer(BaseLayer), Compile(std::move(Compile)), ObjCache(nullptr) {}
|
||||
: BaseLayer(BaseLayer), Compile(std::move(Compile)) {}
|
||||
|
||||
/// @brief Set an ObjectCache to query before compiling.
|
||||
void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; }
|
||||
/// @brief Get a reference to the compiler functor.
|
||||
CompileFtor& getCompiler() { return Compile; }
|
||||
|
||||
/// @brief Compile each module in the given module set, then add the resulting
|
||||
/// set of objects to the base layer along with the memory manager and
|
||||
/// symbol resolver.
|
||||
/// @brief Compile the module, and add the resulting object to the base layer
|
||||
/// along with the given memory manager and symbol resolver.
|
||||
///
|
||||
/// @return A handle for the added modules.
|
||||
template <typename ModuleSetT, typename MemoryManagerPtrT,
|
||||
typename SymbolResolverPtrT>
|
||||
ModuleSetHandleT addModuleSet(ModuleSetT Ms,
|
||||
MemoryManagerPtrT MemMgr,
|
||||
SymbolResolverPtrT Resolver) {
|
||||
std::vector<std::unique_ptr<object::OwningBinary<object::ObjectFile>>>
|
||||
Objects;
|
||||
|
||||
for (const auto &M : Ms) {
|
||||
auto Object =
|
||||
llvm::make_unique<object::OwningBinary<object::ObjectFile>>();
|
||||
|
||||
if (ObjCache)
|
||||
*Object = tryToLoadFromObjectCache(*M);
|
||||
|
||||
if (!Object->getBinary()) {
|
||||
*Object = Compile(*M);
|
||||
if (ObjCache)
|
||||
ObjCache->notifyObjectCompiled(&*M,
|
||||
Object->getBinary()->getMemoryBufferRef());
|
||||
}
|
||||
|
||||
Objects.push_back(std::move(Object));
|
||||
}
|
||||
|
||||
ModuleSetHandleT H =
|
||||
BaseLayer.addObjectSet(std::move(Objects), std::move(MemMgr),
|
||||
std::move(Resolver));
|
||||
|
||||
return H;
|
||||
/// @return A handle for the added module.
|
||||
template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
|
||||
ModuleHandleT addModule(std::shared_ptr<Module> M,
|
||||
MemoryManagerPtrT MemMgr,
|
||||
SymbolResolverPtrT 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));
|
||||
}
|
||||
|
||||
/// @brief Remove the module set associated with the handle H.
|
||||
void removeModuleSet(ModuleSetHandleT H) { BaseLayer.removeObjectSet(H); }
|
||||
/// @brief Remove the module associated with the handle H.
|
||||
void removeModule(ModuleHandleT H) { BaseLayer.removeObject(H); }
|
||||
|
||||
/// @brief Search for the given named symbol.
|
||||
/// @param Name The name of the symbol to search for.
|
||||
@ -96,51 +71,33 @@ template <typename BaseLayerT> class IRCompileLayer {
|
||||
return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
|
||||
}
|
||||
|
||||
/// @brief Get the address of the given symbol in the context of the set of
|
||||
/// compiled modules 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.
|
||||
/// @brief Get the address of the given symbol in compiled module represented
|
||||
/// by the handle H. This call is forwarded to the base layer's
|
||||
/// implementation.
|
||||
/// @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);
|
||||
}
|
||||
|
||||
/// @brief Immediately emit and finalize the moduleOB set represented by the
|
||||
/// given handle.
|
||||
/// @param H Handle for module set to emit/finalize.
|
||||
void emitAndFinalize(ModuleSetHandleT H) {
|
||||
/// @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);
|
||||
}
|
||||
|
||||
private:
|
||||
object::OwningBinary<object::ObjectFile>
|
||||
tryToLoadFromObjectCache(const Module &M) {
|
||||
std::unique_ptr<MemoryBuffer> ObjBuffer = ObjCache->getObject(&M);
|
||||
if (!ObjBuffer)
|
||||
return object::OwningBinary<object::ObjectFile>();
|
||||
|
||||
Expected<std::unique_ptr<object::ObjectFile>> Obj =
|
||||
object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
|
||||
if (!Obj) {
|
||||
// TODO: Actually report errors helpfully.
|
||||
consumeError(Obj.takeError());
|
||||
return object::OwningBinary<object::ObjectFile>();
|
||||
}
|
||||
|
||||
return object::OwningBinary<object::ObjectFile>(std::move(*Obj),
|
||||
std::move(ObjBuffer));
|
||||
}
|
||||
|
||||
BaseLayerT &BaseLayer;
|
||||
CompileFtor Compile;
|
||||
ObjectCache *ObjCache;
|
||||
};
|
||||
|
||||
} // End namespace orc.
|
||||
} // End namespace llvm.
|
||||
} // end namespace orc
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_EXECUTIONENGINE_ORC_IRCOMPILINGLAYER_H
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user