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:
Richard Trieu 2015-06-18 23:39:21 +00:00
commit ca2e7a44ec
1401 changed files with 34328 additions and 9658 deletions

View File

@ -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

View File

@ -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" ;;

View File

@ -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} )

View File

@ -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
View File

@ -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" ;;

View File

@ -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.

View File

@ -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
View 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
}
}

View File

@ -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 |

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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
=================================

View File

@ -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.
*

View File

@ -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

View File

@ -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;
/**

View File

@ -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.

View File

@ -53,6 +53,7 @@
#include <cassert>
#include <cstring>
#include <iterator>
#include <string>
#include <utility>
namespace llvm {

View File

@ -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,

View File

@ -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);

View File

@ -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();

View File

@ -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.
///

View 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

View File

@ -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);

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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);

View 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

View File

@ -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

View File

@ -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; }

View 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

View File

@ -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.
///

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -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;
};
}

View File

@ -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

View File

@ -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.

View 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

View File

@ -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));
}
};

View File

@ -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.

View File

@ -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)

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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],

View File

@ -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">;

View File

@ -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.

View File

@ -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

View File

@ -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();

View File

@ -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());
}

View File

@ -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'

View File

@ -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&);

View 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

View File

@ -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();

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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(); }

View File

@ -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 {

View File

@ -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

View File

@ -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.
///

View File

@ -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:

View File

@ -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;

View File

@ -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

View File

@ -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; }

View File

@ -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);

View File

@ -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;

View File

@ -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

View 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

View File

@ -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;
};
}

View 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

View File

@ -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,

View 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

View File

@ -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;

View File

@ -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();
}
}
}

View File

@ -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

View File

@ -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) {

View File

@ -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 {

View File

@ -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:

View File

@ -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,

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View 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

View File

@ -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);

View File

@ -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);
}
};

View File

@ -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 {

View File

@ -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:

View File

@ -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;
}
}
//===----------------------------------------------------------------------===//

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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