mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-06-29 00:30:47 +00:00
Updating branches/google/testing to r239765
git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/google/testing@240103 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
commit
ca2e7a44ec
|
@ -32,15 +32,23 @@ project(LLVM)
|
|||
set(LLVM_PARALLEL_COMPILE_JOBS "" CACHE STRING
|
||||
"Define the maximum number of concurrent compilation jobs.")
|
||||
if(LLVM_PARALLEL_COMPILE_JOBS)
|
||||
set_property(GLOBAL APPEND PROPERTY JOB_POOLS compile_job_pool=${LLVM_PARALLEL_COMPILE_JOBS})
|
||||
set(CMAKE_JOB_POOL_COMPILE compile_job_pool)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.0 OR NOT CMAKE_MAKE_PROGRAM MATCHES "ninja$")
|
||||
message(WARNING "Job pooling is only available with Ninja generators and CMake 3.0 and later.")
|
||||
else()
|
||||
set_property(GLOBAL APPEND PROPERTY JOB_POOLS compile_job_pool=${LLVM_PARALLEL_COMPILE_JOBS})
|
||||
set(CMAKE_JOB_POOL_COMPILE compile_job_pool)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(LLVM_PARALLEL_LINK_JOBS "" CACHE STRING
|
||||
"Define the maximum number of concurrent link jobs.")
|
||||
if(LLVM_PARALLEL_LINK_JOBS)
|
||||
set_property(GLOBAL APPEND PROPERTY JOB_POOLS link_job_pool=${LLVM_PARALLEL_LINK_JOBS})
|
||||
set(CMAKE_JOB_POOL_LINK link_job_pool)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.0 OR NOT CMAKE_MAKE_PROGRAM MATCHES "ninja$")
|
||||
message(WARNING "Job pooling is only available with Ninja generators and CMake 3.0 and later.")
|
||||
else()
|
||||
set_property(GLOBAL APPEND PROPERTY JOB_POOLS link_job_pool=${LLVM_PARALLEL_LINK_JOBS})
|
||||
set(CMAKE_JOB_POOL_LINK link_job_pool)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Add path for custom modules
|
||||
|
@ -168,14 +176,15 @@ set(LLVM_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/include)
|
|||
|
||||
set(LLVM_ALL_TARGETS
|
||||
AArch64
|
||||
AMDGPU
|
||||
ARM
|
||||
BPF
|
||||
CppBackend
|
||||
Hexagon
|
||||
Mips
|
||||
MSP430
|
||||
NVPTX
|
||||
PowerPC
|
||||
R600
|
||||
Sparc
|
||||
SystemZ
|
||||
X86
|
||||
|
|
|
@ -1097,7 +1097,7 @@ if test "$llvm_cv_enable_crash_overrides" = "yes" ; then
|
|||
fi
|
||||
|
||||
dnl List all possible targets
|
||||
ALL_TARGETS="X86 Sparc PowerPC ARM AArch64 Mips XCore MSP430 CppBackend NVPTX Hexagon SystemZ R600"
|
||||
ALL_TARGETS="X86 Sparc PowerPC ARM AArch64 Mips XCore MSP430 CppBackend NVPTX Hexagon SystemZ AMDGPU BPF"
|
||||
AC_SUBST(ALL_TARGETS,$ALL_TARGETS)
|
||||
|
||||
dnl Allow specific targets to be specified for building (or not)
|
||||
|
@ -1105,7 +1105,7 @@ TARGETS_TO_BUILD=""
|
|||
AC_ARG_ENABLE([targets],AS_HELP_STRING([--enable-targets],
|
||||
[Build specific host targets: all or target1,target2,... Valid targets are:
|
||||
host, x86, x86_64, sparc, powerpc, arm64, arm, aarch64, mips, hexagon,
|
||||
xcore, msp430, nvptx, systemz, r600, and cpp (default=all)]),,
|
||||
xcore, msp430, nvptx, systemz, r600, bpf, and cpp (default=all)]),,
|
||||
enableval=all)
|
||||
if test "$enableval" = host-only ; then
|
||||
enableval=host
|
||||
|
@ -1121,6 +1121,7 @@ case "$enableval" in
|
|||
aarch64) TARGETS_TO_BUILD="AArch64 $TARGETS_TO_BUILD" ;;
|
||||
arm64) TARGETS_TO_BUILD="AArch64 $TARGETS_TO_BUILD" ;;
|
||||
arm) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;;
|
||||
bpf) TARGETS_TO_BUILD="BPF $TARGETS_TO_BUILD" ;;
|
||||
mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;;
|
||||
mipsel) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;;
|
||||
mips64) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;;
|
||||
|
@ -1131,7 +1132,8 @@ case "$enableval" in
|
|||
hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
|
||||
nvptx) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;;
|
||||
systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;;
|
||||
r600) TARGETS_TO_BUILD="R600 $TARGETS_TO_BUILD" ;;
|
||||
amdgpu) TARGETS_TO_BUILD="AMDGPU $TARGETS_TO_BUILD" ;;
|
||||
r600) TARGETS_TO_BUILD="AMDGPU $TARGETS_TO_BUILD" ;;
|
||||
host) case "$llvm_cv_target_arch" in
|
||||
x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
|
||||
x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
|
||||
|
|
|
@ -228,6 +228,76 @@ function(set_output_directory target bindir libdir)
|
|||
endif()
|
||||
endfunction()
|
||||
|
||||
# If on Windows and building with MSVC, add the resource script containing the
|
||||
# VERSIONINFO data to the project. This embeds version resource information
|
||||
# into the output .exe or .dll.
|
||||
# TODO: Enable for MinGW Windows builds too.
|
||||
#
|
||||
function(add_windows_version_resource_file OUT_VAR)
|
||||
set(sources ${ARGN})
|
||||
if (MSVC)
|
||||
set(resource_file ${LLVM_SOURCE_DIR}/resources/windows_version_resource.rc)
|
||||
if(EXISTS ${resource_file})
|
||||
set(sources ${sources} ${resource_file})
|
||||
source_group("Resource Files" ${resource_file})
|
||||
set(windows_resource_file ${resource_file} PARENT_SCOPE)
|
||||
endif()
|
||||
endif(MSVC)
|
||||
|
||||
set(${OUT_VAR} ${sources} PARENT_SCOPE)
|
||||
endfunction(add_windows_version_resource_file)
|
||||
|
||||
# set_windows_version_resource_properties(name resource_file...
|
||||
# VERSION_MAJOR int
|
||||
# Optional major version number (defaults to LLVM_VERSION_MAJOR)
|
||||
# VERSION_MINOR int
|
||||
# Optional minor version number (defaults to LLVM_VERSION_MINOR)
|
||||
# VERSION_PATCHLEVEL int
|
||||
# Optional patchlevel version number (defaults to LLVM_VERSION_PATCH)
|
||||
# VERSION_STRING
|
||||
# Optional version string (defaults to PACKAGE_VERSION)
|
||||
# PRODUCT_NAME
|
||||
# Optional product name string (defaults to "LLVM")
|
||||
# )
|
||||
function(set_windows_version_resource_properties name resource_file)
|
||||
cmake_parse_arguments(ARG
|
||||
""
|
||||
"VERSION_MAJOR;VERSION_MINOR;VERSION_PATCHLEVEL;VERSION_STRING;PRODUCT_NAME"
|
||||
""
|
||||
${ARGN})
|
||||
|
||||
if (NOT DEFINED ARG_VERSION_MAJOR)
|
||||
set(ARG_VERSION_MAJOR ${LLVM_VERSION_MAJOR})
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED ARG_VERSION_MINOR)
|
||||
set(ARG_VERSION_MINOR ${LLVM_VERSION_MINOR})
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED ARG_VERSION_PATCHLEVEL)
|
||||
set(ARG_VERSION_PATCHLEVEL ${LLVM_VERSION_PATCH})
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED ARG_VERSION_STRING)
|
||||
set(ARG_VERSION_STRING ${PACKAGE_VERSION})
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED ARG_PRODUCT_NAME)
|
||||
set(ARG_PRODUCT_NAME "LLVM")
|
||||
endif()
|
||||
|
||||
set_property(SOURCE ${resource_file}
|
||||
PROPERTY COMPILE_DEFINITIONS
|
||||
"RC_VERSION_FIELD_1=${ARG_VERSION_MAJOR}"
|
||||
"RC_VERSION_FIELD_2=${ARG_VERSION_MINOR}"
|
||||
"RC_VERSION_FIELD_3=${ARG_VERSION_PATCHLEVEL}"
|
||||
"RC_VERSION_FIELD_4=0"
|
||||
"RC_FILE_VERSION=\"${ARG_VERSION_STRING}\""
|
||||
"RC_INTERNAL_NAME=\"${name}\""
|
||||
"RC_PRODUCT_NAME=\"${ARG_PRODUCT_NAME}\""
|
||||
"RC_PRODUCT_VERSION=\"${ARG_VERSION_STRING}\"")
|
||||
endfunction(set_windows_version_resource_properties)
|
||||
|
||||
# llvm_add_library(name sources...
|
||||
# SHARED;STATIC
|
||||
# STATIC by default w/o BUILD_SHARED_LIBS.
|
||||
|
@ -316,10 +386,17 @@ function(llvm_add_library name)
|
|||
if(ARG_MODULE)
|
||||
add_library(${name} MODULE ${ALL_FILES})
|
||||
elseif(ARG_SHARED)
|
||||
add_windows_version_resource_file(ALL_FILES ${ALL_FILES})
|
||||
add_library(${name} SHARED ${ALL_FILES})
|
||||
else()
|
||||
add_library(${name} STATIC ${ALL_FILES})
|
||||
endif()
|
||||
|
||||
if(DEFINED windows_resource_file)
|
||||
set_windows_version_resource_properties(${name} ${windows_resource_file})
|
||||
set(windows_resource_file ${windows_resource_file} PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
set_output_directory(${name} ${LLVM_RUNTIME_OUTPUT_INTDIR} ${LLVM_LIBRARY_OUTPUT_INTDIR})
|
||||
llvm_update_compile_flags(${name})
|
||||
add_link_opts( ${name} )
|
||||
|
@ -482,11 +559,18 @@ endmacro(add_llvm_loadable_module name)
|
|||
|
||||
macro(add_llvm_executable name)
|
||||
llvm_process_sources( ALL_FILES ${ARGN} )
|
||||
add_windows_version_resource_file(ALL_FILES ${ALL_FILES})
|
||||
|
||||
if( EXCLUDE_FROM_ALL )
|
||||
add_executable(${name} EXCLUDE_FROM_ALL ${ALL_FILES})
|
||||
else()
|
||||
add_executable(${name} ${ALL_FILES})
|
||||
endif()
|
||||
|
||||
if(DEFINED windows_resource_file)
|
||||
set_windows_version_resource_properties(${name} ${windows_resource_file})
|
||||
endif()
|
||||
|
||||
llvm_update_compile_flags(${name})
|
||||
add_link_opts( ${name} )
|
||||
|
||||
|
|
|
@ -149,7 +149,7 @@ function(add_ocaml_library name)
|
|||
"-I" "${LLVM_LIBRARY_DIR}/ocaml/"
|
||||
"-dump" "${bin}/${name}.odoc"
|
||||
${ocaml_pkgs} ${ocaml_inputs}
|
||||
DEPENDS ${ocaml_inputs}
|
||||
DEPENDS ${ocaml_inputs} ${ocaml_outputs}
|
||||
COMMENT "Building OCaml documentation for ${name}"
|
||||
VERBATIM)
|
||||
|
||||
|
|
10
configure
vendored
10
configure
vendored
|
@ -1462,8 +1462,8 @@ Optional Features:
|
|||
--enable-targets Build specific host targets: all or
|
||||
target1,target2,... Valid targets are: host, x86,
|
||||
x86_64, sparc, powerpc, arm64, arm, aarch64, mips,
|
||||
hexagon, xcore, msp430, nvptx, systemz, r600, and
|
||||
cpp (default=all)
|
||||
hexagon, xcore, msp430, nvptx, systemz, r600, bpf,
|
||||
and cpp (default=all)
|
||||
--enable-experimental-targets
|
||||
Build experimental host targets: disable or
|
||||
target1,target2,... (default=disable)
|
||||
|
@ -5628,7 +5628,7 @@ _ACEOF
|
|||
|
||||
fi
|
||||
|
||||
ALL_TARGETS="X86 Sparc PowerPC ARM AArch64 Mips XCore MSP430 CppBackend NVPTX Hexagon SystemZ R600"
|
||||
ALL_TARGETS="X86 Sparc PowerPC ARM AArch64 Mips XCore MSP430 CppBackend NVPTX Hexagon SystemZ AMDGPU BPF"
|
||||
ALL_TARGETS=$ALL_TARGETS
|
||||
|
||||
|
||||
|
@ -5654,6 +5654,7 @@ case "$enableval" in
|
|||
aarch64) TARGETS_TO_BUILD="AArch64 $TARGETS_TO_BUILD" ;;
|
||||
arm64) TARGETS_TO_BUILD="AArch64 $TARGETS_TO_BUILD" ;;
|
||||
arm) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;;
|
||||
bpf) TARGETS_TO_BUILD="BPF $TARGETS_TO_BUILD" ;;
|
||||
mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;;
|
||||
mipsel) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;;
|
||||
mips64) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;;
|
||||
|
@ -5664,7 +5665,8 @@ case "$enableval" in
|
|||
hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
|
||||
nvptx) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;;
|
||||
systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;;
|
||||
r600) TARGETS_TO_BUILD="R600 $TARGETS_TO_BUILD" ;;
|
||||
amdgpu) TARGETS_TO_BUILD="AMDGPU $TARGETS_TO_BUILD" ;;
|
||||
r600) TARGETS_TO_BUILD="AMDGPU $TARGETS_TO_BUILD" ;;
|
||||
host) case "$llvm_cv_target_arch" in
|
||||
x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
|
||||
x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
============================
|
||||
User Guide for R600 Back-end
|
||||
============================
|
||||
==============================
|
||||
User Guide for AMDGPU Back-end
|
||||
==============================
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
The R600 back-end provides ISA code generation for AMD GPUs, starting with
|
||||
The AMDGPU back-end provides ISA code generation for AMD GPUs, starting with
|
||||
the R600 family up until the current Volcanic Islands (GCN Gen 3).
|
||||
|
||||
|
||||
|
@ -14,7 +14,7 @@ Assembler
|
|||
|
||||
The assembler is currently considered experimental.
|
||||
|
||||
For syntax examples look in test/MC/R600.
|
||||
For syntax examples look in test/MC/AMDGPU.
|
||||
|
||||
Below some of the currently supported features (modulo bugs). These
|
||||
all apply to the Southern Islands ISA, Sea Islands and Volcanic Islands
|
||||
|
@ -24,6 +24,11 @@ DS Instructions
|
|||
---------------
|
||||
All DS instructions are supported.
|
||||
|
||||
FLAT Instructions
|
||||
------------------
|
||||
These instructions are only present in the Sea Islands and Volcanic Islands
|
||||
instruction set. All FLAT instructions are supported for these architectures
|
||||
|
||||
MUBUF Instructions
|
||||
------------------
|
||||
All non-atomic MUBUF instructions are supported.
|
|
@ -68,8 +68,8 @@ Other documents, collections, notes
|
|||
* `PowerPC64 alignment of long doubles (from GCC) <http://gcc.gnu.org/ml/gcc-patches/2003-09/msg00997.html>`_
|
||||
* `Long branch stubs for powerpc64-linux (from binutils) <http://sources.redhat.com/ml/binutils/2002-04/msg00573.html>`_
|
||||
|
||||
R600
|
||||
----
|
||||
AMDGPU
|
||||
------
|
||||
|
||||
* `AMD R6xx shader ISA <http://developer.amd.com/wordpress/media/2012/10/R600_Instruction_Set_Architecture.pdf>`_
|
||||
* `AMD R7xx shader ISA <http://developer.amd.com/wordpress/media/2012/10/R700-Family_Instruction_Set_Architecture.pdf>`_
|
||||
|
|
54
docs/FaultMaps.rst
Normal file
54
docs/FaultMaps.rst
Normal file
|
@ -0,0 +1,54 @@
|
|||
==============================
|
||||
FaultMaps and implicit checks
|
||||
==============================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 2
|
||||
|
||||
Motivation
|
||||
==========
|
||||
|
||||
Code generated by managed language runtimes tend to have checks that
|
||||
are required for safety but never fail in practice. In such cases, it
|
||||
is profitable to make the non-failing case cheaper even if it makes
|
||||
the failing case significantly more expensive. This asymmetry can be
|
||||
exploited by folding such safety checks into operations that can be
|
||||
made to fault reliably if the check would have failed, and recovering
|
||||
from such a fault by using a signal handler.
|
||||
|
||||
For example, Java requires null checks on objects before they are read
|
||||
from or written to. If the object is ``null`` then a
|
||||
``NullPointerException`` has to be thrown, interrupting normal
|
||||
execution. In practice, however, dereferencing a ``null`` pointer is
|
||||
extremely rare in well-behaved Java programs, and typically the null
|
||||
check can be folded into a nearby memory operation that operates on
|
||||
the same memory location.
|
||||
|
||||
The Fault Map Section
|
||||
=====================
|
||||
|
||||
Information about implicit checks generated by LLVM are put in a
|
||||
special "fault map" section. On Darwin this section is named
|
||||
``__llvm_faultmaps``.
|
||||
|
||||
The format of this section is
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
Header {
|
||||
uint8 : Fault Map Version (current version is 1)
|
||||
uint8 : Reserved (expected to be 0)
|
||||
uint16 : Reserved (expected to be 0)
|
||||
}
|
||||
uint32 : NumFunctions
|
||||
FunctionInfo[NumFunctions] {
|
||||
uint64 : FunctionAddress
|
||||
uint32 : NumFaultingPCs
|
||||
uint32 : Reserved (expected to be 0)
|
||||
FunctionFaultInfo[NumFaultingPCs] {
|
||||
uint32 : FaultKind = FaultMaps::FaultingLoad (only legal value currently)
|
||||
uint32 : FaultingPCOffset
|
||||
uint32 : handlerPCOffset
|
||||
}
|
||||
}
|
|
@ -711,7 +711,7 @@ used by people developing LLVM.
|
|||
| | as ``LLVM_ALL_TARGETS``, and can be set to include |
|
||||
| | out-of-tree targets. The default value includes: |
|
||||
| | ``AArch64, ARM, CppBackend, Hexagon, |
|
||||
| | Mips, MSP430, NVPTX, PowerPC, R600, Sparc, |
|
||||
| | Mips, MSP430, NVPTX, PowerPC, AMDGPU, Sparc, |
|
||||
| | SystemZ, X86, XCore``. |
|
||||
+-------------------------+----------------------------------------------------+
|
||||
| LLVM_ENABLE_DOXYGEN | Build doxygen-based documentation from the source |
|
||||
|
|
|
@ -1319,6 +1319,15 @@ example:
|
|||
``setjmp`` is an example of such a function. The compiler disables
|
||||
some optimizations (like tail calls) in the caller of these
|
||||
functions.
|
||||
``safestack``
|
||||
This attribute indicates that
|
||||
`SafeStack <http://clang.llvm.org/docs/SafeStack.html>`_
|
||||
protection is enabled for this function.
|
||||
|
||||
If a function that has a ``safestack`` attribute is inlined into a
|
||||
function that doesn't have a ``safestack`` attribute or which has an
|
||||
``ssp``, ``sspstrong`` or ``sspreq`` attribute, then the resulting
|
||||
function will have a ``safestack`` attribute.
|
||||
``sanitize_address``
|
||||
This attribute indicates that AddressSanitizer checks
|
||||
(dynamic address safety analysis) are enabled for this function.
|
||||
|
|
|
@ -131,6 +131,10 @@ L
|
|||
**LCSSA**
|
||||
Loop-Closed Static Single Assignment Form
|
||||
|
||||
**LGTM**
|
||||
"Looks Good To Me". In a review thread, this indicates that the
|
||||
reviewer thinks that the patch is okay to commit.
|
||||
|
||||
**LICM**
|
||||
Loop Invariant Code Motion
|
||||
|
||||
|
|
|
@ -190,7 +190,7 @@ supported include:
|
|||
for 'a' in 'c.' This operation is analogous to $(subst) in GNU make.
|
||||
|
||||
``!foreach(a, b, c)``
|
||||
For each member 'b' of dag or list 'a' apply operator 'c.' 'b' is a dummy
|
||||
For each member of dag or list 'b' apply operator 'c.' 'a' is a dummy
|
||||
variable that should be declared as a member variable of an instantiated
|
||||
class. This operation is analogous to $(foreach) in GNU make.
|
||||
|
||||
|
|
|
@ -252,7 +252,7 @@ For API clients and LLVM developers.
|
|||
WritingAnLLVMPass
|
||||
HowToUseAttributes
|
||||
NVPTXUsage
|
||||
R600Usage
|
||||
AMDGPUUsage
|
||||
StackMaps
|
||||
InAlloca
|
||||
BigEndianNEON
|
||||
|
@ -260,6 +260,7 @@ For API clients and LLVM developers.
|
|||
Statepoints
|
||||
MergeFunctions
|
||||
BitSets
|
||||
FaultMaps
|
||||
|
||||
:doc:`WritingAnLLVMPass`
|
||||
Information on how to write LLVM transformations and analyses.
|
||||
|
@ -338,8 +339,8 @@ For API clients and LLVM developers.
|
|||
:doc:`NVPTXUsage`
|
||||
This document describes using the NVPTX back-end to compile GPU kernels.
|
||||
|
||||
:doc:`R600Usage`
|
||||
This document describes how to use the R600 back-end.
|
||||
:doc:`AMDGPUUsage`
|
||||
This document describes how to use the AMDGPU back-end.
|
||||
|
||||
:doc:`StackMaps`
|
||||
LLVM support for mapping instruction addresses to the location of
|
||||
|
@ -362,6 +363,9 @@ For API clients and LLVM developers.
|
|||
:doc:`InAlloca`
|
||||
Description of the ``inalloca`` argument attribute.
|
||||
|
||||
:doc:`FaultMaps`
|
||||
LLVM support for folding control flow into faulting machine instructions.
|
||||
|
||||
Development Process Documentation
|
||||
=================================
|
||||
|
||||
|
|
|
@ -997,6 +997,13 @@ unsigned LLVMCountStructElementTypes(LLVMTypeRef StructTy);
|
|||
*/
|
||||
void LLVMGetStructElementTypes(LLVMTypeRef StructTy, LLVMTypeRef *Dest);
|
||||
|
||||
/**
|
||||
* Get the type of the element at a given index in the structure.
|
||||
*
|
||||
* @see llvm::StructType::getTypeAtIndex()
|
||||
*/
|
||||
LLVMTypeRef LLVMStructGetTypeAtIndex(LLVMTypeRef StructTy, unsigned i);
|
||||
|
||||
/**
|
||||
* Determine whether a structure is packed.
|
||||
*
|
||||
|
|
|
@ -58,6 +58,24 @@ LLVMBool LLVMLoadLibraryPermanently(const char* Filename);
|
|||
void LLVMParseCommandLineOptions(int argc, const char *const *argv,
|
||||
const char *Overview);
|
||||
|
||||
/**
|
||||
* This function will search through all previously loaded dynamic
|
||||
* libraries for the symbol \p symbolName. If it is found, the address of
|
||||
* that symbol is returned. If not, null is returned.
|
||||
*
|
||||
* @see sys::DynamicLibrary::SearchForAddressOfSymbol()
|
||||
*/
|
||||
void *LLVMSearchForAddressOfSymbol(const char *symbolName);
|
||||
|
||||
/**
|
||||
* This functions permanently adds the symbol \p symbolName with the
|
||||
* value \p symbolValue. These symbols are searched before any
|
||||
* libraries.
|
||||
*
|
||||
* @see sys::DynamicLibrary::AddSymbol()
|
||||
*/
|
||||
void LLVMAddSymbol(const char *symbolName, void *symbolValue);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -62,7 +62,8 @@ typedef enum {
|
|||
LTO_SYMBOL_SCOPE_HIDDEN = 0x00001000,
|
||||
LTO_SYMBOL_SCOPE_PROTECTED = 0x00002000,
|
||||
LTO_SYMBOL_SCOPE_DEFAULT = 0x00001800,
|
||||
LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN = 0x00002800
|
||||
LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN = 0x00002800,
|
||||
LTO_SYMBOL_COMDAT = 0x00004000
|
||||
} lto_symbol_attributes;
|
||||
|
||||
/**
|
||||
|
|
|
@ -129,7 +129,7 @@ class APInt {
|
|||
|
||||
/// \brief Clear unused high order bits
|
||||
///
|
||||
/// This method is used internally to clear the to "N" bits in the high order
|
||||
/// This method is used internally to clear the top "N" bits in the high order
|
||||
/// word that are not used by the APInt. This is needed after the most
|
||||
/// significant word is assigned a value to ensure that those bits are
|
||||
/// zero'd out.
|
||||
|
@ -351,8 +351,7 @@ public:
|
|||
/// 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 BitWidth == 1 ? VAL == 0
|
||||
: !isNegative() && countPopulation() == BitWidth - 1;
|
||||
return !isNegative() && countPopulation() == BitWidth - 1;
|
||||
}
|
||||
|
||||
/// \brief Determine if this is the smallest unsigned value.
|
||||
|
@ -366,7 +365,7 @@ public:
|
|||
/// 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 BitWidth == 1 ? VAL == 1 : isNegative() && isPowerOf2();
|
||||
return isNegative() && isPowerOf2();
|
||||
}
|
||||
|
||||
/// \brief Check if this APInt has an N-bits unsigned integer value.
|
||||
|
@ -796,7 +795,7 @@ public:
|
|||
|
||||
/// \brief Bitwise OR function.
|
||||
///
|
||||
/// Performs a bitwise or on *this and RHS. This is implemented bny simply
|
||||
/// Performs a bitwise or on *this and RHS. This is implemented by simply
|
||||
/// calling operator|.
|
||||
///
|
||||
/// \returns An APInt value representing the bitwise OR of *this and RHS.
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace llvm {
|
||||
|
|
|
@ -50,7 +50,8 @@ public:
|
|||
armeb, // ARM (big endian): armeb
|
||||
aarch64, // AArch64 (little endian): aarch64
|
||||
aarch64_be, // AArch64 (big endian): aarch64_be
|
||||
bpf, // eBPF or extended BPF or 64-bit BPF (little endian)
|
||||
bpfel, // eBPF or extended BPF or 64-bit BPF (little endian)
|
||||
bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian)
|
||||
hexagon, // Hexagon: hexagon
|
||||
mips, // MIPS: mips, mipsallegrex
|
||||
mipsel, // MIPSEL: mipsel, mipsallegrexel
|
||||
|
@ -83,7 +84,8 @@ public:
|
|||
spir, // SPIR: standard portable IR for OpenCL 32-bit version
|
||||
spir64, // SPIR: standard portable IR for OpenCL 64-bit version
|
||||
kalimba, // Kalimba: generic kalimba
|
||||
LastArchType = kalimba
|
||||
shave, // SHAVE: Movidius vector VLIW processors
|
||||
LastArchType = shave
|
||||
};
|
||||
enum SubArchType {
|
||||
NoSubArch,
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/IR/CallSite.h"
|
||||
#include "llvm/IR/Metadata.h"
|
||||
#include "llvm/Analysis/MemoryLocation.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
|
@ -82,7 +83,7 @@ public:
|
|||
/// UnknownSize - This is a special value which can be used with the
|
||||
/// size arguments in alias queries to indicate that the caller does not
|
||||
/// know the sizes of the potential memory references.
|
||||
static uint64_t const UnknownSize = ~UINT64_C(0);
|
||||
static uint64_t const UnknownSize = MemoryLocation::UnknownSize;
|
||||
|
||||
/// getTargetLibraryInfo - Return a pointer to the current TargetLibraryInfo
|
||||
/// object, or null if no TargetLibraryInfo object is available.
|
||||
|
@ -98,70 +99,9 @@ public:
|
|||
/// Alias Queries...
|
||||
///
|
||||
|
||||
/// Location - A description of a memory location.
|
||||
struct Location {
|
||||
/// Ptr - The address of the start of the location.
|
||||
const Value *Ptr;
|
||||
/// Size - The maximum size of the location, in address-units, or
|
||||
/// UnknownSize if the size is not known. Note that an unknown size does
|
||||
/// not mean the pointer aliases the entire virtual address space, because
|
||||
/// there are restrictions on stepping out of one object and into another.
|
||||
/// See http://llvm.org/docs/LangRef.html#pointeraliasing
|
||||
uint64_t Size;
|
||||
/// AATags - The metadata nodes which describes the aliasing of the
|
||||
/// location (each member is null if that kind of information is
|
||||
/// unavailable)..
|
||||
AAMDNodes AATags;
|
||||
|
||||
explicit Location(const Value *P = nullptr, uint64_t S = UnknownSize,
|
||||
const AAMDNodes &N = AAMDNodes())
|
||||
: Ptr(P), Size(S), AATags(N) {}
|
||||
|
||||
Location getWithNewPtr(const Value *NewPtr) const {
|
||||
Location Copy(*this);
|
||||
Copy.Ptr = NewPtr;
|
||||
return Copy;
|
||||
}
|
||||
|
||||
Location getWithNewSize(uint64_t NewSize) const {
|
||||
Location Copy(*this);
|
||||
Copy.Size = NewSize;
|
||||
return Copy;
|
||||
}
|
||||
|
||||
Location getWithoutAATags() const {
|
||||
Location Copy(*this);
|
||||
Copy.AATags = AAMDNodes();
|
||||
return Copy;
|
||||
}
|
||||
|
||||
bool operator==(const AliasAnalysis::Location &Other) const {
|
||||
return Ptr == Other.Ptr && Size == Other.Size && AATags == Other.AATags;
|
||||
}
|
||||
};
|
||||
|
||||
/// getLocation - Fill in Loc with information about the memory reference by
|
||||
/// the given instruction.
|
||||
Location getLocation(const LoadInst *LI);
|
||||
Location getLocation(const StoreInst *SI);
|
||||
Location getLocation(const VAArgInst *VI);
|
||||
Location getLocation(const AtomicCmpXchgInst *CXI);
|
||||
Location getLocation(const AtomicRMWInst *RMWI);
|
||||
static Location getLocationForSource(const MemTransferInst *MTI);
|
||||
static Location getLocationForDest(const MemIntrinsic *MI);
|
||||
Location getLocation(const Instruction *Inst) {
|
||||
if (auto *I = dyn_cast<LoadInst>(Inst))
|
||||
return getLocation(I);
|
||||
else if (auto *I = dyn_cast<StoreInst>(Inst))
|
||||
return getLocation(I);
|
||||
else if (auto *I = dyn_cast<VAArgInst>(Inst))
|
||||
return getLocation(I);
|
||||
else if (auto *I = dyn_cast<AtomicCmpXchgInst>(Inst))
|
||||
return getLocation(I);
|
||||
else if (auto *I = dyn_cast<AtomicRMWInst>(Inst))
|
||||
return getLocation(I);
|
||||
llvm_unreachable("unsupported memory instruction");
|
||||
}
|
||||
/// Legacy typedef for the AA location object. New code should use \c
|
||||
/// MemoryLocation directly.
|
||||
typedef MemoryLocation Location;
|
||||
|
||||
/// Alias analysis result - Either we know for sure that it does not alias, we
|
||||
/// know for sure it must alias, or we don't know anything: The two pointers
|
||||
|
@ -601,28 +541,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
// Specialize DenseMapInfo for Location.
|
||||
template<>
|
||||
struct DenseMapInfo<AliasAnalysis::Location> {
|
||||
static inline AliasAnalysis::Location getEmptyKey() {
|
||||
return AliasAnalysis::Location(DenseMapInfo<const Value *>::getEmptyKey(),
|
||||
0);
|
||||
}
|
||||
static inline AliasAnalysis::Location getTombstoneKey() {
|
||||
return AliasAnalysis::Location(
|
||||
DenseMapInfo<const Value *>::getTombstoneKey(), 0);
|
||||
}
|
||||
static unsigned getHashValue(const AliasAnalysis::Location &Val) {
|
||||
return DenseMapInfo<const Value *>::getHashValue(Val.Ptr) ^
|
||||
DenseMapInfo<uint64_t>::getHashValue(Val.Size) ^
|
||||
DenseMapInfo<AAMDNodes>::getHashValue(Val.AATags);
|
||||
}
|
||||
static bool isEqual(const AliasAnalysis::Location &LHS,
|
||||
const AliasAnalysis::Location &RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
};
|
||||
|
||||
/// isNoAliasCall - Return true if this pointer is returned by a noalias
|
||||
/// function.
|
||||
bool isNoAliasCall(const Value *V);
|
||||
|
|
|
@ -191,8 +191,8 @@ public:
|
|||
|
||||
/// \brief Data about a loop.
|
||||
///
|
||||
/// Contains the data necessary to represent represent a loop as a
|
||||
/// pseudo-node once it's packaged.
|
||||
/// Contains the data necessary to represent a loop as a pseudo-node once it's
|
||||
/// packaged.
|
||||
struct LoopData {
|
||||
typedef SmallVector<std::pair<BlockNode, BlockMass>, 4> ExitMap;
|
||||
typedef SmallVector<BlockNode, 4> NodeList;
|
||||
|
@ -930,7 +930,7 @@ void BlockFrequencyInfoImpl<BT>::doFunction(const FunctionT *F,
|
|||
initializeRPOT();
|
||||
initializeLoops();
|
||||
|
||||
// Visit loops in post-order to find thelocal mass distribution, and then do
|
||||
// Visit loops in post-order to find the local mass distribution, and then do
|
||||
// the full function.
|
||||
computeMassInLoops();
|
||||
computeMassInFunction();
|
||||
|
|
|
@ -345,6 +345,10 @@ public:
|
|||
/// to needsChecking.
|
||||
bool needsAnyChecking(const SmallVectorImpl<int> *PtrPartition) const;
|
||||
|
||||
/// \brief Returns the number of run-time checks required according to
|
||||
/// needsChecking.
|
||||
unsigned getNumberOfChecks(const SmallVectorImpl<int> *PtrPartition) const;
|
||||
|
||||
/// \brief Print the list run-time memory checks necessary.
|
||||
///
|
||||
/// If \p PtrPartition is set, it contains the partition number for
|
||||
|
@ -385,7 +389,10 @@ public:
|
|||
|
||||
/// \brief Number of memchecks required to prove independence of otherwise
|
||||
/// may-alias pointers.
|
||||
unsigned getNumRuntimePointerChecks() const { return NumComparisons; }
|
||||
unsigned getNumRuntimePointerChecks(
|
||||
const SmallVectorImpl<int> *PtrPartition = nullptr) const {
|
||||
return PtrRtCheck.getNumberOfChecks(PtrPartition);
|
||||
}
|
||||
|
||||
/// Return true if the block BB needs to be predicated in order for the loop
|
||||
/// to be vectorized.
|
||||
|
@ -460,10 +467,6 @@ private:
|
|||
/// loop-independent and loop-carried dependences between memory accesses.
|
||||
MemoryDepChecker DepChecker;
|
||||
|
||||
/// \brief Number of memchecks required to prove independence of otherwise
|
||||
/// may-alias pointers
|
||||
unsigned NumComparisons;
|
||||
|
||||
Loop *TheLoop;
|
||||
ScalarEvolution *SE;
|
||||
const DataLayout &DL;
|
||||
|
@ -501,6 +504,11 @@ const SCEV *replaceSymbolicStrideSCEV(ScalarEvolution *SE,
|
|||
const ValueToValueMap &PtrToStride,
|
||||
Value *Ptr, Value *OrigPtr = nullptr);
|
||||
|
||||
/// \brief Check the stride of the pointer and ensure that it does not wrap in
|
||||
/// the address space.
|
||||
int isStridedPtr(ScalarEvolution *SE, Value *Ptr, const Loop *Lp,
|
||||
const ValueToValueMap &StridesMap);
|
||||
|
||||
/// \brief This analysis provides dependence information for the memory accesses
|
||||
/// of a loop.
|
||||
///
|
||||
|
|
137
include/llvm/Analysis/MemoryLocation.h
Normal file
137
include/llvm/Analysis/MemoryLocation.h
Normal file
|
@ -0,0 +1,137 @@
|
|||
//===- MemoryLocation.h - Memory location descriptions ----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// \file
|
||||
/// This file provides utility analysis objects describing memory locations.
|
||||
/// These are used both by the Alias Analysis infrastructure and more
|
||||
/// specialized memory analysis layers.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_MEMORYLOCATION_H
|
||||
#define LLVM_ANALYSIS_MEMORYLOCATION_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/IR/CallSite.h"
|
||||
#include "llvm/IR/Metadata.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class LoadInst;
|
||||
class StoreInst;
|
||||
class MemTransferInst;
|
||||
class MemIntrinsic;
|
||||
|
||||
/// Representation for a specific memory location.
|
||||
///
|
||||
/// This abstraction can be used to represent a specific location in memory.
|
||||
/// The goal of the location is to represent enough information to describe
|
||||
/// abstract aliasing, modification, and reference behaviors of whatever
|
||||
/// value(s) are stored in memory at the particular location.
|
||||
///
|
||||
/// The primary user of this interface is LLVM's Alias Analysis, but other
|
||||
/// memory analyses such as MemoryDependence can use it as well.
|
||||
class MemoryLocation {
|
||||
public:
|
||||
/// UnknownSize - This is a special value which can be used with the
|
||||
/// size arguments in alias queries to indicate that the caller does not
|
||||
/// know the sizes of the potential memory references.
|
||||
enum : uint64_t { UnknownSize = ~UINT64_C(0) };
|
||||
|
||||
/// The address of the start of the location.
|
||||
const Value *Ptr;
|
||||
|
||||
/// The maximum size of the location, in address-units, or
|
||||
/// UnknownSize if the size is not known.
|
||||
///
|
||||
/// Note that an unknown size does not mean the pointer aliases the entire
|
||||
/// virtual address space, because there are restrictions on stepping out of
|
||||
/// one object and into another. See
|
||||
/// http://llvm.org/docs/LangRef.html#pointeraliasing
|
||||
uint64_t Size;
|
||||
|
||||
/// The metadata nodes which describes the aliasing of the location (each
|
||||
/// member is null if that kind of information is unavailable).
|
||||
AAMDNodes AATags;
|
||||
|
||||
/// Return a location with information about the memory reference by the given
|
||||
/// instruction.
|
||||
static MemoryLocation get(const LoadInst *LI);
|
||||
static MemoryLocation get(const StoreInst *SI);
|
||||
static MemoryLocation get(const VAArgInst *VI);
|
||||
static MemoryLocation get(const AtomicCmpXchgInst *CXI);
|
||||
static MemoryLocation get(const AtomicRMWInst *RMWI);
|
||||
static MemoryLocation get(const Instruction *Inst) {
|
||||
if (auto *I = dyn_cast<LoadInst>(Inst))
|
||||
return get(I);
|
||||
else if (auto *I = dyn_cast<StoreInst>(Inst))
|
||||
return get(I);
|
||||
else if (auto *I = dyn_cast<VAArgInst>(Inst))
|
||||
return get(I);
|
||||
else if (auto *I = dyn_cast<AtomicCmpXchgInst>(Inst))
|
||||
return get(I);
|
||||
else if (auto *I = dyn_cast<AtomicRMWInst>(Inst))
|
||||
return get(I);
|
||||
llvm_unreachable("unsupported memory instruction");
|
||||
}
|
||||
|
||||
/// Return a location representing the source of a memory transfer.
|
||||
static MemoryLocation getForSource(const MemTransferInst *MTI);
|
||||
|
||||
/// Return a location representing the destination of a memory set or
|
||||
/// transfer.
|
||||
static MemoryLocation getForDest(const MemIntrinsic *MI);
|
||||
|
||||
explicit MemoryLocation(const Value *Ptr = nullptr,
|
||||
uint64_t Size = UnknownSize,
|
||||
const AAMDNodes &AATags = AAMDNodes())
|
||||
: Ptr(Ptr), Size(Size), AATags(AATags) {}
|
||||
|
||||
MemoryLocation getWithNewPtr(const Value *NewPtr) const {
|
||||
MemoryLocation Copy(*this);
|
||||
Copy.Ptr = NewPtr;
|
||||
return Copy;
|
||||
}
|
||||
|
||||
MemoryLocation getWithNewSize(uint64_t NewSize) const {
|
||||
MemoryLocation Copy(*this);
|
||||
Copy.Size = NewSize;
|
||||
return Copy;
|
||||
}
|
||||
|
||||
MemoryLocation getWithoutAATags() const {
|
||||
MemoryLocation Copy(*this);
|
||||
Copy.AATags = AAMDNodes();
|
||||
return Copy;
|
||||
}
|
||||
|
||||
bool operator==(const MemoryLocation &Other) const {
|
||||
return Ptr == Other.Ptr && Size == Other.Size && AATags == Other.AATags;
|
||||
}
|
||||
};
|
||||
|
||||
// Specialize DenseMapInfo for MemoryLocation.
|
||||
template <> struct DenseMapInfo<MemoryLocation> {
|
||||
static inline MemoryLocation getEmptyKey() {
|
||||
return MemoryLocation(DenseMapInfo<const Value *>::getEmptyKey(), 0);
|
||||
}
|
||||
static inline MemoryLocation getTombstoneKey() {
|
||||
return MemoryLocation(DenseMapInfo<const Value *>::getTombstoneKey(), 0);
|
||||
}
|
||||
static unsigned getHashValue(const MemoryLocation &Val) {
|
||||
return DenseMapInfo<const Value *>::getHashValue(Val.Ptr) ^
|
||||
DenseMapInfo<uint64_t>::getHashValue(Val.Size) ^
|
||||
DenseMapInfo<AAMDNodes>::getHashValue(Val.AATags);
|
||||
}
|
||||
static bool isEqual(const MemoryLocation &LHS, const MemoryLocation &RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -221,19 +221,21 @@ public:
|
|||
|
||||
/// Parameters that control the generic loop unrolling transformation.
|
||||
struct UnrollingPreferences {
|
||||
/// The cost threshold for the unrolled loop, compared to
|
||||
/// CodeMetrics.NumInsts aggregated over all basic blocks in the loop body.
|
||||
/// The unrolling factor is set such that the unrolled loop body does not
|
||||
/// exceed this cost. Set this to UINT_MAX to disable the loop body cost
|
||||
/// The cost threshold for the unrolled loop. Should be relative to the
|
||||
/// getUserCost values returned by this API, and the expectation is that
|
||||
/// the unrolled loop's instructions when run through that interface should
|
||||
/// not exceed this cost. However, this is only an estimate. Also, specific
|
||||
/// loops may be unrolled even with a cost above this threshold if deemed
|
||||
/// profitable. Set this to UINT_MAX to disable the loop body cost
|
||||
/// restriction.
|
||||
unsigned Threshold;
|
||||
/// If complete unrolling could help other optimizations (e.g. InstSimplify)
|
||||
/// to remove N% of instructions, then we can go beyond unroll threshold.
|
||||
/// This value set the minimal percent for allowing that.
|
||||
unsigned MinPercentOfOptimized;
|
||||
/// The absolute cost threshold. We won't go beyond this even if complete
|
||||
/// unrolling could result in optimizing out 90% of instructions.
|
||||
unsigned AbsoluteThreshold;
|
||||
/// If complete unrolling will reduce the cost of the loop below its
|
||||
/// expected dynamic cost while rolled by this percentage, apply a discount
|
||||
/// (below) to its unrolled cost.
|
||||
unsigned PercentDynamicCostSavedThreshold;
|
||||
/// The discount applied to the unrolled cost when the *dynamic* cost
|
||||
/// savings of unrolling exceed the \c PercentDynamicCostSavedThreshold.
|
||||
unsigned DynamicCostSavingsDiscount;
|
||||
/// The cost threshold for the unrolled loop when optimizing for size (set
|
||||
/// to UINT_MAX to disable).
|
||||
unsigned OptSizeThreshold;
|
||||
|
@ -303,7 +305,8 @@ public:
|
|||
/// mode is legal for a load/store of any legal type.
|
||||
/// TODO: Handle pre/postinc as well.
|
||||
bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
|
||||
bool HasBaseReg, int64_t Scale) const;
|
||||
bool HasBaseReg, int64_t Scale,
|
||||
unsigned AddrSpace = 0) const;
|
||||
|
||||
/// \brief Return true if the target works with masked instruction
|
||||
/// AVX2 allows masks for consecutive load and store for i32 and i64 elements.
|
||||
|
@ -319,7 +322,8 @@ public:
|
|||
/// If the AM is not supported, it returns a negative value.
|
||||
/// TODO: Handle pre/postinc as well.
|
||||
int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
|
||||
bool HasBaseReg, int64_t Scale) const;
|
||||
bool HasBaseReg, int64_t Scale,
|
||||
unsigned AddrSpace = 0) const;
|
||||
|
||||
/// \brief Return true if it's free to truncate a value of type Ty1 to type
|
||||
/// Ty2. e.g. On x86 it's free to truncate a i32 value in register EAX to i16
|
||||
|
@ -444,6 +448,20 @@ public:
|
|||
unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
|
||||
unsigned AddressSpace) const;
|
||||
|
||||
/// \return The cost of the interleaved memory operation.
|
||||
/// \p Opcode is the memory operation code
|
||||
/// \p VecTy is the vector type of the interleaved access.
|
||||
/// \p Factor is the interleave factor
|
||||
/// \p Indices is the indices for interleaved load members (as interleaved
|
||||
/// load allows gaps)
|
||||
/// \p Alignment is the alignment of the memory operation
|
||||
/// \p AddressSpace is address space of the pointer.
|
||||
unsigned getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy,
|
||||
unsigned Factor,
|
||||
ArrayRef<unsigned> Indices,
|
||||
unsigned Alignment,
|
||||
unsigned AddressSpace) const;
|
||||
|
||||
/// \brief Calculate the cost of performing a vector reduction.
|
||||
///
|
||||
/// This is the cost of reducing the vector value of type \p Ty to a scalar
|
||||
|
@ -539,12 +557,13 @@ public:
|
|||
virtual bool isLegalICmpImmediate(int64_t Imm) = 0;
|
||||
virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV,
|
||||
int64_t BaseOffset, bool HasBaseReg,
|
||||
int64_t Scale) = 0;
|
||||
int64_t Scale,
|
||||
unsigned AddrSpace) = 0;
|
||||
virtual bool isLegalMaskedStore(Type *DataType, int Consecutive) = 0;
|
||||
virtual bool isLegalMaskedLoad(Type *DataType, int Consecutive) = 0;
|
||||
virtual int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV,
|
||||
int64_t BaseOffset, bool HasBaseReg,
|
||||
int64_t Scale) = 0;
|
||||
int64_t Scale, unsigned AddrSpace) = 0;
|
||||
virtual bool isTruncateFree(Type *Ty1, Type *Ty2) = 0;
|
||||
virtual bool isProfitableToHoist(Instruction *I) = 0;
|
||||
virtual bool isTypeLegal(Type *Ty) = 0;
|
||||
|
@ -582,6 +601,11 @@ public:
|
|||
virtual unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src,
|
||||
unsigned Alignment,
|
||||
unsigned AddressSpace) = 0;
|
||||
virtual unsigned getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy,
|
||||
unsigned Factor,
|
||||
ArrayRef<unsigned> Indices,
|
||||
unsigned Alignment,
|
||||
unsigned AddressSpace) = 0;
|
||||
virtual unsigned getReductionCost(unsigned Opcode, Type *Ty,
|
||||
bool IsPairwiseForm) = 0;
|
||||
virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
|
||||
|
@ -648,9 +672,10 @@ public:
|
|||
return Impl.isLegalICmpImmediate(Imm);
|
||||
}
|
||||
bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
|
||||
bool HasBaseReg, int64_t Scale) override {
|
||||
bool HasBaseReg, int64_t Scale,
|
||||
unsigned AddrSpace) override {
|
||||
return Impl.isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg,
|
||||
Scale);
|
||||
Scale, AddrSpace);
|
||||
}
|
||||
bool isLegalMaskedStore(Type *DataType, int Consecutive) override {
|
||||
return Impl.isLegalMaskedStore(DataType, Consecutive);
|
||||
|
@ -659,8 +684,10 @@ public:
|
|||
return Impl.isLegalMaskedLoad(DataType, Consecutive);
|
||||
}
|
||||
int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
|
||||
bool HasBaseReg, int64_t Scale) override {
|
||||
return Impl.getScalingFactorCost(Ty, BaseGV, BaseOffset, HasBaseReg, Scale);
|
||||
bool HasBaseReg, int64_t Scale,
|
||||
unsigned AddrSpace) override {
|
||||
return Impl.getScalingFactorCost(Ty, BaseGV, BaseOffset, HasBaseReg,
|
||||
Scale, AddrSpace);
|
||||
}
|
||||
bool isTruncateFree(Type *Ty1, Type *Ty2) override {
|
||||
return Impl.isTruncateFree(Ty1, Ty2);
|
||||
|
@ -740,6 +767,14 @@ public:
|
|||
unsigned AddressSpace) override {
|
||||
return Impl.getMaskedMemoryOpCost(Opcode, Src, Alignment, AddressSpace);
|
||||
}
|
||||
unsigned getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy,
|
||||
unsigned Factor,
|
||||
ArrayRef<unsigned> Indices,
|
||||
unsigned Alignment,
|
||||
unsigned AddressSpace) override {
|
||||
return Impl.getInterleavedMemoryOpCost(Opcode, VecTy, Factor, Indices,
|
||||
Alignment, AddressSpace);
|
||||
}
|
||||
unsigned getReductionCost(unsigned Opcode, Type *Ty,
|
||||
bool IsPairwiseForm) override {
|
||||
return Impl.getReductionCost(Opcode, Ty, IsPairwiseForm);
|
||||
|
|
|
@ -207,7 +207,8 @@ public:
|
|||
bool isLegalICmpImmediate(int64_t Imm) { return false; }
|
||||
|
||||
bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
|
||||
bool HasBaseReg, int64_t Scale) {
|
||||
bool HasBaseReg, int64_t Scale,
|
||||
unsigned AddrSpace) {
|
||||
// Guess that only reg and reg+reg addressing is allowed. This heuristic is
|
||||
// taken from the implementation of LSR.
|
||||
return !BaseGV && BaseOffset == 0 && (Scale == 0 || Scale == 1);
|
||||
|
@ -218,9 +219,10 @@ public:
|
|||
bool isLegalMaskedLoad(Type *DataType, int Consecutive) { return false; }
|
||||
|
||||
int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
|
||||
bool HasBaseReg, int64_t Scale) {
|
||||
bool HasBaseReg, int64_t Scale, unsigned AddrSpace) {
|
||||
// Guess that all legal addressing mode are free.
|
||||
if (isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, Scale))
|
||||
if (isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg,
|
||||
Scale, AddrSpace))
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
@ -300,6 +302,14 @@ public:
|
|||
return 1;
|
||||
}
|
||||
|
||||
unsigned getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy,
|
||||
unsigned Factor,
|
||||
ArrayRef<unsigned> Indices,
|
||||
unsigned Alignment,
|
||||
unsigned AddressSpace) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
|
||||
ArrayRef<Type *> Tys) {
|
||||
return 1;
|
||||
|
|
|
@ -403,7 +403,8 @@ namespace bitc {
|
|||
ATTR_KIND_JUMP_TABLE = 40,
|
||||
ATTR_KIND_DEREFERENCEABLE = 41,
|
||||
ATTR_KIND_DEREFERENCEABLE_OR_NULL = 42,
|
||||
ATTR_KIND_CONVERGENT = 43
|
||||
ATTR_KIND_CONVERGENT = 43,
|
||||
ATTR_KIND_SAFESTACK = 44,
|
||||
};
|
||||
|
||||
enum ComdatSelectionKindCodes {
|
||||
|
|
|
@ -125,23 +125,24 @@ public:
|
|||
}
|
||||
|
||||
bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
|
||||
bool HasBaseReg, int64_t Scale) {
|
||||
bool HasBaseReg, int64_t Scale,
|
||||
unsigned AddrSpace) {
|
||||
TargetLoweringBase::AddrMode AM;
|
||||
AM.BaseGV = BaseGV;
|
||||
AM.BaseOffs = BaseOffset;
|
||||
AM.HasBaseReg = HasBaseReg;
|
||||
AM.Scale = Scale;
|
||||
return getTLI()->isLegalAddressingMode(AM, Ty);
|
||||
return getTLI()->isLegalAddressingMode(AM, Ty, AddrSpace);
|
||||
}
|
||||
|
||||
int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
|
||||
bool HasBaseReg, int64_t Scale) {
|
||||
bool HasBaseReg, int64_t Scale, unsigned AddrSpace) {
|
||||
TargetLoweringBase::AddrMode AM;
|
||||
AM.BaseGV = BaseGV;
|
||||
AM.BaseOffs = BaseOffset;
|
||||
AM.HasBaseReg = HasBaseReg;
|
||||
AM.Scale = Scale;
|
||||
return getTLI()->getScalingFactorCost(AM, Ty);
|
||||
return getTLI()->getScalingFactorCost(AM, Ty, AddrSpace);
|
||||
}
|
||||
|
||||
bool isTruncateFree(Type *Ty1, Type *Ty2) {
|
||||
|
@ -522,6 +523,73 @@ public:
|
|||
return Cost;
|
||||
}
|
||||
|
||||
unsigned getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy,
|
||||
unsigned Factor,
|
||||
ArrayRef<unsigned> Indices,
|
||||
unsigned Alignment,
|
||||
unsigned AddressSpace) {
|
||||
VectorType *VT = dyn_cast<VectorType>(VecTy);
|
||||
assert(VT && "Expect a vector type for interleaved memory op");
|
||||
|
||||
unsigned NumElts = VT->getNumElements();
|
||||
assert(Factor > 1 && NumElts % Factor == 0 && "Invalid interleave factor");
|
||||
|
||||
unsigned NumSubElts = NumElts / Factor;
|
||||
VectorType *SubVT = VectorType::get(VT->getElementType(), NumSubElts);
|
||||
|
||||
// Firstly, the cost of load/store operation.
|
||||
unsigned Cost = getMemoryOpCost(Opcode, VecTy, Alignment, AddressSpace);
|
||||
|
||||
// Then plus the cost of interleave operation.
|
||||
if (Opcode == Instruction::Load) {
|
||||
// The interleave cost is similar to extract sub vectors' elements
|
||||
// from the wide vector, and insert them into sub vectors.
|
||||
//
|
||||
// E.g. An interleaved load of factor 2 (with one member of index 0):
|
||||
// %vec = load <8 x i32>, <8 x i32>* %ptr
|
||||
// %v0 = shuffle %vec, undef, <0, 2, 4, 6> ; Index 0
|
||||
// The cost is estimated as extract elements at 0, 2, 4, 6 from the
|
||||
// <8 x i32> vector and insert them into a <4 x i32> vector.
|
||||
|
||||
assert(Indices.size() <= Factor &&
|
||||
"Interleaved memory op has too many members");
|
||||
for (unsigned Index : Indices) {
|
||||
assert(Index < Factor && "Invalid index for interleaved memory op");
|
||||
|
||||
// Extract elements from loaded vector for each sub vector.
|
||||
for (unsigned i = 0; i < NumSubElts; i++)
|
||||
Cost += getVectorInstrCost(Instruction::ExtractElement, VT,
|
||||
Index + i * Factor);
|
||||
}
|
||||
|
||||
unsigned InsSubCost = 0;
|
||||
for (unsigned i = 0; i < NumSubElts; i++)
|
||||
InsSubCost += getVectorInstrCost(Instruction::InsertElement, SubVT, i);
|
||||
|
||||
Cost += Indices.size() * InsSubCost;
|
||||
} else {
|
||||
// The interleave cost is extract all elements from sub vectors, and
|
||||
// insert them into the wide vector.
|
||||
//
|
||||
// E.g. An interleaved store of factor 2:
|
||||
// %v0_v1 = shuffle %v0, %v1, <0, 4, 1, 5, 2, 6, 3, 7>
|
||||
// store <8 x i32> %interleaved.vec, <8 x i32>* %ptr
|
||||
// The cost is estimated as extract all elements from both <4 x i32>
|
||||
// vectors and insert into the <8 x i32> vector.
|
||||
|
||||
unsigned ExtSubCost = 0;
|
||||
for (unsigned i = 0; i < NumSubElts; i++)
|
||||
ExtSubCost += getVectorInstrCost(Instruction::ExtractElement, SubVT, i);
|
||||
|
||||
Cost += Factor * ExtSubCost;
|
||||
|
||||
for (unsigned i = 0; i < NumElts; i++)
|
||||
Cost += getVectorInstrCost(Instruction::InsertElement, VT, i);
|
||||
}
|
||||
|
||||
return Cost;
|
||||
}
|
||||
|
||||
unsigned getIntrinsicInstrCost(Intrinsic::ID IID, Type *RetTy,
|
||||
ArrayRef<Type *> Tys) {
|
||||
unsigned ISD = 0;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#ifndef LLVM_CODEGEN_COMMANDFLAGS_H
|
||||
#define LLVM_CODEGEN_COMMANDFLAGS_H
|
||||
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/MC/MCTargetOptionsCommandFlags.h"
|
||||
#include "llvm//MC/SubtargetFeature.h"
|
||||
|
@ -24,6 +25,7 @@
|
|||
#include "llvm/Support/Host.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include "llvm/Target/TargetRecip.h"
|
||||
#include <string>
|
||||
using namespace llvm;
|
||||
|
||||
|
@ -149,9 +151,15 @@ FuseFPOps("fp-contract",
|
|||
clEnumValN(FPOpFusion::Standard, "on",
|
||||
"Only fuse 'blessed' FP ops."),
|
||||
clEnumValN(FPOpFusion::Strict, "off",
|
||||
"Only fuse FP ops when the result won't be effected."),
|
||||
"Only fuse FP ops when the result won't be affected."),
|
||||
clEnumValEnd));
|
||||
|
||||
cl::list<std::string>
|
||||
ReciprocalOps("recip",
|
||||
cl::CommaSeparated,
|
||||
cl::desc("Choose reciprocal operation types and parameters."),
|
||||
cl::value_desc("all,none,default,divf,!vec-sqrtd,vec-divd:0,sqrt:9..."));
|
||||
|
||||
cl::opt<bool>
|
||||
DontPlaceZerosInBSS("nozero-initialized-in-bss",
|
||||
cl::desc("Don't place zero-initialized symbols into bss section"),
|
||||
|
@ -230,6 +238,7 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
|
|||
TargetOptions Options;
|
||||
Options.LessPreciseFPMADOption = EnableFPMAD;
|
||||
Options.AllowFPOpFusion = FuseFPOps;
|
||||
Options.Reciprocals = TargetRecip(ReciprocalOps);
|
||||
Options.UnsafeFPMath = EnableUnsafeFPMath;
|
||||
Options.NoInfsFPMath = EnableNoInfsFPMath;
|
||||
Options.NoNaNsFPMath = EnableNoNaNsFPMath;
|
||||
|
@ -239,7 +248,6 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
|
|||
Options.FloatABIType = FloatABIForCalls;
|
||||
Options.NoZerosInBSS = DontPlaceZerosInBSS;
|
||||
Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt;
|
||||
Options.DisableTailCalls = DisableTailCalls;
|
||||
Options.StackAlignmentOverride = OverrideStackAlignment;
|
||||
Options.TrapFuncName = TrapFuncName;
|
||||
Options.PositionIndependentExecutable = EnablePIE;
|
||||
|
@ -307,6 +315,11 @@ static inline void setFunctionAttributes(StringRef CPU, StringRef Features,
|
|||
"no-frame-pointer-elim",
|
||||
DisableFPElim ? "true" : "false");
|
||||
|
||||
if (DisableTailCalls.getNumOccurrences() > 0)
|
||||
NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex,
|
||||
"disable-tail-calls",
|
||||
toStringRef(DisableTailCalls));
|
||||
|
||||
// Let NewAttrs override Attrs.
|
||||
NewAttrs = Attrs.addAttributes(Ctx, AttributeSet::FunctionIndex, NewAttrs);
|
||||
F.setAttributes(NewAttrs);
|
||||
|
|
73
include/llvm/CodeGen/FaultMaps.h
Normal file
73
include/llvm/CodeGen/FaultMaps.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
//===------------------- FaultMaps.h - StackMaps ----------------*- 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_FAULTMAPS_H
|
||||
#define LLVM_CODEGEN_FAULTMAPS_H
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class AsmPrinter;
|
||||
class MCExpr;
|
||||
class MCSymbol;
|
||||
class MCStreamer;
|
||||
|
||||
class FaultMaps {
|
||||
public:
|
||||
enum FaultKind { FaultingLoad = 1, FaultKindMax };
|
||||
|
||||
static const char *faultTypeToString(FaultKind);
|
||||
|
||||
explicit FaultMaps(AsmPrinter &AP);
|
||||
|
||||
void recordFaultingOp(FaultKind FaultTy, const MCSymbol *HandlerLabel);
|
||||
void serializeToFaultMapSection();
|
||||
|
||||
private:
|
||||
static const char *WFMP;
|
||||
|
||||
struct FaultInfo {
|
||||
FaultKind Kind;
|
||||
const MCExpr *FaultingOffsetExpr;
|
||||
const MCExpr *HandlerOffsetExpr;
|
||||
|
||||
FaultInfo()
|
||||
: Kind(FaultKindMax), FaultingOffsetExpr(nullptr),
|
||||
HandlerOffsetExpr(nullptr) {}
|
||||
|
||||
explicit FaultInfo(FaultMaps::FaultKind Kind, const MCExpr *FaultingOffset,
|
||||
const MCExpr *HandlerOffset)
|
||||
: Kind(Kind), FaultingOffsetExpr(FaultingOffset),
|
||||
HandlerOffsetExpr(HandlerOffset) {}
|
||||
};
|
||||
|
||||
typedef std::vector<FaultInfo> FunctionFaultInfos;
|
||||
|
||||
// We'd like to keep a stable iteration order for FunctionInfos to help
|
||||
// FileCheck based testing.
|
||||
struct MCSymbolComparator {
|
||||
bool operator()(const MCSymbol *LHS, const MCSymbol *RHS) const {
|
||||
return LHS->getName() < RHS->getName();
|
||||
}
|
||||
};
|
||||
|
||||
std::map<const MCSymbol *, FunctionFaultInfos, MCSymbolComparator>
|
||||
FunctionInfos;
|
||||
AsmPrinter &AP;
|
||||
|
||||
void emitFunctionInfo(const MCSymbol *FnLabel, const FunctionFaultInfos &FFI);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -19,33 +19,62 @@
|
|||
#define LLVM_CODEGEN_MIRPARSER_MIRPARSER_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/CodeGen/MachineFunctionInitializer.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include <memory>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MIRParserImpl;
|
||||
class SMDiagnostic;
|
||||
|
||||
/// This class initializes machine functions by applying the state loaded from
|
||||
/// a MIR file.
|
||||
class MIRParser : public MachineFunctionInitializer {
|
||||
std::unique_ptr<MIRParserImpl> Impl;
|
||||
|
||||
public:
|
||||
MIRParser(std::unique_ptr<MIRParserImpl> Impl);
|
||||
MIRParser(const MIRParser &) = delete;
|
||||
~MIRParser();
|
||||
|
||||
/// Parse the optional LLVM IR module that's embedded in the MIR file.
|
||||
///
|
||||
/// A new, empty module is created if the LLVM IR isn't present.
|
||||
/// Returns null if a parsing error occurred.
|
||||
std::unique_ptr<Module> parseLLVMModule();
|
||||
|
||||
/// Initialize the machine function to the state that's described in the MIR
|
||||
/// file.
|
||||
///
|
||||
/// Return true if error occurred.
|
||||
bool initializeMachineFunction(MachineFunction &MF) override;
|
||||
};
|
||||
|
||||
/// This function is the main interface to the MIR serialization format parser.
|
||||
///
|
||||
/// It reads a YAML file that has an optional LLVM IR and returns an LLVM
|
||||
/// module.
|
||||
/// It reads in a MIR file and returns a MIR parser that can parse the embedded
|
||||
/// LLVM IR module and initialize the machine functions by parsing the machine
|
||||
/// function's state.
|
||||
///
|
||||
/// \param Filename - The name of the file to parse.
|
||||
/// \param Error - Error result info.
|
||||
/// \param Context - Context in which to allocate globals info.
|
||||
std::unique_ptr<Module> parseMIRFile(StringRef Filename, SMDiagnostic &Error,
|
||||
LLVMContext &Context);
|
||||
/// \param Context - Context which will be used for the parsed LLVM IR module.
|
||||
std::unique_ptr<MIRParser> createMIRParserFromFile(StringRef Filename,
|
||||
SMDiagnostic &Error,
|
||||
LLVMContext &Context);
|
||||
|
||||
/// This function is another interface to the MIR serialization format parser.
|
||||
///
|
||||
/// It parses the optional LLVM IR in the given buffer, and returns an LLVM
|
||||
/// module.
|
||||
/// It returns a MIR parser that works with the given memory buffer and that can
|
||||
/// parse the embedded LLVM IR module and initialize the machine functions by
|
||||
/// parsing the machine function's state.
|
||||
///
|
||||
/// \param Contents - The MemoryBuffer containing the machine level IR.
|
||||
/// \param Error - Error result info.
|
||||
/// \param Context - Context in which to allocate globals info.
|
||||
std::unique_ptr<Module> parseMIR(std::unique_ptr<MemoryBuffer> Contents,
|
||||
SMDiagnostic &Error, LLVMContext &Context);
|
||||
/// \param Context - Context which will be used for the parsed LLVM IR module.
|
||||
std::unique_ptr<MIRParser>
|
||||
createMIRParser(std::unique_ptr<MemoryBuffer> Contents, LLVMContext &Context);
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
namespace llvm {
|
||||
|
||||
class MachineFunction;
|
||||
class MachineFunctionInitializer;
|
||||
class TargetMachine;
|
||||
|
||||
/// MachineFunctionAnalysis - This class is a Pass that manages a
|
||||
|
@ -28,9 +29,12 @@ private:
|
|||
const TargetMachine &TM;
|
||||
MachineFunction *MF;
|
||||
unsigned NextFnNum;
|
||||
MachineFunctionInitializer *MFInitializer;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
explicit MachineFunctionAnalysis(const TargetMachine &tm);
|
||||
explicit MachineFunctionAnalysis(const TargetMachine &tm,
|
||||
MachineFunctionInitializer *MFInitializer);
|
||||
~MachineFunctionAnalysis() override;
|
||||
|
||||
MachineFunction &getMF() const { return *MF; }
|
||||
|
|
38
include/llvm/CodeGen/MachineFunctionInitializer.h
Normal file
38
include/llvm/CodeGen/MachineFunctionInitializer.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
//===- MachineFunctionInitalizer.h - machine function initializer ---------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares an interface that allows custom machine function
|
||||
// initialization.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CODEGEN_MACHINEFUNCTIONINITIALIZER_H
|
||||
#define LLVM_CODEGEN_MACHINEFUNCTIONINITIALIZER_H
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class MachineFunction;
|
||||
|
||||
/// This interface provides a way to initialize machine functions after they are
|
||||
/// created by the machine function analysis pass.
|
||||
class MachineFunctionInitializer {
|
||||
virtual void anchor();
|
||||
|
||||
public:
|
||||
virtual ~MachineFunctionInitializer() {}
|
||||
|
||||
/// Initialize the machine function.
|
||||
///
|
||||
/// Return true if error occurred.
|
||||
virtual bool initializeMachineFunction(MachineFunction &MF) = 0;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
|
@ -936,7 +936,7 @@ public:
|
|||
/// For normal instructions, this is derived from the MCInstrDesc.
|
||||
/// For inline assembly it is derived from the flag words.
|
||||
///
|
||||
/// Returns NULL if the static register classs constraint cannot be
|
||||
/// Returns NULL if the static register class constraint cannot be
|
||||
/// determined.
|
||||
///
|
||||
const TargetRegisterClass*
|
||||
|
@ -948,10 +948,10 @@ public:
|
|||
/// the given \p CurRC.
|
||||
/// If \p ExploreBundle is set and MI is part of a bundle, all the
|
||||
/// instructions inside the bundle will be taken into account. In other words,
|
||||
/// this method accumulates all the constrains of the operand of this MI and
|
||||
/// this method accumulates all the constraints of the operand of this MI and
|
||||
/// the related bundle if MI is a bundle or inside a bundle.
|
||||
///
|
||||
/// Returns the register class that statisfies both \p CurRC and the
|
||||
/// Returns the register class that satisfies both \p CurRC and the
|
||||
/// constraints set by MI. Returns NULL if such a register class does not
|
||||
/// exist.
|
||||
///
|
||||
|
@ -964,7 +964,7 @@ public:
|
|||
/// \brief Applies the constraints (def/use) implied by the \p OpIdx operand
|
||||
/// to the given \p CurRC.
|
||||
///
|
||||
/// Returns the register class that statisfies both \p CurRC and the
|
||||
/// Returns the register class that satisfies both \p CurRC and the
|
||||
/// constraints set by \p OpIdx MI. Returns NULL if such a register class
|
||||
/// does not exist.
|
||||
///
|
||||
|
|
|
@ -157,11 +157,6 @@ class MachineModuleInfo : public ImmutablePass {
|
|||
/// emit common EH frames.
|
||||
std::vector<const Function *> Personalities;
|
||||
|
||||
/// UsedFunctions - The functions in the @llvm.used list in a more easily
|
||||
/// searchable format. This does not include the functions in
|
||||
/// llvm.compiler.used.
|
||||
SmallPtrSet<const Function *, 32> UsedFunctions;
|
||||
|
||||
/// AddrLabelSymbols - This map keeps track of which symbol is being used for
|
||||
/// the specified basic block's address of label.
|
||||
MMIAddrLabelMap *AddrLabelSymbols;
|
||||
|
@ -246,10 +241,6 @@ public:
|
|||
return const_cast<MachineModuleInfo*>(this)->getObjFileInfo<Ty>();
|
||||
}
|
||||
|
||||
/// AnalyzeModule - Scan the module for global debug information.
|
||||
///
|
||||
void AnalyzeModule(const Module &M);
|
||||
|
||||
/// hasDebugInfo - Returns true if valid debug info is present.
|
||||
///
|
||||
bool hasDebugInfo() const { return DbgInfoAvailable; }
|
||||
|
@ -339,13 +330,6 @@ public:
|
|||
return Personalities;
|
||||
}
|
||||
|
||||
/// isUsedFunction - Return true if the functions in the llvm.used list. This
|
||||
/// does not return true for things in llvm.compiler.used unless they are also
|
||||
/// in llvm.used.
|
||||
bool isUsedFunction(const Function *F) const {
|
||||
return UsedFunctions.count(F);
|
||||
}
|
||||
|
||||
/// addCatchTypeInfo - Provide the catch typeinfo for a landing pad.
|
||||
///
|
||||
void addCatchTypeInfo(MachineBasicBlock *LandingPad,
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class FunctionPass;
|
||||
class MachineFunctionPass;
|
||||
class PassConfigImpl;
|
||||
class PassInfo;
|
||||
|
@ -519,6 +519,8 @@ namespace llvm {
|
|||
/// IfConverter - This pass performs machine code if conversion.
|
||||
extern char &IfConverterID;
|
||||
|
||||
FunctionPass *createIfConverter(std::function<bool(const Function &)> Ftor);
|
||||
|
||||
/// MachineBlockPlacement - This pass places basic blocks based on branch
|
||||
/// probabilities.
|
||||
extern char &MachineBlockPlacementID;
|
||||
|
@ -550,6 +552,10 @@ namespace llvm {
|
|||
/// MachineCSE - This pass performs global CSE on machine instructions.
|
||||
extern char &MachineCSEID;
|
||||
|
||||
/// ImplicitNullChecks - This pass folds null pointer checks into nearby
|
||||
/// memory operations.
|
||||
extern char &ImplicitNullChecksID;
|
||||
|
||||
/// MachineLICM - This pass performs LICM on machine instructions.
|
||||
extern char &MachineLICMID;
|
||||
|
||||
|
@ -613,6 +619,9 @@ namespace llvm {
|
|||
/// UnpackMachineBundles - This pass unpack machine instruction bundles.
|
||||
extern char &UnpackMachineBundlesID;
|
||||
|
||||
FunctionPass *
|
||||
createUnpackMachineBundles(std::function<bool(const Function &)> Ftor);
|
||||
|
||||
/// FinalizeMachineBundles - This pass finalize machine instruction
|
||||
/// bundles (created earlier, e.g. during pre-RA scheduling).
|
||||
extern char &FinalizeMachineBundlesID;
|
||||
|
|
|
@ -144,14 +144,15 @@ struct WinEHFuncInfo {
|
|||
SmallVector<WinEHUnwindMapEntry, 4> UnwindMap;
|
||||
SmallVector<WinEHTryBlockMapEntry, 4> TryBlockMap;
|
||||
SmallVector<std::pair<MCSymbol *, int>, 4> IPToStateList;
|
||||
int UnwindHelpFrameIdx;
|
||||
int UnwindHelpFrameOffset;
|
||||
int UnwindHelpFrameIdx = INT_MAX;
|
||||
int UnwindHelpFrameOffset = -1;
|
||||
unsigned NumIPToStateFuncsVisited = 0;
|
||||
|
||||
unsigned NumIPToStateFuncsVisited;
|
||||
/// frameescape index of the 32-bit EH registration node. Set by
|
||||
/// WinEHStatePass and used indirectly by SEH filter functions of the parent.
|
||||
int EHRegNodeEscapeIndex = INT_MAX;
|
||||
|
||||
WinEHFuncInfo()
|
||||
: UnwindHelpFrameIdx(INT_MAX), UnwindHelpFrameOffset(-1),
|
||||
NumIPToStateFuncsVisited(0) {}
|
||||
WinEHFuncInfo() {}
|
||||
};
|
||||
|
||||
/// Analyze the IR in ParentFn and it's handlers to build WinEHFuncInfo, which
|
||||
|
|
|
@ -141,8 +141,7 @@ private:
|
|||
/// on the fly.
|
||||
class LoadedObjectInfo {
|
||||
public:
|
||||
LoadedObjectInfo() {}
|
||||
virtual ~LoadedObjectInfo() {}
|
||||
virtual ~LoadedObjectInfo() = default;
|
||||
|
||||
/// Obtain the Load Address of a section by Name.
|
||||
///
|
||||
|
@ -170,7 +169,7 @@ public:
|
|||
/// Obtain a copy of this LoadedObjectInfo.
|
||||
///
|
||||
/// The caller is responsible for deallocation once the copy is no longer required.
|
||||
virtual LoadedObjectInfo *clone() const = 0;
|
||||
virtual std::unique_ptr<LoadedObjectInfo> clone() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -205,7 +205,7 @@ public:
|
|||
/// runFunction - Execute the specified function with the specified arguments,
|
||||
/// and return the result.
|
||||
virtual GenericValue runFunction(Function *F,
|
||||
const std::vector<GenericValue> &ArgValues) = 0;
|
||||
ArrayRef<GenericValue> ArgValues) = 0;
|
||||
|
||||
/// getPointerToNamedFunction - This method returns the address of the
|
||||
/// specified function by using the dlsym function call. As such it is only
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
#ifndef LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
|
||||
#define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
|
||||
|
||||
//#include "CloneSubModule.h"
|
||||
#include "IndirectionUtils.h"
|
||||
#include "LambdaResolver.h"
|
||||
#include "LogicalDylib.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
|
||||
#include "llvm/Transforms/Utils/Cloning.h"
|
||||
|
@ -36,7 +36,9 @@ namespace orc {
|
|||
/// added to the layer below. When a stub is called it triggers the extraction
|
||||
/// of the function body from the original module. The extracted body is then
|
||||
/// compiled and executed.
|
||||
template <typename BaseLayerT, typename CompileCallbackMgrT>
|
||||
template <typename BaseLayerT, typename CompileCallbackMgrT,
|
||||
typename PartitioningFtor =
|
||||
std::function<std::set<Function*>(Function&)>>
|
||||
class CompileOnDemandLayer {
|
||||
private:
|
||||
|
||||
|
@ -44,333 +46,63 @@ private:
|
|||
// variables.
|
||||
class GlobalDeclMaterializer : public ValueMaterializer {
|
||||
public:
|
||||
GlobalDeclMaterializer(Module &Dst) : Dst(Dst) {}
|
||||
typedef std::set<const Function*> StubSet;
|
||||
|
||||
GlobalDeclMaterializer(Module &Dst, const StubSet *StubsToClone = nullptr)
|
||||
: Dst(Dst), StubsToClone(StubsToClone) {}
|
||||
|
||||
Value* materializeValueFor(Value *V) final {
|
||||
if (auto *GV = dyn_cast<GlobalVariable>(V))
|
||||
return cloneGlobalVariableDecl(Dst, *GV);
|
||||
else if (auto *F = dyn_cast<Function>(V))
|
||||
return cloneFunctionDecl(Dst, *F);
|
||||
else if (auto *F = dyn_cast<Function>(V)) {
|
||||
auto *ClonedF = cloneFunctionDecl(Dst, *F);
|
||||
if (StubsToClone && StubsToClone->count(F)) {
|
||||
GlobalVariable *FnBodyPtr =
|
||||
createImplPointer(*ClonedF->getType(), *ClonedF->getParent(),
|
||||
ClonedF->getName() + "$orc_addr", nullptr);
|
||||
makeStub(*ClonedF, *FnBodyPtr);
|
||||
ClonedF->setLinkage(GlobalValue::AvailableExternallyLinkage);
|
||||
ClonedF->addFnAttr(Attribute::AlwaysInline);
|
||||
}
|
||||
return ClonedF;
|
||||
}
|
||||
// Else.
|
||||
return nullptr;
|
||||
}
|
||||
private:
|
||||
Module &Dst;
|
||||
const StubSet *StubsToClone;
|
||||
};
|
||||
|
||||
typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
|
||||
class UncompiledPartition;
|
||||
|
||||
// Logical module.
|
||||
//
|
||||
// This struct contains the handles for the global values and stubs (which
|
||||
// cover the external symbols of the original module), plus the handes for
|
||||
// each of the extracted partitions. These handleds are used for lookup (only
|
||||
// the globals/stubs module is searched) and memory management. The actual
|
||||
// searching and resource management are handled by the LogicalDylib that owns
|
||||
// the LogicalModule.
|
||||
struct LogicalModule {
|
||||
LogicalModule() {}
|
||||
|
||||
LogicalModule(LogicalModule &&Other)
|
||||
: SrcM(std::move(Other.SrcM)),
|
||||
GVsAndStubsHandle(std::move(Other.GVsAndStubsHandle)),
|
||||
ImplHandles(std::move(Other.ImplHandles)) {}
|
||||
|
||||
std::unique_ptr<Module> SrcM;
|
||||
BaseLayerModuleSetHandleT GVsAndStubsHandle;
|
||||
std::vector<BaseLayerModuleSetHandleT> ImplHandles;
|
||||
struct LogicalModuleResources {
|
||||
std::shared_ptr<Module> SourceModule;
|
||||
std::set<const Function*> StubsToClone;
|
||||
};
|
||||
|
||||
// Logical dylib.
|
||||
//
|
||||
// This class handles symbol resolution and resource management for a set of
|
||||
// modules that were added together as a logical dylib.
|
||||
//
|
||||
// A logical dylib contains one-or-more LogicalModules plus a set of
|
||||
// UncompiledPartitions. LogicalModules support symbol resolution and resource
|
||||
// management for for code that has already been emitted. UncompiledPartitions
|
||||
// represent code that has not yet been compiled.
|
||||
class LogicalDylib {
|
||||
private:
|
||||
friend class UncompiledPartition;
|
||||
typedef std::list<LogicalModule> LogicalModuleList;
|
||||
public:
|
||||
|
||||
typedef unsigned UncompiledPartitionID;
|
||||
typedef typename LogicalModuleList::iterator LMHandle;
|
||||
|
||||
// Construct a logical dylib.
|
||||
LogicalDylib(CompileOnDemandLayer &CODLayer) : CODLayer(CODLayer) { }
|
||||
|
||||
// Delete this logical dylib, release logical module resources.
|
||||
virtual ~LogicalDylib() {
|
||||
releaseLogicalModuleResources();
|
||||
}
|
||||
|
||||
// Get a reference to the containing layer.
|
||||
CompileOnDemandLayer& getCODLayer() { return CODLayer; }
|
||||
|
||||
// Get a reference to the base layer.
|
||||
BaseLayerT& getBaseLayer() { return CODLayer.BaseLayer; }
|
||||
|
||||
// Start a new context for a single logical module.
|
||||
LMHandle createLogicalModule() {
|
||||
LogicalModules.push_back(LogicalModule());
|
||||
return std::prev(LogicalModules.end());
|
||||
}
|
||||
|
||||
// Set the global-values-and-stubs module handle for this logical module.
|
||||
void setGVsAndStubsHandle(LMHandle LMH, BaseLayerModuleSetHandleT H) {
|
||||
LMH->GVsAndStubsHandle = H;
|
||||
}
|
||||
|
||||
// Return the global-values-and-stubs module handle for this logical module.
|
||||
BaseLayerModuleSetHandleT getGVsAndStubsHandle(LMHandle LMH) {
|
||||
return LMH->GVsAndStubsHandle;
|
||||
}
|
||||
|
||||
// Add a handle to a module containing lazy function bodies to the given
|
||||
// logical module.
|
||||
void addToLogicalModule(LMHandle LMH, BaseLayerModuleSetHandleT H) {
|
||||
LMH->ImplHandles.push_back(H);
|
||||
}
|
||||
|
||||
// Create an UncompiledPartition attached to this LogicalDylib.
|
||||
UncompiledPartition& createUncompiledPartition(LMHandle LMH,
|
||||
std::shared_ptr<Module> SrcM);
|
||||
|
||||
// Take ownership of the given UncompiledPartition from the logical dylib.
|
||||
std::unique_ptr<UncompiledPartition>
|
||||
takeUPOwnership(UncompiledPartitionID ID);
|
||||
|
||||
// Look up a symbol in this context.
|
||||
JITSymbol findSymbolInternally(LMHandle LMH, const std::string &Name) {
|
||||
if (auto Symbol = getBaseLayer().findSymbolIn(LMH->GVsAndStubsHandle,
|
||||
Name, false))
|
||||
return Symbol;
|
||||
|
||||
for (auto I = LogicalModules.begin(), E = LogicalModules.end(); I != E;
|
||||
++I)
|
||||
if (I != LMH)
|
||||
if (auto Symbol = getBaseLayer().findSymbolIn(I->GVsAndStubsHandle,
|
||||
Name, false))
|
||||
return Symbol;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
|
||||
for (auto &LM : LogicalModules)
|
||||
if (auto Symbol = getBaseLayer().findSymbolIn(LM.GVsAndStubsHandle,
|
||||
Name,
|
||||
ExportedSymbolsOnly))
|
||||
return Symbol;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Find an external symbol (via the user supplied SymbolResolver).
|
||||
virtual RuntimeDyld::SymbolInfo
|
||||
findSymbolExternally(const std::string &Name) const = 0;
|
||||
|
||||
private:
|
||||
|
||||
void releaseLogicalModuleResources() {
|
||||
for (auto I = LogicalModules.begin(), E = LogicalModules.end(); I != E;
|
||||
++I) {
|
||||
getBaseLayer().removeModuleSet(I->GVsAndStubsHandle);
|
||||
for (auto H : I->ImplHandles)
|
||||
getBaseLayer().removeModuleSet(H);
|
||||
}
|
||||
}
|
||||
|
||||
CompileOnDemandLayer &CODLayer;
|
||||
LogicalModuleList LogicalModules;
|
||||
std::vector<std::unique_ptr<UncompiledPartition>> UncompiledPartitions;
|
||||
struct LogicalDylibResources {
|
||||
typedef std::function<RuntimeDyld::SymbolInfo(const std::string&)>
|
||||
SymbolResolverFtor;
|
||||
SymbolResolverFtor ExternalSymbolResolver;
|
||||
PartitioningFtor Partitioner;
|
||||
};
|
||||
|
||||
template <typename ResolverPtrT>
|
||||
class LogicalDylibImpl : public LogicalDylib {
|
||||
public:
|
||||
LogicalDylibImpl(CompileOnDemandLayer &CODLayer, ResolverPtrT Resolver)
|
||||
: LogicalDylib(CODLayer), Resolver(std::move(Resolver)) {}
|
||||
typedef LogicalDylib<BaseLayerT, LogicalModuleResources,
|
||||
LogicalDylibResources> CODLogicalDylib;
|
||||
|
||||
RuntimeDyld::SymbolInfo
|
||||
findSymbolExternally(const std::string &Name) const override {
|
||||
return Resolver->findSymbol(Name);
|
||||
}
|
||||
|
||||
private:
|
||||
ResolverPtrT Resolver;
|
||||
};
|
||||
|
||||
template <typename ResolverPtrT>
|
||||
static std::unique_ptr<LogicalDylib>
|
||||
createLogicalDylib(CompileOnDemandLayer &CODLayer,
|
||||
ResolverPtrT Resolver) {
|
||||
typedef LogicalDylibImpl<ResolverPtrT> Impl;
|
||||
return llvm::make_unique<Impl>(CODLayer, std::move(Resolver));
|
||||
}
|
||||
|
||||
// Uncompiled partition.
|
||||
//
|
||||
// Represents one as-yet uncompiled portion of a module.
|
||||
class UncompiledPartition {
|
||||
public:
|
||||
|
||||
struct PartitionEntry {
|
||||
PartitionEntry(Function *F, TargetAddress CallbackID)
|
||||
: F(F), CallbackID(CallbackID) {}
|
||||
Function *F;
|
||||
TargetAddress CallbackID;
|
||||
};
|
||||
|
||||
typedef std::vector<PartitionEntry> PartitionEntryList;
|
||||
|
||||
// Creates an uncompiled partition with the list of functions that make up
|
||||
// this partition.
|
||||
UncompiledPartition(LogicalDylib &LD, typename LogicalDylib::LMHandle LMH,
|
||||
std::shared_ptr<Module> SrcM)
|
||||
: LD(LD), LMH(LMH), SrcM(std::move(SrcM)), ID(~0U) {}
|
||||
|
||||
~UncompiledPartition() {
|
||||
// FIXME: When we want to support threaded lazy compilation we'll need to
|
||||
// lock the callback manager here.
|
||||
auto &CCMgr = LD.getCODLayer().CompileCallbackMgr;
|
||||
for (auto PEntry : PartitionEntries)
|
||||
CCMgr.releaseCompileCallback(PEntry.CallbackID);
|
||||
}
|
||||
|
||||
// Set the ID for this partition.
|
||||
void setID(typename LogicalDylib::UncompiledPartitionID ID) {
|
||||
this->ID = ID;
|
||||
}
|
||||
|
||||
// Set the function set and callbacks for this partition.
|
||||
void setPartitionEntries(PartitionEntryList PartitionEntries) {
|
||||
this->PartitionEntries = std::move(PartitionEntries);
|
||||
}
|
||||
|
||||
// Handle a compile callback for the function at index FnIdx.
|
||||
TargetAddress compile(unsigned FnIdx) {
|
||||
// Take ownership of self. This will ensure we delete the partition and
|
||||
// free all its resources once we're done compiling.
|
||||
std::unique_ptr<UncompiledPartition> This = LD.takeUPOwnership(ID);
|
||||
|
||||
// Release all other compile callbacks for this partition.
|
||||
// We skip the callback for this function because that's the one that
|
||||
// called us, and the callback manager will already have removed it.
|
||||
auto &CCMgr = LD.getCODLayer().CompileCallbackMgr;
|
||||
for (unsigned I = 0; I < PartitionEntries.size(); ++I)
|
||||
if (I != FnIdx)
|
||||
CCMgr.releaseCompileCallback(PartitionEntries[I].CallbackID);
|
||||
|
||||
// Grab the name of the function being called here.
|
||||
Function *F = PartitionEntries[FnIdx].F;
|
||||
std::string CalledFnName = Mangle(F->getName(), SrcM->getDataLayout());
|
||||
|
||||
// Extract the function and add it to the base layer.
|
||||
auto PartitionImplH = emitPartition();
|
||||
LD.addToLogicalModule(LMH, PartitionImplH);
|
||||
|
||||
// Update body pointers.
|
||||
// FIXME: When we start supporting remote lazy jitting this will need to
|
||||
// be replaced with a user-supplied callback for updating the
|
||||
// remote pointers.
|
||||
TargetAddress CalledAddr = 0;
|
||||
for (unsigned I = 0; I < PartitionEntries.size(); ++I) {
|
||||
auto F = PartitionEntries[I].F;
|
||||
std::string FName(F->getName());
|
||||
auto FnBodySym =
|
||||
LD.getBaseLayer().findSymbolIn(PartitionImplH,
|
||||
Mangle(FName, SrcM->getDataLayout()),
|
||||
false);
|
||||
auto FnPtrSym =
|
||||
LD.getBaseLayer().findSymbolIn(LD.getGVsAndStubsHandle(LMH),
|
||||
Mangle(FName + "$orc_addr",
|
||||
SrcM->getDataLayout()),
|
||||
false);
|
||||
assert(FnBodySym && "Couldn't find function body.");
|
||||
assert(FnPtrSym && "Couldn't find function body pointer.");
|
||||
|
||||
auto FnBodyAddr = FnBodySym.getAddress();
|
||||
void *FnPtrAddr = reinterpret_cast<void*>(
|
||||
static_cast<uintptr_t>(FnPtrSym.getAddress()));
|
||||
|
||||
// If this is the function we're calling record the address so we can
|
||||
// return it from this function.
|
||||
if (I == FnIdx)
|
||||
CalledAddr = FnBodyAddr;
|
||||
|
||||
memcpy(FnPtrAddr, &FnBodyAddr, sizeof(uintptr_t));
|
||||
}
|
||||
|
||||
// Finally, clear the partition structure so we don't try to
|
||||
// double-release the callbacks in the UncompiledPartition destructor.
|
||||
PartitionEntries.clear();
|
||||
|
||||
return CalledAddr;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
BaseLayerModuleSetHandleT emitPartition() {
|
||||
// Create the module.
|
||||
std::string NewName(SrcM->getName());
|
||||
for (auto &PEntry : PartitionEntries) {
|
||||
NewName += ".";
|
||||
NewName += PEntry.F->getName();
|
||||
}
|
||||
auto PM = llvm::make_unique<Module>(NewName, SrcM->getContext());
|
||||
PM->setDataLayout(SrcM->getDataLayout());
|
||||
ValueToValueMapTy VMap;
|
||||
GlobalDeclMaterializer GDM(*PM);
|
||||
|
||||
// Create decls in the new module.
|
||||
for (auto &PEntry : PartitionEntries)
|
||||
cloneFunctionDecl(*PM, *PEntry.F, &VMap);
|
||||
|
||||
// Move the function bodies.
|
||||
for (auto &PEntry : PartitionEntries)
|
||||
moveFunctionBody(*PEntry.F, VMap);
|
||||
|
||||
// Create memory manager and symbol resolver.
|
||||
auto MemMgr = llvm::make_unique<SectionMemoryManager>();
|
||||
auto Resolver = createLambdaResolver(
|
||||
[this](const std::string &Name) {
|
||||
if (auto Symbol = LD.findSymbolInternally(LMH, Name))
|
||||
return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
|
||||
Symbol.getFlags());
|
||||
return LD.findSymbolExternally(Name);
|
||||
},
|
||||
[this](const std::string &Name) {
|
||||
if (auto Symbol = LD.findSymbolInternally(LMH, Name))
|
||||
return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
|
||||
Symbol.getFlags());
|
||||
return RuntimeDyld::SymbolInfo(nullptr);
|
||||
});
|
||||
std::vector<std::unique_ptr<Module>> PartMSet;
|
||||
PartMSet.push_back(std::move(PM));
|
||||
return LD.getBaseLayer().addModuleSet(std::move(PartMSet),
|
||||
std::move(MemMgr),
|
||||
std::move(Resolver));
|
||||
}
|
||||
|
||||
LogicalDylib &LD;
|
||||
typename LogicalDylib::LMHandle LMH;
|
||||
std::shared_ptr<Module> SrcM;
|
||||
typename LogicalDylib::UncompiledPartitionID ID;
|
||||
PartitionEntryList PartitionEntries;
|
||||
};
|
||||
|
||||
typedef std::list<std::unique_ptr<LogicalDylib>> LogicalDylibList;
|
||||
typedef typename CODLogicalDylib::LogicalModuleHandle LogicalModuleHandle;
|
||||
typedef std::list<CODLogicalDylib> LogicalDylibList;
|
||||
|
||||
public:
|
||||
/// @brief Handle to a set of loaded modules.
|
||||
typedef typename LogicalDylibList::iterator ModuleSetHandleT;
|
||||
|
||||
/// @brief Construct a compile-on-demand layer instance.
|
||||
CompileOnDemandLayer(BaseLayerT &BaseLayer, CompileCallbackMgrT &CallbackMgr)
|
||||
: BaseLayer(BaseLayer), CompileCallbackMgr(CallbackMgr) {}
|
||||
CompileOnDemandLayer(BaseLayerT &BaseLayer, CompileCallbackMgrT &CallbackMgr,
|
||||
bool CloneStubsIntoPartitions)
|
||||
: BaseLayer(BaseLayer), CompileCallbackMgr(CallbackMgr),
|
||||
CloneStubsIntoPartitions(CloneStubsIntoPartitions) {}
|
||||
|
||||
/// @brief Add a module to the compile-on-demand layer.
|
||||
template <typename ModuleSetT, typename MemoryManagerPtrT,
|
||||
|
@ -382,20 +114,25 @@ public:
|
|||
assert(MemMgr == nullptr &&
|
||||
"User supplied memory managers not supported with COD yet.");
|
||||
|
||||
LogicalDylibs.push_back(createLogicalDylib(*this, std::move(Resolver)));
|
||||
LogicalDylibs.push_back(CODLogicalDylib(BaseLayer));
|
||||
auto &LDResources = LogicalDylibs.back().getDylibResources();
|
||||
|
||||
LDResources.ExternalSymbolResolver =
|
||||
[Resolver](const std::string &Name) {
|
||||
return Resolver->findSymbol(Name);
|
||||
};
|
||||
|
||||
LDResources.Partitioner =
|
||||
[](Function &F) {
|
||||
std::set<Function*> Partition;
|
||||
Partition.insert(&F);
|
||||
return Partition;
|
||||
};
|
||||
|
||||
// Process each of the modules in this module set.
|
||||
for (auto &M : Ms) {
|
||||
std::vector<std::vector<Function*>> Partitioning;
|
||||
for (auto &F : *M) {
|
||||
if (F.isDeclaration())
|
||||
continue;
|
||||
Partitioning.emplace_back(1, &F);
|
||||
}
|
||||
addLogicalModule(*LogicalDylibs.back(),
|
||||
std::shared_ptr<Module>(std::move(M)),
|
||||
std::move(Partitioning));
|
||||
}
|
||||
for (auto &M : Ms)
|
||||
addLogicalModule(LogicalDylibs.back(),
|
||||
std::shared_ptr<Module>(std::move(M)));
|
||||
|
||||
return std::prev(LogicalDylibs.end());
|
||||
}
|
||||
|
@ -420,13 +157,12 @@ public:
|
|||
/// below this one.
|
||||
JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
|
||||
bool ExportedSymbolsOnly) {
|
||||
return (*H)->findSymbol(Name, ExportedSymbolsOnly);
|
||||
return H->findSymbol(Name, ExportedSymbolsOnly);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void addLogicalModule(LogicalDylib &LD, std::shared_ptr<Module> SrcM,
|
||||
std::vector<std::vector<Function*>> Partitions) {
|
||||
void addLogicalModule(CODLogicalDylib &LD, std::shared_ptr<Module> SrcM) {
|
||||
|
||||
// Bump the linkage and rename any anonymous/privote members in SrcM to
|
||||
// ensure that everything will resolve properly after we partition SrcM.
|
||||
|
@ -434,6 +170,8 @@ private:
|
|||
|
||||
// Create a logical module handle for SrcM within the logical dylib.
|
||||
auto LMH = LD.createLogicalModule();
|
||||
auto &LMResources = LD.getLogicalModuleResources(LMH);
|
||||
LMResources.SourceModule = SrcM;
|
||||
|
||||
// Create the GVs-and-stubs module.
|
||||
auto GVsAndStubsM = llvm::make_unique<Module>(
|
||||
|
@ -442,31 +180,35 @@ private:
|
|||
GVsAndStubsM->setDataLayout(SrcM->getDataLayout());
|
||||
ValueToValueMapTy VMap;
|
||||
|
||||
// Process partitions and create stubs.
|
||||
// Process module and create stubs.
|
||||
// We create the stubs before copying the global variables as we know the
|
||||
// stubs won't refer to any globals (they only refer to their implementation
|
||||
// pointer) so there's no ordering/value-mapping issues.
|
||||
for (auto& Partition : Partitions) {
|
||||
auto &UP = LD.createUncompiledPartition(LMH, SrcM);
|
||||
typename UncompiledPartition::PartitionEntryList PartitionEntries;
|
||||
for (auto &F : Partition) {
|
||||
assert(!F->isDeclaration() &&
|
||||
"Partition should only contain definitions");
|
||||
unsigned FnIdx = PartitionEntries.size();
|
||||
auto CCI = CompileCallbackMgr.getCompileCallback(SrcM->getContext());
|
||||
PartitionEntries.push_back(
|
||||
typename UncompiledPartition::PartitionEntry(F, CCI.getAddress()));
|
||||
Function *StubF = cloneFunctionDecl(*GVsAndStubsM, *F, &VMap);
|
||||
GlobalVariable *FnBodyPtr =
|
||||
createImplPointer(*StubF->getType(), *StubF->getParent(),
|
||||
StubF->getName() + "$orc_addr",
|
||||
createIRTypedAddress(*StubF->getFunctionType(),
|
||||
CCI.getAddress()));
|
||||
makeStub(*StubF, *FnBodyPtr);
|
||||
CCI.setCompileAction([&UP, FnIdx]() { return UP.compile(FnIdx); });
|
||||
}
|
||||
for (auto &F : *SrcM) {
|
||||
|
||||
UP.setPartitionEntries(std::move(PartitionEntries));
|
||||
// Skip declarations.
|
||||
if (F.isDeclaration())
|
||||
continue;
|
||||
|
||||
// Record all functions defined by this module.
|
||||
if (CloneStubsIntoPartitions)
|
||||
LMResources.StubsToClone.insert(&F);
|
||||
|
||||
// For each definition: create a callback, a stub, and a function body
|
||||
// pointer. Initialize the function body pointer to point at the callback,
|
||||
// and set the callback to compile the function body.
|
||||
auto CCInfo = CompileCallbackMgr.getCompileCallback(SrcM->getContext());
|
||||
Function *StubF = cloneFunctionDecl(*GVsAndStubsM, F, &VMap);
|
||||
GlobalVariable *FnBodyPtr =
|
||||
createImplPointer(*StubF->getType(), *StubF->getParent(),
|
||||
StubF->getName() + "$orc_addr",
|
||||
createIRTypedAddress(*StubF->getFunctionType(),
|
||||
CCInfo.getAddress()));
|
||||
makeStub(*StubF, *FnBodyPtr);
|
||||
CCInfo.setCompileAction(
|
||||
[this, &LD, LMH, &F]() {
|
||||
return this->extractAndCompile(LD, LMH, F);
|
||||
});
|
||||
}
|
||||
|
||||
// Now clone the global variable declarations.
|
||||
|
@ -483,12 +225,9 @@ private:
|
|||
// Build a resolver for the stubs module and add it to the base layer.
|
||||
auto GVsAndStubsResolver = createLambdaResolver(
|
||||
[&LD](const std::string &Name) {
|
||||
if (auto Symbol = LD.findSymbol(Name, false))
|
||||
return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
|
||||
Symbol.getFlags());
|
||||
return LD.findSymbolExternally(Name);
|
||||
return LD.getDylibResources().ExternalSymbolResolver(Name);
|
||||
},
|
||||
[&LD](const std::string &Name) {
|
||||
[](const std::string &Name) {
|
||||
return RuntimeDyld::SymbolInfo(nullptr);
|
||||
});
|
||||
|
||||
|
@ -498,7 +237,7 @@ private:
|
|||
BaseLayer.addModuleSet(std::move(GVsAndStubsMSet),
|
||||
llvm::make_unique<SectionMemoryManager>(),
|
||||
std::move(GVsAndStubsResolver));
|
||||
LD.setGVsAndStubsHandle(LMH, GVsAndStubsH);
|
||||
LD.addToLogicalModule(LMH, GVsAndStubsH);
|
||||
}
|
||||
|
||||
static std::string Mangle(StringRef Name, const DataLayout &DL) {
|
||||
|
@ -511,35 +250,104 @@ private:
|
|||
return MangledName;
|
||||
}
|
||||
|
||||
TargetAddress extractAndCompile(CODLogicalDylib &LD,
|
||||
LogicalModuleHandle LMH,
|
||||
Function &F) {
|
||||
Module &SrcM = *LD.getLogicalModuleResources(LMH).SourceModule;
|
||||
|
||||
// If F is a declaration we must already have compiled it.
|
||||
if (F.isDeclaration())
|
||||
return 0;
|
||||
|
||||
// Grab the name of the function being called here.
|
||||
std::string CalledFnName = Mangle(F.getName(), SrcM.getDataLayout());
|
||||
|
||||
auto Partition = LD.getDylibResources().Partitioner(F);
|
||||
auto PartitionH = emitPartition(LD, LMH, Partition);
|
||||
|
||||
TargetAddress CalledAddr = 0;
|
||||
for (auto *SubF : Partition) {
|
||||
std::string FName = SubF->getName();
|
||||
auto FnBodySym =
|
||||
BaseLayer.findSymbolIn(PartitionH, Mangle(FName, SrcM.getDataLayout()),
|
||||
false);
|
||||
auto FnPtrSym =
|
||||
BaseLayer.findSymbolIn(*LD.moduleHandlesBegin(LMH),
|
||||
Mangle(FName + "$orc_addr",
|
||||
SrcM.getDataLayout()),
|
||||
false);
|
||||
assert(FnBodySym && "Couldn't find function body.");
|
||||
assert(FnPtrSym && "Couldn't find function body pointer.");
|
||||
|
||||
TargetAddress FnBodyAddr = FnBodySym.getAddress();
|
||||
void *FnPtrAddr = reinterpret_cast<void*>(
|
||||
static_cast<uintptr_t>(FnPtrSym.getAddress()));
|
||||
|
||||
// If this is the function we're calling record the address so we can
|
||||
// return it from this function.
|
||||
if (SubF == &F)
|
||||
CalledAddr = FnBodyAddr;
|
||||
|
||||
memcpy(FnPtrAddr, &FnBodyAddr, sizeof(uintptr_t));
|
||||
}
|
||||
|
||||
return CalledAddr;
|
||||
}
|
||||
|
||||
template <typename PartitionT>
|
||||
BaseLayerModuleSetHandleT emitPartition(CODLogicalDylib &LD,
|
||||
LogicalModuleHandle LMH,
|
||||
const PartitionT &Partition) {
|
||||
auto &LMResources = LD.getLogicalModuleResources(LMH);
|
||||
Module &SrcM = *LMResources.SourceModule;
|
||||
|
||||
// Create the module.
|
||||
std::string NewName = SrcM.getName();
|
||||
for (auto *F : Partition) {
|
||||
NewName += ".";
|
||||
NewName += F->getName();
|
||||
}
|
||||
|
||||
auto M = llvm::make_unique<Module>(NewName, SrcM.getContext());
|
||||
M->setDataLayout(SrcM.getDataLayout());
|
||||
ValueToValueMapTy VMap;
|
||||
GlobalDeclMaterializer GDM(*M, &LMResources.StubsToClone);
|
||||
|
||||
// Create decls in the new module.
|
||||
for (auto *F : Partition)
|
||||
cloneFunctionDecl(*M, *F, &VMap);
|
||||
|
||||
// Move the function bodies.
|
||||
for (auto *F : Partition)
|
||||
moveFunctionBody(*F, VMap, &GDM);
|
||||
|
||||
// Create memory manager and symbol resolver.
|
||||
auto MemMgr = llvm::make_unique<SectionMemoryManager>();
|
||||
auto Resolver = createLambdaResolver(
|
||||
[this, &LD, LMH](const std::string &Name) {
|
||||
if (auto Symbol = LD.findSymbolInternally(LMH, Name))
|
||||
return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
|
||||
Symbol.getFlags());
|
||||
return LD.getDylibResources().ExternalSymbolResolver(Name);
|
||||
},
|
||||
[this, &LD, LMH](const std::string &Name) {
|
||||
if (auto Symbol = LD.findSymbolInternally(LMH, Name))
|
||||
return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
|
||||
Symbol.getFlags());
|
||||
return RuntimeDyld::SymbolInfo(nullptr);
|
||||
});
|
||||
std::vector<std::unique_ptr<Module>> PartMSet;
|
||||
PartMSet.push_back(std::move(M));
|
||||
return BaseLayer.addModuleSet(std::move(PartMSet), std::move(MemMgr),
|
||||
std::move(Resolver));
|
||||
}
|
||||
|
||||
BaseLayerT &BaseLayer;
|
||||
CompileCallbackMgrT &CompileCallbackMgr;
|
||||
LogicalDylibList LogicalDylibs;
|
||||
bool CloneStubsIntoPartitions;
|
||||
};
|
||||
|
||||
template <typename BaseLayerT, typename CompileCallbackMgrT>
|
||||
typename CompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT>::
|
||||
UncompiledPartition&
|
||||
CompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT>::LogicalDylib::
|
||||
createUncompiledPartition(LMHandle LMH, std::shared_ptr<Module> SrcM) {
|
||||
UncompiledPartitions.push_back(
|
||||
llvm::make_unique<UncompiledPartition>(*this, LMH, std::move(SrcM)));
|
||||
UncompiledPartitions.back()->setID(UncompiledPartitions.size() - 1);
|
||||
return *UncompiledPartitions.back();
|
||||
}
|
||||
|
||||
template <typename BaseLayerT, typename CompileCallbackMgrT>
|
||||
std::unique_ptr<typename CompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT>::
|
||||
UncompiledPartition>
|
||||
CompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT>::LogicalDylib::
|
||||
takeUPOwnership(UncompiledPartitionID ID) {
|
||||
|
||||
std::swap(UncompiledPartitions[ID], UncompiledPartitions.back());
|
||||
UncompiledPartitions[ID]->setID(ID);
|
||||
auto UP = std::move(UncompiledPartitions.back());
|
||||
UncompiledPartitions.pop_back();
|
||||
return UP;
|
||||
}
|
||||
|
||||
} // End namespace orc.
|
||||
} // End namespace llvm.
|
||||
|
||||
|
|
115
include/llvm/ExecutionEngine/Orc/LogicalDylib.h
Normal file
115
include/llvm/ExecutionEngine/Orc/LogicalDylib.h
Normal file
|
@ -0,0 +1,115 @@
|
|||
//===--- LogicalDylib.h - Simulates dylib-style symbol lookup ---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Simulates symbol resolution inside a dylib.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_EXECUTIONENGINE_ORC_LOGICALDYLIB_H
|
||||
#define LLVM_EXECUTIONENGINE_ORC_LOGICALDYLIB_H
|
||||
|
||||
namespace llvm {
|
||||
namespace orc {
|
||||
|
||||
template <typename BaseLayerT,
|
||||
typename LogicalModuleResources,
|
||||
typename LogicalDylibResources>
|
||||
class LogicalDylib {
|
||||
public:
|
||||
typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
|
||||
private:
|
||||
|
||||
typedef std::vector<BaseLayerModuleSetHandleT> BaseLayerHandleList;
|
||||
|
||||
struct LogicalModule {
|
||||
LogicalModuleResources Resources;
|
||||
BaseLayerHandleList BaseLayerHandles;
|
||||
};
|
||||
typedef std::vector<LogicalModule> LogicalModuleList;
|
||||
|
||||
public:
|
||||
|
||||
typedef typename BaseLayerHandleList::iterator BaseLayerHandleIterator;
|
||||
typedef typename LogicalModuleList::iterator LogicalModuleHandle;
|
||||
|
||||
LogicalDylib(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
|
||||
|
||||
~LogicalDylib() {
|
||||
for (auto &LM : LogicalModules)
|
||||
for (auto BLH : LM.BaseLayerHandles)
|
||||
BaseLayer.removeModuleSet(BLH);
|
||||
}
|
||||
|
||||
LogicalModuleHandle createLogicalModule() {
|
||||
LogicalModules.push_back(LogicalModule());
|
||||
return std::prev(LogicalModules.end());
|
||||
}
|
||||
|
||||
void addToLogicalModule(LogicalModuleHandle LMH,
|
||||
BaseLayerModuleSetHandleT BaseLayerHandle) {
|
||||
LMH->BaseLayerHandles.push_back(BaseLayerHandle);
|
||||
}
|
||||
|
||||
LogicalModuleResources& getLogicalModuleResources(LogicalModuleHandle LMH) {
|
||||
return LMH->Resources;
|
||||
}
|
||||
|
||||
BaseLayerHandleIterator moduleHandlesBegin(LogicalModuleHandle LMH) {
|
||||
return LMH->BaseLayerHandles.begin();
|
||||
}
|
||||
|
||||
BaseLayerHandleIterator moduleHandlesEnd(LogicalModuleHandle LMH) {
|
||||
return LMH->BaseLayerHandles.end();
|
||||
}
|
||||
|
||||
JITSymbol findSymbolInLogicalModule(LogicalModuleHandle LMH,
|
||||
const std::string &Name) {
|
||||
for (auto BLH : LMH->BaseLayerHandles)
|
||||
if (auto Symbol = BaseLayer.findSymbolIn(BLH, Name, false))
|
||||
return Symbol;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JITSymbol findSymbolInternally(LogicalModuleHandle LMH,
|
||||
const std::string &Name) {
|
||||
if (auto Symbol = findSymbolInLogicalModule(LMH, Name))
|
||||
return Symbol;
|
||||
|
||||
for (auto LMI = LogicalModules.begin(), LME = LogicalModules.end();
|
||||
LMI != LME; ++LMI) {
|
||||
if (LMI != LMH)
|
||||
if (auto Symbol = findSymbolInLogicalModule(LMI, Name))
|
||||
return Symbol;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
|
||||
for (auto &LM : LogicalModules)
|
||||
for (auto BLH : LM.BaseLayerHandles)
|
||||
if (auto Symbol =
|
||||
BaseLayer.findSymbolIn(BLH, Name, ExportedSymbolsOnly))
|
||||
return Symbol;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LogicalDylibResources& getDylibResources() { return DylibResources; }
|
||||
|
||||
protected:
|
||||
BaseLayerT BaseLayer;
|
||||
LogicalModuleList LogicalModules;
|
||||
LogicalDylibResources DylibResources;
|
||||
|
||||
};
|
||||
|
||||
} // End namespace orc.
|
||||
} // End namespace llvm.
|
||||
|
||||
#endif // LLVM_EXECUTIONENGINE_ORC_LOGICALDYLIB_H
|
|
@ -15,6 +15,7 @@
|
|||
#define LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H
|
||||
|
||||
#include "JITSymbolFlags.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Memory.h"
|
||||
#include "llvm/DebugInfo/DIContext.h"
|
||||
|
@ -62,8 +63,6 @@ public:
|
|||
unsigned EndIdx)
|
||||
: RTDyld(RTDyld), BeginIdx(BeginIdx), EndIdx(EndIdx) { }
|
||||
|
||||
virtual ~LoadedObjectInfo() = default;
|
||||
|
||||
virtual object::OwningBinary<object::ObjectFile>
|
||||
getObjectForDebug(const object::ObjectFile &Obj) const = 0;
|
||||
|
||||
|
@ -80,8 +79,8 @@ public:
|
|||
LoadedObjectInfoHelper(RuntimeDyldImpl &RTDyld, unsigned BeginIdx,
|
||||
unsigned EndIdx)
|
||||
: LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {}
|
||||
llvm::LoadedObjectInfo *clone() const override {
|
||||
return new Derived(static_cast<const Derived &>(*this));
|
||||
std::unique_ptr<llvm::LoadedObjectInfo> clone() const override {
|
||||
return llvm::make_unique<Derived>(static_cast<const Derived &>(*this));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -108,6 +108,7 @@ public:
|
|||
StackProtect, ///< Stack protection.
|
||||
StackProtectReq, ///< Stack protection required.
|
||||
StackProtectStrong, ///< Strong Stack protection.
|
||||
SafeStack, ///< Safe Stack protection.
|
||||
StructRet, ///< Hidden pointer to structure to return
|
||||
SanitizeAddress, ///< AddressSanitizer is on.
|
||||
SanitizeThread, ///< ThreadSanitizer is on.
|
||||
|
|
|
@ -32,6 +32,7 @@ class LLVMContextImpl;
|
|||
class Twine;
|
||||
class Value;
|
||||
class DebugLoc;
|
||||
class SMDiagnostic;
|
||||
|
||||
/// \brief Defines the different supported severity of a diagnostic.
|
||||
enum DiagnosticSeverity {
|
||||
|
@ -56,6 +57,7 @@ enum DiagnosticKind {
|
|||
DK_OptimizationRemarkMissed,
|
||||
DK_OptimizationRemarkAnalysis,
|
||||
DK_OptimizationFailure,
|
||||
DK_MIRParser,
|
||||
DK_FirstPluginKind
|
||||
};
|
||||
|
||||
|
@ -386,6 +388,24 @@ public:
|
|||
bool isEnabled() const override;
|
||||
};
|
||||
|
||||
/// Diagnostic information for machine IR parser.
|
||||
class DiagnosticInfoMIRParser : public DiagnosticInfo {
|
||||
const SMDiagnostic &Diagnostic;
|
||||
|
||||
public:
|
||||
DiagnosticInfoMIRParser(DiagnosticSeverity Severity,
|
||||
const SMDiagnostic &Diagnostic)
|
||||
: DiagnosticInfo(DK_MIRParser, Severity), Diagnostic(Diagnostic) {}
|
||||
|
||||
const SMDiagnostic &getDiagnostic() const { return Diagnostic; }
|
||||
|
||||
void print(DiagnosticPrinter &DP) const override;
|
||||
|
||||
static bool classof(const DiagnosticInfo *DI) {
|
||||
return DI->getKind() == DK_MIRParser;
|
||||
}
|
||||
};
|
||||
|
||||
// Create wrappers for C Binding types (see CBindingWrapping.h).
|
||||
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DiagnosticInfo, LLVMDiagnosticInfoRef)
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace llvm {
|
|||
// Forward declarations.
|
||||
class Module;
|
||||
class raw_ostream;
|
||||
class SMDiagnostic;
|
||||
class StringRef;
|
||||
class Twine;
|
||||
class Value;
|
||||
|
@ -51,6 +52,9 @@ public:
|
|||
// IR related types.
|
||||
virtual DiagnosticPrinter &operator<<(const Value &V) = 0;
|
||||
virtual DiagnosticPrinter &operator<<(const Module &M) = 0;
|
||||
|
||||
// Other types.
|
||||
virtual DiagnosticPrinter &operator<<(const SMDiagnostic &Diag) = 0;
|
||||
};
|
||||
|
||||
/// \brief Basic diagnostic printer that uses an underlying raw_ostream.
|
||||
|
@ -81,6 +85,9 @@ public:
|
|||
// IR related types.
|
||||
DiagnosticPrinter &operator<<(const Value &V) override;
|
||||
DiagnosticPrinter &operator<<(const Module &M) override;
|
||||
|
||||
// Other types.
|
||||
DiagnosticPrinter &operator<<(const SMDiagnostic &Diag) override;
|
||||
};
|
||||
} // End namespace llvm
|
||||
|
||||
|
|
|
@ -83,11 +83,12 @@ protected:
|
|||
|
||||
unsigned ThreadLocal : 3; // Is this symbol "Thread Local", if so, what is
|
||||
// the desired model?
|
||||
static const unsigned GlobalValueSubClassDataBits = 19;
|
||||
|
||||
private:
|
||||
// Give subclasses access to what otherwise would be wasted padding.
|
||||
// (19 + 3 + 2 + 1 + 2 + 5) == 32.
|
||||
unsigned SubClassData : 19;
|
||||
unsigned SubClassData : GlobalValueSubClassDataBits;
|
||||
|
||||
protected:
|
||||
/// \brief The intrinsic ID for this subclass (which must be a Function).
|
||||
|
@ -98,12 +99,11 @@ protected:
|
|||
/// This is stored here to save space in Function on 64-bit hosts.
|
||||
Intrinsic::ID IntID;
|
||||
|
||||
static const unsigned GlobalValueSubClassDataBits = 19;
|
||||
unsigned getGlobalValueSubClassData() const {
|
||||
return SubClassData;
|
||||
}
|
||||
void setGlobalValueSubClassData(unsigned V) {
|
||||
assert(V < (1 << 19) && "It will not fit");
|
||||
assert(V < (1 << GlobalValueSubClassDataBits) && "It will not fit");
|
||||
SubClassData = V;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,8 @@ public:
|
|||
bool isExternallyInitialized = false);
|
||||
|
||||
~GlobalVariable() override {
|
||||
NumOperands = 1; // FIXME: needed by operator delete
|
||||
// FIXME: needed by operator delete
|
||||
setGlobalVariableNumOperands(1);
|
||||
}
|
||||
|
||||
/// Provide fast operand accessors
|
||||
|
|
|
@ -2226,7 +2226,7 @@ class PHINode : public Instruction {
|
|||
PHINode(const PHINode &PN);
|
||||
// allocate space for exactly zero operands
|
||||
void *operator new(size_t s) {
|
||||
return User::operator new(s, 0);
|
||||
return User::operator new(s);
|
||||
}
|
||||
explicit PHINode(Type *Ty, unsigned NumReservedValues,
|
||||
const Twine &NameStr = "",
|
||||
|
@ -2234,7 +2234,7 @@ class PHINode : public Instruction {
|
|||
: Instruction(Ty, Instruction::PHI, nullptr, 0, InsertBefore),
|
||||
ReservedSpace(NumReservedValues) {
|
||||
setName(NameStr);
|
||||
OperandList = allocHungoffUses(ReservedSpace);
|
||||
allocHungoffUses(ReservedSpace);
|
||||
}
|
||||
|
||||
PHINode(Type *Ty, unsigned NumReservedValues, const Twine &NameStr,
|
||||
|
@ -2242,13 +2242,15 @@ class PHINode : public Instruction {
|
|||
: Instruction(Ty, Instruction::PHI, nullptr, 0, InsertAtEnd),
|
||||
ReservedSpace(NumReservedValues) {
|
||||
setName(NameStr);
|
||||
OperandList = allocHungoffUses(ReservedSpace);
|
||||
allocHungoffUses(ReservedSpace);
|
||||
}
|
||||
protected:
|
||||
// allocHungoffUses - this is more complicated than the generic
|
||||
// User::allocHungoffUses, because we have to allocate Uses for the incoming
|
||||
// values and pointers to the incoming blocks, all in one allocation.
|
||||
Use *allocHungoffUses(unsigned) const;
|
||||
void allocHungoffUses(unsigned N) {
|
||||
User::allocHungoffUses(N, /* IsPhi */ true);
|
||||
}
|
||||
|
||||
PHINode *clone_impl() const override;
|
||||
public:
|
||||
|
@ -2263,7 +2265,6 @@ public:
|
|||
const Twine &NameStr, BasicBlock *InsertAtEnd) {
|
||||
return new PHINode(Ty, NumReservedValues, NameStr, InsertAtEnd);
|
||||
}
|
||||
~PHINode() override;
|
||||
|
||||
/// Provide fast operand accessors
|
||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
||||
|
@ -2349,12 +2350,12 @@ public:
|
|||
assert(BB && "PHI node got a null basic block!");
|
||||
assert(getType() == V->getType() &&
|
||||
"All operands to PHI node must be the same type as the PHI node!");
|
||||
if (NumOperands == ReservedSpace)
|
||||
if (getNumOperands() == ReservedSpace)
|
||||
growOperands(); // Get more space!
|
||||
// Initialize some new operands.
|
||||
++NumOperands;
|
||||
setIncomingValue(NumOperands - 1, V);
|
||||
setIncomingBlock(NumOperands - 1, BB);
|
||||
setNumHungOffUseOperands(getNumOperands() + 1);
|
||||
setIncomingValue(getNumOperands() - 1, V);
|
||||
setIncomingBlock(getNumOperands() - 1, BB);
|
||||
}
|
||||
|
||||
/// removeIncomingValue - Remove an incoming value. This is useful if a
|
||||
|
@ -2433,7 +2434,7 @@ private:
|
|||
void *operator new(size_t, unsigned) = delete;
|
||||
// Allocate space for exactly zero operands.
|
||||
void *operator new(size_t s) {
|
||||
return User::operator new(s, 0);
|
||||
return User::operator new(s);
|
||||
}
|
||||
void growOperands(unsigned Size);
|
||||
void init(Value *PersFn, unsigned NumReservedValues, const Twine &NameStr);
|
||||
|
@ -2456,7 +2457,6 @@ public:
|
|||
static LandingPadInst *Create(Type *RetTy, Value *PersonalityFn,
|
||||
unsigned NumReservedClauses,
|
||||
const Twine &NameStr, BasicBlock *InsertAtEnd);
|
||||
~LandingPadInst() override;
|
||||
|
||||
/// Provide fast operand accessors
|
||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
||||
|
@ -2482,17 +2482,17 @@ public:
|
|||
/// Get the value of the clause at index Idx. Use isCatch/isFilter to
|
||||
/// determine what type of clause this is.
|
||||
Constant *getClause(unsigned Idx) const {
|
||||
return cast<Constant>(OperandList[Idx + 1]);
|
||||
return cast<Constant>(getOperandList()[Idx + 1]);
|
||||
}
|
||||
|
||||
/// isCatch - Return 'true' if the clause and index Idx is a catch clause.
|
||||
bool isCatch(unsigned Idx) const {
|
||||
return !isa<ArrayType>(OperandList[Idx + 1]->getType());
|
||||
return !isa<ArrayType>(getOperandList()[Idx + 1]->getType());
|
||||
}
|
||||
|
||||
/// isFilter - Return 'true' if the clause and index Idx is a filter clause.
|
||||
bool isFilter(unsigned Idx) const {
|
||||
return isa<ArrayType>(OperandList[Idx + 1]->getType());
|
||||
return isa<ArrayType>(getOperandList()[Idx + 1]->getType());
|
||||
}
|
||||
|
||||
/// getNumClauses - Get the number of clauses for this landing pad.
|
||||
|
@ -2708,7 +2708,7 @@ class SwitchInst : public TerminatorInst {
|
|||
void growOperands();
|
||||
// allocate space for exactly zero operands
|
||||
void *operator new(size_t s) {
|
||||
return User::operator new(s, 0);
|
||||
return User::operator new(s);
|
||||
}
|
||||
/// SwitchInst ctor - Create a new switch instruction, specifying a value to
|
||||
/// switch on and a default destination. The number of additional cases can
|
||||
|
@ -2855,8 +2855,6 @@ public:
|
|||
return new SwitchInst(Value, Default, NumCases, InsertAtEnd);
|
||||
}
|
||||
|
||||
~SwitchInst() override;
|
||||
|
||||
/// Provide fast operand accessors
|
||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
||||
|
||||
|
@ -3017,7 +3015,7 @@ class IndirectBrInst : public TerminatorInst {
|
|||
void growOperands();
|
||||
// allocate space for exactly zero operands
|
||||
void *operator new(size_t s) {
|
||||
return User::operator new(s, 0);
|
||||
return User::operator new(s);
|
||||
}
|
||||
/// IndirectBrInst ctor - Create a new indirectbr instruction, specifying an
|
||||
/// Address to jump to. The number of expected destinations can be specified
|
||||
|
@ -3041,7 +3039,6 @@ public:
|
|||
BasicBlock *InsertAtEnd) {
|
||||
return new IndirectBrInst(Address, NumDests, InsertAtEnd);
|
||||
}
|
||||
~IndirectBrInst() override;
|
||||
|
||||
/// Provide fast operand accessors.
|
||||
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
|
||||
|
|
|
@ -428,8 +428,7 @@ def int_eh_endcatch : Intrinsic<[], []>;
|
|||
// Represents the list of actions to take when an exception is thrown.
|
||||
def int_eh_actions : Intrinsic<[llvm_ptr_ty], [llvm_vararg_ty], []>;
|
||||
|
||||
def int_eh_exceptioncode : Intrinsic<[llvm_i32_ty], []>;
|
||||
def int_eh_exceptioninfo : Intrinsic<[llvm_ptr_ty], []>;
|
||||
def int_eh_exceptioncode : Intrinsic<[llvm_i32_ty], [], [IntrReadMem]>;
|
||||
|
||||
// __builtin_unwind_init is an undocumented GCC intrinsic that causes all
|
||||
// callee-saved registers to be saved and restored (regardless of whether they
|
||||
|
@ -537,7 +536,8 @@ def int_experimental_patchpoint_i64 : Intrinsic<[llvm_i64_ty],
|
|||
def int_experimental_gc_statepoint : Intrinsic<[llvm_i32_ty],
|
||||
[llvm_i64_ty, llvm_i32_ty,
|
||||
llvm_anyptr_ty, llvm_i32_ty,
|
||||
llvm_i32_ty, llvm_vararg_ty]>;
|
||||
llvm_i32_ty, llvm_vararg_ty],
|
||||
[Throws]>;
|
||||
|
||||
def int_experimental_gc_result : Intrinsic<[llvm_any_ty], [llvm_i32_ty]>;
|
||||
def int_experimental_gc_relocate : Intrinsic<[llvm_anyptr_ty],
|
||||
|
|
|
@ -608,6 +608,11 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.".
|
|||
def int_ppc_altivec_vsel : GCCBuiltin<"__builtin_altivec_vsel_4si">,
|
||||
Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty,
|
||||
llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>;
|
||||
def int_ppc_altivec_vgbbd : GCCBuiltin<"__builtin_altivec_vgbbd">,
|
||||
Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty], [IntrNoMem]>;
|
||||
def int_ppc_altivec_vbpermq : GCCBuiltin<"__builtin_altivec_vbpermq">,
|
||||
Intrinsic<[llvm_v2i64_ty], [llvm_v16i8_ty, llvm_v16i8_ty],
|
||||
[IntrNoMem]>;
|
||||
}
|
||||
|
||||
def int_ppc_altivec_vexptefp : PowerPC_Vec_FF_Intrinsic<"vexptefp">;
|
||||
|
|
|
@ -18,9 +18,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
|||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SEH LSDA for Windows
|
||||
// SEH intrinsics for Windows
|
||||
let TargetPrefix = "x86" in {
|
||||
def int_x86_seh_lsda : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], [IntrNoMem]>;
|
||||
def int_x86_seh_exceptioninfo : Intrinsic<[llvm_ptr_ty],
|
||||
[llvm_ptr_ty, llvm_ptr_ty],
|
||||
[IntrReadMem]>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -2995,6 +2998,20 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
|||
def int_x86_avx512_cvtusi642sd : GCCBuiltin<"__builtin_ia32_cvtusi642sd">,
|
||||
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
|
||||
llvm_i64_ty], [IntrNoMem]>;
|
||||
|
||||
def int_x86_avx512_cvtsi2ss32 : GCCBuiltin<"__builtin_ia32_cvtsi2ss32">,
|
||||
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty,
|
||||
llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_x86_avx512_cvtsi2ss64 : GCCBuiltin<"__builtin_ia32_cvtsi2ss64">,
|
||||
Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty,
|
||||
llvm_i64_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_x86_avx512_cvtsi2sd32 : GCCBuiltin<"__builtin_ia32_cvtsi2sd32">,
|
||||
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
|
||||
llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
def int_x86_avx512_cvtsi2sd64 : GCCBuiltin<"__builtin_ia32_cvtsi2sd64">,
|
||||
Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty,
|
||||
llvm_i64_ty, llvm_i32_ty], [IntrNoMem]>;
|
||||
|
||||
}
|
||||
|
||||
// Pack ops.
|
||||
|
|
|
@ -512,28 +512,28 @@ public:
|
|||
const GlobalListType &getGlobalList() const { return GlobalList; }
|
||||
/// Get the Module's list of global variables.
|
||||
GlobalListType &getGlobalList() { return GlobalList; }
|
||||
static iplist<GlobalVariable> Module::*getSublistAccess(GlobalVariable*) {
|
||||
static GlobalListType Module::*getSublistAccess(GlobalVariable*) {
|
||||
return &Module::GlobalList;
|
||||
}
|
||||
/// Get the Module's list of functions (constant).
|
||||
const FunctionListType &getFunctionList() const { return FunctionList; }
|
||||
/// Get the Module's list of functions.
|
||||
FunctionListType &getFunctionList() { return FunctionList; }
|
||||
static iplist<Function> Module::*getSublistAccess(Function*) {
|
||||
static FunctionListType Module::*getSublistAccess(Function*) {
|
||||
return &Module::FunctionList;
|
||||
}
|
||||
/// Get the Module's list of aliases (constant).
|
||||
const AliasListType &getAliasList() const { return AliasList; }
|
||||
/// Get the Module's list of aliases.
|
||||
AliasListType &getAliasList() { return AliasList; }
|
||||
static iplist<GlobalAlias> Module::*getSublistAccess(GlobalAlias*) {
|
||||
static AliasListType Module::*getSublistAccess(GlobalAlias*) {
|
||||
return &Module::AliasList;
|
||||
}
|
||||
/// Get the Module's list of named metadata (constant).
|
||||
const NamedMDListType &getNamedMDList() const { return NamedMDList; }
|
||||
/// Get the Module's list of named metadata.
|
||||
NamedMDListType &getNamedMDList() { return NamedMDList; }
|
||||
static ilist<NamedMDNode> Module::*getSublistAccess(NamedMDNode*) {
|
||||
static NamedMDListType Module::*getSublistAccess(NamedMDNode*) {
|
||||
return &Module::NamedMDList;
|
||||
}
|
||||
/// Get the symbol table of global variable and function identifiers
|
||||
|
|
|
@ -92,10 +92,10 @@ struct VariadicOperandTraits {
|
|||
template <unsigned MINARITY = 1>
|
||||
struct HungoffOperandTraits {
|
||||
static Use *op_begin(User* U) {
|
||||
return U->OperandList;
|
||||
return U->getOperandList();
|
||||
}
|
||||
static Use *op_end(User* U) {
|
||||
return U->OperandList + U->getNumOperands();
|
||||
return U->getOperandList() + U->getNumOperands();
|
||||
}
|
||||
static unsigned operands(const User *U) {
|
||||
return U->getNumOperands();
|
||||
|
|
|
@ -34,33 +34,45 @@ struct OperandTraits;
|
|||
|
||||
class User : public Value {
|
||||
User(const User &) = delete;
|
||||
void *operator new(size_t) = delete;
|
||||
template <unsigned>
|
||||
friend struct HungoffOperandTraits;
|
||||
virtual void anchor();
|
||||
protected:
|
||||
/// \brief This is a pointer to the array of Uses for this User.
|
||||
///
|
||||
/// For nodes of fixed arity (e.g. a binary operator) this array will live
|
||||
/// prefixed to some derived class instance. For nodes of resizable variable
|
||||
/// arity (e.g. PHINodes, SwitchInst etc.), this memory will be dynamically
|
||||
/// allocated and should be destroyed by the classes' virtual dtor.
|
||||
Use *OperandList;
|
||||
|
||||
void *operator new(size_t s, unsigned Us);
|
||||
protected:
|
||||
/// Allocate a User with an operand pointer co-allocated.
|
||||
///
|
||||
/// This is used for subclasses which need to allocate a variable number
|
||||
/// of operands, ie, 'hung off uses'.
|
||||
void *operator new(size_t Size);
|
||||
|
||||
/// Allocate a User with the operands co-allocated.
|
||||
///
|
||||
/// This is used for subclasses which have a fixed number of operands.
|
||||
void *operator new(size_t Size, unsigned Us);
|
||||
|
||||
User(Type *ty, unsigned vty, Use *OpList, unsigned NumOps)
|
||||
: Value(ty, vty), OperandList(OpList) {
|
||||
NumOperands = NumOps;
|
||||
}
|
||||
Use *allocHungoffUses(unsigned) const;
|
||||
void dropHungoffUses() {
|
||||
Use::zap(OperandList, OperandList + NumOperands, true);
|
||||
OperandList = nullptr;
|
||||
// Reset NumOperands so User::operator delete() does the right thing.
|
||||
NumOperands = 0;
|
||||
: Value(ty, vty) {
|
||||
assert(NumOps < (1u << NumUserOperandsBits) && "Too many operands");
|
||||
NumUserOperands = NumOps;
|
||||
// If we have hung off uses, then the operand list should initially be
|
||||
// null.
|
||||
assert((!HasHungOffUses || !getOperandList()) &&
|
||||
"Error in initializing hung off uses for User");
|
||||
}
|
||||
|
||||
/// \brief Allocate the array of Uses, followed by a pointer
|
||||
/// (with bottom bit set) to the User.
|
||||
/// \param IsPhi identifies callers which are phi nodes and which need
|
||||
/// N BasicBlock* allocated along with N
|
||||
void allocHungoffUses(unsigned N, bool IsPhi = false);
|
||||
|
||||
/// \brief Grow the number of hung off uses. Note that allocHungoffUses
|
||||
/// should be called if there are no uses.
|
||||
void growHungoffUses(unsigned N, bool IsPhi = false);
|
||||
|
||||
public:
|
||||
~User() override { Use::zap(OperandList, OperandList + NumOperands); }
|
||||
~User() override {
|
||||
}
|
||||
/// \brief Free memory allocated for User and Use objects.
|
||||
void operator delete(void *Usr);
|
||||
/// \brief Placement delete - required by std, but never called.
|
||||
|
@ -83,28 +95,68 @@ protected:
|
|||
template <int Idx> const Use &Op() const {
|
||||
return OpFrom<Idx>(this);
|
||||
}
|
||||
private:
|
||||
Use *&getHungOffOperands() { return *(reinterpret_cast<Use **>(this) - 1); }
|
||||
|
||||
Use *getIntrusiveOperands() {
|
||||
return reinterpret_cast<Use *>(this) - NumUserOperands;
|
||||
}
|
||||
|
||||
void setOperandList(Use *NewList) {
|
||||
assert(HasHungOffUses &&
|
||||
"Setting operand list only required for hung off uses");
|
||||
getHungOffOperands() = NewList;
|
||||
}
|
||||
public:
|
||||
Use *getOperandList() {
|
||||
return HasHungOffUses ? getHungOffOperands() : getIntrusiveOperands();
|
||||
}
|
||||
const Use *getOperandList() const {
|
||||
return const_cast<User *>(this)->getOperandList();
|
||||
}
|
||||
Value *getOperand(unsigned i) const {
|
||||
assert(i < NumOperands && "getOperand() out of range!");
|
||||
return OperandList[i];
|
||||
assert(i < NumUserOperands && "getOperand() out of range!");
|
||||
return getOperandList()[i];
|
||||
}
|
||||
void setOperand(unsigned i, Value *Val) {
|
||||
assert(i < NumOperands && "setOperand() out of range!");
|
||||
assert(i < NumUserOperands && "setOperand() out of range!");
|
||||
assert((!isa<Constant>((const Value*)this) ||
|
||||
isa<GlobalValue>((const Value*)this)) &&
|
||||
"Cannot mutate a constant with setOperand!");
|
||||
OperandList[i] = Val;
|
||||
getOperandList()[i] = Val;
|
||||
}
|
||||
const Use &getOperandUse(unsigned i) const {
|
||||
assert(i < NumOperands && "getOperandUse() out of range!");
|
||||
return OperandList[i];
|
||||
assert(i < NumUserOperands && "getOperandUse() out of range!");
|
||||
return getOperandList()[i];
|
||||
}
|
||||
Use &getOperandUse(unsigned i) {
|
||||
assert(i < NumOperands && "getOperandUse() out of range!");
|
||||
return OperandList[i];
|
||||
assert(i < NumUserOperands && "getOperandUse() out of range!");
|
||||
return getOperandList()[i];
|
||||
}
|
||||
|
||||
unsigned getNumOperands() const { return NumOperands; }
|
||||
unsigned getNumOperands() const { return NumUserOperands; }
|
||||
|
||||
/// Set the number of operands on a GlobalVariable.
|
||||
///
|
||||
/// GlobalVariable always allocates space for a single operands, but
|
||||
/// doesn't always use it.
|
||||
///
|
||||
/// FIXME: As that the number of operands is used to find the start of
|
||||
/// the allocated memory in operator delete, we need to always think we have
|
||||
/// 1 operand before delete.
|
||||
void setGlobalVariableNumOperands(unsigned NumOps) {
|
||||
assert(NumOps <= 1 && "GlobalVariable can only have 0 or 1 operands");
|
||||
NumUserOperands = NumOps;
|
||||
}
|
||||
|
||||
/// \brief Subclasses with hung off uses need to manage the operand count
|
||||
/// themselves. In these instances, the operand count isn't used to find the
|
||||
/// OperandList, so there's no issue in having the operand count change.
|
||||
void setNumHungOffUseOperands(unsigned NumOps) {
|
||||
assert(HasHungOffUses && "Must have hung off uses to use this method");
|
||||
assert(NumOps < (1u << NumUserOperandsBits) && "Too many operands");
|
||||
NumUserOperands = NumOps;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Operand Iterator interface...
|
||||
|
@ -114,14 +166,18 @@ public:
|
|||
typedef iterator_range<op_iterator> op_range;
|
||||
typedef iterator_range<const_op_iterator> const_op_range;
|
||||
|
||||
inline op_iterator op_begin() { return OperandList; }
|
||||
inline const_op_iterator op_begin() const { return OperandList; }
|
||||
inline op_iterator op_end() { return OperandList+NumOperands; }
|
||||
inline const_op_iterator op_end() const { return OperandList+NumOperands; }
|
||||
inline op_range operands() {
|
||||
op_iterator op_begin() { return getOperandList(); }
|
||||
const_op_iterator op_begin() const { return getOperandList(); }
|
||||
op_iterator op_end() {
|
||||
return getOperandList() + NumUserOperands;
|
||||
}
|
||||
const_op_iterator op_end() const {
|
||||
return getOperandList() + NumUserOperands;
|
||||
}
|
||||
op_range operands() {
|
||||
return op_range(op_begin(), op_end());
|
||||
}
|
||||
inline const_op_range operands() const {
|
||||
const_op_range operands() const {
|
||||
return const_op_range(op_begin(), op_end());
|
||||
}
|
||||
|
||||
|
@ -136,13 +192,13 @@ public:
|
|||
Value *operator->() const { return operator*(); }
|
||||
};
|
||||
|
||||
inline value_op_iterator value_op_begin() {
|
||||
value_op_iterator value_op_begin() {
|
||||
return value_op_iterator(op_begin());
|
||||
}
|
||||
inline value_op_iterator value_op_end() {
|
||||
value_op_iterator value_op_end() {
|
||||
return value_op_iterator(op_end());
|
||||
}
|
||||
inline iterator_range<value_op_iterator> operand_values() {
|
||||
iterator_range<value_op_iterator> operand_values() {
|
||||
return iterator_range<value_op_iterator>(value_op_begin(), value_op_end());
|
||||
}
|
||||
|
||||
|
|
|
@ -100,10 +100,15 @@ protected:
|
|||
/// This is stored here to save space in User on 64-bit hosts. Since most
|
||||
/// instances of Value have operands, 32-bit hosts aren't significantly
|
||||
/// affected.
|
||||
unsigned NumOperands : 30;
|
||||
///
|
||||
/// Note, this should *NOT* be used directly by any class other than User.
|
||||
/// User uses this value to find the Use list.
|
||||
static const unsigned NumUserOperandsBits = 29;
|
||||
unsigned NumUserOperands : 29;
|
||||
|
||||
bool IsUsedByMD : 1;
|
||||
bool HasName : 1;
|
||||
bool HasHungOffUses : 1;
|
||||
|
||||
private:
|
||||
template <typename UseT> // UseT == 'Use' or 'const Use'
|
||||
|
|
|
@ -187,6 +187,7 @@ void initializeMachineBlockPlacementPass(PassRegistry&);
|
|||
void initializeMachineBlockPlacementStatsPass(PassRegistry&);
|
||||
void initializeMachineBranchProbabilityInfoPass(PassRegistry&);
|
||||
void initializeMachineCSEPass(PassRegistry&);
|
||||
void initializeImplicitNullChecksPass(PassRegistry&);
|
||||
void initializeMachineDominatorTreePass(PassRegistry&);
|
||||
void initializeMachineDominanceFrontierPass(PassRegistry&);
|
||||
void initializeMachinePostDominatorTreePass(PassRegistry&);
|
||||
|
@ -241,6 +242,7 @@ void initializeRegionOnlyViewerPass(PassRegistry&);
|
|||
void initializeRegionPrinterPass(PassRegistry&);
|
||||
void initializeRegionViewerPass(PassRegistry&);
|
||||
void initializeRewriteStatepointsForGCPass(PassRegistry&);
|
||||
void initializeSafeStackPass(PassRegistry&);
|
||||
void initializeSCCPPass(PassRegistry&);
|
||||
void initializeSROAPass(PassRegistry&);
|
||||
void initializeSROA_DTPass(PassRegistry&);
|
||||
|
|
24
include/llvm/LibDriver/LibDriver.h
Normal file
24
include/llvm/LibDriver/LibDriver.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
//===- llvm/LibDriver/LibDriver.h - lib.exe-compatible driver ---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Defines an interface to a lib.exe-compatible driver that also understands
|
||||
// bitcode files. Used by llvm-lib and lld-link2 /lib.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBDRIVER_LIBDRIVER_H
|
||||
#define LLVM_LIBDRIVER_LIBDRIVER_H
|
||||
|
||||
namespace llvm {
|
||||
|
||||
int libDriverMain(int argc, const char **argv);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -98,7 +98,7 @@ namespace {
|
|||
(void) llvm::createLICMPass();
|
||||
(void) llvm::createLazyValueInfoPass();
|
||||
(void) llvm::createLoopExtractorPass();
|
||||
(void)llvm::createLoopInterchangePass();
|
||||
(void) llvm::createLoopInterchangePass();
|
||||
(void) llvm::createLoopSimplifyPass();
|
||||
(void) llvm::createLoopStrengthReducePass();
|
||||
(void) llvm::createLoopRerollPass();
|
||||
|
@ -131,6 +131,7 @@ namespace {
|
|||
(void) llvm::createRegionPrinterPass();
|
||||
(void) llvm::createRegionViewerPass();
|
||||
(void) llvm::createSCCPPass();
|
||||
(void) llvm::createSafeStackPass();
|
||||
(void) llvm::createScalarReplAggregatesPass();
|
||||
(void) llvm::createSingleLoopExtractorPass();
|
||||
(void) llvm::createStripSymbolsPass();
|
||||
|
|
|
@ -155,6 +155,10 @@ protected:
|
|||
/// Defaults to false.
|
||||
bool AllowAtInName;
|
||||
|
||||
/// If this is true, symbol names with invalid characters will be printed in
|
||||
/// quotes.
|
||||
bool SupportsQuotedNames;
|
||||
|
||||
/// This is true if data region markers should be printed as
|
||||
/// ".data_region/.end_data_region" directives. If false, use "$d/$a" labels
|
||||
/// instead.
|
||||
|
@ -406,6 +410,10 @@ public:
|
|||
unsigned Encoding,
|
||||
MCStreamer &Streamer) const;
|
||||
|
||||
/// Return true if the identifier \p Name does not need quotes to be
|
||||
/// syntactically correct.
|
||||
virtual bool isValidUnquotedName(StringRef Name) const;
|
||||
|
||||
bool usesSunStyleELFSectionSwitchSyntax() const {
|
||||
return SunStyleELFSectionSwitchSyntax;
|
||||
}
|
||||
|
@ -456,6 +464,7 @@ public:
|
|||
const char *getCode64Directive() const { return Code64Directive; }
|
||||
unsigned getAssemblerDialect() const { return AssemblerDialect; }
|
||||
bool doesAllowAtInName() const { return AllowAtInName; }
|
||||
bool supportsNameQuoting() const { return SupportsQuotedNames; }
|
||||
bool doesSupportDataRegionDirectives() const {
|
||||
return UseDataRegionDirectives;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@ public:
|
|||
void reset() override {
|
||||
SeenIdent = false;
|
||||
LocalCommons.clear();
|
||||
BindingExplicitlySet.clear();
|
||||
BundleGroups.clear();
|
||||
MCObjectStreamer::reset();
|
||||
}
|
||||
|
@ -106,8 +105,6 @@ private:
|
|||
|
||||
std::vector<LocalCommon> LocalCommons;
|
||||
|
||||
SmallPtrSet<MCSymbol *, 16> BindingExplicitlySet;
|
||||
|
||||
/// BundleGroups - The stack of fragments holding the bundle-locked
|
||||
/// instructions.
|
||||
llvm::SmallVector<MCDataFragment *, 4> BundleGroups;
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
//===- MCELFSymbolFlags.h - ELF Symbol Flags ----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares the SymbolFlags used for the ELF target.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_MC_MCELFSYMBOLFLAGS_H
|
||||
#define LLVM_MC_MCELFSYMBOLFLAGS_H
|
||||
|
||||
#include "llvm/Support/ELF.h"
|
||||
|
||||
// Because all the symbol flags need to be stored in the MCSymbol
|
||||
// 'flags' variable we need to provide shift constants per flag type.
|
||||
|
||||
namespace llvm {
|
||||
enum {
|
||||
ELF_STT_Shift = 0, // Shift value for STT_* flags.
|
||||
ELF_STB_Shift = 4, // Shift value for STB_* flags.
|
||||
ELF_STV_Shift = 8, // Shift value for STV_* flags.
|
||||
ELF_STO_Shift = 10 // Shift value for STO_* flags.
|
||||
};
|
||||
|
||||
enum ELFSymbolFlags {
|
||||
ELF_STB_Local = (ELF::STB_LOCAL << ELF_STB_Shift),
|
||||
ELF_STB_Global = (ELF::STB_GLOBAL << ELF_STB_Shift),
|
||||
ELF_STB_Weak = (ELF::STB_WEAK << ELF_STB_Shift),
|
||||
ELF_STB_Loproc = (ELF::STB_LOPROC << ELF_STB_Shift),
|
||||
ELF_STB_Hiproc = (ELF::STB_HIPROC << ELF_STB_Shift),
|
||||
|
||||
ELF_STT_Notype = (ELF::STT_NOTYPE << ELF_STT_Shift),
|
||||
ELF_STT_Object = (ELF::STT_OBJECT << ELF_STT_Shift),
|
||||
ELF_STT_Func = (ELF::STT_FUNC << ELF_STT_Shift),
|
||||
ELF_STT_Section = (ELF::STT_SECTION << ELF_STT_Shift),
|
||||
ELF_STT_File = (ELF::STT_FILE << ELF_STT_Shift),
|
||||
ELF_STT_Common = (ELF::STT_COMMON << ELF_STT_Shift),
|
||||
ELF_STT_Tls = (ELF::STT_TLS << ELF_STT_Shift),
|
||||
ELF_STT_GnuIFunc = (ELF::STT_GNU_IFUNC << ELF_STT_Shift),
|
||||
ELF_STT_Loproc = (ELF::STT_LOPROC << ELF_STT_Shift),
|
||||
ELF_STT_Hiproc = (ELF::STT_HIPROC << ELF_STT_Shift),
|
||||
|
||||
ELF_STV_Default = (ELF::STV_DEFAULT << ELF_STV_Shift),
|
||||
ELF_STV_Internal = (ELF::STV_INTERNAL << ELF_STV_Shift),
|
||||
ELF_STV_Hidden = (ELF::STV_HIDDEN << ELF_STV_Shift),
|
||||
ELF_STV_Protected = (ELF::STV_PROTECTED << ELF_STV_Shift)
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
|
@ -72,7 +72,7 @@ public:
|
|||
/// \name Utility Methods
|
||||
/// @{
|
||||
|
||||
void print(raw_ostream &OS) const;
|
||||
void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
|
||||
void dump() const;
|
||||
|
||||
/// @}
|
||||
|
@ -121,7 +121,7 @@ public:
|
|||
};
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const MCExpr &E) {
|
||||
E.print(OS);
|
||||
E.print(OS, nullptr);
|
||||
return OS;
|
||||
}
|
||||
|
||||
|
@ -551,8 +551,7 @@ protected:
|
|||
MCTargetExpr() : MCExpr(Target) {}
|
||||
virtual ~MCTargetExpr() {}
|
||||
public:
|
||||
|
||||
virtual void printImpl(raw_ostream &OS) const = 0;
|
||||
virtual void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const = 0;
|
||||
virtual bool evaluateAsRelocatableImpl(MCValue &Res,
|
||||
const MCAsmLayout *Layout,
|
||||
const MCFixup *Fixup) const = 0;
|
||||
|
|
|
@ -167,11 +167,11 @@ public:
|
|||
|
||||
void addOperand(const MCOperand &Op) { Operands.push_back(Op); }
|
||||
|
||||
void clear() { Operands.clear(); }
|
||||
size_t size() const { return Operands.size(); }
|
||||
|
||||
typedef SmallVectorImpl<MCOperand>::iterator iterator;
|
||||
typedef SmallVectorImpl<MCOperand>::const_iterator const_iterator;
|
||||
void clear() { Operands.clear(); }
|
||||
void erase(iterator I) { Operands.erase(I); }
|
||||
size_t size() const { return Operands.size(); }
|
||||
iterator begin() { return Operands.begin(); }
|
||||
const_iterator begin() const { return Operands.begin(); }
|
||||
iterator end() { return Operands.end(); }
|
||||
|
|
|
@ -89,8 +89,8 @@ public:
|
|||
bool getPrintImmHex() const { return PrintImmHex; }
|
||||
void setPrintImmHex(bool Value) { PrintImmHex = Value; }
|
||||
|
||||
HexStyle::Style getPrintHexStyleHex() const { return PrintHexStyle; }
|
||||
void setPrintImmHex(HexStyle::Style Value) { PrintHexStyle = Value; }
|
||||
HexStyle::Style getPrintHexStyle() const { return PrintHexStyle; }
|
||||
void setPrintHexStyle(HexStyle::Style Value) { PrintHexStyle = Value; }
|
||||
|
||||
/// Utility function to print immediates in decimal or hex.
|
||||
format_object<int64_t> formatImm(int64_t Value) const {
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
//===- MCMachOSymbolFlags.h - MachO Symbol Flags ----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares the SymbolFlags used for the MachO target.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_MC_MCMACHOSYMBOLFLAGS_H
|
||||
#define LLVM_MC_MCMACHOSYMBOLFLAGS_H
|
||||
|
||||
// These flags are mostly used in MCMachOStreamer.cpp but also needed in
|
||||
// MachObjectWriter.cpp to test for Weak Definitions of symbols to emit
|
||||
// the correct relocation information.
|
||||
|
||||
namespace llvm {
|
||||
/// MachOSymbolFlags - We store the value for the 'desc' symbol field in the
|
||||
/// lowest 16 bits of the implementation defined flags.
|
||||
enum MachOSymbolFlags { // See <mach-o/nlist.h>.
|
||||
SF_DescFlagsMask = 0xFFFF,
|
||||
|
||||
// Reference type flags.
|
||||
SF_ReferenceTypeMask = 0x0007,
|
||||
SF_ReferenceTypeUndefinedNonLazy = 0x0000,
|
||||
SF_ReferenceTypeUndefinedLazy = 0x0001,
|
||||
SF_ReferenceTypeDefined = 0x0002,
|
||||
SF_ReferenceTypePrivateDefined = 0x0003,
|
||||
SF_ReferenceTypePrivateUndefinedNonLazy = 0x0004,
|
||||
SF_ReferenceTypePrivateUndefinedLazy = 0x0005,
|
||||
|
||||
// Other 'desc' flags.
|
||||
SF_ThumbFunc = 0x0008,
|
||||
SF_NoDeadStrip = 0x0020,
|
||||
SF_WeakReference = 0x0040,
|
||||
SF_WeakDefinition = 0x0080,
|
||||
SF_SymbolResolver = 0x0100
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
|
@ -27,15 +27,11 @@ class MCMachObjectTargetWriter {
|
|||
const unsigned Is64Bit : 1;
|
||||
const uint32_t CPUType;
|
||||
const uint32_t CPUSubtype;
|
||||
// FIXME: Remove this, we should just always use it once we no longer care
|
||||
// about Darwin 'as' compatibility.
|
||||
const unsigned UseAggressiveSymbolFolding : 1;
|
||||
unsigned LocalDifference_RIT;
|
||||
|
||||
protected:
|
||||
MCMachObjectTargetWriter(bool Is64Bit_, uint32_t CPUType_,
|
||||
uint32_t CPUSubtype_,
|
||||
bool UseAggressiveSymbolFolding_ = false);
|
||||
uint32_t CPUSubtype_);
|
||||
|
||||
void setLocalDifferenceRelocationType(unsigned Type) {
|
||||
LocalDifference_RIT = Type;
|
||||
|
@ -47,7 +43,7 @@ public:
|
|||
/// \name Lifetime Management
|
||||
/// @{
|
||||
|
||||
virtual void reset() {};
|
||||
virtual void reset() {}
|
||||
|
||||
/// @}
|
||||
|
||||
|
@ -55,7 +51,6 @@ public:
|
|||
/// @{
|
||||
|
||||
bool is64Bit() const { return Is64Bit; }
|
||||
bool useAggressiveSymbolFolding() const { return UseAggressiveSymbolFolding; }
|
||||
uint32_t getCPUType() const { return CPUType; }
|
||||
uint32_t getCPUSubtype() const { return CPUSubtype; }
|
||||
unsigned getLocalDifferenceRelocationType() const {
|
||||
|
@ -67,7 +62,7 @@ public:
|
|||
/// \name API
|
||||
/// @{
|
||||
|
||||
virtual void RecordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
|
||||
virtual void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
|
@ -77,8 +72,7 @@ public:
|
|||
};
|
||||
|
||||
class MachObjectWriter : public MCObjectWriter {
|
||||
/// MachSymbolData - Helper struct for containing some precomputed information
|
||||
/// on symbols.
|
||||
/// Helper struct for containing some precomputed information on symbols.
|
||||
struct MachSymbolData {
|
||||
const MCSymbol *Symbol;
|
||||
uint64_t StringIndex;
|
||||
|
@ -104,6 +98,8 @@ class MachObjectWriter : public MCObjectWriter {
|
|||
llvm::DenseMap<const MCSection *, std::vector<RelAndSymbol>> Relocations;
|
||||
llvm::DenseMap<const MCSection *, unsigned> IndirectSymBase;
|
||||
|
||||
SectionAddrMap SectionAddress;
|
||||
|
||||
/// @}
|
||||
/// \name Symbol Table Data
|
||||
/// @{
|
||||
|
@ -136,8 +132,6 @@ public:
|
|||
|
||||
bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind);
|
||||
|
||||
SectionAddrMap SectionAddress;
|
||||
|
||||
SectionAddrMap &getSectionAddressMap() { return SectionAddress; }
|
||||
|
||||
uint64_t getSectionAddress(const MCSection *Sec) const {
|
||||
|
@ -165,41 +159,37 @@ public:
|
|||
|
||||
/// @}
|
||||
|
||||
void WriteHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize,
|
||||
void writeHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize,
|
||||
bool SubsectionsViaSymbols);
|
||||
|
||||
/// WriteSegmentLoadCommand - Write a segment load command.
|
||||
/// Write a segment load command.
|
||||
///
|
||||
/// \param NumSections The number of sections in this segment.
|
||||
/// \param SectionDataSize The total size of the sections.
|
||||
void WriteSegmentLoadCommand(unsigned NumSections,
|
||||
uint64_t VMSize,
|
||||
void writeSegmentLoadCommand(unsigned NumSections, uint64_t VMSize,
|
||||
uint64_t SectionDataStartOffset,
|
||||
uint64_t SectionDataSize);
|
||||
|
||||
void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
void writeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
const MCSection &Sec, uint64_t FileOffset,
|
||||
uint64_t RelocationsStart, unsigned NumRelocations);
|
||||
|
||||
void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
|
||||
void writeSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
|
||||
uint32_t StringTableOffset,
|
||||
uint32_t StringTableSize);
|
||||
|
||||
void WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol,
|
||||
uint32_t NumLocalSymbols,
|
||||
uint32_t FirstExternalSymbol,
|
||||
uint32_t NumExternalSymbols,
|
||||
uint32_t FirstUndefinedSymbol,
|
||||
uint32_t NumUndefinedSymbols,
|
||||
uint32_t IndirectSymbolOffset,
|
||||
uint32_t NumIndirectSymbols);
|
||||
void writeDysymtabLoadCommand(
|
||||
uint32_t FirstLocalSymbol, uint32_t NumLocalSymbols,
|
||||
uint32_t FirstExternalSymbol, uint32_t NumExternalSymbols,
|
||||
uint32_t FirstUndefinedSymbol, uint32_t NumUndefinedSymbols,
|
||||
uint32_t IndirectSymbolOffset, uint32_t NumIndirectSymbols);
|
||||
|
||||
void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout);
|
||||
void writeNlist(MachSymbolData &MSD, const MCAsmLayout &Layout);
|
||||
|
||||
void WriteLinkeditLoadCommand(uint32_t Type, uint32_t DataOffset,
|
||||
void writeLinkeditLoadCommand(uint32_t Type, uint32_t DataOffset,
|
||||
uint32_t DataSize);
|
||||
|
||||
void WriteLinkerOptionsLoadCommand(const std::vector<std::string> &Options);
|
||||
void writeLinkerOptionsLoadCommand(const std::vector<std::string> &Options);
|
||||
|
||||
// FIXME: We really need to improve the relocation validation. Basically, we
|
||||
// want to implement a separate computation which evaluates the relocation
|
||||
|
@ -226,29 +216,25 @@ public:
|
|||
Relocations[Sec].push_back(P);
|
||||
}
|
||||
|
||||
void RecordScatteredRelocation(const MCAssembler &Asm,
|
||||
void recordScatteredRelocation(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
unsigned Log2Size,
|
||||
uint64_t &FixedValue);
|
||||
unsigned Log2Size, uint64_t &FixedValue);
|
||||
|
||||
void RecordTLVPRelocation(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
uint64_t &FixedValue);
|
||||
void recordTLVPRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment, const MCFixup &Fixup,
|
||||
MCValue Target, uint64_t &FixedValue);
|
||||
|
||||
void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment, const MCFixup &Fixup,
|
||||
MCValue Target, bool &IsPCRel,
|
||||
uint64_t &FixedValue) override;
|
||||
|
||||
void BindIndirectSymbols(MCAssembler &Asm);
|
||||
void bindIndirectSymbols(MCAssembler &Asm);
|
||||
|
||||
/// ComputeSymbolTable - Compute the symbol table data
|
||||
///
|
||||
void ComputeSymbolTable(MCAssembler &Asm,
|
||||
/// Compute the symbol table data.
|
||||
void computeSymbolTable(MCAssembler &Asm,
|
||||
std::vector<MachSymbolData> &LocalSymbolData,
|
||||
std::vector<MachSymbolData> &ExternalSymbolData,
|
||||
std::vector<MachSymbolData> &UndefinedSymbolData);
|
||||
|
@ -256,19 +242,18 @@ public:
|
|||
void computeSectionAddresses(const MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout);
|
||||
|
||||
void ExecutePostLayoutBinding(MCAssembler &Asm,
|
||||
void executePostLayoutBinding(MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout) override;
|
||||
|
||||
bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
|
||||
bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
|
||||
const MCSymbol &SymA,
|
||||
const MCFragment &FB, bool InSet,
|
||||
bool IsPCRel) const override;
|
||||
|
||||
void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
|
||||
void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
|
||||
};
|
||||
|
||||
|
||||
/// \brief Construct a new Mach-O writer instance.
|
||||
/// Construct a new Mach-O writer instance.
|
||||
///
|
||||
/// This routine takes ownership of the target writer subclass.
|
||||
///
|
||||
|
|
|
@ -18,28 +18,25 @@
|
|||
#include "llvm/Support/CodeGen.h"
|
||||
|
||||
namespace llvm {
|
||||
class MCContext;
|
||||
class MCSection;
|
||||
class StringRef;
|
||||
class MCContext;
|
||||
class MCSection;
|
||||
class StringRef;
|
||||
|
||||
class MCObjectFileInfo {
|
||||
protected:
|
||||
/// CommDirectiveSupportsAlignment - True if .comm supports alignment. This
|
||||
/// is a hack for as long as we support 10.4 Tiger, whose assembler doesn't
|
||||
/// support alignment on comm.
|
||||
/// True if .comm supports alignment. This is a hack for as long as we
|
||||
/// support 10.4 Tiger, whose assembler doesn't support alignment on comm.
|
||||
bool CommDirectiveSupportsAlignment;
|
||||
|
||||
/// SupportsWeakEmptyEHFrame - True if target object file supports a
|
||||
/// weak_definition of constant 0 for an omitted EH frame.
|
||||
/// True if target object file supports a weak_definition of constant 0 for an
|
||||
/// omitted EH frame.
|
||||
bool SupportsWeakOmittedEHFrame;
|
||||
|
||||
/// SupportsCompactUnwindWithoutEHFrame - True if the target object file
|
||||
/// supports emitting a compact unwind section without an associated EH frame
|
||||
/// section.
|
||||
/// True if the target object file supports emitting a compact unwind section
|
||||
/// without an associated EH frame section.
|
||||
bool SupportsCompactUnwindWithoutEHFrame;
|
||||
|
||||
/// PersonalityEncoding, LSDAEncoding, TTypeEncoding - Some encoding values
|
||||
/// for EH.
|
||||
/// Some encoding values for EH.
|
||||
unsigned PersonalityEncoding;
|
||||
unsigned LSDAEncoding;
|
||||
unsigned FDECFIEncoding;
|
||||
|
@ -49,16 +46,13 @@ protected:
|
|||
unsigned EHSectionType;
|
||||
unsigned EHSectionFlags;
|
||||
|
||||
/// CompactUnwindDwarfEHFrameOnly - Compact unwind encoding indicating that we
|
||||
/// should emit only an EH frame.
|
||||
/// Compact unwind encoding indicating that we should emit only an EH frame.
|
||||
unsigned CompactUnwindDwarfEHFrameOnly;
|
||||
|
||||
/// Section directive for standard text.
|
||||
///
|
||||
MCSection *TextSection;
|
||||
|
||||
/// Section directive for standard data.
|
||||
///
|
||||
MCSection *DataSection;
|
||||
|
||||
/// Section that is default initialized to zero.
|
||||
|
@ -101,7 +95,7 @@ protected:
|
|||
// can be enabled by a compiler flag.
|
||||
MCSection *DwarfPubNamesSection;
|
||||
|
||||
// DWARF5 Experimental Debug Info Sections
|
||||
/// DWARF5 Experimental Debug Info Sections
|
||||
/// DwarfAccelNamesSection, DwarfAccelObjCSection,
|
||||
/// DwarfAccelNamespaceSection, DwarfAccelTypesSection -
|
||||
/// If we use the DWARF accelerated hash tables then we want to emit these
|
||||
|
@ -111,7 +105,7 @@ protected:
|
|||
MCSection *DwarfAccelNamespaceSection;
|
||||
MCSection *DwarfAccelTypesSection;
|
||||
|
||||
/// These are used for the Fission separate debug information files.
|
||||
// These are used for the Fission separate debug information files.
|
||||
MCSection *DwarfInfoDWOSection;
|
||||
MCSection *DwarfTypesDWOSection;
|
||||
MCSection *DwarfAbbrevDWOSection;
|
||||
|
@ -121,32 +115,39 @@ protected:
|
|||
MCSection *DwarfStrOffDWOSection;
|
||||
MCSection *DwarfAddrSection;
|
||||
|
||||
/// Sections for newer gnu pubnames and pubtypes.
|
||||
/// Section for newer gnu pubnames.
|
||||
MCSection *DwarfGnuPubNamesSection;
|
||||
/// Section for newer gnu pubtypes.
|
||||
MCSection *DwarfGnuPubTypesSection;
|
||||
|
||||
MCSection *COFFDebugSymbolsSection;
|
||||
|
||||
// Extra TLS Variable Data section. If the target needs to put additional
|
||||
// information for a TLS variable, it'll go here.
|
||||
/// Extra TLS Variable Data section.
|
||||
///
|
||||
/// If the target needs to put additional information for a TLS variable,
|
||||
/// it'll go here.
|
||||
MCSection *TLSExtraDataSection;
|
||||
|
||||
/// Section directive for Thread Local data. ELF, MachO and COFF.
|
||||
MCSection *TLSDataSection; // Defaults to ".tdata".
|
||||
|
||||
/// Section directive for Thread Local uninitialized data. Null if this target
|
||||
/// doesn't support a BSS section. ELF and MachO only.
|
||||
/// Section directive for Thread Local uninitialized data.
|
||||
///
|
||||
/// Null if this target doesn't support a BSS section. ELF and MachO only.
|
||||
MCSection *TLSBSSSection; // Defaults to ".tbss".
|
||||
|
||||
/// StackMap section.
|
||||
MCSection *StackMapSection;
|
||||
|
||||
/// EH frame section. It is initialized on demand so it can be overwritten
|
||||
/// (with uniquing).
|
||||
/// FaultMap section.
|
||||
MCSection *FaultMapSection;
|
||||
|
||||
/// EH frame section.
|
||||
///
|
||||
/// It is initialized on demand so it can be overwritten (with uniquing).
|
||||
MCSection *EHFrameSection;
|
||||
|
||||
/// ELF specific sections.
|
||||
///
|
||||
// ELF specific sections.
|
||||
MCSection *DataRelSection;
|
||||
const MCSection *DataRelLocalSection;
|
||||
MCSection *DataRelROSection;
|
||||
|
@ -155,17 +156,16 @@ protected:
|
|||
MCSection *MergeableConst8Section;
|
||||
MCSection *MergeableConst16Section;
|
||||
|
||||
/// MachO specific sections.
|
||||
///
|
||||
// MachO specific sections.
|
||||
|
||||
/// Section for thread local structure information. Contains the source code
|
||||
/// name of the variable, visibility and a pointer to the initial value
|
||||
/// (.tdata or .tbss).
|
||||
/// Section for thread local structure information.
|
||||
///
|
||||
/// Contains the source code name of the variable, visibility and a pointer to
|
||||
/// the initial value (.tdata or .tbss).
|
||||
MCSection *TLSTLVSection; // Defaults to ".tlv".
|
||||
|
||||
/// TLSThreadInitSection - Section for thread local data initialization
|
||||
/// functions.
|
||||
const MCSection *TLSThreadInitSection; // Defaults to ".thread_init_func".
|
||||
/// Section for thread local data initialization functions.
|
||||
const MCSection *TLSThreadInitSection; // Defaults to ".thread_init_func".
|
||||
|
||||
MCSection *CStringSection;
|
||||
MCSection *UStringSection;
|
||||
|
@ -182,7 +182,6 @@ protected:
|
|||
MCSection *NonLazySymbolPointerSection;
|
||||
|
||||
/// COFF specific sections.
|
||||
///
|
||||
MCSection *DrectveSection;
|
||||
MCSection *PDataSection;
|
||||
MCSection *XDataSection;
|
||||
|
@ -266,9 +265,9 @@ public:
|
|||
MCSection *getTLSBSSSection() const { return TLSBSSSection; }
|
||||
|
||||
MCSection *getStackMapSection() const { return StackMapSection; }
|
||||
MCSection *getFaultMapSection() const { return FaultMapSection; }
|
||||
|
||||
/// ELF specific sections.
|
||||
///
|
||||
// ELF specific sections.
|
||||
MCSection *getDataRelSection() const { return DataRelSection; }
|
||||
const MCSection *getDataRelLocalSection() const {
|
||||
return DataRelLocalSection;
|
||||
|
@ -285,8 +284,7 @@ public:
|
|||
return MergeableConst16Section;
|
||||
}
|
||||
|
||||
/// MachO specific sections.
|
||||
///
|
||||
// MachO specific sections.
|
||||
const MCSection *getTLSTLVSection() const { return TLSTLVSection; }
|
||||
const MCSection *getTLSThreadInitSection() const {
|
||||
return TLSThreadInitSection;
|
||||
|
@ -317,8 +315,7 @@ public:
|
|||
return NonLazySymbolPointerSection;
|
||||
}
|
||||
|
||||
/// COFF specific sections.
|
||||
///
|
||||
// COFF specific sections.
|
||||
MCSection *getDrectveSection() const { return DrectveSection; }
|
||||
MCSection *getPDataSection() const { return PDataSection; }
|
||||
MCSection *getXDataSection() const { return XDataSection; }
|
||||
|
@ -331,13 +328,9 @@ public:
|
|||
}
|
||||
|
||||
enum Environment { IsMachO, IsELF, IsCOFF };
|
||||
Environment getObjectFileType() const {
|
||||
return Env;
|
||||
}
|
||||
Environment getObjectFileType() const { return Env; }
|
||||
|
||||
Reloc::Model getRelocM() const {
|
||||
return RelocM;
|
||||
}
|
||||
Reloc::Model getRelocM() const { return RelocM; }
|
||||
|
||||
private:
|
||||
Environment Env;
|
||||
|
@ -346,12 +339,11 @@ private:
|
|||
MCContext *Ctx;
|
||||
Triple TT;
|
||||
|
||||
void InitMachOMCObjectFileInfo(Triple T);
|
||||
void InitELFMCObjectFileInfo(Triple T);
|
||||
void InitCOFFMCObjectFileInfo(Triple T);
|
||||
void initMachOMCObjectFileInfo(Triple T);
|
||||
void initELFMCObjectFileInfo(Triple T);
|
||||
void initCOFFMCObjectFileInfo(Triple T);
|
||||
|
||||
/// InitEHFrameSection - Initialize EHFrameSection on demand.
|
||||
///
|
||||
/// Initialize EHFrameSection on demand.
|
||||
void InitEHFrameSection();
|
||||
|
||||
public:
|
||||
|
|
|
@ -56,9 +56,6 @@ public:
|
|||
/// Object streamers require the integrated assembler.
|
||||
bool isIntegratedAssemblerRequired() const override { return true; }
|
||||
|
||||
void getOrCreateSymbolData(const MCSymbol *Symbol) {
|
||||
getAssembler().registerSymbol(*Symbol);
|
||||
}
|
||||
void EmitFrames(MCAsmBackend *MAB);
|
||||
void EmitCFISections(bool EH, bool Debug) override;
|
||||
|
||||
|
@ -138,8 +135,7 @@ public:
|
|||
/// data fragment. Otherwise, do nothing and return \c false.
|
||||
///
|
||||
/// \pre Offset of \c Hi is greater than the offset \c Lo.
|
||||
/// \return true on success.
|
||||
bool emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
|
||||
void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
|
||||
unsigned Size) override;
|
||||
|
||||
bool mayHaveInstructions(MCSection &Sec) const override;
|
||||
|
|
|
@ -25,14 +25,14 @@ class MCFragment;
|
|||
class MCSymbolRefExpr;
|
||||
class MCValue;
|
||||
|
||||
/// MCObjectWriter - Defines the object file and target independent interfaces
|
||||
/// used by the assembler backend to write native file format object files.
|
||||
/// Defines the object file and target independent interfaces used by the
|
||||
/// assembler backend to write native file format object files.
|
||||
///
|
||||
/// The object writer contains a few callbacks used by the assembler to allow
|
||||
/// the object writer to modify the assembler data structures at appropriate
|
||||
/// points. Once assembly is complete, the object writer is given the
|
||||
/// MCAssembler instance, which contains all the symbol and section data which
|
||||
/// should be emitted as part of WriteObject().
|
||||
/// should be emitted as part of writeObject().
|
||||
///
|
||||
/// The object writer also contains a number of helper methods for writing
|
||||
/// binary data to the output stream.
|
||||
|
@ -53,7 +53,7 @@ public:
|
|||
virtual ~MCObjectWriter();
|
||||
|
||||
/// lifetime management
|
||||
virtual void reset() { }
|
||||
virtual void reset() {}
|
||||
|
||||
bool isLittleEndian() const { return IsLittleEndian; }
|
||||
|
||||
|
@ -62,109 +62,106 @@ public:
|
|||
/// \name High-Level API
|
||||
/// @{
|
||||
|
||||
/// \brief Perform any late binding of symbols (for example, to assign symbol
|
||||
/// Perform any late binding of symbols (for example, to assign symbol
|
||||
/// indices for use when generating relocations).
|
||||
///
|
||||
/// This routine is called by the assembler after layout and relaxation is
|
||||
/// complete.
|
||||
virtual void ExecutePostLayoutBinding(MCAssembler &Asm,
|
||||
virtual void executePostLayoutBinding(MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout) = 0;
|
||||
|
||||
/// \brief Record a relocation entry.
|
||||
/// Record a relocation entry.
|
||||
///
|
||||
/// This routine is called by the assembler after layout and relaxation, and
|
||||
/// post layout binding. The implementation is responsible for storing
|
||||
/// information about the relocation so that it can be emitted during
|
||||
/// WriteObject().
|
||||
virtual void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
/// writeObject().
|
||||
virtual void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
const MCFragment *Fragment,
|
||||
const MCFixup &Fixup, MCValue Target,
|
||||
bool &IsPCRel, uint64_t &FixedValue) = 0;
|
||||
|
||||
/// \brief Check whether the difference (A - B) between two symbol
|
||||
/// references is fully resolved.
|
||||
/// Check whether the difference (A - B) between two symbol references is
|
||||
/// fully resolved.
|
||||
///
|
||||
/// Clients are not required to answer precisely and may conservatively return
|
||||
/// false, even when a difference is fully resolved.
|
||||
bool IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
|
||||
bool isSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
|
||||
const MCSymbolRefExpr *A,
|
||||
const MCSymbolRefExpr *B,
|
||||
bool InSet) const;
|
||||
|
||||
virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
|
||||
virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
|
||||
const MCSymbol &SymA,
|
||||
const MCFragment &FB,
|
||||
bool InSet,
|
||||
bool IsPCRel) const;
|
||||
|
||||
/// \brief True if this symbol (which is a variable) is weak. This is not
|
||||
/// True if this symbol (which is a variable) is weak. This is not
|
||||
/// just STB_WEAK, but more generally whether or not we can evaluate
|
||||
/// past it.
|
||||
virtual bool isWeak(const MCSymbol &Sym) const;
|
||||
|
||||
/// \brief Write the object file.
|
||||
/// Write the object file.
|
||||
///
|
||||
/// This routine is called by the assembler after layout and relaxation is
|
||||
/// complete, fixups have been evaluated and applied, and relocations
|
||||
/// generated.
|
||||
virtual void WriteObject(MCAssembler &Asm,
|
||||
const MCAsmLayout &Layout) = 0;
|
||||
virtual void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) = 0;
|
||||
|
||||
/// @}
|
||||
/// \name Binary Output
|
||||
/// @{
|
||||
|
||||
void Write8(uint8_t Value) {
|
||||
OS << char(Value);
|
||||
}
|
||||
void write8(uint8_t Value) { OS << char(Value); }
|
||||
|
||||
void WriteLE16(uint16_t Value) {
|
||||
void writeLE16(uint16_t Value) {
|
||||
support::endian::Writer<support::little>(OS).write(Value);
|
||||
}
|
||||
|
||||
void WriteLE32(uint32_t Value) {
|
||||
void writeLE32(uint32_t Value) {
|
||||
support::endian::Writer<support::little>(OS).write(Value);
|
||||
}
|
||||
|
||||
void WriteLE64(uint64_t Value) {
|
||||
void writeLE64(uint64_t Value) {
|
||||
support::endian::Writer<support::little>(OS).write(Value);
|
||||
}
|
||||
|
||||
void WriteBE16(uint16_t Value) {
|
||||
void writeBE16(uint16_t Value) {
|
||||
support::endian::Writer<support::big>(OS).write(Value);
|
||||
}
|
||||
|
||||
void WriteBE32(uint32_t Value) {
|
||||
void writeBE32(uint32_t Value) {
|
||||
support::endian::Writer<support::big>(OS).write(Value);
|
||||
}
|
||||
|
||||
void WriteBE64(uint64_t Value) {
|
||||
void writeBE64(uint64_t Value) {
|
||||
support::endian::Writer<support::big>(OS).write(Value);
|
||||
}
|
||||
|
||||
void Write16(uint16_t Value) {
|
||||
void write16(uint16_t Value) {
|
||||
if (IsLittleEndian)
|
||||
WriteLE16(Value);
|
||||
writeLE16(Value);
|
||||
else
|
||||
WriteBE16(Value);
|
||||
writeBE16(Value);
|
||||
}
|
||||
|
||||
void Write32(uint32_t Value) {
|
||||
void write32(uint32_t Value) {
|
||||
if (IsLittleEndian)
|
||||
WriteLE32(Value);
|
||||
writeLE32(Value);
|
||||
else
|
||||
WriteBE32(Value);
|
||||
writeBE32(Value);
|
||||
}
|
||||
|
||||
void Write64(uint64_t Value) {
|
||||
void write64(uint64_t Value) {
|
||||
if (IsLittleEndian)
|
||||
WriteLE64(Value);
|
||||
writeLE64(Value);
|
||||
else
|
||||
WriteBE64(Value);
|
||||
writeBE64(Value);
|
||||
}
|
||||
|
||||
void WriteZeros(unsigned N) {
|
||||
const char Zeros[16] = { 0 };
|
||||
const char Zeros[16] = {0};
|
||||
|
||||
for (unsigned i = 0, e = N / 16; i != e; ++i)
|
||||
OS << StringRef(Zeros, 16);
|
||||
|
@ -172,22 +169,23 @@ public:
|
|||
OS << StringRef(Zeros, N % 16);
|
||||
}
|
||||
|
||||
void WriteBytes(const SmallVectorImpl<char> &ByteVec, unsigned ZeroFillSize = 0) {
|
||||
WriteBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize);
|
||||
void writeBytes(const SmallVectorImpl<char> &ByteVec,
|
||||
unsigned ZeroFillSize = 0) {
|
||||
writeBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize);
|
||||
}
|
||||
|
||||
void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
|
||||
void writeBytes(StringRef Str, unsigned ZeroFillSize = 0) {
|
||||
// TODO: this version may need to go away once all fragment contents are
|
||||
// converted to SmallVector<char, N>
|
||||
assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) &&
|
||||
"data size greater than fill size, unexpected large write will occur");
|
||||
assert(
|
||||
(ZeroFillSize == 0 || Str.size() <= ZeroFillSize) &&
|
||||
"data size greater than fill size, unexpected large write will occur");
|
||||
OS << Str;
|
||||
if (ZeroFillSize)
|
||||
WriteZeros(ZeroFillSize - Str.size());
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
|
|
@ -58,7 +58,10 @@ private:
|
|||
MCSymbol *Begin, const MCSectionELF *Associated)
|
||||
: MCSection(SV_ELF, K, Begin), SectionName(Section), Type(type),
|
||||
Flags(flags), UniqueID(UniqueID), EntrySize(entrySize), Group(group),
|
||||
Associated(Associated) {}
|
||||
Associated(Associated) {
|
||||
if (Group)
|
||||
Group->setIsSignature();
|
||||
}
|
||||
~MCSectionELF() override;
|
||||
|
||||
void setSectionName(StringRef Name) { SectionName = Name; }
|
||||
|
|
|
@ -307,11 +307,15 @@ public:
|
|||
bool PopSection() {
|
||||
if (SectionStack.size() <= 1)
|
||||
return false;
|
||||
MCSectionSubPair oldSection = SectionStack.pop_back_val().first;
|
||||
MCSectionSubPair curSection = SectionStack.back().first;
|
||||
auto I = SectionStack.end();
|
||||
--I;
|
||||
MCSectionSubPair OldSection = I->first;
|
||||
--I;
|
||||
MCSectionSubPair NewSection = I->first;
|
||||
|
||||
if (oldSection != curSection)
|
||||
ChangeSection(curSection.first, curSection.second);
|
||||
if (OldSection != NewSection)
|
||||
ChangeSection(NewSection.first, NewSection.second);
|
||||
SectionStack.pop_back();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -632,14 +636,11 @@ public:
|
|||
unsigned Isa, unsigned Discriminator,
|
||||
StringRef FileName);
|
||||
|
||||
/// Emit the absolute difference between two symbols if possible.
|
||||
/// Emit the absolute difference between two symbols.
|
||||
///
|
||||
/// \pre Offset of \c Hi is greater than the offset \c Lo.
|
||||
/// \return true on success.
|
||||
virtual bool emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
|
||||
unsigned Size) {
|
||||
return false;
|
||||
}
|
||||
virtual void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo,
|
||||
unsigned Size);
|
||||
|
||||
virtual MCSymbol *getDwarfLineTableSymbol(unsigned CUID);
|
||||
virtual void EmitCFISections(bool EH, bool Debug);
|
||||
|
|
|
@ -27,7 +27,7 @@ class StringRef;
|
|||
/// MCSubtargetInfo - Generic base class for all target subtargets.
|
||||
///
|
||||
class MCSubtargetInfo {
|
||||
std::string TargetTriple; // Target triple
|
||||
Triple TargetTriple; // Target triple
|
||||
std::string CPU; // CPU being targeted.
|
||||
ArrayRef<SubtargetFeatureKV> ProcFeatures; // Processor feature list
|
||||
ArrayRef<SubtargetFeatureKV> ProcDesc; // Processor descriptions
|
||||
|
@ -45,20 +45,17 @@ class MCSubtargetInfo {
|
|||
FeatureBitset FeatureBits; // Feature bits for current CPU + FS
|
||||
|
||||
public:
|
||||
void InitMCSubtargetInfo(StringRef TT, StringRef CPU, StringRef FS,
|
||||
void InitMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS,
|
||||
ArrayRef<SubtargetFeatureKV> PF,
|
||||
ArrayRef<SubtargetFeatureKV> PD,
|
||||
const SubtargetInfoKV *ProcSched,
|
||||
const MCWriteProcResEntry *WPR,
|
||||
const MCWriteLatencyEntry *WL,
|
||||
const MCReadAdvanceEntry *RA,
|
||||
const InstrStage *IS,
|
||||
const MCReadAdvanceEntry *RA, const InstrStage *IS,
|
||||
const unsigned *OC, const unsigned *FP);
|
||||
|
||||
/// getTargetTriple - Return the target triple string.
|
||||
StringRef getTargetTriple() const {
|
||||
return TargetTriple;
|
||||
}
|
||||
const Triple &getTargetTriple() const { return TargetTriple; }
|
||||
|
||||
/// getCPU - Return the CPU string.
|
||||
StringRef getCPU() const {
|
||||
|
@ -73,7 +70,9 @@ public:
|
|||
|
||||
/// setFeatureBits - Set the feature bits.
|
||||
///
|
||||
void setFeatureBits(FeatureBitset& FeatureBits_) { FeatureBits = FeatureBits_; }
|
||||
void setFeatureBits(const FeatureBitset &FeatureBits_) {
|
||||
FeatureBits = FeatureBits_;
|
||||
}
|
||||
|
||||
/// InitMCProcessorInfo - Set or change the CPU (optionally supplemented with
|
||||
/// feature string). Recompute feature bits and scheduling model.
|
||||
|
@ -94,6 +93,10 @@ public:
|
|||
/// feature bits. This version will also change all implied bits.
|
||||
FeatureBitset ToggleFeature(StringRef FS);
|
||||
|
||||
/// Apply a feature flag and return the re-computed feature bits, including
|
||||
/// all feature bits implied by the flag.
|
||||
FeatureBitset ApplyFeatureFlag(StringRef FS);
|
||||
|
||||
/// getSchedModelForCPU - Get the machine model of a CPU.
|
||||
///
|
||||
MCSchedModel getSchedModelForCPU(StringRef CPU) const;
|
||||
|
|
|
@ -14,12 +14,13 @@
|
|||
#ifndef LLVM_MC_MCSYMBOL_H
|
||||
#define LLVM_MC_MCSYMBOL_H
|
||||
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
||||
namespace llvm {
|
||||
class MCAsmInfo;
|
||||
class MCExpr;
|
||||
class MCSymbol;
|
||||
class MCFragment;
|
||||
|
@ -35,29 +36,33 @@ class raw_ostream;
|
|||
/// Section member is set to indicate what section it lives in. Otherwise, if
|
||||
/// it is a reference to an external entity, it has a null section.
|
||||
class MCSymbol {
|
||||
protected:
|
||||
/// The kind of the symbol. If it is any value other than unset then this
|
||||
/// class is actually one of the appropriate subclasses of MCSymbol.
|
||||
enum SymbolKind {
|
||||
SymbolKindUnset,
|
||||
SymbolKindCOFF,
|
||||
SymbolKindELF,
|
||||
SymbolKindMachO,
|
||||
};
|
||||
|
||||
// Special sentinal value for the absolute pseudo section.
|
||||
//
|
||||
// FIXME: Use a PointerInt wrapper for this?
|
||||
static MCSection *AbsolutePseudoSection;
|
||||
|
||||
/// Name - The name of the symbol. The referred-to string data is actually
|
||||
/// held by the StringMap that lives in MCContext.
|
||||
const StringMapEntry<bool> *Name;
|
||||
|
||||
/// If a symbol has a Fragment, the section is implied, so we only need
|
||||
/// one pointer.
|
||||
/// FIXME: We might be able to simplify this by having the asm streamer create
|
||||
/// dummy fragments.
|
||||
union {
|
||||
/// The section the symbol is defined in. This is null for undefined
|
||||
/// symbols, and the special AbsolutePseudoSection value for absolute
|
||||
/// symbols. If this is a variable symbol, this caches the variable value's
|
||||
/// section.
|
||||
mutable MCSection *Section;
|
||||
|
||||
/// The fragment this symbol's value is relative to, if any.
|
||||
mutable MCFragment *Fragment;
|
||||
};
|
||||
/// If this is a section, then it gives the symbol is defined in. This is null
|
||||
/// for undefined symbols, and the special AbsolutePseudoSection value for
|
||||
/// absolute symbols. If this is a variable symbol, this caches the variable
|
||||
/// value's section.
|
||||
///
|
||||
/// If this is a fragment, then it gives the fragment this symbol's value is
|
||||
/// relative to, if any.
|
||||
mutable PointerUnion<MCSection *, MCFragment *> SectionOrFragment;
|
||||
|
||||
/// Value - If non-null, the value for a variable symbol.
|
||||
const MCExpr *Value;
|
||||
|
@ -81,9 +86,14 @@ class MCSymbol {
|
|||
/// This symbol is private extern.
|
||||
mutable unsigned IsPrivateExtern : 1;
|
||||
|
||||
mutable unsigned HasFragment : 1;
|
||||
/// True if this symbol is named.
|
||||
/// A named symbol will have a pointer to the name allocated in the bytes
|
||||
/// immediately prior to the MCSymbol.
|
||||
unsigned HasName : 1;
|
||||
|
||||
unsigned IsELF : 1;
|
||||
/// LLVM RTTI discriminator. This is actually a SymbolKind enumerator, but is
|
||||
/// unsigned to avoid sign extension and achieve better bitpacking with MSVC.
|
||||
unsigned Kind : 2;
|
||||
|
||||
/// Index field, for use by the object file implementation.
|
||||
mutable uint32_t Index = 0;
|
||||
|
@ -108,29 +118,73 @@ class MCSymbol {
|
|||
protected: // MCContext creates and uniques these.
|
||||
friend class MCExpr;
|
||||
friend class MCContext;
|
||||
MCSymbol(bool IsELF, const StringMapEntry<bool> *Name, bool isTemporary)
|
||||
: Name(Name), Section(nullptr), Value(nullptr), IsTemporary(isTemporary),
|
||||
|
||||
/// \brief The name for a symbol.
|
||||
/// MCSymbol contains a uint64_t so is probably aligned to 8. On a 32-bit
|
||||
/// system, the name is a pointer so isn't going to satisfy the 8 byte
|
||||
/// alignment of uint64_t. Account for that here.
|
||||
typedef union {
|
||||
const StringMapEntry<bool> *NameEntry;
|
||||
uint64_t AlignmentPadding;
|
||||
} NameEntryStorageTy;
|
||||
|
||||
MCSymbol(SymbolKind Kind, const StringMapEntry<bool> *Name, bool isTemporary)
|
||||
: Value(nullptr), IsTemporary(isTemporary),
|
||||
IsRedefinable(false), IsUsed(false), IsRegistered(false),
|
||||
IsExternal(false), IsPrivateExtern(false), HasFragment(false),
|
||||
IsELF(IsELF) {
|
||||
IsExternal(false), IsPrivateExtern(false), HasName(!!Name),
|
||||
Kind(Kind) {
|
||||
Offset = 0;
|
||||
if (Name)
|
||||
getNameEntryPtr() = Name;
|
||||
}
|
||||
|
||||
// Provide custom new/delete as we will only allocate space for a name
|
||||
// if we need one.
|
||||
void *operator new(size_t s, const StringMapEntry<bool> *Name,
|
||||
MCContext &Ctx);
|
||||
|
||||
private:
|
||||
|
||||
void operator delete(void *);
|
||||
/// \brief Placement delete - required by std, but never called.
|
||||
void operator delete(void*, unsigned) {
|
||||
llvm_unreachable("Constructor throws?");
|
||||
}
|
||||
/// \brief Placement delete - required by std, but never called.
|
||||
void operator delete(void*, unsigned, bool) {
|
||||
llvm_unreachable("Constructor throws?");
|
||||
}
|
||||
|
||||
MCSymbol(const MCSymbol &) = delete;
|
||||
void operator=(const MCSymbol &) = delete;
|
||||
MCSection *getSectionPtr() const {
|
||||
if (MCFragment *F = getFragment())
|
||||
return F->getParent();
|
||||
assert(!HasFragment);
|
||||
assert(!SectionOrFragment.is<MCFragment *>() && "Section or null expected");
|
||||
MCSection *Section = SectionOrFragment.dyn_cast<MCSection *>();
|
||||
if (Section || !Value)
|
||||
return Section;
|
||||
return Section = Value->findAssociatedSection();
|
||||
}
|
||||
|
||||
/// \brief Get a reference to the name field. Requires that we have a name
|
||||
const StringMapEntry<bool> *&getNameEntryPtr() {
|
||||
assert(HasName && "Name is required");
|
||||
NameEntryStorageTy *Name = reinterpret_cast<NameEntryStorageTy *>(this);
|
||||
return (*(Name - 1)).NameEntry;
|
||||
}
|
||||
const StringMapEntry<bool> *&getNameEntryPtr() const {
|
||||
return const_cast<MCSymbol*>(this)->getNameEntryPtr();
|
||||
}
|
||||
|
||||
public:
|
||||
/// getName - Get the symbol name.
|
||||
StringRef getName() const { return Name ? Name->first() : ""; }
|
||||
StringRef getName() const {
|
||||
if (!HasName)
|
||||
return StringRef();
|
||||
|
||||
return getNameEntryPtr()->first();
|
||||
}
|
||||
|
||||
bool isRegistered() const { return IsRegistered; }
|
||||
void setIsRegistered(bool Value) const { IsRegistered = Value; }
|
||||
|
@ -153,8 +207,7 @@ public:
|
|||
void redefineIfPossible() {
|
||||
if (IsRedefinable) {
|
||||
Value = nullptr;
|
||||
Section = nullptr;
|
||||
HasFragment = false;
|
||||
SectionOrFragment = nullptr;
|
||||
IsRedefinable = false;
|
||||
}
|
||||
}
|
||||
|
@ -187,17 +240,20 @@ public:
|
|||
/// Mark the symbol as defined in the section \p S.
|
||||
void setSection(MCSection &S) {
|
||||
assert(!isVariable() && "Cannot set section of variable");
|
||||
assert(!HasFragment);
|
||||
Section = &S;
|
||||
assert(!SectionOrFragment.is<MCFragment *>() && "Section or null expected");
|
||||
SectionOrFragment = &S;
|
||||
}
|
||||
|
||||
/// Mark the symbol as undefined.
|
||||
void setUndefined() {
|
||||
HasFragment = false;
|
||||
Section = nullptr;
|
||||
SectionOrFragment = nullptr;
|
||||
}
|
||||
|
||||
bool isELF() const { return IsELF; }
|
||||
bool isELF() const { return Kind == SymbolKindELF; }
|
||||
|
||||
bool isCOFF() const { return Kind == SymbolKindCOFF; }
|
||||
|
||||
bool isMachO() const { return Kind == SymbolKindMachO; }
|
||||
|
||||
/// @}
|
||||
/// \name Variable Symbols
|
||||
|
@ -258,9 +314,44 @@ public:
|
|||
return CommonAlign;
|
||||
}
|
||||
|
||||
/// Declare this symbol as being 'common'.
|
||||
///
|
||||
/// \param Size - The size of the symbol.
|
||||
/// \param Align - The alignment of the symbol.
|
||||
/// \return True if symbol was already declared as a different type
|
||||
bool declareCommon(uint64_t Size, unsigned Align) {
|
||||
assert(isCommon() || getOffset() == 0);
|
||||
if(isCommon()) {
|
||||
if(CommonSize != Size || CommonAlign != Align)
|
||||
return true;
|
||||
} else
|
||||
setCommon(Size, Align);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Is this a 'common' symbol.
|
||||
bool isCommon() const { return CommonAlign != -1U; }
|
||||
|
||||
MCFragment *getFragment() const {
|
||||
return SectionOrFragment.dyn_cast<MCFragment *>();
|
||||
}
|
||||
void setFragment(MCFragment *Value) const {
|
||||
SectionOrFragment = Value;
|
||||
}
|
||||
|
||||
bool isExternal() const { return IsExternal; }
|
||||
void setExternal(bool Value) const { IsExternal = Value; }
|
||||
|
||||
bool isPrivateExtern() const { return IsPrivateExtern; }
|
||||
void setPrivateExtern(bool Value) { IsPrivateExtern = Value; }
|
||||
|
||||
/// print - Print the value to the stream \p OS.
|
||||
void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
|
||||
|
||||
/// dump - Print the value to stderr.
|
||||
void dump() const;
|
||||
|
||||
protected:
|
||||
/// Get the (implementation defined) symbol flags.
|
||||
uint32_t getFlags() const { return Flags; }
|
||||
|
||||
|
@ -271,32 +362,10 @@ public:
|
|||
void modifyFlags(uint32_t Value, uint32_t Mask) const {
|
||||
Flags = (Flags & ~Mask) | Value;
|
||||
}
|
||||
|
||||
MCFragment *getFragment() const {
|
||||
if (!HasFragment)
|
||||
return nullptr;
|
||||
return Fragment;
|
||||
}
|
||||
void setFragment(MCFragment *Value) const {
|
||||
HasFragment = true;
|
||||
Fragment = Value;
|
||||
}
|
||||
|
||||
bool isExternal() const { return IsExternal; }
|
||||
void setExternal(bool Value) const { IsExternal = Value; }
|
||||
|
||||
bool isPrivateExtern() const { return IsPrivateExtern; }
|
||||
void setPrivateExtern(bool Value) { IsPrivateExtern = Value; }
|
||||
|
||||
/// print - Print the value to the stream \p OS.
|
||||
void print(raw_ostream &OS) const;
|
||||
|
||||
/// dump - Print the value to stderr.
|
||||
void dump() const;
|
||||
};
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) {
|
||||
Sym.print(OS);
|
||||
Sym.print(OS, nullptr);
|
||||
return OS;
|
||||
}
|
||||
} // end namespace llvm
|
||||
|
|
64
include/llvm/MC/MCSymbolCOFF.h
Normal file
64
include/llvm/MC/MCSymbolCOFF.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
//===- MCSymbolCOFF.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_MC_MCSYMBOLCOFF_H
|
||||
#define LLVM_MC_MCSYMBOLCOFF_H
|
||||
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
|
||||
namespace llvm {
|
||||
class MCSymbolCOFF : public MCSymbol {
|
||||
|
||||
/// This corresponds to the e_type field of the COFF symbol.
|
||||
mutable uint16_t Type;
|
||||
|
||||
enum SymbolFlags : uint16_t {
|
||||
SF_ClassMask = 0x00FF,
|
||||
SF_ClassShift = 0,
|
||||
|
||||
SF_WeakExternal = 0x0100,
|
||||
SF_SafeSEH = 0x0200,
|
||||
};
|
||||
|
||||
public:
|
||||
MCSymbolCOFF(const StringMapEntry<bool> *Name, bool isTemporary)
|
||||
: MCSymbol(SymbolKindCOFF, Name, isTemporary), Type(0) {}
|
||||
|
||||
uint16_t getType() const {
|
||||
return Type;
|
||||
}
|
||||
void setType(uint16_t Ty) const {
|
||||
Type = Ty;
|
||||
}
|
||||
|
||||
uint16_t getClass() const {
|
||||
return (getFlags() & SF_ClassMask) >> SF_ClassShift;
|
||||
}
|
||||
void setClass(uint16_t StorageClass) const {
|
||||
modifyFlags(StorageClass << SF_ClassShift, SF_ClassMask);
|
||||
}
|
||||
|
||||
bool isWeakExternal() const {
|
||||
return getFlags() & SF_WeakExternal;
|
||||
}
|
||||
void setIsWeakExternal() const {
|
||||
modifyFlags(SF_WeakExternal, SF_WeakExternal);
|
||||
}
|
||||
|
||||
bool isSafeSEH() const {
|
||||
return getFlags() & SF_SafeSEH;
|
||||
}
|
||||
void setIsSafeSEH() const {
|
||||
modifyFlags(SF_SafeSEH, SF_SafeSEH);
|
||||
}
|
||||
|
||||
static bool classof(const MCSymbol *S) { return S->isCOFF(); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -19,7 +19,7 @@ class MCSymbolELF : public MCSymbol {
|
|||
|
||||
public:
|
||||
MCSymbolELF(const StringMapEntry<bool> *Name, bool isTemporary)
|
||||
: MCSymbol(true, Name, isTemporary) {}
|
||||
: MCSymbol(SymbolKindELF, Name, isTemporary) {}
|
||||
void setSize(const MCExpr *SS) { SymbolSize = SS; }
|
||||
|
||||
const MCExpr *getSize() const { return SymbolSize; }
|
||||
|
@ -36,7 +36,21 @@ public:
|
|||
void setBinding(unsigned Binding) const;
|
||||
unsigned getBinding() const;
|
||||
|
||||
bool isBindingSet() const;
|
||||
|
||||
void setUsedInReloc() const;
|
||||
bool isUsedInReloc() const;
|
||||
|
||||
void setIsWeakrefUsedInReloc() const;
|
||||
bool isWeakrefUsedInReloc() const;
|
||||
|
||||
void setIsSignature() const;
|
||||
bool isSignature() const;
|
||||
|
||||
static bool classof(const MCSymbol *S) { return S->isELF(); }
|
||||
|
||||
private:
|
||||
void setIsBindingSet() const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
123
include/llvm/MC/MCSymbolMachO.h
Normal file
123
include/llvm/MC/MCSymbolMachO.h
Normal file
|
@ -0,0 +1,123 @@
|
|||
//===- MCSymbolMachO.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_MC_MCSYMBOLMACHO_H
|
||||
#define setIsWeakExternal
|
||||
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
|
||||
namespace llvm {
|
||||
class MCSymbolMachO : public MCSymbol {
|
||||
/// \brief We store the value for the 'desc' symbol field in the
|
||||
/// lowest 16 bits of the implementation defined flags.
|
||||
enum MachOSymbolFlags : uint16_t { // See <mach-o/nlist.h>.
|
||||
SF_DescFlagsMask = 0xFFFF,
|
||||
|
||||
// Reference type flags.
|
||||
SF_ReferenceTypeMask = 0x0007,
|
||||
SF_ReferenceTypeUndefinedNonLazy = 0x0000,
|
||||
SF_ReferenceTypeUndefinedLazy = 0x0001,
|
||||
SF_ReferenceTypeDefined = 0x0002,
|
||||
SF_ReferenceTypePrivateDefined = 0x0003,
|
||||
SF_ReferenceTypePrivateUndefinedNonLazy = 0x0004,
|
||||
SF_ReferenceTypePrivateUndefinedLazy = 0x0005,
|
||||
|
||||
// Other 'desc' flags.
|
||||
SF_ThumbFunc = 0x0008,
|
||||
SF_NoDeadStrip = 0x0020,
|
||||
SF_WeakReference = 0x0040,
|
||||
SF_WeakDefinition = 0x0080,
|
||||
SF_SymbolResolver = 0x0100,
|
||||
|
||||
// Common alignment
|
||||
SF_CommonAlignmentMask = 0xF0FF,
|
||||
SF_CommonAlignmentShift = 8
|
||||
};
|
||||
|
||||
public:
|
||||
MCSymbolMachO(const StringMapEntry<bool> *Name, bool isTemporary)
|
||||
: MCSymbol(SymbolKindMachO, Name, isTemporary) {}
|
||||
|
||||
// Reference type methods.
|
||||
|
||||
void clearReferenceType() const {
|
||||
modifyFlags(0, SF_ReferenceTypeMask);
|
||||
}
|
||||
|
||||
void setReferenceTypeUndefinedLazy(bool Value) const {
|
||||
modifyFlags(Value ? SF_ReferenceTypeUndefinedLazy : 0,
|
||||
SF_ReferenceTypeUndefinedLazy);
|
||||
}
|
||||
|
||||
// Other 'desc' methods.
|
||||
|
||||
void setThumbFunc() const {
|
||||
modifyFlags(SF_ThumbFunc, SF_ThumbFunc);
|
||||
}
|
||||
|
||||
bool isNoDeadStrip() const {
|
||||
return getFlags() & SF_NoDeadStrip;
|
||||
}
|
||||
void setNoDeadStrip() const {
|
||||
modifyFlags(SF_NoDeadStrip, SF_NoDeadStrip);
|
||||
}
|
||||
|
||||
bool isWeakReference() const {
|
||||
return getFlags() & SF_WeakReference;
|
||||
}
|
||||
void setWeakReference() const {
|
||||
modifyFlags(SF_WeakReference, SF_WeakReference);
|
||||
}
|
||||
|
||||
bool isWeakDefinition() const {
|
||||
return getFlags() & SF_WeakDefinition;
|
||||
}
|
||||
void setWeakDefinition() const {
|
||||
modifyFlags(SF_WeakDefinition, SF_WeakDefinition);
|
||||
}
|
||||
|
||||
bool isSymbolResolver() const {
|
||||
return getFlags() & SF_SymbolResolver;
|
||||
}
|
||||
void setSymbolResolver() const {
|
||||
modifyFlags(SF_SymbolResolver, SF_SymbolResolver);
|
||||
}
|
||||
|
||||
void setDesc(unsigned Value) const {
|
||||
assert(Value == (Value & SF_DescFlagsMask) &&
|
||||
"Invalid .desc value!");
|
||||
setFlags(Value & SF_DescFlagsMask);
|
||||
}
|
||||
|
||||
/// \brief Get the encoded value of the flags as they will be emitted in to
|
||||
/// the MachO binary
|
||||
uint16_t getEncodedFlags() const {
|
||||
uint16_t Flags = getFlags();
|
||||
|
||||
// Common alignment is packed into the 'desc' bits.
|
||||
if (isCommon()) {
|
||||
if (unsigned Align = getCommonAlignment()) {
|
||||
unsigned Log2Size = Log2_32(Align);
|
||||
assert((1U << Log2Size) == Align && "Invalid 'common' alignment!");
|
||||
if (Log2Size > 15)
|
||||
report_fatal_error("invalid 'common' alignment '" +
|
||||
Twine(Align) + "' for '" + getName() + "'",
|
||||
false);
|
||||
Flags = (Flags & SF_CommonAlignmentMask) |
|
||||
(Log2Size << SF_CommonAlignmentShift);
|
||||
}
|
||||
}
|
||||
|
||||
return Flags;
|
||||
}
|
||||
|
||||
static bool classof(const MCSymbol *S) { return S->isMachO(); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -103,6 +103,10 @@ public:
|
|||
FeatureBitset ToggleFeature(FeatureBitset Bits, StringRef String,
|
||||
ArrayRef<SubtargetFeatureKV> FeatureTable);
|
||||
|
||||
/// Apply the feature flag and return the newly updated feature bits.
|
||||
FeatureBitset ApplyFeatureFlag(FeatureBitset Bits, StringRef Feature,
|
||||
ArrayRef<SubtargetFeatureKV> FeatureTable);
|
||||
|
||||
/// Get feature bits of a CPU.
|
||||
FeatureBitset getFeatureBits(StringRef CPU,
|
||||
ArrayRef<SubtargetFeatureKV> CPUTable,
|
||||
|
|
51
include/llvm/Object/ArchiveWriter.h
Normal file
51
include/llvm/Object/ArchiveWriter.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
//===- ArchiveWriter.h - ar archive file format writer ----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Declares the writeArchive function for writing an archive file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_OBJECT_ARCHIVEWRITER_H
|
||||
#define LLVM_OBJECT_ARCHIVEWRITER_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Object/Archive.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class NewArchiveIterator {
|
||||
bool IsNewMember;
|
||||
StringRef Name;
|
||||
|
||||
object::Archive::child_iterator OldI;
|
||||
|
||||
StringRef NewFilename;
|
||||
|
||||
public:
|
||||
NewArchiveIterator(object::Archive::child_iterator I, StringRef Name);
|
||||
NewArchiveIterator(StringRef I, StringRef Name);
|
||||
NewArchiveIterator();
|
||||
bool isNewMember() const;
|
||||
StringRef getName() const;
|
||||
|
||||
object::Archive::child_iterator getOld() const;
|
||||
|
||||
StringRef getNew() const;
|
||||
llvm::ErrorOr<int> getFD(sys::fs::file_status &NewStatus) const;
|
||||
const sys::fs::file_status &getStatus() const;
|
||||
};
|
||||
|
||||
std::pair<StringRef, std::error_code>
|
||||
writeArchive(StringRef ArcName, std::vector<NewArchiveIterator> &NewMembers,
|
||||
bool WriteSymtab);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -695,7 +695,7 @@ public:
|
|||
return object_error::parse_failed;
|
||||
|
||||
Res = reinterpret_cast<coff_symbol_type *>(getSymbolTable()) + Index;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
ErrorOr<COFFSymbolRef> getSymbol(uint32_t index) const {
|
||||
if (SymbolTable16) {
|
||||
|
@ -718,7 +718,7 @@ public:
|
|||
if (std::error_code EC = s.getError())
|
||||
return EC;
|
||||
Res = reinterpret_cast<const T *>(s->getRawPtr());
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
std::error_code getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const;
|
||||
|
||||
|
|
|
@ -223,7 +223,7 @@ public:
|
|||
|
||||
std::error_code getPlatformFlags(unsigned &Result) const override {
|
||||
Result = EF.getHeader()->e_flags;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
const ELFFile<ELFT> *getELFFile() const { return &EF; }
|
||||
|
@ -257,7 +257,7 @@ std::error_code ELFObjectFile<ELFT>::getSymbolName(DataRefImpl Symb,
|
|||
if (!Name)
|
||||
return Name.getError();
|
||||
Result = *Name;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
|
@ -271,7 +271,7 @@ std::error_code ELFObjectFile<ELFT>::getSymbolVersion(SymbolRef SymRef,
|
|||
if (!Ver)
|
||||
return Ver.getError();
|
||||
Version = *Ver;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
|
@ -294,10 +294,10 @@ std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb,
|
|||
case ELF::SHN_COMMON:
|
||||
case ELF::SHN_UNDEF:
|
||||
Result = UnknownAddressOrSize;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
case ELF::SHN_ABS:
|
||||
Result = ESym->st_value;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -316,7 +316,7 @@ std::error_code ELFObjectFile<ELFT>::getSymbolAddress(DataRefImpl Symb,
|
|||
Result += Section->sh_addr;
|
||||
}
|
||||
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
|
@ -336,7 +336,7 @@ template <class ELFT>
|
|||
std::error_code ELFObjectFile<ELFT>::getSymbolOther(DataRefImpl Symb,
|
||||
uint8_t &Result) const {
|
||||
Result = toELFSymIter(Symb)->st_other;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
|
@ -367,7 +367,7 @@ ELFObjectFile<ELFT>::getSymbolType(DataRefImpl Symb,
|
|||
Result = SymbolRef::ST_Other;
|
||||
break;
|
||||
}
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
|
@ -424,7 +424,7 @@ std::error_code
|
|||
ELFObjectFile<ELFT>::getSymbolSection(DataRefImpl Symb,
|
||||
section_iterator &Res) const {
|
||||
Res = getSymbolSection(getSymbol(Symb));
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
|
@ -439,7 +439,7 @@ std::error_code ELFObjectFile<ELFT>::getSectionName(DataRefImpl Sec,
|
|||
if (!Name)
|
||||
return Name.getError();
|
||||
Result = *Name;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
|
@ -458,7 +458,7 @@ ELFObjectFile<ELFT>::getSectionContents(DataRefImpl Sec,
|
|||
StringRef &Result) const {
|
||||
Elf_Shdr_Iter EShdr = toELFShdrIter(Sec);
|
||||
Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size);
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
|
@ -613,7 +613,7 @@ ELFObjectFile<ELFT>::getRelocationAddress(DataRefImpl Rel,
|
|||
Result = ROffset;
|
||||
}
|
||||
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
|
@ -623,7 +623,7 @@ ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel,
|
|||
assert(EF.getHeader()->e_type == ELF::ET_REL &&
|
||||
"Only relocatable object files have relocation offsets");
|
||||
Result = getROffset(Rel);
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
|
@ -655,7 +655,7 @@ std::error_code ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel,
|
|||
break;
|
||||
}
|
||||
}
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
|
@ -682,7 +682,7 @@ std::error_code ELFObjectFile<ELFT>::getRelocationTypeName(
|
|||
}
|
||||
|
||||
EF.getRelocationTypeName(type, Result);
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
|
@ -695,11 +695,11 @@ ELFObjectFile<ELFT>::getRelocationAddend(DataRefImpl Rel,
|
|||
report_fatal_error("Invalid section type in Rel!");
|
||||
case ELF::SHT_REL: {
|
||||
Result = 0;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
case ELF::SHT_RELA: {
|
||||
Result = getRela(Rel)->r_addend;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,12 +154,15 @@ struct Elf_Sym_Base<ELFType<TargetEndianness, true>> {
|
|||
template <class ELFT>
|
||||
struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> {
|
||||
using Elf_Sym_Base<ELFT>::st_info;
|
||||
using Elf_Sym_Base<ELFT>::st_shndx;
|
||||
using Elf_Sym_Base<ELFT>::st_other;
|
||||
using Elf_Sym_Base<ELFT>::st_value;
|
||||
|
||||
// These accessors and mutators correspond to the ELF32_ST_BIND,
|
||||
// ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification:
|
||||
unsigned char getBinding() const { return st_info >> 4; }
|
||||
unsigned char getType() const { return st_info & 0x0f; }
|
||||
uint64_t getValue() const { return st_value; }
|
||||
void setBinding(unsigned char b) { setBindingAndType(b, getType()); }
|
||||
void setType(unsigned char t) { setBindingAndType(getBinding(), t); }
|
||||
void setBindingAndType(unsigned char b, unsigned char t) {
|
||||
|
@ -176,6 +179,24 @@ struct Elf_Sym_Impl : Elf_Sym_Base<ELFT> {
|
|||
assert(v < 4 && "Invalid value for visibility");
|
||||
st_other = (st_other & ~0x3) | v;
|
||||
}
|
||||
|
||||
bool isAbsolute() const { return st_shndx == ELF::SHN_ABS; }
|
||||
bool isCommon() const {
|
||||
return getType() == ELF::STT_COMMON || st_shndx == ELF::SHN_COMMON;
|
||||
}
|
||||
bool isDefined() const { return !isUndefined(); }
|
||||
bool isProcessorSpecific() const {
|
||||
return st_shndx >= ELF::SHN_LOPROC && st_shndx <= ELF::SHN_HIPROC;
|
||||
}
|
||||
bool isOSSpecific() const {
|
||||
return st_shndx >= ELF::SHN_LOOS && st_shndx <= ELF::SHN_HIOS;
|
||||
}
|
||||
bool isReserved() const {
|
||||
// ELF::SHN_HIRESERVE is 0xffff so st_shndx <= ELF::SHN_HIRESERVE is always
|
||||
// true and some compilers warn about it.
|
||||
return st_shndx >= ELF::SHN_LORESERVE;
|
||||
}
|
||||
bool isUndefined() const { return st_shndx == ELF::SHN_UNDEF; }
|
||||
};
|
||||
|
||||
/// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section
|
||||
|
|
|
@ -22,12 +22,15 @@ namespace object {
|
|||
const std::error_category &object_category();
|
||||
|
||||
enum class object_error {
|
||||
success = 0,
|
||||
arch_not_found,
|
||||
// Error code 0 is absent. Use std::error_code() instead.
|
||||
arch_not_found = 1,
|
||||
invalid_file_type,
|
||||
parse_failed,
|
||||
unexpected_eof,
|
||||
bitcode_section_not_found,
|
||||
macho_small_load_command,
|
||||
macho_load_segment_too_many_sections,
|
||||
macho_load_segment_too_small,
|
||||
};
|
||||
|
||||
inline std::error_code make_error_code(object_error e) {
|
||||
|
|
|
@ -190,6 +190,8 @@ public:
|
|||
const char *Ptr; // Where in memory the load command is.
|
||||
MachO::load_command C; // The command itself.
|
||||
};
|
||||
typedef SmallVector<LoadCommandInfo, 4> LoadCommandList;
|
||||
typedef LoadCommandList::const_iterator load_command_iterator;
|
||||
|
||||
MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits,
|
||||
std::error_code &EC);
|
||||
|
@ -270,10 +272,14 @@ public:
|
|||
|
||||
dice_iterator begin_dices() const;
|
||||
dice_iterator end_dices() const;
|
||||
|
||||
|
||||
load_command_iterator begin_load_commands() const;
|
||||
load_command_iterator end_load_commands() const;
|
||||
iterator_range<load_command_iterator> load_commands() const;
|
||||
|
||||
/// For use iterating over all exported symbols.
|
||||
iterator_range<export_iterator> exports() const;
|
||||
|
||||
|
||||
/// For use examining a trie not in a MachOObjectFile.
|
||||
static iterator_range<export_iterator> exports(ArrayRef<uint8_t> Trie);
|
||||
|
||||
|
@ -326,10 +332,6 @@ public:
|
|||
unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const;
|
||||
SectionRef getAnyRelocationSection(const MachO::any_relocation_info &RE) const;
|
||||
|
||||
// Walk load commands.
|
||||
LoadCommandInfo getFirstLoadCommandInfo() const;
|
||||
LoadCommandInfo getNextLoadCommandInfo(const LoadCommandInfo &L) const;
|
||||
|
||||
// MachO specific structures.
|
||||
MachO::section getSection(DataRefImpl DRI) const;
|
||||
MachO::section_64 getSection64(DataRefImpl DRI) const;
|
||||
|
@ -383,8 +385,8 @@ public:
|
|||
|
||||
MachO::any_relocation_info getRelocation(DataRefImpl Rel) const;
|
||||
MachO::data_in_code_entry getDice(DataRefImpl Rel) const;
|
||||
MachO::mach_header getHeader() const;
|
||||
MachO::mach_header_64 getHeader64() const;
|
||||
const MachO::mach_header &getHeader() const;
|
||||
const MachO::mach_header_64 &getHeader64() const;
|
||||
uint32_t
|
||||
getIndirectSymbolTableEntry(const MachO::dysymtab_command &DLC,
|
||||
unsigned Index) const;
|
||||
|
@ -427,10 +429,15 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
MachO::mach_header_64 Header64;
|
||||
MachO::mach_header Header;
|
||||
};
|
||||
typedef SmallVector<const char*, 1> SectionList;
|
||||
SectionList Sections;
|
||||
typedef SmallVector<const char*, 1> LibraryList;
|
||||
LibraryList Libraries;
|
||||
LoadCommandList LoadCommands;
|
||||
typedef SmallVector<StringRef, 1> LibraryShortName;
|
||||
mutable LibraryShortName LibrariesShortNames;
|
||||
const char *SymtabLoadCmd;
|
||||
|
@ -469,7 +476,7 @@ inline std::error_code DiceRef::getOffset(uint32_t &Result) const {
|
|||
static_cast<const MachOObjectFile *>(OwningObject);
|
||||
MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl);
|
||||
Result = Dice.offset;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
inline std::error_code DiceRef::getLength(uint16_t &Result) const {
|
||||
|
@ -477,7 +484,7 @@ inline std::error_code DiceRef::getLength(uint16_t &Result) const {
|
|||
static_cast<const MachOObjectFile *>(OwningObject);
|
||||
MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl);
|
||||
Result = Dice.length;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
inline std::error_code DiceRef::getKind(uint16_t &Result) const {
|
||||
|
@ -485,7 +492,7 @@ inline std::error_code DiceRef::getKind(uint16_t &Result) const {
|
|||
static_cast<const MachOObjectFile *>(OwningObject);
|
||||
MachO::data_in_code_entry Dice = MachOOF->getDice(DicePimpl);
|
||||
Result = Dice.kind;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
inline DataRefImpl DiceRef::getRawDataRefImpl() const {
|
||||
|
|
|
@ -250,7 +250,7 @@ protected:
|
|||
virtual std::error_code getRelocationHidden(DataRefImpl Rel,
|
||||
bool &Result) const {
|
||||
Result = false;
|
||||
return object_error::success;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
|
@ -155,17 +155,6 @@ namespace COFF {
|
|||
uint8_t NumberOfAuxSymbols;
|
||||
};
|
||||
|
||||
enum SymbolFlags {
|
||||
SF_TypeMask = 0x0000FFFF,
|
||||
SF_TypeShift = 0,
|
||||
|
||||
SF_ClassMask = 0x00FF0000,
|
||||
SF_ClassShift = 16,
|
||||
|
||||
SF_WeakExternal = 0x01000000,
|
||||
SF_SafeSEH = 0x02000000,
|
||||
};
|
||||
|
||||
enum SymbolSectionNumber : int32_t {
|
||||
IMAGE_SYM_DEBUG = -2,
|
||||
IMAGE_SYM_ABSOLUTE = -1,
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
|
||||
namespace llvm {
|
||||
|
||||
class BumpPtrStringSaver;
|
||||
class StringSaver;
|
||||
|
||||
/// cl Namespace - This namespace contains all of the command line option
|
||||
/// processing machinery. It is intentionally a short name to make qualified
|
||||
/// usage concise.
|
||||
|
@ -1676,16 +1679,6 @@ StringMap<Option *> &getRegisteredOptions();
|
|||
// Standalone command line processing utilities.
|
||||
//
|
||||
|
||||
/// \brief Saves strings in the inheritor's stable storage and returns a stable
|
||||
/// raw character pointer.
|
||||
class StringSaver {
|
||||
virtual void anchor();
|
||||
|
||||
public:
|
||||
virtual const char *SaveString(const char *Str) = 0;
|
||||
virtual ~StringSaver(){}; // Pacify -Wnon-virtual-dtor.
|
||||
};
|
||||
|
||||
/// \brief Tokenizes a command line that can contain escapes and quotes.
|
||||
//
|
||||
/// The quoting rules match those used by GCC and other tools that use
|
||||
|
|
|
@ -90,3 +90,11 @@ ELF_RELOC(R_HEX_IE_GOT_11_X, 82)
|
|||
ELF_RELOC(R_HEX_TPREL_32_6_X, 83)
|
||||
ELF_RELOC(R_HEX_TPREL_16_X, 84)
|
||||
ELF_RELOC(R_HEX_TPREL_11_X, 85)
|
||||
ELF_RELOC(R_HEX_LD_PLT_B22_PCREL, 86)
|
||||
ELF_RELOC(R_HEX_LD_GOT_LO16, 87)
|
||||
ELF_RELOC(R_HEX_LD_GOT_HI16, 88)
|
||||
ELF_RELOC(R_HEX_LD_GOT_32, 89)
|
||||
ELF_RELOC(R_HEX_LD_GOT_16, 90)
|
||||
ELF_RELOC(R_HEX_LD_GOT_32_6_X, 91)
|
||||
ELF_RELOC(R_HEX_LD_GOT_16_X, 92)
|
||||
ELF_RELOC(R_HEX_LD_GOT_11_X, 93)
|
||||
|
|
|
@ -104,6 +104,16 @@ struct packed_endian_specific_integral {
|
|||
return *this;
|
||||
}
|
||||
|
||||
packed_endian_specific_integral &operator|=(value_type newValue) {
|
||||
*this = *this | newValue;
|
||||
return *this;
|
||||
}
|
||||
|
||||
packed_endian_specific_integral &operator&=(value_type newValue) {
|
||||
*this = *this & newValue;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
AlignedCharArray<PickAlignment<value_type, alignment>::value,
|
||||
sizeof(value_type)> Value;
|
||||
|
|
|
@ -562,7 +562,7 @@ inline uint64_t MinAlign(uint64_t A, uint64_t B) {
|
|||
///
|
||||
/// Alignment should be a power of two. This method rounds up, so
|
||||
/// alignAddr(7, 4) == 8 and alignAddr(8, 4) == 8.
|
||||
inline uintptr_t alignAddr(void *Addr, size_t Alignment) {
|
||||
inline uintptr_t alignAddr(const void *Addr, size_t Alignment) {
|
||||
assert(Alignment && isPowerOf2_64((uint64_t)Alignment) &&
|
||||
"Alignment is not a power of two!");
|
||||
|
||||
|
@ -573,7 +573,7 @@ inline uintptr_t alignAddr(void *Addr, size_t Alignment) {
|
|||
|
||||
/// \brief Returns the necessary adjustment for aligning \c Ptr to \c Alignment
|
||||
/// bytes, rounding up.
|
||||
inline size_t alignmentAdjustment(void *Ptr, size_t Alignment) {
|
||||
inline size_t alignmentAdjustment(const void *Ptr, size_t Alignment) {
|
||||
return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -276,8 +276,8 @@ public:
|
|||
return FixIts;
|
||||
}
|
||||
|
||||
void print(const char *ProgName, raw_ostream &S,
|
||||
bool ShowColors = true) const;
|
||||
void print(const char *ProgName, raw_ostream &S, bool ShowColors = true,
|
||||
bool ShowKindLabel = true) const;
|
||||
};
|
||||
|
||||
} // end llvm namespace
|
||||
|
|
42
include/llvm/Support/StringSaver.h
Normal file
42
include/llvm/Support/StringSaver.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
//===- llvm/Support/StringSaver.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_SUPPORT_STRINGSAVER_H
|
||||
#define LLVM_SUPPORT_STRINGSAVER_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// \brief Saves strings in the inheritor's stable storage and returns a stable
|
||||
/// raw character pointer.
|
||||
class StringSaver {
|
||||
protected:
|
||||
~StringSaver() {}
|
||||
virtual const char *saveImpl(StringRef S);
|
||||
|
||||
public:
|
||||
StringSaver(BumpPtrAllocator &Alloc) : Alloc(Alloc) {}
|
||||
const char *save(const char *S) { return save(StringRef(S)); }
|
||||
const char *save(StringRef S) { return saveImpl(S); }
|
||||
const char *save(const Twine &S) { return save(StringRef(S.str())); }
|
||||
const char *save(std::string &S) { return save(StringRef(S)); }
|
||||
|
||||
private:
|
||||
BumpPtrAllocator &Alloc;
|
||||
};
|
||||
|
||||
class BumpPtrStringSaver final : public StringSaver {
|
||||
public:
|
||||
BumpPtrStringSaver(BumpPtrAllocator &Alloc) : StringSaver(Alloc) {}
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -15,6 +15,10 @@
|
|||
#ifndef LLVM_SUPPORT_TARGETPARSER_H
|
||||
#define LLVM_SUPPORT_TARGETPARSER_H
|
||||
|
||||
// FIXME: vector is used because that's what clang uses for subtarget feature
|
||||
// lists, but SmallVector would probably be better
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
class StringRef;
|
||||
|
||||
|
@ -28,13 +32,16 @@ namespace ARM {
|
|||
// FPU names.
|
||||
enum FPUKind {
|
||||
FK_INVALID = 0,
|
||||
FK_NONE,
|
||||
FK_VFP,
|
||||
FK_VFPV2,
|
||||
FK_VFPV3,
|
||||
FK_VFPV3_D16,
|
||||
FK_VFPV4,
|
||||
FK_VFPV4_D16,
|
||||
FK_FPV4_SP_D16,
|
||||
FK_FPV5_D16,
|
||||
FK_FPV5_SP_D16,
|
||||
FK_FP_ARMV8,
|
||||
FK_NEON,
|
||||
FK_NEON_VFPV4,
|
||||
|
@ -44,6 +51,20 @@ namespace ARM {
|
|||
FK_LAST
|
||||
};
|
||||
|
||||
// An FPU name implies one of three levels of Neon support:
|
||||
enum NeonSupportLevel {
|
||||
NS_None = 0, ///< No Neon
|
||||
NS_Neon, ///< Neon
|
||||
NS_Crypto ///< Neon with Crypto
|
||||
};
|
||||
|
||||
// An FPU name restricts the FPU in one of three ways:
|
||||
enum FPURestriction {
|
||||
FR_None = 0, ///< No restriction
|
||||
FR_D16, ///< Only 16 D registers
|
||||
FR_SP_D16 ///< Only single-precision instructions, with 16 D registers
|
||||
};
|
||||
|
||||
// Arch names.
|
||||
enum ArchKind {
|
||||
AK_INVALID = 0,
|
||||
|
@ -139,6 +160,12 @@ public:
|
|||
|
||||
// Information by ID
|
||||
static const char * getFPUName(unsigned FPUKind);
|
||||
static unsigned getFPUVersion(unsigned FPUKind);
|
||||
static unsigned getFPUNeonSupportLevel(unsigned FPUKind);
|
||||
static unsigned getFPURestriction(unsigned FPUKind);
|
||||
// FIXME: This should be moved to TargetTuple once it exists
|
||||
static bool getFPUFeatures(unsigned FPUKind,
|
||||
std::vector<const char*> &Features);
|
||||
static const char * getArchName(unsigned ArchKind);
|
||||
static unsigned getArchAttr(unsigned ArchKind);
|
||||
static const char * getCPUAttr(unsigned ArchKind);
|
||||
|
|
|
@ -69,7 +69,7 @@ MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB,
|
|||
bool RelaxAll, bool DWARFMustBeAtTheEnd,
|
||||
bool LabelSections = false);
|
||||
|
||||
MCRelocationInfo *createMCRelocationInfo(StringRef TT, MCContext &Ctx);
|
||||
MCRelocationInfo *createMCRelocationInfo(const Triple &TT, MCContext &Ctx);
|
||||
|
||||
MCSymbolizer *createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo,
|
||||
LLVMSymbolLookupCallback SymbolLookUp,
|
||||
|
@ -91,14 +91,14 @@ public:
|
|||
typedef bool (*ArchMatchFnTy)(Triple::ArchType Arch);
|
||||
|
||||
typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(const MCRegisterInfo &MRI,
|
||||
StringRef TT);
|
||||
const Triple &TT);
|
||||
typedef MCCodeGenInfo *(*MCCodeGenInfoCtorFnTy)(StringRef TT, Reloc::Model RM,
|
||||
CodeModel::Model CM,
|
||||
CodeGenOpt::Level OL);
|
||||
typedef MCInstrInfo *(*MCInstrInfoCtorFnTy)(void);
|
||||
typedef MCInstrAnalysis *(*MCInstrAnalysisCtorFnTy)(const MCInstrInfo *Info);
|
||||
typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(StringRef TT);
|
||||
typedef MCSubtargetInfo *(*MCSubtargetInfoCtorFnTy)(StringRef TT,
|
||||
typedef MCSubtargetInfo *(*MCSubtargetInfoCtorFnTy)(const Triple &TT,
|
||||
StringRef CPU,
|
||||
StringRef Features);
|
||||
typedef TargetMachine *(*TargetMachineCtorTy)(
|
||||
|
@ -112,7 +112,7 @@ public:
|
|||
TargetMachine &TM, std::unique_ptr<MCStreamer> &&Streamer);
|
||||
typedef MCAsmBackend *(*MCAsmBackendCtorTy)(const Target &T,
|
||||
const MCRegisterInfo &MRI,
|
||||
StringRef TT, StringRef CPU);
|
||||
const Triple &TT, StringRef CPU);
|
||||
typedef MCTargetAsmParser *(*MCAsmParserCtorTy)(
|
||||
MCSubtargetInfo &STI, MCAsmParser &P, const MCInstrInfo &MII,
|
||||
const MCTargetOptions &Options);
|
||||
|
@ -147,7 +147,7 @@ public:
|
|||
bool IsVerboseAsm);
|
||||
typedef MCTargetStreamer *(*ObjectTargetStreamerCtorTy)(
|
||||
MCStreamer &S, const MCSubtargetInfo &STI);
|
||||
typedef MCRelocationInfo *(*MCRelocationInfoCtorTy)(StringRef TT,
|
||||
typedef MCRelocationInfo *(*MCRelocationInfoCtorTy)(const Triple &TT,
|
||||
MCContext &Ctx);
|
||||
typedef MCSymbolizer *(*MCSymbolizerCtorTy)(
|
||||
StringRef TT, LLVMOpInfoCallback GetOpInfo,
|
||||
|
@ -287,15 +287,15 @@ public:
|
|||
/// createMCAsmInfo - Create a MCAsmInfo implementation for the specified
|
||||
/// target triple.
|
||||
///
|
||||
/// \param Triple This argument is used to determine the target machine
|
||||
/// \param TheTriple This argument is used to determine the target machine
|
||||
/// feature set; it should always be provided. Generally this should be
|
||||
/// either the target triple from the module, or the target triple of the
|
||||
/// host if that does not exist.
|
||||
MCAsmInfo *createMCAsmInfo(const MCRegisterInfo &MRI,
|
||||
StringRef Triple) const {
|
||||
StringRef TheTriple) const {
|
||||
if (!MCAsmInfoCtorFn)
|
||||
return nullptr;
|
||||
return MCAsmInfoCtorFn(MRI, Triple);
|
||||
return MCAsmInfoCtorFn(MRI, Triple(TheTriple));
|
||||
}
|
||||
|
||||
/// createMCCodeGenInfo - Create a MCCodeGenInfo implementation.
|
||||
|
@ -334,18 +334,18 @@ public:
|
|||
|
||||
/// createMCSubtargetInfo - Create a MCSubtargetInfo implementation.
|
||||
///
|
||||
/// \param Triple This argument is used to determine the target machine
|
||||
/// \param TheTriple This argument is used to determine the target machine
|
||||
/// feature set; it should always be provided. Generally this should be
|
||||
/// either the target triple from the module, or the target triple of the
|
||||
/// host if that does not exist.
|
||||
/// \param CPU This specifies the name of the target CPU.
|
||||
/// \param Features This specifies the string representation of the
|
||||
/// additional target features.
|
||||
MCSubtargetInfo *createMCSubtargetInfo(StringRef Triple, StringRef CPU,
|
||||
MCSubtargetInfo *createMCSubtargetInfo(StringRef TheTriple, StringRef CPU,
|
||||
StringRef Features) const {
|
||||
if (!MCSubtargetInfoCtorFn)
|
||||
return nullptr;
|
||||
return MCSubtargetInfoCtorFn(Triple, CPU, Features);
|
||||
return MCSubtargetInfoCtorFn(Triple(TheTriple), CPU, Features);
|
||||
}
|
||||
|
||||
/// createTargetMachine - Create a target specific machine implementation
|
||||
|
@ -369,12 +369,12 @@ public:
|
|||
|
||||
/// createMCAsmBackend - Create a target specific assembly parser.
|
||||
///
|
||||
/// \param Triple The target triple string.
|
||||
MCAsmBackend *createMCAsmBackend(const MCRegisterInfo &MRI, StringRef Triple,
|
||||
StringRef CPU) const {
|
||||
/// \param TheTriple The target triple string.
|
||||
MCAsmBackend *createMCAsmBackend(const MCRegisterInfo &MRI,
|
||||
StringRef TheTriple, StringRef CPU) const {
|
||||
if (!MCAsmBackendCtorFn)
|
||||
return nullptr;
|
||||
return MCAsmBackendCtorFn(*this, MRI, Triple, CPU);
|
||||
return MCAsmBackendCtorFn(*this, MRI, Triple(TheTriple), CPU);
|
||||
}
|
||||
|
||||
/// createMCAsmParser - Create a target specific assembly parser.
|
||||
|
@ -507,7 +507,7 @@ public:
|
|||
MCRelocationInfoCtorTy Fn = MCRelocationInfoCtorFn
|
||||
? MCRelocationInfoCtorFn
|
||||
: llvm::createMCRelocationInfo;
|
||||
return Fn(TT, Ctx);
|
||||
return Fn(Triple(TT), Ctx);
|
||||
}
|
||||
|
||||
/// createMCSymbolizer - Create a target specific MCSymbolizer.
|
||||
|
@ -889,7 +889,8 @@ template <class MCAsmInfoImpl> struct RegisterMCAsmInfo {
|
|||
}
|
||||
|
||||
private:
|
||||
static MCAsmInfo *Allocator(const MCRegisterInfo & /*MRI*/, StringRef TT) {
|
||||
static MCAsmInfo *Allocator(const MCRegisterInfo & /*MRI*/,
|
||||
const Triple &TT) {
|
||||
return new MCAsmInfoImpl(TT);
|
||||
}
|
||||
};
|
||||
|
@ -1055,7 +1056,7 @@ template <class MCSubtargetInfoImpl> struct RegisterMCSubtargetInfo {
|
|||
}
|
||||
|
||||
private:
|
||||
static MCSubtargetInfo *Allocator(StringRef /*TT*/, StringRef /*CPU*/,
|
||||
static MCSubtargetInfo *Allocator(const Triple & /*TT*/, StringRef /*CPU*/,
|
||||
StringRef /*FS*/) {
|
||||
return new MCSubtargetInfoImpl();
|
||||
}
|
||||
|
@ -1093,7 +1094,7 @@ private:
|
|||
StringRef FS, const TargetOptions &Options,
|
||||
Reloc::Model RM, CodeModel::Model CM,
|
||||
CodeGenOpt::Level OL) {
|
||||
return new TargetMachineImpl(T, TT, CPU, FS, Options, RM, CM, OL);
|
||||
return new TargetMachineImpl(T, Triple(TT), CPU, FS, Options, RM, CM, OL);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1111,8 +1112,8 @@ template <class MCAsmBackendImpl> struct RegisterMCAsmBackend {
|
|||
|
||||
private:
|
||||
static MCAsmBackend *Allocator(const Target &T, const MCRegisterInfo &MRI,
|
||||
StringRef Triple, StringRef CPU) {
|
||||
return new MCAsmBackendImpl(T, MRI, Triple, CPU);
|
||||
const Triple &TheTriple, StringRef CPU) {
|
||||
return new MCAsmBackendImpl(T, MRI, TheTriple, CPU);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -17,11 +17,11 @@
|
|||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/ADT/PointerIntPair.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/SMLoc.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <map>
|
||||
|
||||
|
@ -660,8 +660,8 @@ public:
|
|||
// Clone - Clone this operator, replacing arguments with the new list
|
||||
virtual OpInit *clone(std::vector<Init *> &Operands) const = 0;
|
||||
|
||||
virtual int getNumOperands() const = 0;
|
||||
virtual Init *getOperand(int i) const = 0;
|
||||
virtual unsigned getNumOperands() const = 0;
|
||||
virtual Init *getOperand(unsigned i) const = 0;
|
||||
|
||||
// Fold - If possible, fold this to a simpler init. Return this if not
|
||||
// possible to fold.
|
||||
|
@ -702,8 +702,8 @@ public:
|
|||
return UnOpInit::get(getOpcode(), *Operands.begin(), getType());
|
||||
}
|
||||
|
||||
int getNumOperands() const override { return 1; }
|
||||
Init *getOperand(int i) const override {
|
||||
unsigned getNumOperands() const override { return 1; }
|
||||
Init *getOperand(unsigned i) const override {
|
||||
assert(i == 0 && "Invalid operand id for unary operator");
|
||||
return getOperand();
|
||||
}
|
||||
|
@ -750,13 +750,12 @@ public:
|
|||
return BinOpInit::get(getOpcode(), Operands[0], Operands[1], getType());
|
||||
}
|
||||
|
||||
int getNumOperands() const override { return 2; }
|
||||
Init *getOperand(int i) const override {
|
||||
assert((i == 0 || i == 1) && "Invalid operand id for binary operator");
|
||||
if (i == 0) {
|
||||
return getLHS();
|
||||
} else {
|
||||
return getRHS();
|
||||
unsigned getNumOperands() const override { return 2; }
|
||||
Init *getOperand(unsigned i) const override {
|
||||
switch (i) {
|
||||
default: llvm_unreachable("Invalid operand id for binary operator");
|
||||
case 0: return getLHS();
|
||||
case 1: return getRHS();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -806,16 +805,13 @@ public:
|
|||
getType());
|
||||
}
|
||||
|
||||
int getNumOperands() const override { return 3; }
|
||||
Init *getOperand(int i) const override {
|
||||
assert((i == 0 || i == 1 || i == 2) &&
|
||||
"Invalid operand id for ternary operator");
|
||||
if (i == 0) {
|
||||
return getLHS();
|
||||
} else if (i == 1) {
|
||||
return getMHS();
|
||||
} else {
|
||||
return getRHS();
|
||||
unsigned getNumOperands() const override { return 3; }
|
||||
Init *getOperand(unsigned i) const override {
|
||||
switch (i) {
|
||||
default: llvm_unreachable("Invalid operand id for ternary operator");
|
||||
case 0: return getLHS();
|
||||
case 1: return getMHS();
|
||||
case 2: return getRHS();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1113,22 +1109,21 @@ public:
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class RecordVal {
|
||||
Init *Name;
|
||||
PointerIntPair<Init *, 1, bool> NameAndPrefix;
|
||||
RecTy *Ty;
|
||||
unsigned Prefix;
|
||||
Init *Value;
|
||||
|
||||
public:
|
||||
RecordVal(Init *N, RecTy *T, unsigned P);
|
||||
RecordVal(const std::string &N, RecTy *T, unsigned P);
|
||||
RecordVal(Init *N, RecTy *T, bool P);
|
||||
RecordVal(const std::string &N, RecTy *T, bool P);
|
||||
|
||||
const std::string &getName() const;
|
||||
const Init *getNameInit() const { return Name; }
|
||||
const Init *getNameInit() const { return NameAndPrefix.getPointer(); }
|
||||
std::string getNameInitAsString() const {
|
||||
return getNameInit()->getAsUnquotedString();
|
||||
}
|
||||
|
||||
unsigned getPrefix() const { return Prefix; }
|
||||
bool getPrefix() const { return NameAndPrefix.getInt(); }
|
||||
RecTy *getType() const { return Ty; }
|
||||
Init *getValue() const { return Value; }
|
||||
|
||||
|
@ -1187,13 +1182,6 @@ class Record {
|
|||
|
||||
public:
|
||||
// Constructs a record.
|
||||
explicit Record(const std::string &N, ArrayRef<SMLoc> locs,
|
||||
RecordKeeper &records, bool Anonymous = false) :
|
||||
ID(LastID++), Name(StringInit::get(N)), Locs(locs.begin(), locs.end()),
|
||||
TrackedRecords(records), TheInit(nullptr), IsAnonymous(Anonymous),
|
||||
ResolveFirst(false) {
|
||||
init();
|
||||
}
|
||||
explicit Record(Init *N, ArrayRef<SMLoc> locs, RecordKeeper &records,
|
||||
bool Anonymous = false) :
|
||||
ID(LastID++), Name(N), Locs(locs.begin(), locs.end()),
|
||||
|
@ -1201,6 +1189,10 @@ public:
|
|||
ResolveFirst(false) {
|
||||
init();
|
||||
}
|
||||
explicit Record(const std::string &N, ArrayRef<SMLoc> locs,
|
||||
RecordKeeper &records, bool Anonymous = false)
|
||||
: Record(StringInit::get(N), locs, records, Anonymous) {}
|
||||
|
||||
|
||||
// When copy-constructing a Record, we must still guarantee a globally unique
|
||||
// ID number. All other fields can be copied normally.
|
||||
|
@ -1356,7 +1348,7 @@ public:
|
|||
|
||||
/// Return true if the named field is unset.
|
||||
bool isValueUnset(StringRef FieldName) const {
|
||||
return getValueInit(FieldName) == UnsetInit::get();
|
||||
return isa<UnsetInit>(getValueInit(FieldName));
|
||||
}
|
||||
|
||||
/// getValueAsString - This method looks up the specified field and returns
|
||||
|
@ -1508,7 +1500,6 @@ struct LessRecordFieldName {
|
|||
};
|
||||
|
||||
struct LessRecordRegister {
|
||||
static size_t min(size_t a, size_t b) { return a < b ? a : b; }
|
||||
static bool ascii_isdigit(char x) { return x >= '0' && x <= '9'; }
|
||||
|
||||
struct RecordParts {
|
||||
|
|
|
@ -47,9 +47,10 @@
|
|||
#ifndef LLVM_TABLEGEN_SETTHEORY_H
|
||||
#define LLVM_TABLEGEN_SETTHEORY_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/SetVector.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/SMLoc.h"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
|
@ -58,7 +59,6 @@ namespace llvm {
|
|||
class DagInit;
|
||||
class Init;
|
||||
class Record;
|
||||
class RecordKeeper;
|
||||
|
||||
class SetTheory {
|
||||
public:
|
||||
|
|
|
@ -881,6 +881,12 @@ def FRAME_ALLOC : Instruction {
|
|||
let hasSideEffects = 0;
|
||||
let hasCtrlDep = 1;
|
||||
}
|
||||
def FAULTING_LOAD_OP : Instruction {
|
||||
let OutOperandList = (outs unknown:$dst);
|
||||
let InOperandList = (ins variable_ops);
|
||||
let usesCustomInserter = 1;
|
||||
let mayLoad = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -40,6 +40,7 @@ class TargetRegisterClass;
|
|||
class TargetRegisterInfo;
|
||||
class BranchProbability;
|
||||
class TargetSubtargetInfo;
|
||||
class TargetSchedModel;
|
||||
class DFAPacketizer;
|
||||
|
||||
template<class T> class SmallVectorImpl;
|
||||
|
@ -386,6 +387,51 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
/// Represents a predicate at the MachineFunction level. The control flow a
|
||||
/// MachineBranchPredicate represents is:
|
||||
///
|
||||
/// Reg <def>= LHS `Predicate` RHS == ConditionDef
|
||||
/// if Reg then goto TrueDest else goto FalseDest
|
||||
///
|
||||
struct MachineBranchPredicate {
|
||||
enum ComparePredicate {
|
||||
PRED_EQ, // True if two values are equal
|
||||
PRED_NE, // True if two values are not equal
|
||||
PRED_INVALID // Sentinel value
|
||||
};
|
||||
|
||||
ComparePredicate Predicate;
|
||||
MachineOperand LHS;
|
||||
MachineOperand RHS;
|
||||
MachineBasicBlock *TrueDest;
|
||||
MachineBasicBlock *FalseDest;
|
||||
MachineInstr *ConditionDef;
|
||||
|
||||
/// SingleUseCondition is true if ConditionDef is dead except for the
|
||||
/// branch(es) at the end of the basic block.
|
||||
///
|
||||
bool SingleUseCondition;
|
||||
|
||||
explicit MachineBranchPredicate()
|
||||
: Predicate(PRED_INVALID), LHS(MachineOperand::CreateImm(0)),
|
||||
RHS(MachineOperand::CreateImm(0)), TrueDest(nullptr),
|
||||
FalseDest(nullptr), ConditionDef(nullptr), SingleUseCondition(false) {
|
||||
}
|
||||
};
|
||||
|
||||
/// Analyze the branching code at the end of MBB and parse it into the
|
||||
/// MachineBranchPredicate structure if possible. Returns false on success
|
||||
/// and true on failure.
|
||||
///
|
||||
/// If AllowModify is true, then this routine is allowed to modify the basic
|
||||
/// block (e.g. delete instructions after the unconditional branch).
|
||||
///
|
||||
virtual bool AnalyzeBranchPredicate(MachineBasicBlock &MBB,
|
||||
MachineBranchPredicate &MBP,
|
||||
bool AllowModify = false) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Remove the branching code at the end of the specific MBB.
|
||||
/// This is only invoked in cases where AnalyzeBranch returns success. It
|
||||
/// returns the number of instructions that were removed.
|
||||
|
@ -405,7 +451,7 @@ public:
|
|||
/// merging needs to be disabled.
|
||||
virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||
MachineBasicBlock *FBB,
|
||||
const SmallVectorImpl<MachineOperand> &Cond,
|
||||
ArrayRef<MachineOperand> Cond,
|
||||
DebugLoc DL) const {
|
||||
llvm_unreachable("Target didn't implement TargetInstrInfo::InsertBranch!");
|
||||
}
|
||||
|
@ -530,7 +576,7 @@ public:
|
|||
/// @param TrueCycles Latency from TrueReg to select output.
|
||||
/// @param FalseCycles Latency from FalseReg to select output.
|
||||
virtual bool canInsertSelect(const MachineBasicBlock &MBB,
|
||||
const SmallVectorImpl<MachineOperand> &Cond,
|
||||
ArrayRef<MachineOperand> Cond,
|
||||
unsigned TrueReg, unsigned FalseReg,
|
||||
int &CondCycles,
|
||||
int &TrueCycles, int &FalseCycles) const {
|
||||
|
@ -554,8 +600,7 @@ public:
|
|||
/// @param FalseReg Virtual register to copy when Cons is false.
|
||||
virtual void insertSelect(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I, DebugLoc DL,
|
||||
unsigned DstReg,
|
||||
const SmallVectorImpl<MachineOperand> &Cond,
|
||||
unsigned DstReg, ArrayRef<MachineOperand> Cond,
|
||||
unsigned TrueReg, unsigned FalseReg) const {
|
||||
llvm_unreachable("Target didn't implement TargetInstrInfo::insertSelect!");
|
||||
}
|
||||
|
@ -711,20 +756,22 @@ protected:
|
|||
/// Target-dependent implementation for foldMemoryOperand.
|
||||
/// Target-independent code in foldMemoryOperand will
|
||||
/// take care of adding a MachineMemOperand to the newly created instruction.
|
||||
virtual MachineInstr *foldMemoryOperandImpl(MachineFunction &MF,
|
||||
MachineInstr *MI,
|
||||
ArrayRef<unsigned> Ops,
|
||||
int FrameIndex) const {
|
||||
/// The instruction and any auxiliary instructions necessary will be inserted
|
||||
/// at InsertPt.
|
||||
virtual MachineInstr *foldMemoryOperandImpl(
|
||||
MachineFunction &MF, MachineInstr *MI, ArrayRef<unsigned> Ops,
|
||||
MachineBasicBlock::iterator InsertPt, int FrameIndex) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Target-dependent implementation for foldMemoryOperand.
|
||||
/// Target-independent code in foldMemoryOperand will
|
||||
/// take care of adding a MachineMemOperand to the newly created instruction.
|
||||
virtual MachineInstr *foldMemoryOperandImpl(MachineFunction &MF,
|
||||
MachineInstr *MI,
|
||||
ArrayRef<unsigned> Ops,
|
||||
MachineInstr *LoadMI) const {
|
||||
/// The instruction and any auxiliary instructions necessary will be inserted
|
||||
/// at InsertPt.
|
||||
virtual MachineInstr *foldMemoryOperandImpl(
|
||||
MachineFunction &MF, MachineInstr *MI, ArrayRef<unsigned> Ops,
|
||||
MachineBasicBlock::iterator InsertPt, MachineInstr *LoadMI) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -825,10 +872,11 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
/// Get the base register and byte offset of a load/store instr.
|
||||
virtual bool getLdStBaseRegImmOfs(MachineInstr *LdSt,
|
||||
unsigned &BaseReg, unsigned &Offset,
|
||||
const TargetRegisterInfo *TRI) const {
|
||||
/// Get the base register and byte offset of an instruction that reads/writes
|
||||
/// memory.
|
||||
virtual bool getMemOpBaseRegImmOfs(MachineInstr *MemOp, unsigned &BaseReg,
|
||||
unsigned &Offset,
|
||||
const TargetRegisterInfo *TRI) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -876,13 +924,13 @@ public:
|
|||
/// It returns true if the operation was successful.
|
||||
virtual
|
||||
bool PredicateInstruction(MachineInstr *MI,
|
||||
const SmallVectorImpl<MachineOperand> &Pred) const;
|
||||
ArrayRef<MachineOperand> Pred) const;
|
||||
|
||||
/// Returns true if the first specified predicate
|
||||
/// subsumes the second, e.g. GE subsumes GT.
|
||||
virtual
|
||||
bool SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
|
||||
const SmallVectorImpl<MachineOperand> &Pred2) const {
|
||||
bool SubsumesPredicate(ArrayRef<MachineOperand> Pred1,
|
||||
ArrayRef<MachineOperand> Pred2) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1053,7 +1101,7 @@ public:
|
|||
/// determine whether it makes sense to hoist an instruction out even in a
|
||||
/// high register pressure situation.
|
||||
virtual
|
||||
bool hasHighOperandLatency(const InstrItineraryData *ItinData,
|
||||
bool hasHighOperandLatency(const TargetSchedModel &SchedModel,
|
||||
const MachineRegisterInfo *MRI,
|
||||
const MachineInstr *DefMI, unsigned DefIdx,
|
||||
const MachineInstr *UseMI, unsigned UseIdx) const {
|
||||
|
@ -1063,7 +1111,7 @@ public:
|
|||
/// Compute operand latency of a def of 'Reg'. Return true
|
||||
/// if the target considered it 'low'.
|
||||
virtual
|
||||
bool hasLowDefLatency(const InstrItineraryData *ItinData,
|
||||
bool hasLowDefLatency(const TargetSchedModel &SchedModel,
|
||||
const MachineInstr *DefMI, unsigned DefIdx) const;
|
||||
|
||||
/// Perform target-specific instruction verification.
|
||||
|
|
|
@ -1457,9 +1457,12 @@ public:
|
|||
/// The type may be VoidTy, in which case only return true if the addressing
|
||||
/// mode is legal for a load/store of any legal type. TODO: Handle
|
||||
/// pre/postinc as well.
|
||||
///
|
||||
/// If the address space cannot be determined, it will be -1.
|
||||
///
|
||||
/// TODO: Remove default argument
|
||||
virtual bool isLegalAddressingMode(const AddrMode &AM, Type *Ty,
|
||||
unsigned AS = 0) const;
|
||||
unsigned AddrSpace) const;
|
||||
|
||||
/// \brief Return the cost of the scaling factor used in the addressing mode
|
||||
/// represented by AM for this target, for a load/store of the specified type.
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#define LLVM_TARGET_TARGETMACHINE_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/CodeGen.h"
|
||||
|
@ -27,6 +28,7 @@ namespace llvm {
|
|||
class InstrItineraryData;
|
||||
class GlobalValue;
|
||||
class Mangler;
|
||||
class MachineFunctionInitializer;
|
||||
class MCAsmInfo;
|
||||
class MCCodeGenInfo;
|
||||
class MCContext;
|
||||
|
@ -68,7 +70,7 @@ class TargetMachine {
|
|||
void operator=(const TargetMachine &) = delete;
|
||||
protected: // Can only create subclasses.
|
||||
TargetMachine(const Target &T, StringRef DataLayoutString,
|
||||
StringRef TargetTriple, StringRef CPU, StringRef FS,
|
||||
const Triple &TargetTriple, StringRef CPU, StringRef FS,
|
||||
const TargetOptions &Options);
|
||||
|
||||
/// The Target that this machine was created for.
|
||||
|
@ -79,7 +81,7 @@ protected: // Can only create subclasses.
|
|||
|
||||
/// Triple string, CPU name, and target feature strings the TargetMachine
|
||||
/// instance is created with.
|
||||
std::string TargetTriple;
|
||||
Triple TargetTriple;
|
||||
std::string TargetCPU;
|
||||
std::string TargetFS;
|
||||
|
||||
|
@ -103,7 +105,8 @@ public:
|
|||
|
||||
const Target &getTarget() const { return TheTarget; }
|
||||
|
||||
StringRef getTargetTriple() const { return TargetTriple; }
|
||||
// FIXME: Either rename to getTargetName() or make it return a triple.
|
||||
StringRef getTargetTriple() const { return TargetTriple.str(); }
|
||||
StringRef getTargetCPU() const { return TargetCPU; }
|
||||
StringRef getTargetFeatureString() const { return TargetFS; }
|
||||
|
||||
|
@ -208,11 +211,11 @@ public:
|
|||
/// emitted. Typically this will involve several steps of code generation.
|
||||
/// This method should return true if emission of this file type is not
|
||||
/// supported, or false on success.
|
||||
virtual bool addPassesToEmitFile(PassManagerBase &, raw_pwrite_stream &,
|
||||
CodeGenFileType,
|
||||
bool /*DisableVerify*/ = true,
|
||||
AnalysisID /*StartAfter*/ = nullptr,
|
||||
AnalysisID /*StopAfter*/ = nullptr) {
|
||||
virtual bool addPassesToEmitFile(
|
||||
PassManagerBase &, raw_pwrite_stream &, CodeGenFileType,
|
||||
bool /*DisableVerify*/ = true, AnalysisID /*StartAfter*/ = nullptr,
|
||||
AnalysisID /*StopAfter*/ = nullptr,
|
||||
MachineFunctionInitializer * /*MFInitializer*/ = nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -238,7 +241,7 @@ public:
|
|||
class LLVMTargetMachine : public TargetMachine {
|
||||
protected: // Can only create subclasses.
|
||||
LLVMTargetMachine(const Target &T, StringRef DataLayoutString,
|
||||
StringRef TargetTriple, StringRef CPU, StringRef FS,
|
||||
const Triple &TargetTriple, StringRef CPU, StringRef FS,
|
||||
TargetOptions Options, Reloc::Model RM, CodeModel::Model CM,
|
||||
CodeGenOpt::Level OL);
|
||||
|
||||
|
@ -256,10 +259,11 @@ public:
|
|||
|
||||
/// Add passes to the specified pass manager to get the specified file
|
||||
/// emitted. Typically this will involve several steps of code generation.
|
||||
bool addPassesToEmitFile(PassManagerBase &PM, raw_pwrite_stream &Out,
|
||||
CodeGenFileType FileType, bool DisableVerify = true,
|
||||
AnalysisID StartAfter = nullptr,
|
||||
AnalysisID StopAfter = nullptr) override;
|
||||
bool addPassesToEmitFile(
|
||||
PassManagerBase &PM, raw_pwrite_stream &Out, CodeGenFileType FileType,
|
||||
bool DisableVerify = true, AnalysisID StartAfter = nullptr,
|
||||
AnalysisID StopAfter = nullptr,
|
||||
MachineFunctionInitializer *MFInitializer = nullptr) override;
|
||||
|
||||
/// Add passes to the specified pass manager to get machine code emitted with
|
||||
/// the MCJIT. This method returns true if machine code is not supported. It
|
||||
|
|
|
@ -122,6 +122,12 @@ enum {
|
|||
/// label. Created by the llvm.frameallocate intrinsic. It has two arguments:
|
||||
/// the symbol for the label and the frame index of the stack allocation.
|
||||
FRAME_ALLOC = 21,
|
||||
|
||||
/// Loading instruction that may page fault, bundled with associated
|
||||
/// information on how to handle such a page fault. It is intended to support
|
||||
/// "zero cost" null checks in managed languages by allowing LLVM to fold
|
||||
/// comparisions into existing memory operations.
|
||||
FAULTING_LOAD_OP = 22,
|
||||
};
|
||||
} // end namespace TargetOpcode
|
||||
} // end namespace llvm
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#ifndef LLVM_TARGET_TARGETOPTIONS_H
|
||||
#define LLVM_TARGET_TARGETOPTIONS_H
|
||||
|
||||
#include "llvm/Target/TargetRecip.h"
|
||||
#include "llvm/MC/MCTargetOptions.h"
|
||||
#include <string>
|
||||
|
||||
|
@ -66,13 +67,14 @@ namespace llvm {
|
|||
HonorSignDependentRoundingFPMathOption(false),
|
||||
NoZerosInBSS(false),
|
||||
GuaranteedTailCallOpt(false),
|
||||
DisableTailCalls(false), StackAlignmentOverride(0),
|
||||
StackAlignmentOverride(0),
|
||||
EnableFastISel(false), PositionIndependentExecutable(false),
|
||||
UseInitArray(false), DisableIntegratedAS(false),
|
||||
CompressDebugSections(false), FunctionSections(false),
|
||||
DataSections(false), UniqueSectionNames(true), TrapUnreachable(false),
|
||||
TrapFuncName(), FloatABIType(FloatABI::Default),
|
||||
AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single),
|
||||
AllowFPOpFusion(FPOpFusion::Standard), Reciprocals(TargetRecip()),
|
||||
JTType(JumpTable::Single),
|
||||
ThreadModel(ThreadModel::POSIX) {}
|
||||
|
||||
/// PrintMachineCode - This flag is enabled when the -print-machineinstrs
|
||||
|
@ -135,10 +137,6 @@ namespace llvm {
|
|||
/// as their parent function, etc.), using an alternate ABI if necessary.
|
||||
unsigned GuaranteedTailCallOpt : 1;
|
||||
|
||||
/// DisableTailCalls - This flag controls whether we will use tail calls.
|
||||
/// Disabling them may be useful to maintain a correct call stack.
|
||||
unsigned DisableTailCalls : 1;
|
||||
|
||||
/// StackAlignmentOverride - Override default stack alignment for target.
|
||||
unsigned StackAlignmentOverride;
|
||||
|
||||
|
@ -206,6 +204,9 @@ namespace llvm {
|
|||
/// the value of this option.
|
||||
FPOpFusion::FPOpFusionMode AllowFPOpFusion;
|
||||
|
||||
/// This class encapsulates options for reciprocal-estimate code generation.
|
||||
TargetRecip Reciprocals;
|
||||
|
||||
/// JTType - This flag specifies the type of jump-instruction table to
|
||||
/// create for functions that have the jumptable attribute.
|
||||
JumpTable::JumpTableType JTType;
|
||||
|
@ -231,7 +232,6 @@ inline bool operator==(const TargetOptions &LHS,
|
|||
ARE_EQUAL(HonorSignDependentRoundingFPMathOption) &&
|
||||
ARE_EQUAL(NoZerosInBSS) &&
|
||||
ARE_EQUAL(GuaranteedTailCallOpt) &&
|
||||
ARE_EQUAL(DisableTailCalls) &&
|
||||
ARE_EQUAL(StackAlignmentOverride) &&
|
||||
ARE_EQUAL(EnableFastISel) &&
|
||||
ARE_EQUAL(PositionIndependentExecutable) &&
|
||||
|
@ -240,6 +240,7 @@ inline bool operator==(const TargetOptions &LHS,
|
|||
ARE_EQUAL(TrapFuncName) &&
|
||||
ARE_EQUAL(FloatABIType) &&
|
||||
ARE_EQUAL(AllowFPOpFusion) &&
|
||||
ARE_EQUAL(Reciprocals) &&
|
||||
ARE_EQUAL(JTType) &&
|
||||
ARE_EQUAL(ThreadModel) &&
|
||||
ARE_EQUAL(MCOptions);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user