diff --git a/.gitignore b/.gitignore index 02146ef0ac5..e3d191dcbcc 100644 --- a/.gitignore +++ b/.gitignore @@ -44,7 +44,7 @@ autoconf/autom4te.cache #==============================================================================# # External projects that are tracked independently. projects/* -!projects/CMakeLists.txt +!projects/*.* !projects/Makefile # Clang, which is tracked independently. tools/clang diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f9f40ffc84..b26e2692578 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,33 +26,29 @@ else() set(cmake_3_2_USES_TERMINAL USES_TERMINAL) endif() -project(LLVM) - -# @LOCALMOD-BEGIN -# Enable ccache for builds, if cmake is invoked with -DSYSTEM_HAS_CCACHE=ON. -# Set CCACHE_CPP2 envvar, to avoid an error due to a strange ccache/clang++ -# interaction. Specifically, errors about "argument unused during compilation". -option(SYSTEM_HAS_CCACHE "Use ccache for building" OFF) -if(SYSTEM_HAS_CCACHE) - set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) - set(ENV(CCACHE_CPP2) "yes") - add_compile_options(-Qunused-arguments) -endif() -# @LOCALMOD-END +project(LLVM C CXX ASM) # The following only works with the Ninja generator in CMake >= 3.0. 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 @@ -63,7 +59,7 @@ set(CMAKE_MODULE_PATH ) set(LLVM_VERSION_MAJOR 3) -set(LLVM_VERSION_MINOR 7) +set(LLVM_VERSION_MINOR 8) set(LLVM_VERSION_PATCH 0) set(LLVM_VERSION_SUFFIX svn) @@ -105,6 +101,7 @@ set(CPACK_PACKAGE_VERSION_MINOR ${LLVM_VERSION_MINOR}) set(CPACK_PACKAGE_VERSION_PATCH ${LLVM_VERSION_PATCH}) set(CPACK_PACKAGE_VERSION ${PACKAGE_VERSION}) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.TXT") +set(CPACK_NSIS_COMPRESSOR "/SOLID lzma \r\n SetCompressorDictSize 32") if(WIN32 AND NOT UNIX) set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "LLVM") set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}\\\\cmake\\\\nsis_logo.bmp") @@ -179,7 +176,9 @@ set(LLVM_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/include) set(LLVM_ALL_TARGETS AArch64 + AMDGPU ARM + BPF CppBackend Hexagon JSBackend # @LOCALMOD @@ -187,7 +186,6 @@ set(LLVM_ALL_TARGETS MSP430 NVPTX PowerPC - R600 Sparc SystemZ X86 @@ -234,13 +232,6 @@ option(LLVM_ENABLE_THREADS "Use threads if available." ON) option(LLVM_ENABLE_ZLIB "Use zlib for compression/decompression if available." ON) -set(SUBZERO_TARGETS_TO_BUILD "none" - CACHE STRING "Semicolon-separated list of targets to build, or \"none\".") - -if( SUBZERO_TARGETS_TO_BUILD STREQUAL "none" ) - set( SUBZERO_TARGETS_TO_BUILD "" ) -endif() - if( LLVM_TARGETS_TO_BUILD STREQUAL "all" ) set( LLVM_TARGETS_TO_BUILD ${LLVM_ALL_TARGETS} ) endif() @@ -486,11 +477,6 @@ foreach(t ${LLVM_TARGETS_TO_BUILD}) endif() endforeach(t) -set(SUBZERO_ENUM_TARGETS "") -foreach(t ${SUBZERO_TARGETS_TO_BUILD}) - set(SUBZERO_ENUM_TARGETS "${SUBZERO_ENUM_TARGETS}SUBZERO_TARGET(${t})\n") -endforeach(t) - # Produce the target definition files, which provide a way for clients to easily # include various classes of targets. configure_file( @@ -505,10 +491,6 @@ configure_file( ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/Disassemblers.def.in ${LLVM_INCLUDE_DIR}/llvm/Config/Disassemblers.def ) -configure_file( - ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/SZTargets.def.in - ${LLVM_INCLUDE_DIR}/llvm/Config/SZTargets.def - ) configure_file( ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/Targets.def.in ${LLVM_INCLUDE_DIR}/llvm/Config/Targets.def @@ -549,7 +531,7 @@ endif() # check its symbols. This is wasteful (the check was done when foo.so # was created) and can fail since it is not the dynamic linker and # doesn't know how to handle search paths correctly. -if (UNIX AND NOT APPLE) +if (UNIX AND NOT APPLE AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "SunOS") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-allow-shlib-undefined") endif() diff --git a/CODE_OWNERS.TXT b/CODE_OWNERS.TXT index 4e8ff888929..a15f2919cc7 100644 --- a/CODE_OWNERS.TXT +++ b/CODE_OWNERS.TXT @@ -65,6 +65,10 @@ N: Hal Finkel E: hfinkel@anl.gov D: BBVectorize, the loop reroller, alias analysis and the PowerPC target +N: Dan Gohman +E: sunfish@mozilla.com +D: WebAssembly Backend (lib/Target/WebAssembly/*) + N: Renato Golin E: renato.golin@linaro.org D: ARM Linux support @@ -89,6 +93,10 @@ N: Lang Hames E: lhames@gmail.com D: MCJIT, RuntimeDyld and JIT event listeners +N: David Majnemer +E: david.majnemer@gmail.com +D: IR Constant Folder + N: Galina Kistanova E: gkistanova@gmail.com D: LLVM Buildbot @@ -182,3 +190,7 @@ D: libLTO, IR Linker N: Peter Zotov E: whitequark@whitequark.org D: OCaml bindings + +N: Andrey Churbanov +E: andrey.churbanov@intel.com +D: OpenMP runtime library diff --git a/CREDITS.TXT b/CREDITS.TXT index 40d67f4f2dc..da1fb010e35 100644 --- a/CREDITS.TXT +++ b/CREDITS.TXT @@ -152,8 +152,9 @@ E: foldr@codedgers.com D: Author of llvmc2 N: Dan Gohman -E: dan433584@gmail.com +E: sunfish@mozilla.com D: Miscellaneous bug fixes +D: WebAssembly Backend N: David Goodwin E: david@goodwinz.net diff --git a/Makefile b/Makefile index e9559af0e67..2b9468af205 100644 --- a/Makefile +++ b/Makefile @@ -43,11 +43,6 @@ EXTRA_DIST := test unittests llvm.spec include win32 Xcode include $(LEVEL)/Makefile.config -ifeq ($(PNACL_BROWSER_TRANSLATOR),1) - DIRS := $(filter-out tools/llvm-shlib runtime docs unittests, $(DIRS)) - OPTIONAL_DIRS := -endif - ifneq ($(ENABLE_SHARED),1) DIRS := $(filter-out tools/llvm-shlib, $(DIRS)) endif @@ -111,15 +106,12 @@ all:: cross-compile-build-tools clean:: $(Verb) rm -rf BuildTools -# @LOCALMOD-START Pass BUILD_CFLAGS et al through for host libcxx; -# Only required to build on Ubuntu Precise cross-compile-build-tools: $(Verb) if [ ! -f BuildTools/Makefile ]; then \ $(MKDIR) BuildTools; \ cd BuildTools ; \ - CFLAGS="$(BUILD_CFLAGS)" ; \ - CXXFLAGS="$(BUILD_CXXFLAGS)" ; \ - LDFLAGS="$(BUILD_LDFLAGS)" ; \ + unset CFLAGS ; \ + unset CXXFLAGS ; \ AR=$(BUILD_AR) ; \ AS=$(BUILD_AS) ; \ LD=$(BUILD_LD) ; \ @@ -138,7 +130,6 @@ cross-compile-build-tools: fi; \ ($(MAKE) -C BuildTools \ BUILD_DIRS_ONLY=1 \ - PNACL_BROWSER_TRANSLATOR=0 \ UNIVERSAL= \ UNIVERSAL_SDK_PATH= \ SDKROOT= \ @@ -151,14 +142,10 @@ cross-compile-build-tools: DISABLE_ASSERTIONS=$(DISABLE_ASSERTIONS) \ ENABLE_EXPENSIVE_CHECKS=$(ENABLE_EXPENSIVE_CHECKS) \ ENABLE_LIBCPP=$(ENABLE_LIBCPP) \ - CC=$(BUILD_CC) \ - CXX=$(BUILD_CXX) \ - CFLAGS="$(BUILD_CFLAGS)" \ - CXXFLAGS="$(BUILD_CXXFLAGS)" \ - LDFLAGS="$(BUILD_LDFLAGS)" \ + CFLAGS= \ + CXXFLAGS= \ ) || exit 1; endif -# @LOCALMOD-END # Include the main makefile machinery. include $(LLVM_SRC_ROOT)/Makefile.rules @@ -214,7 +201,6 @@ FilesToConfig := \ llvm.spec \ include/llvm/Config/config.h \ include/llvm/Config/llvm-config.h \ - include/llvm/Config/SZTargets.def \ include/llvm/Config/Targets.def \ include/llvm/Config/AsmPrinters.def \ include/llvm/Config/AsmParsers.def \ diff --git a/Makefile.config.in b/Makefile.config.in index f4354d5628f..3258714ac59 100644 --- a/Makefile.config.in +++ b/Makefile.config.in @@ -58,15 +58,16 @@ LLVM_OBJ_ROOT := $(call realpath, @abs_top_builddir@) PROJ_SRC_ROOT := $(LLVM_SRC_ROOT) PROJ_SRC_DIR := $(LLVM_SRC_ROOT)$(patsubst $(PROJ_OBJ_ROOT)%,%,$(PROJ_OBJ_DIR)) +# See: http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20150323/268067.html +ifeq ($(LLVM_SRC_ROOT), $(LLVM_OBJ_ROOT)) + $(error In-source builds are not allowed. Please configure from a separate build directory!) +endif + ifneq ($(CLANG_SRC_ROOT),) CLANG_SRC_ROOT:= $(call realpath, $(CLANG_SRC_ROOT)) PROJ_SRC_DIR := $(patsubst $(LLVM_SRC_ROOT)/tools/clang%,$(CLANG_SRC_ROOT)%,$(PROJ_SRC_DIR)) endif -ifneq ($(SUBZERO_SRC_ROOT),) - PROJ_SRC_DIR := $(patsubst $(LLVM_SRC_ROOT)/tools/subzero%,$(SUBZERO_SRC_ROOT)%,$(PROJ_SRC_DIR)) -endif - prefix := @prefix@ PROJ_prefix := $(prefix) program_prefix := @program_prefix@ diff --git a/Makefile.rules b/Makefile.rules index 2a01833cc80..24cac3b3765 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -322,9 +322,9 @@ endif ifeq ($(ENABLE_CXX1Y),1) CXX.Flags += -std=c++1y else - ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW NativeClient)) - # MinGW, Cygwin, and NativeClient+newlib are a bit stricter and - # lack things like 'strdup', 'stricmp', etc in c++11 mode. + ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) + # MinGW and Cygwin are a bit stricter and lack things like + # 'strdup', 'stricmp', etc in c++11 mode. CXX.Flags += -std=gnu++11 else CXX.Flags += -std=c++11 @@ -671,11 +671,6 @@ ifneq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) endif endif -#@LOCALMOD-BEGIN -ifeq ($(PNACL_BROWSER_TRANSLATOR),1) - CPP.Flags += -DPNACL_BROWSER_TRANSLATOR -endif -# @LOCALMOD-END #---------------------------------------------------------- # Options To Invoke Tools diff --git a/OWNERS b/OWNERS deleted file mode 100644 index ac015a5aadb..00000000000 --- a/OWNERS +++ /dev/null @@ -1,8 +0,0 @@ -dschuff@chromium.org -eliben@chromium.org -jfb@chromium.org -jvoung@chromium.org -kschimpf@chromium.org -mseaborn@chromium.org -sehr@chromium.org -stichnot@chromium.org diff --git a/PRESUBMIT.py b/PRESUBMIT.py deleted file mode 100644 index d81168ea093..00000000000 --- a/PRESUBMIT.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright (c) 2012 The Native Client Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# Documentation on PRESUBMIT.py can be found at: -# http://www.chromium.org/developers/how-tos/depottools/presubmit-scripts - -EXCLUDE_PROJECT_CHECKS_DIRS = [ '.' ] - -import subprocess -def CheckGitBranch(): - p = subprocess.Popen("git branch -vv", shell=True, - stdout=subprocess.PIPE) - output, _ = p.communicate() - - lines = output.split('\n') - for line in lines: - # output format for checked-out branch should be - # * branchname hash [TrackedBranchName ... - toks = line.split() - if '*' not in toks[0]: - continue - if not 'origin/master' in toks[3]: - warning = 'Warning: your current branch:\n' + line - warning += '\nis not tracking origin/master. git cl push may silently ' - warning += 'fail to push your change. To fix this, do\n' - warning += 'git branch -u origin/master' - return warning - return None - print 'Warning: presubmit check could not determine local git branch' - return None - -def _CommonChecks(input_api, output_api): - """Checks for both upload and commit.""" - results = [] - results.extend(input_api.canned_checks.PanProjectChecks( - input_api, output_api, project_name='Native Client', - excluded_paths=tuple(EXCLUDE_PROJECT_CHECKS_DIRS))) - branch_warning = CheckGitBranch() - if branch_warning: - results.append(output_api.PresubmitPromptWarning(branch_warning)) - return results - -def CheckChangeOnUpload(input_api, output_api): - """Verifies all changes in all files. - Args: - input_api: the limited set of input modules allowed in presubmit. - output_api: the limited set of output modules allowed in presubmit. - """ - report = [] - report.extend(_CommonChecks(input_api, output_api)) - return report - -def CheckChangeOnCommit(input_api, output_api): - """Verifies all changes in all files and verifies that the - tree is open and can accept a commit. - Args: - input_api: the limited set of input modules allowed in presubmit. - output_api: the limited set of output modules allowed in presubmit. - """ - report = [] - report.extend(CheckChangeOnUpload(input_api, output_api)) - return report - -def GetPreferredTrySlaves(project, change): - return [] diff --git a/autoconf/config.guess b/autoconf/config.guess index 73d671bc2c6..b209a1a06c6 100755 --- a/autoconf/config.guess +++ b/autoconf/config.guess @@ -810,6 +810,9 @@ EOF *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; + *:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 diff --git a/autoconf/config.sub b/autoconf/config.sub index 4ef86e33fb3..2583c901235 100755 --- a/autoconf/config.sub +++ b/autoconf/config.sub @@ -239,10 +239,6 @@ case $os in basic_machine=m68k-atari os=-mint ;; - -nacl*) - basic_machine=i686-pc - os=-nacl - ;; esac # Decode aliases for certain CPU-COMPANY combinations. @@ -352,14 +348,6 @@ case $basic_machine in i*86 | x86_64) basic_machine=$basic_machine-pc ;; - nacl64*) - basic_machine=x86_64-pc - os=-nacl - ;; - nacl*) - basic_machine=i686-pc - os=-nacl - ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 @@ -1378,9 +1366,6 @@ case $os in ;; esac ;; - -nacl*) - os=-nacl - ;; -nto-qnx*) ;; -nto*) diff --git a/autoconf/configure.ac b/autoconf/configure.ac index fb5c4cc6d68..2968ec79a0b 100644 --- a/autoconf/configure.ac +++ b/autoconf/configure.ac @@ -32,10 +32,10 @@ dnl===-----------------------------------------------------------------------=== dnl Initialize autoconf and define the package name, version number and dnl address for reporting bugs. -AC_INIT([LLVM],[3.7.0svn],[http://llvm.org/bugs/]) +AC_INIT([LLVM],[3.8.0svn],[http://llvm.org/bugs/]) LLVM_VERSION_MAJOR=3 -LLVM_VERSION_MINOR=7 +LLVM_VERSION_MINOR=8 LLVM_VERSION_PATCH=0 LLVM_VERSION_SUFFIX=svn @@ -73,6 +73,11 @@ if test ${srcdir} != "." ; then fi fi +dnl Quit if it is an in-source build +if test ${srcdir} == "." ; then + AC_MSG_ERROR([In-source builds are not allowed. Please configure from a separate build directory!]) +fi + dnl Default to empty (i.e. assigning the null string to) CFLAGS and CXXFLAGS, dnl instead of the autoconf default (for example, '-g -O2' for CC=gcc). : ${CFLAGS=} @@ -105,7 +110,7 @@ if test "$CXX" = "clang++" ; then ], [ AC_MSG_RESULT([no]) - AC_MSG_ERROR([Selected compiler could not find or parse C++ standard library headers. Rerun with CC=c-compiler CXX=c++-compiler ./configure ...]) + AC_MSG_ERROR([Selected compiler could not find or parse C++ standard library headers. Rerun with CC=c-compiler CXX=c++-compiler LLVM_SRC_DIR/configure ...]) ]) AC_LANG_POP([C++]) fi @@ -322,11 +327,6 @@ AC_CACHE_CHECK([type of operating system we're going to host on], llvm_cv_no_link_all_option="-Wl,--no-whole-archive" llvm_cv_os_type="Freestanding" llvm_cv_platform_type="Unix" ;; - *-*-nacl*) - llvm_cv_link_all_option="-Wl,--whole-archive" - llvm_cv_no_link_all_option="-Wl,--no-whole-archive" - llvm_cv_os_type="NativeClient" - llvm_cv_platform_type="Unix" ;; *) llvm_cv_link_all_option="" llvm_cv_no_link_all_option="" @@ -437,6 +437,7 @@ AC_CACHE_CHECK([target architecture],[llvm_cv_target_arch], hexagon-*) llvm_cv_target_arch="Hexagon" ;; nvptx-*) llvm_cv_target_arch="NVPTX" ;; s390x-*) llvm_cv_target_arch="SystemZ" ;; + wasm*-*) llvm_cv_target_arch="WebAssembly" ;; *) llvm_cv_target_arch="Unknown" ;; esac]) @@ -472,6 +473,7 @@ case $host in msp430-*) host_arch="MSP430" ;; hexagon-*) host_arch="Hexagon" ;; s390x-*) host_arch="SystemZ" ;; + wasm*-*) host_arch="WebAssembly" ;; *) host_arch="Unknown" ;; esac @@ -804,6 +806,7 @@ else Hexagon) AC_SUBST(TARGET_HAS_JIT,0) ;; NVPTX) AC_SUBST(TARGET_HAS_JIT,0) ;; SystemZ) AC_SUBST(TARGET_HAS_JIT,1) ;; + WebAssembly) AC_SUBST(TARGET_HAS_JIT,0) ;; *) AC_SUBST(TARGET_HAS_JIT,0) ;; esac fi @@ -1089,7 +1092,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 JSBackend NVPTX Hexagon SystemZ R600" +ALL_TARGETS="X86 Sparc PowerPC ARM AArch64 Mips XCore MSP430 CppBackend NVPTX Hexagon SystemZ AMDGPU BPF JSBackend" AC_SUBST(ALL_TARGETS,$ALL_TARGETS) dnl Allow specific targets to be specified for building (or not) @@ -1097,7 +1100,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, js, and cpp (default=all)]),, + xcore, msp430, nvptx, systemz, r600, bpf, wasm, js, and cpp (default=all)]),, enableval=all) if test "$enableval" = host-only ; then enableval=host @@ -1113,6 +1116,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" ;; @@ -1124,7 +1128,9 @@ 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" ;; + wasm) TARGETS_TO_BUILD="WebAssembly $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" ;; @@ -1138,6 +1144,7 @@ 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" ;; + WebAssembly) TARGETS_TO_BUILD="WebAssembly $TARGETS_TO_BUILD" ;; *) AC_MSG_ERROR([Can not set target to build]) ;; esac ;; *) AC_MSG_ERROR([Unrecognized target $a_target]) ;; @@ -1216,34 +1223,6 @@ AC_SUBST(LLVM_ENUM_ASM_PRINTERS) AC_SUBST(LLVM_ENUM_ASM_PARSERS) AC_SUBST(LLVM_ENUM_DISASSEMBLERS) - -dnl Allow specific Subzero targets to be specified for building (or not) -SUBZERO_TARGETS_TO_BUILD="" -AC_ARG_ENABLE([subzero_targets],AS_HELP_STRING([--enable-subzero-targets], - [Build specific subzero targets: target1,target2,...(default=none)]),, - enableval=none) -case "$enableval" in - none) ;; - *)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do - case "$a_target" in - X8632) SUBZERO_TARGETS_TO_BUILD="X8632 $SUBZERO_TARGETS_TO_BUILD" ;; - X8664) SUBZERO_TARGETS_TO_BUILD="X8664 $SUBZERO_TARGETS_TO_BUILD" ;; - ARM32) SUBZERO_TARGETS_TO_BUILD="ARM32 $SUBZERO_TARGETS_TO_BUILD" ;; - ARM64) SUBZERO_TARGETS_TO_BUILD="ARM64 $SUBZERO_TARGETS_TO_BUILD" ;; - MIPS32) SUBZERO_TARGETS_TO_BUILD="MIPS32 $SUBZERO_TARGETS_TO_BUILD" ;; - *) AC_MSG_ERROR([Unrecognized subzero target $a_target]) ;; - esac - done - ;; -esac - -dnl Build the SUBZERO_ENUM_TARGETS macro for SZTargets.def. -SUBZERO_ENUM_TARGETS="" -for target_to_build in $SUBZERO_TARGETS_TO_BUILD; do - SUBZERO_ENUM_TARGETS="SUBZERO_TARGET($target_to_build) $SUBZERO_ENUM_TARGETS" -done -AC_SUBST(SUBZERO_ENUM_TARGETS) - dnl Override the option to use for optimized builds. AC_ARG_WITH(optimize-option, AS_HELP_STRING([--with-optimize-option], @@ -1358,6 +1337,13 @@ AC_ARG_WITH(default-sysroot, AC_DEFINE_UNQUOTED(DEFAULT_SYSROOT,"$withval", [Default to all compiler invocations for --sysroot=.]) +AC_ARG_WITH(clang-default-openmp-runtime, + AS_HELP_STRING([--with-clang-default-openmp-runtime], + [The default OpenMP runtime for Clang.]),, + withval="libgomp") +AC_DEFINE_UNQUOTED(CLANG_DEFAULT_OPENMP_RUNTIME,"$withval", + [Default OpenMP runtime used by -fopenmp.]) + dnl Allow linking of LLVM with GPLv3 binutils code. AC_ARG_WITH(binutils-include, AS_HELP_STRING([--with-binutils-include], @@ -1643,7 +1629,7 @@ dnl===-----------------------------------------------------------------------=== AC_CHECK_LIB(m,sin) if test "$llvm_cv_os_type" = "MingW" ; then - AC_CHECK_LIB(imagehlp, main) + AC_CHECK_LIB(ole32, main) AC_CHECK_LIB(psapi, main) AC_CHECK_LIB(shell32, main) fi @@ -2184,10 +2170,12 @@ dnl contains the same list of files as AC_CONFIG_HEADERS below. This ensures the dnl files can be updated automatically when their *.in sources change. AC_CONFIG_HEADERS([include/llvm/Config/config.h include/llvm/Config/llvm-config.h]) AH_TOP([#ifndef CONFIG_H -#define CONFIG_H]) +#define CONFIG_H + +/* Exported configuration */ +#include "llvm/Config/llvm-config.h"]) AH_BOTTOM([#endif]) -AC_CONFIG_FILES([include/llvm/Config/SZTargets.def]) AC_CONFIG_FILES([include/llvm/Config/Targets.def]) AC_CONFIG_FILES([include/llvm/Config/AsmPrinters.def]) AC_CONFIG_FILES([include/llvm/Config/AsmParsers.def]) diff --git a/bindings/go/llvm/DIBuilderBindings.cpp b/bindings/go/llvm/DIBuilderBindings.cpp index cfae6053bfe..627c09131aa 100644 --- a/bindings/go/llvm/DIBuilderBindings.cpp +++ b/bindings/go/llvm/DIBuilderBindings.cpp @@ -40,16 +40,14 @@ LLVMMetadataRef LLVMDIBuilderCreateCompileUnit(LLVMDIBuilderRef Dref, int Optimized, const char *Flags, unsigned RuntimeVersion) { DIBuilder *D = unwrap(Dref); - DICompileUnit CU = D->createCompileUnit(Lang, File, Dir, Producer, Optimized, - Flags, RuntimeVersion); - return wrap(CU); + return wrap(D->createCompileUnit(Lang, File, Dir, Producer, Optimized, Flags, + RuntimeVersion)); } LLVMMetadataRef LLVMDIBuilderCreateFile(LLVMDIBuilderRef Dref, const char *File, const char *Dir) { DIBuilder *D = unwrap(Dref); - DIFile F = D->createFile(File, Dir); - return wrap(F); + return wrap(D->createFile(File, Dir)); } LLVMMetadataRef LLVMDIBuilderCreateLexicalBlock(LLVMDIBuilderRef Dref, @@ -58,8 +56,8 @@ LLVMMetadataRef LLVMDIBuilderCreateLexicalBlock(LLVMDIBuilderRef Dref, unsigned Line, unsigned Column) { DIBuilder *D = unwrap(Dref); - auto *LB = D->createLexicalBlock(unwrap(Scope), - unwrap(File), Line, Column); + auto *LB = D->createLexicalBlock(unwrap(Scope), + unwrap(File), Line, Column); return wrap(LB); } @@ -68,9 +66,8 @@ LLVMMetadataRef LLVMDIBuilderCreateLexicalBlockFile(LLVMDIBuilderRef Dref, LLVMMetadataRef File, unsigned Discriminator) { DIBuilder *D = unwrap(Dref); - DILexicalBlockFile LBF = D->createLexicalBlockFile( - unwrap(Scope), unwrap(File), Discriminator); - return wrap(LBF); + return wrap(D->createLexicalBlockFile(unwrap(Scope), + unwrap(File), Discriminator)); } LLVMMetadataRef LLVMDIBuilderCreateFunction( @@ -79,23 +76,26 @@ LLVMMetadataRef LLVMDIBuilderCreateFunction( LLVMMetadataRef CompositeType, int IsLocalToUnit, int IsDefinition, unsigned ScopeLine, unsigned Flags, int IsOptimized, LLVMValueRef Func) { DIBuilder *D = unwrap(Dref); - DISubprogram SP = D->createFunction( - unwrap(Scope), Name, LinkageName, - File ? unwrap(File) : nullptr, Line, - unwrap(CompositeType), IsLocalToUnit, IsDefinition, - ScopeLine, Flags, IsOptimized, unwrap(Func)); - return wrap(SP); + return wrap(D->createFunction(unwrap(Scope), Name, LinkageName, + File ? unwrap(File) : nullptr, Line, + unwrap(CompositeType), + IsLocalToUnit, IsDefinition, ScopeLine, Flags, + IsOptimized, unwrap(Func))); } LLVMMetadataRef LLVMDIBuilderCreateLocalVariable( - LLVMDIBuilderRef Dref, unsigned Tag, LLVMMetadataRef Scope, + LLVMDIBuilderRef Dref, unsigned, LLVMMetadataRef Scope, const char *Name, LLVMMetadataRef File, unsigned Line, LLVMMetadataRef Ty, int AlwaysPreserve, unsigned Flags, unsigned ArgNo) { DIBuilder *D = unwrap(Dref); - DIVariable V = D->createLocalVariable( - Tag, unwrap(Scope), Name, unwrap(File), Line, - unwrap(Ty), AlwaysPreserve, Flags, ArgNo); - return wrap(V); + // FIXME: Update the Go bindings to match the DIBuilder API. + if (ArgNo) + return wrap(D->createParameterVariable( + unwrap(Scope), Name, ArgNo, unwrap(File), Line, + unwrap(Ty), AlwaysPreserve, Flags)); + return wrap(D->createAutoVariable(unwrap(Scope), Name, + unwrap(File), Line, + unwrap(Ty), AlwaysPreserve, Flags)); } LLVMMetadataRef LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef Dref, @@ -104,8 +104,7 @@ LLVMMetadataRef LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef Dref, uint64_t AlignInBits, unsigned Encoding) { DIBuilder *D = unwrap(Dref); - DIBasicType T = D->createBasicType(Name, SizeInBits, AlignInBits, Encoding); - return wrap(T); + return wrap(D->createBasicType(Name, SizeInBits, AlignInBits, Encoding)); } LLVMMetadataRef LLVMDIBuilderCreatePointerType(LLVMDIBuilderRef Dref, @@ -114,19 +113,17 @@ LLVMMetadataRef LLVMDIBuilderCreatePointerType(LLVMDIBuilderRef Dref, uint64_t AlignInBits, const char *Name) { DIBuilder *D = unwrap(Dref); - DIDerivedType T = D->createPointerType(unwrap(PointeeType), - SizeInBits, AlignInBits, Name); - return wrap(T); + return wrap(D->createPointerType(unwrap(PointeeType), SizeInBits, + AlignInBits, Name)); } LLVMMetadataRef LLVMDIBuilderCreateSubroutineType(LLVMDIBuilderRef Dref, LLVMMetadataRef File, LLVMMetadataRef ParameterTypes) { DIBuilder *D = unwrap(Dref); - DICompositeType CT = - D->createSubroutineType(File ? unwrap(File) : nullptr, - DITypeArray(unwrap(ParameterTypes))); - return wrap(CT); + return wrap( + D->createSubroutineType(File ? unwrap(File) : nullptr, + DITypeRefArray(unwrap(ParameterTypes)))); } LLVMMetadataRef LLVMDIBuilderCreateStructType( @@ -135,12 +132,11 @@ LLVMMetadataRef LLVMDIBuilderCreateStructType( uint64_t AlignInBits, unsigned Flags, LLVMMetadataRef DerivedFrom, LLVMMetadataRef ElementTypes) { DIBuilder *D = unwrap(Dref); - DICompositeType CT = D->createStructType( - unwrap(Scope), Name, File ? unwrap(File) : nullptr, Line, + return wrap(D->createStructType( + unwrap(Scope), Name, File ? unwrap(File) : nullptr, Line, SizeInBits, AlignInBits, Flags, - DerivedFrom ? unwrap(DerivedFrom) : nullptr, - ElementTypes ? DIArray(unwrap(ElementTypes)) : nullptr); - return wrap(CT); + DerivedFrom ? unwrap(DerivedFrom) : nullptr, + ElementTypes ? DINodeArray(unwrap(ElementTypes)) : nullptr)); } LLVMMetadataRef LLVMDIBuilderCreateReplaceableCompositeType( @@ -149,10 +145,9 @@ LLVMMetadataRef LLVMDIBuilderCreateReplaceableCompositeType( unsigned RuntimeLang, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags) { DIBuilder *D = unwrap(Dref); - DICompositeType CT = D->createReplaceableCompositeType( - Tag, Name, unwrap(Scope), File ? unwrap(File) : nullptr, - Line, RuntimeLang, SizeInBits, AlignInBits, Flags); - return wrap(CT); + return wrap(D->createReplaceableCompositeType( + Tag, Name, unwrap(Scope), File ? unwrap(File) : nullptr, + Line, RuntimeLang, SizeInBits, AlignInBits, Flags)); } LLVMMetadataRef @@ -162,10 +157,9 @@ LLVMDIBuilderCreateMemberType(LLVMDIBuilderRef Dref, LLVMMetadataRef Scope, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, LLVMMetadataRef Ty) { DIBuilder *D = unwrap(Dref); - DIDerivedType DT = D->createMemberType( - unwrap(Scope), Name, File ? unwrap(File) : nullptr, Line, - SizeInBits, AlignInBits, OffsetInBits, Flags, unwrap(Ty)); - return wrap(DT); + return wrap(D->createMemberType( + unwrap(Scope), Name, File ? unwrap(File) : nullptr, Line, + SizeInBits, AlignInBits, OffsetInBits, Flags, unwrap(Ty))); } LLVMMetadataRef LLVMDIBuilderCreateArrayType(LLVMDIBuilderRef Dref, @@ -174,10 +168,9 @@ LLVMMetadataRef LLVMDIBuilderCreateArrayType(LLVMDIBuilderRef Dref, LLVMMetadataRef ElementType, LLVMMetadataRef Subscripts) { DIBuilder *D = unwrap(Dref); - DICompositeType CT = - D->createArrayType(SizeInBits, AlignInBits, unwrap(ElementType), - DIArray(unwrap(Subscripts))); - return wrap(CT); + return wrap(D->createArrayType(SizeInBits, AlignInBits, + unwrap(ElementType), + DINodeArray(unwrap(Subscripts)))); } LLVMMetadataRef LLVMDIBuilderCreateTypedef(LLVMDIBuilderRef Dref, @@ -185,17 +178,15 @@ LLVMMetadataRef LLVMDIBuilderCreateTypedef(LLVMDIBuilderRef Dref, LLVMMetadataRef File, unsigned Line, LLVMMetadataRef Context) { DIBuilder *D = unwrap(Dref); - DIDerivedType DT = D->createTypedef( - unwrap(Ty), Name, File ? unwrap(File) : nullptr, Line, - Context ? unwrap(Context) : nullptr); - return wrap(DT); + return wrap(D->createTypedef(unwrap(Ty), Name, + File ? unwrap(File) : nullptr, Line, + Context ? unwrap(Context) : nullptr)); } LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange(LLVMDIBuilderRef Dref, int64_t Lo, int64_t Count) { DIBuilder *D = unwrap(Dref); - DISubrange S = D->getOrCreateSubrange(Lo, Count); - return wrap(S); + return wrap(D->getOrCreateSubrange(Lo, Count)); } LLVMMetadataRef LLVMDIBuilderGetOrCreateArray(LLVMDIBuilderRef Dref, @@ -204,7 +195,7 @@ LLVMMetadataRef LLVMDIBuilderGetOrCreateArray(LLVMDIBuilderRef Dref, DIBuilder *D = unwrap(Dref); Metadata **DataValue = unwrap(Data); ArrayRef Elements(DataValue, Length); - DIArray A = D->getOrCreateArray(Elements); + DINodeArray A = D->getOrCreateArray(Elements); return wrap(A.get()); } @@ -214,15 +205,14 @@ LLVMMetadataRef LLVMDIBuilderGetOrCreateTypeArray(LLVMDIBuilderRef Dref, DIBuilder *D = unwrap(Dref); Metadata **DataValue = unwrap(Data); ArrayRef Elements(DataValue, Length); - DITypeArray A = D->getOrCreateTypeArray(Elements); + DITypeRefArray A = D->getOrCreateTypeArray(Elements); return wrap(A.get()); } LLVMMetadataRef LLVMDIBuilderCreateExpression(LLVMDIBuilderRef Dref, int64_t *Addr, size_t Length) { DIBuilder *D = unwrap(Dref); - DIExpression Expr = D->createExpression(ArrayRef(Addr, Length)); - return wrap(Expr); + return wrap(D->createExpression(ArrayRef(Addr, Length))); } LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef Dref, @@ -236,8 +226,8 @@ LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef Dref, DIBuilder *D = unwrap(Dref); Instruction *Instr = D->insertDeclare( - unwrap(Storage), unwrap(VarInfo), - unwrap(Expr), /* DebugLoc */ nullptr, unwrap(Block)); + unwrap(Storage), unwrap(VarInfo), + unwrap(Expr), /* DebugLoc */ nullptr, unwrap(Block)); return wrap(Instr); } @@ -252,7 +242,7 @@ LLVMValueRef LLVMDIBuilderInsertValueAtEnd(LLVMDIBuilderRef Dref, DIBuilder *D = unwrap(Dref); Instruction *Instr = D->insertDbgValueIntrinsic( - unwrap(Val), Offset, unwrap(VarInfo), - unwrap(Expr), /* DebugLoc */ nullptr, unwrap(Block)); + unwrap(Val), Offset, unwrap(VarInfo), + unwrap(Expr), /* DebugLoc */ nullptr, unwrap(Block)); return wrap(Instr); } diff --git a/bindings/go/llvm/ir.go b/bindings/go/llvm/ir.go index e5916a1bacf..8fcd6ec4d74 100644 --- a/bindings/go/llvm/ir.go +++ b/bindings/go/llvm/ir.go @@ -160,6 +160,8 @@ const ( InAllocaAttribute Attribute = 1 << 43 NonNullAttribute Attribute = 1 << 44 JumpTableAttribute Attribute = 1 << 45 + ConvergentAttribute Attribute = 1 << 46 + SafeStackAttribute Attribute = 1 << 47 ) //------------------------------------------------------------------------- @@ -1052,6 +1054,9 @@ func (v Value) AddTargetDependentFunctionAttr(attr, value string) { defer C.free(unsafe.Pointer(cvalue)) C.LLVMAddTargetDependentFunctionAttr(v.C, cattr, cvalue) } +func (v Value) SetPersonality(p Value) { + C.LLVMSetPersonalityFn(v.C, p.C) +} // Operations on parameters func (v Value) ParamsCount() int { return int(C.LLVMCountParams(v.C)) } @@ -1204,7 +1209,7 @@ func (b Builder) Dispose() { C.LLVMDisposeBuilder(b.C) } func (b Builder) SetCurrentDebugLocation(line, col uint, scope, inlinedAt Metadata) { C.LLVMSetCurrentDebugLocation2(b.C, C.unsigned(line), C.unsigned(col), scope.C, inlinedAt.C) } -func (b Builder) SetInstDebugLocation(v Value) { C.LLVMSetInstDebugLocation(b.C, v.C) } +func (b Builder) SetInstDebugLocation(v Value) { C.LLVMSetInstDebugLocation(b.C, v.C) } func (b Builder) InsertDeclare(module Module, storage Value, md Value) Value { f := module.NamedFunction("llvm.dbg.declare") if f.IsNil() { @@ -1723,10 +1728,10 @@ func (b Builder) CreatePtrDiff(lhs, rhs Value, name string) (v Value) { return } -func (b Builder) CreateLandingPad(t Type, personality Value, nclauses int, name string) (l Value) { +func (b Builder) CreateLandingPad(t Type, nclauses int, name string) (l Value) { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) - l.C = C.LLVMBuildLandingPad(b.C, t.C, personality.C, C.unsigned(nclauses), cname) + l.C = C.LLVMBuildLandingPad(b.C, t.C, nil, C.unsigned(nclauses), cname) return l } diff --git a/bindings/go/llvm/ir_test.go b/bindings/go/llvm/ir_test.go index 981c94aa63e..edeeab935db 100644 --- a/bindings/go/llvm/ir_test.go +++ b/bindings/go/llvm/ir_test.go @@ -53,6 +53,7 @@ func TestAttributes(t *testing.T) { {AlwaysInlineAttribute, "alwaysinline"}, {BuiltinAttribute, "builtin"}, {ByValAttribute, "byval"}, + {ConvergentAttribute, "convergent"}, {InAllocaAttribute, "inalloca"}, {InlineHintAttribute, "inlinehint"}, {InRegAttribute, "inreg"}, @@ -78,6 +79,7 @@ func TestAttributes(t *testing.T) { {ReturnedAttribute, "returned"}, {ReturnsTwiceAttribute, "returns_twice"}, {SExtAttribute, "signext"}, + {SafeStackAttribute, "safestack"}, {StackProtectAttribute, "ssp"}, {StackProtectReqAttribute, "sspreq"}, {StackProtectStrongAttribute, "sspstrong"}, diff --git a/bindings/ocaml/Makefile.ocaml b/bindings/ocaml/Makefile.ocaml index 1f65a7b8f90..22b96a298ef 100644 --- a/bindings/ocaml/Makefile.ocaml +++ b/bindings/ocaml/Makefile.ocaml @@ -277,6 +277,8 @@ uninstall-local:: uninstall-deplibs build-deplibs: $(OutputLibs) +$(OcamlDir)/%.so: $(LibDir)/%.so + $(Verb) ln -sf $< $@ $(OcamlDir)/%.a: $(LibDir)/%.a $(Verb) ln -sf $< $@ diff --git a/bindings/ocaml/executionengine/llvm_executionengine.ml b/bindings/ocaml/executionengine/llvm_executionengine.ml index 34031bed603..3f37e0c9d3d 100644 --- a/bindings/ocaml/executionengine/llvm_executionengine.ml +++ b/bindings/ocaml/executionengine/llvm_executionengine.ml @@ -43,11 +43,11 @@ external run_static_dtors : llexecutionengine -> unit = "llvm_ee_run_static_dtors" external data_layout : llexecutionengine -> Llvm_target.DataLayout.t = "llvm_ee_get_data_layout" -external add_global_mapping_ : Llvm.llvalue -> int64 -> llexecutionengine -> unit +external add_global_mapping_ : Llvm.llvalue -> nativeint -> llexecutionengine -> unit = "llvm_ee_add_global_mapping" -external get_global_value_address_ : string -> llexecutionengine -> int64 +external get_global_value_address_ : string -> llexecutionengine -> nativeint = "llvm_ee_get_global_value_address" -external get_function_address_ : string -> llexecutionengine -> int64 +external get_function_address_ : string -> llexecutionengine -> nativeint = "llvm_ee_get_function_address" let add_global_mapping llval ptr ee = @@ -55,14 +55,14 @@ let add_global_mapping llval ptr ee = let get_global_value_address name typ ee = let vptr = get_global_value_address_ name ee in - if Int64.to_int vptr <> 0 then + if Nativeint.to_int vptr <> 0 then let open Ctypes in !@ (coerce (ptr void) (ptr typ) (ptr_of_raw_address vptr)) else raise (Error ("Value " ^ name ^ " not found")) let get_function_address name typ ee = let fptr = get_function_address_ name ee in - if Int64.to_int fptr <> 0 then + if Nativeint.to_int fptr <> 0 then let open Ctypes in coerce (ptr void) typ (ptr_of_raw_address fptr) else raise (Error ("Function " ^ name ^ " not found")) diff --git a/bindings/python/llvm/object.py b/bindings/python/llvm/object.py index 4e912ed5da9..b427113e9ce 100644 --- a/bindings/python/llvm/object.py +++ b/bindings/python/llvm/object.py @@ -371,14 +371,6 @@ def __init__(self, ptr): self.expired = False - @CachedProperty - def address(self): - """The address of this relocation, in long bytes.""" - if self.expired: - raise Exception('Relocation instance has expired.') - - return lib.LLVMGetRelocationAddress(self) - @CachedProperty def offset(self): """The offset of this relocation, in long bytes.""" @@ -498,9 +490,6 @@ def register_library(library): library.LLVMGetSymbolSize.argtypes = [Symbol] library.LLVMGetSymbolSize.restype = c_uint64 - library.LLVMGetRelocationAddress.argtypes = [c_object_p] - library.LLVMGetRelocationAddress.restype = c_uint64 - library.LLVMGetRelocationOffset.argtypes = [c_object_p] library.LLVMGetRelocationOffset.restype = c_uint64 diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake index c57f9006a84..74cd76e5167 100755 --- a/cmake/config-ix.cmake +++ b/cmake/config-ix.cmake @@ -358,6 +358,10 @@ elseif (LLVM_NATIVE_ARCH MATCHES "hexagon") set(LLVM_NATIVE_ARCH Hexagon) elseif (LLVM_NATIVE_ARCH MATCHES "s390x") set(LLVM_NATIVE_ARCH SystemZ) +elseif (LLVM_NATIVE_ARCH MATCHES "wasm32") + set(LLVM_NATIVE_ARCH WebAssembly) +elseif (LLVM_NATIVE_ARCH MATCHES "wasm64") + set(LLVM_NATIVE_ARCH WebAssembly) else () message(FATAL_ERROR "Unknown architecture ${LLVM_NATIVE_ARCH}") endif () @@ -393,12 +397,10 @@ else () endif () if( MINGW ) - set(HAVE_LIBIMAGEHLP 1) set(HAVE_LIBPSAPI 1) set(HAVE_LIBSHELL32 1) # TODO: Check existence of libraries. # include(CheckLibraryExists) - # CHECK_LIBRARY_EXISTS(imagehlp ??? . HAVE_LIBIMAGEHLP) endif( MINGW ) if (NOT HAVE_STRTOLL) @@ -489,7 +491,7 @@ if (LLVM_ENABLE_DOXYGEN) option(LLVM_DOXYGEN_EXTERNAL_SEARCH "Enable doxygen external search." OFF) if (LLVM_DOXYGEN_EXTERNAL_SEARCH) - set(LLVM_DOXYGEN_SEARCHENGINE_URL "" CACHE STRING "URL to use for external searhc.") + set(LLVM_DOXYGEN_SEARCHENGINE_URL "" CACHE STRING "URL to use for external search.") set(LLVM_DOXYGEN_SEARCH_MAPPINGS "" CACHE STRING "Doxygen Search Mappings") endif() endif() @@ -526,11 +528,9 @@ else() endif() endif() -find_program(GOLD_EXECUTABLE NAMES ld.gold ld DOC "The gold linker") -if(GOLD_EXECUTABLE) - set(LLVM_BINUTILS_INCDIR "" CACHE PATH - "PATH to binutils/include containing plugin-api.h for gold plugin.") -endif() +find_program(GOLD_EXECUTABLE NAMES ${LLVM_DEFAULT_TARGET_TRIPLE}-ld.gold ld.gold ${LLVM_DEFAULT_TARGET_TRIPLE}-ld ld DOC "The gold linker") +set(LLVM_BINUTILS_INCDIR "" CACHE PATH + "PATH to binutils/include containing plugin-api.h for gold plugin.") if(APPLE) find_program(LD64_EXECUTABLE NAMES ld DOC "The ld64 linker") @@ -548,13 +548,13 @@ else() if( OCAML_VERSION VERSION_LESS "4.00.0" ) message(STATUS "OCaml bindings disabled, need OCaml >=4.00.0.") else() - find_ocamlfind_package(ctypes VERSION 0.3 OPTIONAL) + find_ocamlfind_package(ctypes VERSION 0.4 OPTIONAL) if( HAVE_OCAML_CTYPES ) message(STATUS "OCaml bindings enabled.") find_ocamlfind_package(oUnit VERSION 2 OPTIONAL) set(LLVM_BINDINGS "${LLVM_BINDINGS} ocaml") else() - message(STATUS "OCaml bindings disabled, need ctypes >=0.3.") + message(STATUS "OCaml bindings disabled, need ctypes >=0.4.") endif() endif() endif() diff --git a/cmake/modules/AddLLVM.cmake b/cmake/modules/AddLLVM.cmake index ba6e2c508ea..34441173fac 100644 --- a/cmake/modules/AddLLVM.cmake +++ b/cmake/modules/AddLLVM.cmake @@ -1,4 +1,3 @@ -include(LLVMParseArguments) include(LLVMProcessSources) include(LLVM-Config) @@ -84,34 +83,24 @@ function(add_llvm_symbol_exports target_name export_file) DEPENDS ${export_file} VERBATIM COMMENT "Creating export file for ${target_name}") - set_property(TARGET ${target_name} APPEND_STRING PROPERTY - LINK_FLAGS " -Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}") + if (${CMAKE_SYSTEM_NAME} MATCHES "SunOS") + set_property(TARGET ${target_name} APPEND_STRING PROPERTY + LINK_FLAGS " -Wl,-M,${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}") + else() + set_property(TARGET ${target_name} APPEND_STRING PROPERTY + LINK_FLAGS " -Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}") + endif() else() set(native_export_file "${target_name}.def") - set(CAT "cat") - set(export_file_nativeslashes ${export_file}) - if(WIN32 AND NOT CYGWIN) - set(CAT "type") - # Convert ${export_file} to native format (backslashes) for "type" - # Does not use file(TO_NATIVE_PATH) as it doesn't create a native - # path but a build-system specific format (see CMake bug - # http://public.kitware.com/Bug/print_bug_page.php?bug_id=5939 ) - string(REPLACE / \\ export_file_nativeslashes ${export_file}) - endif() - add_custom_command(OUTPUT ${native_export_file} - COMMAND ${CMAKE_COMMAND} -E echo "EXPORTS" > ${native_export_file} - COMMAND ${CAT} ${export_file_nativeslashes} >> ${native_export_file} + COMMAND ${PYTHON_EXECUTABLE} -c "import sys;print(''.join(['EXPORTS\\n']+sys.stdin.readlines(),))" + < ${export_file} > ${native_export_file} DEPENDS ${export_file} VERBATIM COMMENT "Creating export file for ${target_name}") set(export_file_linker_flag "${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}") if(MSVC) - # set(export_file_linker_flag "/DEF:${export_file_linker_flag}") - # XXX Emscripten: Fix build when build directory has spaces in it. - # See bug https://github.com/kripken/emscripten/issues/3382 and - # https://llvm.org/bugs/show_bug.cgi?id=23313 . set(export_file_linker_flag "/DEF:\"${export_file_linker_flag}\"") endif() set_property(TARGET ${target_name} APPEND_STRING PROPERTY @@ -168,7 +157,7 @@ function(add_link_opts target_name) # Pass -O3 to the linker. This enabled different optimizations on different # linkers. - if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR WIN32)) + if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin|SunOS" OR WIN32)) set_property(TARGET ${target_name} APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-O3") endif() @@ -186,6 +175,9 @@ function(add_link_opts target_name) # ld64's implementation of -dead_strip breaks tools that use plugins. set_property(TARGET ${target_name} APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-dead_strip") + elseif(${CMAKE_SYSTEM_NAME} MATCHES "SunOS") + set_property(TARGET ${target_name} APPEND_STRING PROPERTY + LINK_FLAGS " -Wl,-z -Wl,discard-unused=sections") elseif(NOT WIN32 AND NOT LLVM_LINKER_IS_GOLD) # Object files are compiled with -ffunction-data-sections. # Versions of bfd ld < 2.23.1 have a bug in --gc-sections that breaks @@ -232,6 +224,78 @@ 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_FLAGS /nologo) + 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. @@ -320,10 +384,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} ) @@ -421,11 +492,17 @@ macro(add_llvm_library name) else() llvm_add_library(${name} ${ARGN}) endif() - set_property( GLOBAL APPEND PROPERTY LLVM_LIBS ${name} ) + # The gtest libraries should not be installed or exported as a target + if ("${name}" STREQUAL gtest OR "${name}" STREQUAL gtest_main) + set(_is_gtest TRUE) + else() + set(_is_gtest FALSE) + set_property( GLOBAL APPEND PROPERTY LLVM_LIBS ${name} ) + endif() if( EXCLUDE_FROM_ALL ) set_target_properties( ${name} PROPERTIES EXCLUDE_FROM_ALL ON) - else() + elseif(NOT _is_gtest) if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR ${name} STREQUAL "LTO") if(ARG_SHARED OR BUILD_SHARED_LIBS) if(WIN32 OR CYGWIN) @@ -486,11 +563,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} ) @@ -592,6 +676,13 @@ macro(add_llvm_target target_name) set( CURRENT_LLVM_TARGET LLVM${target_name} ) endmacro(add_llvm_target) +function(canonicalize_tool_name name output) + string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" nameStrip ${name}) + string(REPLACE "-" "_" nameUNDERSCORE ${nameStrip}) + string(TOUPPER ${nameUNDERSCORE} nameUPPER) + set(${output} "${nameUPPER}" PARENT_SCOPE) +endfunction(canonicalize_tool_name) + # Add external project that may want to be built as part of llvm such as Clang, # lld, and Polly. This adds two options. One for the source directory of the # project, which defaults to ${CMAKE_CURRENT_SOURCE_DIR}/${name}. Another to @@ -602,38 +693,72 @@ macro(add_llvm_external_project name) if("${add_llvm_external_dir}" STREQUAL "") set(add_llvm_external_dir ${name}) endif() - list(APPEND LLVM_IMPLICIT_PROJECT_IGNORE "${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir}") - string(REPLACE "-" "_" nameUNDERSCORE ${name}) - string(TOUPPER ${nameUNDERSCORE} nameUPPER) - set(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir}" - CACHE PATH "Path to ${name} source directory") - if (NOT ${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR} STREQUAL "" - AND EXISTS ${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR}/CMakeLists.txt) - option(LLVM_EXTERNAL_${nameUPPER}_BUILD - "Whether to build ${name} as part of LLVM" ON) - if (LLVM_EXTERNAL_${nameUPPER}_BUILD) - add_subdirectory(${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR} ${add_llvm_external_dir}) + canonicalize_tool_name(${name} nameUPPER) + if(NOT DEFINED LLVM_TOOL_${nameUPPER}_BUILD) + option(LLVM_TOOL_${nameUPPER}_BUILD + "Whether to build ${name} as part of LLVM" On) + endif() + if (LLVM_TOOL_${nameUPPER}_BUILD) + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir}/CMakeLists.txt) + add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir} ${add_llvm_external_dir}) + set(LLVM_TOOL_${nameUPPER}_BUILD Off) + elseif(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR) + set(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR + "${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR}" + CACHE PATH "Path to ${name} source directory") + mark_as_advanced(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR) + if(IS_DIRECTORY "${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR} ${add_llvm_external_dir}") # XXX EMSCRIPTEN + add_subdirectory(${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR} ${add_llvm_external_dir}) + else() + message(" (ignoring non-existing external_project |${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR} ${add_llvm_external_dir}|)") + endif() + set(LLVM_TOOL_${nameUPPER}_BUILD Off) endif() endif() endmacro(add_llvm_external_project) macro(add_llvm_tool_subdirectory name) - list(APPEND LLVM_IMPLICIT_PROJECT_IGNORE "${CMAKE_CURRENT_SOURCE_DIR}/${name}") - add_subdirectory(${name}) + add_llvm_external_project(${name}) endmacro(add_llvm_tool_subdirectory) -macro(ignore_llvm_tool_subdirectory name) - list(APPEND LLVM_IMPLICIT_PROJECT_IGNORE "${CMAKE_CURRENT_SOURCE_DIR}/${name}") -endmacro(ignore_llvm_tool_subdirectory) +function(get_project_name_from_src_var var output) + string(REGEX MATCH "LLVM_EXTERNAL_(.*)_SOURCE_DIR" + MACHED_TOOL "${var}") + if(MACHED_TOOL) + set(${output} ${CMAKE_MATCH_1} PARENT_SCOPE) + else() + set(${output} PARENT_SCOPE) + endif() +endfunction() + +function(create_llvm_tool_options) + file(GLOB sub-dirs "${CMAKE_CURRENT_SOURCE_DIR}/*") + foreach(dir ${sub-dirs}) + if(IS_DIRECTORY "${dir}" AND EXISTS "${dir}/CMakeLists.txt") + canonicalize_tool_name(${dir} name) + option(LLVM_TOOL_${name}_BUILD + "Whether to build ${name} as part of LLVM" On) + mark_as_advanced(LLVM_TOOL_${name}_BUILD) + endif() + endforeach() + get_cmake_property(variableNames VARIABLES) + foreach (variableName ${variableNames}) + get_project_name_from_src_var(${variableName} projectName) + if(projectName) + option(LLVM_TOOL_${projectName}_BUILD + "Whether to build ${name} as part of LLVM" On) + mark_as_advanced(LLVM_TOOL_${name}_BUILD) + endif() + endforeach() +endfunction(create_llvm_tool_options) -function(add_llvm_implicit_external_projects) +function(add_llvm_implicit_projects) set(list_of_implicit_subdirs "") file(GLOB sub-dirs "${CMAKE_CURRENT_SOURCE_DIR}/*") foreach(dir ${sub-dirs}) - if(IS_DIRECTORY "${dir}") - list(FIND LLVM_IMPLICIT_PROJECT_IGNORE "${dir}" tool_subdir_ignore) - if( tool_subdir_ignore EQUAL -1 - AND EXISTS "${dir}/CMakeLists.txt") + if(IS_DIRECTORY "${dir}" AND EXISTS "${dir}/CMakeLists.txt") + canonicalize_tool_name(${dir} name) + if (LLVM_TOOL_${name}_BUILD) get_filename_component(fn "${dir}" NAME) list(APPEND list_of_implicit_subdirs "${fn}") endif() @@ -643,7 +768,7 @@ function(add_llvm_implicit_external_projects) foreach(external_proj ${list_of_implicit_subdirs}) add_llvm_external_project("${external_proj}") endforeach() -endfunction(add_llvm_implicit_external_projects) +endfunction(add_llvm_implicit_projects) # Generic support for adding a unittest. function(add_unittest test_suite test_name) @@ -694,7 +819,7 @@ function(llvm_add_go_executable binary pkgpath) endforeach(d) set(ldflags "${CMAKE_EXE_LINKER_FLAGS}") add_custom_command(OUTPUT ${binpath} - COMMAND ${CMAKE_BINARY_DIR}/bin/llvm-go "cc=${cc}" "cxx=${cxx}" "cppflags=${cppflags}" "ldflags=${ldflags}" + COMMAND ${CMAKE_BINARY_DIR}/bin/llvm-go "go=${GO_EXECUTABLE}" "cc=${cc}" "cxx=${cxx}" "cppflags=${cppflags}" "ldflags=${ldflags}" ${ARG_GOFLAGS} build -o ${binpath} ${pkgpath} DEPENDS llvm-config ${CMAKE_BINARY_DIR}/bin/llvm-go${CMAKE_EXECUTABLE_SUFFIX} ${llvmlibs} ${ARG_DEPENDS} @@ -765,7 +890,7 @@ endfunction() # A raw function to create a lit target. This is used to implement the testuite # management functions. function(add_lit_target target comment) - parse_arguments(ARG "PARAMS;DEPENDS;ARGS" "" ${ARGN}) + cmake_parse_arguments(ARG "" "" "PARAMS;DEPENDS;ARGS" ${ARGN}) set(LIT_ARGS "${ARG_ARGS} ${LLVM_LIT_ARGS}") separate_arguments(LIT_ARGS) if (NOT CMAKE_CFG_INTDIR STREQUAL ".") @@ -780,9 +905,9 @@ function(add_lit_target target comment) foreach(param ${ARG_PARAMS}) list(APPEND LIT_COMMAND --param ${param}) endforeach() - if (ARG_DEFAULT_ARGS) + if (ARG_UNPARSED_ARGUMENTS) add_custom_target(${target} - COMMAND ${LIT_COMMAND} ${ARG_DEFAULT_ARGS} + COMMAND ${LIT_COMMAND} ${ARG_UNPARSED_ARGUMENTS} COMMENT "${comment}" ${cmake_3_2_USES_TERMINAL} ) @@ -801,12 +926,12 @@ endfunction() # A function to add a set of lit test suites to be driven through 'check-*' targets. function(add_lit_testsuite target comment) - parse_arguments(ARG "PARAMS;DEPENDS;ARGS" "" ${ARGN}) + cmake_parse_arguments(ARG "" "" "PARAMS;DEPENDS;ARGS" ${ARGN}) # EXCLUDE_FROM_ALL excludes the test ${target} out of check-all. if(NOT EXCLUDE_FROM_ALL) # Register the testsuites, params and depends for the global check rule. - set_property(GLOBAL APPEND PROPERTY LLVM_LIT_TESTSUITES ${ARG_DEFAULT_ARGS}) + set_property(GLOBAL APPEND PROPERTY LLVM_LIT_TESTSUITES ${ARG_UNPARSED_ARGUMENTS}) set_property(GLOBAL APPEND PROPERTY LLVM_LIT_PARAMS ${ARG_PARAMS}) set_property(GLOBAL APPEND PROPERTY LLVM_LIT_DEPENDS ${ARG_DEPENDS}) set_property(GLOBAL APPEND PROPERTY LLVM_LIT_EXTRA_ARGS ${ARG_ARGS}) @@ -814,7 +939,7 @@ function(add_lit_testsuite target comment) # Produce a specific suffixed check rule. add_lit_target(${target} ${comment} - ${ARG_DEFAULT_ARGS} + ${ARG_UNPARSED_ARGUMENTS} PARAMS ${ARG_PARAMS} DEPENDS ${ARG_DEPENDS} ARGS ${ARG_ARGS} @@ -823,7 +948,7 @@ endfunction() function(add_lit_testsuites project directory) if (NOT CMAKE_CONFIGURATION_TYPES) - parse_arguments(ARG "PARAMS;DEPENDS;ARGS" "" ${ARGN}) + cmake_parse_arguments(ARG "" "" "PARAMS;DEPENDS;ARGS" ${ARGN}) file(GLOB_RECURSE litCfg ${directory}/lit*.cfg) set(lit_suites) foreach(f ${litCfg}) diff --git a/cmake/modules/AddOCaml.cmake b/cmake/modules/AddOCaml.cmake index c58ac9cb734..8b33332d07b 100644 --- a/cmake/modules/AddOCaml.cmake +++ b/cmake/modules/AddOCaml.cmake @@ -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) diff --git a/cmake/modules/CheckAtomic.cmake b/cmake/modules/CheckAtomic.cmake index a03788ec9f9..551de6ade84 100644 --- a/cmake/modules/CheckAtomic.cmake +++ b/cmake/modules/CheckAtomic.cmake @@ -2,15 +2,45 @@ INCLUDE(CheckCXXSourceCompiles) -check_function_exists(__atomic_fetch_add_4 HAVE___ATOMIC_FETCH_ADD_4) -if( NOT HAVE___ATOMIC_FETCH_ADD_4 ) - check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC) - set(HAVE_LIBATOMIC False) - if( HAVE_LIBATOMIC ) - list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") +# Sometimes linking against libatomic is required for atomic ops, if +# the platform doesn't support lock-free atomics. + +function(check_working_cxx_atomics varname) + set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + set(CMAKE_REQUIRED_FLAGS "-std=c++11") + CHECK_CXX_SOURCE_COMPILES(" +#include +std::atomic x; +int main() { + return x; +} +" ${varname}) + set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) +endfunction(check_working_cxx_atomics) + +# This isn't necessary on MSVC, so avoid command-line switch annoyance +# by only running on GCC-like hosts. +if (LLVM_COMPILER_IS_GCC_COMPATIBLE) + # First check if atomics work without the library. + check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB) + # If not, check if the library exists, and atomics work with it. + if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB) + check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC) + if( HAVE_LIBATOMIC ) + list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") + check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB) + if (NOT HAVE_CXX_ATOMICS_WITH_LIB) + message(FATAL_ERROR "Host compiler must support std::atomic!") + endif() + else() + message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.") + endif() endif() endif() +## TODO: This define is only used for the legacy atomic operations in +## llvm's Atomic.h, which should be replaced. Other code simply +## assumes C++11 works. CHECK_CXX_SOURCE_COMPILES(" #ifdef _MSC_VER #include /* Workaround for PR19898. */ diff --git a/cmake/modules/HandleLLVMOptions.cmake b/cmake/modules/HandleLLVMOptions.cmake index 27147dcfd29..bee77c14b5b 100644 --- a/cmake/modules/HandleLLVMOptions.cmake +++ b/cmake/modules/HandleLLVMOptions.cmake @@ -88,6 +88,9 @@ elseif( uppercase_LLVM_ABI_BREAKING_CHECKS STREQUAL "FORCE_ON" ) set( LLVM_ENABLE_ABI_BREAKING_CHECKS 1 ) elseif( uppercase_LLVM_ABI_BREAKING_CHECKS STREQUAL "FORCE_OFF" ) # We don't need to do anything special to turn off ABI breaking checks. +elseif( NOT DEFINED LLVM_ABI_BREAKING_CHECKS ) + # Treat LLVM_ABI_BREAKING_CHECKS like "FORCE_OFF" when it has not been + # defined. else() message(FATAL_ERROR "Unknown value for LLVM_ABI_BREAKING_CHECKS: \"${LLVM_ABI_BREAKING_CHECKS}\"!") endif() @@ -128,7 +131,7 @@ endif() # Pass -Wl,-z,defs. This makes sure all symbols are defined. Otherwise a DSO # build might work on ELF but fail on MachO/COFF. -if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR WIN32 OR +if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR WIN32 OR CYGWIN OR ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") AND NOT LLVM_USE_SANITIZER) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,defs") @@ -163,6 +166,7 @@ function(add_flag_or_print_warning flag name) message(STATUS "Building with ${flag}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}" PARENT_SCOPE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}" PARENT_SCOPE) + set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${flag}" PARENT_SCOPE) else() message(WARNING "${flag} is not supported.") endif() @@ -304,7 +308,17 @@ if( MSVC ) -wd4611 # Suppress 'interaction between '_setjmp' and C++ object destruction is non-portable' -wd4805 # Suppress 'unsafe mix of type and type in operation' -wd4204 # Suppress 'nonstandard extension used : non-constant aggregate initializer' - + -wd4577 # Suppress 'noexcept used with no exception handling mode specified; termination on exception is not guaranteed' + -wd4091 # Suppress 'typedef: ignored on left of '' when no variable is declared' + + # Ideally, we'd like this warning to be enabled, but MSVC 2013 doesn't + # support the 'aligned' attribute in the way that clang sources requires (for + # any code that uses the LLVM_ALIGNAS macro), so this is must be disabled to + # avoid unwanted alignment warnings. + # When we switch to requiring a version of MSVC that supports the 'alignas' + # specifier (MSVC 2015?) this warning can be re-enabled. + -wd4324 # Suppress 'structure was padded due to __declspec(align())' + # Promoted warnings. -w14062 # Promote 'enumerator in switch of enum is not handled' to level 1 warning. @@ -334,6 +348,11 @@ if( MSVC ) append("${flag}" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endforeach(flag) + # Disable sized deallocation if the flag is supported. MSVC fails to compile + # the operator new overload in User otherwise. + check_c_compiler_flag("/WX /Zc:sizedDealloc-" SUPPORTS_SIZED_DEALLOC) + append_if(SUPPORTS_SIZED_DEALLOC "/Zc:sizedDealloc-" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + elseif( LLVM_COMPILER_IS_GCC_COMPATIBLE ) if (LLVM_ENABLE_WARNINGS) append("-Wall -W -Wno-unused-parameter -Wwrite-strings" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) @@ -451,7 +470,7 @@ if(LLVM_USE_SANITIZER) endif() elseif (LLVM_USE_SANITIZER STREQUAL "Undefined") append_common_sanitizer_flags() - append("-fsanitize=undefined -fno-sanitize=vptr,function -fno-sanitize-recover" + append("-fsanitize=undefined -fno-sanitize=vptr,function -fno-sanitize-recover=all" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) elseif (LLVM_USE_SANITIZER STREQUAL "Thread") append_common_sanitizer_flags() @@ -459,7 +478,7 @@ if(LLVM_USE_SANITIZER) elseif (LLVM_USE_SANITIZER STREQUAL "Address;Undefined" OR LLVM_USE_SANITIZER STREQUAL "Undefined;Address") append_common_sanitizer_flags() - append("-fsanitize=address,undefined -fno-sanitize=vptr,function -fno-sanitize-recover" + append("-fsanitize=address,undefined -fno-sanitize=vptr,function -fno-sanitize-recover=all" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) else() message(WARNING "Unsupported value of LLVM_USE_SANITIZER: ${LLVM_USE_SANITIZER}") @@ -468,7 +487,7 @@ if(LLVM_USE_SANITIZER) message(WARNING "LLVM_USE_SANITIZER is not supported on this platform.") endif() if (LLVM_USE_SANITIZE_COVERAGE) - append("-fsanitize-coverage=4 -mllvm -sanitizer-coverage-8bit-counters=1" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + append("-fsanitize-coverage=edge,indirect-calls,8bit-counters,trace-cmp" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() endif() diff --git a/cmake/modules/LLVM-Config.cmake b/cmake/modules/LLVM-Config.cmake index bc0527f1db4..22ac7145191 100644 --- a/cmake/modules/LLVM-Config.cmake +++ b/cmake/modules/LLVM-Config.cmake @@ -132,6 +132,41 @@ function(llvm_map_components_to_libnames out_libs) # already processed elseif( c STREQUAL "all" ) list(APPEND expanded_components ${LLVM_AVAILABLE_LIBS}) + elseif( c STREQUAL "AllTargetsAsmPrinters" ) + # Link all the asm printers from all the targets + foreach(t ${LLVM_TARGETS_TO_BUILD}) + if( TARGET LLVM${t}AsmPrinter ) + list(APPEND expanded_components "LLVM${t}AsmPrinter") + endif() + endforeach(t) + elseif( c STREQUAL "AllTargetsAsmParsers" ) + # Link all the asm parsers from all the targets + foreach(t ${LLVM_TARGETS_TO_BUILD}) + if( TARGET LLVM${t}AsmParser ) + list(APPEND expanded_components "LLVM${t}AsmParser") + endif() + endforeach(t) + elseif( c STREQUAL "AllTargetsDescs" ) + # Link all the descs from all the targets + foreach(t ${LLVM_TARGETS_TO_BUILD}) + if( TARGET LLVM${t}Desc ) + list(APPEND expanded_components "LLVM${t}Desc") + endif() + endforeach(t) + elseif( c STREQUAL "AllTargetsDisassemblers" ) + # Link all the disassemblers from all the targets + foreach(t ${LLVM_TARGETS_TO_BUILD}) + if( TARGET LLVM${t}Disassembler ) + list(APPEND expanded_components "LLVM${t}Disassembler") + endif() + endforeach(t) + elseif( c STREQUAL "AllTargetsInfos" ) + # Link all the infos from all the targets + foreach(t ${LLVM_TARGETS_TO_BUILD}) + if( TARGET LLVM${t}Info ) + list(APPEND expanded_components "LLVM${t}Info") + endif() + endforeach(t) else( NOT idx LESS 0 ) # Canonize the component name: string(TOUPPER "${c}" capitalized) diff --git a/cmake/modules/LLVMParseArguments.cmake b/cmake/modules/LLVMParseArguments.cmake deleted file mode 100644 index ce19be114b3..00000000000 --- a/cmake/modules/LLVMParseArguments.cmake +++ /dev/null @@ -1,80 +0,0 @@ -# Copied from http://www.itk.org/Wiki/CMakeMacroParseArguments under -# http://creativecommons.org/licenses/by/2.5/. -# -# The PARSE_ARGUMENTS macro will take the arguments of another macro and define -# several variables. The first argument to PARSE_ARGUMENTS is a prefix to put on -# all variables it creates. The second argument is a list of names, and the -# third argument is a list of options. Both of these lists should be quoted. The -# rest of PARSE_ARGUMENTS are arguments from another macro to be parsed. -# -# PARSE_ARGUMENTS(prefix arg_names options arg1 arg2...) -# -# For each item in options, PARSE_ARGUMENTS will create a variable with that -# name, prefixed with prefix_. So, for example, if prefix is MY_MACRO and -# options is OPTION1;OPTION2, then PARSE_ARGUMENTS will create the variables -# MY_MACRO_OPTION1 and MY_MACRO_OPTION2. These variables will be set to true if -# the option exists in the command line or false otherwise. -# -#For each item in arg_names, PARSE_ARGUMENTS will create a variable with that -#name, prefixed with prefix_. Each variable will be filled with the arguments -#that occur after the given arg_name is encountered up to the next arg_name or -#the end of the arguments. All options are removed from these -#lists. PARSE_ARGUMENTS also creates a prefix_DEFAULT_ARGS variable containing -#the list of all arguments up to the first arg_name encountered. -# -#Here is a simple, albeit impractical, example of using PARSE_ARGUMENTS that -#demonstrates its behavior. -# -# SET(arguments -# hello OPTION3 world -# LIST3 foo bar -# OPTION2 -# LIST1 fuz baz -# ) -# -# PARSE_ARGUMENTS(ARG "LIST1;LIST2;LIST3" "OPTION1;OPTION2;OPTION3" ${arguments}) -# -# PARSE_ARGUMENTS creates 7 variables and sets them as follows: -# ARG_DEFAULT_ARGS: hello;world -# ARG_LIST1: fuz;baz -# ARG_LIST2: -# ARG_LIST3: foo;bar -# ARG_OPTION1: FALSE -# ARG_OPTION2: TRUE -# ARG_OPTION3: TRUE -# -# If you don't have any options, use an empty string in its place. -# PARSE_ARGUMENTS(ARG "LIST1;LIST2;LIST3" "" ${arguments}) -# Likewise if you have no lists. -# PARSE_ARGUMENTS(ARG "" "OPTION1;OPTION2;OPTION3" ${arguments}) - -MACRO(PARSE_ARGUMENTS prefix arg_names option_names) - SET(DEFAULT_ARGS) - FOREACH(arg_name ${arg_names}) - SET(${prefix}_${arg_name}) - ENDFOREACH(arg_name) - FOREACH(option ${option_names}) - SET(${prefix}_${option} FALSE) - ENDFOREACH(option) - - SET(current_arg_name DEFAULT_ARGS) - SET(current_arg_list) - FOREACH(arg ${ARGN}) - SET(larg_names ${arg_names}) - LIST(FIND larg_names "${arg}" is_arg_name) - IF (is_arg_name GREATER -1) - SET(${prefix}_${current_arg_name} ${current_arg_list}) - SET(current_arg_name ${arg}) - SET(current_arg_list) - ELSE (is_arg_name GREATER -1) - SET(loption_names ${option_names}) - LIST(FIND loption_names "${arg}" is_option) - IF (is_option GREATER -1) - SET(${prefix}_${arg} TRUE) - ELSE (is_option GREATER -1) - SET(current_arg_list ${current_arg_list} ${arg}) - ENDIF (is_option GREATER -1) - ENDIF (is_arg_name GREATER -1) - ENDFOREACH(arg) - SET(${prefix}_${current_arg_name} ${current_arg_list}) -ENDMACRO(PARSE_ARGUMENTS) diff --git a/cmake/modules/Makefile b/cmake/modules/Makefile index 97ee7d3df4b..f644c45dcd0 100644 --- a/cmake/modules/Makefile +++ b/cmake/modules/Makefile @@ -47,6 +47,12 @@ ifeq ($(LLVM_LIBS_TO_EXPORT),Error) $(error llvm-config --libs failed) endif +# Strip out gtest and gtest_main from LLVM_LIBS_TO_EXPORT, these are not +# installed and won't be available from the install tree. +# FIXME: If we used llvm-config from the install tree this wouldn't be +# necessary. +LLVM_LIBS_TO_EXPORT := $(filter-out gtest gtest_main,$(LLVM_LIBS_TO_EXPORT)) + ifndef LLVM_LIBS_TO_EXPORT $(error LLVM_LIBS_TO_EXPORT cannot be empty) endif @@ -54,11 +60,27 @@ endif OBJMODS := LLVMConfig.cmake LLVMConfigVersion.cmake LLVMExports.cmake +LLVM_CONFIG_CODE := \ +\# Compute the CMake directory from the LLVMConfig.cmake file location.\n\ +get_filename_component(_LLVM_CMAKE_DIR "$${CMAKE_CURRENT_LIST_FILE}" PATH)\n\ +\# Compute the installation prefix from the LLVMConfig.cmake file location.\n\ +get_filename_component(LLVM_INSTALL_PREFIX "$${CMAKE_CURRENT_LIST_FILE}" PATH)\n + +# Compute number of levels (typically 3 - ``share/llvm/cmake/``) to PROJ_prefix +# from PROJ_cmake, then emit the appropriate number of calls to +# get_filename_components(). Note this assumes there are no spaces in the +# cmake_path_suffix variable. +cmake_path_suffix := $(subst $(PROJ_prefix),,$(subst $(DESTDIR),,$(PROJ_cmake))) +cmake_path_dirs := $(subst /, ,$(cmake_path_suffix)) +LLVM_CONFIG_CODE += $(foreach __not_used,$(cmake_path_dirs),get_filename_component(LLVM_INSTALL_PREFIX "$${LLVM_INSTALL_PREFIX}" PATH)\n) + +LLVM_CONFIG_CODE += set(_LLVM_LIBRARY_DIR "$${LLVM_INSTALL_PREFIX}\/lib") + $(PROJ_OBJ_DIR)/LLVMConfig.cmake: LLVMConfig.cmake.in Makefile $(LLVMBuildCMakeFrag) $(Echo) 'Generating LLVM CMake package config file' $(Verb) ( \ cat $< | sed \ - -e 's/@LLVM_CONFIG_CODE@/set(LLVM_INSTALL_PREFIX "'"$(subst /,\/,$(PROJ_prefix))"'")/' \ + -e 's/@LLVM_CONFIG_CODE@/$(LLVM_CONFIG_CODE)/' \ -e 's/@LLVM_VERSION_MAJOR@/'"$(LLVM_VERSION_MAJOR)"'/' \ -e 's/@LLVM_VERSION_MINOR@/'"$(LLVM_VERSION_MINOR)"'/' \ -e 's/@LLVM_VERSION_PATCH@/'"$(LLVM_VERSION_PATCH)"'/' \ @@ -81,17 +103,20 @@ $(PROJ_OBJ_DIR)/LLVMConfig.cmake: LLVMConfig.cmake.in Makefile $(LLVMBuildCMakeF -e 's/@LLVM_ON_UNIX@/'"$(LLVM_ON_UNIX)"'/' \ -e 's/@LLVM_ON_WIN32@/'"$(LLVM_ON_WIN32)"'/' \ -e 's/@LLVM_LIBDIR_SUFFIX@//' \ - -e 's/@LLVM_CONFIG_INCLUDE_DIRS@/'"$(subst /,\/,$(PROJ_includedir))"'/' \ - -e 's/@LLVM_CONFIG_LIBRARY_DIRS@/'"$(subst /,\/,$(PROJ_libdir))"'/' \ - -e 's/@LLVM_CONFIG_CMAKE_DIR@/'"$(subst /,\/,$(PROJ_cmake))"'/' \ - -e 's/@LLVM_CONFIG_TOOLS_BINARY_DIR@/'"$(subst /,\/,$(PROJ_bindir))"'/' \ + -e 's#@LLVM_CONFIG_INCLUDE_DIRS@#$${LLVM_INSTALL_PREFIX}/include#' \ + -e 's#@LLVM_CONFIG_LIBRARY_DIRS@#$${_LLVM_LIBRARY_DIR}#' \ + -e 's#@LLVM_CONFIG_CMAKE_DIR@#$${_LLVM_CMAKE_DIR}#' \ + -e 's#@LLVM_CONFIG_TOOLS_BINARY_DIR@#$${LLVM_INSTALL_PREFIX}/bin#' \ -e 's/@LLVM_CONFIG_EXPORTS_FILE@/$${LLVM_CMAKE_DIR}\/LLVMExports.cmake/' \ -e 's/@all_llvm_lib_deps@//' \ && \ - grep '^set_property.*LLVMBUILD_LIB_DEPS_' "$(LLVMBuildCMakeFrag)" \ + ( grep '^set_property.*LLVMBUILD_LIB_DEPS_' "$(LLVMBuildCMakeFrag)" | \ + grep -v LLVMBUILD_LIB_DEPS_gtest ) && \ + echo 'unset(_LLVM_CMAKE_DIR)' && \ + echo 'unset(_LLVM_LIBRARY_DIR)' \ ) > $@ -$(PROJ_OBJ_DIR)/LLVMConfigVersion.cmake: LLVMConfigVersion.cmake.in +$(PROJ_OBJ_DIR)/LLVMConfigVersion.cmake: LLVMConfigVersion.cmake.in Makefile $(Echo) 'Generating LLVM CMake package version file' $(Verb) cat $< | sed \ -e 's/@PACKAGE_VERSION@/'"$(LLVMVersion)"'/' \ @@ -100,13 +125,13 @@ $(PROJ_OBJ_DIR)/LLVMConfigVersion.cmake: LLVMConfigVersion.cmake.in -e 's/@LLVM_VERSION_PATCH@/'"$(LLVM_VERSION_PATCH)"'/' \ > $@ -$(PROJ_OBJ_DIR)/LLVMExports.cmake: $(LLVMBuildCMakeExportsFrag) +$(PROJ_OBJ_DIR)/LLVMExports.cmake: $(LLVMBuildCMakeExportsFrag) Makefile $(Echo) 'Generating LLVM CMake target exports file' $(Verb) ( \ echo '# LLVM CMake target exports. Do not include directly.' && \ for lib in $(LLVM_LIBS_TO_EXPORT); do \ echo 'add_library('"$$lib"' STATIC IMPORTED)' && \ - echo 'set_property(TARGET '"$$lib"' PROPERTY IMPORTED_LOCATION "'"$(PROJ_libdir)/lib$$lib.a"'")' ; \ + echo 'set_property(TARGET '"$$lib"' PROPERTY IMPORTED_LOCATION "$${_LLVM_LIBRARY_DIR}/'lib$$lib.a'")' ; \ done && \ cat "$(LLVMBuildCMakeExportsFrag)" && \ echo 'set_property(TARGET LLVMSupport APPEND PROPERTY IMPORTED_LINK_INTERFACE_LIBRARIES '"$(subst -l,,$(LIBS))"')' \ diff --git a/cmake/modules/TableGen.cmake b/cmake/modules/TableGen.cmake index bb0d844605f..85d720e91fd 100644 --- a/cmake/modules/TableGen.cmake +++ b/cmake/modules/TableGen.cmake @@ -32,7 +32,7 @@ function(tablegen project ofn) # The file in LLVM_TARGET_DEFINITIONS may be not in the current # directory and local_tds may not contain it, so we must # explicitly list it here: - DEPENDS ${${project}_TABLEGEN_EXE} ${local_tds} ${global_tds} + DEPENDS ${${project}_TABLEGEN_TARGET} ${local_tds} ${global_tds} ${LLVM_TARGET_DEFINITIONS_ABSOLUTE} COMMENT "Building ${ofn}..." ) @@ -90,10 +90,15 @@ macro(add_tablegen target project) # Effective tblgen executable to be used: set(${project}_TABLEGEN_EXE ${${project}_TABLEGEN} PARENT_SCOPE) + set(${project}_TABLEGEN_TARGET ${${project}_TABLEGEN} PARENT_SCOPE) if(LLVM_USE_HOST_TOOLS) if( ${${project}_TABLEGEN} STREQUAL "${target}" ) - set(${project}_TABLEGEN_EXE "${LLVM_NATIVE_BUILD}/bin/${target}") + if (NOT CMAKE_CONFIGURATION_TYPES) + set(${project}_TABLEGEN_EXE "${LLVM_NATIVE_BUILD}/bin/${target}") + else() + set(${project}_TABLEGEN_EXE "${LLVM_NATIVE_BUILD}/Release/bin/${target}") + endif() set(${project}_TABLEGEN_EXE ${${project}_TABLEGEN_EXE} PARENT_SCOPE) add_custom_command(OUTPUT ${${project}_TABLEGEN_EXE} @@ -101,8 +106,8 @@ macro(add_tablegen target project) DEPENDS CONFIGURE_LLVM_NATIVE ${target} WORKING_DIRECTORY ${LLVM_NATIVE_BUILD} COMMENT "Building native TableGen...") - add_custom_target(${project}NativeTableGen DEPENDS ${${project}_TABLEGEN_EXE}) - add_dependencies(${project}NativeTableGen CONFIGURE_LLVM_NATIVE) + add_custom_target(${project}-tablegen-host DEPENDS ${${project}_TABLEGEN_EXE}) + set(${project}_TABLEGEN_TARGET ${project}-tablegen-host PARENT_SCOPE) endif() endif() diff --git a/codereview.settings b/codereview.settings deleted file mode 100644 index 1c4f6bdeec6..00000000000 --- a/codereview.settings +++ /dev/null @@ -1,8 +0,0 @@ -# This file is used by gcl to get repository specific information. -CODE_REVIEW_SERVER: codereview.chromium.org -CC_LIST: native-client-reviews@googlegroups.com -VIEW_VC: https://chromium.googlesource.com/native_client/pnacl-llvm/+/ -STATUS: http://nativeclient-status.appspot.com/status -TRY_ON_UPLOAD: False -TRYSERVER_PROJECT: nacl -TRYSERVER_SVN_URL: svn://svn.chromium.org/chrome-try/try-nacl diff --git a/configure b/configure index 20c36aa1b2d..6b6d0cdd3e4 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.60 for LLVM 3.7.0svn. +# Generated by GNU Autoconf 2.60 for LLVM 3.8.0svn. # # Report bugs to . # @@ -561,8 +561,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='LLVM' PACKAGE_TARNAME='llvm' -PACKAGE_VERSION='3.7.0svn' -PACKAGE_STRING='LLVM 3.7.0svn' +PACKAGE_VERSION='3.8.0svn' +PACKAGE_STRING='LLVM 3.8.0svn' PACKAGE_BUGREPORT='http://llvm.org/bugs/' ac_unique_file="lib/IR/Module.cpp" @@ -737,7 +737,6 @@ LLVM_ENUM_TARGETS LLVM_ENUM_ASM_PRINTERS LLVM_ENUM_ASM_PARSERS LLVM_ENUM_DISASSEMBLERS -SUBZERO_ENUM_TARGETS OPTIMIZE_OPTION EXTRA_OPTIONS EXTRA_LD_OPTIONS @@ -1334,7 +1333,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures LLVM 3.7.0svn to adapt to many kinds of systems. +\`configure' configures LLVM 3.8.0svn to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1400,7 +1399,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of LLVM 3.7.0svn:";; + short | recursive ) echo "Configuration of LLVM 3.8.0svn:";; esac cat <<\_ACEOF @@ -1463,14 +1462,11 @@ 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, js, - and cpp (default=all) + hexagon, xcore, msp430, nvptx, systemz, r600, bpf, + wasm, js, and cpp (default=all) --enable-experimental-targets Build experimental host targets: disable or target1,target2,... (default=disable) - --enable-subzero-targets - Build specific subzero targets: - target1,target2,...(default=none) --enable-bindings Build specific language bindings: all,auto,none,{binding-name} (default=auto) --enable-terminfo Query the terminfo database if available (default is @@ -1499,6 +1495,8 @@ Optional Packages: search for headers --with-gcc-toolchain Directory where gcc is installed. --with-default-sysroot Add --sysroot= to all compiler invocations. + --with-clang-default-openmp-runtime + The default OpenMP runtime for Clang. --with-binutils-include Specify path to binutils/include/ containing plugin-api.h file for gold plugin. --with-bug-report-url Specify the URL where bug reports should be @@ -1585,7 +1583,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -LLVM configure 3.7.0svn +LLVM configure 3.8.0svn generated by GNU Autoconf 2.60 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1601,7 +1599,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by LLVM $as_me 3.7.0svn, which was +It was created by LLVM $as_me 3.8.0svn, which was generated by GNU Autoconf 2.60. Invocation command line was $ $0 $@ @@ -1956,7 +1954,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu LLVM_VERSION_MAJOR=3 -LLVM_VERSION_MINOR=7 +LLVM_VERSION_MINOR=8 LLVM_VERSION_PATCH=0 LLVM_VERSION_SUFFIX=svn @@ -2034,6 +2032,12 @@ echo "$as_me: error: Already configured in ${srcdir}" >&2;} fi fi +if test ${srcdir} == "." ; then + { { echo "$as_me:$LINENO: error: In-source builds are not allowed. Please configure from a separate build directory!" >&5 +echo "$as_me: error: In-source builds are not allowed. Please configure from a separate build directory!" >&2;} + { (exit 1); exit 1; }; } +fi + : ${CFLAGS=} : ${CXXFLAGS=} @@ -3609,8 +3613,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } - { { echo "$as_me:$LINENO: error: Selected compiler could not find or parse C++ standard library headers. Rerun with CC=c-compiler CXX=c++-compiler ./configure ..." >&5 -echo "$as_me: error: Selected compiler could not find or parse C++ standard library headers. Rerun with CC=c-compiler CXX=c++-compiler ./configure ..." >&2;} + { { echo "$as_me:$LINENO: error: Selected compiler could not find or parse C++ standard library headers. Rerun with CC=c-compiler CXX=c++-compiler LLVM_SRC_DIR/configure ..." >&5 +echo "$as_me: error: Selected compiler could not find or parse C++ standard library headers. Rerun with CC=c-compiler CXX=c++-compiler LLVM_SRC_DIR/configure ..." >&2;} { (exit 1); exit 1; }; } fi @@ -4056,11 +4060,6 @@ else llvm_cv_no_link_all_option="-Wl,--no-whole-archive" llvm_cv_os_type="Freestanding" llvm_cv_platform_type="Unix" ;; - *-*-nacl*) - llvm_cv_link_all_option="-Wl,--whole-archive" - llvm_cv_no_link_all_option="-Wl,--no-whole-archive" - llvm_cv_os_type="NativeClient" - llvm_cv_platform_type="Unix" ;; *) llvm_cv_link_all_option="" llvm_cv_no_link_all_option="" @@ -4193,6 +4192,7 @@ else hexagon-*) llvm_cv_target_arch="Hexagon" ;; nvptx-*) llvm_cv_target_arch="NVPTX" ;; s390x-*) llvm_cv_target_arch="SystemZ" ;; + wasm*-*) llvm_cv_target_arch="WebAssembly" ;; *) llvm_cv_target_arch="Unknown" ;; esac fi @@ -4229,6 +4229,7 @@ case $host in msp430-*) host_arch="MSP430" ;; hexagon-*) host_arch="Hexagon" ;; s390x-*) host_arch="SystemZ" ;; + wasm*-*) host_arch="WebAssembly" ;; *) host_arch="Unknown" ;; esac @@ -5155,6 +5156,8 @@ else NVPTX) TARGET_HAS_JIT=0 ;; SystemZ) TARGET_HAS_JIT=1 + ;; + WebAssembly) TARGET_HAS_JIT=0 ;; *) TARGET_HAS_JIT=0 ;; @@ -5614,7 +5617,7 @@ _ACEOF fi -ALL_TARGETS="X86 Sparc PowerPC ARM AArch64 Mips XCore MSP430 CppBackend JSBackend NVPTX Hexagon SystemZ R600" +ALL_TARGETS="X86 Sparc PowerPC ARM AArch64 Mips XCore MSP430 CppBackend NVPTX Hexagon SystemZ AMDGPU BPF JSBackend" ALL_TARGETS=$ALL_TARGETS @@ -5640,6 +5643,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" ;; @@ -5651,7 +5655,9 @@ 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" ;; + wasm) TARGETS_TO_BUILD="WebAssembly $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" ;; @@ -5665,6 +5671,7 @@ 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" ;; + WebAssembly) TARGETS_TO_BUILD="WebAssembly $TARGETS_TO_BUILD" ;; *) { { echo "$as_me:$LINENO: error: Can not set target to build" >&5 echo "$as_me: error: Can not set target to build" >&2;} { (exit 1); exit 1; }; } ;; @@ -5769,38 +5776,6 @@ done -SUBZERO_TARGETS_TO_BUILD="" -# Check whether --enable-subzero_targets was given. -if test "${enable_subzero_targets+set}" = set; then - enableval=$enable_subzero_targets; -else - enableval=none -fi - -case "$enableval" in - none) ;; - *)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do - case "$a_target" in - X8632) SUBZERO_TARGETS_TO_BUILD="X8632 $SUBZERO_TARGETS_TO_BUILD" ;; - X8664) SUBZERO_TARGETS_TO_BUILD="X8664 $SUBZERO_TARGETS_TO_BUILD" ;; - ARM32) SUBZERO_TARGETS_TO_BUILD="ARM32 $SUBZERO_TARGETS_TO_BUILD" ;; - ARM64) SUBZERO_TARGETS_TO_BUILD="ARM64 $SUBZERO_TARGETS_TO_BUILD" ;; - MIPS32) SUBZERO_TARGETS_TO_BUILD="MIPS32 $SUBZERO_TARGETS_TO_BUILD" ;; - *) { { echo "$as_me:$LINENO: error: Unrecognized subzero target $a_target" >&5 -echo "$as_me: error: Unrecognized subzero target $a_target" >&2;} - { (exit 1); exit 1; }; } ;; - esac - done - ;; -esac - -SUBZERO_ENUM_TARGETS="" -for target_to_build in $SUBZERO_TARGETS_TO_BUILD; do - SUBZERO_ENUM_TARGETS="SUBZERO_TARGET($target_to_build) $SUBZERO_ENUM_TARGETS" -done - - - # Check whether --with-optimize-option was given. if test "${with_optimize_option+set}" = set; then withval=$with_optimize_option; @@ -5969,6 +5944,20 @@ _ACEOF +# Check whether --with-clang-default-openmp-runtime was given. +if test "${with_clang_default_openmp_runtime+set}" = set; then + withval=$with_clang_default_openmp_runtime; +else + withval="libgomp" +fi + + +cat >>confdefs.h <<_ACEOF +#define CLANG_DEFAULT_OPENMP_RUNTIME "$withval" +_ACEOF + + + # Check whether --with-binutils-include was given. if test "${with_binutils_include+set}" = set; then withval=$with_binutils_include; @@ -8736,6 +8725,87 @@ _ACEOF fi +{ echo "$as_me:$LINENO: checking for main in -lole32" >&5 +echo $ECHO_N "checking for main in -lole32... $ECHO_C" >&6; } +if test "${ac_cv_lib_ole32_main+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lole32 $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_ole32_main=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_ole32_main=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_ole32_main" >&5 +echo "${ECHO_T}$ac_cv_lib_ole32_main" >&6; } +if test $ac_cv_lib_ole32_main = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBOLE32 1 +_ACEOF + + LIBS="-lole32 $LIBS" + +fi + + { echo "$as_me:$LINENO: checking for main in -lpsapi" >&5 echo $ECHO_N "checking for main in -lpsapi... $ECHO_C" >&6; } if test "${ac_cv_lib_psapi_main+set}" = set; then @@ -18074,8 +18144,6 @@ ac_config_headers="$ac_config_headers include/llvm/Config/config.h include/llvm/ -ac_config_files="$ac_config_files include/llvm/Config/SZTargets.def" - ac_config_files="$ac_config_files include/llvm/Config/Targets.def" ac_config_files="$ac_config_files include/llvm/Config/AsmPrinters.def" @@ -18543,7 +18611,7 @@ exec 6>&1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by LLVM $as_me 3.7.0svn, which was +This file was extended by LLVM $as_me 3.8.0svn, which was generated by GNU Autoconf 2.60. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -18596,7 +18664,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -LLVM config.status 3.7.0svn +LLVM config.status 3.8.0svn configured by $0, generated by GNU Autoconf 2.60, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" @@ -18711,7 +18779,6 @@ do case $ac_config_target in "include/llvm/Config/config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/llvm/Config/config.h" ;; "include/llvm/Config/llvm-config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/llvm/Config/llvm-config.h" ;; - "include/llvm/Config/SZTargets.def") CONFIG_FILES="$CONFIG_FILES include/llvm/Config/SZTargets.def" ;; "include/llvm/Config/Targets.def") CONFIG_FILES="$CONFIG_FILES include/llvm/Config/Targets.def" ;; "include/llvm/Config/AsmPrinters.def") CONFIG_FILES="$CONFIG_FILES include/llvm/Config/AsmPrinters.def" ;; "include/llvm/Config/AsmParsers.def") CONFIG_FILES="$CONFIG_FILES include/llvm/Config/AsmParsers.def" ;; @@ -18974,7 +19041,6 @@ LLVM_ENUM_TARGETS!$LLVM_ENUM_TARGETS$ac_delim LLVM_ENUM_ASM_PRINTERS!$LLVM_ENUM_ASM_PRINTERS$ac_delim LLVM_ENUM_ASM_PARSERS!$LLVM_ENUM_ASM_PARSERS$ac_delim LLVM_ENUM_DISASSEMBLERS!$LLVM_ENUM_DISASSEMBLERS$ac_delim -SUBZERO_ENUM_TARGETS!$SUBZERO_ENUM_TARGETS$ac_delim OPTIMIZE_OPTION!$OPTIMIZE_OPTION$ac_delim EXTRA_OPTIONS!$EXTRA_OPTIONS$ac_delim EXTRA_LD_OPTIONS!$EXTRA_LD_OPTIONS$ac_delim @@ -19033,6 +19099,7 @@ HAVE_LIBZ!$HAVE_LIBZ$ac_delim HUGE_VAL_SANITY!$HUGE_VAL_SANITY$ac_delim MMAP_FILE!$MMAP_FILE$ac_delim SHLIBEXT!$SHLIBEXT$ac_delim +LLVM_PREFIX!$LLVM_PREFIX$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then @@ -19074,7 +19141,6 @@ _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF -LLVM_PREFIX!$LLVM_PREFIX$ac_delim LLVM_BINDIR!$LLVM_BINDIR$ac_delim LLVM_DATADIR!$LLVM_DATADIR$ac_delim LLVM_DOCSDIR!$LLVM_DOCSDIR$ac_delim @@ -19095,7 +19161,7 @@ LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 19; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 18; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 diff --git a/docs/AMDGPUUsage.rst b/docs/AMDGPUUsage.rst new file mode 100644 index 00000000000..97d6662a2ed --- /dev/null +++ b/docs/AMDGPUUsage.rst @@ -0,0 +1,177 @@ +============================== +User Guide for AMDGPU Back-end +============================== + +Introduction +============ + +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). + + +Assembler +========= + +The assembler is currently considered experimental. + +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 +are also supported but may be missing some instructions and have more bugs: + +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. + +SMRD Instructions +----------------- +Only the s_load_dword* SMRD instructions are supported. + +SOP1 Instructions +----------------- +All SOP1 instructions are supported. + +SOP2 Instructions +----------------- +All SOP2 instructions are supported. + +SOPC Instructions +----------------- +All SOPC instructions are supported. + +SOPP Instructions +----------------- + +Unless otherwise mentioned, all SOPP instructions that have one or more +operands accept integer operands only. No verification is performed +on the operands, so it is up to the programmer to be familiar with the +range or acceptable values. + +s_waitcnt +^^^^^^^^^ + +s_waitcnt accepts named arguments to specify which memory counter(s) to +wait for. + +.. code-block:: nasm + + // Wait for all counters to be 0 + s_waitcnt 0 + + // Equivalent to s_waitcnt 0. Counter names can also be delimited by + // '&' or ','. + s_waitcnt vmcnt(0) expcnt(0) lgkcmt(0) + + // Wait for vmcnt counter to be 1. + s_waitcnt vmcnt(1) + +VOP1, VOP2, VOP3, VOPC Instructions +----------------------------------- + +All 32-bit and 64-bit encodings should work. + +The assembler will automatically detect which encoding size to use for +VOP1, VOP2, and VOPC instructions based on the operands. If you want to force +a specific encoding size, you can add an _e32 (for 32-bit encoding) or +_e64 (for 64-bit encoding) suffix to the instruction. Most, but not all +instructions support an explicit suffix. These are all valid assembly +strings: + +.. code-block:: nasm + + v_mul_i32_i24 v1, v2, v3 + v_mul_i32_i24_e32 v1, v2, v3 + v_mul_i32_i24_e64 v1, v2, v3 + +Assembler Directives +-------------------- + +.hsa_code_object_version major, minor +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*major* and *minor* are integers that specify the version of the HSA code +object that will be generated by the assembler. This value will be stored +in an entry of the .note section. + +.hsa_code_object_isa [major, minor, stepping, vendor, arch] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +*major*, *minor*, and *stepping* are all integers that describe the instruction +set architecture (ISA) version of the assembly program. + +*vendor* and *arch* are quoted strings. *vendor* should always be equal to +"AMD" and *arch* should always be equal to "AMDGPU". + +If no arguments are specified, then the assembler will derive the ISA version, +*vendor*, and *arch* from the value of the -mcpu option that is passed to the +assembler. + +ISA version, *vendor*, and *arch* will all be stored in a single entry of the +.note section. + +.amd_kernel_code_t +^^^^^^^^^^^^^^^^^^ + +This directive marks the beginning of a list of key / value pairs that are used +to specify the amd_kernel_code_t object that will be emitted by the assembler. +The list must be terminated by the *.end_amd_kernel_code_t* directive. For +any amd_kernel_code_t values that are unspecified a default value will be +used. The default value for all keys is 0, with the following exceptions: + +- *kernel_code_version_major* defaults to 1. +- *machine_kind* defaults to 1. +- *machine_version_major*, *machine_version_minor*, and + *machine_version_stepping* are derived from the value of the -mcpu option + that is passed to the assembler. +- *kernel_code_entry_byte_offset* defaults to 256. +- *wavefront_size* defaults to 6. +- *kernarg_segment_alignment*, *group_segment_alignment*, and + *private_segment_alignment* default to 4. Note that alignments are specified + as a power of two, so a value of **n** means an alignment of 2^ **n**. + +The *.amd_kernel_code_t* directive must be placed immediately after the +function label and before any instructions. + +For a full list of amd_kernel_code_t keys, see the examples in +test/CodeGen/AMDGPU/hsa.s. For an explanation of the meanings of the different +keys, see the comments in lib/Target/AMDGPU/AmdKernelCodeT.h + +Here is an example of a minimal amd_kernel_code_t specification: + +.. code-block:: nasm + + .hsa_code_object_version 1,0 + .hsa_code_object_isa + + .text + + hello_world: + + .amd_kernel_code_t + enable_sgpr_kernarg_segment_ptr = 1 + is_ptr64 = 1 + compute_pgm_rsrc1_vgprs = 0 + compute_pgm_rsrc1_sgprs = 0 + compute_pgm_rsrc2_user_sgpr = 2 + kernarg_segment_byte_size = 8 + wavefront_sgpr_count = 2 + workitem_vgpr_count = 3 + .end_amd_kernel_code_t + + s_load_dwordx2 s[0:1], s[0:1] 0x0 + v_mov_b32 v0, 3.14159 + s_waitcnt lgkmcnt(0) + v_mov_b32 v1, s0 + v_mov_b32 v2, s1 + flat_store_dword v0, v[1:2] + s_endpgm diff --git a/docs/AliasAnalysis.rst b/docs/AliasAnalysis.rst index 1cbaee703f3..f62cc3fe4d3 100644 --- a/docs/AliasAnalysis.rst +++ b/docs/AliasAnalysis.rst @@ -286,8 +286,8 @@ Mod/Ref result, simply return whatever the superclass computes. For example: .. code-block:: c++ - AliasAnalysis::AliasResult alias(const Value *V1, unsigned V1Size, - const Value *V2, unsigned V2Size) { + AliasResult alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size) { if (...) return NoAlias; ... diff --git a/docs/BitCodeFormat.rst b/docs/BitCodeFormat.rst index 4b398a4e956..25ea421ed08 100644 --- a/docs/BitCodeFormat.rst +++ b/docs/BitCodeFormat.rst @@ -741,7 +741,7 @@ global variable. The operand fields are: MODULE_CODE_FUNCTION Record ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prologuedata, dllstorageclass, comdat, prefixdata]`` +``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prologuedata, dllstorageclass, comdat, prefixdata, personalityfn]`` The ``FUNCTION`` record (code 8) marks the declaration or definition of a function. The operand fields are: @@ -795,6 +795,8 @@ function. The operand fields are: * *prefixdata*: If non-zero, the value index of the prefix data for this function, plus 1. +* *personalityfn*: If non-zero, the value index of the personality function for this function, + plus 1. MODULE_CODE_ALIAS Record ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/BranchWeightMetadata.rst b/docs/BranchWeightMetadata.rst index aff7923d186..2ebc6c32416 100644 --- a/docs/BranchWeightMetadata.rst +++ b/docs/BranchWeightMetadata.rst @@ -115,3 +115,26 @@ CFG Modifications Branch Weight Metatada is not proof against CFG changes. If terminator operands' are changed some action should be taken. In other case some misoptimizations may occur due to incorrent branch prediction information. + +Function Entry Counts +===================== + +To allow comparing different functions durint inter-procedural analysis and +optimization, ``MD_prof`` nodes can also be assigned to a function definition. +The first operand is a string indicating the name of the associated counter. + +Currently, one counter is supported: "function_entry_count". This is a 64-bit +counter that indicates the number of times that this function was invoked (in +the case of instrumentation-based profiles). In the case of sampling-based +profiles, this counter is an approximation of how many times the function was +invoked. + +For example, in the code below, the instrumentation for function foo() +indicates that it was called 2,590 times at runtime. + +.. code-block:: llvm + + define i32 @foo() !prof !1 { + ret i32 0 + } + !1 = !{!"function_entry_count", i64 2590} diff --git a/docs/BuildingLLVMWithAutotools.rst b/docs/BuildingLLVMWithAutotools.rst index 4c04f1e1865..6f9a1341055 100644 --- a/docs/BuildingLLVMWithAutotools.rst +++ b/docs/BuildingLLVMWithAutotools.rst @@ -121,7 +121,7 @@ To configure LLVM, follow these steps: .. code-block:: console - % SRC_ROOT/configure --prefix=/install/path [other options] + % $LLVM_SRC_DIR/configure --prefix=/install/path [other options] Compiling the LLVM Suite Source Code ------------------------------------ @@ -187,7 +187,7 @@ source code: ``gmake install`` Installs LLVM header files, libraries, tools, and documentation in a hierarchy - under ``$PREFIX``, specified with ``./configure --prefix=[dir]``, which + under ``$PREFIX``, specified with ``$LLVM_SRC_DIR/configure --prefix=[dir]``, which defaults to ``/usr/local``. ``gmake -C runtime install-bytecode`` @@ -240,7 +240,7 @@ There are some HTML documents that have not yet been converted to the new system (which uses the easy-to-read and easy-to-write `reStructuredText `_ plaintext markup language). -The generated documentation is built in the ``SRC_ROOT/docs`` directory using +The generated documentation is built in the ``$LLVM_SRC_DIR/docs`` directory using a special makefile. For instructions on how to install Sphinx, see `Sphinx Introduction for LLVM Developers @@ -250,7 +250,7 @@ HTML documentation by doing the following: .. code-block:: console - $ cd SRC_ROOT/docs + $ cd $LLVM_SRC_DIR/docs $ make -f Makefile.sphinx This creates a ``_build/html`` sub-directory with all of the HTML files, not @@ -296,7 +296,7 @@ This is accomplished in the typical autoconf manner: .. code-block:: console - % SRC_ROOT/configure + % $LLVM_SRC_DIR/configure The LLVM build will place files underneath *OBJ_ROOT* in directories named after the build type: diff --git a/docs/CMake.rst b/docs/CMake.rst index b9e473fab2b..b6dd83850ff 100644 --- a/docs/CMake.rst +++ b/docs/CMake.rst @@ -327,8 +327,8 @@ LLVM-specific variables **LLVM_USE_SANITIZER**:STRING Define the sanitizer used to build LLVM binaries and tests. Possible values - are ``Address``, ``Memory``, ``MemoryWithOrigins`` and ``Undefined``. - Defaults to empty string. + are ``Address``, ``Memory``, ``MemoryWithOrigins``, ``Undefined``, ``Thread``, + and ``Address;Undefined``. Defaults to empty string. **LLVM_PARALLEL_COMPILE_JOBS**:STRING Define the maximum number of concurrent compilation jobs. diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index da27627f07e..e02fcd9a4d6 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -138,7 +138,9 @@ if( NOT uses_ocaml LESS 0 ) COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html COMMAND ${OCAMLFIND} ocamldoc -d ${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html - -sort -colorize-code -html ${odoc_files}) + -sort -colorize-code -html ${odoc_files} + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/_ocamldoc/style.css + ${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html) add_dependencies(ocaml_doc ${doc_targets}) diff --git a/docs/CodeGenerator.rst b/docs/CodeGenerator.rst index 75d40db958c..516031dd7bc 100644 --- a/docs/CodeGenerator.rst +++ b/docs/CodeGenerator.rst @@ -749,7 +749,7 @@ The SelectionDAG is a Directed-Acyclic-Graph whose nodes are instances of the ``SDNode`` class. The primary payload of the ``SDNode`` is its operation code (Opcode) that indicates what operation the node performs and the operands to the operation. The various operation node types are described at the top of the -``include/llvm/CodeGen/SelectionDAGNodes.h`` file. +``include/llvm/CodeGen/ISDOpcodes.h`` file. Although most operations define a single value, each node in the graph may define multiple values. For example, a combined div/rem operation will define @@ -829,7 +829,7 @@ One great way to visualize what is going on here is to take advantage of a few LLC command line options. The following options pop up a window displaying the SelectionDAG at specific times (if you only get errors printed to the console while using this, you probably `need to configure your -system `_ to add support for it). +system `_ to add support for it). * ``-view-dag-combine1-dags`` displays the DAG after being built, before the first optimization pass. diff --git a/docs/CodingStandards.rst b/docs/CodingStandards.rst index 992939259ab..498d76b04d8 100644 --- a/docs/CodingStandards.rst +++ b/docs/CodingStandards.rst @@ -131,6 +131,12 @@ unlikely to be supported by our host compilers. cannot synthesize them. * Initializer lists: N2627_ * Delegating constructors: N1986_ +* Default member initializers (non-static data member initializers): N2756_ + + * Only use these for scalar members that would otherwise be left + uninitialized. Non-scalar members generally have appropriate default + constructors, and MSVC 2013 has problems when braced initializer lists are + involved. .. _N2118: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html .. _N2439: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2439.htm @@ -156,7 +162,7 @@ unlikely to be supported by our host compilers. .. _N2346: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm .. _N2627: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2672.htm .. _N1986: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf -.. _MSVC-compatible RTTI: http://llvm.org/PR18951 +.. _N2756: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2756.htm The supported features in the C++11 standard libraries are less well tracked, but also much greater. Most of the standard libraries implement most of C++11's @@ -241,8 +247,8 @@ tree. The standard header looks like this: //===----------------------------------------------------------------------===// /// /// \file - /// \brief This file contains the declaration of the Instruction class, which is - /// the base class for all of the VM instructions. + /// This file contains the declaration of the Instruction class, which is the + /// base class for all of the VM instructions. /// //===----------------------------------------------------------------------===// @@ -262,10 +268,10 @@ file is released under. This makes it perfectly clear what terms the source code can be distributed under and should not be modified in any way. The main body is a ``doxygen`` comment (identified by the ``///`` comment -marker instead of the usual ``//``) describing the purpose of the file. It -should have a ``\brief`` command that describes the file in one or two -sentences. Any additional information should be separated by a blank line. If -an algorithm is being implemented or something tricky is going on, a reference +marker instead of the usual ``//``) describing the purpose of the file. The +first sentence or a passage beginning with ``\brief`` is used as an abstract. +Any additional information should be separated by a blank line. If an +algorithm is being implemented or something tricky is going on, a reference to the paper where it is published should be included, as well as any notes or *gotchas* in the code to watch out for. @@ -314,10 +320,11 @@ Doxygen Use in Documentation Comments Use the ``\file`` command to turn the standard file header into a file-level comment. -Include descriptive ``\brief`` paragraphs for all public interfaces (public -classes, member and non-member functions). Explain API use and purpose in -``\brief`` paragraphs, don't just restate the information that can be inferred -from the API name. Put detailed discussion into separate paragraphs. +Include descriptive paragraphs for all public interfaces (public classes, +member and non-member functions). Don't just restate the information that can +be inferred from the API name. The first sentence or a paragraph beginning +with ``\brief`` is used as an abstract. Put detailed discussion into separate +paragraphs. To refer to parameter names inside a paragraph, use the ``\p name`` command. Don't use the ``\arg name`` command since it starts a new paragraph that @@ -337,8 +344,8 @@ A minimal documentation comment: .. code-block:: c++ - /// \brief Does foo and bar. - void fooBar(bool Baz); + /// Sets the xyzzy property to \p Baz. + void setXyzzy(bool Baz); A documentation comment that uses all Doxygen features in a preferred way: @@ -395,10 +402,10 @@ Correct: // In Something.h: - /// \brief An abstraction for some complicated thing. + /// An abstraction for some complicated thing. class Something { public: - /// \brief Does foo and bar. + /// Does foo and bar. void fooBar(); }; diff --git a/docs/CommandGuide/FileCheck.rst b/docs/CommandGuide/FileCheck.rst index f48bf474519..03c88297677 100644 --- a/docs/CommandGuide/FileCheck.rst +++ b/docs/CommandGuide/FileCheck.rst @@ -200,9 +200,9 @@ For example, the following works like you'd expect: .. code-block:: llvm - !0 = !MDLocation(line: 5, scope: !1, inlinedAt: !2) + !0 = !DILocation(line: 5, scope: !1, inlinedAt: !2) - ; CHECK: !MDLocation(line: 5, + ; CHECK: !DILocation(line: 5, ; CHECK-NOT: column: ; CHECK-SAME: scope: ![[SCOPE:[0-9]+]] diff --git a/docs/CommandGuide/index.rst b/docs/CommandGuide/index.rst index ed18cd048aa..46db57f1c84 100644 --- a/docs/CommandGuide/index.rst +++ b/docs/CommandGuide/index.rst @@ -21,6 +21,7 @@ Basic Commands lli llvm-link llvm-ar + llvm-lib llvm-nm llvm-config llvm-diff diff --git a/docs/CommandGuide/lit.rst b/docs/CommandGuide/lit.rst index 9c63848a76d..e820eef2faf 100644 --- a/docs/CommandGuide/lit.rst +++ b/docs/CommandGuide/lit.rst @@ -56,7 +56,7 @@ GENERAL OPTIONS Search for :file:`{NAME}.cfg` and :file:`{NAME}.site.cfg` when searching for test suites, instead of :file:`lit.cfg` and :file:`lit.site.cfg`. -.. option:: --param NAME, --param NAME=VALUE +.. option:: -D NAME, -D NAME=VALUE, --param NAME, --param NAME=VALUE Add a user defined parameter ``NAME`` with the given ``VALUE`` (or the empty string if not given). The meaning and use of these parameters is test suite @@ -161,7 +161,7 @@ ADDITIONAL OPTIONS .. option:: --show-tests - List all of the the discovered tests and exit. + List all of the discovered tests and exit. EXIT STATUS ----------- diff --git a/docs/CommandGuide/lli.rst b/docs/CommandGuide/lli.rst index 502fbd60935..9da13ee47e0 100644 --- a/docs/CommandGuide/lli.rst +++ b/docs/CommandGuide/lli.rst @@ -1,172 +1,127 @@ lli - directly execute programs from LLVM bitcode ================================================= - SYNOPSIS -------- - -**lli** [*options*] [*filename*] [*program args*] - +:program:`lli` [*options*] [*filename*] [*program args*] DESCRIPTION ----------- +:program:`lli` directly executes programs in LLVM bitcode format. It takes a program +in LLVM bitcode format and executes it using a just-in-time compiler or an +interpreter. -**lli** directly executes programs in LLVM bitcode format. It takes a program -in LLVM bitcode format and executes it using a just-in-time compiler, if one is -available for the current architecture, or an interpreter. **lli** takes all of -the same code generator options as llc|llc, but they are only effective when -**lli** is using the just-in-time compiler. +:program:`lli` is *not* an emulator. It will not execute IR of different architectures +and it can only interpret (or JIT-compile) for the host architecture. -If *filename* is not specified, then **lli** reads the LLVM bitcode for the +The JIT compiler takes the same arguments as other tools, like :program:`llc`, +but they don't necessarily work for the interpreter. + +If `filename` is not specified, then :program:`lli` reads the LLVM bitcode for the program from standard input. The optional *args* specified on the command line are passed to the program as arguments. - GENERAL OPTIONS --------------- - - -**-fake-argv0**\ =\ *executable* +.. option:: -fake-argv0=executable Override the ``argv[0]`` value passed into the executing program. - - -**-force-interpreter**\ =\ *{false,true}* +.. option:: -force-interpreter={false,true} If set to true, use the interpreter even if a just-in-time compiler is available for this architecture. Defaults to false. - - -**-help** +.. option:: -help Print a summary of command line options. +.. option:: -load=pluginfilename - -**-load**\ =\ *pluginfilename* - - Causes **lli** to load the plugin (shared object) named *pluginfilename* and use + Causes :program:`lli` to load the plugin (shared object) named *pluginfilename* and use it for optimization. - - -**-stats** +.. option:: -stats Print statistics from the code-generation passes. This is only meaningful for the just-in-time compiler, at present. - - -**-time-passes** +.. option:: -time-passes Record the amount of time needed for each code-generation pass and print it to standard error. +.. option:: -version - -**-version** - - Print out the version of **lli** and exit without doing anything else. - - - + Print out the version of :program:`lli` and exit without doing anything else. TARGET OPTIONS -------------- - - -**-mtriple**\ =\ *target triple* +.. option:: -mtriple=target triple Override the target triple specified in the input bitcode file with the specified string. This may result in a crash if you pick an architecture which is not compatible with the current system. - - -**-march**\ =\ *arch* +.. option:: -march=arch Specify the architecture for which to generate assembly, overriding the target encoded in the bitcode file. See the output of **llc -help** for a list of valid architectures. By default this is inferred from the target triple or autodetected to the current architecture. - - -**-mcpu**\ =\ *cpuname* +.. option:: -mcpu=cpuname Specify a specific chip in the current architecture to generate code for. By default this is inferred from the target triple and autodetected to the current architecture. For a list of available CPUs, use: **llvm-as < /dev/null | llc -march=xyz -mcpu=help** - - -**-mattr**\ =\ *a1,+a2,-a3,...* +.. option:: -mattr=a1,+a2,-a3,... Override or control specific attributes of the target, such as whether SIMD operations are enabled or not. The default set of attributes is set by the current CPU. For a list of available attributes, use: **llvm-as < /dev/null | llc -march=xyz -mattr=help** - - - FLOATING POINT OPTIONS ---------------------- - - -**-disable-excess-fp-precision** +.. option:: -disable-excess-fp-precision Disable optimizations that may increase floating point precision. - - -**-enable-no-infs-fp-math** +.. option:: -enable-no-infs-fp-math Enable optimizations that assume no Inf values. - - -**-enable-no-nans-fp-math** +.. option:: -enable-no-nans-fp-math Enable optimizations that assume no NAN values. +.. option:: -enable-unsafe-fp-math - -**-enable-unsafe-fp-math** - - Causes **lli** to enable optimizations that may decrease floating point + Causes :program:`lli` to enable optimizations that may decrease floating point precision. +.. option:: -soft-float - -**-soft-float** - - Causes **lli** to generate software floating point library calls instead of + Causes :program:`lli` to generate software floating point library calls instead of equivalent hardware instructions. - - - CODE GENERATION OPTIONS ----------------------- - - -**-code-model**\ =\ *model* +.. option:: -code-model=model Choose the code model from: - .. code-block:: perl default: Target default code model @@ -175,42 +130,30 @@ CODE GENERATION OPTIONS medium: Medium code model large: Large code model - - - -**-disable-post-RA-scheduler** +.. option:: -disable-post-RA-scheduler Disable scheduling after register allocation. - - -**-disable-spill-fusing** +.. option:: -disable-spill-fusing Disable fusing of spill code into instructions. - - -**-jit-enable-eh** +.. option:: -jit-enable-eh Exception handling should be enabled in the just-in-time compiler. - - -**-join-liveintervals** +.. option:: -join-liveintervals Coalesce copies (default=true). +.. option:: -nozero-initialized-in-bss + Don't place zero-initialized symbols into the BSS section. -**-nozero-initialized-in-bss** Don't place zero-initialized symbols into the BSS section. - - - -**-pre-RA-sched**\ =\ *scheduler* +.. option:: -pre-RA-sched=scheduler Instruction schedulers available (before register allocation): - .. code-block:: perl =default: Best scheduler for the target @@ -221,74 +164,51 @@ CODE GENERATION OPTIONS =list-tdrr: Top-down register reduction list scheduling =list-td: Top-down list scheduler -print-machineinstrs - Print generated machine code - - - -**-regalloc**\ =\ *allocator* +.. option:: -regalloc=allocator Register allocator to use (default=linearscan) - .. code-block:: perl =bigblock: Big-block register allocator =linearscan: linear scan register allocator =local - local register allocator =simple: simple register allocator - - - -**-relocation-model**\ =\ *model* +.. option:: -relocation-model=model Choose relocation model from: - .. code-block:: perl =default: Target default relocation model =static: Non-relocatable code =pic - Fully relocatable, position independent code =dynamic-no-pic: Relocatable external references, non-relocatable code - - - -**-spiller** +.. option:: -spiller Spiller to use (default=local) - .. code-block:: perl =simple: simple spiller =local: local spiller - - - -**-x86-asm-syntax**\ =\ *syntax* +.. option:: -x86-asm-syntax=syntax Choose style of code to emit from X86 backend: - .. code-block:: perl =att: Emit AT&T-style assembly =intel: Emit Intel-style assembly - - - - EXIT STATUS ----------- - -If **lli** fails to load the program, it will exit with an exit code of 1. +If :program:`lli` fails to load the program, it will exit with an exit code of 1. Otherwise, it will return the exit code of the program it executes. - SEE ALSO -------- - -llc|llc +:program:`llc` diff --git a/docs/CommandGuide/llvm-cov.rst b/docs/CommandGuide/llvm-cov.rst index dff337572e4..d0e78a9a1d1 100644 --- a/docs/CommandGuide/llvm-cov.rst +++ b/docs/CommandGuide/llvm-cov.rst @@ -175,7 +175,7 @@ The :program:`llvm-cov show` command shows line by line coverage of a binary *BIN* using the profile data *PROFILE*. It can optionally be filtered to only show the coverage for the files listed in *SOURCES*. -To use :program:`llvm-cov show`, you need a program that's compiled with +To use :program:`llvm-cov show`, you need a program that is compiled with instrumentation to emit profile and coverage data. To build such a program with ``clang`` use the ``-fprofile-instr-generate`` and ``-fcoverage-mapping`` flags. If linking with the ``clang`` driver, pass ``-fprofile-instr-generate`` @@ -223,10 +223,10 @@ OPTIONS .. option:: -arch= - If the covered binary is a universal binary, select the architecture to use - when looking up the coverage map. Errors out if the supplied architecture is - not found in the universal binary, or if used on a non-universal binary of - a different architecture. + If the covered binary is a universal binary, select the architecture to use. + It is an error to specify an architecture that is not included in the + universal binary or to use an architecture that does not match a + non-universal binary. .. option:: -name= @@ -291,7 +291,7 @@ OPTIONS .. option:: -arch= - If the covered binary is a universal binary, select the architecture to use - when looking up the coverage map. Errors out if the supplied architecture is - not found in the universal binary, or if used on a non-universal binary of - a different architecture. + If the covered binary is a universal binary, select the architecture to use. + It is an error to specify an architecture that is not included in the + universal binary or to use an architecture that does not match a + non-universal binary. diff --git a/docs/CommandGuide/llvm-dwarfdump.rst b/docs/CommandGuide/llvm-dwarfdump.rst index afaa0be3819..30c18adb771 100644 --- a/docs/CommandGuide/llvm-dwarfdump.rst +++ b/docs/CommandGuide/llvm-dwarfdump.rst @@ -26,5 +26,5 @@ OPTIONS EXIT STATUS ----------- -:program:`llvm-dwarfdump` returns 0. Other exit codes imply internal -program error. +:program:`llvm-dwarfdump` returns 0 if the input files were parsed and dumped +successfully. Otherwise, it returns 1. diff --git a/docs/CommandGuide/llvm-lib.rst b/docs/CommandGuide/llvm-lib.rst new file mode 100644 index 00000000000..ecd0a7db7e3 --- /dev/null +++ b/docs/CommandGuide/llvm-lib.rst @@ -0,0 +1,31 @@ +llvm-lib - LLVM lib.exe compatible library tool +=============================================== + + +SYNOPSIS +-------- + + +**llvm-lib** [/libpath:] [/out:] [/llvmlibthin] +[/ignore] [/machine] [/nologo] [files...] + + +DESCRIPTION +----------- + + +The **llvm-lib** command is intended to be a ``lib.exe`` compatible +tool. See https://msdn.microsoft.com/en-us/library/7ykb2k5f for the +general description. + +**llvm-lib** has the following extensions: + +* Bitcode files in symbol tables. + **llvm-lib** includes symbols from both bitcode files and regular + object files in the symbol table. + +* Creating thin archives. + The /llvmlibthin option causes **llvm-lib** to create thin archive + that contain only the symbol table and the header for the various + members. These files are much smaller, but are not compatible with + link.exe (lld can handle them). diff --git a/docs/CommandGuide/llvm-profdata.rst b/docs/CommandGuide/llvm-profdata.rst index 45f70731d69..7053b7fa710 100644 --- a/docs/CommandGuide/llvm-profdata.rst +++ b/docs/CommandGuide/llvm-profdata.rst @@ -49,6 +49,28 @@ OPTIONS Specify the output file name. *Output* cannot be ``-`` as the resulting indexed profile data can't be written to standard output. +.. option:: -instr (default) + + Specify that the input profile is an instrumentation-based profile. + +.. option:: -sample + + Specify that the input profile is a sample-based profile. When using + sample-based profiles, the format of the generated file can be generated + in one of three ways: + + .. option:: -binary (default) + + Emit the profile using a binary encoding. + + .. option:: -text + + Emit the profile in text mode. + + .. option:: -gcc + + Emit the profile using GCC's gcov format (Not yet supported). + .. program:: llvm-profdata show .. _profdata-show: @@ -95,6 +117,14 @@ OPTIONS Specify the output file name. If *output* is ``-`` or it isn't specified, then the output is sent to standard output. +.. option:: -instr (default) + + Specify that the input profile is an instrumentation-based profile. + +.. option:: -sample + + Specify that the input profile is a sample-based profile. + EXIT STATUS ----------- diff --git a/docs/CommandLine.rst b/docs/CommandLine.rst index 1d85215f2af..556c302501e 100644 --- a/docs/CommandLine.rst +++ b/docs/CommandLine.rst @@ -1737,6 +1737,7 @@ exported by the ``lib/VMCore/PassManager.cpp`` file. .. _dynamically loaded options: Dynamically adding command line options +--------------------------------------- .. todo:: diff --git a/docs/CompilerWriterInfo.rst b/docs/CompilerWriterInfo.rst index 2dfdc9b142d..900ba24e230 100644 --- a/docs/CompilerWriterInfo.rst +++ b/docs/CompilerWriterInfo.rst @@ -68,8 +68,8 @@ Other documents, collections, notes * `PowerPC64 alignment of long doubles (from GCC) `_ * `Long branch stubs for powerpc64-linux (from binutils) `_ -R600 ----- +AMDGPU +------ * `AMD R6xx shader ISA `_ * `AMD R7xx shader ISA `_ diff --git a/docs/CoverageMappingFormat.rst b/docs/CoverageMappingFormat.rst index 8fcffb838a3..9ac476c88b3 100644 --- a/docs/CoverageMappingFormat.rst +++ b/docs/CoverageMappingFormat.rst @@ -405,7 +405,7 @@ LEB128 is an unsigned interger value that is encoded using DWARF's LEB128 encoding, optimizing for the case where values are small (1 byte for values less than 128). -.. _strings: +.. _Strings: Strings ^^^^^^^ diff --git a/docs/DeveloperPolicy.rst b/docs/DeveloperPolicy.rst index a07b5fab217..4ee43fcdb9e 100644 --- a/docs/DeveloperPolicy.rst +++ b/docs/DeveloperPolicy.rst @@ -324,6 +324,11 @@ Below are some guidelines about the format of the message itself: * Text formatting and spelling should follow the same rules as documentation and in-code comments, ex. capitalization, full stop, etc. +* If the commit is a bug fix on top of another recently committed patch, or a + revert or reapply of a patch, include the svn revision number of the prior + related commit. This could be as simple as "Revert rNNNN because it caused + PR#". + For minor violations of these recommendations, the community normally favors reminding the contributor of this policy over reverting. Minor corrections and omissions can be handled by sending a reply to the commits mailing list. @@ -619,5 +624,5 @@ patent-related trouble with their changes (including from third parties). If you or your employer own the rights to a patent and would like to contribute code to LLVM that relies on it, we require that the copyright owner sign an agreement that allows any other user of LLVM to freely use your patent. Please -contact the `oversight group `_ for more +contact the `LLVM Foundation Board of Directors `_ for more details. diff --git a/docs/ExceptionHandling.rst b/docs/ExceptionHandling.rst index 72ed78a3c99..55ffdb45efe 100644 --- a/docs/ExceptionHandling.rst +++ b/docs/ExceptionHandling.rst @@ -339,11 +339,11 @@ original context before code generation. Catch handlers are called with a pointer to the handler itself as the first argument and a pointer to the parent function's stack frame as the second -argument. The catch handler uses the `llvm.recoverframe -`_ to get a +argument. The catch handler uses the `llvm.localrecover +`_ to get a pointer to a frame allocation block that is created in the parent frame using -the `llvm.allocateframe -`_ intrinsic. +the `llvm.localescape +`_ intrinsic. The ``WinEHPrepare`` pass will have created a structure definition for the contents of this block. The first two members of the structure will always be (1) a 32-bit integer that the runtime uses to track the exception state of the @@ -520,12 +520,12 @@ action. A code of ``i32 1`` indicates a catch action, which expects three additional arguments. Different EH schemes give different meanings to the three arguments, but the first argument indicates whether the catch should fire, the second is -the frameescape index of the exception object, and the third is the code to run +the localescape index of the exception object, and the third is the code to run to catch the exception. For Windows C++ exception handling, the first argument for a catch handler is a pointer to the RTTI type descriptor for the object to catch. The second -argument is an index into the argument list of the ``llvm.frameescape`` call in +argument is an index into the argument list of the ``llvm.localescape`` call in the main function. The exception object will be copied into the provided stack object. If the exception object is not required, this argument should be -1. The third argument is a pointer to a function implementing the catch. This diff --git a/docs/FAQ.rst b/docs/FAQ.rst index 8db94c6250c..0559a1ff215 100644 --- a/docs/FAQ.rst +++ b/docs/FAQ.rst @@ -102,7 +102,7 @@ grabbing the wrong linker/assembler/etc, there are two ways to fix it: .. code-block:: console - % PATH=[the path without the bad program] ./configure ... + % PATH=[the path without the bad program] $LLVM_SRC_DIR/configure ... This is still somewhat inconvenient, but it allows ``configure`` to do its work without having to adjust your ``PATH`` permanently. diff --git a/docs/FaultMaps.rst b/docs/FaultMaps.rst new file mode 100644 index 00000000000..4ecdd86d769 --- /dev/null +++ b/docs/FaultMaps.rst @@ -0,0 +1,127 @@ +============================== +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 + } + } + + +The ``ImplicitNullChecks`` pass +=============================== + +The ``ImplicitNullChecks`` pass transforms explicit control flow for +checking if a pointer is ``null``, like: + +.. code-block:: llvm + + %ptr = call i32* @get_ptr() + %ptr_is_null = icmp i32* %ptr, null + br i1 %ptr_is_null, label %is_null, label %not_null, !make.implicit !0 + + not_null: + %t = load i32, i32* %ptr + br label %do_something_with_t + + is_null: + call void @HFC() + unreachable + + !0 = !{} + +to control flow implicit in the instruction loading or storing through +the pointer being null checked: + +.. code-block:: llvm + + %ptr = call i32* @get_ptr() + %t = load i32, i32* %ptr ;; handler-pc = label %is_null + br label %do_something_with_t + + is_null: + call void @HFC() + unreachable + +This transform happens at the ``MachineInstr`` level, not the LLVM IR +level (so the above example is only representative, not literal). The +``ImplicitNullChecks`` pass runs during codegen, if +``-enable-implicit-null-checks`` is passed to ``llc``. + +The ``ImplicitNullChecks`` pass adds entries to the +``__llvm_faultmaps`` section described above as needed. + +``make.implicit`` metadata +-------------------------- + +Making null checks implicit is an aggressive optimization, and it can +be a net performance pessimization if too many memory operations end +up faulting because of it. A language runtime typically needs to +ensure that only a negligible number of implicit null checks actually +fault once the application has reached a steady state. A standard way +of doing this is by healing failed implicit null checks into explicit +null checks via code patching or recompilation. It follows that there +are two requirements an explicit null check needs to satisfy for it to +be profitable to convert it to an implicit null check: + + 1. The case where the pointer is actually null (i.e. the "failing" + case) is extremely rare. + + 2. The failing path heals the implicit null check into an explicit + null check so that the application does not repeatedly page + fault. + +The frontend is expected to mark branches that satisfy (1) and (2) +using a ``!make.implicit`` metadata node (the actual content of the +metadata node is ignored). Only branches that are marked with +``!make.implicit`` metadata are considered as candidates for +conversion into implicit null checks. + +(Note that while we could deal with (1) using profiling data, dealing +with (2) requires some information not present in branch profiles.) diff --git a/docs/Frontend/PerformanceTips.rst b/docs/Frontend/PerformanceTips.rst index d8c04651f0a..22b3fe45984 100644 --- a/docs/Frontend/PerformanceTips.rst +++ b/docs/Frontend/PerformanceTips.rst @@ -55,8 +55,7 @@ Other things to consider #. Add nsw/nuw flags as appropriate. Reasoning about overflow is generally hard for an optimizer so providing these facts from the frontend - can be very impactful. For languages which need overflow semantics, - consider using the :ref:`overflow intrinsics `. + can be very impactful. #. Use fast-math flags on floating point operations if legal. If you don't need strict IEEE floating point semantics, there are a number of additional @@ -142,6 +141,29 @@ Other things to consider perform badly with confronted with such structures. The only exception to this guidance is that a unified return block with high in-degree is fine. +#. When checking a value against a constant, emit the check using a consistent + comparison type. The GVN pass *will* optimize redundant equalities even if + the type of comparison is inverted, but GVN only runs late in the pipeline. + As a result, you may miss the opportunity to run other important + optimizations. Improvements to EarlyCSE to remove this issue are tracked in + Bug 23333. + +#. Avoid using arithmetic intrinsics unless you are *required* by your source + language specification to emit a particular code sequence. The optimizer + is quite good at reasoning about general control flow and arithmetic, it is + not anywhere near as strong at reasoning about the various intrinsics. If + profitable for code generation purposes, the optimizer will likely form the + intrinsics itself late in the optimization pipeline. It is *very* rarely + profitable to emit these directly in the language frontend. This item + explicitly includes the use of the :ref:`overflow intrinsics `. + +#. Avoid using the :ref:`assume intrinsic ` until you've + established that a) there's no other way to express the given fact and b) + that fact is critical for optimization purposes. Assumes are a great + prototyping mechanism, but they can have negative effects on both compile + time and optimization effectiveness. The former is fixable with enough + effort, but the later is fairly fundamental to their designed purpose. + p.s. If you want to help improve this document, patches expanding any of the above items into standalone sections of their own with a more complete discussion would be very welcome. diff --git a/docs/GarbageCollection.rst b/docs/GarbageCollection.rst index a1557fcdb09..56b4b9f8f95 100644 --- a/docs/GarbageCollection.rst +++ b/docs/GarbageCollection.rst @@ -494,6 +494,7 @@ a ``gcroot`` strategy. As there names imply, the binary format produced is intended to model that used by the Erlang and OCaml compilers respectively. +.. _statepoint_example_gc: The Statepoint Example GC ------------------------- @@ -517,6 +518,28 @@ The stack map format generated by this GC strategy can be found in the `. This format is intended to be the standard format supported by LLVM going forward. +The CoreCLR GC +------------------------- + +.. code-block:: c++ + + F.setGC("coreclr"); + +This GC leverages the ``gc.statepoint`` mechanism to support the +`CoreCLR `__ runtime. + +Support for this GC strategy is a work in progress. This strategy will +differ from +:ref:`statepoint-example GC` strategy in +certain aspects like: + +* Base-pointers of interior pointers are not explicitly + tracked and reported. + +* A different format is used for encoding stack maps. + +* Safe-point polls are only needed before loop-back edges + and before tail-calls (not needed at function-entry). Custom GC Strategies ==================== diff --git a/docs/GettingStarted.rst b/docs/GettingStarted.rst index 18b3c1d87cc..75f0e60c41f 100644 --- a/docs/GettingStarted.rst +++ b/docs/GettingStarted.rst @@ -326,7 +326,11 @@ Easy steps for installing GCC 4.8.2: .. code-block:: console - % wget ftp://ftp.gnu.org/gnu/gcc/gcc-4.8.2/gcc-4.8.2.tar.bz2 + % wget https://ftp.gnu.org/gnu/gcc/gcc-4.8.2/gcc-4.8.2.tar.bz2 + % wget https://ftp.gnu.org/gnu/gcc/gcc-4.8.2/gcc-4.8.2.tar.bz2.sig + % wget https://ftp.gnu.org/gnu/gnu-keyring.gpg + % signature_invalid=`gpg --verify --no-default-keyring --keyring ./gnu-keyring.gpg gcc-4.8.2.tar.bz2.sig` + % if [ $signature_invalid ]; then echo "Invalid signature" ; exit 1 ; fi % tar -xvjf gcc-4.8.2.tar.bz2 % cd gcc-4.8.2 % ./contrib/download_prerequisites @@ -711,7 +715,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 | diff --git a/docs/HowToBuildOnARM.rst b/docs/HowToBuildOnARM.rst index f2edaef76cd..6579d36a72a 100644 --- a/docs/HowToBuildOnARM.rst +++ b/docs/HowToBuildOnARM.rst @@ -40,7 +40,7 @@ on the ARMv6 and ARMv7 architectures and may be inapplicable to older chips. .. code-block:: bash - ./configure --build=armv7l-unknown-linux-gnueabihf \ + ../$LLVM_SRC_DIR/configure --build=armv7l-unknown-linux-gnueabihf \ --host=armv7l-unknown-linux-gnueabihf \ --target=armv7l-unknown-linux-gnueabihf --with-cpu=cortex-a9 \ --with-float=hard --with-abi=aapcs-vfp --with-fpu=neon \ diff --git a/docs/HowToReleaseLLVM.rst b/docs/HowToReleaseLLVM.rst index 26e9f3b2ee8..33c547e97a8 100644 --- a/docs/HowToReleaseLLVM.rst +++ b/docs/HowToReleaseLLVM.rst @@ -136,51 +136,24 @@ Regenerate the configure scripts for both ``llvm`` and the ``test-suite``. In addition, the version numbers of all the Bugzilla components must be updated for the next release. -Build the LLVM Release Candidates -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Tagging the LLVM Release Candidates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Create release candidates for ``llvm``, ``clang``, ``dragonegg``, and the LLVM -``test-suite`` by tagging the branch with the respective release candidate -number. For instance, to create **Release Candidate 1** you would issue the -following commands: +Tag release candidates using the tag.sh script in utils/release. :: - $ svn mkdir https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XYZ - $ svn copy https://llvm.org/svn/llvm-project/llvm/branches/release_XY \ - https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XYZ/rc1 - - $ svn mkdir https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_XYZ - $ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_XY \ - https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_XYZ/rc1 - - $ svn mkdir https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_XYZ - $ svn copy https://llvm.org/svn/llvm-project/dragonegg/branches/release_XY \ - https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_XYZ/rc1 - - $ svn mkdir https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XYZ - $ svn copy https://llvm.org/svn/llvm-project/test-suite/branches/release_XY \ - https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XYZ/rc1 - -Similarly, **Release Candidate 2** would be named ``RC2`` and so on. This keeps -a permanent copy of the release candidate around for people to export and build -as they wish. The final released sources will be tagged in the ``RELEASE_XYZ`` -directory as ``Final`` (c.f. :ref:`tag`). + $ ./tag.sh -release X.Y.Z -rc $RC The Release Manager may supply pre-packaged source tarballs for users. This can -be done with the following commands: +be done with the export.sh script in utils/release. :: - $ svn export https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XYZ/rc1 llvm-X.Yrc1 - $ svn export https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_XYZ/rc1 clang-X.Yrc1 - $ svn export https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_XYZ/rc1 dragonegg-X.Yrc1 - $ svn export https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XYZ/rc1 llvm-test-X.Yrc1 + $ ./export.sh -release X.Y.Z -rc $RC - $ tar -cvf - llvm-X.Yrc1 | gzip > llvm-X.Yrc1.src.tar.gz - $ tar -cvf - clang-X.Yrc1 | gzip > clang-X.Yrc1.src.tar.gz - $ tar -cvf - dragonegg-X.Yrc1 | gzip > dragonegg-X.Yrc1.src.tar.gz - $ tar -cvf - llvm-test-X.Yrc1 | gzip > llvm-test-X.Yrc1.src.tar.gz +This will generate source tarballs for each LLVM project being validated, which +can be uploaded to the website for further testing. Building the Release -------------------- @@ -384,21 +357,11 @@ mainline into the release branch. Tag the LLVM Final Release ^^^^^^^^^^^^^^^^^^^^^^^^^^ -Tag the final release sources using the following procedure: +Tag the final release sources using the tag.sh script in utils/release. :: - $ svn copy https://llvm.org/svn/llvm-project/llvm/branches/release_XY \ - https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XYZ/Final - - $ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_XY \ - https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_XYZ/Final - - $ svn copy https://llvm.org/svn/llvm-project/dragonegg/branches/release_XY \ - https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_XYZ/Final - - $ svn copy https://llvm.org/svn/llvm-project/test-suite/branches/release_XY \ - https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XYZ/Final + $ ./tag.sh -release X.Y.Z -final Update the LLVM Demo Page ------------------------- diff --git a/docs/LangRef.rst b/docs/LangRef.rst index a5a886952b7..2030c475b09 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -494,6 +494,9 @@ model is not supported, or if a better choice of model can be made. A model can also be specified in a alias, but then it only governs how the alias is accessed. It will not have any effect in the aliasee. +For platforms without linker support of ELF TLS model, the -femulated-tls +flag can be used to generate GCC compatible emulated TLS code. + .. _namedtypes: Structure Types @@ -635,8 +638,9 @@ attributes `), optional :ref:`function attributes `, an optional section, an optional alignment, an optional :ref:`comdat `, an optional :ref:`garbage collector name `, an optional :ref:`prefix `, -an optional :ref:`prologue `, an opening -curly brace, a list of basic blocks, and a closing curly brace. +an optional :ref:`prologue `, +an optional :ref:`personality `, +an opening curly brace, a list of basic blocks, and a closing curly brace. LLVM function declarations consist of the "``declare``" keyword, an optional :ref:`linkage type `, an optional :ref:`visibility @@ -683,7 +687,8 @@ Syntax:: [cconv] [ret attrs] @ ([argument list]) [unnamed_addr] [fn Attrs] [section "name"] [comdat [($name)]] - [align N] [gc] [prefix Constant] [prologue Constant] { ... } + [align N] [gc] [prefix Constant] [prologue Constant] + [personality Constant] { ... } The argument list is a comma seperated sequence of arguments where each argument is of the following form @@ -821,9 +826,11 @@ with the same name. This is necessary because both globals belong to different COMDAT groups and COMDATs, at the object file level, are represented by sections. -Note that certain IR constructs like global variables and functions may create -COMDATs in the object file in addition to any which are specified using COMDAT -IR. This arises, for example, when a global variable has linkonce_odr linkage. +Note that certain IR constructs like global variables and functions may +create COMDATs in the object file in addition to any which are specified using +COMDAT IR. This arises when the code generator is configured to emit globals +in individual sections (e.g. when `-data-sections` or `-function-sections` +is supplied to `llc`). .. _namedmetadatastructure: @@ -834,6 +841,11 @@ Named metadata is a collection of metadata. :ref:`Metadata nodes ` (but not metadata strings) are the only valid operands for a named metadata. +#. Named metadata are represented as a string of characters with the + metadata prefix. The rules for metadata names are the same as for + identifiers, but quoted names are not allowed. ``"\xx"`` type escapes + are still valid, which allows any character to be part of a name. + Syntax:: ; Some unnamed metadata nodes, which are referenced by the named metadata. @@ -1125,6 +1137,14 @@ A function may have prologue data but no body. This has similar semantics to the ``available_externally`` linkage in that the data may be used by the optimizers but will not be emitted in the object file. +.. _personalityfn: + +Personality Function +-------------------- + +The ``personality`` attribute permits functions to specify what function +to use for exception handling. + .. _attrgrp: Attribute Groups @@ -1196,6 +1216,13 @@ example: computing edge weights, basic blocks post-dominated by a cold function call are also considered to be cold; and, thus, given low weight. +``convergent`` + This attribute indicates that the callee is dependent on a convergent + thread execution pattern under certain parallel execution models. + Transformations that are execution model agnostic may only move or + tranform this call if the final location is control equivalent to its + original position in the program, where control equivalence is defined as + A dominates B and B post-dominates A, or vice versa. ``inlinehint`` This attribute indicates that the source code contained a hint that inlining this function is desirable (such as the "inline" keyword in @@ -1302,11 +1329,28 @@ example: On an argument, this attribute indicates that the function does not write through this pointer argument, even though it may write to the memory that the pointer points to. +``argmemonly`` + This attribute indicates that the only memory accesses inside function are + loads and stores from objects pointed to by its pointer-typed arguments, + with arbitrary offsets. Or in other words, all memory operations in the + function can refer to memory only using pointers based on its function + arguments. + Note that ``argmemonly`` can be used together with ``readonly`` attribute + in order to specify that function reads only from its arguments. ``returns_twice`` This attribute indicates that this function can return twice. The C ``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 `_ + 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. @@ -1413,8 +1457,8 @@ The strings can contain any character by escaping non-printable characters. The escape sequence used is simply "\\xx" where "xx" is the two digit hex code for the number. -The inline asm code is simply printed to the machine code .s file when -assembly code is generated. +Note that the assembly string *must* be parseable by LLVM's integrated assembler +(unless it is disabled), even when emitting a ``.s`` file. .. _langref_datalayout: @@ -1804,8 +1848,8 @@ Fast-Math Flags LLVM IR floating-point binary ops (:ref:`fadd `, :ref:`fsub `, :ref:`fmul `, :ref:`fdiv `, -:ref:`frem `) have the following flags that can be set to enable -otherwise unsafe floating point operations +:ref:`frem `, :ref:`fcmp `) have the following flags that can +be set to enable otherwise unsafe floating point operations ``nnan`` No NaNs - Allow optimizations to assume the arguments and result are not @@ -2767,13 +2811,36 @@ Inline Assembler Expressions ---------------------------- LLVM supports inline assembler expressions (as opposed to :ref:`Module-Level -Inline Assembly `) through the use of a special value. This -value represents the inline assembler as a string (containing the -instructions to emit), a list of operand constraints (stored as a -string), a flag that indicates whether or not the inline asm expression -has side effects, and a flag indicating whether the function containing -the asm needs to align its stack conservatively. An example inline -assembler expression is: +Inline Assembly `) through the use of a special value. This value +represents the inline assembler as a template string (containing the +instructions to emit), a list of operand constraints (stored as a string), a +flag that indicates whether or not the inline asm expression has side effects, +and a flag indicating whether the function containing the asm needs to align its +stack conservatively. + +The template string supports argument substitution of the operands using "``$``" +followed by a number, to indicate substitution of the given register/memory +location, as specified by the constraint string. "``${NUM:MODIFIER}``" may also +be used, where ``MODIFIER`` is a target-specific annotation for how to print the +operand (See :ref:`inline-asm-modifiers`). + +A literal "``$``" may be included by using "``$$``" in the template. To include +other special characters into the output, the usual "``\XX``" escapes may be +used, just as in other strings. Note that after template substitution, the +resulting assembly string is parsed by LLVM's integrated assembler unless it is +disabled -- even when emitting a ``.s`` file -- and thus must contain assembly +syntax known to LLVM. + +LLVM's support for inline asm is modeled closely on the requirements of Clang's +GCC-compatible inline-asm support. Thus, the feature-set and the constraint and +modifier codes listed here are similar or identical to those in GCC's inline asm +support. However, to be clear, the syntax of the template and constraint strings +described here is *not* the same as the syntax accepted by GCC and Clang, and, +while most constraint letters are passed through as-is by Clang, some get +translated to other codes when converting from the C source to the LLVM +assembly. + +An example inline assembler expression is: .. code-block:: llvm @@ -2819,6 +2886,596 @@ If multiple keywords appear the '``sideeffect``' keyword must come first, the '``alignstack``' keyword second and the '``inteldialect``' keyword last. +Inline Asm Constraint String +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The constraint list is a comma-separated string, each element containing one or +more constraint codes. + +For each element in the constraint list an appropriate register or memory +operand will be chosen, and it will be made available to assembly template +string expansion as ``$0`` for the first constraint in the list, ``$1`` for the +second, etc. + +There are three different types of constraints, which are distinguished by a +prefix symbol in front of the constraint code: Output, Input, and Clobber. The +constraints must always be given in that order: outputs first, then inputs, then +clobbers. They cannot be intermingled. + +There are also three different categories of constraint codes: + +- Register constraint. This is either a register class, or a fixed physical + register. This kind of constraint will allocate a register, and if necessary, + bitcast the argument or result to the appropriate type. +- Memory constraint. This kind of constraint is for use with an instruction + taking a memory operand. Different constraints allow for different addressing + modes used by the target. +- Immediate value constraint. This kind of constraint is for an integer or other + immediate value which can be rendered directly into an instruction. The + various target-specific constraints allow the selection of a value in the + proper range for the instruction you wish to use it with. + +Output constraints +"""""""""""""""""" + +Output constraints are specified by an "``=``" prefix (e.g. "``=r``"). This +indicates that the assembly will write to this operand, and the operand will +then be made available as a return value of the ``asm`` expression. Output +constraints do not consume an argument from the call instruction. (Except, see +below about indirect outputs). + +Normally, it is expected that no output locations are written to by the assembly +expression until *all* of the inputs have been read. As such, LLVM may assign +the same register to an output and an input. If this is not safe (e.g. if the +assembly contains two instructions, where the first writes to one output, and +the second reads an input and writes to a second output), then the "``&``" +modifier must be used (e.g. "``=&r``") to specify that the output is an +"early-clobber" output. Marking an ouput as "early-clobber" ensures that LLVM +will not use the same register for any inputs (other than an input tied to this +output). + +Input constraints +""""""""""""""""" + +Input constraints do not have a prefix -- just the constraint codes. Each input +constraint will consume one argument from the call instruction. It is not +permitted for the asm to write to any input register or memory location (unless +that input is tied to an output). Note also that multiple inputs may all be +assigned to the same register, if LLVM can determine that they necessarily all +contain the same value. + +Instead of providing a Constraint Code, input constraints may also "tie" +themselves to an output constraint, by providing an integer as the constraint +string. Tied inputs still consume an argument from the call instruction, and +take up a position in the asm template numbering as is usual -- they will simply +be constrained to always use the same register as the output they've been tied +to. For example, a constraint string of "``=r,0``" says to assign a register for +output, and use that register as an input as well (it being the 0'th +constraint). + +It is permitted to tie an input to an "early-clobber" output. In that case, no +*other* input may share the same register as the input tied to the early-clobber +(even when the other input has the same value). + +You may only tie an input to an output which has a register constraint, not a +memory constraint. Only a single input may be tied to an output. + +There is also an "interesting" feature which deserves a bit of explanation: if a +register class constraint allocates a register which is too small for the value +type operand provided as input, the input value will be split into multiple +registers, and all of them passed to the inline asm. + +However, this feature is often not as useful as you might think. + +Firstly, the registers are *not* guaranteed to be consecutive. So, on those +architectures that have instructions which operate on multiple consecutive +instructions, this is not an appropriate way to support them. (e.g. the 32-bit +SparcV8 has a 64-bit load, which instruction takes a single 32-bit register. The +hardware then loads into both the named register, and the next register. This +feature of inline asm would not be useful to support that.) + +A few of the targets provide a template string modifier allowing explicit access +to the second register of a two-register operand (e.g. MIPS ``L``, ``M``, and +``D``). On such an architecture, you can actually access the second allocated +register (yet, still, not any subsequent ones). But, in that case, you're still +probably better off simply splitting the value into two separate operands, for +clarity. (e.g. see the description of the ``A`` constraint on X86, which, +despite existing only for use with this feature, is not really a good idea to +use) + +Indirect inputs and outputs +""""""""""""""""""""""""""" + +Indirect output or input constraints can be specified by the "``*``" modifier +(which goes after the "``=``" in case of an output). This indicates that the asm +will write to or read from the contents of an *address* provided as an input +argument. (Note that in this way, indirect outputs act more like an *input* than +an output: just like an input, they consume an argument of the call expression, +rather than producing a return value. An indirect output constraint is an +"output" only in that the asm is expected to write to the contents of the input +memory location, instead of just read from it). + +This is most typically used for memory constraint, e.g. "``=*m``", to pass the +address of a variable as a value. + +It is also possible to use an indirect *register* constraint, but only on output +(e.g. "``=*r``"). This will cause LLVM to allocate a register for an output +value normally, and then, separately emit a store to the address provided as +input, after the provided inline asm. (It's not clear what value this +functionality provides, compared to writing the store explicitly after the asm +statement, and it can only produce worse code, since it bypasses many +optimization passes. I would recommend not using it.) + + +Clobber constraints +""""""""""""""""""" + +A clobber constraint is indicated by a "``~``" prefix. A clobber does not +consume an input operand, nor generate an output. Clobbers cannot use any of the +general constraint code letters -- they may use only explicit register +constraints, e.g. "``~{eax}``". The one exception is that a clobber string of +"``~{memory}``" indicates that the assembly writes to arbitrary undeclared +memory locations -- not only the memory pointed to by a declared indirect +output. + + +Constraint Codes +"""""""""""""""" +After a potential prefix comes constraint code, or codes. + +A Constraint Code is either a single letter (e.g. "``r``"), a "``^``" character +followed by two letters (e.g. "``^wc``"), or "``{``" register-name "``}``" +(e.g. "``{eax}``"). + +The one and two letter constraint codes are typically chosen to be the same as +GCC's constraint codes. + +A single constraint may include one or more than constraint code in it, leaving +it up to LLVM to choose which one to use. This is included mainly for +compatibility with the translation of GCC inline asm coming from clang. + +There are two ways to specify alternatives, and either or both may be used in an +inline asm constraint list: + +1) Append the codes to each other, making a constraint code set. E.g. "``im``" + or "``{eax}m``". This means "choose any of the options in the set". The + choice of constraint is made independently for each constraint in the + constraint list. + +2) Use "``|``" between constraint code sets, creating alternatives. Every + constraint in the constraint list must have the same number of alternative + sets. With this syntax, the same alternative in *all* of the items in the + constraint list will be chosen together. + +Putting those together, you might have a two operand constraint string like +``"rm|r,ri|rm"``. This indicates that if operand 0 is ``r`` or ``m``, then +operand 1 may be one of ``r`` or ``i``. If operand 0 is ``r``, then operand 1 +may be one of ``r`` or ``m``. But, operand 0 and 1 cannot both be of type m. + +However, the use of either of the alternatives features is *NOT* recommended, as +LLVM is not able to make an intelligent choice about which one to use. (At the +point it currently needs to choose, not enough information is available to do so +in a smart way.) Thus, it simply tries to make a choice that's most likely to +compile, not one that will be optimal performance. (e.g., given "``rm``", it'll +always choose to use memory, not registers). And, if given multiple registers, +or multiple register classes, it will simply choose the first one. (In fact, it +doesn't currently even ensure explicitly specified physical registers are +unique, so specifying multiple physical registers as alternatives, like +``{r11}{r12},{r11}{r12}``, will assign r11 to both operands, not at all what was +intended.) + +Supported Constraint Code List +"""""""""""""""""""""""""""""" + +The constraint codes are, in general, expected to behave the same way they do in +GCC. LLVM's support is often implemented on an 'as-needed' basis, to support C +inline asm code which was supported by GCC. A mismatch in behavior between LLVM +and GCC likely indicates a bug in LLVM. + +Some constraint codes are typically supported by all targets: + +- ``r``: A register in the target's general purpose register class. +- ``m``: A memory address operand. It is target-specific what addressing modes + are supported, typical examples are register, or register + register offset, + or register + immediate offset (of some target-specific size). +- ``i``: An integer constant (of target-specific width). Allows either a simple + immediate, or a relocatable value. +- ``n``: An integer constant -- *not* including relocatable values. +- ``s``: An integer constant, but allowing *only* relocatable values. +- ``X``: Allows an operand of any kind, no constraint whatsoever. Typically + useful to pass a label for an asm branch or call. + + .. FIXME: but that surely isn't actually okay to jump out of an asm + block without telling llvm about the control transfer???) + +- ``{register-name}``: Requires exactly the named physical register. + +Other constraints are target-specific: + +AArch64: + +- ``z``: An immediate integer 0. Outputs ``WZR`` or ``XZR``, as appropriate. +- ``I``: An immediate integer valid for an ``ADD`` or ``SUB`` instruction, + i.e. 0 to 4095 with optional shift by 12. +- ``J``: An immediate integer that, when negated, is valid for an ``ADD`` or + ``SUB`` instruction, i.e. -1 to -4095 with optional left shift by 12. +- ``K``: An immediate integer that is valid for the 'bitmask immediate 32' of a + logical instruction like ``AND``, ``EOR``, or ``ORR`` with a 32-bit register. +- ``L``: An immediate integer that is valid for the 'bitmask immediate 64' of a + logical instruction like ``AND``, ``EOR``, or ``ORR`` with a 64-bit register. +- ``M``: An immediate integer for use with the ``MOV`` assembly alias on a + 32-bit register. This is a superset of ``K``: in addition to the bitmask + immediate, also allows immediate integers which can be loaded with a single + ``MOVZ`` or ``MOVL`` instruction. +- ``N``: An immediate integer for use with the ``MOV`` assembly alias on a + 64-bit register. This is a superset of ``L``. +- ``Q``: Memory address operand must be in a single register (no + offsets). (However, LLVM currently does this for the ``m`` constraint as + well.) +- ``r``: A 32 or 64-bit integer register (W* or X*). +- ``w``: A 32, 64, or 128-bit floating-point/SIMD register. +- ``x``: A lower 128-bit floating-point/SIMD register (``V0`` to ``V15``). + +AMDGPU: + +- ``r``: A 32 or 64-bit integer register. +- ``[0-9]v``: The 32-bit VGPR register, number 0-9. +- ``[0-9]s``: The 32-bit SGPR register, number 0-9. + + +All ARM modes: + +- ``Q``, ``Um``, ``Un``, ``Uq``, ``Us``, ``Ut``, ``Uv``, ``Uy``: Memory address + operand. Treated the same as operand ``m``, at the moment. + +ARM and ARM's Thumb2 mode: + +- ``j``: An immediate integer between 0 and 65535 (valid for ``MOVW``) +- ``I``: An immediate integer valid for a data-processing instruction. +- ``J``: An immediate integer between -4095 and 4095. +- ``K``: An immediate integer whose bitwise inverse is valid for a + data-processing instruction. (Can be used with template modifier "``B``" to + print the inverted value). +- ``L``: An immediate integer whose negation is valid for a data-processing + instruction. (Can be used with template modifier "``n``" to print the negated + value). +- ``M``: A power of two or a integer between 0 and 32. +- ``N``: Invalid immediate constraint. +- ``O``: Invalid immediate constraint. +- ``r``: A general-purpose 32-bit integer register (``r0-r15``). +- ``l``: In Thumb2 mode, low 32-bit GPR registers (``r0-r7``). In ARM mode, same + as ``r``. +- ``h``: In Thumb2 mode, a high 32-bit GPR register (``r8-r15``). In ARM mode, + invalid. +- ``w``: A 32, 64, or 128-bit floating-point/SIMD register: ``s0-s31``, + ``d0-d31``, or ``q0-q15``. +- ``x``: A 32, 64, or 128-bit floating-point/SIMD register: ``s0-s15``, + ``d0-d7``, or ``q0-q3``. +- ``t``: A floating-point/SIMD register, only supports 32-bit values: + ``s0-s31``. + +ARM's Thumb1 mode: + +- ``I``: An immediate integer between 0 and 255. +- ``J``: An immediate integer between -255 and -1. +- ``K``: An immediate integer between 0 and 255, with optional left-shift by + some amount. +- ``L``: An immediate integer between -7 and 7. +- ``M``: An immediate integer which is a multiple of 4 between 0 and 1020. +- ``N``: An immediate integer between 0 and 31. +- ``O``: An immediate integer which is a multiple of 4 between -508 and 508. +- ``r``: A low 32-bit GPR register (``r0-r7``). +- ``l``: A low 32-bit GPR register (``r0-r7``). +- ``h``: A high GPR register (``r0-r7``). +- ``w``: A 32, 64, or 128-bit floating-point/SIMD register: ``s0-s31``, + ``d0-d31``, or ``q0-q15``. +- ``x``: A 32, 64, or 128-bit floating-point/SIMD register: ``s0-s15``, + ``d0-d7``, or ``q0-q3``. +- ``t``: A floating-point/SIMD register, only supports 32-bit values: + ``s0-s31``. + + +Hexagon: + +- ``o``, ``v``: A memory address operand, treated the same as constraint ``m``, + at the moment. +- ``r``: A 32 or 64-bit register. + +MSP430: + +- ``r``: An 8 or 16-bit register. + +MIPS: + +- ``I``: An immediate signed 16-bit integer. +- ``J``: An immediate integer zero. +- ``K``: An immediate unsigned 16-bit integer. +- ``L``: An immediate 32-bit integer, where the lower 16 bits are 0. +- ``N``: An immediate integer between -65535 and -1. +- ``O``: An immediate signed 15-bit integer. +- ``P``: An immediate integer between 1 and 65535. +- ``m``: A memory address operand. In MIPS-SE mode, allows a base address + register plus 16-bit immediate offset. In MIPS mode, just a base register. +- ``R``: A memory address operand. In MIPS-SE mode, allows a base address + register plus a 9-bit signed offset. In MIPS mode, the same as constraint + ``m``. +- ``ZC``: A memory address operand, suitable for use in a ``pref``, ``ll``, or + ``sc`` instruction on the given subtarget (details vary). +- ``r``, ``d``, ``y``: A 32 or 64-bit GPR register. +- ``f``: A 32 or 64-bit FPU register (``F0-F31``), or a 128-bit MSA register + (``W0-W31``). In the case of MSA registers, it is recommended to use the ``w`` + argument modifier for compatibility with GCC. +- ``c``: A 32-bit or 64-bit GPR register suitable for indirect jump (always + ``25``). +- ``l``: The ``lo`` register, 32 or 64-bit. +- ``x``: Invalid. + +NVPTX: + +- ``b``: A 1-bit integer register. +- ``c`` or ``h``: A 16-bit integer register. +- ``r``: A 32-bit integer register. +- ``l`` or ``N``: A 64-bit integer register. +- ``f``: A 32-bit float register. +- ``d``: A 64-bit float register. + + +PowerPC: + +- ``I``: An immediate signed 16-bit integer. +- ``J``: An immediate unsigned 16-bit integer, shifted left 16 bits. +- ``K``: An immediate unsigned 16-bit integer. +- ``L``: An immediate signed 16-bit integer, shifted left 16 bits. +- ``M``: An immediate integer greater than 31. +- ``N``: An immediate integer that is an exact power of 2. +- ``O``: The immediate integer constant 0. +- ``P``: An immediate integer constant whose negation is a signed 16-bit + constant. +- ``es``, ``o``, ``Q``, ``Z``, ``Zy``: A memory address operand, currently + treated the same as ``m``. +- ``r``: A 32 or 64-bit integer register. +- ``b``: A 32 or 64-bit integer register, excluding ``R0`` (that is: + ``R1-R31``). +- ``f``: A 32 or 64-bit float register (``F0-F31``), or when QPX is enabled, a + 128 or 256-bit QPX register (``Q0-Q31``; aliases the ``F`` registers). +- ``v``: For ``4 x f32`` or ``4 x f64`` types, when QPX is enabled, a + 128 or 256-bit QPX register (``Q0-Q31``), otherwise a 128-bit + altivec vector register (``V0-V31``). + + .. FIXME: is this a bug that v accepts QPX registers? I think this + is supposed to only use the altivec vector registers? + +- ``y``: Condition register (``CR0-CR7``). +- ``wc``: An individual CR bit in a CR register. +- ``wa``, ``wd``, ``wf``: Any 128-bit VSX vector register, from the full VSX + register set (overlapping both the floating-point and vector register files). +- ``ws``: A 32 or 64-bit floating point register, from the full VSX register + set. + +Sparc: + +- ``I``: An immediate 13-bit signed integer. +- ``r``: A 32-bit integer register. + +SystemZ: + +- ``I``: An immediate unsigned 8-bit integer. +- ``J``: An immediate unsigned 12-bit integer. +- ``K``: An immediate signed 16-bit integer. +- ``L``: An immediate signed 20-bit integer. +- ``M``: An immediate integer 0x7fffffff. +- ``Q``, ``R``, ``S``, ``T``: A memory address operand, treated the same as + ``m``, at the moment. +- ``r`` or ``d``: A 32, 64, or 128-bit integer register. +- ``a``: A 32, 64, or 128-bit integer address register (excludes R0, which in an + address context evaluates as zero). +- ``h``: A 32-bit value in the high part of a 64bit data register + (LLVM-specific) +- ``f``: A 32, 64, or 128-bit floating point register. + +X86: + +- ``I``: An immediate integer between 0 and 31. +- ``J``: An immediate integer between 0 and 64. +- ``K``: An immediate signed 8-bit integer. +- ``L``: An immediate integer, 0xff or 0xffff or (in 64-bit mode only) + 0xffffffff. +- ``M``: An immediate integer between 0 and 3. +- ``N``: An immediate unsigned 8-bit integer. +- ``O``: An immediate integer between 0 and 127. +- ``e``: An immediate 32-bit signed integer. +- ``Z``: An immediate 32-bit unsigned integer. +- ``o``, ``v``: Treated the same as ``m``, at the moment. +- ``q``: An 8, 16, 32, or 64-bit register which can be accessed as an 8-bit + ``l`` integer register. On X86-32, this is the ``a``, ``b``, ``c``, and ``d`` + registers, and on X86-64, it is all of the integer registers. +- ``Q``: An 8, 16, 32, or 64-bit register which can be accessed as an 8-bit + ``h`` integer register. This is the ``a``, ``b``, ``c``, and ``d`` registers. +- ``r`` or ``l``: An 8, 16, 32, or 64-bit integer register. +- ``R``: An 8, 16, 32, or 64-bit "legacy" integer register -- one which has + existed since i386, and can be accessed without the REX prefix. +- ``f``: A 32, 64, or 80-bit '387 FPU stack pseudo-register. +- ``y``: A 64-bit MMX register, if MMX is enabled. +- ``x``: If SSE is enabled: a 32 or 64-bit scalar operand, or 128-bit vector + operand in a SSE register. If AVX is also enabled, can also be a 256-bit + vector operand in an AVX register. If AVX-512 is also enabled, can also be a + 512-bit vector operand in an AVX512 register, Otherwise, an error. +- ``Y``: The same as ``x``, if *SSE2* is enabled, otherwise an error. +- ``A``: Special case: allocates EAX first, then EDX, for a single operand (in + 32-bit mode, a 64-bit integer operand will get split into two registers). It + is not recommended to use this constraint, as in 64-bit mode, the 64-bit + operand will get allocated only to RAX -- if two 32-bit operands are needed, + you're better off splitting it yourself, before passing it to the asm + statement. + +XCore: + +- ``r``: A 32-bit integer register. + + +.. _inline-asm-modifiers: + +Asm template argument modifiers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In the asm template string, modifiers can be used on the operand reference, like +"``${0:n}``". + +The modifiers are, in general, expected to behave the same way they do in +GCC. LLVM's support is often implemented on an 'as-needed' basis, to support C +inline asm code which was supported by GCC. A mismatch in behavior between LLVM +and GCC likely indicates a bug in LLVM. + +Target-independent: + +- ``c``: Print an immediate integer constant unadorned, without + the target-specific immediate punctuation (e.g. no ``$`` prefix). +- ``n``: Negate and print immediate integer constant unadorned, without the + target-specific immediate punctuation (e.g. no ``$`` prefix). +- ``l``: Print as an unadorned label, without the target-specific label + punctuation (e.g. no ``$`` prefix). + +AArch64: + +- ``w``: Print a GPR register with a ``w*`` name instead of ``x*`` name. E.g., + instead of ``x30``, print ``w30``. +- ``x``: Print a GPR register with a ``x*`` name. (this is the default, anyhow). +- ``b``, ``h``, ``s``, ``d``, ``q``: Print a floating-point/SIMD register with a + ``b*``, ``h*``, ``s*``, ``d*``, or ``q*`` name, rather than the default of + ``v*``. + +AMDGPU: + +- ``r``: No effect. + +ARM: + +- ``a``: Print an operand as an address (with ``[`` and ``]`` surrounding a + register). +- ``P``: No effect. +- ``q``: No effect. +- ``y``: Print a VFP single-precision register as an indexed double (e.g. print + as ``d4[1]`` instead of ``s9``) +- ``B``: Bitwise invert and print an immediate integer constant without ``#`` + prefix. +- ``L``: Print the low 16-bits of an immediate integer constant. +- ``M``: Print as a register set suitable for ldm/stm. Also prints *all* + register operands subsequent to the specified one (!), so use carefully. +- ``Q``: Print the low-order register of a register-pair, or the low-order + register of a two-register operand. +- ``R``: Print the high-order register of a register-pair, or the high-order + register of a two-register operand. +- ``H``: Print the second register of a register-pair. (On a big-endian system, + ``H`` is equivalent to ``Q``, and on little-endian system, ``H`` is equivalent + to ``R``.) + + .. FIXME: H doesn't currently support printing the second register + of a two-register operand. + +- ``e``: Print the low doubleword register of a NEON quad register. +- ``f``: Print the high doubleword register of a NEON quad register. +- ``m``: Print the base register of a memory operand without the ``[`` and ``]`` + adornment. + +Hexagon: + +- ``L``: Print the second register of a two-register operand. Requires that it + has been allocated consecutively to the first. + + .. FIXME: why is it restricted to consecutive ones? And there's + nothing that ensures that happens, is there? + +- ``I``: Print the letter 'i' if the operand is an integer constant, otherwise + nothing. Used to print 'addi' vs 'add' instructions. + +MSP430: + +No additional modifiers. + +MIPS: + +- ``X``: Print an immediate integer as hexadecimal +- ``x``: Print the low 16 bits of an immediate integer as hexadecimal. +- ``d``: Print an immediate integer as decimal. +- ``m``: Subtract one and print an immediate integer as decimal. +- ``z``: Print $0 if an immediate zero, otherwise print normally. +- ``L``: Print the low-order register of a two-register operand, or prints the + address of the low-order word of a double-word memory operand. + + .. FIXME: L seems to be missing memory operand support. + +- ``M``: Print the high-order register of a two-register operand, or prints the + address of the high-order word of a double-word memory operand. + + .. FIXME: M seems to be missing memory operand support. + +- ``D``: Print the second register of a two-register operand, or prints the + second word of a double-word memory operand. (On a big-endian system, ``D`` is + equivalent to ``L``, and on little-endian system, ``D`` is equivalent to + ``M``.) +- ``w``: No effect. Provided for compatibility with GCC which requires this + modifier in order to print MSA registers (``W0-W31``) with the ``f`` + constraint. + +NVPTX: + +- ``r``: No effect. + +PowerPC: + +- ``L``: Print the second register of a two-register operand. Requires that it + has been allocated consecutively to the first. + + .. FIXME: why is it restricted to consecutive ones? And there's + nothing that ensures that happens, is there? + +- ``I``: Print the letter 'i' if the operand is an integer constant, otherwise + nothing. Used to print 'addi' vs 'add' instructions. +- ``y``: For a memory operand, prints formatter for a two-register X-form + instruction. (Currently always prints ``r0,OPERAND``). +- ``U``: Prints 'u' if the memory operand is an update form, and nothing + otherwise. (NOTE: LLVM does not support update form, so this will currently + always print nothing) +- ``X``: Prints 'x' if the memory operand is an indexed form. (NOTE: LLVM does + not support indexed form, so this will currently always print nothing) + +Sparc: + +- ``r``: No effect. + +SystemZ: + +SystemZ implements only ``n``, and does *not* support any of the other +target-independent modifiers. + +X86: + +- ``c``: Print an unadorned integer or symbol name. (The latter is + target-specific behavior for this typically target-independent modifier). +- ``A``: Print a register name with a '``*``' before it. +- ``b``: Print an 8-bit register name (e.g. ``al``); do nothing on a memory + operand. +- ``h``: Print the upper 8-bit register name (e.g. ``ah``); do nothing on a + memory operand. +- ``w``: Print the 16-bit register name (e.g. ``ax``); do nothing on a memory + operand. +- ``k``: Print the 32-bit register name (e.g. ``eax``); do nothing on a memory + operand. +- ``q``: Print the 64-bit register name (e.g. ``rax``), if 64-bit registers are + available, otherwise the 32-bit register name; do nothing on a memory operand. +- ``n``: Negate and print an unadorned integer, or, for operands other than an + immediate integer (e.g. a relocatable symbol expression), print a '-' before + the operand. (The behavior for relocatable symbol expressions is a + target-specific behavior for this typically target-independent modifier) +- ``H``: Print a memory reference with additional offset +8. +- ``P``: Print a memory reference or operand for use as the argument of a call + instruction. (E.g. omit ``(rip)``, even though it's PC-relative.) + +XCore: + +No additional modifiers. + + Inline Asm Metadata ^^^^^^^^^^^^^^^^^^^ @@ -2922,12 +3579,12 @@ order. These aren't inherently debug info centric, but currently all the specialized metadata nodes are related to debug info. -.. _MDCompileUnit: +.. _DICompileUnit: -MDCompileUnit +DICompileUnit """"""""""""" -``MDCompileUnit`` nodes represent a compile unit. The ``enums:``, +``DICompileUnit`` nodes represent a compile unit. The ``enums:``, ``retainedTypes:``, ``subprograms:``, ``globals:`` and ``imports:`` fields are tuples containing the debug info to be emitted along with the compile unit, regardless of code optimizations (some nodes are only emitted if there are @@ -2935,7 +3592,7 @@ references to them from instructions). .. code-block:: llvm - !0 = !MDCompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", + !0 = !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: true, flags: "-O2", runtimeVersion: 2, splitDebugFilename: "abc.debug", emissionKind: 1, enums: !2, retainedTypes: !3, subprograms: !4, @@ -2947,33 +3604,33 @@ These descriptors are collected by a named metadata ``!llvm.dbg.cu``. They keep track of subprograms, global variables, type information, and imported entities (declarations and namespaces). -.. _MDFile: +.. _DIFile: -MDFile +DIFile """""" -``MDFile`` nodes represent files. The ``filename:`` can include slashes. +``DIFile`` nodes represent files. The ``filename:`` can include slashes. .. code-block:: llvm - !0 = !MDFile(filename: "path/to/file", directory: "/path/to/dir") + !0 = !DIFile(filename: "path/to/file", directory: "/path/to/dir") Files are sometimes used in ``scope:`` fields, and are the only valid target for ``file:`` fields. -.. _MDLocation: +.. _DIBasicType: -MDBasicType +DIBasicType """"""""""" -``MDBasicType`` nodes represent primitive types, such as ``int``, ``bool`` and +``DIBasicType`` nodes represent primitive types, such as ``int``, ``bool`` and ``float``. ``tag:`` defaults to ``DW_TAG_base_type``. .. code-block:: llvm - !0 = !MDBasicType(name: "unsigned char", size: 8, align: 8, + !0 = !DIBasicType(name: "unsigned char", size: 8, align: 8, encoding: DW_ATE_unsigned_char) - !1 = !MDBasicType(tag: DW_TAG_unspecified_type, name: "decltype(nullptr)") + !1 = !DIBasicType(tag: DW_TAG_unspecified_type, name: "decltype(nullptr)") The ``encoding:`` describes the details of the type. Usually it's one of the following: @@ -2988,12 +3645,12 @@ following: DW_ATE_unsigned = 7 DW_ATE_unsigned_char = 8 -.. _MDSubroutineType: +.. _DISubroutineType: -MDSubroutineType +DISubroutineType """""""""""""""" -``MDSubroutineType`` nodes represent subroutine types. Their ``types:`` field +``DISubroutineType`` nodes represent subroutine types. Their ``types:`` field refers to a tuple; the first operand is the return type, while the rest are the types of the formal arguments in order. If the first operand is ``null``, that represents a function with no return value (such as ``void foo() {}`` in C++). @@ -3002,21 +3659,21 @@ represents a function with no return value (such as ``void foo() {}`` in C++). !0 = !BasicType(name: "int", size: 32, align: 32, DW_ATE_signed) !1 = !BasicType(name: "char", size: 8, align: 8, DW_ATE_signed_char) - !2 = !MDSubroutineType(types: !{null, !0, !1}) ; void (int, char) + !2 = !DISubroutineType(types: !{null, !0, !1}) ; void (int, char) -.. _MDDerivedType: +.. _DIDerivedType: -MDDerivedType +DIDerivedType """"""""""""" -``MDDerivedType`` nodes represent types derived from other types, such as +``DIDerivedType`` nodes represent types derived from other types, such as qualified types. .. code-block:: llvm - !0 = !MDBasicType(name: "unsigned char", size: 8, align: 8, + !0 = !DIBasicType(name: "unsigned char", size: 8, align: 8, encoding: DW_ATE_unsigned_char) - !1 = !MDDerivedType(tag: DW_TAG_pointer_type, baseType: !0, size: 32, + !1 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !0, size: 32, align: 32) The following ``tag:`` values are valid: @@ -3034,7 +3691,7 @@ The following ``tag:`` values are valid: DW_TAG_restrict_type = 55 ``DW_TAG_member`` is used to define a member of a :ref:`composite type -` or :ref:`subprogram `. The type of the member +` or :ref:`subprogram `. The type of the member is the ``baseType:``. The ``offset:`` is the member's bit offset. ``DW_TAG_formal_parameter`` is used to define a member which is a formal argument of a subprogram. @@ -3047,12 +3704,12 @@ argument of a subprogram. Note that the ``void *`` type is expressed as a type derived from NULL. -.. _MDCompositeType: +.. _DICompositeType: -MDCompositeType +DICompositeType """"""""""""""" -``MDCompositeType`` nodes represent types composed of other types, like +``DICompositeType`` nodes represent types composed of other types, like structures and unions. ``elements:`` points to a tuple of the composed types. If the source language supports ODR, the ``identifier:`` field gives the unique @@ -3062,10 +3719,10 @@ can refer to composite types indirectly via a :ref:`metadata string .. code-block:: llvm - !0 = !MDEnumerator(name: "SixKind", value: 7) - !1 = !MDEnumerator(name: "SevenKind", value: 7) - !2 = !MDEnumerator(name: "NegEightKind", value: -8) - !3 = !MDCompositeType(tag: DW_TAG_enumeration_type, name: "Enum", file: !12, + !0 = !DIEnumerator(name: "SixKind", value: 7) + !1 = !DIEnumerator(name: "SevenKind", value: 7) + !2 = !DIEnumerator(name: "NegEightKind", value: -8) + !3 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Enum", file: !12, line: 2, size: 32, align: 32, identifier: "_M4Enum", elements: !{!0, !1, !2}) @@ -3083,108 +3740,108 @@ The following ``tag:`` values are valid: For ``DW_TAG_array_type``, the ``elements:`` should be :ref:`subrange -descriptors `, each representing the range of subscripts at that +descriptors `, each representing the range of subscripts at that level of indexing. The ``DIFlagVector`` flag to ``flags:`` indicates that an array type is a native packed vector. For ``DW_TAG_enumeration_type``, the ``elements:`` should be :ref:`enumerator -descriptors `, each representing the definition of an enumeration +descriptors `, each representing the definition of an enumeration value for the set. All enumeration type descriptors are collected in the -``enums:`` field of the :ref:`compile unit `. +``enums:`` field of the :ref:`compile unit `. For ``DW_TAG_structure_type``, ``DW_TAG_class_type``, and ``DW_TAG_union_type``, the ``elements:`` should be :ref:`derived types -` with ``tag: DW_TAG_member`` or ``tag: DW_TAG_inheritance``. +` with ``tag: DW_TAG_member`` or ``tag: DW_TAG_inheritance``. -.. _MDSubrange: +.. _DISubrange: -MDSubrange +DISubrange """""""""" -``MDSubrange`` nodes are the elements for ``DW_TAG_array_type`` variants of -:ref:`MDCompositeType`. ``count: -1`` indicates an empty array. +``DISubrange`` nodes are the elements for ``DW_TAG_array_type`` variants of +:ref:`DICompositeType`. ``count: -1`` indicates an empty array. .. code-block:: llvm - !0 = !MDSubrange(count: 5, lowerBound: 0) ; array counting from 0 - !1 = !MDSubrange(count: 5, lowerBound: 1) ; array counting from 1 - !2 = !MDSubrange(count: -1) ; empty array. + !0 = !DISubrange(count: 5, lowerBound: 0) ; array counting from 0 + !1 = !DISubrange(count: 5, lowerBound: 1) ; array counting from 1 + !2 = !DISubrange(count: -1) ; empty array. -.. _MDEnumerator: +.. _DIEnumerator: -MDEnumerator +DIEnumerator """""""""""" -``MDEnumerator`` nodes are the elements for ``DW_TAG_enumeration_type`` -variants of :ref:`MDCompositeType`. +``DIEnumerator`` nodes are the elements for ``DW_TAG_enumeration_type`` +variants of :ref:`DICompositeType`. .. code-block:: llvm - !0 = !MDEnumerator(name: "SixKind", value: 7) - !1 = !MDEnumerator(name: "SevenKind", value: 7) - !2 = !MDEnumerator(name: "NegEightKind", value: -8) + !0 = !DIEnumerator(name: "SixKind", value: 7) + !1 = !DIEnumerator(name: "SevenKind", value: 7) + !2 = !DIEnumerator(name: "NegEightKind", value: -8) -MDTemplateTypeParameter +DITemplateTypeParameter """"""""""""""""""""""" -``MDTemplateTypeParameter`` nodes represent type parameters to generic source -language constructs. They are used (optionally) in :ref:`MDCompositeType` and -:ref:`MDSubprogram` ``templateParams:`` fields. +``DITemplateTypeParameter`` nodes represent type parameters to generic source +language constructs. They are used (optionally) in :ref:`DICompositeType` and +:ref:`DISubprogram` ``templateParams:`` fields. .. code-block:: llvm - !0 = !MDTemplateTypeParameter(name: "Ty", type: !1) + !0 = !DITemplateTypeParameter(name: "Ty", type: !1) -MDTemplateValueParameter +DITemplateValueParameter """""""""""""""""""""""" -``MDTemplateValueParameter`` nodes represent value parameters to generic source +``DITemplateValueParameter`` nodes represent value parameters to generic source language constructs. ``tag:`` defaults to ``DW_TAG_template_value_parameter``, but if specified can also be set to ``DW_TAG_GNU_template_template_param`` or ``DW_TAG_GNU_template_param_pack``. They are used (optionally) in -:ref:`MDCompositeType` and :ref:`MDSubprogram` ``templateParams:`` fields. +:ref:`DICompositeType` and :ref:`DISubprogram` ``templateParams:`` fields. .. code-block:: llvm - !0 = !MDTemplateValueParameter(name: "Ty", type: !1, value: i32 7) + !0 = !DITemplateValueParameter(name: "Ty", type: !1, value: i32 7) -MDNamespace +DINamespace """"""""""" -``MDNamespace`` nodes represent namespaces in the source language. +``DINamespace`` nodes represent namespaces in the source language. .. code-block:: llvm - !0 = !MDNamespace(name: "myawesomeproject", scope: !1, file: !2, line: 7) + !0 = !DINamespace(name: "myawesomeproject", scope: !1, file: !2, line: 7) -MDGlobalVariable +DIGlobalVariable """""""""""""""" -``MDGlobalVariable`` nodes represent global variables in the source language. +``DIGlobalVariable`` nodes represent global variables in the source language. .. code-block:: llvm - !0 = !MDGlobalVariable(name: "foo", linkageName: "foo", scope: !1, + !0 = !DIGlobalVariable(name: "foo", linkageName: "foo", scope: !1, file: !2, line: 7, type: !3, isLocal: true, isDefinition: false, variable: i32* @foo, declaration: !4) All global variables should be referenced by the `globals:` field of a -:ref:`compile unit `. +:ref:`compile unit `. -.. _MDSubprogram: +.. _DISubprogram: -MDSubprogram +DISubprogram """""""""""" -``MDSubprogram`` nodes represent functions from the source language. The -``variables:`` field points at :ref:`variables ` that must be +``DISubprogram`` nodes represent functions from the source language. The +``variables:`` field points at :ref:`variables ` that must be retained, even if their IR counterparts are optimized out of the IR. The -``type:`` field must point at an :ref:`MDSubroutineType`. +``type:`` field must point at an :ref:`DISubroutineType`. .. code-block:: llvm - !0 = !MDSubprogram(name: "foo", linkageName: "_Zfoov", scope: !1, + !0 = !DISubprogram(name: "foo", linkageName: "_Zfoov", scope: !1, file: !2, line: 7, type: !3, isLocal: true, isDefinition: false, scopeLine: 8, containingType: !4, virtuality: DW_VIRTUALITY_pure_virtual, virtualIndex: 10, @@ -3192,76 +3849,78 @@ retained, even if their IR counterparts are optimized out of the IR. The function: void ()* @_Z3foov, templateParams: !5, declaration: !6, variables: !7) -.. _MDLexicalBlock: +.. _DILexicalBlock: -MDLexicalBlock +DILexicalBlock """""""""""""" -``MDLexicalBlock`` nodes describe nested blocks within a :ref:`subprogram -`. The line number and column numbers are used to dinstinguish +``DILexicalBlock`` nodes describe nested blocks within a :ref:`subprogram +`. The line number and column numbers are used to dinstinguish two lexical blocks at same depth. They are valid targets for ``scope:`` fields. .. code-block:: llvm - !0 = distinct !MDLexicalBlock(scope: !1, file: !2, line: 7, column: 35) + !0 = distinct !DILexicalBlock(scope: !1, file: !2, line: 7, column: 35) Usually lexical blocks are ``distinct`` to prevent node merging based on operands. -.. _MDLexicalBlockFile: +.. _DILexicalBlockFile: -MDLexicalBlockFile +DILexicalBlockFile """""""""""""""""" -``MDLexicalBlockFile`` nodes are used to discriminate between sections of a -:ref:`lexical block `. The ``file:`` field can be changed to +``DILexicalBlockFile`` nodes are used to discriminate between sections of a +:ref:`lexical block `. The ``file:`` field can be changed to indicate textual inclusion, or the ``discriminator:`` field can be used to discriminate between control flow within a single block in the source language. .. code-block:: llvm - !0 = !MDLexicalBlock(scope: !3, file: !4, line: 7, column: 35) - !1 = !MDLexicalBlockFile(scope: !0, file: !4, discriminator: 0) - !2 = !MDLexicalBlockFile(scope: !0, file: !4, discriminator: 1) + !0 = !DILexicalBlock(scope: !3, file: !4, line: 7, column: 35) + !1 = !DILexicalBlockFile(scope: !0, file: !4, discriminator: 0) + !2 = !DILexicalBlockFile(scope: !0, file: !4, discriminator: 1) + +.. _DILocation: -MDLocation +DILocation """""""""" -``MDLocation`` nodes represent source debug locations. The ``scope:`` field is -mandatory, and points at an :ref:`MDLexicalBlockFile`, an -:ref:`MDLexicalBlock`, or an :ref:`MDSubprogram`. +``DILocation`` nodes represent source debug locations. The ``scope:`` field is +mandatory, and points at an :ref:`DILexicalBlockFile`, an +:ref:`DILexicalBlock`, or an :ref:`DISubprogram`. .. code-block:: llvm - !0 = !MDLocation(line: 2900, column: 42, scope: !1, inlinedAt: !2) + !0 = !DILocation(line: 2900, column: 42, scope: !1, inlinedAt: !2) -.. _MDLocalVariable: +.. _DILocalVariable: -MDLocalVariable +DILocalVariable """"""""""""""" -``MDLocalVariable`` nodes represent local variables in the source language. +``DILocalVariable`` nodes represent local variables in the source language. Instead of ``DW_TAG_variable``, they use LLVM-specific fake tags to discriminate between local variables (``DW_TAG_auto_variable``) and subprogram arguments (``DW_TAG_arg_variable``). In the latter case, the ``arg:`` field specifies the argument position, and this variable will be included in the -``variables:`` field of its :ref:`MDSubprogram`. +``variables:`` field of its :ref:`DISubprogram`. .. code-block:: llvm - !0 = !MDLocalVariable(tag: DW_TAG_arg_variable, name: "this", arg: 0, + !0 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "this", arg: 1, scope: !3, file: !2, line: 7, type: !3, flags: DIFlagArtificial) - !1 = !MDLocalVariable(tag: DW_TAG_arg_variable, name: "x", arg: 1, + !1 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "x", arg: 2, scope: !4, file: !2, line: 7, type: !3) - !1 = !MDLocalVariable(tag: DW_TAG_auto_variable, name: "y", + !2 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "y", scope: !5, file: !2, line: 7, type: !3) -MDExpression +DIExpression """""""""""" -``MDExpression`` nodes represent DWARF expression sequences. They are used in +``DIExpression`` nodes represent DWARF expression sequences. They are used in :ref:`debug intrinsics` (such as ``llvm.dbg.declare``) to describe how the referenced LLVM variable relates to the source language variable. @@ -3275,30 +3934,30 @@ The current supported vocabulary is limited: .. code-block:: llvm - !0 = !MDExpression(DW_OP_deref) - !1 = !MDExpression(DW_OP_plus, 3) - !2 = !MDExpression(DW_OP_bit_piece, 3, 7) - !3 = !MDExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_bit_piece, 3, 7) + !0 = !DIExpression(DW_OP_deref) + !1 = !DIExpression(DW_OP_plus, 3) + !2 = !DIExpression(DW_OP_bit_piece, 3, 7) + !3 = !DIExpression(DW_OP_deref, DW_OP_plus, 3, DW_OP_bit_piece, 3, 7) -MDObjCProperty +DIObjCProperty """""""""""""" -``MDObjCProperty`` nodes represent Objective-C property nodes. +``DIObjCProperty`` nodes represent Objective-C property nodes. .. code-block:: llvm - !3 = !MDObjCProperty(name: "foo", file: !1, line: 7, setter: "setFoo", + !3 = !DIObjCProperty(name: "foo", file: !1, line: 7, setter: "setFoo", getter: "getFoo", attributes: 7, type: !2) -MDImportedEntity +DIImportedEntity """""""""""""""" -``MDImportedEntity`` nodes represent entities (such as modules) imported into a +``DIImportedEntity`` nodes represent entities (such as modules) imported into a compile unit. .. code-block:: llvm - !2 = !MDImportedEntity(tag: DW_TAG_imported_module, name: "foo", scope: !0, + !2 = !DIImportedEntity(tag: DW_TAG_imported_module, name: "foo", scope: !0, entity: !1, line: 7) '``tbaa``' Metadata @@ -3423,7 +4082,7 @@ For example, %2 = load float, float* %c, align 4, !alias.scope !5 store float %2, float* %arrayidx.i2, align 4, !noalias !6 - ; These two instructions don't alias (for domain !0, the set of scopes in + ; These two instructions may alias (for domain !0, the set of scopes in ; the !noalias list is not a superset of, or equal to, the scopes in the ; !alias.scope list): %2 = load float, float* %c, align 4, !alias.scope !6 @@ -3607,7 +4266,7 @@ will be partially unrolled. '``llvm.loop.unroll.disable``' Metadata ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -This metadata either disables loop unrolling. The metadata has a single operand +This metadata disables loop unrolling. The metadata has a single operand which is the string ``llvm.loop.unroll.disable``. For example: .. code-block:: llvm @@ -3617,7 +4276,7 @@ which is the string ``llvm.loop.unroll.disable``. For example: '``llvm.loop.unroll.runtime.disable``' Metadata ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -This metadata either disables runtime loop unrolling. The metadata has a single +This metadata disables runtime loop unrolling. The metadata has a single operand which is the string ``llvm.loop.unroll.runtime.disable``. For example: .. code-block:: llvm @@ -3627,8 +4286,8 @@ operand which is the string ``llvm.loop.unroll.runtime.disable``. For example: '``llvm.loop.unroll.full``' Metadata ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -This metadata either suggests that the loop should be unrolled fully. The -metadata has a single operand which is the string ``llvm.loop.unroll.disable``. +This metadata suggests that the loop should be unrolled fully. The +metadata has a single operand which is the string ``llvm.loop.unroll.full``. For example: .. code-block:: llvm @@ -4082,7 +4741,12 @@ control flow, not values (the one exception being the The terminator instructions are: ':ref:`ret `', ':ref:`br `', ':ref:`switch `', ':ref:`indirectbr `', ':ref:`invoke `', -':ref:`resume `', and ':ref:`unreachable `'. +':ref:`resume `', ':ref:`catchpad `', +':ref:`catchendpad `', +':ref:`catchret `', +':ref:`cleanupret `', +':ref:`terminatepad `', +and ':ref:`unreachable `'. .. _i_ret: @@ -4436,6 +5100,301 @@ Example: resume { i8*, i32 } %exn +.. _i_catchpad: + +'``catchpad``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = catchpad [*] + to label unwind label + +Overview: +""""""""" + +The '``catchpad``' instruction is used by `LLVM's exception handling +system `_ to specify that a basic block +is a catch block --- one where a personality routine attempts to transfer +control to catch an exception. +The ``args`` correspond to whatever information the personality +routine requires to know if this is an appropriate place to catch the +exception. Control is tranfered to the ``exception`` label if the +``catchpad`` is not an appropriate handler for the in-flight exception. +The ``normal`` label should contain the code found in the ``catch`` +portion of a ``try``/``catch`` sequence. It defines values supplied by +the :ref:`personality function ` upon re-entry to the +function. The ``resultval`` has the type ``resultty``. + +Arguments: +"""""""""" + +The instruction takes a list of arbitrary values which are interpreted +by the :ref:`personality function `. + +The ``catchpad`` must be provided a ``normal`` label to transfer control +to if the ``catchpad`` matches the exception and an ``exception`` +label to transfer control to if it doesn't. + +Semantics: +"""""""""" + +The '``catchpad``' instruction defines the values which are set by the +:ref:`personality function ` upon re-entry to the function, and +therefore the "result type" of the ``catchpad`` instruction. As with +calling conventions, how the personality function results are +represented in LLVM IR is target specific. + +When the call stack is being unwound due to an exception being thrown, +the exception is compared against the ``args``. If it doesn't match, +then control is transfered to the ``exception`` basic block. + +The ``catchpad`` instruction has several restrictions: + +- A catch block is a basic block which is the unwind destination of + an exceptional instruction. +- A catch block must have a '``catchpad``' instruction as its + first non-PHI instruction. +- A catch block's ``exception`` edge must refer to a catch block or a + catch-end block. +- There can be only one '``catchpad``' instruction within the + catch block. +- A basic block that is not a catch block may not include a + '``catchpad``' instruction. +- It is undefined behavior for control to transfer from a ``catchpad`` to a + ``cleanupret`` without first executing a ``catchret`` and a subsequent + ``cleanuppad``. +- It is undefined behavior for control to transfer from a ``catchpad`` to a + ``ret`` without first executing a ``catchret``. + +Example: +"""""""" + +.. code-block:: llvm + + ;; A catch block which can catch an integer. + %res = catchpad { i8*, i32 } [i8** @_ZTIi] + to label %int.handler unwind label %terminate + +.. _i_catchendpad: + +'``catchendpad``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + catchendpad unwind label + catchendpad unwind to caller + +Overview: +""""""""" + +The '``catchendpad``' instruction is used by `LLVM's exception handling +system `_ to communicate to the +:ref:`personality function ` which invokes are associated +with a chain of :ref:`catchpad ` instructions. + +The ``nextaction`` label indicates where control should transfer to if +none of the ``catchpad`` instructions are suitable for catching the +in-flight exception. + +If a ``nextaction`` label is not present, the instruction unwinds out of +its parent function. The +:ref:`personality function ` will continue processing +exception handling actions in the caller. + +Arguments: +"""""""""" + +The instruction optionally takes a label, ``nextaction``, indicating +where control should transfer to if none of the preceding +``catchpad`` instructions are suitable for the in-flight exception. + +Semantics: +"""""""""" + +When the call stack is being unwound due to an exception being thrown +and none of the constituent ``catchpad`` instructions match, then +control is transfered to ``nextaction`` if it is present. If it is not +present, control is transfered to the caller. + +The ``catchendpad`` instruction has several restrictions: + +- A catch-end block is a basic block which is the unwind destination of + an exceptional instruction. +- A catch-end block must have a '``catchendpad``' instruction as its + first non-PHI instruction. +- There can be only one '``catchendpad``' instruction within the + catch block. +- A basic block that is not a catch-end block may not include a + '``catchendpad``' instruction. +- Exactly one catch block may unwind to a ``catchendpad``. +- The unwind target of invokes between a ``catchpad`` and a + corresponding ``catchret`` must be its ``catchendpad``. + +Example: +"""""""" + +.. code-block:: llvm + + catchendpad unwind label %terminate + catchendpad unwind to caller + +.. _i_catchret: + +'``catchret``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + catchret label + +Overview: +""""""""" + +The '``catchret``' instruction is a terminator instruction that has a +single successor. + + +Arguments: +"""""""""" + +The '``catchret``' instruction requires one argument which specifies +where control will transfer to next. + +Semantics: +"""""""""" + +The '``catchret``' instruction ends the existing (in-flight) exception +whose unwinding was interrupted with a +:ref:`catchpad ` instruction. +The :ref:`personality function ` gets a chance to execute +arbitrary code to, for example, run a C++ destructor. +Control then transfers to ``normal``. + +Example: +"""""""" + +.. code-block:: llvm + + catchret label %continue + +.. _i_cleanupret: + +'``cleanupret``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + cleanupret unwind label + cleanupret unwind to caller + +Overview: +""""""""" + +The '``cleanupret``' instruction is a terminator instruction that has +an optional successor. + + +Arguments: +"""""""""" + +The '``cleanupret``' instruction requires one argument, which must have the +same type as the result of any '``cleanuppad``' instruction in the same +function. It also has an optional successor, ``continue``. + +Semantics: +"""""""""" + +The '``cleanupret``' instruction indicates to the +:ref:`personality function ` that one +:ref:`cleanuppad ` it transferred control to has ended. +It transfers control to ``continue`` or unwinds out of the function. + +Example: +"""""""" + +.. code-block:: llvm + + cleanupret void unwind to caller + cleanupret { i8*, i32 } %exn unwind label %continue + +.. _i_terminatepad: + +'``terminatepad``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + terminatepad [*] unwind label + terminatepad [*] unwind to caller + +Overview: +""""""""" + +The '``terminatepad``' instruction is used by `LLVM's exception handling +system `_ to specify that a basic block +is a terminate block --- one where a personality routine may decide to +terminate the program. +The ``args`` correspond to whatever information the personality +routine requires to know if this is an appropriate place to terminate the +program. Control is transferred to the ``exception`` label if the +personality routine decides not to terminate the program for the +in-flight exception. + +Arguments: +"""""""""" + +The instruction takes a list of arbitrary values which are interpreted +by the :ref:`personality function `. + +The ``terminatepad`` may be given an ``exception`` label to +transfer control to if the in-flight exception matches the ``args``. + +Semantics: +"""""""""" + +When the call stack is being unwound due to an exception being thrown, +the exception is compared against the ``args``. If it matches, +then control is transfered to the ``exception`` basic block. Otherwise, +the program is terminated via personality-specific means. Typically, +the first argument to ``terminatepad`` specifies what function the +personality should defer to in order to terminate the program. + +The ``terminatepad`` instruction has several restrictions: + +- A terminate block is a basic block which is the unwind destination of + an exceptional instruction. +- A terminate block must have a '``terminatepad``' instruction as its + first non-PHI instruction. +- There can be only one '``terminatepad``' instruction within the + terminate block. +- A basic block that is not a terminate block may not include a + '``terminatepad``' instruction. + +Example: +"""""""" + +.. code-block:: llvm + + ;; A terminate block which only permits integers. + terminatepad [i8** @_ZTIi] unwind label %continue + .. _i_unreachable: '``unreachable``' Instruction @@ -5060,7 +6019,7 @@ Semantics: The value produced is ``op1`` \* 2\ :sup:`op2` mod 2\ :sup:`n`, where ``n`` is the width of the result. If ``op2`` is (statically or -dynamically) negative or equal to or larger than the number of bits in +dynamically) equal to or larger than the number of bits in ``op1``, the result is undefined. If the arguments are vectors, each vector element of ``op1`` is shifted by the corresponding shift amount in ``op2``. @@ -5656,7 +6615,7 @@ Syntax: :: - = load [volatile] , * [, align ][, !nontemporal !][, !invariant.load !][, !nonnull !] + = load [volatile] , * [, align ][, !nontemporal !][, !invariant.load !][, !nonnull !][, !dereferenceable !][, !dereferenceable_or_null !] = load atomic [volatile] * [singlethread] , align ! = !{ i32 1 } @@ -5721,6 +6680,25 @@ never be null. This is analogous to the ''nonnull'' attribute on parameters and return values. This metadata can only be applied to loads of a pointer type. +The optional ``!dereferenceable`` metadata must reference a single +metadata name ```` corresponding to a metadata node with one ``i64`` +entry. The existence of the ``!dereferenceable`` metadata on the instruction +tells the optimizer that the value loaded is known to be dereferenceable. +The number of bytes known to be dereferenceable is specified by the integer +value in the metadata node. This is analogous to the ''dereferenceable'' +attribute on parameters and return values. This metadata can only be applied +to loads of a pointer type. + +The optional ``!dereferenceable_or_null`` metadata must reference a single +metadata name ```` corresponding to a metadata node with one ``i64`` +entry. The existence of the ``!dereferenceable_or_null`` metadata on the +instruction tells the optimizer that the value loaded is known to be either +dereferenceable or null. +The number of bytes known to be dereferenceable is specified by the integer +value in the metadata node. This is analogous to the ''dereferenceable_or_null'' +attribute on parameters and return values. This metadata can only be applied +to loads of a pointer type. + Semantics: """""""""" @@ -6054,7 +7032,8 @@ Overview: The '``getelementptr``' instruction is used to get the address of a subelement of an :ref:`aggregate ` data structure. It performs -address calculation only and does not access memory. +address calculation only and does not access memory. The instruction can also +be used to calculate a vector of such addresses. Arguments: """""""""" @@ -6180,12 +7159,61 @@ Example: ; yields i32*:iptr %iptr = getelementptr [10 x i32], [10 x i32]* @arr, i16 0, i16 0 -In cases where the pointer argument is a vector of pointers, each index -must be a vector with the same number of elements. For example: +Vector of pointers: +""""""""""""""""""" + +The ``getelementptr`` returns a vector of pointers, instead of a single address, +when one or more of its arguments is a vector. In such cases, all vector +arguments should have the same number of elements, and every scalar argument +will be effectively broadcast into a vector during address calculation. + +.. code-block:: llvm + + ; All arguments are vectors: + ; A[i] = ptrs[i] + offsets[i]*sizeof(i8) + %A = getelementptr i8, <4 x i8*> %ptrs, <4 x i64> %offsets + + ; Add the same scalar offset to each pointer of a vector: + ; A[i] = ptrs[i] + offset*sizeof(i8) + %A = getelementptr i8, <4 x i8*> %ptrs, i64 %offset + + ; Add distinct offsets to the same pointer: + ; A[i] = ptr + offsets[i]*sizeof(i8) + %A = getelementptr i8, i8* %ptr, <4 x i64> %offsets + + ; In all cases described above the type of the result is <4 x i8*> + +The two following instructions are equivalent: + +.. code-block:: llvm + + getelementptr %struct.ST, <4 x %struct.ST*> %s, <4 x i64> %ind1, + <4 x i32> , + <4 x i32> , + <4 x i32> %ind4, + <4 x i64> + + getelementptr %struct.ST, <4 x %struct.ST*> %s, <4 x i64> %ind1, + i32 2, i32 1, <4 x i32> %ind4, i64 13 + +Let's look at the C code, where the vector version of ``getelementptr`` +makes sense: + +.. code-block:: c + + // Let's assume that we vectorize the following loop: + double *A, B; int *C; + for (int i = 0; i < size; ++i) { + A[i] = B[C[i]]; + } .. code-block:: llvm - %A = getelementptr i8, <4 x i8*> %ptrs, <4 x i64> %offsets, + ; get pointers for 8 elements from array B + %ptrs = getelementptr double, double* %B, <8 x i32> %C + ; load 8 elements from array B into A + %A = call <8 x double> @llvm.masked.gather.v8f64(<8 x double*> %ptrs, + i32 8, <8 x i1> %mask, <8 x double> %passthru) Conversion Operations --------------------- @@ -6859,7 +7887,7 @@ Syntax: :: - = fcmp , ; yields i1 or :result + = fcmp [fast-math flags]* , ; yields i1 or :result Overview: """"""""" @@ -6942,6 +7970,15 @@ always yields an :ref:`i1 ` result, as follows: #. ``uno``: yields ``true`` if either operand is a QNAN. #. ``true``: always yields ``true``, regardless of operands. +The ``fcmp`` instruction can also optionally take any number of +:ref:`fast-math flags `, which are optimization hints to enable +otherwise unsafe floating point optimizations. + +Any set of fast-math flags are legal on an ``fcmp`` instruction, but the +only flags that have any effect on its semantics are those that allow +assumptions to be made about the values of input arguments; namely +``nnan``, ``ninf``, and ``nsz``. See :ref:`fastmath` for more information. + Example: """""""" @@ -7241,8 +8278,8 @@ Syntax: :: - = landingpad personality + - = landingpad personality cleanup * + = landingpad + + = landingpad cleanup * := catch := filter @@ -7254,14 +8291,13 @@ The '``landingpad``' instruction is used by `LLVM's exception handling system `_ to specify that a basic block is a landing pad --- one where the exception lands, and corresponds to the code found in the ``catch`` portion of a ``try``/``catch`` sequence. It -defines values supplied by the personality function (``pers_fn``) upon +defines values supplied by the :ref:`personality function ` upon re-entry to the function. The ``resultval`` has the type ``resultty``. Arguments: """""""""" -This instruction takes a ``pers_fn`` value. This is the personality -function associated with the unwinding mechanism. The optional +The optional ``cleanup`` flag indicates that the landing pad block is a cleanup. A ``clause`` begins with the clause type --- ``catch`` or ``filter`` --- and @@ -7276,7 +8312,7 @@ Semantics: """""""""" The '``landingpad``' instruction defines the values which are set by the -personality function (``pers_fn``) upon re-entry to the function, and +:ref:`personality function ` upon re-entry to the function, and therefore the "result type" of the ``landingpad`` instruction. As with calling conventions, how the personality function results are represented in LLVM IR is target specific. @@ -7299,8 +8335,6 @@ The ``landingpad`` instruction has several restrictions: pad block. - A basic block that is not a landing pad block may not include a '``landingpad``' instruction. -- All '``landingpad``' instructions in a function must have the same - personality function. Example: """""""" @@ -7308,16 +8342,82 @@ Example: .. code-block:: llvm ;; A landing pad which can catch an integer. - %res = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 + %res = landingpad { i8*, i32 } catch i8** @_ZTIi ;; A landing pad that is a cleanup. - %res = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 + %res = landingpad { i8*, i32 } cleanup ;; A landing pad which can catch an integer and can only throw a double. - %res = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0 + %res = landingpad { i8*, i32 } catch i8** @_ZTIi filter [1 x i8**] [@_ZTId] +.. _i_cleanuppad: + +'``cleanuppad``' Instruction +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + = cleanuppad [*] + +Overview: +""""""""" + +The '``cleanuppad``' instruction is used by `LLVM's exception handling +system `_ to specify that a basic block +is a cleanup block --- one where a personality routine attempts to +transfer control to run cleanup actions. +The ``args`` correspond to whatever additional +information the :ref:`personality function ` requires to +execute the cleanup. +The ``resultval`` has the type ``resultty``. + +Arguments: +"""""""""" + +The instruction takes a list of arbitrary values which are interpreted +by the :ref:`personality function `. + +Semantics: +"""""""""" + +The '``cleanuppad``' instruction defines the values which are set by the +:ref:`personality function ` upon re-entry to the function, and +therefore the "result type" of the ``cleanuppad`` instruction. As with +calling conventions, how the personality function results are +represented in LLVM IR is target specific. + +When the call stack is being unwound due to an exception being thrown, +the :ref:`personality function ` transfers control to the +``cleanuppad`` with the aid of the personality-specific arguments. + +The ``cleanuppad`` instruction has several restrictions: + +- A cleanup block is a basic block which is the unwind destination of + an exceptional instruction. +- A cleanup block must have a '``cleanuppad``' instruction as its + first non-PHI instruction. +- There can be only one '``cleanuppad``' instruction within the + cleanup block. +- A basic block that is not a cleanup block may not include a + '``cleanuppad``' instruction. +- It is undefined behavior for control to transfer from a ``cleanuppad`` to a + ``catchret`` without first executing a ``cleanupret`` and a subsequent + ``catchpad``. +- It is undefined behavior for control to transfer from a ``cleanuppad`` to a + ``ret`` without first executing a ``cleanupret``. + +Example: +"""""""" + +.. code-block:: llvm + + %res = cleanuppad { i8*, i32 } [label %nextaction] + .. _intrinsics: Intrinsic Functions @@ -7729,7 +8829,7 @@ Note that calling this intrinsic does not prevent function inlining or other aggressive transformations, so the value returned may not be that of the obvious source-language caller. -'``llvm.frameescape``' and '``llvm.framerecover``' Intrinsics +'``llvm.localescape``' and '``llvm.localrecover``' Intrinsics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Syntax: @@ -7737,49 +8837,47 @@ Syntax: :: - declare void @llvm.frameescape(...) - declare i8* @llvm.framerecover(i8* %func, i8* %fp, i32 %idx) + declare void @llvm.localescape(...) + declare i8* @llvm.localrecover(i8* %func, i8* %fp, i32 %idx) Overview: """"""""" -The '``llvm.frameescape``' intrinsic escapes offsets of a collection of static -allocas, and the '``llvm.framerecover``' intrinsic applies those offsets to a +The '``llvm.localescape``' intrinsic escapes offsets of a collection of static +allocas, and the '``llvm.localrecover``' intrinsic applies those offsets to a live frame pointer to recover the address of the allocation. The offset is -computed during frame layout of the caller of ``llvm.frameescape``. +computed during frame layout of the caller of ``llvm.localescape``. Arguments: """""""""" -All arguments to '``llvm.frameescape``' must be pointers to static allocas or -casts of static allocas. Each function can only call '``llvm.frameescape``' +All arguments to '``llvm.localescape``' must be pointers to static allocas or +casts of static allocas. Each function can only call '``llvm.localescape``' once, and it can only do so from the entry block. -The ``func`` argument to '``llvm.framerecover``' must be a constant +The ``func`` argument to '``llvm.localrecover``' must be a constant bitcasted pointer to a function defined in the current module. The code generator cannot determine the frame allocation offset of functions defined in other modules. -The ``fp`` argument to '``llvm.framerecover``' must be a frame -pointer of a call frame that is currently live. The return value of -'``llvm.frameaddress``' is one way to produce such a value, but most platforms -also expose the frame pointer through stack unwinding mechanisms. +The ``fp`` argument to '``llvm.localrecover``' must be a frame pointer of a +call frame that is currently live. The return value of '``llvm.localaddress``' +is one way to produce such a value, but various runtimes also expose a suitable +pointer in platform-specific ways. -The ``idx`` argument to '``llvm.framerecover``' indicates which alloca passed to -'``llvm.frameescape``' to recover. It is zero-indexed. +The ``idx`` argument to '``llvm.localrecover``' indicates which alloca passed to +'``llvm.localescape``' to recover. It is zero-indexed. Semantics: """""""""" -These intrinsics allow a group of functions to access one stack memory -allocation in an ancestor stack frame. The memory returned from -'``llvm.frameallocate``' may be allocated prior to stack realignment, so the -memory is only aligned to the ABI-required stack alignment. Each function may -only call '``llvm.frameallocate``' one or zero times from the function entry -block. The frame allocation intrinsic inhibits inlining, as any frame -allocations in the inlined function frame are likely to be at a different -offset from the one used by '``llvm.framerecover``' called with the -uninlined function. +These intrinsics allow a group of functions to share access to a set of local +stack allocations of a one parent function. The parent function may call the +'``llvm.localescape``' intrinsic once from the function entry block, and the +child functions can use '``llvm.localrecover``' to access the escaped allocas. +The '``llvm.localescape``' intrinsic blocks inlining, as inlining changes where +the escaped allocas are allocated, which would break attempts to use +'``llvm.localrecover``'. .. _int_read_register: .. _int_write_register: @@ -9481,6 +10579,75 @@ Examples: Specialised Arithmetic Intrinsics --------------------------------- +'``llvm.canonicalize.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare float @llvm.canonicalize.f32(float %a) + declare double @llvm.canonicalize.f64(double %b) + +Overview: +""""""""" + +The '``llvm.canonicalize.*``' intrinsic returns the platform specific canonical +encoding of a floating point number. This canonicalization is useful for +implementing certain numeric primitives such as frexp. The canonical encoding is +defined by IEEE-754-2008 to be: + +:: + + 2.1.8 canonical encoding: The preferred encoding of a floating-point + representation in a format. Applied to declets, significands of finite + numbers, infinities, and NaNs, especially in decimal formats. + +This operation can also be considered equivalent to the IEEE-754-2008 +conversion of a floating-point value to the same format. NaNs are handled +according to section 6.2. + +Examples of non-canonical encodings: + +- x87 pseudo denormals, pseudo NaNs, pseudo Infinity, Unnormals. These are + converted to a canonical representation per hardware-specific protocol. +- Many normal decimal floating point numbers have non-canonical alternative + encodings. +- Some machines, like GPUs or ARMv7 NEON, do not support subnormal values. + These are treated as non-canonical encodings of zero and with be flushed to + a zero of the same sign by this operation. + +Note that per IEEE-754-2008 6.2, systems that support signaling NaNs with +default exception handling must signal an invalid exception, and produce a +quiet NaN result. + +This function should always be implementable as multiplication by 1.0, provided +that the compiler does not constant fold the operation. Likewise, division by +1.0 and ``llvm.minnum(x, x)`` are possible implementations. Addition with +-0.0 is also sufficient provided that the rounding mode is not -Infinity. + +``@llvm.canonicalize`` must preserve the equality relation. That is: + +- ``(@llvm.canonicalize(x) == x)`` is equivalent to ``(x == x)`` +- ``(@llvm.canonicalize(x) == @llvm.canonicalize(y))`` is equivalent to + to ``(x == y)`` + +Additionally, the sign of zero must be conserved: +``@llvm.canonicalize(-0.0) = -0.0`` and ``@llvm.canonicalize(+0.0) = +0.0`` + +The payload bits of a NaN must be conserved, with two exceptions. +First, environments which use only a single canonical representation of NaN +must perform said canonicalization. Second, SNaNs must be quieted per the +usual methods. + +The canonicalization operation may be optimized away if: + +- The input is known to be canonical. For example, it was produced by a + floating-point operation that is required by the standard to be canonical. +- The result is consumed only by (or fused with) other floating-point + operations. That is, the bits of the floating point value are not examined. + '``llvm.fmuladd.*``' Intrinsic ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9530,6 +10697,65 @@ Examples: %r2 = call float @llvm.fmuladd.f32(float %a, float %b, float %c) ; yields float:r2 = (a * b) + c + +'``llvm.uabsdiff.*``' and '``llvm.sabsdiff.*``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" +This is an overloaded intrinsic. The loaded data is a vector of any integer bit width. + +.. code-block:: llvm + + declare <4 x integer> @llvm.uabsdiff.v4i32(<4 x integer> %a, <4 x integer> %b) + + +Overview: +""""""""" + +The ``llvm.uabsdiff`` intrinsic returns a vector result of the absolute difference of the two operands, +treating them both as unsigned integers. + +The ``llvm.sabsdiff`` intrinsic returns a vector result of the absolute difference of the two operands, +treating them both as signed integers. + +.. note:: + + These intrinsics are primarily used during the code generation stage of compilation. + They are generated by compiler passes such as the Loop and SLP vectorizers.it is not + recommended for users to create them manually. + +Arguments: +"""""""""" + +Both intrinsics take two integer of the same bitwidth. + +Semantics: +"""""""""" + +The expression:: + + call <4 x i32> @llvm.uabsdiff.v4i32(<4 x i32> %a, <4 x i32> %b) + +is equivalent to:: + + %sub = sub <4 x i32> %a, %b + %ispos = icmp ugt <4 x i32> %sub, + %neg = sub <4 x i32> zeroinitializer, %sub + %1 = select <4 x i1> %ispos, <4 x i32> %sub, <4 x i32> %neg + +Similarly the expression:: + + call <4 x i32> @llvm.sabsdiff.v4i32(<4 x i32> %a, <4 x i32> %b) + +is equivalent to:: + + %sub = sub nsw <4 x i32> %a, %b + %ispos = icmp sgt <4 x i32> %sub, + %neg = sub nsw <4 x i32> zeroinitializer, %sub + %1 = select <4 x i1> %ispos, <4 x i32> %sub, <4 x i32> %neg + + Half Precision Floating Point Intrinsics ---------------------------------------- @@ -9754,6 +10980,8 @@ intrinsic returns the executable address corresponding to ``tramp`` after performing the required machine specific adjustments. The pointer returned can then be :ref:`bitcast and executed `. +.. _int_mload_mstore: + Masked Vector Load and Store Intrinsics --------------------------------------- @@ -9776,13 +11004,13 @@ This is an overloaded intrinsic. The loaded data is a vector of any integer or f Overview: """"""""" -Reads a vector from memory according to the provided mask. The mask holds a bit for each vector lane, and is used to prevent memory accesses to the masked-off lanes. The masked-off lanes in the result vector are taken from the corresponding lanes in the passthru operand. +Reads a vector from memory according to the provided mask. The mask holds a bit for each vector lane, and is used to prevent memory accesses to the masked-off lanes. The masked-off lanes in the result vector are taken from the corresponding lanes of the '``passthru``' operand. Arguments: """""""""" -The first operand is the base pointer for the load. The second operand is the alignment of the source location. It must be a constant integer value. The third operand, mask, is a vector of boolean 'i1' values with the same number of elements as the return type. The fourth is a pass-through value that is used to fill the masked-off lanes of the result. The return type, underlying type of the base pointer and the type of passthru operand are the same vector types. +The first operand is the base pointer for the load. The second operand is the alignment of the source location. It must be a constant integer value. The third operand, mask, is a vector of boolean values with the same number of elements as the return type. The fourth is a pass-through value that is used to fill the masked-off lanes of the result. The return type, underlying type of the base pointer and the type of the '``passthru``' operand are the same vector types. Semantics: @@ -9841,6 +11069,115 @@ The result of this operation is equivalent to a load-modify-store sequence. Howe store <16 x float> %res, <16 x float>* %ptr, align 4 +Masked Vector Gather and Scatter Intrinsics +------------------------------------------- + +LLVM provides intrinsics for vector gather and scatter operations. They are similar to :ref:`Masked Vector Load and Store `, except they are designed for arbitrary memory accesses, rather than sequential memory accesses. Gather and scatter also employ a mask operand, which holds one bit per vector element, switching the associated vector lane on or off. The memory addresses corresponding to the "off" lanes are not accessed. When all bits are off, no memory is accessed. + +.. _int_mgather: + +'``llvm.masked.gather.*``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" +This is an overloaded intrinsic. The loaded data are multiple scalar values of any integer or floating point data type gathered together into one vector. + +:: + + declare <16 x float> @llvm.masked.gather.v16f32 (<16 x float*> , i32 , <16 x i1> , <16 x float> ) + declare <2 x double> @llvm.masked.gather.v2f64 (<2 x double*> , i32 , <2 x i1> , <2 x double> ) + +Overview: +""""""""" + +Reads scalar values from arbitrary memory locations and gathers them into one vector. The memory locations are provided in the vector of pointers '``ptrs``'. The memory is accessed according to the provided mask. The mask holds a bit for each vector lane, and is used to prevent memory accesses to the masked-off lanes. The masked-off lanes in the result vector are taken from the corresponding lanes of the '``passthru``' operand. + + +Arguments: +"""""""""" + +The first operand is a vector of pointers which holds all memory addresses to read. The second operand is an alignment of the source addresses. It must be a constant integer value. The third operand, mask, is a vector of boolean values with the same number of elements as the return type. The fourth is a pass-through value that is used to fill the masked-off lanes of the result. The return type, underlying type of the vector of pointers and the type of the '``passthru``' operand are the same vector types. + + +Semantics: +"""""""""" + +The '``llvm.masked.gather``' intrinsic is designed for conditional reading of multiple scalar values from arbitrary memory locations in a single IR operation. It is useful for targets that support vector masked gathers and allows vectorizing basic blocks with data and control divergence. Other targets may support this intrinsic differently, for example by lowering it into a sequence of scalar load operations. +The semantics of this operation are equivalent to a sequence of conditional scalar loads with subsequent gathering all loaded values into a single vector. The mask restricts memory access to certain lanes and facilitates vectorization of predicated basic blocks. + + +:: + + %res = call <4 x double> @llvm.masked.gather.v4f64 (<4 x double*> %ptrs, i32 8, <4 x i1>%mask, <4 x double> ) + + ;; The gather with all-true mask is equivalent to the following instruction sequence + %ptr0 = extractelement <4 x double*> %ptrs, i32 0 + %ptr1 = extractelement <4 x double*> %ptrs, i32 1 + %ptr2 = extractelement <4 x double*> %ptrs, i32 2 + %ptr3 = extractelement <4 x double*> %ptrs, i32 3 + + %val0 = load double, double* %ptr0, align 8 + %val1 = load double, double* %ptr1, align 8 + %val2 = load double, double* %ptr2, align 8 + %val3 = load double, double* %ptr3, align 8 + + %vec0 = insertelement <4 x double>undef, %val0, 0 + %vec01 = insertelement <4 x double>%vec0, %val1, 1 + %vec012 = insertelement <4 x double>%vec01, %val2, 2 + %vec0123 = insertelement <4 x double>%vec012, %val3, 3 + +.. _int_mscatter: + +'``llvm.masked.scatter.*``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" +This is an overloaded intrinsic. The data stored in memory is a vector of any integer or floating point data type. Each vector element is stored in an arbitrary memory addresses. Scatter with overlapping addresses is guaranteed to be ordered from least-significant to most-significant element. + +:: + + declare void @llvm.masked.scatter.v8i32 (<8 x i32> , <8 x i32*> , i32 , <8 x i1> ) + declare void @llvm.masked.scatter.v16f32(<16 x i32> , <16 x i32*> , i32 , <16 x i1> ) + +Overview: +""""""""" + +Writes each element from the value vector to the corresponding memory address. The memory addresses are represented as a vector of pointers. Writing is done according to the provided mask. The mask holds a bit for each vector lane, and is used to prevent memory accesses to the masked-off lanes. + +Arguments: +"""""""""" + +The first operand is a vector value to be written to memory. The second operand is a vector of pointers, pointing to where the value elements should be stored. It has the same underlying type as the value operand. The third operand is an alignment of the destination addresses. The fourth operand, mask, is a vector of boolean values. The types of the mask and the value operand must have the same number of vector elements. + + +Semantics: +"""""""""" + +The '``llvm.masked.scatter``' intrinsics is designed for writing selected vector elements to arbitrary memory addresses in a single IR operation. The operation may be conditional, when not all bits in the mask are switched on. It is useful for targets that support vector masked scatter and allows vectorizing basic blocks with data and control divergency. Other targets may support this intrinsic differently, for example by lowering it into a sequence of branches that guard scalar store operations. + +:: + + ;; This instruction unconditionaly stores data vector in multiple addresses + call @llvm.masked.scatter.v8i32 (<8 x i32> %value, <8 x i32*> %ptrs, i32 4, <8 x i1> ) + + ;; It is equivalent to a list of scalar stores + %val0 = extractelement <8 x i32> %value, i32 0 + %val1 = extractelement <8 x i32> %value, i32 1 + .. + %val7 = extractelement <8 x i32> %value, i32 7 + %ptr0 = extractelement <8 x i32*> %ptrs, i32 0 + %ptr1 = extractelement <8 x i32*> %ptrs, i32 1 + .. + %ptr7 = extractelement <8 x i32*> %ptrs, i32 7 + ;; Note: the order of the following stores is important when they overlap: + store i32 %val0, i32* %ptr0, align 4 + store i32 %val1, i32* %ptr1, align 4 + .. + store i32 %val7, i32* %ptr7, align 4 + + Memory Use Markers ------------------ @@ -10285,6 +11622,8 @@ Semantics: This intrinsic is lowered to the ``val``. +.. _int_assume: + '``llvm.assume``' Intrinsic ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/Lexicon.rst b/docs/Lexicon.rst index 9a599da1285..912dee2cf07 100644 --- a/docs/Lexicon.rst +++ b/docs/Lexicon.rst @@ -46,6 +46,15 @@ B C - +**CFI** + Call Frame Information. Used in DWARF debug info and in C++ unwind info + to show how the function prolog lays out the stack frame. + +**CIE** + Common Information Entry. A kind of CFI used to reduce the size of FDEs. + The compiler creates a CIE which contains the information common across all + the FDEs. Each FDE then points to its CIE. + **CSE** Common Subexpression Elimination. An optimization that removes common subexpression compuation. For example ``(a+b)*(a+b)`` has two subexpressions @@ -82,6 +91,10 @@ F **FCA** First Class Aggregate +**FDE** + Frame Description Entry. A kind of CFI used to describe the stack frame of + one function. + G - @@ -118,9 +131,21 @@ 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 +**LSDA** + Language Specific Data Area. C++ "zero cost" unwinding is built on top a + generic unwinding mechanism. As the unwinder walks each frame, it calls + a "personality" function to do language specific analysis. Each function's + FDE points to an optional LSDA which is passed to the personality function. + For C++, the LSDA contain info about the type and location of catch + statements in that function. + **Load-VN** Load Value Numbering diff --git a/docs/LibFuzzer.rst b/docs/LibFuzzer.rst index a31f83d3950..1ac75a40698 100644 --- a/docs/LibFuzzer.rst +++ b/docs/LibFuzzer.rst @@ -14,26 +14,29 @@ This library is intended primarily for in-process coverage-guided fuzz testing * Build the Fuzzer library as a static archive (or just a set of .o files). Note that the Fuzzer contains the main() function. Preferably do *not* use sanitizers while building the Fuzzer. -* Build the library you are going to test with -fsanitize-coverage=[234] +* Build the library you are going to test with + `-fsanitize-coverage={bb,edge}[,indirect-calls,8bit-counters]` and one of the sanitizers. We recommend to build the library in several different modes (e.g. asan, msan, lsan, ubsan, etc) and even using different optimizations options (e.g. -O0, -O1, -O2) to diversify testing. * Build a test driver using the same options as the library. The test driver is a C/C++ file containing interesting calls to the library - inside a single function ``extern "C" void TestOneInput(const uint8_t *Data, size_t Size);`` + inside a single function ``extern "C" void LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);`` * Link the Fuzzer, the library and the driver together into an executable using the same sanitizer options as for the library. * Collect the initial corpus of inputs for the fuzzer (a directory with test inputs, one file per input). The better your inputs are the faster you will find something interesting. Also try to keep your inputs small, otherwise the Fuzzer will run too slow. + By default, the Fuzzer limits the size of every input to 64 bytes + (use ``-max_len=N`` to override). * Run the fuzzer with the test corpus. As new interesting test cases are discovered they will be added to the corpus. If a bug is discovered by the sanitizer (asan, etc) it will be reported as usual and the reproducer will be written to disk. Each Fuzzer process is single-threaded (unless the library starts its own - threads). You can run the Fuzzer on the same corpus in multiple processes. - in parallel. For run-time options run the Fuzzer binary with '-help=1'. + threads). You can run the Fuzzer on the same corpus in multiple processes + in parallel. The Fuzzer is similar in concept to AFL_, @@ -47,6 +50,27 @@ and is used to fuzz various parts of LLVM, but the Fuzzer itself does not (and should not) depend on any part of LLVM and can be used for other projects w/o requiring the rest of LLVM. +Flags +===== +The most important flags are:: + + seed 0 Random seed. If 0, seed is generated. + runs -1 Number of individual test runs (-1 for infinite runs). + max_len 64 Maximum length of the test input. + cross_over 1 If 1, cross over inputs. + mutate_depth 5 Apply this number of consecutive mutations to each input. + timeout 1200 Timeout in seconds (if positive). If one unit runs more than this number of seconds the process will abort. + help 0 Print help. + save_minimized_corpus 0 If 1, the minimized corpus is saved into the first input directory + jobs 0 Number of jobs to run. If jobs >= 1 we spawn this number of jobs in separate worker processes with stdout/stderr redirected to fuzz-JOB.log. + workers 0 Number of simultaneous worker processes to run the jobs. If zero, "min(jobs,NumberOfCpuCores()/2)" is used. + tokens 0 Use the file with tokens (one token per line) to fuzz a token based input language. + apply_tokens 0 Read the given input file, substitute bytes with tokens and write the result to stdout. + sync_command 0 Execute an external command " " to synchronize the test corpus. + sync_timeout 600 Minimum timeout between syncs. + +For the full list of flags run the fuzzer binary with ``-help=1``. + Usage examples ============== @@ -56,7 +80,7 @@ Toy example A simple function that does something interesting if it receives the input "HI!":: cat << EOF >> test_fuzzer.cc - extern "C" void TestOneInput(const unsigned char *data, unsigned long size) { + extern "C" void LLVMFuzzerTestOneInput(const unsigned char *data, unsigned long size) { if (size > 0 && data[0] == 'H') if (size > 1 && data[1] == 'I') if (size > 2 && data[2] == '!') @@ -68,7 +92,7 @@ A simple function that does something interesting if it receives the input "HI!" # Build lib/Fuzzer files. clang -c -g -O2 -std=c++11 Fuzzer/*.cpp -IFuzzer # Build test_fuzzer.cc with asan and link against lib/Fuzzer. - clang++ -fsanitize=address -fsanitize-coverage=3 test_fuzzer.cc Fuzzer*.o + clang++ -fsanitize=address -fsanitize-coverage=edge test_fuzzer.cc Fuzzer*.o # Run the fuzzer with no corpus. ./a.out @@ -79,7 +103,7 @@ PCRE2 Here we show how to use lib/Fuzzer on something real, yet simple: pcre2_:: - COV_FLAGS=" -fsanitize-coverage=4 -mllvm -sanitizer-coverage-8bit-counters=1" + COV_FLAGS=" -fsanitize-coverage=edge,indirect-calls,8bit-counters" # Get PCRE2 svn co svn://vcs.exim.org/pcre2/code/trunk pcre # Get lib/Fuzzer. Assuming that you already have fresh clang in PATH. @@ -88,11 +112,11 @@ Here we show how to use lib/Fuzzer on something real, yet simple: pcre2_:: (cd pcre; ./autogen.sh; CC="clang -fsanitize=address $COV_FLAGS" ./configure --prefix=`pwd`/../inst && make -j && make install) # Build lib/Fuzzer files. clang -c -g -O2 -std=c++11 Fuzzer/*.cpp -IFuzzer - # Build the the actual function that does something interesting with PCRE2. + # Build the actual function that does something interesting with PCRE2. cat << EOF > pcre_fuzzer.cc #include #include "pcre2posix.h" - extern "C" void TestOneInput(const unsigned char *data, size_t size) { + extern "C" void LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) { if (size < 1) return; char *str = new char[size+1]; memcpy(str, data, size); @@ -151,17 +175,21 @@ Now, interrupt the fuzzer and run it again the same way. You will see:: This time you were running the fuzzer with a non-empty input corpus (564 items). As the first step, the fuzzer minimized the set to produce 344 interesting items (the ``INITED`` line) +It is quite convenient to store test corpuses in git. +As an example, here is a git repository with test inputs for the above PCRE2 fuzzer:: + + git clone https://github.com/kcc/fuzzing-with-sanitizers.git + ./pcre_fuzzer ./fuzzing-with-sanitizers/pcre2/C1/ + You may run ``N`` independent fuzzer jobs in parallel on ``M`` CPUs:: N=100; M=4; ./pcre_fuzzer ./CORPUS -jobs=$N -workers=$M -This is useful when you already have an exhaustive test corpus. -If you've just started fuzzing with no good corpus running independent -jobs will create a corpus with too many duplicates. -One way to avoid this and still use all of your CPUs is to use the flag ``-exit_on_first=1`` -which will cause the fuzzer to exit on the first new synthesised input:: +By default (``-reload=1``) the fuzzer processes will periodically scan the CORPUS directory +and reload any new tests. This way the test inputs found by one process will be picked up +by all others. - N=100; M=4; ./pcre_fuzzer ./CORPUS -jobs=$N -workers=$M -exit_on_first=1 +If ``-workers=$M`` is not supplied, ``min($N,NumberOfCpuCore/2)`` will be used. Heartbleed ---------- @@ -172,7 +200,7 @@ to find Heartbleed with LibFuzzer:: wget https://www.openssl.org/source/openssl-1.0.1f.tar.gz tar xf openssl-1.0.1f.tar.gz - COV_FLAGS="-fsanitize-coverage=4" # -mllvm -sanitizer-coverage-8bit-counters=1" + COV_FLAGS="-fsanitize-coverage=edge,indirect-calls" # -fsanitize-coverage=8bit-counters (cd openssl-1.0.1f/ && ./config && make -j 32 CC="clang -g -fsanitize=address $COV_FLAGS") # Get and build LibFuzzer @@ -196,7 +224,7 @@ to find Heartbleed with LibFuzzer:: assert (SSL_CTX_use_PrivateKey_file(sctx, "server.key", SSL_FILETYPE_PEM)); return 0; } - extern "C" void TestOneInput(unsigned char *Data, size_t Size) { + extern "C" void LLVMFuzzerTestOneInput(unsigned char *Data, size_t Size) { static int unused = Init(); SSL *server = SSL_new(sctx); BIO *sinbio = BIO_new(BIO_s_mem()); @@ -259,7 +287,7 @@ Periodically restart both fuzzers so that they can use each other's findings. How good is my fuzzer? ---------------------- -Once you implement your target function ``TestOneInput`` and fuzz it to death, +Once you implement your target function ``LLVMFuzzerTestOneInput`` and fuzz it to death, you will want to know whether the function or the corpus can be improved further. One easy to use metric is, of course, code coverage. You can get the coverage for your corpus like this:: @@ -271,6 +299,12 @@ and dump covered PCs to disk before exiting. Then you can subtract the set of covered PCs from the set of all instrumented PCs in the binary, see SanitizerCoverage_ for details. +User-supplied mutators +---------------------- + +LibFuzzer allows to use custom (user-supplied) mutators, +see FuzzerInterface.h_ + Fuzzing components of LLVM ========================== @@ -299,6 +333,24 @@ Clang can also be fuzzed with Tokens_ using ``-tokens=$LLVM/lib/Fuzzer/cxx_fuzze Tracking bug: https://llvm.org/bugs/show_bug.cgi?id=23057 +Buildbot +-------- + +We have a buildbot that runs the above fuzzers for LLVM components +24/7/365 at http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fuzzer . + +Pre-fuzzed test inputs in git +----------------------------- + +The buildbot occumulates large test corpuses over time. +The corpuses are stored in git on github and can be used like this:: + + git clone https://github.com/kcc/fuzzing-with-sanitizers.git + bin/clang-format-fuzzer fuzzing-with-sanitizers/llvm/clang-format/C1 + bin/clang-fuzzer fuzzing-with-sanitizers/llvm/clang/C1/ + bin/clang-fuzzer fuzzing-with-sanitizers/llvm/clang/TOK1 -tokens=$LLVM/llvm/lib/Fuzzer/cxx_fuzzer_tokens.txt + + FAQ ========================= @@ -359,6 +411,8 @@ Examples: regular expression matchers, text or binary format parsers. .. _AFL: http://lcamtuf.coredump.cx/afl/ -.. _SanitizerCoverage: https://code.google.com/p/address-sanitizer/wiki/AsanCoverage +.. _SanitizerCoverage: http://clang.llvm.org/docs/SanitizerCoverage.html .. _Heartbleed: http://en.wikipedia.org/wiki/Heartbleed + +.. _FuzzerInterface.h: https://github.com/llvm-mirror/llvm/blob/master/lib/Fuzzer/FuzzerInterface.h diff --git a/docs/NVPTXUsage.rst b/docs/NVPTXUsage.rst index e1c401df877..fc697ca0046 100644 --- a/docs/NVPTXUsage.rst +++ b/docs/NVPTXUsage.rst @@ -168,10 +168,10 @@ These are overloaded intrinsics. You can use these on any pointer types. .. code-block:: llvm - declare i8* @llvm.nvvm.ptr.gen.to.global.p1i8.p0i8(i8 addrspace(1)*) - declare i8* @llvm.nvvm.ptr.gen.to.shared.p3i8.p0i8(i8 addrspace(3)*) - declare i8* @llvm.nvvm.ptr.gen.to.constant.p4i8.p0i8(i8 addrspace(4)*) - declare i8* @llvm.nvvm.ptr.gen.to.local.p5i8.p0i8(i8 addrspace(5)*) + declare i8 addrspace(1)* @llvm.nvvm.ptr.gen.to.global.p1i8.p0i8(i8*) + declare i8 addrspace(3)* @llvm.nvvm.ptr.gen.to.shared.p3i8.p0i8(i8*) + declare i8 addrspace(4)* @llvm.nvvm.ptr.gen.to.constant.p4i8.p0i8(i8*) + declare i8 addrspace(5)* @llvm.nvvm.ptr.gen.to.local.p5i8.p0i8(i8*) Overview: """"""""" diff --git a/docs/Phabricator.rst b/docs/Phabricator.rst index b0f62e02d19..69bf3bfd103 100644 --- a/docs/Phabricator.rst +++ b/docs/Phabricator.rst @@ -60,26 +60,28 @@ to upload your patch): To upload a new patch: * Click *Differential*. -* Click *Create Diff*. -* Paste the text diff or upload the patch file. - Note that TODO +* Click *+ Create Diff*. +* Paste the text diff or browse to the patch file. Click *Create Diff*. +* Leave the Repository field blank. * Leave the drop down on *Create a new Revision...* and click *Continue*. * Enter a descriptive title and summary. The title and summary are usually in the form of a :ref:`commit message `. * Add reviewers and mailing lists that you want to be included in the review. If your patch is - for LLVM, add llvm-commits as a subscriber; if your patch is for Clang, + for LLVM, add llvm-commits as a Subscriber; if your patch is for Clang, add cfe-commits. +* Leave the Repository and Project fields blank. * Click *Save*. To submit an updated patch: * Click *Differential*. -* Click *Create Diff*. -* Paste the updated diff. +* Click *+ Create Diff*. +* Paste the updated diff or browse to the updated patch file. Click *Create Diff*. * Select the review you want to from the *Attach To* dropdown and click *Continue*. -* Click *Save*. +* Leave the Repository and Project fields blank. +* Add comments about the changes in the new diff. Click *Save*. Reviewing code with Phabricator ------------------------------- @@ -146,10 +148,20 @@ Submit button to finish closing the review. Status ------ -Please let us know whether you like it and what could be improved! +Please let us know whether you like it and what could be improved! We're still +working on setting up a bug tracker, but you can email klimek-at-google-dot-com +and chandlerc-at-gmail-dot-com and CC the llvmdev mailing list with questions +until then. We also could use help implementing improvements. This sadly is +really painful and hard because the Phabricator codebase is in PHP and not as +testable as you might like. However, we've put exactly what we're deploying up +on an `llvm-reviews GitHub project`_ where folks can hack on it and post pull +requests. We're looking into what the right long-term hosting for this is, but +note that it is a derivative of an existing open source project, and so not +trivially a good fit for an official LLVM project. .. _LLVM's Phabricator: http://reviews.llvm.org .. _`http://reviews.llvm.org`: http://reviews.llvm.org .. _Code Repository Browser: http://reviews.llvm.org/diffusion/ -.. _Arcanist Quick Start: http://www.phabricator.com/docs/phabricator/article/Arcanist_Quick_Start.html -.. _Arcanist User Guide: http://www.phabricator.com/docs/phabricator/article/Arcanist_User_Guide.html +.. _Arcanist Quick Start: https://secure.phabricator.com/book/phabricator/article/arcanist_quick_start/ +.. _Arcanist User Guide: https://secure.phabricator.com/book/phabricator/article/arcanist/ +.. _llvm-reviews GitHub project: https://github.com/r4nt/llvm-reviews/ diff --git a/docs/ProgrammersManual.rst b/docs/ProgrammersManual.rst index 6a4c22a692d..08cc61a187b 100644 --- a/docs/ProgrammersManual.rst +++ b/docs/ProgrammersManual.rst @@ -1105,10 +1105,10 @@ If you have a set-like data structure that is usually small and whose elements are reasonably small, a ``SmallSet`` is a good choice. This set has space for N elements in place (thus, if the set is dynamically smaller than N, no malloc traffic is required) and accesses them with a simple linear search. -When the set grows beyond 'N' elements, it allocates a more expensive +When the set grows beyond N elements, it allocates a more expensive representation that guarantees efficient access (for most types, it falls back -to std::set, but for pointers it uses something far better, :ref:`SmallPtrSet -`. +to :ref:`std::set `, but for pointers it uses something far better, +:ref:`SmallPtrSet `. The magic of this class is that it handles small sets extremely efficiently, but gracefully handles extremely large sets without loss of efficiency. The @@ -1120,16 +1120,31 @@ and erasing, but does not support iteration. llvm/ADT/SmallPtrSet.h ^^^^^^^^^^^^^^^^^^^^^^ -SmallPtrSet has all the advantages of ``SmallSet`` (and a ``SmallSet`` of +``SmallPtrSet`` has all the advantages of ``SmallSet`` (and a ``SmallSet`` of pointers is transparently implemented with a ``SmallPtrSet``), but also supports -iterators. If more than 'N' insertions are performed, a single quadratically +iterators. If more than N insertions are performed, a single quadratically probed hash table is allocated and grows as needed, providing extremely efficient access (constant time insertion/deleting/queries with low constant factors) and is very stingy with malloc traffic. -Note that, unlike ``std::set``, the iterators of ``SmallPtrSet`` are invalidated -whenever an insertion occurs. Also, the values visited by the iterators are not -visited in sorted order. +Note that, unlike :ref:`std::set `, the iterators of ``SmallPtrSet`` +are invalidated whenever an insertion occurs. Also, the values visited by the +iterators are not visited in sorted order. + +.. _dss_stringset: + +llvm/ADT/StringSet.h +^^^^^^^^^^^^^^^^^^^^ + +``StringSet`` is a thin wrapper around :ref:`StringMap\ `, +and it allows efficient storage and retrieval of unique strings. + +Functionally analogous to ``SmallSet``, ``StringSet`` also suports +iteration. (The iterator dereferences to a ``StringMapEntry``, so you +need to call ``i->getKey()`` to access the item of the StringSet.) On the +other hand, ``StringSet`` doesn't support range-insertion and +copy-construction, which :ref:`SmallSet ` and :ref:`SmallPtrSet +` do support. .. _dss_denseset: @@ -1297,8 +1312,9 @@ never use hash_set and unordered_set because they are generally very expensive (each insertion requires a malloc) and very non-portable. std::multiset is useful if you're not interested in elimination of duplicates, -but has all the drawbacks of std::set. A sorted vector (where you don't delete -duplicate entries) or some other approach is almost always better. +but has all the drawbacks of :ref:`std::set `. A sorted vector +(where you don't delete duplicate entries) or some other approach is almost +always better. .. _ds_map: @@ -1852,7 +1868,7 @@ Iterating over predecessors & successors of blocks ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Iterating over the predecessors and successors of a block is quite easy with the -routines defined in ``"llvm/Support/CFG.h"``. Just use code like this to +routines defined in ``"llvm/IR/CFG.h"``. Just use code like this to iterate over all predecessors of BB: .. code-block:: c++ diff --git a/docs/R600Usage.rst b/docs/R600Usage.rst deleted file mode 100644 index 093cdd762b4..00000000000 --- a/docs/R600Usage.rst +++ /dev/null @@ -1,89 +0,0 @@ -============================ -User Guide for R600 Back-end -============================ - -Introduction -============ - -The R600 back-end provides ISA code generation for AMD GPUs, starting with -the R600 family up until the current Volcanic Islands (GCN Gen 3). - - -Assembler -========= - -The assembler is currently considered experimental. - -For syntax examples look in test/MC/R600. - -Below some of the currently supported features (modulo bugs). These -all apply to the Southern Islands ISA, Sea Islands and Volcanic Islands -are also supported but may be missing some instructions and have more bugs: - -DS Instructions ---------------- -All DS instructions are supported. - -MUBUF Instructions ------------------- -All non-atomic MUBUF instructions are supported. - -SMRD Instructions ------------------ -Only the s_load_dword* SMRD instructions are supported. - -SOP1 Instructions ------------------ -All SOP1 instructions are supported. - -SOP2 Instructions ------------------ -All SOP2 instructions are supported. - -SOPC Instructions ------------------ -All SOPC instructions are supported. - -SOPP Instructions ------------------ - -Unless otherwise mentioned, all SOPP instructions that have one or more -operands accept integer operands only. No verification is performed -on the operands, so it is up to the programmer to be familiar with the -range or acceptable values. - -s_waitcnt -^^^^^^^^^ - -s_waitcnt accepts named arguments to specify which memory counter(s) to -wait for. - -.. code-block:: nasm - - // Wait for all counters to be 0 - s_waitcnt 0 - - // Equivalent to s_waitcnt 0. Counter names can also be delimited by - // '&' or ','. - s_waitcnt vmcnt(0) expcnt(0) lgkcmt(0) - - // Wait for vmcnt counter to be 1. - s_waitcnt vmcnt(1) - -VOP1, VOP2, VOP3, VOPC Instructions ------------------------------------ - -All 32-bit and 64-bit encodings should work. - -The assembler will automatically detect which encoding size to use for -VOP1, VOP2, and VOPC instructions based on the operands. If you want to force -a specific encoding size, you can add an _e32 (for 32-bit encoding) or -_e64 (for 64-bit encoding) suffix to the instruction. Most, but not all -instructions support an explicit suffix. These are all valid assembly -strings: - -.. code-block:: nasm - - v_mul_i32_i24 v1, v2, v3 - v_mul_i32_i24_e32 v1, v2, v3 - v_mul_i32_i24_e64 v1, v2, v3 diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst index c0d2ea18981..17c5c069d5f 100644 --- a/docs/ReleaseNotes.rst +++ b/docs/ReleaseNotes.rst @@ -1,12 +1,12 @@ ====================== -LLVM 3.7 Release Notes +LLVM 3.8 Release Notes ====================== .. contents:: :local: .. warning:: - These are in-progress notes for the upcoming LLVM 3.7 release. You may + These are in-progress notes for the upcoming LLVM 3.8 release. You may prefer the `LLVM 3.6 Release Notes `_. @@ -15,7 +15,7 @@ Introduction ============ This document contains the release notes for the LLVM Compiler Infrastructure, -release 3.7. Here we describe the status of LLVM, including major improvements +release 3.8. Here we describe the status of LLVM, including major improvements from the previous release, improvements in various subprojects of LLVM, and some of the current users of the code. All LLVM releases may be downloaded from the `LLVM releases web site `_. @@ -41,18 +41,6 @@ Non-comprehensive list of changes in this release functionality, or simply have a lot to talk about), see the `NOTE` below for adding a new subsection. -* The minimum required Visual Studio version for building LLVM is now 2013 - Update 4. - -* A new documentation page, :doc:`Frontend/PerformanceTips`, contains a - collection of tips for frontend authors on how to generate IR which LLVM is - able to effectively optimize. - -* The DataLayout is no longer optional. All the IR level optimizations expects - it to be present and the API has been changed to use a reference instead of - a pointer to make it explicit. The Module owns the datalayout and it has to - match the one attached to the TargetMachine for generating code. - * ... next change ... .. NOTE @@ -89,12 +77,12 @@ Changes to the OCaml bindings During this release ... -External Open Source Projects Using LLVM 3.7 +External Open Source Projects Using LLVM 3.8 ============================================ An exciting aspect of LLVM is that it is used as an enabling technology for a lot of other language and tools projects. This section lists some of the -projects that have already been updated to work with LLVM 3.7. +projects that have already been updated to work with LLVM 3.8. * A project diff --git a/docs/SourceLevelDebugging.rst b/docs/SourceLevelDebugging.rst index 55e12d3efa0..99186f58188 100644 --- a/docs/SourceLevelDebugging.rst +++ b/docs/SourceLevelDebugging.rst @@ -153,8 +153,8 @@ debugger to interpret the information. To provide basic functionality, the LLVM debugger does have to make some assumptions about the source-level language being debugged, though it keeps these to a minimum. The only common features that the LLVM debugger assumes -exist are `source files `_, and `program objects -`_. These abstract objects are used by a +exist are `source files `_, and `program objects +`_. These abstract objects are used by a debugger to form stack traces, show information about local variables, etc. This section of the documentation first describes the representation aspects @@ -177,27 +177,27 @@ provide debug information at various points in generated code. .. code-block:: llvm - void %llvm.dbg.declare(metadata, metadata, metadata) + void @llvm.dbg.declare(metadata, metadata, metadata) This intrinsic provides information about a local element (e.g., variable). The first argument is metadata holding the alloca for the variable. The second -argument is a `local variable `_ containing a +argument is a `local variable `_ containing a description of the variable. The third argument is a `complex expression -`_. +`_. ``llvm.dbg.value`` ^^^^^^^^^^^^^^^^^^ .. code-block:: llvm - void %llvm.dbg.value(metadata, i64, metadata, metadata) + void @llvm.dbg.value(metadata, i64, metadata, metadata) This intrinsic provides information when a user source variable is set to a new value. The first argument is the new value (wrapped as metadata). The second argument is the offset in the user source variable where the new value is written. The third argument is a `local variable -`_ containing a description of the variable. The -third argument is a `complex expression `_. +`_ containing a description of the variable. The +third argument is a `complex expression `_. Object lifetimes and scoping ============================ @@ -259,31 +259,31 @@ Compiled to LLVM, this function would be represented like this: !llvm.module.flags = !{!7, !8, !9} !llvm.ident = !{!10} - !0 = !MDCompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.7.0 (trunk 231150) (llvm/trunk 231154)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !2, subprograms: !3, globals: !2, imports: !2) - !1 = !MDFile(filename: "/dev/stdin", directory: "/Users/dexonsmith/data/llvm/debug-info") + !0 = !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.7.0 (trunk 231150) (llvm/trunk 231154)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !2, subprograms: !3, globals: !2, imports: !2) + !1 = !DIFile(filename: "/dev/stdin", directory: "/Users/dexonsmith/data/llvm/debug-info") !2 = !{} !3 = !{!4} - !4 = !MDSubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, function: void ()* @foo, variables: !2) - !5 = !MDSubroutineType(types: !6) + !4 = !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, function: void ()* @foo, variables: !2) + !5 = !DISubroutineType(types: !6) !6 = !{null} !7 = !{i32 2, !"Dwarf Version", i32 2} !8 = !{i32 2, !"Debug Info Version", i32 3} !9 = !{i32 1, !"PIC Level", i32 2} !10 = !{!"clang version 3.7.0 (trunk 231150) (llvm/trunk 231154)"} - !11 = !MDLocalVariable(tag: DW_TAG_auto_variable, name: "X", scope: !4, file: !1, line: 2, type: !12) - !12 = !MDBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) - !13 = !MDExpression() - !14 = !MDLocation(line: 2, column: 9, scope: !4) - !15 = !MDLocalVariable(tag: DW_TAG_auto_variable, name: "Y", scope: !4, file: !1, line: 3, type: !12) - !16 = !MDLocation(line: 3, column: 9, scope: !4) - !17 = !MDLocalVariable(tag: DW_TAG_auto_variable, name: "Z", scope: !18, file: !1, line: 5, type: !12) - !18 = distinct !MDLexicalBlock(scope: !4, file: !1, line: 4, column: 5) - !19 = !MDLocation(line: 5, column: 11, scope: !18) - !20 = !MDLocation(line: 6, column: 11, scope: !18) - !21 = !MDLocation(line: 6, column: 9, scope: !18) - !22 = !MDLocation(line: 8, column: 9, scope: !4) - !23 = !MDLocation(line: 8, column: 7, scope: !4) - !24 = !MDLocation(line: 9, column: 3, scope: !4) + !11 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "X", scope: !4, file: !1, line: 2, type: !12) + !12 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) + !13 = !DIExpression() + !14 = !DILocation(line: 2, column: 9, scope: !4) + !15 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "Y", scope: !4, file: !1, line: 3, type: !12) + !16 = !DILocation(line: 3, column: 9, scope: !4) + !17 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "Z", scope: !18, file: !1, line: 5, type: !12) + !18 = distinct !DILexicalBlock(scope: !4, file: !1, line: 4, column: 5) + !19 = !DILocation(line: 5, column: 11, scope: !18) + !20 = !DILocation(line: 6, column: 11, scope: !18) + !21 = !DILocation(line: 6, column: 9, scope: !18) + !22 = !DILocation(line: 8, column: 9, scope: !4) + !23 = !DILocation(line: 8, column: 7, scope: !4) + !24 = !DILocation(line: 9, column: 3, scope: !4) This example illustrates a few important details about LLVM debugging @@ -303,15 +303,15 @@ scope information for the variable ``X``. .. code-block:: llvm - !14 = !MDLocation(line: 2, column: 9, scope: !4) - !4 = !MDSubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !5, + !14 = !DILocation(line: 2, column: 9, scope: !4) + !4 = !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, function: void ()* @foo, variables: !2) Here ``!14`` is metadata providing `location information -`_. In this example, scope is encoded by ``!4``, a -`subprogram descriptor `_. This way the location +`_. In this example, scope is encoded by ``!4``, a +`subprogram descriptor `_. This way the location information attached to the intrinsics indicates that the variable ``X`` is declared at line number 2 at a function level scope in function ``foo``. @@ -328,8 +328,8 @@ scope information for the variable ``Z``. .. code-block:: llvm - !18 = distinct !MDLexicalBlock(scope: !4, file: !1, line: 4, column: 5) - !19 = !MDLocation(line: 5, column: 11, scope: !18) + !18 = distinct !DILexicalBlock(scope: !4, file: !1, line: 4, column: 5) + !19 = !DILocation(line: 5, column: 11, scope: !18) Here ``!19`` indicates that ``Z`` is declared at line number 5 and column number 0 inside of lexical scope ``!18``. The lexical scope itself resides @@ -406,7 +406,7 @@ a C/C++ front-end would generate the following descriptors: !llvm.module.flags = !{!6, !7} ;; Define the compile unit. - !0 = !MDCompileUnit(language: DW_LANG_C99, file: !1, + !0 = !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.7.0 (trunk 231150) (llvm/trunk 231154)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, @@ -416,7 +416,7 @@ a C/C++ front-end would generate the following descriptors: ;; ;; Define the file ;; - !1 = !MDFile(filename: "/dev/stdin", + !1 = !DIFile(filename: "/dev/stdin", directory: "/Users/dexonsmith/data/llvm/debug-info") ;; An empty array. @@ -428,14 +428,14 @@ a C/C++ front-end would generate the following descriptors: ;; ;; Define the global variable itself. ;; - !4 = !MDGlobalVariable(name: "MyGlobal", scope: !0, file: !1, line: 1, + !4 = !DIGlobalVariable(name: "MyGlobal", scope: !0, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, variable: i32* @MyGlobal) ;; ;; Define the type ;; - !5 = !MDBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) + !5 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) ;; Dwarf version to output. !6 = !{i32 2, !"Dwarf Version", i32 2} @@ -461,7 +461,7 @@ a C/C++ front-end would generate the following descriptors: ;; ;; Define the anchor for subprograms. ;; - !4 = !MDSubprogram(name: "main", scope: !1, file: !1, line: 1, type: !5, + !4 = !DISubprogram(name: "main", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, function: i32 (i32, i8**)* @main, variables: !2) diff --git a/docs/StackMaps.rst b/docs/StackMaps.rst index 43c60c9e785..5bdae38b699 100644 --- a/docs/StackMaps.rst +++ b/docs/StackMaps.rst @@ -221,12 +221,10 @@ lowered according to the calling convention specified at the intrinsic's callsite. Variants of the intrinsic with non-void return type also return a value according to calling convention. -On PowerPC, note that ```` must be the actual intended target of -the indirect call. Specifically, even when compiling for the ELF V1 ABI, -```` is not the function-descriptor address normally used as the C/C++ -function-pointer representation. As a result, the call target must be local -because no adjustment or restoration of the TOC pointer (in register r2) will -be performed. +On PowerPC, note that ```` must be the ABI function pointer for the +intended target of the indirect call. Specifically, when compiling for the +ELF V1 ABI, ```` is the function-descriptor address normally used as +the C/C++ function-pointer representation. Requesting zero patch point arguments is valid. In this case, all variable operands are handled just like @@ -501,3 +499,13 @@ the same requirement imposed by the llvm.gcroot intrinsic.) LLVM transformations must not substitute the alloca with any intervening value. This can be verified by the runtime simply by checking that the stack map's location is a Direct location type. + + +Supported Architectures +======================= + +Support for StackMap generation and the related intrinsics requires +some code for each backend. Today, only a subset of LLVM's backends +are supported. The currently supported architectures are X86_64, +PowerPC, and Aarch64. + diff --git a/docs/Statepoints.rst b/docs/Statepoints.rst index 9741c93cc81..2b01374a9ec 100644 --- a/docs/Statepoints.rst +++ b/docs/Statepoints.rst @@ -142,8 +142,8 @@ resulting relocation sequence is: define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj) gc "statepoint-example" { - %0 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj) - %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 9, i32 9) + %0 = call i32 (i64, i32, void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj) + %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 7, i32 7) ret i8 addrspace(1)* %obj.relocated } @@ -207,7 +207,82 @@ This example was taken from the tests for the :ref:`RewriteStatepointsForGC` uti opt -rewrite-statepoints-for-gc test/Transforms/RewriteStatepointsForGC/basics.ll -S | llc -debug-only=stackmaps +GC Transitions +^^^^^^^^^^^^^^^^^^ + +As a practical consideration, many garbage-collected systems allow code that is +collector-aware ("managed code") to call code that is not collector-aware +("unmanaged code"). It is common that such calls must also be safepoints, since +it is desirable to allow the collector to run during the execution of +unmanaged code. Futhermore, it is common that coordinating the transition from +managed to unmanaged code requires extra code generation at the call site to +inform the collector of the transition. In order to support these needs, a +statepoint may be marked as a GC transition, and data that is necessary to +perform the transition (if any) may be provided as additional arguments to the +statepoint. + + Note that although in many cases statepoints may be inferred to be GC + transitions based on the function symbols involved (e.g. a call from a + function with GC strategy "foo" to a function with GC strategy "bar"), + indirect calls that are also GC transitions must also be supported. This + requirement is the driving force behing the decision to require that GC + transitions are explicitly marked. + +Let's revisit the sample given above, this time treating the call to ``@foo`` +as a GC transition. Depending on our target, the transition code may need to +access some extra state in order to inform the collector of the transition. +Let's assume a hypothetical GC--somewhat unimaginatively named "hypothetical-gc" +--that requires that a TLS variable must be written to before and after a call +to unmanaged code. The resulting relocation sequence is: +.. code-block:: llvm + + @flag = thread_local global i32 0, align 4 + + define i8 addrspace(1)* @test1(i8 addrspace(1) *%obj) + gc "hypothetical-gc" { + + %0 = call i32 (i64, i32, void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @foo, i32 0, i32 1, i32* @Flag, i32 0, i8 addrspace(1)* %obj) + %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 7, i32 7) + ret i8 addrspace(1)* %obj.relocated + } + +During lowering, this will result in a instruction selection DAG that looks +something like: + +:: + + CALLSEQ_START + ... + GC_TRANSITION_START (lowered i32 *@Flag), SRCVALUE i32* Flag + STATEPOINT + GC_TRANSITION_END (lowered i32 *@Flag), SRCVALUE i32 *Flag + ... + CALLSEQ_END + +In order to generate the necessary transition code, the backend for each target +supported by "hypothetical-gc" must be modified to lower ``GC_TRANSITION_START`` +and ``GC_TRANSITION_END`` nodes appropriately when the "hypothetical-gc" +strategy is in use for a particular function. Assuming that such lowering has +been added for X86, the generated assembly would be: + +.. code-block:: gas + + .globl test1 + .align 16, 0x90 + pushq %rax + movl $1, %fs:Flag@TPOFF + callq foo + movl $0, %fs:Flag@TPOFF + .Ltmp1: + movq (%rsp), %rax # This load is redundant (oops!) + popq %rdx + retq + +Note that the design as presented above is not fully implemented: in particular, +strategy-specific lowering is not present, and all GC transitions are emitted as +as single no-op before and after the call instruction. These no-ops are often +removed by the backend during dead machine instruction elimination. Intrinsics @@ -222,9 +297,11 @@ Syntax: :: declare i32 - @llvm.experimental.gc.statepoint(func_type , - i64 <#call args>. i64 , + @llvm.experimental.gc.statepoint(i64 , i32 , + func_type , + i64 <#call args>, i64 , ... (call parameters), + i64 <# transition args>, ... (transition parameters), i64 <# deopt args>, ... (deopt parameters), ... (gc parameters)) @@ -237,6 +314,28 @@ runtime. Operands: """"""""" +The 'id' operand is a constant integer that is reported as the ID +field in the generated stackmap. LLVM does not interpret this +parameter in any way and its meaning is up to the statepoint user to +decide. Note that LLVM is free to duplicate code containing +statepoint calls, and this may transform IR that had a unique 'id' per +lexical call to statepoint to IR that does not. + +If 'num patch bytes' is non-zero then the call instruction +corresponding to the statepoint is not emitted and LLVM emits 'num +patch bytes' bytes of nops in its place. LLVM will emit code to +prepare the function arguments and retrieve the function return value +in accordance to the calling convention; the former before the nop +sequence and the latter after the nop sequence. It is expected that +the user will patch over the 'num patch bytes' bytes of nops with a +calling sequence specific to their runtime before executing the +generated machine code. There are no guarantees with respect to the +alignment of the nop sequence. Unlike :doc:`StackMaps` statepoints do +not have a concept of shadow bytes. Note that semantically the +statepoint still represents a call or invoke to 'target', and the nop +sequence after patching is expected to represent an operation +equivalent to a call or invoke to 'target'. + The 'target' operand is the function actually being called. The target can be specified as either a symbolic LLVM function, or as an arbitrary Value of appropriate function type. Note that the function @@ -247,8 +346,19 @@ The '#call args' operand is the number of arguments to the actual call. It must exactly match the number of arguments passed in the 'call parameters' variable length section. -The 'unused' operand is unused and likely to be removed. Please do -not use. +The 'flags' operand is used to specify extra information about the +statepoint. This is currently only used to mark certain statepoints +as GC transitions. This operand is a 64-bit integer with the following +layout, where bit 0 is the least significant bit: + + +-------+---------------------------------------------------+ + | Bit # | Usage | + +=======+===================================================+ + | 0 | Set if the statepoint is a GC transition, cleared | + | | otherwise. | + +-------+---------------------------------------------------+ + | 1-63 | Reserved for future use; must be cleared. | + +-------+---------------------------------------------------+ The 'call parameters' arguments are simply the arguments which need to be passed to the call target. They will be lowered according to the @@ -257,6 +367,14 @@ instruction. The number of arguments must exactly match what is specified in '# call args'. The types must match the signature of 'target'. +The 'transition parameters' arguments contain an arbitrary list of +Values which need to be passed to GC transition code. They will be +lowered and passed as operands to the appropriate GC_TRANSITION nodes +in the selection DAG. It is assumed that these arguments must be +available before and after (but not necessarily during) the execution +of the callee. The '# transition args' field indicates how many operands +are to be interpreted as 'transition parameters'. + The 'deopt parameters' arguments contain an arbitrary list of Values which is meaningful to the runtime. The runtime may read any of these values, but is assumed not to modify them. If the garbage collector @@ -388,6 +506,12 @@ the runtime or collector are provided via the :ref:`Stack Map format Each statepoint generates the following Locations: +* Constant which describes the calling convention of the call target. This + constant is a valid :ref:`calling convention identifier ` for + the version of LLVM used to generate the stackmap. No additional compatibility + guarantees are made for this constant over what LLVM provides elsewhere w.r.t. + these identifiers. +* Constant which describes the flags passed to the statepoint intrinsic * Constant which describes number of following deopt *Locations* (not operands) * Variable number of Locations, one for each deopt parameter listed in @@ -405,9 +529,6 @@ Note that the Locations used in each section may describe the same physical location. e.g. A stack slot may appear as a deopt location, a gc base pointer, and a gc derived pointer. -The ID field of the 'StkMapRecord' for a statepoint is meaningless and -it's value is explicitly unspecified. - The LiveOut section of the StkMapRecord will be empty for a statepoint record. @@ -471,7 +592,7 @@ As an example, given this code: define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj) gc "statepoint-example" { - call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + call i32 (i64, i32, void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) ret i8 addrspace(1)* %obj } @@ -481,8 +602,8 @@ The pass would produce this IR: define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj) gc "statepoint-example" { - %0 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj) - %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 9, i32 9) + %0 = call i32 (i64, i32, void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj) + %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 12, i32 12) ret i8 addrspace(1)* %obj.relocated } @@ -535,8 +656,8 @@ This pass would produce the following IR: .. code-block:: llvm define void @test() gc "statepoint-example" { - %safepoint_token = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0) - %safepoint_token1 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (i64, i32, void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0) + %safepoint_token1 = call i32 (i64, i32, void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) ret void } @@ -558,6 +679,21 @@ of this function is inserted at each poll site desired. While calls or invokes inside this method are transformed to a ``gc.statepoints``, recursive poll insertion is not performed. +By default PlaceSafepoints passes in ``0xABCDEF00`` as the statepoint +ID and ``0`` as the number of patchable bytes to the newly constructed +``gc.statepoint``. These values can be configured on a per-callsite +basis using the attributes ``"statepoint-id"`` and +``"statepoint-num-patch-bytes"``. If a call site is marked with a +``"statepoint-id"`` function attribute and its value is a positive +integer (represented as a string), then that value is used as the ID +of the newly constructed ``gc.statepoint``. If a call site is marked +with a ``"statepoint-num-patch-bytes"`` function attribute and its +value is a positive integer, then that value is used as the 'num patch +bytes' parameter of the newly constructed ``gc.statepoint``. The +``"statepoint-id"`` and ``"statepoint-num-patch-bytes"`` attributes +are not propagated to the ``gc.statepoint`` call or invoke if they +could be successfully parsed. + If you are scheduling the RewriteStatepointsForGC pass late in the pass order, you should probably schedule this pass immediately before it. The exception would be if you need to preserve abstract frame information (e.g. for @@ -565,6 +701,12 @@ deoptimization or introspection) at safepoints. In that case, ask on the llvmdev mailing list for suggestions. +Supported Architectures +======================= + +Support for statepoint generation requires some code for each backend. +Today, only X86_64 is supported. + Bugs and Enhancements ===================== diff --git a/docs/TableGen/LangIntro.rst b/docs/TableGen/LangIntro.rst index 85c74a5b460..4d4551e8a6e 100644 --- a/docs/TableGen/LangIntro.rst +++ b/docs/TableGen/LangIntro.rst @@ -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. diff --git a/docs/TestingGuide.rst b/docs/TestingGuide.rst index 3463156495a..adf5f3d4cfb 100644 --- a/docs/TestingGuide.rst +++ b/docs/TestingGuide.rst @@ -473,6 +473,25 @@ RUN lines: To add more substituations, look at ``test/lit.cfg`` or ``lit.local.cfg``. +Options +------- + +The llvm lit configuration allows to customize some things with user options: + +``llc``, ``opt``, ... + Substitute the respective llvm tool name with a custom command line. This + allows to specify custom paths and default arguments for these tools. + Example: + + % llvm-lit "-Dllc=llc -verify-machineinstrs" + +``run_long_tests`` + Enable the execution of long running tests. + +``llvm_site_config`` + Load the specified lit configuration instead of the default one. + + Other Features -------------- diff --git a/docs/YamlIO.rst b/docs/YamlIO.rst index 3cc683b6b82..f0baeb4c69d 100644 --- a/docs/YamlIO.rst +++ b/docs/YamlIO.rst @@ -456,10 +456,10 @@ looks like: template <> struct ScalarTraits { - static void output(const T &value, llvm::raw_ostream &out) { + static void output(const T &value, void*, llvm::raw_ostream &out) { out << value; // do custom formatting here } - static StringRef input(StringRef scalar, T &value) { + static StringRef input(StringRef scalar, void*, T &value) { // do custom parsing here. Return the empty string on success, // or an error message on failure. return StringRef(); @@ -467,6 +467,56 @@ looks like: // Determine if this scalar needs quotes. static bool mustQuote(StringRef) { return true; } }; + +Block Scalars +------------- + +YAML block scalars are string literals that are represented in YAML using the +literal block notation, just like the example shown below: + +.. code-block:: yaml + + text: | + First line + Second line + +The YAML I/O library provides support for translating between YAML block scalars +and specific C++ types by allowing you to specialize BlockScalarTraits<> on +your data type. The library doesn't provide any built-in support for block +scalar I/O for types like std::string and llvm::StringRef as they are already +supported by YAML I/O and use the ordinary scalar notation by default. + +BlockScalarTraits specializations are very similar to the +ScalarTraits specialization - YAML I/O will provide the native type and your +specialization must create a temporary llvm::StringRef when writing, and +it will also provide an llvm::StringRef that has the value of that block scalar +and your specialization must convert that to your native data type when reading. +An example of a custom type with an appropriate specialization of +BlockScalarTraits is shown below: + +.. code-block:: c++ + + using llvm::yaml::BlockScalarTraits; + using llvm::yaml::IO; + + struct MyStringType { + std::string Str; + }; + + template <> + struct BlockScalarTraits { + static void output(const MyStringType &Value, void *Ctxt, + llvm::raw_ostream &OS) { + OS << Value.Str; + } + + static StringRef input(StringRef Scalar, void *Ctxt, + MyStringType &Value) { + Value.Str = Scalar.str(); + return StringRef(); + } + }; + Mappings @@ -723,6 +773,33 @@ because it is a programming error to have invalid struct values. } }; +Flow Mapping +------------ +A YAML "flow mapping" is a mapping that uses the inline notation +(e.g { x: 1, y: 0 } ) when written to YAML. To specify that a type should be +written in YAML using flow mapping, your MappingTraits specialization should +add "static const bool flow = true;". For instance: + +.. code-block:: c++ + + using llvm::yaml::MappingTraits; + using llvm::yaml::IO; + + struct Stuff { + ... + }; + + template <> + struct MappingTraits { + static void mapping(IO &io, Stuff &stuff) { + ... + } + + static const bool flow = true; + } + +Flow mappings are subject to line wrapping according to the Output object +configuration. Sequence ======== @@ -770,6 +847,8 @@ With the above, if you used MyList as the data type in your native data structures, then when converted to YAML, a flow sequence of integers will be used (e.g. [ 10, -3, 4 ]). +Flow sequences are subject to line wrapping according to the Output object +configuration. Utility Macros -------------- @@ -833,14 +912,14 @@ Output The llvm::yaml::Output class is used to generate a YAML document from your in-memory data structures, using traits defined on your data types. -To instantiate an Output object you need an llvm::raw_ostream, and optionally -a context pointer: +To instantiate an Output object you need an llvm::raw_ostream, an optional +context pointer and an optional wrapping column: .. code-block:: c++ class Output : public IO { public: - Output(llvm::raw_ostream &, void *context=NULL); + Output(llvm::raw_ostream &, void *context = NULL, int WrapColumn = 70); Once you have an Output object, you can use the C++ stream operator on it to write your native data as YAML. One thing to recall is that a YAML file @@ -849,6 +928,10 @@ streaming as YAML is a mapping, scalar, or sequence, then Output assumes you are generating one document and wraps the mapping output with "``---``" and trailing "``...``". +The WrapColumn parameter will cause the flow mappings and sequences to +line-wrap when they go over the supplied column. Pass 0 to completely +suppress the wrapping. + .. code-block:: c++ using llvm::yaml::Output; diff --git a/docs/_ocamldoc/style.css b/docs/_ocamldoc/style.css new file mode 100644 index 00000000000..00595d7f2f2 --- /dev/null +++ b/docs/_ocamldoc/style.css @@ -0,0 +1,97 @@ +/* A style for ocamldoc. Daniel C. Buenzli */ + +/* Reset a few things. */ +html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre, +a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp, +small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset, +form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td +{ margin: 0; padding: 0; border: 0 none; outline: 0; font-size: 100%; + font-weight: inherit; font-style:inherit; font-family:inherit; + line-height: inherit; vertical-align: baseline; text-align:inherit; + color:inherit; background: transparent; } + +table { border-collapse: collapse; border-spacing: 0; } + +/* Basic page layout */ + +body { font: normal 10pt/1.375em helvetica, arial, sans-serif; text-align:left; + margin: 1.375em 10%; min-width: 40ex; max-width: 72ex; + color: black; background: transparent /* url(line-height-22.gif) */; } + +b { font-weight: bold } +em { font-style: italic } + +tt, code, pre { font-family: WorkAroundWebKitAndMozilla, monospace; + font-size: 1em; } +pre code { font-size : inherit; } +.codepre { margin-bottom:1.375em /* after code example we introduce space. */ } + +.superscript,.subscript +{ font-size : 0.813em; line-height:0; margin-left:0.4ex;} +.superscript { vertical-align: super; } +.subscript { vertical-align: sub; } + +/* ocamldoc markup workaround hacks */ + + + +hr, hr + br, div + br, center + br, span + br, ul + br, ol + br, pre + br +{ display: none } /* annoying */ + +div.info + br { display:block} + +.codepre br + br { display: none } +h1 + pre { margin-bottom:1.375em} /* Toplevel module description */ + +/* Sections and document divisions */ + +/* .navbar { margin-bottom: -1.375em } */ +h1 { font-weight: bold; font-size: 1.5em; /* margin-top:1.833em; */ + margin-top:0.917em; padding-top:0.875em; + border-top-style:solid; border-width:1px; border-color:#AAA; } +h2 { font-weight: bold; font-size: 1.313em; margin-top: 1.048em } +h3 { font-weight: bold; font-size: 1.125em; margin-top: 1.222em } +h3 { font-weight: bold; font-size: 1em; margin-top: 1.375em} +h4 { font-style: italic; } + +/* Used by OCaml's own library documentation. */ + h6 { font-weight: bold; font-size: 1.125em; margin-top: 1.222em } + .h7 { font-weight: bold; font-size: 1em; margin-top: 1.375em } + +p { margin-top: 1.375em } +pre { margin-top: 1.375em } +.info { margin: 0.458em 0em -0.458em 2em;}/* Description of types values etc. */ +td .info { margin:0; padding:0; margin-left: 2em;} /* Description in indexes */ + +ul, ol { margin-top:0.688em; padding-bottom:0.687em; + list-style-position:outside} +ul + p, ol + p { margin-top: 0em } +ul { list-style-type: square } + + +/* h2 + ul, h3 + ul, p + ul { } */ +ul > li { margin-left: 1.375em; } +ol > li { margin-left: 1.7em; } +/* Links */ + +a, a:link, a:visited, a:active, a:hover { color : #00B; text-decoration: none } +a:hover { text-decoration : underline } +*:target {background-color: #FFFF99;} /* anchor highlight */ + +/* Code */ + +.keyword { font-weight: bold; } +.comment { color : red } +.constructor { color : green } +.string { color : brown } +.warning { color : red ; font-weight : bold } + +/* Functors */ + +.paramstable { border-style : hidden ; padding-bottom:1.375em} +.paramstable code { margin-left: 1ex; margin-right: 1ex } +.sig_block {margin-left: 1em} + +/* Images */ + +img { margin-top: 1.375em } diff --git a/docs/conf.py b/docs/conf.py index 18972824dbb..e1e6c45a56f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -47,9 +47,9 @@ # built documents. # # The short X.Y version. -version = '3.7' +version = '3.8' # The full version, including alpha/beta/rc tags. -release = '3.7' +release = '3.8' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/doxygen.cfg.in b/docs/doxygen.cfg.in index 114c9d11c06..d8c4051e563 100644 --- a/docs/doxygen.cfg.in +++ b/docs/doxygen.cfg.in @@ -169,7 +169,7 @@ SHORT_NAMES = NO # description.) # The default value is: NO. -JAVADOC_AUTOBRIEF = NO +JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If @@ -177,7 +177,7 @@ JAVADOC_AUTOBRIEF = NO # requiring an explicit \brief command for a brief description.) # The default value is: NO. -QT_AUTOBRIEF = NO +QT_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as diff --git a/docs/index.rst b/docs/index.rst index 2cc5b8bf095..5c04a4e3fc9 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -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 ================================= diff --git a/docs/tutorial/LangImpl8.rst b/docs/tutorial/LangImpl8.rst index 4473035462c..24c4d171f85 100644 --- a/docs/tutorial/LangImpl8.rst +++ b/docs/tutorial/LangImpl8.rst @@ -187,13 +187,13 @@ expressions: static DIBuilder *DBuilder; struct DebugInfo { - DICompileUnit TheCU; - DIType DblTy; + DICompileUnit *TheCU; + DIType *DblTy; - DIType getDoubleTy(); + DIType *getDoubleTy(); } KSDbgInfo; - DIType DebugInfo::getDoubleTy() { + DIType *DebugInfo::getDoubleTy() { if (DblTy.isValid()) return DblTy; @@ -245,26 +245,26 @@ So the context: .. code-block:: c++ - DIFile Unit = DBuilder->createFile(KSDbgInfo.TheCU.getFilename(), - KSDbgInfo.TheCU.getDirectory()); + DIFile *Unit = DBuilder->createFile(KSDbgInfo.TheCU.getFilename(), + KSDbgInfo.TheCU.getDirectory()); -giving us a DIFile and asking the ``Compile Unit`` we created above for the +giving us an DIFile and asking the ``Compile Unit`` we created above for the directory and filename where we are currently. Then, for now, we use some source locations of 0 (since our AST doesn't currently have source location information) and construct our function definition: .. code-block:: c++ - DIDescriptor FContext(Unit); + DIScope *FContext = Unit; unsigned LineNo = 0; unsigned ScopeLine = 0; - DISubprogram SP = DBuilder->createFunction( + DISubprogram *SP = DBuilder->createFunction( FContext, Name, StringRef(), Unit, LineNo, CreateFunctionType(Args.size(), Unit), false /* internal linkage */, - true /* definition */, ScopeLine, DIDescriptor::FlagPrototyped, false, F); + true /* definition */, ScopeLine, DINode::FlagPrototyped, false, F); -and we now have a DISubprogram that contains a reference to all of our metadata -for the function. +and we now have an DISubprogram that contains a reference to all of our +metadata for the function. Source Locations ================ @@ -332,11 +332,11 @@ by constructing another small function: void DebugInfo::emitLocation(ExprAST *AST) { DIScope *Scope; if (LexicalBlocks.empty()) - Scope = &TheCU; + Scope = TheCU; else Scope = LexicalBlocks.back(); Builder.SetCurrentDebugLocation( - DebugLoc::get(AST->getLine(), AST->getCol(), DIScope(*Scope))); + DebugLoc::get(AST->getLine(), AST->getCol(), Scope)); } that both tells the main ``IRBuilder`` where we are, but also what scope @@ -348,10 +348,10 @@ of scopes: .. code-block:: c++ std::vector LexicalBlocks; - std::map FnScopeMap; + std::map FnScopeMap; -and keep a map of each function to the scope that it represents (a DISubprogram -is also a DIScope). +and keep a map of each function to the scope that it represents (an +DISubprogram is also an DIScope). Then we make sure to: @@ -393,15 +393,14 @@ argument allocas in ``PrototypeAST::CreateArgumentAllocas``. .. code-block:: c++ DIScope *Scope = KSDbgInfo.LexicalBlocks.back(); - DIFile Unit = DBuilder->createFile(KSDbgInfo.TheCU.getFilename(), - KSDbgInfo.TheCU.getDirectory()); - DIVariable D = DBuilder->createLocalVariable(dwarf::DW_TAG_arg_variable, - *Scope, Args[Idx], Unit, Line, - KSDbgInfo.getDoubleTy(), Idx); + DIFile *Unit = DBuilder->createFile(KSDbgInfo.TheCU.getFilename(), + KSDbgInfo.TheCU.getDirectory()); + DILocalVariable D = DBuilder->createParameterVariable( + Scope, Args[Idx], Idx + 1, Unit, Line, KSDbgInfo.getDoubleTy(), true); Instruction *Call = DBuilder->insertDeclare( Alloca, D, DBuilder->createExpression(), Builder.GetInsertBlock()); - Call->setDebugLoc(DebugLoc::get(Line, 0, *Scope)); + Call->setDebugLoc(DebugLoc::get(Line, 0, Scope)); Here we're doing a few things. First, we're grabbing our current scope for the variable so we can say what range of code our variable is valid diff --git a/docs/yaml2obj.rst b/docs/yaml2obj.rst index 1812e58914a..d18ce02a336 100644 --- a/docs/yaml2obj.rst +++ b/docs/yaml2obj.rst @@ -65,6 +65,7 @@ Here's a simplified Kwalify_ schema with an extension to allow alternate types. , IMAGE_FILE_MACHINE_AMD64 , IMAGE_FILE_MACHINE_ARM , IMAGE_FILE_MACHINE_ARMNT + , IMAGE_FILE_MACHINE_ARM64 , IMAGE_FILE_MACHINE_EBC , IMAGE_FILE_MACHINE_I386 , IMAGE_FILE_MACHINE_IA64 diff --git a/emscripten-version.txt b/emscripten-version.txt index 8b9623a5e15..73135129478 100644 --- a/emscripten-version.txt +++ b/emscripten-version.txt @@ -1,2 +1,2 @@ -1.35.1 +1.35.2 diff --git a/examples/BrainF/BrainF.cpp b/examples/BrainF/BrainF.cpp index 81c48b9ef8a..8026adc8d07 100644 --- a/examples/BrainF/BrainF.cpp +++ b/examples/BrainF/BrainF.cpp @@ -201,7 +201,8 @@ void BrainF::readloop(PHINode *phi, BasicBlock *oldbb, BasicBlock *testbb, case SYM_READ: { //%tape.%d = call i32 @getchar() - CallInst *getchar_call = builder->CreateCall(getchar_func, tapereg); + CallInst *getchar_call = + builder->CreateCall(getchar_func, {}, tapereg); getchar_call->setTailCall(false); Value *tape_0 = getchar_call; diff --git a/examples/ExceptionDemo/ExceptionDemo.cpp b/examples/ExceptionDemo/ExceptionDemo.cpp index fed42b7c2bc..81337c4823b 100644 --- a/examples/ExceptionDemo/ExceptionDemo.cpp +++ b/examples/ExceptionDemo/ExceptionDemo.cpp @@ -1293,10 +1293,11 @@ static llvm::Function *createCatchWrappedInvokeFunction( // (_Unwind_Exception instance). This member tells us whether or not // the exception is foreign. llvm::Value *unwindExceptionClass = - builder.CreateLoad(builder.CreateStructGEP( - builder.CreatePointerCast(unwindException, - ourUnwindExceptionType->getPointerTo()), - 0)); + builder.CreateLoad(builder.CreateStructGEP( + ourUnwindExceptionType, + builder.CreatePointerCast(unwindException, + ourUnwindExceptionType->getPointerTo()), + 0)); // Branch to the externalExceptionBlock if the exception is foreign or // to a catch router if not. Either way the finally block will be run. @@ -1336,10 +1337,10 @@ static llvm::Function *createCatchWrappedInvokeFunction( // // Note: Index is not relative to pointer but instead to structure // unlike a true getelementptr (GEP) instruction - typeInfoThrown = builder.CreateStructGEP(typeInfoThrown, 0); + typeInfoThrown = builder.CreateStructGEP(ourExceptionType, typeInfoThrown, 0); llvm::Value *typeInfoThrownType = - builder.CreateStructGEP(typeInfoThrown, 0); + builder.CreateStructGEP(builder.getInt8PtrTy(), typeInfoThrown, 0); generateIntegerPrint(context, module, diff --git a/examples/Kaleidoscope/Chapter4/toy.cpp b/examples/Kaleidoscope/Chapter4/toy.cpp index ad091e4496b..db59e265d2e 100644 --- a/examples/Kaleidoscope/Chapter4/toy.cpp +++ b/examples/Kaleidoscope/Chapter4/toy.cpp @@ -560,7 +560,7 @@ void *MCJITHelper::getPointerToFunction(Function *F) { // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. - OpenModule->setDataLayout(*NewEngine->getDataLayout()); + OpenModule->setDataLayout(NewEngine->getDataLayout()); // Provide basic AliasAnalysis support for GVN. FPM->add(createBasicAliasAnalysisPass()); // Promote allocas to registers. diff --git a/examples/Kaleidoscope/Chapter5/toy.cpp b/examples/Kaleidoscope/Chapter5/toy.cpp index db990489573..08d0b77e708 100644 --- a/examples/Kaleidoscope/Chapter5/toy.cpp +++ b/examples/Kaleidoscope/Chapter5/toy.cpp @@ -913,7 +913,7 @@ int main() { // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. - TheModule->setDataLayout(*TheExecutionEngine->getDataLayout()); + TheModule->setDataLayout(TheExecutionEngine->getDataLayout()); // Provide basic AliasAnalysis support for GVN. OurFPM.add(createBasicAliasAnalysisPass()); // Do simple "peephole" optimizations and bit-twiddling optzns. diff --git a/examples/Kaleidoscope/Chapter6/toy.cpp b/examples/Kaleidoscope/Chapter6/toy.cpp index e978a3ea368..109c43b9382 100644 --- a/examples/Kaleidoscope/Chapter6/toy.cpp +++ b/examples/Kaleidoscope/Chapter6/toy.cpp @@ -1034,7 +1034,7 @@ int main() { // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. - TheModule->setDataLayout(*TheExecutionEngine->getDataLayout()); + TheModule->setDataLayout(TheExecutionEngine->getDataLayout()); // Provide basic AliasAnalysis support for GVN. OurFPM.add(createBasicAliasAnalysisPass()); // Do simple "peephole" optimizations and bit-twiddling optzns. diff --git a/examples/Kaleidoscope/Chapter7/CMakeLists.txt b/examples/Kaleidoscope/Chapter7/CMakeLists.txt index 23aba6510b8..8725e4761f7 100644 --- a/examples/Kaleidoscope/Chapter7/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter7/CMakeLists.txt @@ -11,10 +11,6 @@ set(LLVM_LINK_COMPONENTS native ) -set(LLVM_REQUIRES_RTTI 1) - -set(LLVM_BUILD_EXAMPLES OFF) - add_kaleidoscope_chapter(Kaleidoscope-Ch7 toy.cpp ) diff --git a/examples/Kaleidoscope/Chapter7/Makefile b/examples/Kaleidoscope/Chapter7/Makefile index 7abeb3e5b67..c672c0a36c6 100644 --- a/examples/Kaleidoscope/Chapter7/Makefile +++ b/examples/Kaleidoscope/Chapter7/Makefile @@ -9,7 +9,6 @@ LEVEL = ../../.. TOOLNAME = Kaleidoscope-Ch7 EXAMPLE_TOOL = 1 -REQUIRES_RTTI := 1 LINK_COMPONENTS := core mcjit native diff --git a/examples/Kaleidoscope/Chapter7/toy.cpp b/examples/Kaleidoscope/Chapter7/toy.cpp index 53ea51c2b9c..0217fac10ec 100644 --- a/examples/Kaleidoscope/Chapter7/toy.cpp +++ b/examples/Kaleidoscope/Chapter7/toy.cpp @@ -713,7 +713,10 @@ Value *BinaryExprAST::Codegen() { // Special case '=' because we don't want to emit the LHS as an expression. if (Op == '=') { // Assignment requires the LHS to be an identifier. - VariableExprAST *LHSE = dynamic_cast(LHS); + // This assume we're building without RTTI because LLVM builds that way by + // default. If you build LLVM with RTTI this can be changed to a + // dynamic_cast for automatic error checking. + VariableExprAST *LHSE = static_cast(LHS); if (!LHSE) return ErrorV("destination of '=' must be a variable"); // Codegen the RHS. @@ -1208,7 +1211,7 @@ int main() { // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. - TheModule->setDataLayout(*TheExecutionEngine->getDataLayout()); + TheModule->setDataLayout(TheExecutionEngine->getDataLayout()); // Provide basic AliasAnalysis support for GVN. OurFPM.add(createBasicAliasAnalysisPass()); // Promote allocas to registers. diff --git a/examples/Kaleidoscope/Chapter8/CMakeLists.txt b/examples/Kaleidoscope/Chapter8/CMakeLists.txt index 90c79c0b9ae..f94ed743618 100644 --- a/examples/Kaleidoscope/Chapter8/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter8/CMakeLists.txt @@ -7,10 +7,6 @@ set(LLVM_LINK_COMPONENTS native ) -set(LLVM_REQUIRES_RTTI 1) - -set(LLVM_BUILD_EXAMPLES OFF) - add_kaleidoscope_chapter(Kaleidoscope-Ch8 toy.cpp ) diff --git a/examples/Kaleidoscope/Chapter8/Makefile b/examples/Kaleidoscope/Chapter8/Makefile index 8e4d4221178..25f048c39b0 100644 --- a/examples/Kaleidoscope/Chapter8/Makefile +++ b/examples/Kaleidoscope/Chapter8/Makefile @@ -9,7 +9,6 @@ LEVEL = ../../.. TOOLNAME = Kaleidoscope-Ch8 EXAMPLE_TOOL = 1 -REQUIRES_RTTI := 1 LINK_COMPONENTS := core mcjit native diff --git a/examples/Kaleidoscope/Chapter8/toy.cpp b/examples/Kaleidoscope/Chapter8/toy.cpp index c7e096cc484..f525ac7a1b0 100644 --- a/examples/Kaleidoscope/Chapter8/toy.cpp +++ b/examples/Kaleidoscope/Chapter8/toy.cpp @@ -93,13 +93,13 @@ class ExprAST; } static IRBuilder<> Builder(getGlobalContext()); struct DebugInfo { - DICompileUnit TheCU; - DIType DblTy; + DICompileUnit *TheCU; + DIType *DblTy; std::vector LexicalBlocks; - std::map FnScopeMap; + std::map FnScopeMap; void emitLocation(ExprAST *AST); - DIType getDoubleTy(); + DIType *getDoubleTy(); } KSDbgInfo; static std::string IdentifierStr; // Filled in if tok_identifier @@ -816,7 +816,7 @@ static PrototypeAST *ParseExtern() { static DIBuilder *DBuilder; -DIType DebugInfo::getDoubleTy() { +DIType *DebugInfo::getDoubleTy() { if (DblTy) return DblTy; @@ -827,18 +827,18 @@ DIType DebugInfo::getDoubleTy() { void DebugInfo::emitLocation(ExprAST *AST) { if (!AST) return Builder.SetCurrentDebugLocation(DebugLoc()); - MDScope *Scope; + DIScope *Scope; if (LexicalBlocks.empty()) Scope = TheCU; else - Scope = *LexicalBlocks.back(); + Scope = LexicalBlocks.back(); Builder.SetCurrentDebugLocation( DebugLoc::get(AST->getLine(), AST->getCol(), Scope)); } -static MDSubroutineType *CreateFunctionType(unsigned NumArgs, DIFile Unit) { +static DISubroutineType *CreateFunctionType(unsigned NumArgs, DIFile *Unit) { SmallVector EltTys; - DIType DblTy = KSDbgInfo.getDoubleTy(); + DIType *DblTy = KSDbgInfo.getDoubleTy(); // Add the result type. EltTys.push_back(DblTy); @@ -846,8 +846,8 @@ static MDSubroutineType *CreateFunctionType(unsigned NumArgs, DIFile Unit) { for (unsigned i = 0, e = NumArgs; i != e; ++i) EltTys.push_back(DblTy); - DITypeArray EltTypeArray = DBuilder->getOrCreateTypeArray(EltTys); - return DBuilder->createSubroutineType(Unit, EltTypeArray); + return DBuilder->createSubroutineType(Unit, + DBuilder->getOrCreateTypeArray(EltTys)); } //===----------------------------------------------------------------------===// @@ -908,7 +908,10 @@ Value *BinaryExprAST::Codegen() { // Special case '=' because we don't want to emit the LHS as an expression. if (Op == '=') { // Assignment requires the LHS to be an identifier. - VariableExprAST *LHSE = dynamic_cast(LHS); + // This assume we're building without RTTI because LLVM builds that way by + // default. If you build LLVM with RTTI this can be changed to a + // dynamic_cast for automatic error checking. + VariableExprAST *LHSE = static_cast(LHS); if (!LHSE) return ErrorV("destination of '=' must be a variable"); // Codegen the RHS. @@ -1224,15 +1227,15 @@ Function *PrototypeAST::Codegen() { AI->setName(Args[Idx]); // Create a subprogram DIE for this function. - DIFile Unit = DBuilder->createFile(KSDbgInfo.TheCU->getFilename(), - KSDbgInfo.TheCU->getDirectory()); - MDScope *FContext = Unit; + DIFile *Unit = DBuilder->createFile(KSDbgInfo.TheCU->getFilename(), + KSDbgInfo.TheCU->getDirectory()); + DIScope *FContext = Unit; unsigned LineNo = Line; unsigned ScopeLine = Line; - DISubprogram SP = DBuilder->createFunction( + DISubprogram *SP = DBuilder->createFunction( FContext, Name, StringRef(), Unit, LineNo, CreateFunctionType(Args.size(), Unit), false /* internal linkage */, - true /* definition */, ScopeLine, DebugNode::FlagPrototyped, false, F); + true /* definition */, ScopeLine, DINode::FlagPrototyped, false, F); KSDbgInfo.FnScopeMap[this] = SP; return F; @@ -1248,14 +1251,13 @@ void PrototypeAST::CreateArgumentAllocas(Function *F) { // Create a debug descriptor for the variable. DIScope *Scope = KSDbgInfo.LexicalBlocks.back(); - DIFile Unit = DBuilder->createFile(KSDbgInfo.TheCU->getFilename(), - KSDbgInfo.TheCU->getDirectory()); - DIVariable D = DBuilder->createLocalVariable(dwarf::DW_TAG_arg_variable, - *Scope, Args[Idx], Unit, Line, - KSDbgInfo.getDoubleTy(), Idx); + DIFile *Unit = DBuilder->createFile(KSDbgInfo.TheCU->getFilename(), + KSDbgInfo.TheCU->getDirectory()); + DILocalVariable *D = DBuilder->createParameterVariable( + Scope, Args[Idx], Idx + 1, Unit, Line, KSDbgInfo.getDoubleTy(), true); DBuilder->insertDeclare(Alloca, D, DBuilder->createExpression(), - DebugLoc::get(Line, 0, *Scope), + DebugLoc::get(Line, 0, Scope), Builder.GetInsertBlock()); // Store the initial value into the alloca. @@ -1274,7 +1276,7 @@ Function *FunctionAST::Codegen() { return 0; // Push the current scope. - KSDbgInfo.LexicalBlocks.push_back(&KSDbgInfo.FnScopeMap[Proto]); + KSDbgInfo.LexicalBlocks.push_back(KSDbgInfo.FnScopeMap[Proto]); // Unset the location for the prologue emission (leading instructions with no // location in a function are considered part of the prologue and the debugger @@ -1459,7 +1461,7 @@ int main() { // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. - TheModule->setDataLayout(*TheExecutionEngine->getDataLayout()); + TheModule->setDataLayout(TheExecutionEngine->getDataLayout()); #if 0 // Provide basic AliasAnalysis support for GVN. OurFPM.add(createBasicAliasAnalysisPass()); diff --git a/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp b/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp index 7f5ed137cec..77b7f001095 100644 --- a/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp +++ b/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp @@ -672,7 +672,7 @@ Value *BinaryExprAST::Codegen() { // For now, I'm building without RTTI because LLVM builds that way by // default and so we need to build that way to use the command line supprt. // If you build LLVM with RTTI this can be changed back to a dynamic_cast. - VariableExprAST *LHSE = reinterpret_cast(LHS); + VariableExprAST *LHSE = static_cast(LHS); if (!LHSE) return ErrorV("destination of '=' must be a variable"); // Codegen the RHS. diff --git a/examples/Kaleidoscope/MCJIT/cached/toy.cpp b/examples/Kaleidoscope/MCJIT/cached/toy.cpp index f598ca41f0f..cc12abcc431 100644 --- a/examples/Kaleidoscope/MCJIT/cached/toy.cpp +++ b/examples/Kaleidoscope/MCJIT/cached/toy.cpp @@ -1039,7 +1039,7 @@ Value *BinaryExprAST::Codegen() { // Special case '=' because we don't want to emit the LHS as an expression. if (Op == '=') { // Assignment requires the LHS to be an identifier. - VariableExprAST *LHSE = reinterpret_cast(LHS); + VariableExprAST *LHSE = static_cast(LHS); if (!LHSE) return ErrorV("destination of '=' must be a variable"); // Codegen the RHS. diff --git a/examples/Kaleidoscope/MCJIT/complete/toy.cpp b/examples/Kaleidoscope/MCJIT/complete/toy.cpp index 5294bb71ee1..c78ec35fa0b 100644 --- a/examples/Kaleidoscope/MCJIT/complete/toy.cpp +++ b/examples/Kaleidoscope/MCJIT/complete/toy.cpp @@ -1113,7 +1113,7 @@ Value *BinaryExprAST::Codegen() { // This assume we're building without RTTI because LLVM builds that way by // default. If you build LLVM with RTTI this can be changed to a // dynamic_cast for automatic error checking. - VariableExprAST *LHSE = reinterpret_cast(LHS); + VariableExprAST *LHSE = static_cast(LHS); if (!LHSE) return ErrorV("destination of '=' must be a variable"); // Codegen the RHS. diff --git a/examples/Kaleidoscope/MCJIT/initial/toy.cpp b/examples/Kaleidoscope/MCJIT/initial/toy.cpp index dd35358753d..9455946087d 100644 --- a/examples/Kaleidoscope/MCJIT/initial/toy.cpp +++ b/examples/Kaleidoscope/MCJIT/initial/toy.cpp @@ -897,7 +897,7 @@ Value *BinaryExprAST::Codegen() { // Special case '=' because we don't want to emit the LHS as an expression. if (Op == '=') { // Assignment requires the LHS to be an identifier. - VariableExprAST *LHSE = reinterpret_cast(LHS); + VariableExprAST *LHSE = static_cast(LHS); if (!LHSE) return ErrorV("destination of '=' must be a variable"); // Codegen the RHS. diff --git a/examples/Kaleidoscope/MCJIT/lazy/toy.cpp b/examples/Kaleidoscope/MCJIT/lazy/toy.cpp index fe7fb619697..14d758cfa79 100644 --- a/examples/Kaleidoscope/MCJIT/lazy/toy.cpp +++ b/examples/Kaleidoscope/MCJIT/lazy/toy.cpp @@ -937,7 +937,7 @@ Value *BinaryExprAST::Codegen() { // Special case '=' because we don't want to emit the LHS as an expression. if (Op == '=') { // Assignment requires the LHS to be an identifier. - VariableExprAST *LHSE = reinterpret_cast(LHS); + VariableExprAST *LHSE = static_cast(LHS); if (!LHSE) return ErrorV("destination of '=' must be a variable"); // Codegen the RHS. diff --git a/examples/Kaleidoscope/Orc/fully_lazy/toy.cpp b/examples/Kaleidoscope/Orc/fully_lazy/toy.cpp index b5822921b40..b68f807e3e7 100644 --- a/examples/Kaleidoscope/Orc/fully_lazy/toy.cpp +++ b/examples/Kaleidoscope/Orc/fully_lazy/toy.cpp @@ -717,7 +717,7 @@ class IRGenContext { M(new Module(GenerateUniqueName("jit_module_"), Session.getLLVMContext())), Builder(Session.getLLVMContext()) { - M->setDataLayout(*Session.getTarget().getDataLayout()); + M->setDataLayout(Session.getTarget().createDataLayout()); } SessionContext& getSession() { return Session; } @@ -1168,7 +1168,6 @@ class KaleidoscopeJIT { KaleidoscopeJIT(SessionContext &Session) : Session(Session), - Mang(Session.getTarget().getDataLayout()), CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())), LazyEmitLayer(CompileLayer), CompileCallbacks(LazyEmitLayer, CCMgrMemMgr, Session.getLLVMContext(), @@ -1179,7 +1178,8 @@ class KaleidoscopeJIT { std::string MangledName; { raw_string_ostream MangledNameStream(MangledName); - Mang.getNameWithPrefix(MangledNameStream, Name); + Mangler::getNameWithPrefix(MangledNameStream, Name, + Session.getTarget().createDataLayout()); } return MangledName; } @@ -1214,11 +1214,11 @@ class KaleidoscopeJIT { void removeModule(ModuleHandleT H) { LazyEmitLayer.removeModuleSet(H); } JITSymbol findSymbol(const std::string &Name) { - return LazyEmitLayer.findSymbol(Name, true); + return LazyEmitLayer.findSymbol(Name, false); } JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name) { - return LazyEmitLayer.findSymbolIn(H, Name, true); + return LazyEmitLayer.findSymbolIn(H, Name, false); } JITSymbol findUnmangledSymbol(const std::string &Name) { @@ -1276,7 +1276,7 @@ class KaleidoscopeJIT { makeStub(*F, *FunctionBodyPointer); // Step 4) Add the module containing the stub to the JIT. - auto H = addModule(C.takeM()); + auto StubH = addModule(C.takeM()); // Step 5) Set the compile and update actions. // @@ -1289,18 +1289,23 @@ class KaleidoscopeJIT { // The update action will update FunctionBodyPointer to point at the newly // compiled function. std::shared_ptr Fn = std::move(FnAST); - CallbackInfo.setCompileAction([this, Fn]() { + CallbackInfo.setCompileAction([this, Fn, BodyPtrName, StubH]() { auto H = addModule(IRGen(Session, *Fn)); - return findUnmangledSymbolIn(H, Fn->Proto->Name).getAddress(); + auto BodySym = findUnmangledSymbolIn(H, Fn->Proto->Name); + auto BodyPtrSym = findUnmangledSymbolIn(StubH, BodyPtrName); + assert(BodySym && "Missing function body."); + assert(BodyPtrSym && "Missing function pointer."); + auto BodyAddr = BodySym.getAddress(); + auto BodyPtr = reinterpret_cast( + static_cast(BodyPtrSym.getAddress())); + memcpy(BodyPtr, &BodyAddr, sizeof(uintptr_t)); + return BodyAddr; }); - CallbackInfo.setUpdateAction( - getLocalFPUpdater(LazyEmitLayer, H, mangle(BodyPtrName))); - return H; + return StubH; } SessionContext &Session; - Mangler Mang; SectionMemoryManager CCMgrMemMgr; ObjLayerT ObjectLayer; CompileLayerT CompileLayer; diff --git a/examples/Kaleidoscope/Orc/initial/toy.cpp b/examples/Kaleidoscope/Orc/initial/toy.cpp index bf43f2952c7..91290157ace 100644 --- a/examples/Kaleidoscope/Orc/initial/toy.cpp +++ b/examples/Kaleidoscope/Orc/initial/toy.cpp @@ -716,7 +716,7 @@ class IRGenContext { M(new Module(GenerateUniqueName("jit_module_"), Session.getLLVMContext())), Builder(Session.getLLVMContext()) { - M->setDataLayout(*Session.getTarget().getDataLayout()); + M->setDataLayout(Session.getTarget().createDataLayout()); } SessionContext& getSession() { return Session; } @@ -1160,14 +1160,14 @@ class KaleidoscopeJIT { typedef CompileLayerT::ModuleSetHandleT ModuleHandleT; KaleidoscopeJIT(SessionContext &Session) - : Mang(Session.getTarget().getDataLayout()), - CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())) {} + : DL(Session.getTarget().createDataLayout()), + CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())) {} std::string mangle(const std::string &Name) { std::string MangledName; { raw_string_ostream MangledNameStream(MangledName); - Mang.getNameWithPrefix(MangledNameStream, Name); + Mangler::getNameWithPrefix(MangledNameStream, Name, DL); } return MangledName; } @@ -1201,8 +1201,7 @@ class KaleidoscopeJIT { } private: - - Mangler Mang; + const DataLayout DL; ObjLayerT ObjectLayer; CompileLayerT CompileLayer; }; diff --git a/examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp b/examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp index 1369ba6f5ee..17f9dbb6dfa 100644 --- a/examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp +++ b/examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp @@ -716,7 +716,7 @@ class IRGenContext { M(new Module(GenerateUniqueName("jit_module_"), Session.getLLVMContext())), Builder(Session.getLLVMContext()) { - M->setDataLayout(*Session.getTarget().getDataLayout()); + M->setDataLayout(Session.getTarget().createDataLayout()); } SessionContext& getSession() { return Session; } @@ -1162,15 +1162,15 @@ class KaleidoscopeJIT { typedef LazyEmitLayerT::ModuleSetHandleT ModuleHandleT; KaleidoscopeJIT(SessionContext &Session) - : Mang(Session.getTarget().getDataLayout()), - CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())), - LazyEmitLayer(CompileLayer) {} + : DL(Session.getTarget().createDataLayout()), + CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())), + LazyEmitLayer(CompileLayer) {} std::string mangle(const std::string &Name) { std::string MangledName; { raw_string_ostream MangledNameStream(MangledName); - Mang.getNameWithPrefix(MangledNameStream, Name); + Mangler::getNameWithPrefix(MangledNameStream, Name, DL); } return MangledName; } @@ -1204,8 +1204,7 @@ class KaleidoscopeJIT { } private: - - Mangler Mang; + const DataLayout DL; ObjLayerT ObjectLayer; CompileLayerT CompileLayer; LazyEmitLayerT LazyEmitLayer; diff --git a/examples/Kaleidoscope/Orc/lazy_irgen/toy.cpp b/examples/Kaleidoscope/Orc/lazy_irgen/toy.cpp index c489a450d79..7373c99d543 100644 --- a/examples/Kaleidoscope/Orc/lazy_irgen/toy.cpp +++ b/examples/Kaleidoscope/Orc/lazy_irgen/toy.cpp @@ -716,7 +716,7 @@ class IRGenContext { M(new Module(GenerateUniqueName("jit_module_"), Session.getLLVMContext())), Builder(Session.getLLVMContext()) { - M->setDataLayout(*Session.getTarget().getDataLayout()); + M->setDataLayout(Session.getTarget().createDataLayout()); } SessionContext& getSession() { return Session; } @@ -1162,7 +1162,6 @@ class KaleidoscopeJIT { KaleidoscopeJIT(SessionContext &Session) : Session(Session), - Mang(Session.getTarget().getDataLayout()), CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())), LazyEmitLayer(CompileLayer) {} @@ -1170,7 +1169,8 @@ class KaleidoscopeJIT { std::string MangledName; { raw_string_ostream MangledNameStream(MangledName); - Mang.getNameWithPrefix(MangledNameStream, Name); + Mangler::getNameWithPrefix(MangledNameStream, Name, + Session.getTarget().createDataLayout()); } return MangledName; } @@ -1236,7 +1236,6 @@ class KaleidoscopeJIT { } SessionContext &Session; - Mangler Mang; ObjLayerT ObjectLayer; CompileLayerT CompileLayer; LazyEmitLayerT LazyEmitLayer; diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index effbd15c10d..764dbfac342 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -161,15 +161,15 @@ typedef enum { /* FIXME: These attributes are currently not included in the C API as a temporary measure until the API/ABI impact to the C API is understood and the path forward agreed upon. - LLVMAddressSafety = 1ULL << 32, - LLVMStackProtectStrongAttribute = 1ULL<<33, - LLVMCold = 1ULL << 34, - LLVMOptimizeNone = 1ULL << 35, - LLVMInAllocaAttribute = 1ULL << 36, - LLVMNonNullAttribute = 1ULL << 37, - LLVMJumpTableAttribute = 1ULL << 38, - LLVMDereferenceableAttribute = 1ULL << 39, - LLVMDereferenceableOrNullAttribute = 1ULL << 40, + LLVMSanitizeAddressAttribute = 1ULL << 32, + LLVMStackProtectStrongAttribute = 1ULL<<35, + LLVMColdAttribute = 1ULL << 40, + LLVMOptimizeNoneAttribute = 1ULL << 42, + LLVMInAllocaAttribute = 1ULL << 43, + LLVMNonNullAttribute = 1ULL << 44, + LLVMJumpTableAttribute = 1ULL << 45, + LLVMConvergentAttribute = 1ULL << 46, + LLVMSafeStackAttribute = 1ULL << 47, */ } LLVMAttribute; @@ -248,7 +248,13 @@ typedef enum { /* Exception Handling Operators */ LLVMResume = 58, - LLVMLandingPad = 59 + LLVMLandingPad = 59, + LLVMCleanupRet = 61, + LLVMCatchRet = 62, + LLVMCatchPad = 63, + LLVMTerminatePad = 64, + LLVMCleanupPad = 65, + LLVMCatchEndPad = 66 } LLVMOpcode; @@ -997,6 +1003,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. * @@ -1196,6 +1209,7 @@ LLVMTypeRef LLVMX86MMXType(void); macro(InsertElementInst) \ macro(InsertValueInst) \ macro(LandingPadInst) \ + macro(CleanupPadInst) \ macro(PHINode) \ macro(SelectInst) \ macro(ShuffleVectorInst) \ @@ -1208,6 +1222,11 @@ LLVMTypeRef LLVMX86MMXType(void); macro(SwitchInst) \ macro(UnreachableInst) \ macro(ResumeInst) \ + macro(CleanupReturnInst) \ + macro(CatchReturnInst) \ + macro(CatchPadInst) \ + macro(TerminatePadInst) \ + macro(CatchEndPadInst) \ macro(UnaryInstruction) \ macro(AllocaInst) \ macro(CastInst) \ @@ -1880,6 +1899,20 @@ LLVMValueRef LLVMAddAlias(LLVMModuleRef M, LLVMTypeRef Ty, LLVMValueRef Aliasee, */ void LLVMDeleteFunction(LLVMValueRef Fn); +/** + * Obtain the personality function attached to the function. + * + * @see llvm::Function::getPersonalityFn() + */ +LLVMValueRef LLVMGetPersonalityFn(LLVMValueRef Fn); + +/** + * Set the personality function attached to the function. + * + * @see llvm::Function::setPersonalityFn() + */ +void LLVMSetPersonalityFn(LLVMValueRef Fn, LLVMValueRef PersonalityFn); + /** * Obtain the ID number from a function instance. * @@ -1929,7 +1962,7 @@ void LLVMSetGC(LLVMValueRef Fn, const char *Name); void LLVMAddFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA); /** - * Add a target-dependent attribute to a fuction + * Add a target-dependent attribute to a function * @see llvm::AttrBuilder::addAttribute() */ void LLVMAddTargetDependentFunctionAttr(LLVMValueRef Fn, const char *A, diff --git a/include/llvm-c/Object.h b/include/llvm-c/Object.h index 447fcea7bc2..9cab5c426c4 100644 --- a/include/llvm-c/Object.h +++ b/include/llvm-c/Object.h @@ -81,7 +81,6 @@ uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI); uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI); // RelocationRef accessors -uint64_t LLVMGetRelocationAddress(LLVMRelocationIteratorRef RI); uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI); LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI); uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI); diff --git a/include/llvm-c/Support.h b/include/llvm-c/Support.h index a9216d0364a..eca3b7a4203 100644 --- a/include/llvm-c/Support.h +++ b/include/llvm-c/Support.h @@ -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 diff --git a/include/llvm-c/lto.h b/include/llvm-c/lto.h index c6acdaddca5..cb3a6916045 100644 --- a/include/llvm-c/lto.h +++ b/include/llvm-c/lto.h @@ -40,7 +40,7 @@ typedef bool lto_bool_t; * @{ */ -#define LTO_API_VERSION 13 +#define LTO_API_VERSION 17 /** * \since prior to LTO_API_VERSION=3 @@ -62,7 +62,9 @@ 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_ALIAS = 0x00008000 } lto_symbol_attributes; /** @@ -171,7 +173,7 @@ lto_module_create_from_memory(const void* mem, size_t length); * Loads an object file from memory with an extra path argument. * Returns NULL on error (check lto_get_error_message() for details). * - * \since prior to LTO_API_VERSION=9 + * \since LTO_API_VERSION=9 */ extern lto_module_t lto_module_create_from_memory_with_path(const void* mem, size_t length, @@ -279,39 +281,15 @@ lto_module_get_symbol_attribute(lto_module_t mod, unsigned int index); /** - * Returns the number of dependent libraries in the object module. + * Returns the module's linker options. * - * \since LTO_API_VERSION=8 - */ -extern unsigned int -lto_module_get_num_deplibs(lto_module_t mod); - - -/** - * Returns the ith dependent library in the module. - * - * \since LTO_API_VERSION=8 - */ -extern const char* -lto_module_get_deplib(lto_module_t mod, unsigned int index); - - -/** - * Returns the number of linker options in the object module. - * - * \since LTO_API_VERSION=8 - */ -extern unsigned int -lto_module_get_num_linkeropts(lto_module_t mod); - - -/** - * Returns the ith linker option in the module. + * The linker options may consist of multiple flags. It is the linker's + * responsibility to split the flags using a platform-specific mechanism. * - * \since LTO_API_VERSION=8 + * \since LTO_API_VERSION=16 */ extern const char* -lto_module_get_linkeropt(lto_module_t mod, unsigned int index); +lto_module_get_linkeropts(lto_module_t mod); /** @@ -401,7 +379,7 @@ lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod); * * \c cg and \c mod must both be in the same context. * - * \since prior to LTO_API_VERSION=13 + * \since LTO_API_VERSION=13 */ extern void lto_codegen_set_module(lto_code_gen_t cg, lto_module_t mod); @@ -548,6 +526,28 @@ lto_codegen_debug_options(lto_code_gen_t cg, const char *); extern void lto_initialize_disassembler(void); +/** + * Sets if we should run internalize pass during optimization and code + * generation. + * + * \since LTO_API_VERSION=14 + */ +extern void +lto_codegen_set_should_internalize(lto_code_gen_t cg, + lto_bool_t ShouldInternalize); + +/** + * \brief Set whether to embed uselists in bitcode. + * + * Sets whether \a lto_codegen_write_merged_modules() should embed uselists in + * output bitcode. This should be turned on for all -save-temps output. + * + * \since LTO_API_VERSION=15 + */ +extern void +lto_codegen_set_should_embed_uselists(lto_code_gen_t cg, + lto_bool_t ShouldEmbedUselists); + #ifdef __cplusplus } #endif diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 53b53c5dfa5..76615affb25 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -276,6 +276,10 @@ class APFloat { /// \param isIEEE - If 128 bit number, select between PPC and IEEE static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false); + /// Returns the size of the floating point number (in bits) in the given + /// semantics. + static unsigned getSizeInBits(const fltSemantics &Sem); + /// @} /// Used to insert APFloat objects, or objects that contain APFloat objects, @@ -343,7 +347,7 @@ class APFloat { /// copied from some other APFloat. static APFloat copySign(APFloat Value, const APFloat &Sign) { Value.copySign(Sign); - return std::move(Value); + return Value; } /// @} diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index 36d8159d21b..5013f295f5c 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -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 @@ class APInt { /// This checks to see if the value of this APInt is the maximum signed /// value for the APInt's bit width. bool isMaxSignedValue() const { - return 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 @@ class APInt { /// This checks to see if the value of this APInt is the minimum signed /// value for the APInt's bit width. bool isMinSignedValue() const { - return 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 @@ class APInt { /// \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. @@ -1039,7 +1038,9 @@ class APInt { /// the validity of the less-than relationship. /// /// \returns true if *this < RHS when considered unsigned. - bool ult(uint64_t RHS) const { return ult(APInt(getBitWidth(), RHS)); } + bool ult(uint64_t RHS) const { + return getActiveBits() > 64 ? false : getZExtValue() < RHS; + } /// \brief Signed less than comparison /// @@ -1055,7 +1056,9 @@ class APInt { /// the validity of the less-than relationship. /// /// \returns true if *this < RHS when considered signed. - bool slt(uint64_t RHS) const { return slt(APInt(getBitWidth(), RHS)); } + bool slt(int64_t RHS) const { + return getMinSignedBits() > 64 ? isNegative() : getSExtValue() < RHS; + } /// \brief Unsigned less or equal comparison /// @@ -1071,7 +1074,7 @@ class APInt { /// the validity of the less-or-equal relationship. /// /// \returns true if *this <= RHS when considered unsigned. - bool ule(uint64_t RHS) const { return ule(APInt(getBitWidth(), RHS)); } + bool ule(uint64_t RHS) const { return !ugt(RHS); } /// \brief Signed less or equal comparison /// @@ -1087,7 +1090,7 @@ class APInt { /// validity of the less-or-equal relationship. /// /// \returns true if *this <= RHS when considered signed. - bool sle(uint64_t RHS) const { return sle(APInt(getBitWidth(), RHS)); } + bool sle(uint64_t RHS) const { return !sgt(RHS); } /// \brief Unsigned greather than comparison /// @@ -1103,7 +1106,9 @@ class APInt { /// the validity of the greater-than relationship. /// /// \returns true if *this > RHS when considered unsigned. - bool ugt(uint64_t RHS) const { return ugt(APInt(getBitWidth(), RHS)); } + bool ugt(uint64_t RHS) const { + return getActiveBits() > 64 ? true : getZExtValue() > RHS; + } /// \brief Signed greather than comparison /// @@ -1119,7 +1124,9 @@ class APInt { /// the validity of the greater-than relationship. /// /// \returns true if *this > RHS when considered signed. - bool sgt(uint64_t RHS) const { return sgt(APInt(getBitWidth(), RHS)); } + bool sgt(int64_t RHS) const { + return getMinSignedBits() > 64 ? !isNegative() : getSExtValue() > RHS; + } /// \brief Unsigned greater or equal comparison /// @@ -1135,7 +1142,7 @@ class APInt { /// the validity of the greater-or-equal relationship. /// /// \returns true if *this >= RHS when considered unsigned. - bool uge(uint64_t RHS) const { return uge(APInt(getBitWidth(), RHS)); } + bool uge(uint64_t RHS) const { return !ult(RHS); } /// \brief Signed greather or equal comparison /// @@ -1151,7 +1158,7 @@ class APInt { /// the validity of the greater-or-equal relationship. /// /// \returns true if *this >= RHS when considered signed. - bool sge(uint64_t RHS) const { return sge(APInt(getBitWidth(), RHS)); } + bool sge(int64_t RHS) const { return !slt(RHS); } /// This operation tests if there are any pairs of corresponding bits /// between this APInt and RHS that are both set. diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h index 91ccda22f2f..a187515f859 100644 --- a/include/llvm/ADT/APSInt.h +++ b/include/llvm/ADT/APSInt.h @@ -33,6 +33,15 @@ class APSInt : public APInt { explicit APSInt(APInt I, bool isUnsigned = true) : APInt(std::move(I)), IsUnsigned(isUnsigned) {} + /// Construct an APSInt from a string representation. + /// + /// This constructor interprets the string \p Str using the radix of 10. + /// The interpretation stops at the end of the string. The bit width of the + /// constructed APSInt is determined automatically. + /// + /// \param Str the string to be interpreted. + explicit APSInt(StringRef Str); + APSInt &operator=(APInt RHS) { // Retain our current sign. APInt::operator=(std::move(RHS)); diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h index f7b055e3a06..f6cc4f4e7c3 100644 --- a/include/llvm/ADT/ArrayRef.h +++ b/include/llvm/ADT/ArrayRef.h @@ -85,7 +85,7 @@ namespace llvm { /// Construct an ArrayRef from a std::initializer_list. /*implicit*/ ArrayRef(const std::initializer_list &Vec) - : Data(Vec.begin() == Vec.end() ? (T*)0 : Vec.begin()), + : Data(Vec.begin() == Vec.end() ? (T*)nullptr : Vec.begin()), Length(Vec.size()) {} /// Construct an ArrayRef from ArrayRef. This uses SFINAE to @@ -96,6 +96,25 @@ namespace llvm { std::is_convertible::value>::type* = 0) : Data(A.data()), Length(A.size()) {} + /// Construct an ArrayRef from a SmallVector. This is + /// templated in order to avoid instantiating SmallVectorTemplateCommon + /// whenever we copy-construct an ArrayRef. + template + /*implicit*/ ArrayRef(const SmallVectorTemplateCommon &Vec, + typename std::enable_if< + std::is_convertible::value>::type* = 0) + : Data(Vec.data()), Length(Vec.size()) { + } + + /// Construct an ArrayRef from std::vector. This uses SFINAE + /// to ensure that only vectors of pointers can be converted. + template + ArrayRef(const std::vector &Vec, + typename std::enable_if< + std::is_convertible::value>::type* = 0) + : Data(Vec.data()), Length(Vec.size()) {} + /// @} /// @name Simple Operations /// @{ @@ -267,6 +286,11 @@ namespace llvm { return MutableArrayRef(data()+N, M); } + MutableArrayRef drop_back(unsigned N) const { + assert(this->size() >= N && "Dropping more elements than exist"); + return slice(0, this->size() - N); + } + /// @} /// @name Operator Overloads /// @{ diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index 9c2365af6eb..27f73157a29 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -272,10 +272,6 @@ class DenseMapBase : public DebugEpochBase { P->getSecond().~ValueT(); P->getFirst().~KeyT(); } - -#ifndef NDEBUG - memset((void*)getBuckets(), 0x5a, sizeof(BucketT)*getNumBuckets()); -#endif } void initEmpty() { @@ -312,12 +308,6 @@ class DenseMapBase : public DebugEpochBase { } B->getFirst().~KeyT(); } - -#ifndef NDEBUG - if (OldBucketsBegin != OldBucketsEnd) - memset((void*)OldBucketsBegin, 0x5a, - sizeof(BucketT) * (OldBucketsEnd - OldBucketsBegin)); -#endif } template diff --git a/include/llvm/ADT/DenseMapInfo.h b/include/llvm/ADT/DenseMapInfo.h index 6f17a647b63..b0a05307207 100644 --- a/include/llvm/ADT/DenseMapInfo.h +++ b/include/llvm/ADT/DenseMapInfo.h @@ -14,6 +14,8 @@ #ifndef LLVM_ADT_DENSEMAPINFO_H #define LLVM_ADT_DENSEMAPINFO_H +#include "llvm/ADT/Hashing.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include "llvm/Support/type_traits.h" @@ -163,6 +165,31 @@ struct DenseMapInfo > { } }; +// Provide DenseMapInfo for StringRefs. +template <> struct DenseMapInfo { + static inline StringRef getEmptyKey() { + return StringRef(reinterpret_cast(~static_cast(0)), + 0); + } + static inline StringRef getTombstoneKey() { + return StringRef(reinterpret_cast(~static_cast(1)), + 0); + } + static unsigned getHashValue(StringRef Val) { + assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!"); + assert(Val.data() != getTombstoneKey().data() && + "Cannot hash the tombstone key!"); + return (unsigned)(hash_value(Val)); + } + static bool isEqual(StringRef LHS, StringRef RHS) { + if (RHS.data() == getEmptyKey().data()) + return LHS.data() == getEmptyKey().data(); + if (RHS.data() == getTombstoneKey().data()) + return LHS.data() == getTombstoneKey().data(); + return LHS == RHS; + } +}; + } // end namespace llvm #endif diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h index e9668c45d10..d79b9acacfa 100644 --- a/include/llvm/ADT/DepthFirstIterator.h +++ b/include/llvm/ADT/DepthFirstIterator.h @@ -159,8 +159,10 @@ class df_iterator : public std::iterator #include #include +#include #include namespace llvm { diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h index 921bd820d97..fd4412c4166 100644 --- a/include/llvm/ADT/STLExtras.h +++ b/include/llvm/ADT/STLExtras.h @@ -18,6 +18,7 @@ #define LLVM_ADT_STLEXTRAS_H #include "llvm/Support/Compiler.h" +#include // for std::all_of #include #include // for std::size_t #include // for qsort @@ -195,6 +196,41 @@ inline mapped_iterator map_iterator(const ItTy &I, FuncTy F) { return mapped_iterator(I, F); } +/// \brief Metafunction to determine if type T has a member called rbegin(). +template struct has_rbegin { + template static char(&f(const U &, decltype(&U::rbegin)))[1]; + static char(&f(...))[2]; + const static bool value = sizeof(f(std::declval(), nullptr)) == 1; +}; + +// Returns an iterator_range over the given container which iterates in reverse. +// Note that the container must have rbegin()/rend() methods for this to work. +template +auto reverse(ContainerTy &&C, + typename std::enable_if::value>::type * = + nullptr) -> decltype(make_range(C.rbegin(), C.rend())) { + return make_range(C.rbegin(), C.rend()); +} + +// Returns a std::reverse_iterator wrapped around the given iterator. +template +std::reverse_iterator make_reverse_iterator(IteratorTy It) { + return std::reverse_iterator(It); +} + +// Returns an iterator_range over the given container which iterates in reverse. +// Note that the container must have begin()/end() methods which return +// bidirectional iterators for this to work. +template +auto reverse( + ContainerTy &&C, + typename std::enable_if::value>::type * = nullptr) + -> decltype(make_range(llvm::make_reverse_iterator(std::end(C)), + llvm::make_reverse_iterator(std::begin(C)))) { + return make_range(llvm::make_reverse_iterator(std::end(C)), + llvm::make_reverse_iterator(std::begin(C))); +} + //===----------------------------------------------------------------------===// // Extra additions to //===----------------------------------------------------------------------===// @@ -327,6 +363,14 @@ void DeleteContainerSeconds(Container &C) { C.clear(); } +/// Provide wrappers to std::all_of which take ranges instead of having to pass +/// being/end explicitly. +template +bool all_of(R &&Range, UnaryPredicate &&P) { + return std::all_of(Range.begin(), Range.end(), + std::forward(P)); +} + //===----------------------------------------------------------------------===// // Extra additions to //===----------------------------------------------------------------------===// diff --git a/include/llvm/ADT/SetVector.h b/include/llvm/ADT/SetVector.h index a7fd408c854..2125b274f53 100644 --- a/include/llvm/ADT/SetVector.h +++ b/include/llvm/ADT/SetVector.h @@ -44,6 +44,8 @@ class SetVector { typedef Vector vector_type; typedef typename vector_type::const_iterator iterator; typedef typename vector_type::const_iterator const_iterator; + typedef typename vector_type::const_reverse_iterator reverse_iterator; + typedef typename vector_type::const_reverse_iterator const_reverse_iterator; typedef typename vector_type::size_type size_type; /// \brief Construct an empty SetVector @@ -85,6 +87,26 @@ class SetVector { return vector_.end(); } + /// \brief Get an reverse_iterator to the end of the SetVector. + reverse_iterator rbegin() { + return vector_.rbegin(); + } + + /// \brief Get a const_reverse_iterator to the end of the SetVector. + const_reverse_iterator rbegin() const { + return vector_.rbegin(); + } + + /// \brief Get a reverse_iterator to the beginning of the SetVector. + reverse_iterator rend() { + return vector_.rend(); + } + + /// \brief Get a const_reverse_iterator to the beginning of the SetVector. + const_reverse_iterator rend() const { + return vector_.rend(); + } + /// \brief Return the last element of the SetVector. const T &back() const { assert(!empty() && "Cannot call back() on empty SetVector!"); diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h index 20cbe2cddfc..bf7e1544c81 100644 --- a/include/llvm/ADT/SparseBitVector.h +++ b/include/llvm/ADT/SparseBitVector.h @@ -453,6 +453,9 @@ class SparseBitVector { // Assignment SparseBitVector& operator=(const SparseBitVector& RHS) { + if (this == &RHS) + return *this; + Elements.clear(); ElementListConstIter ElementIter = RHS.Elements.begin(); @@ -559,6 +562,9 @@ class SparseBitVector { // Union our bitmap with the RHS and return true if we changed. bool operator|=(const SparseBitVector &RHS) { + if (this == &RHS) + return false; + bool changed = false; ElementListIter Iter1 = Elements.begin(); ElementListConstIter Iter2 = RHS.Elements.begin(); @@ -587,6 +593,9 @@ class SparseBitVector { // Intersect our bitmap with the RHS and return true if ours changed. bool operator&=(const SparseBitVector &RHS) { + if (this == &RHS) + return false; + bool changed = false; ElementListIter Iter1 = Elements.begin(); ElementListConstIter Iter2 = RHS.Elements.begin(); @@ -619,9 +628,13 @@ class SparseBitVector { ElementListIter IterTmp = Iter1; ++Iter1; Elements.erase(IterTmp); + changed = true; } } - Elements.erase(Iter1, Elements.end()); + if (Iter1 != Elements.end()) { + Elements.erase(Iter1, Elements.end()); + changed = true; + } CurrElementIter = Elements.begin(); return changed; } @@ -629,6 +642,14 @@ class SparseBitVector { // Intersect our bitmap with the complement of the RHS and return true // if ours changed. bool intersectWithComplement(const SparseBitVector &RHS) { + if (this == &RHS) { + if (!empty()) { + clear(); + return true; + } + return false; + } + bool changed = false; ElementListIter Iter1 = Elements.begin(); ElementListConstIter Iter2 = RHS.Elements.begin(); @@ -675,6 +696,15 @@ class SparseBitVector { void intersectWithComplement(const SparseBitVector &RHS1, const SparseBitVector &RHS2) { + if (this == &RHS1) { + intersectWithComplement(RHS2); + return; + } else if (this == &RHS2) { + SparseBitVector RHS2Copy(RHS2); + intersectWithComplement(RHS1, RHS2Copy); + return; + } + Elements.clear(); CurrElementIter = Elements.begin(); ElementListConstIter Iter1 = RHS1.Elements.begin(); diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index 7621796fb50..fff287e4910 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -50,7 +50,8 @@ class Triple { 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 @@ -64,6 +65,7 @@ class Triple { amdgcn, // AMDGCN: AMD GCN GPUs sparc, // Sparc: sparc sparcv9, // Sparcv9: Sparcv9 + sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant systemz, // SystemZ: s390x tce, // TCE (http://tce.cs.tut.fi/): tce thumb, // Thumb (little endian): thumb, thumbv.* @@ -82,7 +84,11 @@ class Triple { hsail64, // AMD HSAIL with 64-bit pointers spir, // SPIR: standard portable IR for OpenCL 32-bit version spir64, // SPIR: standard portable IR for OpenCL 64-bit version - kalimba // Kalimba: generic kalimba + kalimba, // Kalimba: generic kalimba + shave, // SHAVE: Movidius vector VLIW processors + wasm32, // WebAssembly with 32-bit pointers + wasm64, // WebAssembly with 64-bit pointers + LastArchType = wasm64 }; enum SubArchType { NoSubArch, @@ -118,7 +124,8 @@ class Triple { ImaginationTechnologies, MipsTechnologies, NVIDIA, - CSR + CSR, + LastVendorType = CSR }; enum OSType { UnknownOS, @@ -147,7 +154,8 @@ class Triple { CUDA, // NVIDIA CUDA NVCL, // NVIDIA OpenCL AMDHSA, // AMD HSA Runtime - PS4 + PS4, + LastOSType = PS4 }; enum EnvironmentType { UnknownEnvironment, @@ -164,6 +172,8 @@ class Triple { MSVC, Itanium, Cygnus, + AMDOpenCL, + LastEnvironmentType = AMDOpenCL }; enum ObjectFormatType { UnknownObjectFormat, @@ -240,21 +250,9 @@ class Triple { /// getVendor - Get the parsed vendor type of this triple. VendorType getVendor() const { return Vendor; } - // @LOCALMOD-BEGIN -- hardcode NaCl for NaCl builds, to help - // prune OS-specific code that is litered all over and not - // cleanly separated. -#if defined(__native_client__) - OSType getOS() const { return NaCl; } - ObjectFormatType getObjectFormat() const { return ELF; } -#else /// getOS - Get the parsed operating system type of this triple. OSType getOS() const { return OS; } - /// getFormat - Get the object format for this triple. - ObjectFormatType getObjectFormat() const { return ObjectFormat; } -#endif - // @LOCALMOD-END - /// hasEnvironment - Does this triple have the optional environment /// (fourth) component? bool hasEnvironment() const { @@ -264,6 +262,18 @@ class Triple { /// getEnvironment - Get the parsed environment type of this triple. EnvironmentType getEnvironment() const { return Environment; } + /// \brief Parse the version number from the OS name component of the + /// triple, if present. + /// + /// For example, "fooos1.2.3" would return (1, 2, 3). + /// + /// If an entry is not defined, it will be returned as 0. + void getEnvironmentVersion(unsigned &Major, unsigned &Minor, + unsigned &Micro) const; + + /// getFormat - Get the object format for this triple. + ObjectFormatType getObjectFormat() const { return ObjectFormat; } + /// getOSVersion - Parse the version number from the OS name component of the /// triple, if present. /// @@ -382,62 +392,6 @@ class Triple { return isOSVersionLT(Minor + 4, Micro, 0); } - // @LOCALMOD-BEGIN: Hardcode OS predicates to help prune code - // that is OS-specific, but not cleanly separated. - // Perhaps this would be cleaner if Triple.h was partly Table-gen'ed. -#if defined(__native_client__) - bool isMacOSX() const { return false; } - bool isiOS() const { return false; } - bool isOSDarwin() const { return false; } - bool isOSNetBSD() const { return false; } - bool isOSOpenBSD() const { return false; } - bool isOSFreeBSD() const { return false; } - bool isOSDragonFly() const { return false; } - bool isOSSolaris() const { return false; } - bool isOSBitrig() const { return false; } - bool isWindowsMSVCEnvironment() const { return false; } - bool isKnownWindowsMSVCEnvironment() const { return false; } - bool isWindowsItaniumEnvironment() const { return false; } - bool isWindowsCygwinEnvironment() const { return false; } - bool isWindowsGNUEnvironment() const { return false; } - bool isOSCygMing() const { return false; } - bool isOSMSVCRT() const { return false; } - bool isOSWindows() const { return false; } - bool isOSNaCl() const { return true; } - bool isOSEmscripten() const { return false; } - bool isOSLinux() const { return false; } - bool isOSBinFormatELF() const { return true; } - bool isOSBinFormatCOFF() const { return false; } - bool isOSBinFormatMachO() const { return false; } - bool isPS4CPU() const { return false; } - bool isPS4() const { return false; } -#elif defined(__EMSCRIPTEN__) - bool isMacOSX() const { return false; } - bool isiOS() const { return false; } - bool isOSDarwin() const { return false; } - bool isOSNetBSD() const { return false; } - bool isOSOpenBSD() const { return false; } - bool isOSFreeBSD() const { return false; } - bool isOSDragonFly() const { return false; } - bool isOSSolaris() const { return false; } - bool isOSBitrig() const { return false; } - bool isWindowsMSVCEnvironment() const { return false; } - bool isKnownWindowsMSVCEnvironment() const { return false; } - bool isWindowsItaniumEnvironment() const { return false; } - bool isWindowsCygwinEnvironment() const { return false; } - bool isWindowsGNUEnvironment() const { return false; } - bool isOSCygMing() const { return false; } - bool isOSMSVCRT() const { return false; } - bool isOSWindows() const { return false; } - bool isOSNaCl() const { return false; } - bool isOSEmscripten() const { return true; } - bool isOSLinux() const { return false; } - bool isOSBinFormatELF() const { return true; } - bool isOSBinFormatCOFF() const { return false; } - bool isOSBinFormatMachO() const { return false; } - bool isPS4CPU() const { return false; } - bool isPS4() const { return false; } -#else /// isMacOSX - Is this a Mac OS X triple. For legacy reasons, we support both /// "darwin" and "osx" as OS X triples. bool isMacOSX() const { @@ -558,8 +512,6 @@ class Triple { return getVendor() == Triple::SCEI && getOS() == Triple::PS4; } -#endif - // @LOCALMOD-END /// @} /// @name Mutators @@ -627,6 +579,22 @@ class Triple { /// architecture if no such variant can be found. llvm::Triple get64BitArchVariant() const; + /// Form a triple with a big endian variant of the current architecture. + /// + /// This can be used to move across "families" of architectures where useful. + /// + /// \returns A new triple with a big endian architecture or an unknown + /// architecture if no such variant can be found. + llvm::Triple getBigEndianArchVariant() const; + + /// Form a triple with a little endian variant of the current architecture. + /// + /// This can be used to move across "families" of architectures where useful. + /// + /// \returns A new triple with a little endian architecture or an unknown + /// architecture if no such variant can be found. + llvm::Triple getLittleEndianArchVariant() const; + /// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting. /// /// \param Arch the architecture name (e.g., "armv7s"). If it is an empty diff --git a/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h index fbe5b655ae7..db0bf4b68de 100644 --- a/include/llvm/ADT/Twine.h +++ b/include/llvm/ADT/Twine.h @@ -10,7 +10,7 @@ #ifndef LLVM_ADT_TWINE_H #define LLVM_ADT_TWINE_H -#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" @@ -137,7 +137,7 @@ namespace llvm { const char *cString; const std::string *stdString; const StringRef *stringRef; - const SmallVectorImpl *smallString; + const SmallVectorImpl *smallString; char character; unsigned int decUI; int decI; @@ -410,7 +410,7 @@ namespace llvm { case CStringKind: case StdStringKind: case StringRefKind: - case SmallStringKind: + case SmallStringKind: return true; default: return false; diff --git a/include/llvm/ADT/edit_distance.h b/include/llvm/ADT/edit_distance.h index 9ee1edc54e0..06a01b18a9f 100644 --- a/include/llvm/ADT/edit_distance.h +++ b/include/llvm/ADT/edit_distance.h @@ -50,50 +50,51 @@ unsigned ComputeEditDistance(ArrayRef FromArray, ArrayRef ToArray, // http://en.wikipedia.org/wiki/Levenshtein_distance // // Although the algorithm is typically described using an m x n - // array, only two rows are used at a time, so this implemenation - // just keeps two separate vectors for those two rows. + // array, only one row plus one element are used at a time, so this + // implementation just keeps one vector for the row. To update one entry, + // only the entries to the left, top, and top-left are needed. The left + // entry is in Row[x-1], the top entry is what's in Row[x] from the last + // iteration, and the top-left entry is stored in Previous. typename ArrayRef::size_type m = FromArray.size(); typename ArrayRef::size_type n = ToArray.size(); const unsigned SmallBufferSize = 64; unsigned SmallBuffer[SmallBufferSize]; std::unique_ptr Allocated; - unsigned *Previous = SmallBuffer; - if (2*(n + 1) > SmallBufferSize) { - Previous = new unsigned [2*(n+1)]; - Allocated.reset(Previous); + unsigned *Row = SmallBuffer; + if (n + 1 > SmallBufferSize) { + Row = new unsigned[n + 1]; + Allocated.reset(Row); } - unsigned *Current = Previous + (n + 1); - for (unsigned i = 0; i <= n; ++i) - Previous[i] = i; + for (unsigned i = 1; i <= n; ++i) + Row[i] = i; for (typename ArrayRef::size_type y = 1; y <= m; ++y) { - Current[0] = y; - unsigned BestThisRow = Current[0]; + Row[0] = y; + unsigned BestThisRow = Row[0]; + unsigned Previous = y - 1; for (typename ArrayRef::size_type x = 1; x <= n; ++x) { + int OldRow = Row[x]; if (AllowReplacements) { - Current[x] = std::min( - Previous[x-1] + (FromArray[y-1] == ToArray[x-1] ? 0u : 1u), - std::min(Current[x-1], Previous[x])+1); + Row[x] = std::min( + Previous + (FromArray[y-1] == ToArray[x-1] ? 0u : 1u), + std::min(Row[x-1], Row[x])+1); } else { - if (FromArray[y-1] == ToArray[x-1]) Current[x] = Previous[x-1]; - else Current[x] = std::min(Current[x-1], Previous[x]) + 1; + if (FromArray[y-1] == ToArray[x-1]) Row[x] = Previous; + else Row[x] = std::min(Row[x-1], Row[x]) + 1; } - BestThisRow = std::min(BestThisRow, Current[x]); + Previous = OldRow; + BestThisRow = std::min(BestThisRow, Row[x]); } if (MaxEditDistance && BestThisRow > MaxEditDistance) return MaxEditDistance + 1; - - unsigned *tmp = Current; - Current = Previous; - Previous = tmp; } - unsigned Result = Previous[n]; + unsigned Result = Row[n]; return Result; } diff --git a/include/llvm/ADT/iterator.h b/include/llvm/ADT/iterator.h index 54a288df017..c3079289270 100644 --- a/include/llvm/ADT/iterator.h +++ b/include/llvm/ADT/iterator.h @@ -162,6 +162,8 @@ class iterator_adaptor_base int>::type = 0) : I(std::forward(u)) {} + const WrappedIteratorT &wrapped() const { return I; } + public: typedef DifferenceTypeT difference_type; diff --git a/include/llvm/ADT/iterator_range.h b/include/llvm/ADT/iterator_range.h index 523a86f02e0..3dd679bd9b7 100644 --- a/include/llvm/ADT/iterator_range.h +++ b/include/llvm/ADT/iterator_range.h @@ -20,6 +20,7 @@ #define LLVM_ADT_ITERATOR_RANGE_H #include +#include namespace llvm { @@ -32,6 +33,12 @@ class iterator_range { IteratorT begin_iterator, end_iterator; public: + //TODO: Add SFINAE to test that the Container's iterators match the range's + // iterators. + template + iterator_range(Container &&c) + //TODO: Consider ADL/non-member begin/end calls. + : begin_iterator(c.begin()), end_iterator(c.end()) {} iterator_range(IteratorT begin_iterator, IteratorT end_iterator) : begin_iterator(std::move(begin_iterator)), end_iterator(std::move(end_iterator)) {} @@ -51,6 +58,11 @@ template iterator_range make_range(T x, T y) { template iterator_range make_range(std::pair p) { return iterator_range(std::move(p.first), std::move(p.second)); } + +template +iterator_range()))> drop_begin(T &&t, int n) { + return make_range(std::next(begin(t), n), end(t)); +} } #endif diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index 6999bd1a029..e76f7771d4d 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -16,11 +16,12 @@ // which automatically provides functionality for the entire suite of client // APIs. // -// This API identifies memory regions with the Location class. The pointer +// This API identifies memory regions with the MemoryLocation class. The pointer // component specifies the base memory address of the region. The Size specifies -// the maximum size (in address units) of the memory region, or UnknownSize if -// the size is not known. The TBAA tag identifies the "type" of the memory -// reference; see the TypeBasedAliasAnalysis class for details. +// the maximum size (in address units) of the memory region, or +// MemoryLocation::UnknownSize if the size is not known. The TBAA tag +// identifies the "type" of the memory reference; see the +// TypeBasedAliasAnalysis class for details. // // Some non-obvious details include: // - Pointers that point to two completely different objects in memory never @@ -40,6 +41,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Metadata.h" +#include "llvm/Analysis/MemoryLocation.h" namespace llvm { @@ -53,6 +55,106 @@ class AnalysisUsage; class MemTransferInst; class MemIntrinsic; class DominatorTree; +class OrderedBasicBlock; + +/// The possible results of an alias query. +/// +/// These results are always computed between two MemoryLocation objects as +/// a query to some alias analysis. +/// +/// Note that these are unscoped enumerations because we would like to support +/// implicitly testing a result for the existence of any possible aliasing with +/// a conversion to bool, but an "enum class" doesn't support this. The +/// canonical names from the literature are suffixed and unique anyways, and so +/// they serve as global constants in LLVM for these results. +/// +/// See docs/AliasAnalysis.html for more information on the specific meanings +/// of these values. +enum AliasResult { + /// The two locations do not alias at all. + /// + /// This value is arranged to convert to false, while all other values + /// convert to true. This allows a boolean context to convert the result to + /// a binary flag indicating whether there is the possibility of aliasing. + NoAlias = 0, + /// The two locations may or may not alias. This is the least precise result. + MayAlias, + /// The two locations alias, but only due to a partial overlap. + PartialAlias, + /// The two locations precisely alias each other. + MustAlias, +}; + +/// Flags indicating whether a memory access modifies or references memory. +/// +/// This is no access at all, a modification, a reference, or both +/// a modification and a reference. These are specifically structured such that +/// they form a two bit matrix and bit-tests for 'mod' or 'ref' work with any +/// of the possible values. +enum ModRefInfo { + /// The access neither references nor modifies the value stored in memory. + MRI_NoModRef = 0, + /// The access references the value stored in memory. + MRI_Ref = 1, + /// The access modifies the value stored in memory. + MRI_Mod = 2, + /// The access both references and modifies the value stored in memory. + MRI_ModRef = MRI_Ref | MRI_Mod +}; + +/// The locations at which a function might access memory. +/// +/// These are primarily used in conjunction with the \c AccessKind bits to +/// describe both the nature of access and the locations of access for a +/// function call. +enum FunctionModRefLocation { + /// Base case is no access to memory. + FMRL_Nowhere = 0, + /// Access to memory via argument pointers. + FMRL_ArgumentPointees = 4, + /// Access to any memory. + FMRL_Anywhere = 8 | FMRL_ArgumentPointees +}; + +/// Summary of how a function affects memory in the program. +/// +/// Loads from constant globals are not considered memory accesses for this +/// interface. Also, functions may freely modify stack space local to their +/// invocation without having to report it through these interfaces. +enum FunctionModRefBehavior { + /// This function does not perform any non-local loads or stores to memory. + /// + /// This property corresponds to the GCC 'const' attribute. + /// This property corresponds to the LLVM IR 'readnone' attribute. + /// This property corresponds to the IntrNoMem LLVM intrinsic flag. + FMRB_DoesNotAccessMemory = FMRL_Nowhere | MRI_NoModRef, + + /// The only memory references in this function (if it has any) are + /// non-volatile loads from objects pointed to by its pointer-typed + /// arguments, with arbitrary offsets. + /// + /// This property corresponds to the IntrReadArgMem LLVM intrinsic flag. + FMRB_OnlyReadsArgumentPointees = FMRL_ArgumentPointees | MRI_Ref, + + /// The only memory references in this function (if it has any) are + /// non-volatile loads and stores from objects pointed to by its + /// pointer-typed arguments, with arbitrary offsets. + /// + /// This property corresponds to the IntrReadWriteArgMem LLVM intrinsic flag. + FMRB_OnlyAccessesArgumentPointees = FMRL_ArgumentPointees | MRI_ModRef, + + /// This function does not perform any non-local stores or volatile loads, + /// but may read from any memory location. + /// + /// This property corresponds to the GCC 'pure' attribute. + /// This property corresponds to the LLVM IR 'readonly' attribute. + /// This property corresponds to the IntrReadMem LLVM intrinsic flag. + FMRB_OnlyReadsMemory = FMRL_Anywhere | MRI_Ref, + + /// This indicates that the function could not be classified into one of the + /// behaviors above. + FMRB_UnknownModRefBehavior = FMRL_Anywhere | MRI_ModRef +}; class AliasAnalysis { protected: @@ -79,11 +181,6 @@ class AliasAnalysis { AliasAnalysis() : DL(nullptr), TLI(nullptr), AA(nullptr) {} virtual ~AliasAnalysis(); // We want to be subclassed - /// 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); - /// getTargetLibraryInfo - Return a pointer to the current TargetLibraryInfo /// object, or null if no TargetLibraryInfo object is available. /// @@ -95,529 +192,360 @@ class AliasAnalysis { uint64_t getTypeStoreSize(Type *Ty); //===--------------------------------------------------------------------===// - /// 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; - } + /// \name Alias Queries + /// @{ - Location getWithoutAATags() const { - Location Copy(*this); - Copy.AATags = AAMDNodes(); - return Copy; - } - }; - - /// 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(Inst)) - return getLocation(I); - else if (auto *I = dyn_cast(Inst)) - return getLocation(I); - else if (auto *I = dyn_cast(Inst)) - return getLocation(I); - else if (auto *I = dyn_cast(Inst)) - return getLocation(I); - else if (auto *I = dyn_cast(Inst)) - return getLocation(I); - llvm_unreachable("unsupported memory instruction"); - } - - /// 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 - /// _might_ alias. This enum is designed so you can do things like: - /// if (AA.alias(P1, P2)) { ... } - /// to check to see if two pointers might alias. - /// - /// See docs/AliasAnalysis.html for more information on the specific meanings - /// of these values. - /// - enum AliasResult { - NoAlias = 0, ///< No dependencies. - MayAlias, ///< Anything goes. - PartialAlias, ///< Pointers differ, but pointees overlap. - MustAlias ///< Pointers are equal. - }; - - /// alias - The main low level interface to the alias analysis implementation. + /// The main low level interface to the alias analysis implementation. /// Returns an AliasResult indicating whether the two pointers are aliased to - /// each other. This is the interface that must be implemented by specific + /// each other. This is the interface that must be implemented by specific /// alias analysis implementations. - virtual AliasResult alias(const Location &LocA, const Location &LocB); + virtual AliasResult alias(const MemoryLocation &LocA, + const MemoryLocation &LocB); - /// alias - A convenience wrapper. - AliasResult alias(const Value *V1, uint64_t V1Size, - const Value *V2, uint64_t V2Size) { - return alias(Location(V1, V1Size), Location(V2, V2Size)); + /// A convenience wrapper around the primary \c alias interface. + AliasResult alias(const Value *V1, uint64_t V1Size, const Value *V2, + uint64_t V2Size) { + return alias(MemoryLocation(V1, V1Size), MemoryLocation(V2, V2Size)); } - /// alias - A convenience wrapper. + /// A convenience wrapper around the primary \c alias interface. AliasResult alias(const Value *V1, const Value *V2) { - return alias(V1, UnknownSize, V2, UnknownSize); + return alias(V1, MemoryLocation::UnknownSize, V2, + MemoryLocation::UnknownSize); } - /// isNoAlias - A trivial helper function to check to see if the specified - /// pointers are no-alias. - bool isNoAlias(const Location &LocA, const Location &LocB) { + /// A trivial helper function to check to see if the specified pointers are + /// no-alias. + bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB) { return alias(LocA, LocB) == NoAlias; } - /// isNoAlias - A convenience wrapper. - bool isNoAlias(const Value *V1, uint64_t V1Size, - const Value *V2, uint64_t V2Size) { - return isNoAlias(Location(V1, V1Size), Location(V2, V2Size)); + /// A convenience wrapper around the \c isNoAlias helper interface. + bool isNoAlias(const Value *V1, uint64_t V1Size, const Value *V2, + uint64_t V2Size) { + return isNoAlias(MemoryLocation(V1, V1Size), MemoryLocation(V2, V2Size)); } - - /// isNoAlias - A convenience wrapper. + + /// A convenience wrapper around the \c isNoAlias helper interface. bool isNoAlias(const Value *V1, const Value *V2) { - return isNoAlias(Location(V1), Location(V2)); + return isNoAlias(MemoryLocation(V1), MemoryLocation(V2)); } - - /// isMustAlias - A convenience wrapper. - bool isMustAlias(const Location &LocA, const Location &LocB) { + + /// A trivial helper function to check to see if the specified pointers are + /// must-alias. + bool isMustAlias(const MemoryLocation &LocA, const MemoryLocation &LocB) { return alias(LocA, LocB) == MustAlias; } - /// isMustAlias - A convenience wrapper. + /// A convenience wrapper around the \c isMustAlias helper interface. bool isMustAlias(const Value *V1, const Value *V2) { return alias(V1, 1, V2, 1) == MustAlias; } - - /// pointsToConstantMemory - If the specified memory location is - /// known to be constant, return true. If OrLocal is true and the - /// specified memory location is known to be "local" (derived from - /// an alloca), return true. Otherwise return false. - virtual bool pointsToConstantMemory(const Location &Loc, + + /// Checks whether the given location points to constant memory, or if + /// \p OrLocal is true whether it points to a local alloca. + virtual bool pointsToConstantMemory(const MemoryLocation &Loc, bool OrLocal = false); - /// pointsToConstantMemory - A convenient wrapper. + /// A convenience wrapper around the primary \c pointsToConstantMemory + /// interface. bool pointsToConstantMemory(const Value *P, bool OrLocal = false) { - return pointsToConstantMemory(Location(P), OrLocal); + return pointsToConstantMemory(MemoryLocation(P), OrLocal); } + /// @} //===--------------------------------------------------------------------===// - /// Simple mod/ref information... - /// + /// \name Simple mod/ref information + /// @{ + + /// Get the ModRef info associated with a pointer argument of a callsite. The + /// result's bits are set to indicate the allowed aliasing ModRef kinds. Note + /// that these bits do not necessarily account for the overall behavior of + /// the function, but rather only provide additional per-argument + /// information. + virtual ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx); - /// ModRefResult - Represent the result of a mod/ref query. Mod and Ref are - /// bits which may be or'd together. + /// Return the behavior of the given call site. + virtual FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS); + + /// Return the behavior when calling the given function. + virtual FunctionModRefBehavior getModRefBehavior(const Function *F); + + /// Checks if the specified call is known to never read or write memory. /// - enum ModRefResult { NoModRef = 0, Ref = 1, Mod = 2, ModRef = 3 }; - - /// These values define additional bits used to define the - /// ModRefBehavior values. - enum { Nowhere = 0, ArgumentPointees = 4, Anywhere = 8 | ArgumentPointees }; - - /// ModRefBehavior - Summary of how a function affects memory in the program. - /// Loads from constant globals are not considered memory accesses for this - /// interface. Also, functions may freely modify stack space local to their - /// invocation without having to report it through these interfaces. - enum ModRefBehavior { - /// DoesNotAccessMemory - This function does not perform any non-local loads - /// or stores to memory. - /// - /// This property corresponds to the GCC 'const' attribute. - /// This property corresponds to the LLVM IR 'readnone' attribute. - /// This property corresponds to the IntrNoMem LLVM intrinsic flag. - DoesNotAccessMemory = Nowhere | NoModRef, - - /// OnlyReadsArgumentPointees - The only memory references in this function - /// (if it has any) are non-volatile loads from objects pointed to by its - /// pointer-typed arguments, with arbitrary offsets. - /// - /// This property corresponds to the IntrReadArgMem LLVM intrinsic flag. - OnlyReadsArgumentPointees = ArgumentPointees | Ref, - - /// OnlyAccessesArgumentPointees - The only memory references in this - /// function (if it has any) are non-volatile loads and stores from objects - /// pointed to by its pointer-typed arguments, with arbitrary offsets. - /// - /// This property corresponds to the IntrReadWriteArgMem LLVM intrinsic flag. - OnlyAccessesArgumentPointees = ArgumentPointees | ModRef, - - /// OnlyReadsMemory - This function does not perform any non-local stores or - /// volatile loads, but may read from any memory location. - /// - /// This property corresponds to the GCC 'pure' attribute. - /// This property corresponds to the LLVM IR 'readonly' attribute. - /// This property corresponds to the IntrReadMem LLVM intrinsic flag. - OnlyReadsMemory = Anywhere | Ref, - - /// UnknownModRefBehavior - This indicates that the function could not be - /// classified into one of the behaviors above. - UnknownModRefBehavior = Anywhere | ModRef - }; - - /// Get the location associated with a pointer argument of a callsite. - /// The mask bits are set to indicate the allowed aliasing ModRef kinds. - /// Note that these mask bits do not necessarily account for the overall - /// behavior of the function, but rather only provide additional - /// per-argument information. - virtual Location getArgLocation(ImmutableCallSite CS, unsigned ArgIdx, - ModRefResult &Mask); - - /// getModRefBehavior - Return the behavior when calling the given call site. - virtual ModRefBehavior getModRefBehavior(ImmutableCallSite CS); - - /// getModRefBehavior - Return the behavior when calling the given function. - /// For use when the call site is not known. - virtual ModRefBehavior getModRefBehavior(const Function *F); - - /// doesNotAccessMemory - If the specified call is known to never read or - /// write memory, return true. If the call only reads from known-constant - /// memory, it is also legal to return true. Calls that unwind the stack - /// are legal for this predicate. + /// Note that if the call only reads from known-constant memory, it is also + /// legal to return true. Also, calls that unwind the stack are legal for + /// this predicate. /// /// Many optimizations (such as CSE and LICM) can be performed on such calls /// without worrying about aliasing properties, and many calls have this /// property (e.g. calls to 'sin' and 'cos'). /// /// This property corresponds to the GCC 'const' attribute. - /// bool doesNotAccessMemory(ImmutableCallSite CS) { - return getModRefBehavior(CS) == DoesNotAccessMemory; + return getModRefBehavior(CS) == FMRB_DoesNotAccessMemory; } - /// doesNotAccessMemory - If the specified function is known to never read or - /// write memory, return true. For use when the call site is not known. + /// Checks if the specified function is known to never read or write memory. /// + /// Note that if the function only reads from known-constant memory, it is + /// also legal to return true. Also, function that unwind the stack are legal + /// for this predicate. + /// + /// Many optimizations (such as CSE and LICM) can be performed on such calls + /// to such functions without worrying about aliasing properties, and many + /// functions have this property (e.g. 'sin' and 'cos'). + /// + /// This property corresponds to the GCC 'const' attribute. bool doesNotAccessMemory(const Function *F) { - return getModRefBehavior(F) == DoesNotAccessMemory; + return getModRefBehavior(F) == FMRB_DoesNotAccessMemory; } - /// onlyReadsMemory - If the specified call is known to only read from - /// non-volatile memory (or not access memory at all), return true. Calls - /// that unwind the stack are legal for this predicate. + /// Checks if the specified call is known to only read from non-volatile + /// memory (or not access memory at all). + /// + /// Calls that unwind the stack are legal for this predicate. /// /// This property allows many common optimizations to be performed in the /// absence of interfering store instructions, such as CSE of strlen calls. /// /// This property corresponds to the GCC 'pure' attribute. - /// bool onlyReadsMemory(ImmutableCallSite CS) { return onlyReadsMemory(getModRefBehavior(CS)); } - /// onlyReadsMemory - If the specified function is known to only read from - /// non-volatile memory (or not access memory at all), return true. For use - /// when the call site is not known. - /// - bool onlyReadsMemory(const Function *F) { - return onlyReadsMemory(getModRefBehavior(F)); - } - - /// onlyReadsMemory - Return true if functions with the specified behavior are - /// known to only read from non-volatile memory (or not access memory at all). + /// Checks if the specified function is known to only read from non-volatile + /// memory (or not access memory at all). /// - static bool onlyReadsMemory(ModRefBehavior MRB) { - return !(MRB & Mod); - } - - /// onlyAccessesArgPointees - Return true if functions with the specified - /// behavior are known to read and write at most from objects pointed to by - /// their pointer-typed arguments (with arbitrary offsets). + /// Functions that unwind the stack are legal for this predicate. /// - static bool onlyAccessesArgPointees(ModRefBehavior MRB) { - return !(MRB & Anywhere & ~ArgumentPointees); - } - - /// doesAccessArgPointees - Return true if functions with the specified - /// behavior are known to potentially read or write from objects pointed - /// to be their pointer-typed arguments (with arbitrary offsets). + /// This property allows many common optimizations to be performed in the + /// absence of interfering store instructions, such as CSE of strlen calls. /// - static bool doesAccessArgPointees(ModRefBehavior MRB) { - return (MRB & ModRef) && (MRB & ArgumentPointees); + /// This property corresponds to the GCC 'pure' attribute. + bool onlyReadsMemory(const Function *F) { + return onlyReadsMemory(getModRefBehavior(F)); } - /// getModRefInfo - Return information about whether or not an - /// instruction may read or write memory (without regard to a - /// specific location) - ModRefResult getModRefInfo(const Instruction *I) { - if (auto CS = ImmutableCallSite(I)) { - auto MRB = getModRefBehavior(CS); - if (MRB & ModRef) - return ModRef; - else if (MRB & Ref) - return Ref; - else if (MRB & Mod) - return Mod; - return NoModRef; - } - - return getModRefInfo(I, Location()); + /// Checks if functions with the specified behavior are known to only read + /// from non-volatile memory (or not access memory at all). + static bool onlyReadsMemory(FunctionModRefBehavior MRB) { + return !(MRB & MRI_Mod); } - /// getModRefInfo - Return information about whether or not an instruction may - /// read or write the specified memory location. An instruction - /// that doesn't read or write memory may be trivially LICM'd for example. - ModRefResult getModRefInfo(const Instruction *I, - const Location &Loc) { - switch (I->getOpcode()) { - case Instruction::VAArg: return getModRefInfo((const VAArgInst*)I, Loc); - case Instruction::Load: return getModRefInfo((const LoadInst*)I, Loc); - case Instruction::Store: return getModRefInfo((const StoreInst*)I, Loc); - case Instruction::Fence: return getModRefInfo((const FenceInst*)I, Loc); - case Instruction::AtomicCmpXchg: - return getModRefInfo((const AtomicCmpXchgInst*)I, Loc); - case Instruction::AtomicRMW: - return getModRefInfo((const AtomicRMWInst*)I, Loc); - case Instruction::Call: return getModRefInfo((const CallInst*)I, Loc); - case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,Loc); - default: return NoModRef; - } + /// Checks if functions with the specified behavior are known to read and + /// write at most from objects pointed to by their pointer-typed arguments + /// (with arbitrary offsets). + static bool onlyAccessesArgPointees(FunctionModRefBehavior MRB) { + return !(MRB & FMRL_Anywhere & ~FMRL_ArgumentPointees); } - /// getModRefInfo - A convenience wrapper. - ModRefResult getModRefInfo(const Instruction *I, - const Value *P, uint64_t Size) { - return getModRefInfo(I, Location(P, Size)); + /// Checks if functions with the specified behavior are known to potentially + /// read or write from objects pointed to be their pointer-typed arguments + /// (with arbitrary offsets). + static bool doesAccessArgPointees(FunctionModRefBehavior MRB) { + return (MRB & MRI_ModRef) && (MRB & FMRL_ArgumentPointees); } /// getModRefInfo (for call sites) - Return information about whether /// a particular call site modifies or reads the specified memory location. - virtual ModRefResult getModRefInfo(ImmutableCallSite CS, - const Location &Loc); + virtual ModRefInfo getModRefInfo(ImmutableCallSite CS, + const MemoryLocation &Loc); /// getModRefInfo (for call sites) - A convenience wrapper. - ModRefResult getModRefInfo(ImmutableCallSite CS, - const Value *P, uint64_t Size) { - return getModRefInfo(CS, Location(P, Size)); + ModRefInfo getModRefInfo(ImmutableCallSite CS, const Value *P, + uint64_t Size) { + return getModRefInfo(CS, MemoryLocation(P, Size)); } /// getModRefInfo (for calls) - Return information about whether /// a particular call modifies or reads the specified memory location. - ModRefResult getModRefInfo(const CallInst *C, const Location &Loc) { + ModRefInfo getModRefInfo(const CallInst *C, const MemoryLocation &Loc) { return getModRefInfo(ImmutableCallSite(C), Loc); } /// getModRefInfo (for calls) - A convenience wrapper. - ModRefResult getModRefInfo(const CallInst *C, const Value *P, uint64_t Size) { - return getModRefInfo(C, Location(P, Size)); + ModRefInfo getModRefInfo(const CallInst *C, const Value *P, uint64_t Size) { + return getModRefInfo(C, MemoryLocation(P, Size)); } /// getModRefInfo (for invokes) - Return information about whether /// a particular invoke modifies or reads the specified memory location. - ModRefResult getModRefInfo(const InvokeInst *I, - const Location &Loc) { + ModRefInfo getModRefInfo(const InvokeInst *I, const MemoryLocation &Loc) { return getModRefInfo(ImmutableCallSite(I), Loc); } /// getModRefInfo (for invokes) - A convenience wrapper. - ModRefResult getModRefInfo(const InvokeInst *I, - const Value *P, uint64_t Size) { - return getModRefInfo(I, Location(P, Size)); + ModRefInfo getModRefInfo(const InvokeInst *I, const Value *P, uint64_t Size) { + return getModRefInfo(I, MemoryLocation(P, Size)); } /// getModRefInfo (for loads) - Return information about whether /// a particular load modifies or reads the specified memory location. - ModRefResult getModRefInfo(const LoadInst *L, const Location &Loc); + ModRefInfo getModRefInfo(const LoadInst *L, const MemoryLocation &Loc); /// getModRefInfo (for loads) - A convenience wrapper. - ModRefResult getModRefInfo(const LoadInst *L, const Value *P, uint64_t Size) { - return getModRefInfo(L, Location(P, Size)); + ModRefInfo getModRefInfo(const LoadInst *L, const Value *P, uint64_t Size) { + return getModRefInfo(L, MemoryLocation(P, Size)); } /// getModRefInfo (for stores) - Return information about whether /// a particular store modifies or reads the specified memory location. - ModRefResult getModRefInfo(const StoreInst *S, const Location &Loc); + ModRefInfo getModRefInfo(const StoreInst *S, const MemoryLocation &Loc); /// getModRefInfo (for stores) - A convenience wrapper. - ModRefResult getModRefInfo(const StoreInst *S, const Value *P, uint64_t Size){ - return getModRefInfo(S, Location(P, Size)); + ModRefInfo getModRefInfo(const StoreInst *S, const Value *P, uint64_t Size) { + return getModRefInfo(S, MemoryLocation(P, Size)); } /// getModRefInfo (for fences) - Return information about whether /// a particular store modifies or reads the specified memory location. - ModRefResult getModRefInfo(const FenceInst *S, const Location &Loc) { + ModRefInfo getModRefInfo(const FenceInst *S, const MemoryLocation &Loc) { // Conservatively correct. (We could possibly be a bit smarter if // Loc is a alloca that doesn't escape.) - return ModRef; + return MRI_ModRef; } /// getModRefInfo (for fences) - A convenience wrapper. - ModRefResult getModRefInfo(const FenceInst *S, const Value *P, uint64_t Size){ - return getModRefInfo(S, Location(P, Size)); + ModRefInfo getModRefInfo(const FenceInst *S, const Value *P, uint64_t Size) { + return getModRefInfo(S, MemoryLocation(P, Size)); } /// getModRefInfo (for cmpxchges) - Return information about whether /// a particular cmpxchg modifies or reads the specified memory location. - ModRefResult getModRefInfo(const AtomicCmpXchgInst *CX, const Location &Loc); + ModRefInfo getModRefInfo(const AtomicCmpXchgInst *CX, + const MemoryLocation &Loc); /// getModRefInfo (for cmpxchges) - A convenience wrapper. - ModRefResult getModRefInfo(const AtomicCmpXchgInst *CX, - const Value *P, unsigned Size) { - return getModRefInfo(CX, Location(P, Size)); + ModRefInfo getModRefInfo(const AtomicCmpXchgInst *CX, const Value *P, + unsigned Size) { + return getModRefInfo(CX, MemoryLocation(P, Size)); } /// getModRefInfo (for atomicrmws) - Return information about whether /// a particular atomicrmw modifies or reads the specified memory location. - ModRefResult getModRefInfo(const AtomicRMWInst *RMW, const Location &Loc); + ModRefInfo getModRefInfo(const AtomicRMWInst *RMW, const MemoryLocation &Loc); /// getModRefInfo (for atomicrmws) - A convenience wrapper. - ModRefResult getModRefInfo(const AtomicRMWInst *RMW, - const Value *P, unsigned Size) { - return getModRefInfo(RMW, Location(P, Size)); + ModRefInfo getModRefInfo(const AtomicRMWInst *RMW, const Value *P, + unsigned Size) { + return getModRefInfo(RMW, MemoryLocation(P, Size)); } /// getModRefInfo (for va_args) - Return information about whether /// a particular va_arg modifies or reads the specified memory location. - ModRefResult getModRefInfo(const VAArgInst* I, const Location &Loc); + ModRefInfo getModRefInfo(const VAArgInst *I, const MemoryLocation &Loc); /// getModRefInfo (for va_args) - A convenience wrapper. - ModRefResult getModRefInfo(const VAArgInst* I, const Value* P, uint64_t Size){ - return getModRefInfo(I, Location(P, Size)); + ModRefInfo getModRefInfo(const VAArgInst *I, const Value *P, uint64_t Size) { + return getModRefInfo(I, MemoryLocation(P, Size)); } - /// getModRefInfo - Return information about whether a call and an instruction - /// may refer to the same memory locations. - ModRefResult getModRefInfo(Instruction *I, - ImmutableCallSite Call); - - /// getModRefInfo - Return information about whether two call sites may refer - /// to the same set of memory locations. See - /// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo - /// for details. - virtual ModRefResult getModRefInfo(ImmutableCallSite CS1, - ImmutableCallSite CS2); - /// callCapturesBefore - Return information about whether a particular call - /// site modifies or reads the specified memory location. - ModRefResult callCapturesBefore(const Instruction *I, - const AliasAnalysis::Location &MemLoc, - DominatorTree *DT); + /// Check whether or not an instruction may read or write memory (without + /// regard to a specific location). + /// + /// For function calls, this delegates to the alias-analysis specific + /// call-site mod-ref behavior queries. Otherwise it delegates to the generic + /// mod ref information query without a location. + ModRefInfo getModRefInfo(const Instruction *I) { + if (auto CS = ImmutableCallSite(I)) { + auto MRB = getModRefBehavior(CS); + if (MRB & MRI_ModRef) + return MRI_ModRef; + else if (MRB & MRI_Ref) + return MRI_Ref; + else if (MRB & MRI_Mod) + return MRI_Mod; + return MRI_NoModRef; + } - /// callCapturesBefore - A convenience wrapper. - ModRefResult callCapturesBefore(const Instruction *I, const Value *P, - uint64_t Size, DominatorTree *DT) { - return callCapturesBefore(I, Location(P, Size), DT); + return getModRefInfo(I, MemoryLocation()); } - //===--------------------------------------------------------------------===// - /// Higher level methods for querying mod/ref information. + /// Check whether or not an instruction may read or write the specified + /// memory location. /// + /// An instruction that doesn't read or write memory may be trivially LICM'd + /// for example. + /// + /// This primarily delegates to specific helpers above. + ModRefInfo getModRefInfo(const Instruction *I, const MemoryLocation &Loc) { + switch (I->getOpcode()) { + case Instruction::VAArg: return getModRefInfo((const VAArgInst*)I, Loc); + case Instruction::Load: return getModRefInfo((const LoadInst*)I, Loc); + case Instruction::Store: return getModRefInfo((const StoreInst*)I, Loc); + case Instruction::Fence: return getModRefInfo((const FenceInst*)I, Loc); + case Instruction::AtomicCmpXchg: + return getModRefInfo((const AtomicCmpXchgInst*)I, Loc); + case Instruction::AtomicRMW: + return getModRefInfo((const AtomicRMWInst*)I, Loc); + case Instruction::Call: return getModRefInfo((const CallInst*)I, Loc); + case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,Loc); + default: + return MRI_NoModRef; + } + } - /// canBasicBlockModify - Return true if it is possible for execution of the - /// specified basic block to modify the location Loc. - bool canBasicBlockModify(const BasicBlock &BB, const Location &Loc); - - /// canBasicBlockModify - A convenience wrapper. - bool canBasicBlockModify(const BasicBlock &BB, const Value *P, uint64_t Size){ - return canBasicBlockModify(BB, Location(P, Size)); + /// A convenience wrapper for constructing the memory location. + ModRefInfo getModRefInfo(const Instruction *I, const Value *P, + uint64_t Size) { + return getModRefInfo(I, MemoryLocation(P, Size)); } - /// canInstructionRangeModRef - Return true if it is possible for the - /// execution of the specified instructions to mod\ref (according to the - /// mode) the location Loc. The instructions to consider are all - /// of the instructions in the range of [I1,I2] INCLUSIVE. - /// I1 and I2 must be in the same basic block. - bool canInstructionRangeModRef(const Instruction &I1, - const Instruction &I2, const Location &Loc, - const ModRefResult Mode); + /// Return information about whether a call and an instruction may refer to + /// the same memory locations. + ModRefInfo getModRefInfo(Instruction *I, ImmutableCallSite Call); + + /// Return information about whether two call sites may refer to the same set + /// of memory locations. See the AA documentation for details: + /// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo + virtual ModRefInfo getModRefInfo(ImmutableCallSite CS1, + ImmutableCallSite CS2); - /// canInstructionRangeModRef - A convenience wrapper. - bool canInstructionRangeModRef(const Instruction &I1, - const Instruction &I2, const Value *Ptr, - uint64_t Size, const ModRefResult Mode) { - return canInstructionRangeModRef(I1, I2, Location(Ptr, Size), Mode); + /// \brief Return information about whether a particular call site modifies + /// or reads the specified memory location \p MemLoc before instruction \p I + /// in a BasicBlock. A ordered basic block \p OBB can be used to speed up + /// instruction ordering queries inside the BasicBlock containing \p I. + ModRefInfo callCapturesBefore(const Instruction *I, + const MemoryLocation &MemLoc, DominatorTree *DT, + OrderedBasicBlock *OBB = nullptr); + + /// \brief A convenience wrapper to synthesize a memory location. + ModRefInfo callCapturesBefore(const Instruction *I, const Value *P, + uint64_t Size, DominatorTree *DT, + OrderedBasicBlock *OBB = nullptr) { + return callCapturesBefore(I, MemoryLocation(P, Size), DT, OBB); } + /// @} //===--------------------------------------------------------------------===// - /// Methods that clients should call when they transform the program to allow - /// alias analyses to update their internal data structures. Note that these - /// methods may be called on any instruction, regardless of whether or not - /// they have pointer-analysis implications. - /// + /// \name Higher level methods for querying mod/ref information. + /// @{ - /// deleteValue - This method should be called whenever an LLVM Value is - /// deleted from the program, for example when an instruction is found to be - /// redundant and is eliminated. - /// - virtual void deleteValue(Value *V); + /// Check if it is possible for execution of the specified basic block to + /// modify the location Loc. + bool canBasicBlockModify(const BasicBlock &BB, const MemoryLocation &Loc); - /// copyValue - This method should be used whenever a preexisting value in the - /// program is copied or cloned, introducing a new value. Note that analysis - /// implementations should tolerate clients that use this method to introduce - /// the same value multiple times: if the analysis already knows about a - /// value, it should ignore the request. - /// - virtual void copyValue(Value *From, Value *To); - - /// addEscapingUse - This method should be used whenever an escaping use is - /// added to a pointer value. Analysis implementations may either return - /// conservative responses for that value in the future, or may recompute - /// some or all internal state to continue providing precise responses. - /// - /// Escaping uses are considered by anything _except_ the following: - /// - GEPs or bitcasts of the pointer - /// - Loads through the pointer - /// - Stores through (but not of) the pointer - virtual void addEscapingUse(Use &U); - - /// replaceWithNewValue - This method is the obvious combination of the two - /// above, and it provided as a helper to simplify client code. - /// - void replaceWithNewValue(Value *Old, Value *New) { - copyValue(Old, New); - deleteValue(Old); + /// A convenience wrapper synthesizing a memory location. + bool canBasicBlockModify(const BasicBlock &BB, const Value *P, + uint64_t Size) { + return canBasicBlockModify(BB, MemoryLocation(P, Size)); } -}; -// Specialize DenseMapInfo for Location. -template<> -struct DenseMapInfo { - static inline AliasAnalysis::Location getEmptyKey() { - return AliasAnalysis::Location(DenseMapInfo::getEmptyKey(), - 0); - } - static inline AliasAnalysis::Location getTombstoneKey() { - return AliasAnalysis::Location( - DenseMapInfo::getTombstoneKey(), 0); - } - static unsigned getHashValue(const AliasAnalysis::Location &Val) { - return DenseMapInfo::getHashValue(Val.Ptr) ^ - DenseMapInfo::getHashValue(Val.Size) ^ - DenseMapInfo::getHashValue(Val.AATags); - } - static bool isEqual(const AliasAnalysis::Location &LHS, - const AliasAnalysis::Location &RHS) { - return LHS.Ptr == RHS.Ptr && - LHS.Size == RHS.Size && - LHS.AATags == RHS.AATags; + /// Check if it is possible for the execution of the specified instructions + /// to mod\ref (according to the mode) the location Loc. + /// + /// The instructions to consider are all of the instructions in the range of + /// [I1,I2] INCLUSIVE. I1 and I2 must be in the same basic block. + bool canInstructionRangeModRef(const Instruction &I1, const Instruction &I2, + const MemoryLocation &Loc, + const ModRefInfo Mode); + + /// A convenience wrapper synthesizing a memory location. + bool canInstructionRangeModRef(const Instruction &I1, const Instruction &I2, + const Value *Ptr, uint64_t Size, + const ModRefInfo Mode) { + return canInstructionRangeModRef(I1, I2, MemoryLocation(Ptr, Size), Mode); } }; diff --git a/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h index fc45903042f..881699d0922 100644 --- a/include/llvm/Analysis/AliasSetTracker.h +++ b/include/llvm/Analysis/AliasSetTracker.h @@ -117,24 +117,30 @@ class AliasSet : public ilist_node { // AliasSets forwarding to it. unsigned RefCount : 28; - /// AccessType - Keep track of whether this alias set merely refers to the - /// locations of memory, whether it modifies the memory, or whether it does - /// both. The lattice goes from "NoModRef" to either Refs or Mods, then to - /// ModRef as necessary. + /// The kinds of access this alias set models. /// - enum AccessType { - NoModRef = 0, Refs = 1, // Ref = bit 1 - Mods = 2, ModRef = 3 // Mod = bit 2 + /// We keep track of whether this alias set merely refers to the locations of + /// memory (and not any particular access), whether it modifies or references + /// the memory, or whether it does both. The lattice goes from "NoAccess" to + /// either RefAccess or ModAccess, then to ModRefAccess as necessary. + enum AccessLattice { + NoAccess = 0, + RefAccess = 1, + ModAccess = 2, + ModRefAccess = RefAccess | ModAccess }; - unsigned AccessTy : 2; + unsigned Access : 2; - /// AliasType - Keep track the relationships between the pointers in the set. - /// Lattice goes from MustAlias to MayAlias. + /// The kind of alias relationship between pointers of the set. /// - enum AliasType { - MustAlias = 0, MayAlias = 1 + /// These represent conservatively correct alias results between any members + /// of the set. We represent these independently of the values of alias + /// results in order to pack it into a single bit. Lattice goes from + /// MustAlias to MayAlias. + enum AliasLattice { + SetMustAlias = 0, SetMayAlias = 1 }; - unsigned AliasTy : 1; + unsigned Alias : 1; // Volatile - True if this alias set contains volatile loads or stores. bool Volatile : 1; @@ -153,10 +159,10 @@ class AliasSet : public ilist_node { public: /// Accessors... - bool isRef() const { return AccessTy & Refs; } - bool isMod() const { return AccessTy & Mods; } - bool isMustAlias() const { return AliasTy == MustAlias; } - bool isMayAlias() const { return AliasTy == MayAlias; } + bool isRef() const { return Access & RefAccess; } + bool isMod() const { return Access & ModAccess; } + bool isMustAlias() const { return Alias == SetMustAlias; } + bool isMayAlias() const { return Alias == SetMayAlias; } // isVolatile - Return true if this alias set contains volatile loads or // stores. @@ -218,7 +224,7 @@ class AliasSet : public ilist_node { friend struct ilist_sentinel_traits; AliasSet() : PtrList(nullptr), PtrListEnd(&PtrList), Forward(nullptr), RefCount(0), - AccessTy(NoModRef), AliasTy(MustAlias), Volatile(false) { + Access(NoAccess), Alias(SetMustAlias), Volatile(false) { } AliasSet(const AliasSet &AS) = delete; @@ -268,7 +274,7 @@ class AliasSet : public ilist_node { /// bool aliasesPointer(const Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo, AliasAnalysis &AA) const; - bool aliasesUnknownInst(Instruction *Inst, AliasAnalysis &AA) const; + bool aliasesUnknownInst(const Instruction *Inst, AliasAnalysis &AA) const; }; inline raw_ostream& operator<<(raw_ostream &OS, const AliasSet &AS) { @@ -358,7 +364,7 @@ class AliasSetTracker { /// getAliasSetForPointerIfExists - Return the alias set containing the /// location specified if one exists, otherwise return null. - AliasSet *getAliasSetForPointerIfExists(Value *P, uint64_t Size, + AliasSet *getAliasSetForPointerIfExists(const Value *P, uint64_t Size, const AAMDNodes &AAInfo) { return findAliasSetForPointer(P, Size, AAInfo); } @@ -366,11 +372,12 @@ class AliasSetTracker { /// containsPointer - Return true if the specified location is represented by /// this alias set, false otherwise. This does not modify the AST object or /// alias sets. - bool containsPointer(Value *P, uint64_t Size, const AAMDNodes &AAInfo) const; + bool containsPointer(const Value *P, uint64_t Size, + const AAMDNodes &AAInfo) const; /// Return true if the specified instruction "may" (or must) alias one of the /// members in any of the sets. - bool containsUnknown(Instruction *I) const; + bool containsUnknown(const Instruction *I) const; /// getAliasAnalysis - Return the underlying alias analysis object used by /// this tracker. @@ -418,11 +425,11 @@ class AliasSetTracker { } AliasSet &addPointer(Value *P, uint64_t Size, const AAMDNodes &AAInfo, - AliasSet::AccessType E, + AliasSet::AccessLattice E, bool &NewSet) { NewSet = false; AliasSet &AS = getAliasSetForPointer(P, Size, AAInfo, &NewSet); - AS.AccessTy |= E; + AS.Access |= E; return AS; } AliasSet *findAliasSetForPointer(const Value *Ptr, uint64_t Size, diff --git a/include/llvm/Analysis/AssumptionCache.h b/include/llvm/Analysis/AssumptionCache.h index 1f00b691b30..9de8ed5d424 100644 --- a/include/llvm/Analysis/AssumptionCache.h +++ b/include/llvm/Analysis/AssumptionCache.h @@ -66,7 +66,7 @@ class AssumptionCache { /// \brief Add an @llvm.assume intrinsic to this function's cache. /// - /// The call passed in must be an instruction within this fuction and must + /// The call passed in must be an instruction within this function and must /// not already be in the cache. void registerAssumption(CallInst *CI); @@ -79,7 +79,7 @@ class AssumptionCache { } /// \brief Access the list of assumption handles currently tracked for this - /// fuction. + /// function. /// /// Note that these produce weak handles that may be null. The caller must /// handle that case. diff --git a/include/llvm/Analysis/BlockFrequencyInfo.h b/include/llvm/Analysis/BlockFrequencyInfo.h index f27c32df928..2b6b16a3fb9 100644 --- a/include/llvm/Analysis/BlockFrequencyInfo.h +++ b/include/llvm/Analysis/BlockFrequencyInfo.h @@ -21,26 +21,20 @@ namespace llvm { class BranchProbabilityInfo; +class LoopInfo; template class BlockFrequencyInfoImpl; /// BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to /// estimate IR basic block frequencies. -class BlockFrequencyInfo : public FunctionPass { +class BlockFrequencyInfo { typedef BlockFrequencyInfoImpl ImplType; std::unique_ptr BFI; public: - static char ID; - BlockFrequencyInfo(); + BlockFrequencyInfo(const Function &F, const BranchProbabilityInfo &BPI, + const LoopInfo &LI); - ~BlockFrequencyInfo() override; - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - bool runOnFunction(Function &F) override; - void releaseMemory() override; - void print(raw_ostream &O, const Module *M) const override; const Function *getFunction() const; void view() const; @@ -51,6 +45,10 @@ class BlockFrequencyInfo : public FunctionPass { /// floating points. BlockFrequency getBlockFreq(const BasicBlock *BB) const; + /// calculate - compute block frequency info for the given function. + void calculate(const Function &F, const BranchProbabilityInfo &BPI, + const LoopInfo &LI); + // Print the block frequency Freq to OS using the current functions entry // frequency to convert freq into a relative decimal form. raw_ostream &printBlockFreq(raw_ostream &OS, const BlockFrequency Freq) const; @@ -60,7 +58,28 @@ class BlockFrequencyInfo : public FunctionPass { raw_ostream &printBlockFreq(raw_ostream &OS, const BasicBlock *BB) const; uint64_t getEntryFreq() const; + void releaseMemory(); + void print(raw_ostream &OS) const; +}; + +/// \brief Legacy analysis pass which computes \c BlockFrequencyInfo. +class BlockFrequencyInfoWrapperPass : public FunctionPass { + BlockFrequencyInfo BFI; +public: + static char ID; + + BlockFrequencyInfoWrapperPass(); + ~BlockFrequencyInfoWrapperPass() override; + + BlockFrequencyInfo &getBFI() { return BFI; } + const BlockFrequencyInfo &getBFI() const { return BFI; } + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + bool runOnFunction(Function &F) override; + void releaseMemory() override; + void print(raw_ostream &OS, const Module *M) const override; }; } diff --git a/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/include/llvm/Analysis/BlockFrequencyInfoImpl.h index 9acc863a738..6c101a63e12 100644 --- a/include/llvm/Analysis/BlockFrequencyInfoImpl.h +++ b/include/llvm/Analysis/BlockFrequencyInfoImpl.h @@ -191,28 +191,31 @@ class BlockFrequencyInfoImplBase { /// \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, 4> ExitMap; typedef SmallVector NodeList; - LoopData *Parent; ///< The parent loop. - bool IsPackaged; ///< Whether this has been packaged. - uint32_t NumHeaders; ///< Number of headers. - ExitMap Exits; ///< Successor edges (and weights). - NodeList Nodes; ///< Header and the members of the loop. - BlockMass BackedgeMass; ///< Mass returned to loop header. + typedef SmallVector HeaderMassList; + LoopData *Parent; ///< The parent loop. + bool IsPackaged; ///< Whether this has been packaged. + uint32_t NumHeaders; ///< Number of headers. + ExitMap Exits; ///< Successor edges (and weights). + NodeList Nodes; ///< Header and the members of the loop. + HeaderMassList BackedgeMass; ///< Mass returned to each loop header. BlockMass Mass; Scaled64 Scale; LoopData(LoopData *Parent, const BlockNode &Header) - : Parent(Parent), IsPackaged(false), NumHeaders(1), Nodes(1, Header) {} + : Parent(Parent), IsPackaged(false), NumHeaders(1), Nodes(1, Header), + BackedgeMass(1) {} template LoopData(LoopData *Parent, It1 FirstHeader, It1 LastHeader, It2 FirstOther, It2 LastOther) : Parent(Parent), IsPackaged(false), Nodes(FirstHeader, LastHeader) { NumHeaders = Nodes.size(); Nodes.insert(Nodes.end(), FirstOther, LastOther); + BackedgeMass.resize(NumHeaders); } bool isHeader(const BlockNode &Node) const { if (isIrreducible()) @@ -223,6 +226,14 @@ class BlockFrequencyInfoImplBase { BlockNode getHeader() const { return Nodes[0]; } bool isIrreducible() const { return NumHeaders > 1; } + HeaderMassList::difference_type getHeaderIndex(const BlockNode &B) { + assert(isHeader(B) && "this is only valid on loop header blocks"); + if (isIrreducible()) + return std::lower_bound(Nodes.begin(), Nodes.begin() + NumHeaders, B) - + Nodes.begin(); + return 0; + } + NodeList::const_iterator members_begin() const { return Nodes.begin() + NumHeaders; } @@ -431,6 +442,16 @@ class BlockFrequencyInfoImplBase { /// \brief Compute the loop scale for a loop. void computeLoopScale(LoopData &Loop); + /// Adjust the mass of all headers in an irreducible loop. + /// + /// Initially, irreducible loops are assumed to distribute their mass + /// equally among its headers. This can lead to wrong frequency estimates + /// since some headers may be executed more frequently than others. + /// + /// This adjusts header mass distribution so it matches the weights of + /// the backedges going into each of the loop headers. + void adjustLoopHeaderMass(LoopData &Loop); + /// \brief Package up a loop. void packageLoop(LoopData &Loop); @@ -695,6 +716,17 @@ void IrreducibleGraph::addEdges(const BlockNode &Node, /// - Distribute the mass accordingly, dithering to minimize mass loss, /// as described in \a distributeMass(). /// +/// In the case of irreducible loops, instead of a single loop header, +/// there will be several. The computation of backedge masses is similar +/// but instead of having a single backedge mass, there will be one +/// backedge per loop header. In these cases, each backedge will carry +/// a mass proportional to the edge weights along the corresponding +/// path. +/// +/// At the end of propagation, the full mass assigned to the loop will be +/// distributed among the loop headers proportionally according to the +/// mass flowing through their backedges. +/// /// Finally, calculate the loop scale from the accumulated backedge mass. /// /// 3. Distribute mass in the function (\a computeMassInFunction()). @@ -735,11 +767,6 @@ void IrreducibleGraph::addEdges(const BlockNode &Node, /// as sub-loops, rather than arbitrarily shoving the problematic /// blocks into the headers of the main irreducible SCC. /// -/// - Backedge frequencies are assumed to be evenly split between the -/// headers of a given irreducible SCC. Instead, we could track the -/// backedge mass separately for each header, and adjust their relative -/// frequencies. -/// /// - Entry frequencies are assumed to be evenly split between the /// headers of a given irreducible SCC, which is the only option if we /// need to compute mass in the SCC before its parent loop. Instead, @@ -846,7 +873,7 @@ template class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase { /// /// \pre \a computeMassInLoop() has been called for each subloop of \c /// OuterLoop. - /// \pre \c Insert points at the the last loop successfully processed by \a + /// \pre \c Insert points at the last loop successfully processed by \a /// computeMassInLoop(). /// \pre \c OuterLoop has irreducible SCCs. void computeIrreducibleMass(LoopData *OuterLoop, @@ -878,8 +905,8 @@ template class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase { public: const FunctionT *getFunction() const { return F; } - void doFunction(const FunctionT *F, const BranchProbabilityInfoT *BPI, - const LoopInfoT *LI); + void calculate(const FunctionT &F, const BranchProbabilityInfoT &BPI, + const LoopInfoT &LI); BlockFrequencyInfoImpl() : BPI(nullptr), LI(nullptr), F(nullptr) {} using BlockFrequencyInfoImplBase::getEntryFreq; @@ -911,13 +938,13 @@ template class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase { }; template -void BlockFrequencyInfoImpl::doFunction(const FunctionT *F, - const BranchProbabilityInfoT *BPI, - const LoopInfoT *LI) { +void BlockFrequencyInfoImpl::calculate(const FunctionT &F, + const BranchProbabilityInfoT &BPI, + const LoopInfoT &LI) { // Save the parameters. - this->BPI = BPI; - this->LI = LI; - this->F = F; + this->BPI = &BPI; + this->LI = &LI; + this->F = &F; // Clean up left-over data structures. BlockFrequencyInfoImplBase::clear(); @@ -925,12 +952,12 @@ void BlockFrequencyInfoImpl::doFunction(const FunctionT *F, Nodes.clear(); // Initialize. - DEBUG(dbgs() << "\nblock-frequency: " << F->getName() << "\n=================" - << std::string(F->getName().size(), '=') << "\n"); + DEBUG(dbgs() << "\nblock-frequency: " << F.getName() << "\n=================" + << std::string(F.getName().size(), '=') << "\n"); 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(); @@ -1042,6 +1069,8 @@ bool BlockFrequencyInfoImpl::computeMassInLoop(LoopData &Loop) { for (const BlockNode &M : Loop.Nodes) if (!propagateMassToSuccessors(&Loop, M)) llvm_unreachable("unhandled irreducible control flow"); + + adjustLoopHeaderMass(Loop); } else { Working[Loop.getHeader().Index].getMass() = BlockMass::getFull(); if (!propagateMassToSuccessors(&Loop, Loop.getHeader())) diff --git a/include/llvm/Analysis/BranchProbabilityInfo.h b/include/llvm/Analysis/BranchProbabilityInfo.h index 89eef68d843..a6e721a388e 100644 --- a/include/llvm/Analysis/BranchProbabilityInfo.h +++ b/include/llvm/Analysis/BranchProbabilityInfo.h @@ -25,9 +25,9 @@ namespace llvm { class LoopInfo; class raw_ostream; -/// \brief Analysis pass providing branch probability information. +/// \brief Analysis providing branch probability information. /// -/// This is a function analysis pass which provides information on the relative +/// This is a function analysis which provides information on the relative /// probabilities of each "edge" in the function's CFG where such an edge is /// defined by a pair (PredBlock and an index in the successors). The /// probability of an edge from one block is always relative to the @@ -37,17 +37,14 @@ class raw_ostream; /// identify an edge, since we can have multiple edges from Src to Dst. /// As an example, we can have a switch which jumps to Dst with value 0 and /// value 10. -class BranchProbabilityInfo : public FunctionPass { +class BranchProbabilityInfo { public: - static char ID; + BranchProbabilityInfo() {} + BranchProbabilityInfo(Function &F, const LoopInfo &LI) { calculate(F, LI); } - BranchProbabilityInfo() : FunctionPass(ID) { - initializeBranchProbabilityInfoPass(*PassRegistry::getPassRegistry()); - } + void releaseMemory(); - void getAnalysisUsage(AnalysisUsage &AU) const override; - bool runOnFunction(Function &F) override; - void print(raw_ostream &OS, const Module *M = nullptr) const override; + void print(raw_ostream &OS) const; /// \brief Get an edge's probability, relative to other out-edges of the Src. /// @@ -115,6 +112,8 @@ class BranchProbabilityInfo : public FunctionPass { return IsLikely ? (1u << 20) - 1 : 1; } + void calculate(Function &F, const LoopInfo& LI); + private: // Since we allow duplicate edges from one basic block to another, we use // a pair (PredBlock and an index in the successors) to specify an edge. @@ -130,9 +129,6 @@ class BranchProbabilityInfo : public FunctionPass { DenseMap Weights; - /// \brief Handle to the LoopInfo analysis. - LoopInfo *LI; - /// \brief Track the last function we run over for printing. Function *LastF; @@ -149,12 +145,33 @@ class BranchProbabilityInfo : public FunctionPass { bool calcMetadataWeights(BasicBlock *BB); bool calcColdCallHeuristics(BasicBlock *BB); bool calcPointerHeuristics(BasicBlock *BB); - bool calcLoopBranchHeuristics(BasicBlock *BB); + bool calcLoopBranchHeuristics(BasicBlock *BB, const LoopInfo &LI); bool calcZeroHeuristics(BasicBlock *BB); bool calcFloatingPointHeuristics(BasicBlock *BB); bool calcInvokeHeuristics(BasicBlock *BB); }; +/// \brief Legacy analysis pass which computes \c BranchProbabilityInfo. +class BranchProbabilityInfoWrapperPass : public FunctionPass { + BranchProbabilityInfo BPI; + +public: + static char ID; + + BranchProbabilityInfoWrapperPass() : FunctionPass(ID) { + initializeBranchProbabilityInfoWrapperPassPass( + *PassRegistry::getPassRegistry()); + } + + BranchProbabilityInfo &getBPI() { return BPI; } + const BranchProbabilityInfo &getBPI() const { return BPI; } + + void getAnalysisUsage(AnalysisUsage &AU) const override; + bool runOnFunction(Function &F) override; + void releaseMemory() override; + void print(raw_ostream &OS, const Module *M = nullptr) const override; +}; + } #endif diff --git a/include/llvm/Analysis/CFG.h b/include/llvm/Analysis/CFG.h index 7f92eda8cb2..7c4df780198 100644 --- a/include/llvm/Analysis/CFG.h +++ b/include/llvm/Analysis/CFG.h @@ -78,6 +78,17 @@ bool isPotentiallyReachable(const BasicBlock *From, const BasicBlock *To, const DominatorTree *DT = nullptr, const LoopInfo *LI = nullptr); +/// \brief Determine whether there is at least one path from a block in +/// 'Worklist' to 'StopBB', returning true if uncertain. +/// +/// Determine whether there is a path from at least one block in Worklist to +/// StopBB within a single function. Returns false only if we can prove that +/// once any block in 'Worklist' has been reached then 'StopBB' can not be +/// executed. Conservatively returns true. +bool isPotentiallyReachableFromMany(SmallVectorImpl &Worklist, + BasicBlock *StopBB, + const DominatorTree *DT = nullptr, + const LoopInfo *LI = nullptr); } // End llvm namespace #endif diff --git a/include/llvm/Analysis/CGSCCPassManager.h b/include/llvm/Analysis/CGSCCPassManager.h index 0d4fe932481..6a406cd2440 100644 --- a/include/llvm/Analysis/CGSCCPassManager.h +++ b/include/llvm/Analysis/CGSCCPassManager.h @@ -263,8 +263,7 @@ template class ModuleToPostOrderCGSCCPassAdaptor { template ModuleToPostOrderCGSCCPassAdaptor createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) { - return std::move( - ModuleToPostOrderCGSCCPassAdaptor(std::move(Pass))); + return ModuleToPostOrderCGSCCPassAdaptor(std::move(Pass)); } /// \brief A CGSCC analysis which acts as a proxy for a function analysis @@ -484,7 +483,7 @@ template class CGSCCToFunctionPassAdaptor { template CGSCCToFunctionPassAdaptor createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) { - return std::move(CGSCCToFunctionPassAdaptor(std::move(Pass))); + return CGSCCToFunctionPassAdaptor(std::move(Pass)); } } diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h index 14b88220202..662ae0e6363 100644 --- a/include/llvm/Analysis/CallGraph.h +++ b/include/llvm/Analysis/CallGraph.h @@ -56,6 +56,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Function.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" #include @@ -229,8 +230,9 @@ class CallGraphNode { /// \brief Adds a function to the list of functions called by this one. void addCalledFunction(CallSite CS, CallGraphNode *M) { assert(!CS.getInstruction() || !CS.getCalledFunction() || - !CS.getCalledFunction()->isIntrinsic()); - CalledFunctions.push_back(std::make_pair(CS.getInstruction(), M)); + !CS.getCalledFunction()->isIntrinsic() || + !Intrinsic::isLeaf(CS.getCalledFunction()->getIntrinsicID())); + CalledFunctions.emplace_back(CS.getInstruction(), M); M->AddRef(); } diff --git a/include/llvm/Analysis/CaptureTracking.h b/include/llvm/Analysis/CaptureTracking.h index 8b7c7a90f7c..8d2c095d858 100644 --- a/include/llvm/Analysis/CaptureTracking.h +++ b/include/llvm/Analysis/CaptureTracking.h @@ -20,6 +20,7 @@ namespace llvm { class Use; class Instruction; class DominatorTree; + class OrderedBasicBlock; /// PointerMayBeCaptured - Return true if this pointer value may be captured /// by the enclosing function (which is required to exist). This routine can @@ -41,10 +42,12 @@ namespace llvm { /// it or not. The boolean StoreCaptures specified whether storing the value /// (or part of it) into memory anywhere automatically counts as capturing it /// or not. Captures by the provided instruction are considered if the - /// final parameter is true. + /// final parameter is true. An ordered basic block in \p OBB could be used + /// to speed up capture-tracker queries. bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures, bool StoreCaptures, const Instruction *I, - DominatorTree *DT, bool IncludeI = false); + DominatorTree *DT, bool IncludeI = false, + OrderedBasicBlock *OBB = nullptr); /// This callback is used in conjunction with PointerMayBeCaptured. In /// addition to the interface here, you'll need to provide your own getters diff --git a/include/llvm/Analysis/ConstantFolding.h b/include/llvm/Analysis/ConstantFolding.h index 541a2109af6..e8185b3b630 100644 --- a/include/llvm/Analysis/ConstantFolding.h +++ b/include/llvm/Analysis/ConstantFolding.h @@ -72,6 +72,17 @@ namespace llvm { Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val, ArrayRef Idxs); +/// \brief Attempt to constant fold an extractvalue instruction with the +/// specified operands and indices. The constant result is returned if +/// successful; if not, null is returned. +Constant *ConstantFoldExtractValueInstruction(Constant *Agg, + ArrayRef Idxs); + +/// \brief Attempt to constant fold an extractelement instruction with the +/// specified operands and indices. The constant result is returned if +/// successful; if not, null is returned. +Constant *ConstantFoldExtractElementInstruction(Constant *Val, Constant *Idx); + /// ConstantFoldLoadFromConstPtr - Return the value that a load from C would /// produce if it is constant and determinable. If this is not determinable, /// return null. diff --git a/include/llvm/Analysis/DependenceAnalysis.h b/include/llvm/Analysis/DependenceAnalysis.h index 0b3b2ea4281..a08ce574ea5 100644 --- a/include/llvm/Analysis/DependenceAnalysis.h +++ b/include/llvm/Analysis/DependenceAnalysis.h @@ -41,6 +41,7 @@ #define LLVM_ANALYSIS_DEPENDENCEANALYSIS_H #include "llvm/ADT/SmallBitVector.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/IR/Instructions.h" #include "llvm/Pass.h" @@ -520,11 +521,11 @@ namespace llvm { /// in LoopNest. bool isLoopInvariant(const SCEV *Expression, const Loop *LoopNest) const; - /// Makes sure both subscripts (i.e. Pair->Src and Pair->Dst) share the same - /// integer type by sign-extending one of them when necessary. + /// Makes sure all subscript pairs share the same integer type by + /// sign-extending as necessary. /// Sign-extending a subscript is safe because getelementptr assumes the - /// array subscripts are signed. - void unifySubscriptType(Subscript *Pair); + /// array subscripts are signed. + void unifySubscriptType(ArrayRef Pairs); /// removeMatchingExtensions - Examines a subscript pair. /// If the source and destination are identically sign (or zero) diff --git a/include/llvm/Analysis/DominanceFrontier.h b/include/llvm/Analysis/DominanceFrontier.h index 996700efdb6..fb730054a8e 100644 --- a/include/llvm/Analysis/DominanceFrontier.h +++ b/include/llvm/Analysis/DominanceFrontier.h @@ -202,8 +202,8 @@ class DominanceFrontier : public FunctionPass { void dump() const; }; -EXTERN_TEMPLATE_INSTANTIATION(class DominanceFrontierBase); -EXTERN_TEMPLATE_INSTANTIATION(class ForwardDominanceFrontierBase); +extern template class DominanceFrontierBase; +extern template class ForwardDominanceFrontierBase; } // End llvm namespace diff --git a/include/llvm/Analysis/DominanceFrontierImpl.h b/include/llvm/Analysis/DominanceFrontierImpl.h index 278d2981516..629ae380904 100644 --- a/include/llvm/Analysis/DominanceFrontierImpl.h +++ b/include/llvm/Analysis/DominanceFrontierImpl.h @@ -19,7 +19,9 @@ #define LLVM_ANALYSIS_DOMINANCEFRONTIERIMPL_H #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Analysis/DominanceFrontier.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/GenericDomTree.h" namespace llvm { diff --git a/include/llvm/Analysis/IVUsers.h b/include/llvm/Analysis/IVUsers.h index ae9c1f5bd9a..00dbcbdd780 100644 --- a/include/llvm/Analysis/IVUsers.h +++ b/include/llvm/Analysis/IVUsers.h @@ -21,6 +21,7 @@ namespace llvm { +class AssumptionCache; class DominatorTree; class Instruction; class Value; @@ -119,15 +120,19 @@ template<> struct ilist_traits class IVUsers : public LoopPass { friend class IVStrideUse; Loop *L; + AssumptionCache *AC; LoopInfo *LI; DominatorTree *DT; ScalarEvolution *SE; - SmallPtrSet Processed; + SmallPtrSet Processed; /// IVUses - A list of all tracked IV uses of induction variable expressions /// we are interested in. ilist IVUses; + // Ephemeral values used by @llvm.assume in this function. + SmallPtrSet EphValues; + void getAnalysisUsage(AnalysisUsage &AU) const override; bool runOnLoop(Loop *L, LPPassManager &LPM) override; diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index 706bd8000d3..d44c5ff4078 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -212,7 +212,7 @@ namespace llvm { /// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, - const DataLayout &DL, + FastMathFlags FMF, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -244,6 +244,24 @@ namespace llvm { AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); + /// \brief Given operands for an ExtractValueInst, see if we can fold the + /// result. If not, this returns null. + Value *SimplifyExtractValueInst(Value *Agg, ArrayRef Idxs, + const DataLayout &DL, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); + + /// \brief Given operands for an ExtractElementInst, see if we can fold the + /// result. If not, this returns null. + Value *SimplifyExtractElementInst(Value *Vec, Value *Idx, + const DataLayout &DL, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); + /// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold /// the result. If not, this returns null. Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout &DL, diff --git a/include/llvm/Analysis/IteratedDominanceFrontier.h b/include/llvm/Analysis/IteratedDominanceFrontier.h new file mode 100644 index 00000000000..5a339f10f50 --- /dev/null +++ b/include/llvm/Analysis/IteratedDominanceFrontier.h @@ -0,0 +1,96 @@ +//===- IteratedDominanceFrontier.h - Calculate IDF --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// \brief Compute iterated dominance frontiers using a linear time algorithm. +/// +/// The algorithm used here is based on: +/// +/// Sreedhar and Gao. A linear time algorithm for placing phi-nodes. +/// In Proceedings of the 22nd ACM SIGPLAN-SIGACT Symposium on Principles of +/// Programming Languages +/// POPL '95. ACM, New York, NY, 62-73. +/// +/// It has been modified to not explicitly use the DJ graph data structure and +/// to directly compute pruned SSA using per-variable liveness information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_IDF_H +#define LLVM_ANALYSIS_IDF_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +class BasicBlock; +template class DomTreeNodeBase; +typedef DomTreeNodeBase DomTreeNode; +class DominatorTree; + +/// \brief Determine the iterated dominance frontier, given a set of defining +/// blocks, and optionally, a set of live-in blocks. +/// +/// In turn, the results can be used to place phi nodes. +/// +/// This algorithm is a linear time computation of Iterated Dominance Frontiers, +/// pruned using the live-in set. +/// By default, liveness is not used to prune the IDF computation. +class IDFCalculator { + +public: + IDFCalculator(DominatorTree &DT) : DT(DT), useLiveIn(false) {} + + /// \brief Give the IDF calculator the set of blocks in which the value is + /// defined. This is equivalent to the set of starting blocks it should be + /// calculating the IDF for (though later gets pruned based on liveness). + /// + /// Note: This set *must* live for the entire lifetime of the IDF calculator. + void setDefiningBlocks(const SmallPtrSetImpl &Blocks) { + DefBlocks = &Blocks; + } + + /// \brief Give the IDF calculator the set of blocks in which the value is + /// live on entry to the block. This is used to prune the IDF calculation to + /// not include blocks where any phi insertion would be dead. + /// + /// Note: This set *must* live for the entire lifetime of the IDF calculator. + + void setLiveInBlocks(const SmallPtrSetImpl &Blocks) { + LiveInBlocks = &Blocks; + useLiveIn = true; + } + + /// \brief Reset the live-in block set to be empty, and tell the IDF + /// calculator to not use liveness anymore. + void resetLiveInBlocks() { + LiveInBlocks = nullptr; + useLiveIn = false; + } + + /// \brief Calculate iterated dominance frontiers + /// + /// This uses the linear-time phi algorithm based on DJ-graphs mentioned in + /// the file-level comment. It performs DF->IDF pruning using the live-in + /// set, to avoid computing the IDF for blocks where an inserted PHI node + /// would be dead. + void calculate(SmallVectorImpl &IDFBlocks); + +private: + DominatorTree &DT; + bool useLiveIn; + DenseMap DomLevels; + const SmallPtrSetImpl *LiveInBlocks; + const SmallPtrSetImpl *DefBlocks; + SmallVector PHIBlocks; +}; +} +#endif diff --git a/include/llvm/Analysis/JumpInstrTableInfo.h b/include/llvm/Analysis/JumpInstrTableInfo.h deleted file mode 100644 index b6dad478cdf..00000000000 --- a/include/llvm/Analysis/JumpInstrTableInfo.h +++ /dev/null @@ -1,71 +0,0 @@ -//===-- JumpInstrTableInfo.h: Info for Jump-Instruction Tables --*- C++ -*-===// -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief Information about jump-instruction tables that have been created by -/// JumpInstrTables pass. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H -#define LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/Pass.h" -#include - -namespace llvm { -class Function; -class FunctionType; - -/// This class stores information about jump-instruction tables created by the -/// JumpInstrTables pass (in lib/CodeGen/JumpInstrTables.cpp). Each table is a -/// map from a function type to a vector of pairs. The first element of each -/// pair is the function that has the jumptable annotation. The second element -/// is a function that was declared by JumpInstrTables and used to replace all -/// address-taking sites for the original function. -/// -/// The information in this pass is used in AsmPrinter -/// (lib/CodeGen/AsmPrinter/AsmPrinter.cpp) to generate the required assembly -/// for the jump-instruction tables. -class JumpInstrTableInfo : public ImmutablePass { -public: - static char ID; - - /// The default byte alignment for jump tables is 16, which is large but - /// usually safe. - JumpInstrTableInfo(uint64_t ByteAlign = 16); - ~JumpInstrTableInfo() override; - const char *getPassName() const override { - return "Jump-Instruction Table Info"; - } - - typedef std::pair JumpPair; - typedef DenseMap > JumpTables; - - /// Inserts an entry in a table, adding the table if it doesn't exist. - void insertEntry(FunctionType *TableFunTy, Function *Target, Function *Jump); - - /// Gets the tables. - const JumpTables &getTables() const { return Tables; } - - /// Gets the alignment in bytes of a jumptable entry. - uint64_t entryByteAlignment() const { return ByteAlignment; } -private: - JumpTables Tables; - - /// A power-of-two alignment of a jumptable entry. - uint64_t ByteAlignment; -}; - -/// Creates a JumpInstrTableInfo pass with the given bound on entry size. This -/// bound specifies the maximum number of bytes needed to represent an -/// unconditional jump or a trap instruction in the back end currently in use. -ModulePass *createJumpInstrTableInfoPass(unsigned Bound); -} - -#endif /* LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H */ diff --git a/include/llvm/Analysis/LazyCallGraph.h b/include/llvm/Analysis/LazyCallGraph.h index b0b9068de34..7cbc40f768e 100644 --- a/include/llvm/Analysis/LazyCallGraph.h +++ b/include/llvm/Analysis/LazyCallGraph.h @@ -190,7 +190,7 @@ class LazyCallGraph { Function &getFunction() const { return F; - }; + } iterator begin() const { return iterator(*G, Callees.begin(), Callees.end()); diff --git a/include/llvm/Analysis/LazyValueInfo.h b/include/llvm/Analysis/LazyValueInfo.h index 1051cff5efb..42002062dca 100644 --- a/include/llvm/Analysis/LazyValueInfo.h +++ b/include/llvm/Analysis/LazyValueInfo.h @@ -25,7 +25,7 @@ namespace llvm { class Instruction; class TargetLibraryInfo; class Value; - + /// This pass computes, caches, and vends lazy value constraint information. class LazyValueInfo : public FunctionPass { AssumptionCache *AC; @@ -45,23 +45,22 @@ class LazyValueInfo : public FunctionPass { enum Tristate { Unknown = -1, False = 0, True = 1 }; - - + // Public query interface. - + /// Determine whether the specified value comparison with a constant is known /// to be true or false on the specified CFG edge. /// Pred is a CmpInst predicate. Tristate getPredicateOnEdge(unsigned Pred, Value *V, Constant *C, BasicBlock *FromBB, BasicBlock *ToBB, Instruction *CxtI = nullptr); - + /// Determine whether the specified value comparison with a constant is known /// to be true or false at the specified instruction /// (from an assume intrinsic). Pred is a CmpInst predicate. Tristate getPredicateAt(unsigned Pred, Value *V, Constant *C, Instruction *CxtI); - + /// Determine whether the specified value is known to be a /// constant at the end of the specified block. Return null if not. Constant *getConstant(Value *V, BasicBlock *BB, Instruction *CxtI = nullptr); @@ -70,14 +69,14 @@ class LazyValueInfo : public FunctionPass { /// constant on the specified edge. Return null if not. Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB, Instruction *CxtI = nullptr); - + /// Inform the analysis cache that we have threaded an edge from /// PredBB to OldSucc to be from PredBB to NewSucc instead. void threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, BasicBlock *NewSucc); - + /// Inform the analysis cache that we have erased a block. void eraseBlock(BasicBlock *BB); - + // Implementation boilerplate. void getAnalysisUsage(AnalysisUsage &AU) const override; diff --git a/include/llvm/Analysis/LibCallAliasAnalysis.h b/include/llvm/Analysis/LibCallAliasAnalysis.h index df95e0e6fdc..12b10a988eb 100644 --- a/include/llvm/Analysis/LibCallAliasAnalysis.h +++ b/include/llvm/Analysis/LibCallAliasAnalysis.h @@ -38,11 +38,11 @@ namespace llvm { } ~LibCallAliasAnalysis() override; - ModRefResult getModRefInfo(ImmutableCallSite CS, - const Location &Loc) override; - - ModRefResult getModRefInfo(ImmutableCallSite CS1, - ImmutableCallSite CS2) override { + ModRefInfo getModRefInfo(ImmutableCallSite CS, + const MemoryLocation &Loc) override; + + ModRefInfo getModRefInfo(ImmutableCallSite CS1, + ImmutableCallSite CS2) override { // TODO: Could compare two direct calls against each other if we cared to. return AliasAnalysis::getModRefInfo(CS1, CS2); } @@ -62,9 +62,9 @@ namespace llvm { } private: - ModRefResult AnalyzeLibCallDetails(const LibCallFunctionInfo *FI, - ImmutableCallSite CS, - const Location &Loc); + ModRefInfo AnalyzeLibCallDetails(const LibCallFunctionInfo *FI, + ImmutableCallSite CS, + const MemoryLocation &Loc); }; } // End of llvm namespace diff --git a/include/llvm/Analysis/LibCallSemantics.h b/include/llvm/Analysis/LibCallSemantics.h index 34831b2849d..09411b9b860 100644 --- a/include/llvm/Analysis/LibCallSemantics.h +++ b/include/llvm/Analysis/LibCallSemantics.h @@ -48,8 +48,7 @@ class InvokeInst; enum LocResult { Yes, No, Unknown }; - LocResult (*isLocation)(ImmutableCallSite CS, - const AliasAnalysis::Location &Loc); + LocResult (*isLocation)(ImmutableCallSite CS, const MemoryLocation &Loc); }; /// LibCallFunctionInfo - Each record in the array of FunctionInfo structs @@ -72,15 +71,15 @@ class InvokeInst; /// any specific context knowledge. For example, if the function is known /// to be readonly, this would be set to 'ref'. If known to be readnone, /// this is set to NoModRef. - AliasAnalysis::ModRefResult UniversalBehavior; - + ModRefInfo UniversalBehavior; + /// LocationMRInfo - This pair captures info about whether a specific /// location is modified or referenced by a libcall. struct LocationMRInfo { /// LocationID - ID # of the accessed location or ~0U for array end. unsigned LocationID; /// MRInfo - Mod/Ref info for this location. - AliasAnalysis::ModRefResult MRInfo; + ModRefInfo MRInfo; }; /// DetailsType - Indicate the sense of the LocationDetails array. This @@ -207,7 +206,19 @@ class InvokeInst; llvm_unreachable("invalid enum"); } - bool canSimplifyInvokeNoUnwind(const InvokeInst *II); + /// \brief Return true if this personality may be safely removed if there + /// are no invoke instructions remaining in the current function. + inline bool isNoOpWithoutInvoke(EHPersonality Pers) { + switch (Pers) { + case EHPersonality::Unknown: + return false; + // All known personalities currently have this behavior + default: return true; + } + llvm_unreachable("invalid enum"); + } + + bool canSimplifyInvokeNoUnwind(const Function *F); } // end namespace llvm diff --git a/include/llvm/Analysis/LoopAccessAnalysis.h b/include/llvm/Analysis/LoopAccessAnalysis.h index a4393bba232..7971bbbbd19 100644 --- a/include/llvm/Analysis/LoopAccessAnalysis.h +++ b/include/llvm/Analysis/LoopAccessAnalysis.h @@ -225,6 +225,8 @@ class MemoryDepChecker { return RecordInterestingDependences ? &InterestingDependences : nullptr; } + void clearInterestingDependences() { InterestingDependences.clear(); } + /// \brief The vector of memory access instructions. The indices are used as /// instruction identifiers in the Dependence class. const SmallVectorImpl &getMemoryInstructions() const { @@ -290,6 +292,163 @@ class MemoryDepChecker { bool couldPreventStoreLoadForward(unsigned Distance, unsigned TypeByteSize); }; +/// \brief Holds information about the memory runtime legality checks to verify +/// that a group of pointers do not overlap. +class RuntimePointerChecking { +public: + struct PointerInfo { + /// Holds the pointer value that we need to check. + TrackingVH PointerValue; + /// Holds the pointer value at the beginning of the loop. + const SCEV *Start; + /// Holds the pointer value at the end of the loop. + const SCEV *End; + /// Holds the information if this pointer is used for writing to memory. + bool IsWritePtr; + /// Holds the id of the set of pointers that could be dependent because of a + /// shared underlying object. + unsigned DependencySetId; + /// Holds the id of the disjoint alias set to which this pointer belongs. + unsigned AliasSetId; + /// SCEV for the access. + const SCEV *Expr; + + PointerInfo(Value *PointerValue, const SCEV *Start, const SCEV *End, + bool IsWritePtr, unsigned DependencySetId, unsigned AliasSetId, + const SCEV *Expr) + : PointerValue(PointerValue), Start(Start), End(End), + IsWritePtr(IsWritePtr), DependencySetId(DependencySetId), + AliasSetId(AliasSetId), Expr(Expr) {} + }; + + RuntimePointerChecking(ScalarEvolution *SE) : Need(false), SE(SE) {} + + /// Reset the state of the pointer runtime information. + void reset() { + Need = false; + Pointers.clear(); + } + + /// Insert a pointer and calculate the start and end SCEVs. + void insert(Loop *Lp, Value *Ptr, bool WritePtr, unsigned DepSetId, + unsigned ASId, const ValueToValueMap &Strides); + + /// \brief No run-time memory checking is necessary. + bool empty() const { return Pointers.empty(); } + + /// A grouping of pointers. A single memcheck is required between + /// two groups. + struct CheckingPtrGroup { + /// \brief Create a new pointer checking group containing a single + /// pointer, with index \p Index in RtCheck. + CheckingPtrGroup(unsigned Index, RuntimePointerChecking &RtCheck) + : RtCheck(RtCheck), High(RtCheck.Pointers[Index].End), + Low(RtCheck.Pointers[Index].Start) { + Members.push_back(Index); + } + + /// \brief Tries to add the pointer recorded in RtCheck at index + /// \p Index to this pointer checking group. We can only add a pointer + /// to a checking group if we will still be able to get + /// the upper and lower bounds of the check. Returns true in case + /// of success, false otherwise. + bool addPointer(unsigned Index); + + /// Constitutes the context of this pointer checking group. For each + /// pointer that is a member of this group we will retain the index + /// at which it appears in RtCheck. + RuntimePointerChecking &RtCheck; + /// The SCEV expression which represents the upper bound of all the + /// pointers in this group. + const SCEV *High; + /// The SCEV expression which represents the lower bound of all the + /// pointers in this group. + const SCEV *Low; + /// Indices of all the pointers that constitute this grouping. + SmallVector Members; + }; + + /// \brief A memcheck which made up of a pair of grouped pointers. + /// + /// These *have* to be const for now, since checks are generated from + /// CheckingPtrGroups in LAI::addRuntimeCheck which is a const member + /// function. FIXME: once check-generation is moved inside this class (after + /// the PtrPartition hack is removed), we could drop const. + typedef std::pair + PointerCheck; + + /// \brief Groups pointers such that a single memcheck is required + /// between two different groups. This will clear the CheckingGroups vector + /// and re-compute it. We will only group dependecies if \p UseDependencies + /// is true, otherwise we will create a separate group for each pointer. + void groupChecks(MemoryDepChecker::DepCandidates &DepCands, + bool UseDependencies); + + /// Generate the checks and return them. + /// + /// \p PtrToPartition contains the partition number for pointers. If passed, + /// omit checks between pointers belonging to the same partition. Partition + /// number -1 means that the pointer is used in multiple partitions. In this + /// case we can't safely omit the check. + SmallVector + generateChecks(const SmallVectorImpl *PtrPartition = nullptr) const; + + /// \brief Decide if we need to add a check between two groups of pointers, + /// according to needsChecking. + bool needsChecking(const CheckingPtrGroup &M, const CheckingPtrGroup &N, + const SmallVectorImpl *PtrPartition) const; + + /// \brief Return true if any pointer requires run-time checking according + /// to needsChecking. + bool needsAnyChecking(const SmallVectorImpl *PtrPartition) const; + + /// \brief Returns the number of run-time checks required according to + /// needsChecking. + unsigned getNumberOfChecks(const SmallVectorImpl *PtrPartition) const; + + /// \brief Print the list run-time memory checks necessary. + /// + /// If \p PtrPartition is set, it contains the partition number for + /// pointers (-1 if the pointer belongs to multiple partitions). In this + /// case omit checks between pointers belonging to the same partition. + void print(raw_ostream &OS, unsigned Depth = 0, + const SmallVectorImpl *PtrPartition = nullptr) const; + + /// Print \p Checks. + void printChecks(raw_ostream &OS, const SmallVectorImpl &Checks, + unsigned Depth = 0) const; + + /// This flag indicates if we need to add the runtime check. + bool Need; + + /// Information about the pointers that may require checking. + SmallVector Pointers; + + /// Holds a partitioning of pointers into "check groups". + SmallVector CheckingGroups; + + /// \brief Check if pointers are in the same partition + /// + /// \p PtrToPartition contains the partition number for pointers (-1 if the + /// pointer belongs to multiple partitions). + static bool + arePointersInSamePartition(const SmallVectorImpl &PtrToPartition, + unsigned PtrIdx1, unsigned PtrIdx2); + + /// \brief Decide whether we need to issue a run-time check for pointer at + /// index \p I and \p J to prove their independence. + /// + /// If \p PtrPartition is set, it contains the partition number for + /// pointers (-1 if the pointer belongs to multiple partitions). In this + /// case omit checks between pointers belonging to the same partition. + bool needsChecking(unsigned I, unsigned J, + const SmallVectorImpl *PtrPartition = nullptr) const; + +private: + /// Holds a pointer to the ScalarEvolution analysis. + ScalarEvolution *SE; +}; + /// \brief Drive the analysis of memory accesses in the loop /// /// This class is responsible for analyzing the memory accesses of a loop. It @@ -306,83 +465,25 @@ class MemoryDepChecker { /// RuntimePointerCheck class. class LoopAccessInfo { public: - /// This struct holds information about the memory runtime legality check that - /// a group of pointers do not overlap. - struct RuntimePointerCheck { - RuntimePointerCheck() : Need(false) {} - - /// Reset the state of the pointer runtime information. - void reset() { - Need = false; - Pointers.clear(); - Starts.clear(); - Ends.clear(); - IsWritePtr.clear(); - DependencySetId.clear(); - AliasSetId.clear(); - } - - /// Insert a pointer and calculate the start and end SCEVs. - void insert(ScalarEvolution *SE, Loop *Lp, Value *Ptr, bool WritePtr, - unsigned DepSetId, unsigned ASId, - const ValueToValueMap &Strides); - - /// \brief No run-time memory checking is necessary. - bool empty() const { return Pointers.empty(); } - - /// \brief Decide whether we need to issue a run-time check for pointer at - /// index \p I and \p J to prove their independence. - /// - /// If \p PtrPartition is set, it contains the partition number for - /// pointers (-1 if the pointer belongs to multiple partitions). In this - /// case omit checks between pointers belonging to the same partition. - bool needsChecking(unsigned I, unsigned J, - const SmallVectorImpl *PtrPartition) const; - - /// \brief Return true if any pointer requires run-time checking according - /// to needsChecking. - bool needsAnyChecking(const SmallVectorImpl *PtrPartition) const; - - /// \brief Print the list run-time memory checks necessary. - /// - /// If \p PtrPartition is set, it contains the partition number for - /// pointers (-1 if the pointer belongs to multiple partitions). In this - /// case omit checks between pointers belonging to the same partition. - void print(raw_ostream &OS, unsigned Depth = 0, - const SmallVectorImpl *PtrPartition = nullptr) const; - - /// This flag indicates if we need to add the runtime check. - bool Need; - /// Holds the pointers that we need to check. - SmallVector, 2> Pointers; - /// Holds the pointer value at the beginning of the loop. - SmallVector Starts; - /// Holds the pointer value at the end of the loop. - SmallVector Ends; - /// Holds the information if this pointer is used for writing to memory. - SmallVector IsWritePtr; - /// Holds the id of the set of pointers that could be dependent because of a - /// shared underlying object. - SmallVector DependencySetId; - /// Holds the id of the disjoint alias set to which this pointer belongs. - SmallVector AliasSetId; - }; - LoopAccessInfo(Loop *L, ScalarEvolution *SE, const DataLayout &DL, const TargetLibraryInfo *TLI, AliasAnalysis *AA, - DominatorTree *DT, const ValueToValueMap &Strides); + DominatorTree *DT, LoopInfo *LI, + const ValueToValueMap &Strides); /// Return true we can analyze the memory accesses in the loop and there are /// no memory dependence cycles. bool canVectorizeMemory() const { return CanVecMem; } - const RuntimePointerCheck *getRuntimePointerCheck() const { - return &PtrRtCheck; + const RuntimePointerChecking *getRuntimePointerChecking() const { + return &PtrRtChecking; } /// \brief Number of memchecks required to prove independence of otherwise /// may-alias pointers. - unsigned getNumRuntimePointerChecks() const { return NumComparisons; } + unsigned getNumRuntimePointerChecks( + const SmallVectorImpl *PtrPartition = nullptr) const { + return PtrRtChecking.getNumberOfChecks(PtrPartition); + } /// Return true if the block BB needs to be predicated in order for the loop /// to be vectorized. @@ -409,6 +510,16 @@ class LoopAccessInfo { addRuntimeCheck(Instruction *Loc, const SmallVectorImpl *PtrPartition = nullptr) const; + /// \brief Generete the instructions for the checks in \p PointerChecks. + /// + /// Returns a pair of instructions where the first element is the first + /// instruction generated in possibly a sequence of instructions and the + /// second value is the final comparator value or NULL if no check is needed. + std::pair + addRuntimeCheck(Instruction *Loc, + const SmallVectorImpl + &PointerChecks) const; + /// \brief The diagnostics report generated for the analysis. E.g. why we /// couldn't analyze the loop. const Optional &getReport() const { return Report; } @@ -451,22 +562,19 @@ class LoopAccessInfo { /// We need to check that all of the pointers in this list are disjoint /// at runtime. - RuntimePointerCheck PtrRtCheck; + RuntimePointerChecking PtrRtChecking; /// \brief the Memory Dependence Checker which can determine the /// 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; const TargetLibraryInfo *TLI; AliasAnalysis *AA; DominatorTree *DT; + LoopInfo *LI; unsigned NumLoads; unsigned NumStores; @@ -497,6 +605,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. /// @@ -541,6 +654,7 @@ class LoopAccessAnalysis : public FunctionPass { const TargetLibraryInfo *TLI; AliasAnalysis *AA; DominatorTree *DT; + LoopInfo *LI; }; } // End llvm namespace diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index f3d85e68404..841c002a5c6 100644 --- a/include/llvm/Analysis/LoopInfo.h +++ b/include/llvm/Analysis/LoopInfo.h @@ -47,13 +47,6 @@ namespace llvm { template class AnalysisManager; class PreservedAnalyses; -template -inline void RemoveFromVector(std::vector &V, T *N) { - typename std::vector::iterator I = std::find(V.begin(), V.end(), N); - assert(I != V.end() && "N is not in this list!"); - V.erase(I); -} - class DominatorTree; class LoopInfo; class Loop; @@ -324,7 +317,10 @@ class LoopBase { /// current loop, updating the Blocks as appropriate. This does not update /// the mapping in the LoopInfo class. void removeBlockFromLoop(BlockT *BB) { - RemoveFromVector(Blocks, BB); + auto I = std::find(Blocks.begin(), Blocks.end(), BB); + assert(I != Blocks.end() && "N is not in this list!"); + Blocks.erase(I); + DenseBlockSet.erase(BB); } @@ -351,9 +347,7 @@ raw_ostream& operator<<(raw_ostream &OS, const LoopBase &Loop) { } // Implementation in LoopInfoImpl.h -#ifdef __GNUC__ -__extension__ extern template class LoopBase; -#endif +extern template class LoopBase; class Loop : public LoopBase { public: @@ -361,11 +355,11 @@ class Loop : public LoopBase { /// isLoopInvariant - Return true if the specified value is loop invariant /// - bool isLoopInvariant(Value *V) const; + bool isLoopInvariant(const Value *V) const; /// hasLoopInvariantOperands - Return true if all the operands of the /// specified instruction are loop invariant. - bool hasLoopInvariantOperands(Instruction *I) const; + bool hasLoopInvariantOperands(const Instruction *I) const; /// makeLoopInvariant - If the given value is an instruction inside of the /// loop and it can be hoisted, do so to make it trivially loop-invariant. @@ -493,7 +487,7 @@ class Loop : public LoopBase { template class LoopInfoBase { // BBMap - Mapping of basic blocks to the inner most loop they occur in - DenseMap BBMap; + DenseMap BBMap; std::vector TopLevelLoops; friend class LoopBase; friend class LoopInfo; @@ -543,9 +537,7 @@ class LoopInfoBase { /// getLoopFor - Return the inner most loop that BB lives in. If a basic /// block is in no loop (for example the entry node), null is returned. /// - LoopT *getLoopFor(const BlockT *BB) const { - return BBMap.lookup(const_cast(BB)); - } + LoopT *getLoopFor(const BlockT *BB) const { return BBMap.lookup(BB); } /// operator[] - same as getLoopFor... /// @@ -562,7 +554,7 @@ class LoopInfoBase { } // isLoopHeader - True if the block is a loop header node - bool isLoopHeader(BlockT *BB) const { + bool isLoopHeader(const BlockT *BB) const { const LoopT *L = getLoopFor(BB); return L && L->getHeader() == BB; } @@ -630,7 +622,7 @@ class LoopInfoBase { } /// Create the loop forest using a stable algorithm. - void Analyze(DominatorTreeBase &DomTree); + void analyze(const DominatorTreeBase &DomTree); // Debugging void print(raw_ostream &OS) const; @@ -639,9 +631,7 @@ class LoopInfoBase { }; // Implementation in LoopInfoImpl.h -#ifdef __GNUC__ -__extension__ extern template class LoopInfoBase; -#endif +extern template class LoopInfoBase; class LoopInfo : public LoopInfoBase { typedef LoopInfoBase BaseT; @@ -652,6 +642,7 @@ class LoopInfo : public LoopInfoBase { LoopInfo(const LoopInfo &) = delete; public: LoopInfo() {} + explicit LoopInfo(const DominatorTreeBase &DomTree); LoopInfo(LoopInfo &&Arg) : BaseT(std::move(static_cast(Arg))) {} LoopInfo &operator=(LoopInfo &&RHS) { @@ -729,12 +720,6 @@ class LoopAnalysis { /// \brief Provide a name for the analysis for debugging and logging. static StringRef name() { return "LoopAnalysis"; } - LoopAnalysis() {} - LoopAnalysis(const LoopAnalysis &Arg) {} - LoopAnalysis(LoopAnalysis &&Arg) {} - LoopAnalysis &operator=(const LoopAnalysis &RHS) { return *this; } - LoopAnalysis &operator=(LoopAnalysis &&RHS) { return *this; } - LoopInfo run(Function &F, AnalysisManager *AM); }; diff --git a/include/llvm/Analysis/LoopInfoImpl.h b/include/llvm/Analysis/LoopInfoImpl.h index 0490bb1d761..dcd9a0f4cbc 100644 --- a/include/llvm/Analysis/LoopInfoImpl.h +++ b/include/llvm/Analysis/LoopInfoImpl.h @@ -345,7 +345,7 @@ void LoopBase::print(raw_ostream &OS, unsigned Depth) const { template static void discoverAndMapSubloop(LoopT *L, ArrayRef Backedges, LoopInfoBase *LI, - DominatorTreeBase &DomTree) { + const DominatorTreeBase &DomTree) { typedef GraphTraits > InvBlockTraits; unsigned NumBlocks = 0; @@ -468,10 +468,10 @@ void PopulateLoopsDFS::insertIntoLoop(BlockT *Block) { /// insertions per block. template void LoopInfoBase:: -Analyze(DominatorTreeBase &DomTree) { +analyze(const DominatorTreeBase &DomTree) { // Postorder traversal of the dominator tree. - DomTreeNodeBase* DomRoot = DomTree.getRootNode(); + const DomTreeNodeBase *DomRoot = DomTree.getRootNode(); for (auto DomNode : post_order(DomRoot)) { BlockT *Header = DomNode->getBlock(); @@ -527,7 +527,7 @@ void LoopInfoBase::verify() const { // Verify that blocks are mapped to valid loops. #ifndef NDEBUG for (auto &Entry : BBMap) { - BlockT *BB = Entry.first; + const BlockT *BB = Entry.first; LoopT *L = Entry.second; assert(Loops.count(L) && "orphaned loop"); assert(L->contains(BB) && "orphaned block"); diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h index c8453e9ea34..511898071c2 100644 --- a/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -19,6 +19,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/IR/BasicBlock.h" +#include "llvm/IR/PredIteratorCache.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" @@ -286,7 +287,7 @@ namespace llvm { /// conflicting tags. AAMDNodes AATags; - NonLocalPointerInfo() : Size(AliasAnalysis::UnknownSize) {} + NonLocalPointerInfo() : Size(MemoryLocation::UnknownSize) {} }; /// CachedNonLocalPointerInfo - This map stores the cached results of doing @@ -325,7 +326,7 @@ namespace llvm { AliasAnalysis *AA; DominatorTree *DT; AssumptionCache *AC; - std::unique_ptr PredCache; + PredIteratorCache PredCache; public: MemoryDependenceAnalysis(); @@ -402,13 +403,12 @@ namespace llvm { /// /// Note that this is an uncached query, and thus may be inefficient. /// - MemDepResult getPointerDependencyFrom(const AliasAnalysis::Location &Loc, + MemDepResult getPointerDependencyFrom(const MemoryLocation &Loc, bool isLoad, BasicBlock::iterator ScanIt, BasicBlock *BB, Instruction *QueryInst = nullptr); - /// getLoadLoadClobberFullWidthSize - This is a little bit of analysis that /// looks at a memory location for a load (specified by MemLocBase, Offs, /// and Size) and compares it against a load. If the specified load could @@ -427,15 +427,14 @@ namespace llvm { BasicBlock *BB); bool getNonLocalPointerDepFromBB(Instruction *QueryInst, const PHITransAddr &Pointer, - const AliasAnalysis::Location &Loc, - bool isLoad, BasicBlock *BB, + const MemoryLocation &Loc, bool isLoad, + BasicBlock *BB, SmallVectorImpl &Result, - DenseMap &Visited, + DenseMap &Visited, bool SkipFirstBlock = false); MemDepResult GetNonLocalInfoForBlock(Instruction *QueryInst, - const AliasAnalysis::Location &Loc, - bool isLoad, BasicBlock *BB, - NonLocalDepInfo *Cache, + const MemoryLocation &Loc, bool isLoad, + BasicBlock *BB, NonLocalDepInfo *Cache, unsigned NumSortedEntries); void RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair P); diff --git a/include/llvm/Analysis/MemoryLocation.h b/include/llvm/Analysis/MemoryLocation.h new file mode 100644 index 00000000000..426b49a3ecd --- /dev/null +++ b/include/llvm/Analysis/MemoryLocation.h @@ -0,0 +1,142 @@ +//===- 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; +class TargetLibraryInfo; + +/// 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(Inst)) + return get(I); + else if (auto *I = dyn_cast(Inst)) + return get(I); + else if (auto *I = dyn_cast(Inst)) + return get(I); + else if (auto *I = dyn_cast(Inst)) + return get(I); + else if (auto *I = dyn_cast(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); + + /// Return a location representing a particular argument of a call. + static MemoryLocation getForArgument(ImmutableCallSite CS, unsigned ArgIdx, + const TargetLibraryInfo &TLI); + + 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 { + static inline MemoryLocation getEmptyKey() { + return MemoryLocation(DenseMapInfo::getEmptyKey(), 0); + } + static inline MemoryLocation getTombstoneKey() { + return MemoryLocation(DenseMapInfo::getTombstoneKey(), 0); + } + static unsigned getHashValue(const MemoryLocation &Val) { + return DenseMapInfo::getHashValue(Val.Ptr) ^ + DenseMapInfo::getHashValue(Val.Size) ^ + DenseMapInfo::getHashValue(Val.AATags); + } + static bool isEqual(const MemoryLocation &LHS, const MemoryLocation &RHS) { + return LHS == RHS; + } +}; +} + +#endif diff --git a/include/llvm/Analysis/NaCl/PNaClABIProps.h b/include/llvm/Analysis/NaCl/PNaClABIProps.h deleted file mode 100644 index dfb3d0d512b..00000000000 --- a/include/llvm/Analysis/NaCl/PNaClABIProps.h +++ /dev/null @@ -1,80 +0,0 @@ -//===- PNaClABIProps.h - Verify PNaCl ABI Properties ----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Verify PNaCl ABI properties. -// -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_NACL_PNACLABIPROPS_H -#define LLVM_ANALYSIS_NACL_PNACLABIPROPS_H - -#include "llvm/ADT/APInt.h" -#include "llvm/IR/CallingConv.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/Type.h" - -namespace llvm { - -class NamedMDNode; -class DataLayout; - -// Checks properties needed to verify IR constructs. Unlike -// PNaClABIVerifyFunctions and PNaClABIVerifyModule, this class is -// pass-free, and checks individual elements within IR. -class PNaClABIProps { - PNaClABIProps(const PNaClABIProps&) = delete; - void operator=(const PNaClABIProps&) = delete; -public: - // Returns true if metadata kind MDKind is allowed. - static bool isWhitelistedMetadata(unsigned MDKind); - // Returns true if metadata is allowed. - static bool isWhitelistedMetadata(const NamedMDNode *MD); - // Returns true if integer constant Idx is in [0..NumElements). - static bool isVectorIndexSafe(const APInt &Idx, - unsigned NumElements) { - return Idx.ult(NumElements); - } - // Returns true if Alignment is allowed for type Ty, assuming DL. - static bool isAllowedAlignment(const DataLayout *DL, uint64_t Alignment, - const Type *Ty); - - // Returns true if alloca type Ty is correct. - static bool isAllocaAllocatedType(const Type *Ty) { - return Ty->isIntegerTy(8); - } - // Returns true if the type associated with the size field in an alloca - // instruction is valid. - static bool isAllocaSizeType(const Type *Ty) { - return Ty->isIntegerTy(32); - } - // Returns string describing expected type for the size field in an - // alloca instruction. - static const char *ExpectedAllocaSizeType() { - return "alloca array size is not i32"; - } - // Returns the name for the given calling convention. - static const char *CallingConvName(CallingConv::ID CallingConv); - // Returns true if CallingConv is valid. - static bool isValidCallingConv(CallingConv::ID CallingConv) { - return CallingConv == CallingConv::C; - } - // Returns the name for linkage type LT. - static const char *LinkageName(GlobalValue::LinkageTypes LT); - // Returns true if Linkage is valid. - static bool isValidGlobalLinkage(GlobalValue::LinkageTypes Linkage); - // Returns kind of global value name, based on IsFunction. - static const char *GVTypeName(bool IsFunction) { - return IsFunction ? "Function" : "Variable"; - } -}; - -} - -#endif // LLVM_ANALYSIS_NACL_PNACLABIPROPS_H diff --git a/include/llvm/Analysis/NaCl/PNaClABITypeChecker.h b/include/llvm/Analysis/NaCl/PNaClABITypeChecker.h deleted file mode 100644 index 7d0a4643127..00000000000 --- a/include/llvm/Analysis/NaCl/PNaClABITypeChecker.h +++ /dev/null @@ -1,80 +0,0 @@ -//===- PNaClABITypeChecker.h - Verify PNaCl ABI rules -----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Common type-checking code for module and function-level passes -// -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_NACL_PNACLABITYPECHECKER_H -#define LLVM_ANALYSIS_NACL_PNACLABITYPECHECKER_H - -#include "llvm/ADT/DenseSet.h" -#include "llvm/IR/Type.h" -#include "llvm/Support/raw_ostream.h" - -namespace llvm { -class FunctionType; - -class PNaClABITypeChecker { - PNaClABITypeChecker(const PNaClABITypeChecker&) = delete; - void operator=(const PNaClABITypeChecker&) = delete; -public: - // Returns true if Ty is a valid argument or return value type for PNaCl. - static bool isValidParamType(const Type *Ty); - - // Returns true if Ty is a valid function type for PNaCl. - static bool isValidFunctionType(const FunctionType *FTy); - - // Returns true if Ty is a valid non-derived type for PNaCl. - static bool isValidScalarType(const Type *Ty); - - // Returns true if Ty is a valid vector type for PNaCl. - static bool isValidVectorType(const Type *Ty); - - // Returns true if type Ty can be used in (integer) arithmetic operations. - static bool isValidIntArithmeticType(const Type *Ty); - - // Returns true if type Ty can be used to define the test condition of - // a switch instruction. - static bool isValidSwitchConditionType(const Type *Ty) { - return PNaClABITypeChecker::isValidIntArithmeticType(Ty); - } - // Returns error message showing what was expected when given the - // switch condition type Ty. Assumes isValidSwitchConditionType(Ty) - // returned false. - static const char *ExpectedSwitchConditionType(const Type *Ty) { - if (!Ty->isIntegerTy()) - return "switch not on integer type"; - if (Ty->isIntegerTy(1)) - return "switch on i1 not allowed"; - return "switch disallowed for integer type"; - } - - // There's no built-in way to get the name of a type, so use a - // string ostream to print it. - static std::string getTypeName(const Type *T) { - std::string TypeName; - raw_string_ostream N(TypeName); - T->print(N); - return N.str(); - } - - // Returns true if T1 is equivalent to T2, converting to i32 if - // a pointer type. - static bool IsPointerEquivType(Type *T1, Type *T2) { - if (T1->isPointerTy()) return T2->isIntegerTy(32); - if (T2->isPointerTy()) return T1->isIntegerTy(32); - return T1 == T2; - } - -}; -} // namespace llvm - -#endif // LLVM_ANALYSIS_NACL_PNACLABITYPECHECKER_H diff --git a/include/llvm/Analysis/NaCl/PNaClABIVerifyFunctions.h b/include/llvm/Analysis/NaCl/PNaClABIVerifyFunctions.h deleted file mode 100644 index f456d2ffd47..00000000000 --- a/include/llvm/Analysis/NaCl/PNaClABIVerifyFunctions.h +++ /dev/null @@ -1,67 +0,0 @@ -//===- PNaClABIVerifyFunctions.h - Verify PNaCl ABI rules -----------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Verify function-level PNaCl ABI requirements. -// -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_NACL_PNACLABIVERIFYFUNCTIONS_H -#define LLVM_ANALYSIS_NACL_PNACLABIVERIFYFUNCTIONS_H - -#include "llvm/Analysis/NaCl/PNaClABIProps.h" - -#include "llvm/Analysis/NaCl.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/NaClAtomicIntrinsics.h" -#include "llvm/Pass.h" - -namespace llvm { - -// Checks that examine anything in the function body should be in -// FunctionPasses to make them streaming-friendly. -class PNaClABIVerifyFunctions : public FunctionPass { - PNaClABIVerifyFunctions(const PNaClABIVerifyFunctions&) = delete; - void operator=(const PNaClABIVerifyFunctions&) = delete; - public: - static char ID; - PNaClABIVerifyFunctions() : - FunctionPass(ID), - Reporter(new PNaClABIErrorReporter), - ReporterIsOwned(true) { - initializePNaClABIVerifyFunctionsPass(*PassRegistry::getPassRegistry()); - } - explicit PNaClABIVerifyFunctions(PNaClABIErrorReporter *Reporter_) : - FunctionPass(ID), - Reporter(Reporter_), - ReporterIsOwned(false) { - initializePNaClABIVerifyFunctionsPass(*PassRegistry::getPassRegistry()); - } - virtual ~PNaClABIVerifyFunctions(); - virtual bool doInitialization(Module &M) { - AtomicIntrinsics.reset(new NaCl::AtomicIntrinsics(M.getContext())); - return false; - } - virtual void getAnalysisUsage(AnalysisUsage &Info) const { - Info.setPreservesAll(); - } - bool runOnFunction(Function &F); - virtual void print(raw_ostream &O, const Module *M) const; - -private: - const char *checkInstruction(const DataLayout *DL, const Instruction *Inst); - PNaClABIErrorReporter *Reporter; - bool ReporterIsOwned; - std::unique_ptr AtomicIntrinsics; -}; - -} - -#endif // LLVM_ANALYSIS_NACL_PNACLABIVERIFYFUNCTIONS_H diff --git a/include/llvm/Analysis/NaCl/PNaClABIVerifyModule.h b/include/llvm/Analysis/NaCl/PNaClABIVerifyModule.h deleted file mode 100644 index e43fccb9dbd..00000000000 --- a/include/llvm/Analysis/NaCl/PNaClABIVerifyModule.h +++ /dev/null @@ -1,76 +0,0 @@ -//===- PNaClABIVerifyModule.h - Verify PNaCl ABI rules ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Verify module-level PNaCl ABI requirements (specifically those that do not -// require looking at the function bodies). -// -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_NACL_PNACLABIVERIFYMODULE_H -#define LLVM_ANALYSIS_NACL_PNACLABIVERIFYMODULE_H - -#include "llvm/ADT/StringMap.h" -#include "llvm/Analysis/NaCl.h" -#include "llvm/IR/Module.h" -#include "llvm/Pass.h" - -namespace llvm { - -class PNaClAllowedIntrinsics; - -// This pass should not touch function bodies, to stay streaming-friendly -class PNaClABIVerifyModule : public ModulePass { - PNaClABIVerifyModule(const PNaClABIVerifyModule&) = delete; - void operator=(const PNaClABIVerifyModule&) = delete; - public: - static char ID; - PNaClABIVerifyModule() : - ModulePass(ID), - Reporter(new PNaClABIErrorReporter), - ReporterIsOwned(true), - StreamingMode(false), - SeenEntryPoint(false) { - initializePNaClABIVerifyModulePass(*PassRegistry::getPassRegistry()); - } - PNaClABIVerifyModule(PNaClABIErrorReporter *Reporter_, - bool StreamingMode) : - ModulePass(ID), - Reporter(Reporter_), - ReporterIsOwned(false), - StreamingMode(StreamingMode), - SeenEntryPoint(false) { - initializePNaClABIVerifyModulePass(*PassRegistry::getPassRegistry()); - } - virtual ~PNaClABIVerifyModule(); - bool runOnModule(Module &M); - virtual void print(raw_ostream &O, const Module *M) const; - - // Checks validity of function declaration F with given name Name. - // (see PNaClABIVerifyFunctions.h for handling function bodies). - void checkFunction(const Function *F, const StringRef &Name, - PNaClAllowedIntrinsics &Intrinsics); - // Checks validity of global variable declaration GV. - void checkGlobalVariable(const GlobalVariable *GV) { - return checkGlobalValue(GV); - } - private: - void checkGlobalValue(const GlobalValue *GV); - /// Checks whether \p GV is an allowed external symbol in stable bitcode. - void checkExternalSymbol(const GlobalValue *GV); - - void checkGlobalIsFlattened(const GlobalVariable *GV); - PNaClABIErrorReporter *Reporter; - bool ReporterIsOwned; - bool StreamingMode; - bool SeenEntryPoint; -}; - -} -#endif // LLVM_ANALYSIS_NACL_PNACLABIVERIFYMODULE_H diff --git a/include/llvm/Analysis/NaCl/PNaClAllowedIntrinsics.h b/include/llvm/Analysis/NaCl/PNaClAllowedIntrinsics.h deleted file mode 100644 index f9b7e669b5f..00000000000 --- a/include/llvm/Analysis/NaCl/PNaClAllowedIntrinsics.h +++ /dev/null @@ -1,73 +0,0 @@ -//===- PNaClAllowedIntrinsics.h - Set of allowed intrinsics -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Declares class that holds set of allowed PNaCl intrinsics. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_NACL_PNACLALLOWEDINTRINSICS_H -#define LLVM_ANALYSIS_NACL_PNACLALLOWEDINTRINSICS_H - -#include "llvm/ADT/StringMap.h" -#include "llvm/IR/Intrinsics.h" - -namespace llvm { - -class LLVMContext; -class Function; -class FunctionType; - -// Holds the set of allowed instrinsics. -class PNaClAllowedIntrinsics { - PNaClAllowedIntrinsics(const PNaClAllowedIntrinsics&) = delete; - void operator=(const PNaClAllowedIntrinsics&) = delete; -public: - PNaClAllowedIntrinsics(LLVMContext *Context); - - // Checks if there is an allowable PNaCl intrinsic function with the - // given name and type signature. - bool isAllowed(const std::string &FcnName, const FunctionType *FcnType) { - return isIntrinsicName(FcnName) && FcnType == getIntrinsicType(FcnName); - } - // Checks if Func is an allowed PNaCl intrinsic function. Note: - // This function also allows debugging intrinsics if - // PNaClABIAllowDebugMetadata is true. - bool isAllowed(const Function *Func); - - // Returns the type signature for the Name'd intrinsic, if entered - // via a call to AddIntrinsic. Returns 0 otherwise (implying we - // don't know the expected type signature). - FunctionType *getIntrinsicType(const std::string &Name) { - return isIntrinsicName(Name) ? TypeMap[Name] : 0; - } - - static bool isAllowedDebugInfoIntrinsic(unsigned IntrinsicID); - -private: - LLVMContext *Context; - // Maps from an allowed intrinsic's name to its type. - StringMap TypeMap; - - // Tys is an array of type parameters for the intrinsic. This - // defaults to an empty array. - void addIntrinsic(Intrinsic::ID ID, - ArrayRef Tys = ArrayRef()); - - // Returns true if a valid PNaCl intrinsic name. - bool isIntrinsicName(const std::string &Name) { - return TypeMap.count(Name) == 1; - } - - // Returns true if intrinsic ID is allowed as a PNaCl intrinsic. - bool isAllowedIntrinsicID(unsigned ID); -}; - -} - -#endif // LLVM_ANALYSIS_NACL_PNACLALLOWEDINTRINSICS_H diff --git a/include/llvm/Analysis/OrderedBasicBlock.h b/include/llvm/Analysis/OrderedBasicBlock.h new file mode 100644 index 00000000000..5aa813eb483 --- /dev/null +++ b/include/llvm/Analysis/OrderedBasicBlock.h @@ -0,0 +1,66 @@ +//===- llvm/Analysis/OrderedBasicBlock.h --------------------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the OrderedBasicBlock class. OrderedBasicBlock maintains +// an interface where clients can query if one instruction comes before another +// in a BasicBlock. Since BasicBlock currently lacks a reliable way to query +// relative position between instructions one can use OrderedBasicBlock to do +// such queries. OrderedBasicBlock is lazily built on a source BasicBlock and +// maintains an internal Instruction -> Position map. A OrderedBasicBlock +// instance should be discarded whenever the source BasicBlock changes. +// +// It's currently used by the CaptureTracker in order to find relative +// positions of a pair of instructions inside a BasicBlock. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_ORDEREDBASICBLOCK_H +#define LLVM_ANALYSIS_ORDEREDBASICBLOCK_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/IR/BasicBlock.h" + +namespace llvm { + +class Instruction; +class BasicBlock; + +class OrderedBasicBlock { +private: + /// \brief Map a instruction to its position in a BasicBlock. + SmallDenseMap NumberedInsts; + + /// \brief Keep track of last instruction inserted into \p NumberedInsts. + /// It speeds up queries for uncached instructions by providing a start point + /// for new queries in OrderedBasicBlock::comesBefore. + BasicBlock::const_iterator LastInstFound; + + /// \brief The position/number to tag the next instruction to be found. + unsigned NextInstPos; + + /// \brief The source BasicBlock to map. + const BasicBlock *BB; + + /// \brief Given no cached results, find if \p A comes before \p B in \p BB. + /// Cache and number out instruction while walking \p BB. + bool comesBefore(const Instruction *A, const Instruction *B); + +public: + OrderedBasicBlock(const BasicBlock *BasicB); + + /// \brief Find out whether \p A dominates \p B, meaning whether \p A + /// comes before \p B in \p BB. This is a simplification that considers + /// cached instruction positions and ignores other basic blocks, being + /// only relevant to compare relative instructions positions inside \p BB. + bool dominates(const Instruction *A, const Instruction *B); +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/PHITransAddr.h b/include/llvm/Analysis/PHITransAddr.h index 84bb9d8008b..cbdbb88f740 100644 --- a/include/llvm/Analysis/PHITransAddr.h +++ b/include/llvm/Analysis/PHITransAddr.h @@ -75,12 +75,12 @@ class PHITransAddr { bool IsPotentiallyPHITranslatable() const; /// PHITranslateValue - PHI translate the current address up the CFG from - /// CurBB to Pred, updating our state to reflect any needed changes. If the - /// dominator tree DT is non-null, the translated value must dominate + /// CurBB to Pred, updating our state to reflect any needed changes. If + /// 'MustDominate' is true, the translated value must dominate /// PredBB. This returns true on failure and sets Addr to null. bool PHITranslateValue(BasicBlock *CurBB, BasicBlock *PredBB, - const DominatorTree *DT); - + const DominatorTree *DT, bool MustDominate); + /// PHITranslateWithInsertion - PHI translate this value into the specified /// predecessor block, inserting a computation of the value if it is /// unavailable. diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h index 7ceb086ee0a..8560f1f6716 100644 --- a/include/llvm/Analysis/RegionInfo.h +++ b/include/llvm/Analysis/RegionInfo.h @@ -902,9 +902,9 @@ inline raw_ostream &operator<<(raw_ostream &OS, return OS << Node.template getNodeAs()->getName(); } -EXTERN_TEMPLATE_INSTANTIATION(class RegionBase>); -EXTERN_TEMPLATE_INSTANTIATION(class RegionNodeBase>); -EXTERN_TEMPLATE_INSTANTIATION(class RegionInfoBase>); +extern template class RegionBase>; +extern template class RegionNodeBase>; +extern template class RegionInfoBase>; } // End llvm namespace #endif diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index 1240b85d176..c45fdb27191 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -48,6 +48,7 @@ namespace llvm { class LoopInfo; class Operator; class SCEVUnknown; + class SCEVAddRecExpr; class SCEV; template<> struct FoldingSetTrait; @@ -565,19 +566,43 @@ namespace llvm { /// forgetMemoizedResults - Drop memoized information computed for S. void forgetMemoizedResults(const SCEV *S); + /// Return an existing SCEV for V if there is one, otherwise return nullptr. + const SCEV *getExistingSCEV(Value *V); + /// Return false iff given SCEV contains a SCEVUnknown with NULL value- /// pointer. bool checkValidity(const SCEV *S) const; - // Return true if `ExtendOpTy`({`Start`,+,`Step`}) can be proved to be equal - // to {`ExtendOpTy`(`Start`),+,`ExtendOpTy`(`Step`)}. This is equivalent to - // proving no signed (resp. unsigned) wrap in {`Start`,+,`Step`} if - // `ExtendOpTy` is `SCEVSignExtendExpr` (resp. `SCEVZeroExtendExpr`). - // + /// Return true if `ExtendOpTy`({`Start`,+,`Step`}) can be proved to be + /// equal to {`ExtendOpTy`(`Start`),+,`ExtendOpTy`(`Step`)}. This is + /// equivalent to proving no signed (resp. unsigned) wrap in + /// {`Start`,+,`Step`} if `ExtendOpTy` is `SCEVSignExtendExpr` + /// (resp. `SCEVZeroExtendExpr`). + /// template bool proveNoWrapByVaryingStart(const SCEV *Start, const SCEV *Step, const Loop *L); + bool isMonotonicPredicateImpl(const SCEVAddRecExpr *LHS, + ICmpInst::Predicate Pred, bool &Increasing); + + /// Return true if, for all loop invariant X, the predicate "LHS `Pred` X" + /// is monotonically increasing or decreasing. In the former case set + /// `Increasing` to true and in the latter case set `Increasing` to false. + /// + /// A predicate is said to be monotonically increasing if may go from being + /// false to being true as the loop iterates, but never the other way + /// around. A predicate is said to be monotonically decreasing if may go + /// from being true to being false as the loop iterates, but never the other + /// way around. + bool isMonotonicPredicate(const SCEVAddRecExpr *LHS, + ICmpInst::Predicate Pred, bool &Increasing); + + // Return SCEV no-wrap flags that can be proven based on reasoning + // about how poison produced from no-wrap flags on this value + // (e.g. a nuw add) would trigger undefined behavior on overflow. + SCEV::NoWrapFlags getNoWrapFlagsFromUB(const Value *V); + public: static char ID; // Pass identification, replacement for typeid ScalarEvolution(); @@ -657,6 +682,15 @@ namespace llvm { SmallVector NewOp(Operands.begin(), Operands.end()); return getAddRecExpr(NewOp, L, Flags); } + /// \brief Returns an expression for a GEP + /// + /// \p PointeeType The type used as the basis for the pointer arithmetics + /// \p BaseExpr The expression for the pointer operand. + /// \p IndexExprs The expressions for the indices. + /// \p InBounds Whether the GEP is in bounds. + const SCEV *getGEPExpr(Type *PointeeType, const SCEV *BaseExpr, + const SmallVectorImpl &IndexExprs, + bool InBounds = false); const SCEV *getSMaxExpr(const SCEV *LHS, const SCEV *RHS); const SCEV *getSMaxExpr(SmallVectorImpl &Operands); const SCEV *getUMaxExpr(const SCEV *LHS, const SCEV *RHS); @@ -890,6 +924,16 @@ namespace llvm { bool isKnownPredicate(ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS); + /// Return true if the result of the predicate LHS `Pred` RHS is loop + /// invariant with respect to L. Set InvariantPred, InvariantLHS and + /// InvariantLHS so that InvariantLHS `InvariantPred` InvariantRHS is the + /// loop invariant form of LHS `Pred` RHS. + bool isLoopInvariantPredicate(ICmpInst::Predicate Pred, const SCEV *LHS, + const SCEV *RHS, const Loop *L, + ICmpInst::Predicate &InvariantPred, + const SCEV *&InvariantLHS, + const SCEV *&InvariantRHS); + /// SimplifyICmpOperands - Simplify LHS and RHS in a comparison with /// predicate Pred. Return true iff any changes were made. If the /// operands are provably equal or unequal, LHS and RHS are set to @@ -945,6 +989,86 @@ namespace llvm { void print(raw_ostream &OS, const Module* = nullptr) const override; void verifyAnalysis() const override; + /// Collect parametric terms occurring in step expressions. + void collectParametricTerms(const SCEV *Expr, + SmallVectorImpl &Terms); + + + + /// Return in Subscripts the access functions for each dimension in Sizes. + void computeAccessFunctions(const SCEV *Expr, + SmallVectorImpl &Subscripts, + SmallVectorImpl &Sizes); + + /// Split this SCEVAddRecExpr into two vectors of SCEVs representing the + /// subscripts and sizes of an array access. + /// + /// The delinearization is a 3 step process: the first two steps compute the + /// sizes of each subscript and the third step computes the access functions + /// for the delinearized array: + /// + /// 1. Find the terms in the step functions + /// 2. Compute the array size + /// 3. Compute the access function: divide the SCEV by the array size + /// starting with the innermost dimensions found in step 2. The Quotient + /// is the SCEV to be divided in the next step of the recursion. The + /// Remainder is the subscript of the innermost dimension. Loop over all + /// array dimensions computed in step 2. + /// + /// To compute a uniform array size for several memory accesses to the same + /// object, one can collect in step 1 all the step terms for all the memory + /// accesses, and compute in step 2 a unique array shape. This guarantees + /// that the array shape will be the same across all memory accesses. + /// + /// FIXME: We could derive the result of steps 1 and 2 from a description of + /// the array shape given in metadata. + /// + /// Example: + /// + /// A[][n][m] + /// + /// for i + /// for j + /// for k + /// A[j+k][2i][5i] = + /// + /// The initial SCEV: + /// + /// A[{{{0,+,2*m+5}_i, +, n*m}_j, +, n*m}_k] + /// + /// 1. Find the different terms in the step functions: + /// -> [2*m, 5, n*m, n*m] + /// + /// 2. Compute the array size: sort and unique them + /// -> [n*m, 2*m, 5] + /// find the GCD of all the terms = 1 + /// divide by the GCD and erase constant terms + /// -> [n*m, 2*m] + /// GCD = m + /// divide by GCD -> [n, 2] + /// remove constant terms + /// -> [n] + /// size of the array is A[unknown][n][m] + /// + /// 3. Compute the access function + /// a. Divide {{{0,+,2*m+5}_i, +, n*m}_j, +, n*m}_k by the innermost size m + /// Quotient: {{{0,+,2}_i, +, n}_j, +, n}_k + /// Remainder: {{{0,+,5}_i, +, 0}_j, +, 0}_k + /// The remainder is the subscript of the innermost array dimension: [5i]. + /// + /// b. Divide Quotient: {{{0,+,2}_i, +, n}_j, +, n}_k by next outer size n + /// Quotient: {{{0,+,0}_i, +, 1}_j, +, 1}_k + /// Remainder: {{{0,+,2}_i, +, 0}_j, +, 0}_k + /// The Remainder is the subscript of the next array dimension: [2i]. + /// + /// The subscript of the outermost dimension is the Quotient: [j+k]. + /// + /// Overall, we have: A[][n][m], and the access function: A[j+k][2i][5i]. + void delinearize(const SCEV *Expr, + SmallVectorImpl &Subscripts, + SmallVectorImpl &Sizes, + const SCEV *ElementSize); + private: /// Compute the backedge taken count knowing the interval difference, the /// stride and presence of the equality in the comparison. diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h index ff82db19b9e..da24de281d4 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -356,84 +356,6 @@ namespace llvm { static inline bool classof(const SCEV *S) { return S->getSCEVType() == scAddRecExpr; } - - /// Collect parametric terms occurring in step expressions. - void collectParametricTerms(ScalarEvolution &SE, - SmallVectorImpl &Terms) const; - - /// Return in Subscripts the access functions for each dimension in Sizes. - void computeAccessFunctions(ScalarEvolution &SE, - SmallVectorImpl &Subscripts, - SmallVectorImpl &Sizes) const; - - /// Split this SCEVAddRecExpr into two vectors of SCEVs representing the - /// subscripts and sizes of an array access. - /// - /// The delinearization is a 3 step process: the first two steps compute the - /// sizes of each subscript and the third step computes the access functions - /// for the delinearized array: - /// - /// 1. Find the terms in the step functions - /// 2. Compute the array size - /// 3. Compute the access function: divide the SCEV by the array size - /// starting with the innermost dimensions found in step 2. The Quotient - /// is the SCEV to be divided in the next step of the recursion. The - /// Remainder is the subscript of the innermost dimension. Loop over all - /// array dimensions computed in step 2. - /// - /// To compute a uniform array size for several memory accesses to the same - /// object, one can collect in step 1 all the step terms for all the memory - /// accesses, and compute in step 2 a unique array shape. This guarantees - /// that the array shape will be the same across all memory accesses. - /// - /// FIXME: We could derive the result of steps 1 and 2 from a description of - /// the array shape given in metadata. - /// - /// Example: - /// - /// A[][n][m] - /// - /// for i - /// for j - /// for k - /// A[j+k][2i][5i] = - /// - /// The initial SCEV: - /// - /// A[{{{0,+,2*m+5}_i, +, n*m}_j, +, n*m}_k] - /// - /// 1. Find the different terms in the step functions: - /// -> [2*m, 5, n*m, n*m] - /// - /// 2. Compute the array size: sort and unique them - /// -> [n*m, 2*m, 5] - /// find the GCD of all the terms = 1 - /// divide by the GCD and erase constant terms - /// -> [n*m, 2*m] - /// GCD = m - /// divide by GCD -> [n, 2] - /// remove constant terms - /// -> [n] - /// size of the array is A[unknown][n][m] - /// - /// 3. Compute the access function - /// a. Divide {{{0,+,2*m+5}_i, +, n*m}_j, +, n*m}_k by the innermost size m - /// Quotient: {{{0,+,2}_i, +, n}_j, +, n}_k - /// Remainder: {{{0,+,5}_i, +, 0}_j, +, 0}_k - /// The remainder is the subscript of the innermost array dimension: [5i]. - /// - /// b. Divide Quotient: {{{0,+,2}_i, +, n}_j, +, n}_k by next outer size n - /// Quotient: {{{0,+,0}_i, +, 1}_j, +, 1}_k - /// Remainder: {{{0,+,2}_i, +, 0}_j, +, 0}_k - /// The Remainder is the subscript of the next array dimension: [2i]. - /// - /// The subscript of the outermost dimension is the Quotient: [j+k]. - /// - /// Overall, we have: A[][n][m], and the access function: A[j+k][2i][5i]. - void delinearize(ScalarEvolution &SE, - SmallVectorImpl &Subscripts, - SmallVectorImpl &Sizes, - const SCEV *ElementSize) const; }; //===--------------------------------------------------------------------===// diff --git a/include/llvm/Analysis/TargetLibraryInfo.def b/include/llvm/Analysis/TargetLibraryInfo.def index 0837fbba6a2..1c1fdfef980 100644 --- a/include/llvm/Analysis/TargetLibraryInfo.def +++ b/include/llvm/Analysis/TargetLibraryInfo.def @@ -470,8 +470,7 @@ TLI_DEFINE_STRING_INTERNAL("fscanf") TLI_DEFINE_ENUM_INTERNAL(fseek) TLI_DEFINE_STRING_INTERNAL("fseek") /// int fseeko(FILE *stream, off_t offset, int whence); -// LOCALMOD ftello->Ftello -TLI_DEFINE_ENUM_INTERNAL(Fseeko) +TLI_DEFINE_ENUM_INTERNAL(fseeko) TLI_DEFINE_STRING_INTERNAL("fseeko") /// int fseeko64(FILE *stream, off64_t offset, int whence) TLI_DEFINE_ENUM_INTERNAL(fseeko64) @@ -495,8 +494,7 @@ TLI_DEFINE_STRING_INTERNAL("fstatvfs64") TLI_DEFINE_ENUM_INTERNAL(ftell) TLI_DEFINE_STRING_INTERNAL("ftell") /// off_t ftello(FILE *stream); -// LOCALMOD ftello->Ftello -TLI_DEFINE_ENUM_INTERNAL(Ftello) +TLI_DEFINE_ENUM_INTERNAL(ftello) TLI_DEFINE_STRING_INTERNAL("ftello") /// off64_t ftello64(FILE *stream) TLI_DEFINE_ENUM_INTERNAL(ftello64) diff --git a/include/llvm/Analysis/TargetLibraryInfo.h b/include/llvm/Analysis/TargetLibraryInfo.h index e0a1ee37827..98e450c867d 100644 --- a/include/llvm/Analysis/TargetLibraryInfo.h +++ b/include/llvm/Analysis/TargetLibraryInfo.h @@ -201,13 +201,13 @@ class TargetLibraryInfo { } bool isFunctionVectorizable(StringRef F, unsigned VF) const { return Impl->isFunctionVectorizable(F, VF); - }; + } bool isFunctionVectorizable(StringRef F) const { return Impl->isFunctionVectorizable(F); - }; + } StringRef getVectorizedFunction(StringRef F, unsigned VF) const { return Impl->getVectorizedFunction(F, VF); - }; + } /// \brief Tests if the function is both available and a candidate for /// optimized code generation. diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index f4195fbb072..fd3cfe72921 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -69,7 +69,7 @@ class TargetTransformInfo { /// /// The TTI implementation will reflect the information in the DataLayout /// provided if non-null. - explicit TargetTransformInfo(const DataLayout *DL); + explicit TargetTransformInfo(const DataLayout &DL); // Provide move semantics. TargetTransformInfo(TargetTransformInfo &&Arg); @@ -136,7 +136,8 @@ class TargetTransformInfo { /// The contract for this function is the same as \c getOperationCost except /// that it supports an interface that provides extra information specific to /// the GEP operation. - unsigned getGEPCost(const Value *Ptr, ArrayRef Operands) const; + unsigned getGEPCost(Type *PointeeType, const Value *Ptr, + ArrayRef Operands) const; /// \brief Estimate the cost of a function call when lowered. /// @@ -221,19 +222,21 @@ class TargetTransformInfo { /// 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 +306,8 @@ class TargetTransformInfo { /// 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,13 +323,19 @@ class TargetTransformInfo { /// 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 /// by referencing its sub-register AX. bool isTruncateFree(Type *Ty1, Type *Ty2) const; + /// \brief Return true if it's free to zero extend a value of type Ty1 to type + /// Ty2. e.g. on x86-64, all instructions that define 32-bit values implicit + /// zero-extend the result out to 64 bits. + bool isZExtFree(Type *Ty1, Type *Ty2) const; + /// \brief Return true if it is profitable to hoist instruction in the /// then/else to before if. bool isProfitableToHoist(Instruction *I) const; @@ -403,7 +413,7 @@ class TargetTransformInfo { /// \return The maximum interleave factor that any transform should try to /// perform for this target. This number depends on the level of parallelism /// and the number of execution units in the CPU. - unsigned getMaxInterleaveFactor() const; + unsigned getMaxInterleaveFactor(unsigned VF) const; /// \return The expected cost of arithmetic ops, such as mul, xor, fsub, etc. unsigned @@ -444,6 +454,20 @@ class TargetTransformInfo { 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 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 @@ -501,6 +525,11 @@ class TargetTransformInfo { Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, Type *ExpectedType) const; + /// \returns True if the two functions have compatible attributes for inlining + /// purposes. + bool areInlineCompatible(const Function *Caller, + const Function *Callee) const; + /// @} private: @@ -518,9 +547,9 @@ class TargetTransformInfo { class TargetTransformInfo::Concept { public: virtual ~Concept() = 0; - + virtual const DataLayout &getDataLayout() const = 0; virtual unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) = 0; - virtual unsigned getGEPCost(const Value *Ptr, + virtual unsigned getGEPCost(Type *PointeeType, const Value *Ptr, ArrayRef Operands) = 0; virtual unsigned getCallCost(FunctionType *FTy, int NumArgs) = 0; virtual unsigned getCallCost(const Function *F, int NumArgs) = 0; @@ -539,13 +568,15 @@ class TargetTransformInfo::Concept { 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 isZExtFree(Type *Ty1, Type *Ty2) = 0; virtual bool isProfitableToHoist(Instruction *I) = 0; virtual bool isTypeLegal(Type *Ty) = 0; virtual unsigned getJumpBufAlignment() = 0; @@ -562,7 +593,7 @@ class TargetTransformInfo::Concept { const APInt &Imm, Type *Ty) = 0; virtual unsigned getNumberOfRegisters(bool Vector) = 0; virtual unsigned getRegisterBitWidth(bool Vector) = 0; - virtual unsigned getMaxInterleaveFactor() = 0; + virtual unsigned getMaxInterleaveFactor(unsigned VF) = 0; virtual unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info, OperandValueKind Opd2Info, @@ -582,6 +613,11 @@ class TargetTransformInfo::Concept { virtual unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, unsigned AddressSpace) = 0; + virtual unsigned getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, + unsigned Factor, + ArrayRef Indices, + unsigned Alignment, + unsigned AddressSpace) = 0; virtual unsigned getReductionCost(unsigned Opcode, Type *Ty, bool IsPairwiseForm) = 0; virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, @@ -595,6 +631,8 @@ class TargetTransformInfo::Concept { MemIntrinsicInfo &Info) = 0; virtual Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, Type *ExpectedType) = 0; + virtual bool areInlineCompatible(const Function *Caller, + const Function *Callee) const = 0; }; template @@ -605,12 +643,16 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept { Model(T Impl) : Impl(std::move(Impl)) {} ~Model() override {} + const DataLayout &getDataLayout() const override { + return Impl.getDataLayout(); + } + unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) override { return Impl.getOperationCost(Opcode, Ty, OpTy); } - unsigned getGEPCost(const Value *Ptr, + unsigned getGEPCost(Type *PointeeType, const Value *Ptr, ArrayRef Operands) override { - return Impl.getGEPCost(Ptr, Operands); + return Impl.getGEPCost(PointeeType, Ptr, Operands); } unsigned getCallCost(FunctionType *FTy, int NumArgs) override { return Impl.getCallCost(FTy, NumArgs); @@ -648,9 +690,10 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept { 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,12 +702,17 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept { 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); } + bool isZExtFree(Type *Ty1, Type *Ty2) override { + return Impl.isZExtFree(Ty1, Ty2); + } bool isProfitableToHoist(Instruction *I) override { return Impl.isProfitableToHoist(I); } @@ -703,8 +751,8 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept { unsigned getRegisterBitWidth(bool Vector) override { return Impl.getRegisterBitWidth(Vector); } - unsigned getMaxInterleaveFactor() override { - return Impl.getMaxInterleaveFactor(); + unsigned getMaxInterleaveFactor(unsigned VF) override { + return Impl.getMaxInterleaveFactor(VF); } unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info, @@ -740,6 +788,14 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept { unsigned AddressSpace) override { return Impl.getMaskedMemoryOpCost(Opcode, Src, Alignment, AddressSpace); } + unsigned getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, + unsigned Factor, + ArrayRef 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); @@ -769,6 +825,10 @@ class TargetTransformInfo::Model final : public TargetTransformInfo::Concept { Type *ExpectedType) override { return Impl.getOrCreateResultFromMemIntrinsic(Inst, ExpectedType); } + bool areInlineCompatible(const Function *Caller, + const Function *Callee) const override { + return Impl.areInlineCompatible(Caller, Callee); + } }; template diff --git a/include/llvm/Analysis/TargetTransformInfoImpl.h b/include/llvm/Analysis/TargetTransformInfoImpl.h index b00de7723ef..9805f6bc663 100644 --- a/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -19,6 +19,7 @@ #include "llvm/IR/CallSite.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/Operator.h" #include "llvm/IR/Type.h" @@ -30,26 +31,17 @@ class TargetTransformInfoImplBase { protected: typedef TargetTransformInfo TTI; - const DataLayout *DL; + const DataLayout &DL; - explicit TargetTransformInfoImplBase(const DataLayout *DL) - : DL(DL) {} + explicit TargetTransformInfoImplBase(const DataLayout &DL) : DL(DL) {} public: // Provide value semantics. MSVC requires that we spell all of these out. TargetTransformInfoImplBase(const TargetTransformInfoImplBase &Arg) : DL(Arg.DL) {} - TargetTransformInfoImplBase(TargetTransformInfoImplBase &&Arg) - : DL(std::move(Arg.DL)) {} - TargetTransformInfoImplBase & - operator=(const TargetTransformInfoImplBase &RHS) { - DL = RHS.DL; - return *this; - } - TargetTransformInfoImplBase &operator=(TargetTransformInfoImplBase &&RHS) { - DL = std::move(RHS.DL); - return *this; - } + TargetTransformInfoImplBase(TargetTransformInfoImplBase &&Arg) : DL(Arg.DL) {} + + const DataLayout &getDataLayout() const { return DL; } unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) { switch (Opcode) { @@ -70,28 +62,22 @@ class TargetTransformInfoImplBase { return TTI::TCC_Basic; case Instruction::IntToPtr: { - if (!DL) - return TTI::TCC_Basic; - // An inttoptr cast is free so long as the input is a legal integer type // which doesn't contain values outside the range of a pointer. unsigned OpSize = OpTy->getScalarSizeInBits(); - if (DL->isLegalInteger(OpSize) && - OpSize <= DL->getPointerTypeSizeInBits(Ty)) + if (DL.isLegalInteger(OpSize) && + OpSize <= DL.getPointerTypeSizeInBits(Ty)) return TTI::TCC_Free; // Otherwise it's not a no-op. return TTI::TCC_Basic; } case Instruction::PtrToInt: { - if (!DL) - return TTI::TCC_Basic; - // A ptrtoint cast is free so long as the result is large enough to store // the pointer, and a legal integer type. unsigned DestSize = Ty->getScalarSizeInBits(); - if (DL->isLegalInteger(DestSize) && - DestSize >= DL->getPointerTypeSizeInBits(OpTy)) + if (DL.isLegalInteger(DestSize) && + DestSize >= DL.getPointerTypeSizeInBits(OpTy)) return TTI::TCC_Free; // Otherwise it's not a no-op. @@ -100,14 +86,15 @@ class TargetTransformInfoImplBase { case Instruction::Trunc: // trunc to a native type is free (assuming the target has compare and // shift-right of the same width). - if (DL && DL->isLegalInteger(DL->getTypeSizeInBits(Ty))) + if (DL.isLegalInteger(DL.getTypeSizeInBits(Ty))) return TTI::TCC_Free; return TTI::TCC_Basic; } } - unsigned getGEPCost(const Value *Ptr, ArrayRef Operands) { + unsigned getGEPCost(Type *PointeeType, const Value *Ptr, + ArrayRef Operands) { // In the basic model, we just assume that all-constant GEPs will be folded // into their uses via addressing modes. for (unsigned Idx = 0, Size = Operands.size(); Idx != Size; ++Idx) @@ -207,10 +194,11 @@ class TargetTransformInfoImplBase { bool isLegalICmpImmediate(int64_t Imm) { return false; } bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, - bool HasBaseReg, int64_t Scale) { - // Guess that reg+reg addressing is allowed. This heuristic is taken from - // the implementation of LSR. - return !BaseGV && BaseOffset == 0 && Scale <= 1; + 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); } bool isLegalMaskedStore(Type *DataType, int Consecutive) { return false; } @@ -218,15 +206,18 @@ class TargetTransformInfoImplBase { 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; } bool isTruncateFree(Type *Ty1, Type *Ty2) { return false; } + bool isZExtFree(Type *Ty1, Type *Ty2) { return false; } + bool isProfitableToHoist(Instruction *I) { return true; } bool isTypeLegal(Type *Ty) { return false; } @@ -263,7 +254,7 @@ class TargetTransformInfoImplBase { unsigned getRegisterBitWidth(bool Vector) { return 32; } - unsigned getMaxInterleaveFactor() { return 1; } + unsigned getMaxInterleaveFactor(unsigned VF) { return 1; } unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty, TTI::OperandValueKind Opd1Info, @@ -300,6 +291,14 @@ class TargetTransformInfoImplBase { return 1; } + unsigned getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, + unsigned Factor, + ArrayRef Indices, + unsigned Alignment, + unsigned AddressSpace) { + return 1; + } + unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, ArrayRef Tys) { return 1; @@ -325,6 +324,14 @@ class TargetTransformInfoImplBase { Type *ExpectedType) { return nullptr; } + + bool areInlineCompatible(const Function *Caller, + const Function *Callee) const { + return (Caller->getFnAttribute("target-cpu") == + Callee->getFnAttribute("target-cpu")) && + (Caller->getFnAttribute("target-features") == + Callee->getFnAttribute("target-features")); + } }; /// \brief CRTP base class for use as a mix-in that aids implementing @@ -335,8 +342,7 @@ class TargetTransformInfoImplCRTPBase : public TargetTransformInfoImplBase { typedef TargetTransformInfoImplBase BaseT; protected: - explicit TargetTransformInfoImplCRTPBase(const DataLayout *DL) - : BaseT(DL) {} + explicit TargetTransformInfoImplCRTPBase(const DataLayout &DL) : BaseT(DL) {} public: // Provide value semantics. MSVC requires that we spell all of these out. @@ -344,16 +350,6 @@ class TargetTransformInfoImplCRTPBase : public TargetTransformInfoImplBase { : BaseT(static_cast(Arg)) {} TargetTransformInfoImplCRTPBase(TargetTransformInfoImplCRTPBase &&Arg) : BaseT(std::move(static_cast(Arg))) {} - TargetTransformInfoImplCRTPBase & - operator=(const TargetTransformInfoImplCRTPBase &RHS) { - BaseT::operator=(static_cast(RHS)); - return *this; - } - TargetTransformInfoImplCRTPBase & - operator=(TargetTransformInfoImplCRTPBase &&RHS) { - BaseT::operator=(std::move(static_cast(RHS))); - return *this; - } using BaseT::getCallCost; @@ -365,7 +361,7 @@ class TargetTransformInfoImplCRTPBase : public TargetTransformInfoImplBase { // function. NumArgs = F->arg_size(); - if (Intrinsic::ID IID = (Intrinsic::ID)F->getIntrinsicID()) { + if (Intrinsic::ID IID = F->getIntrinsicID()) { FunctionType *FTy = F->getFunctionType(); SmallVector ParamTys(FTy->param_begin(), FTy->param_end()); return static_cast(this) @@ -386,6 +382,54 @@ class TargetTransformInfoImplCRTPBase : public TargetTransformInfoImplBase { return static_cast(this)->getCallCost(F, Arguments.size()); } + using BaseT::getGEPCost; + + unsigned getGEPCost(Type *PointeeType, const Value *Ptr, + ArrayRef Operands) { + const GlobalValue *BaseGV = nullptr; + if (Ptr != nullptr) { + // TODO: will remove this when pointers have an opaque type. + assert(Ptr->getType()->getScalarType()->getPointerElementType() == + PointeeType && + "explicit pointee type doesn't match operand's pointee type"); + BaseGV = dyn_cast(Ptr->stripPointerCasts()); + } + bool HasBaseReg = (BaseGV == nullptr); + int64_t BaseOffset = 0; + int64_t Scale = 0; + + // Assumes the address space is 0 when Ptr is nullptr. + unsigned AS = + (Ptr == nullptr ? 0 : Ptr->getType()->getPointerAddressSpace()); + auto GTI = gep_type_begin(PointerType::get(PointeeType, AS), Operands); + for (auto I = Operands.begin(); I != Operands.end(); ++I, ++GTI) { + if (isa(*GTI)) { + int64_t ElementSize = DL.getTypeAllocSize(GTI.getIndexedType()); + if (const ConstantInt *ConstIdx = dyn_cast(*I)) { + BaseOffset += ConstIdx->getSExtValue() * ElementSize; + } else { + // Needs scale register. + if (Scale != 0) { + // No addressing mode takes two scale registers. + return TTI::TCC_Basic; + } + Scale = ElementSize; + } + } else { + StructType *STy = cast(*GTI); + uint64_t Field = cast(*I)->getZExtValue(); + BaseOffset += DL.getStructLayout(STy)->getElementOffset(Field); + } + } + + if (static_cast(this)->isLegalAddressingMode( + PointerType::get(*GTI, AS), const_cast(BaseGV), + BaseOffset, HasBaseReg, Scale, AS)) { + return TTI::TCC_Free; + } + return TTI::TCC_Basic; + } + using BaseT::getIntrinsicCost; unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, @@ -405,9 +449,9 @@ class TargetTransformInfoImplCRTPBase : public TargetTransformInfoImplBase { return TTI::TCC_Free; // Model all PHI nodes as free. if (const GEPOperator *GEP = dyn_cast(U)) { - SmallVector Indices(GEP->idx_begin(), GEP->idx_end()); - return static_cast(this) - ->getGEPCost(GEP->getPointerOperand(), Indices); + SmallVector Indices(GEP->idx_begin(), GEP->idx_end()); + return static_cast(this)->getGEPCost( + GEP->getSourceElementType(), GEP->getPointerOperand(), Indices); } if (auto CS = ImmutableCallSite(U)) { diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index 8955b7c7bd7..258723dc4db 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -16,6 +16,7 @@ #define LLVM_ANALYSIS_VALUETRACKING_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/IR/Instruction.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -28,6 +29,8 @@ namespace llvm { class AssumptionCache; class DominatorTree; class TargetLibraryInfo; + class LoopInfo; + class Loop; /// Determine which bits of V are known to be either zero or one and return /// them in the KnownZero/KnownOne bit sets. @@ -46,6 +49,11 @@ namespace llvm { /// \p KnownZero the set of bits that are known to be zero void computeKnownBitsFromRangeMetadata(const MDNode &Ranges, APInt &KnownZero); + /// Return true if LHS and RHS have no common bits set. + bool haveNoCommonBitsSet(Value *LHS, Value *RHS, const DataLayout &DL, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr); /// ComputeSignBit - Determine whether the sign bit is known to be zero or /// one. Convenience wrapper around computeKnownBits. @@ -59,7 +67,7 @@ namespace llvm { /// exactly one bit set when defined. For vectors return true if every /// element is known to be a power of two when defined. Supports values with /// integer or pointer type and vectors of integers. If 'OrZero' is set then - /// returns true if the given value is either a power of two or zero. + /// return true if the given value is either a power of two or zero. bool isKnownToBeAPowerOfTwo(Value *V, const DataLayout &DL, bool OrZero = false, unsigned Depth = 0, AssumptionCache *AC = nullptr, @@ -176,16 +184,51 @@ namespace llvm { return GetUnderlyingObject(const_cast(V), DL, MaxLookup); } - /// GetUnderlyingObjects - This method is similar to GetUnderlyingObject - /// except that it can look through phi and select instructions and return - /// multiple objects. + /// \brief This method is similar to GetUnderlyingObject except that it can + /// look through phi and select instructions and return multiple objects. + /// + /// If LoopInfo is passed, loop phis are further analyzed. If a pointer + /// accesses different objects in each iteration, we don't look through the + /// phi node. E.g. consider this loop nest: + /// + /// int **A; + /// for (i) + /// for (j) { + /// A[i][j] = A[i-1][j] * B[j] + /// } + /// + /// This is transformed by Load-PRE to stash away A[i] for the next iteration + /// of the outer loop: + /// + /// Curr = A[0]; // Prev_0 + /// for (i: 1..N) { + /// Prev = Curr; // Prev = PHI (Prev_0, Curr) + /// Curr = A[i]; + /// for (j: 0..N) { + /// Curr[j] = Prev[j] * B[j] + /// } + /// } + /// + /// Since A[i] and A[i-1] are independent pointers, getUnderlyingObjects + /// should not assume that Curr and Prev share the same underlying object thus + /// it shouldn't look through the phi above. void GetUnderlyingObjects(Value *V, SmallVectorImpl &Objects, - const DataLayout &DL, unsigned MaxLookup = 6); + const DataLayout &DL, LoopInfo *LI = nullptr, + unsigned MaxLookup = 6); /// onlyUsedByLifetimeMarkers - Return true if the only users of this pointer /// are lifetime markers. bool onlyUsedByLifetimeMarkers(const Value *V); + /// isDereferenceablePointer - Return true if this is always a dereferenceable + /// pointer. If the context instruction is specified perform context-sensitive + /// analysis and return true if the pointer is dereferenceable at the + /// specified instruction. + bool isDereferenceablePointer(const Value *V, const DataLayout &DL, + const Instruction *CtxI = nullptr, + const DominatorTree *DT = nullptr, + const TargetLibraryInfo *TLI = nullptr); + /// isSafeToSpeculativelyExecute - Return true if the instruction does not /// have any effects besides calculating the result and does not have /// undefined behavior. @@ -199,18 +242,36 @@ namespace llvm { /// memory leak. It also returns false for instructions related to control /// flow, specifically terminators and PHI nodes. /// - /// This method only looks at the instruction itself and its operands, so if - /// this method returns true, it is safe to move the instruction as long as - /// the correct dominance relationships for the operands and users hold. - /// However, this method can return true for instructions that read memory; + /// If the CtxI is specified this method performs context-sensitive analysis + /// and returns true if it is safe to execute the instruction immediately + /// before the CtxI. + /// + /// If the CtxI is NOT specified this method only looks at the instruction + /// itself and its operands, so if this method returns true, it is safe to + /// move the instruction as long as the correct dominance relationships for + /// the operands and users hold. + /// + /// This method can return true for instructions that read memory; /// for such instructions, moving them may change the resulting value. - bool isSafeToSpeculativelyExecute(const Value *V); + bool isSafeToSpeculativelyExecute(const Value *V, + const Instruction *CtxI = nullptr, + const DominatorTree *DT = nullptr, + const TargetLibraryInfo *TLI = nullptr); /// isKnownNonNull - Return true if this pointer couldn't possibly be null by /// its definition. This returns true for allocas, non-extern-weak globals /// and byval arguments. bool isKnownNonNull(const Value *V, const TargetLibraryInfo *TLI = nullptr); + /// isKnownNonNullAt - Return true if this pointer couldn't possibly be null. + /// If the context instruction is specified perform context-sensitive analysis + /// and return true if the pointer couldn't possibly be null at the specified + /// instruction. + bool isKnownNonNullAt(const Value *V, + const Instruction *CtxI = nullptr, + const DominatorTree *DT = nullptr, + const TargetLibraryInfo *TLI = nullptr); + /// Return true if it is valid to use the assumptions provided by an /// assume intrinsic, I, at the point in the control-flow identified by the /// context instruction, CxtI. @@ -228,6 +289,81 @@ namespace llvm { AssumptionCache *AC, const Instruction *CxtI, const DominatorTree *DT); + + /// Return true if this function can prove that the instruction I will + /// always transfer execution to one of its successors (including the next + /// instruction that follows within a basic block). E.g. this is not + /// guaranteed for function calls that could loop infinitely. + /// + /// In other words, this function returns false for instructions that may + /// transfer execution or fail to transfer execution in a way that is not + /// captured in the CFG nor in the sequence of instructions within a basic + /// block. + /// + /// Undefined behavior is assumed not to happen, so e.g. division is + /// guaranteed to transfer execution to the following instruction even + /// though division by zero might cause undefined behavior. + bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I); + + /// Return true if this function can prove that the instruction I + /// is executed for every iteration of the loop L. + /// + /// Note that this currently only considers the loop header. + bool isGuaranteedToExecuteForEveryIteration(const Instruction *I, + const Loop *L); + + /// Return true if this function can prove that I is guaranteed to yield + /// full-poison (all bits poison) if at least one of its operands are + /// full-poison (all bits poison). + /// + /// The exact rules for how poison propagates through instructions have + /// not been settled as of 2015-07-10, so this function is conservative + /// and only considers poison to be propagated in uncontroversial + /// cases. There is no attempt to track values that may be only partially + /// poison. + bool propagatesFullPoison(const Instruction *I); + + /// Return either nullptr or an operand of I such that I will trigger + /// undefined behavior if I is executed and that operand has a full-poison + /// value (all bits poison). + const Value *getGuaranteedNonFullPoisonOp(const Instruction *I); + + /// Return true if this function can prove that if PoisonI is executed + /// and yields a full-poison value (all bits poison), then that will + /// trigger undefined behavior. + /// + /// Note that this currently only considers the basic block that is + /// the parent of I. + bool isKnownNotFullPoison(const Instruction *PoisonI); + + /// \brief Specific patterns of select instructions we can match. + enum SelectPatternFlavor { + SPF_UNKNOWN = 0, + SPF_SMIN, // Signed minimum + SPF_UMIN, // Unsigned minimum + SPF_SMAX, // Signed maximum + SPF_UMAX, // Unsigned maximum + SPF_ABS, // Absolute value + SPF_NABS // Negated absolute value + }; + /// Pattern match integer [SU]MIN, [SU]MAX and ABS idioms, returning the kind + /// and providing the out parameter results if we successfully match. + /// + /// If CastOp is not nullptr, also match MIN/MAX idioms where the type does + /// not match that of the original select. If this is the case, the cast + /// operation (one of Trunc,SExt,Zext) that must be done to transform the + /// type of LHS and RHS into the type of V is returned in CastOp. + /// + /// For example: + /// %1 = icmp slt i32 %a, i32 4 + /// %2 = sext i32 %a to i64 + /// %3 = select i1 %1, i64 %2, i64 4 + /// + /// -> LHS = %a, RHS = i32 4, *CastOp = Instruction::SExt + /// + SelectPatternFlavor matchSelectPattern(Value *V, Value *&LHS, Value *&RHS, + Instruction::CastOps *CastOp = nullptr); + } // end namespace llvm #endif diff --git a/include/llvm/Analysis/VectorUtils.h b/include/llvm/Analysis/VectorUtils.h new file mode 100644 index 00000000000..d8e9ca42e62 --- /dev/null +++ b/include/llvm/Analysis/VectorUtils.h @@ -0,0 +1,84 @@ +//===- llvm/Transforms/Utils/VectorUtils.h - Vector utilities -*- C++ -*-=====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines some vectorizer utilities. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_VECTORUTILS_H +#define LLVM_TRANSFORMS_UTILS_VECTORUTILS_H + +#include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Intrinsics.h" + +namespace llvm { + +class GetElementPtrInst; +class Loop; +class ScalarEvolution; +class Type; +class Value; + +/// \brief Identify if the intrinsic is trivially vectorizable. +/// This method returns true if the intrinsic's argument types are all +/// scalars for the scalar form of the intrinsic and all vectors for +/// the vector form of the intrinsic. +bool isTriviallyVectorizable(Intrinsic::ID ID); + +/// \brief Identifies if the intrinsic has a scalar operand. It checks for +/// ctlz,cttz and powi special intrinsics whose argument is scalar. +bool hasVectorInstrinsicScalarOpd(Intrinsic::ID ID, unsigned ScalarOpdIdx); + +/// \brief Identify if call has a unary float signature +/// It returns input intrinsic ID if call has a single argument, +/// argument type and call instruction type should be floating +/// point type and call should only reads memory. +/// else return not_intrinsic. +Intrinsic::ID checkUnaryFloatSignature(const CallInst &I, + Intrinsic::ID ValidIntrinsicID); + +/// \brief Identify if call has a binary float signature +/// It returns input intrinsic ID if call has two arguments, +/// arguments type and call instruction type should be floating +/// point type and call should only reads memory. +/// else return not_intrinsic. +Intrinsic::ID checkBinaryFloatSignature(const CallInst &I, + Intrinsic::ID ValidIntrinsicID); + +/// \brief Returns intrinsic ID for call. +/// For the input call instruction it finds mapping intrinsic and returns +/// its intrinsic ID, in case it does not found it return not_intrinsic. +Intrinsic::ID getIntrinsicIDForCall(CallInst *CI, const TargetLibraryInfo *TLI); + +/// \brief Find the operand of the GEP that should be checked for consecutive +/// stores. This ignores trailing indices that have no effect on the final +/// pointer. +unsigned getGEPInductionOperand(const GetElementPtrInst *Gep); + +/// \brief If the argument is a GEP, then returns the operand identified by +/// getGEPInductionOperand. However, if there is some other non-loop-invariant +/// operand, it returns that instead. +Value *stripGetElementPtr(Value *Ptr, ScalarEvolution *SE, Loop *Lp); + +/// \brief If a value has only one user that is a CastInst, return it. +Value *getUniqueCastUse(Value *Ptr, Loop *Lp, Type *Ty); + +/// \brief Get the stride of a pointer access in a loop. Looks for symbolic +/// strides "a[i*stride]". Returns the symbolic stride, or null otherwise. +Value *getStrideFromPointer(Value *Ptr, ScalarEvolution *SE, Loop *Lp); + +/// \brief Given a vector and an element number, see if the scalar value is +/// already around as a register, for example if it were inserted then extracted +/// from the vector. +Value *findScalarElement(Value *V, unsigned EltNo); + +} // llvm namespace + +#endif diff --git a/include/llvm/AsmParser/Parser.h b/include/llvm/AsmParser/Parser.h index 7ef78d73da1..9fe33603bc6 100644 --- a/include/llvm/AsmParser/Parser.h +++ b/include/llvm/AsmParser/Parser.h @@ -18,54 +18,75 @@ namespace llvm { +class Constant; +class LLVMContext; class Module; +struct SlotMapping; class SMDiagnostic; -class LLVMContext; /// This function is the main interface to the LLVM Assembly Parser. It parses /// an ASCII file that (presumably) contains LLVM Assembly code. It returns a /// Module (intermediate representation) with the corresponding features. Note /// that this does not verify that the generated Module is valid, so you should /// run the verifier after parsing the file to check that it is okay. -/// @brief Parse LLVM Assembly from a file -/// @param Filename The name of the file to parse -/// @param Error Error result info. -/// @param Context Context in which to allocate globals info. +/// \brief Parse LLVM Assembly from a file +/// \param Filename The name of the file to parse +/// \param Error Error result info. +/// \param Context Context in which to allocate globals info. +/// \param Slots The optional slot mapping that will be initialized during +/// parsing. std::unique_ptr parseAssemblyFile(StringRef Filename, SMDiagnostic &Error, - LLVMContext &Context); + LLVMContext &Context, + SlotMapping *Slots = nullptr); /// The function is a secondary interface to the LLVM Assembly Parser. It parses /// an ASCII string that (presumably) contains LLVM Assembly code. It returns a /// Module (intermediate representation) with the corresponding features. Note /// that this does not verify that the generated Module is valid, so you should /// run the verifier after parsing the file to check that it is okay. -/// @brief Parse LLVM Assembly from a string -/// @param AsmString The string containing assembly -/// @param Error Error result info. -/// @param Context Context in which to allocate globals info. +/// \brief Parse LLVM Assembly from a string +/// \param AsmString The string containing assembly +/// \param Error Error result info. +/// \param Context Context in which to allocate globals info. +/// \param Slots The optional slot mapping that will be initialized during +/// parsing. std::unique_ptr parseAssemblyString(StringRef AsmString, SMDiagnostic &Error, - LLVMContext &Context); + LLVMContext &Context, + SlotMapping *Slots = nullptr); /// parseAssemblyFile and parseAssemblyString are wrappers around this function. -/// @brief Parse LLVM Assembly from a MemoryBuffer. -/// @param F The MemoryBuffer containing assembly -/// @param Err Error result info. -/// @param Context Context in which to allocate globals info. +/// \brief Parse LLVM Assembly from a MemoryBuffer. +/// \param F The MemoryBuffer containing assembly +/// \param Err Error result info. +/// \param Slots The optional slot mapping that will be initialized during +/// parsing. std::unique_ptr parseAssembly(MemoryBufferRef F, SMDiagnostic &Err, - LLVMContext &Context); + LLVMContext &Context, + SlotMapping *Slots = nullptr); /// This function is the low-level interface to the LLVM Assembly Parser. /// This is kept as an independent function instead of being inlined into /// parseAssembly for the convenience of interactive users that want to add /// recently parsed bits to an existing module. /// -/// @param F The MemoryBuffer containing assembly -/// @param M The module to add data to. -/// @param Err Error result info. -/// @return true on error. -bool parseAssemblyInto(MemoryBufferRef F, Module &M, SMDiagnostic &Err); +/// \param F The MemoryBuffer containing assembly +/// \param M The module to add data to. +/// \param Err Error result info. +/// \param Slots The optional slot mapping that will be initialized during +/// parsing. +/// \return true on error. +bool parseAssemblyInto(MemoryBufferRef F, Module &M, SMDiagnostic &Err, + SlotMapping *Slots = nullptr); + +/// Parse a type and a constant value in the given string. +/// +/// The constant value can be any LLVM constant, including a constant +/// expression. +/// +/// \return null on error. +Constant *parseConstantValue(StringRef Asm, SMDiagnostic &Err, const Module &M); } // End llvm namespace diff --git a/include/llvm/AsmParser/SlotMapping.h b/include/llvm/AsmParser/SlotMapping.h new file mode 100644 index 00000000000..c5f61d25c3a --- /dev/null +++ b/include/llvm/AsmParser/SlotMapping.h @@ -0,0 +1,34 @@ +//===-- SlotMapping.h - Slot number mapping for unnamed values --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the SlotMapping struct. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASMPARSER_SLOTMAPPING_H +#define LLVM_ASMPARSER_SLOTMAPPING_H + +#include "llvm/IR/TrackingMDRef.h" +#include +#include + +namespace llvm { + +class GlobalValue; + +/// This struct contains the mapping from the slot numbers to unnamed metadata +/// nodes and global values. +struct SlotMapping { + std::vector GlobalValues; + std::map MetadataNodes; +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 18f6b9e011e..4c040a7f3e2 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -113,7 +113,7 @@ class BitstreamReader { return *const_cast(BI); // Otherwise, add a new record. - BlockInfoRecords.push_back(BlockInfo()); + BlockInfoRecords.emplace_back(); BlockInfoRecords.back().BlockID = BlockID; return BlockInfoRecords.back(); } @@ -198,6 +198,8 @@ class BitstreamCursor { public: + static const size_t MaxChunkSize = sizeof(word_t) * 8; + BitstreamCursor() { init(nullptr); } explicit BitstreamCursor(BitstreamReader &R) { init(&R); } @@ -335,7 +337,7 @@ class BitstreamCursor { } word_t Read(unsigned NumBits) { - static const unsigned BitsInWord = sizeof(word_t) * 8; + static const unsigned BitsInWord = MaxChunkSize; assert(NumBits && NumBits <= BitsInWord && "Cannot return zero or more than BitsInWord bits!"); diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitcode/BitstreamWriter.h index 9e2c2fa4a15..9f23023a141 100644 --- a/include/llvm/Bitcode/BitstreamWriter.h +++ b/include/llvm/Bitcode/BitstreamWriter.h @@ -18,6 +18,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Bitcode/BitCodes.h" +#include "llvm/Support/Endian.h" #include namespace llvm { @@ -63,10 +64,7 @@ class BitstreamWriter { // BackpatchWord - Backpatch a 32-bit word in the output with the specified // value. void BackpatchWord(unsigned ByteNo, unsigned NewWord) { - Out[ByteNo++] = (unsigned char)(NewWord >> 0); - Out[ByteNo++] = (unsigned char)(NewWord >> 8); - Out[ByteNo++] = (unsigned char)(NewWord >> 16); - Out[ByteNo ] = (unsigned char)(NewWord >> 24); + support::endian::write32le(&Out[ByteNo], NewWord); } void WriteByte(unsigned char Value) { @@ -74,12 +72,9 @@ class BitstreamWriter { } void WriteWord(unsigned Value) { - unsigned char Bytes[4] = { - (unsigned char)(Value >> 0), - (unsigned char)(Value >> 8), - (unsigned char)(Value >> 16), - (unsigned char)(Value >> 24) }; - Out.append(&Bytes[0], &Bytes[4]); + Value = support::endian::byte_swap(Value); + Out.append(reinterpret_cast(&Value), + reinterpret_cast(&Value + 1)); } unsigned GetBufferOffset() const { @@ -215,7 +210,7 @@ class BitstreamWriter { // Push the outer block's abbrev set onto the stack, start out with an // empty abbrev set. - BlockScope.push_back(Block(OldCodeSize, BlockSizeWordIndex)); + BlockScope.emplace_back(OldCodeSize, BlockSizeWordIndex); BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); // If there is a blockinfo for this BlockID, add all the predefined abbrevs @@ -503,7 +498,7 @@ class BitstreamWriter { return *BI; // Otherwise, add a new record. - BlockInfoRecords.push_back(BlockInfo()); + BlockInfoRecords.emplace_back(); BlockInfoRecords.back().BlockID = BlockID; return BlockInfoRecords.back(); } diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index e450db0eba6..6a9f32e1aad 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -167,6 +167,7 @@ namespace bitc { METADATA_EXPRESSION = 29, // [distinct, n x element] METADATA_OBJC_PROPERTY = 30, // [distinct, name, file, line, ...] METADATA_IMPORTED_ENTITY=31, // [distinct, tag, scope, entity, line, name] + METADATA_MODULE=32, // [distinct, scope, name, ...] }; // The constants block (CONSTANTS_BLOCK_ID) describes emission for each @@ -318,7 +319,7 @@ namespace bitc { // This store code encodes the pointer type, rather than the value type // this is so information only available in the pointer type (e.g. address // spaces) is retained. - FUNC_CODE_INST_STORE = 24, // STORE: [ptrty,ptr,val, align, vol] + FUNC_CODE_INST_STORE_OLD = 24, // STORE: [ptrty,ptr,val, align, vol] // 25 is unused. FUNC_CODE_INST_EXTRACTVAL = 26, // EXTRACTVAL: [n x operands] FUNC_CODE_INST_INSERTVAL = 27, // INSERTVAL: [n x operands] @@ -336,18 +337,29 @@ namespace bitc { FUNC_CODE_DEBUG_LOC = 35, // DEBUG_LOC: [Line,Col,ScopeVal, IAVal] FUNC_CODE_INST_FENCE = 36, // FENCE: [ordering, synchscope] - FUNC_CODE_INST_CMPXCHG = 37, // CMPXCHG: [ptrty,ptr,cmp,new, align, vol, + FUNC_CODE_INST_CMPXCHG_OLD = 37, // CMPXCHG: [ptrty,ptr,cmp,new, align, vol, // ordering, synchscope] FUNC_CODE_INST_ATOMICRMW = 38, // ATOMICRMW: [ptrty,ptr,val, operation, // align, vol, // ordering, synchscope] FUNC_CODE_INST_RESUME = 39, // RESUME: [opval] - FUNC_CODE_INST_LANDINGPAD = 40, // LANDINGPAD: [ty,val,val,num,id0,val0...] + FUNC_CODE_INST_LANDINGPAD_OLD = 40, // LANDINGPAD: [ty,val,val,num,id0,val0...] FUNC_CODE_INST_LOADATOMIC = 41, // LOAD: [opty, op, align, vol, // ordering, synchscope] - FUNC_CODE_INST_STOREATOMIC = 42, // STORE: [ptrty,ptr,val, align, vol + FUNC_CODE_INST_STOREATOMIC_OLD = 42, // STORE: [ptrty,ptr,val, align, vol // ordering, synchscope] FUNC_CODE_INST_GEP = 43, // GEP: [inbounds, n x operands] + FUNC_CODE_INST_STORE = 44, // STORE: [ptrty,ptr,valty,val, align, vol] + FUNC_CODE_INST_STOREATOMIC = 45, // STORE: [ptrty,ptr,val, align, vol + FUNC_CODE_INST_CMPXCHG = 46, // CMPXCHG: [ptrty,ptr,valty,cmp,new, align, + // vol,ordering,synchscope] + FUNC_CODE_INST_LANDINGPAD = 47, // LANDINGPAD: [ty,val,num,id0,val0...] + FUNC_CODE_INST_CLEANUPRET = 48, // CLEANUPRET: [] or [val] or [bb#] or [val,bb#] + FUNC_CODE_INST_CATCHRET = 49, // CATCHRET: [bb#] + FUNC_CODE_INST_CATCHPAD = 50, // CATCHPAD: [ty,val,val,num,args...] + FUNC_CODE_INST_TERMINATEPAD = 51, // TERMINATEPAD: [bb#,num,args...] + FUNC_CODE_INST_CLEANUPPAD = 52, // CLEANUPPAD: [num,args...] + FUNC_CODE_INST_CATCHENDPAD = 53, // CATCHENDPAD: [] or [bb#] }; enum UseListCodes { @@ -398,7 +410,12 @@ namespace bitc { ATTR_KIND_NON_NULL = 39, ATTR_KIND_JUMP_TABLE = 40, ATTR_KIND_DEREFERENCEABLE = 41, - ATTR_KIND_DEREFERENCEABLE_OR_NULL = 42 + ATTR_KIND_DEREFERENCEABLE_OR_NULL = 42, + ATTR_KIND_CONVERGENT = 43, + ATTR_KIND_SAFESTACK = 44, + ATTR_KIND_ARGMEMONLY = 45, + ATTR_KIND_SWIFT_SELF = 46, + ATTR_KIND_SWIFT_ERROR = 47 }; enum ComdatSelectionKindCodes { diff --git a/include/llvm/Bitcode/NaCl/AbbrevTrieNode.h b/include/llvm/Bitcode/NaCl/AbbrevTrieNode.h deleted file mode 100644 index e3a6ee4ba88..00000000000 --- a/include/llvm/Bitcode/NaCl/AbbrevTrieNode.h +++ /dev/null @@ -1,135 +0,0 @@ -//===- AbbrevTrieNode.h - Abbreviation lookup tries ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This header file defines class AbbrevTrieNode that implement abbreviation -// lookup tries. These tries reduce the set of abbreviations that need to -// be tested for best fit to a pnacl bitcode record, by sorting abbreviations -// on literal constants that may appear in the abbreviations. By doing this, -// we can reduce hundreds of possible abbreviations down to a small number -// of possibly applicable abbreviations. -// -// The tries separate abbreviations based on constant size, and constants -// that appear in the abbreviations. The trie is used to capture constants -// that appear at any index, and use these constants to decide if a trie -// node applies to the record. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_NACL_ABBREV_TRIE_NODE_H -#define LLVM_BITCODE_NACL_ABBREV_TRIE_NODE_H - -#include "llvm/Bitcode/NaCl/NaClBitcodeParser.h" -#include -#include - -namespace llvm { - -// Models the association of an abbreviation index with the -// corresponding abbreviation associated with that index. -typedef std::pair AbbrevIndexPair; - -// Models a trie of abbreviation matches that can be used to reduce -// the number of applicable abbreviations. This is done by moving -// abbreviations that require literals to appear in them, to be in -// successor nodes. Abbreviations without literals are stored -// in this node. -class AbbrevTrieNode { - // For faster lookup, we could model the successor map as - // std::map, AbbrevTrieNode*>. However, - // we split up the pair into a nested map. This allows us to reduce - // the size of the domain of the map considerably, as well as - // avoiding much value (i.e. std::pair) - // copying. These modifications result in considerable better time - // performance. - // - // We also do this representation because the trie is sparse, - // with respect to where constants can appear. Hence, we don't - // built a possible successor for all possible indicies, but only - // for those that can contain constants in some abbreviation. - typedef std::map SuccessorValueMap; - typedef std::map SuccessorMap; - -public: - // Models the list of successor labels defined for a node. - typedef std::vector< std::pair > SuccessorLabels; - - // Creates an entry node into the trie. - AbbrevTrieNode() {} - - ~AbbrevTrieNode(); - - // Print out the trie to the given stream, indenting the given - // amount. If LocalOnly is true, no successor information is - // printed. - void Print(raw_ostream &Stream, - const std::string &Indent, - bool LocalOnly=false) const; - - // Adds matching constants, defined in Abbreviation, to the trie. - // Returns true if any nodes were added to the trie to add the given - // abbreviation. Note: This method only creates nodes, Abbreviations - // must be aded in a separate pass using method Insert. Note: If - // you call NaClBuildAbbrevLookupMap, it will construct the - // (complete) abbrevation trie, calling Add and Insert in the - // appropriate order. - bool Add(NaClBitCodeAbbrev *Abbrev) { - return Add(Abbrev, 0, 0); - } - - // Inserts the given abbreviation (pair) in all trie nodes that - // might match the given abbreviation. Should not be called until - // all trie nodes are built using Add. - void Insert(AbbrevIndexPair &AbbrevPair); - - // Returns the successor trie node matching the given Index/Value pair. - AbbrevTrieNode* GetSuccessor(size_t Index, uint64_t Value) const; - - // Collects the set of successor (edge) labels defined for the node. - void GetSuccessorLabels(SuccessorLabels &labels) const; - - // Returns a trie node (in the trie) that defines all possible - // abbreviations that may apply to the given record. - const AbbrevTrieNode *MatchRecord(const NaClBitcodeRecordData &Record) const; - - // Returns the abbreviations associated with the node. - const std::set &GetAbbreviations() const { - return Abbreviations; - } - -private: - // Adds matching constants, defined in Abbreviation, to the trie. - // Returns true if any nodes were added to the trie to add the given - // abbreviation. Index is the positition (within the abbreviation) - // where search should begin for the next available - // literal. SkipIndex is the smallest skipped index used to find the - // next available literal. - bool Add(NaClBitCodeAbbrev *Abbrev, - size_t Index, - size_t SkipIndex); - - // The set of possible successor trie nodes defined for this node. - SuccessorMap Successors; - - // The set of abbreviations that apply if one can't match a pnacl - // bitcode record against any of the successors. - std::set Abbreviations; -}; - -// A map from record sizes, to the corresponding trie one should use -// to find abbreviations for records of that size. -typedef std::map AbbrevLookupSizeMap; - -// Builds abbreviation lookup trie for abbreviations -void NaClBuildAbbrevLookupMap(AbbrevLookupSizeMap &LookupMap, - const SmallVectorImpl &Abbrevs, - size_t InitialIndex = 0); - -} - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClAnalyzerBlockDist.h b/include/llvm/Bitcode/NaCl/NaClAnalyzerBlockDist.h deleted file mode 100644 index 9845fe6a6ae..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClAnalyzerBlockDist.h +++ /dev/null @@ -1,100 +0,0 @@ -//===-- NaClAnalyzerBlockDist.h --------------------------------------------===// -// Defines distribution maps used to collect block and record -// distributions for tools pnacl-bcanalyzer. -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Defines a block distribution, with nested subblock and record code -// distributions, to be collected during analysis. - -#ifndef LLVM_BITCODE_NACL_NACLANALYZERBLOCKDIST_H -#define LLVM_BITCODE_NACL_NACLANALYZERBLOCKDIST_H - -#include "llvm/Bitcode/NaCl/NaClBitcodeBlockDist.h" -#include "llvm/Bitcode/NaCl/NaClBitcodeCodeDist.h" -#include "llvm/Bitcode/NaCl/NaClBitcodeSubblockDist.h" - -namespace llvm { - -/// Holds block distribution, and nested subblock and record code distributions, -/// to be collected during analysis. -class NaClAnalyzerBlockDistElement : public NaClBitcodeBlockDistElement { - NaClAnalyzerBlockDistElement(const NaClAnalyzerBlockDistElement&) = delete; - void operator=(const NaClAnalyzerBlockDistElement&) = delete; - -public: - static bool classof(const NaClBitcodeDistElement *Element) { - return Element->getKind() >= RDE_NaClAnalBlockDist && - Element->getKind() < RDE_NaClAnalBlockDistLast; - } - - explicit NaClAnalyzerBlockDistElement(unsigned BlockID=0, - bool OrderBlocksByID=false) - : NaClBitcodeBlockDistElement(RDE_NaClAnalBlockDist), - BlockID(BlockID), - RecordDist(BlockID), - OrderBlocksByID(OrderBlocksByID) { - NestedDists.push_back(&SubblockDist); - NestedDists.push_back(&RecordDist); - } - - virtual ~NaClAnalyzerBlockDistElement(); - - virtual NaClBitcodeDistElement* - CreateElement(NaClBitcodeDistValue Value) const; - - virtual double GetImportance(NaClBitcodeDistValue Value) const; - - virtual const SmallVectorImpl * - GetNestedDistributions() const; - - NaClBitcodeDist &GetSubblockDist() { - return SubblockDist; - } - - NaClBitcodeCodeDist &GetRecordDist() { - return RecordDist; - } - -private: - // The block ID of the distribution. - unsigned BlockID; - - // Subblocks that appear in this block. - NaClBitcodeSubblockDist SubblockDist; - - // Records that appear in this block. - NaClBitcodeCodeDist RecordDist; - - // Nested blocks used by GetNestedDistributions. - SmallVector NestedDists; - - // If true, order (top-level) blocks by block ID instead of file - // size. - bool OrderBlocksByID; -}; - -/// Holds block distribution, and nested subblock and record code distributions, -/// to be collected during analysis. -class NaClAnalyzerBlockDist : public NaClBitcodeBlockDist { - NaClAnalyzerBlockDist(const NaClAnalyzerBlockDist&) = delete; - void operator=(const NaClAnalyzerBlockDist&) = delete; -public: - NaClAnalyzerBlockDist(NaClAnalyzerBlockDistElement &Sentinel) - : NaClBitcodeBlockDist(&Sentinel) - {} - - virtual ~NaClAnalyzerBlockDist() {} - - virtual void AddRecord(const NaClBitcodeRecord &Record); - - virtual void AddBlock(const NaClBitcodeBlock &Block); -}; - -} -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClBitCodes.h b/include/llvm/Bitcode/NaCl/NaClBitCodes.h deleted file mode 100644 index 44b61a1c4bb..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClBitCodes.h +++ /dev/null @@ -1,407 +0,0 @@ -//===- NaClBitCodes.h - Enum values for the bitcode format ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This header Bitcode enum values. -// -// The enum values defined in this file should be considered permanent. If -// new features are added, they should have values added at the end of the -// respective lists. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_NACL_NACLBITCODES_H -#define LLVM_BITCODE_NACL_NACLBITCODES_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MathExtras.h" -#include - -namespace llvm { -class raw_ostream; - -namespace naclbitc { - enum StandardWidths { - BlockIDWidth = 8, // We use VBR-8 for block IDs. - CodeLenWidth = 4, // Codelen are VBR-4. - BlockSizeWidth = 32, // BlockSize up to 2^32 32-bit words = 16GB per block. - MaxAbbrevWidth = 32 // Maximum value allowed for Fixed and VBR. - }; - - // The standard abbrev namespace always has a way to exit a block, enter a - // nested block, define abbrevs, and define an unabbreviated record. - enum FixedAbbrevIDs { - END_BLOCK = 0, // Must be zero to guarantee termination for broken bitcode. - ENTER_SUBBLOCK = 1, - - /// DEFINE_ABBREV - Defines an abbrev for the current block. It consists - /// of a vbr5 for # operand infos. Each operand info is emitted with a - /// single bit to indicate if it is a literal encoding. If so, the value is - /// emitted with a vbr8. If not, the encoding is emitted as 3 bits followed - /// by the info value as a vbr5 if needed. - DEFINE_ABBREV = 2, - - // UNABBREV_RECORDs are emitted with a vbr6 for the record code, followed by - // a vbr6 for the # operands, followed by vbr6's for each operand. - UNABBREV_RECORD = 3, - - // This is not a code, this is a marker for the first abbrev assignment. - // In addition, we assume up to two additional enumerated constants are - // added for each extension. These constants are: - // - // PREFIX_MAX_FIXED_ABBREV - // PREFIX_MAX_ABBREV - // - // PREFIX_MAX_ABBREV defines the maximal enumeration value used for - // the code selector of a block. If Both PREFIX_MAX_FIXED_ABBREV - // and PREFIX_MAX_ABBREV is defined, then PREFIX_MAX_FIXED_ABBREV - // defines the last code selector of the block that must be read using - // a single read (i.e. a FIXED read, or the first chunk of a VBR read. - FIRST_APPLICATION_ABBREV = 4, - // Defines default values for code length, if no additional selectors - // are added. - DEFAULT_MAX_ABBREV = FIRST_APPLICATION_ABBREV-1 - }; - - /// StandardBlockIDs - All bitcode files can optionally include a BLOCKINFO - /// block, which contains metadata about other blocks in the file. - enum StandardBlockIDs { - /// BLOCKINFO_BLOCK is used to define metadata about blocks, for example, - /// standard abbrevs that should be available to all blocks of a specified - /// ID. - BLOCKINFO_BLOCK_ID = 0, - - // Block IDs 1-7 are reserved for future expansion. - FIRST_APPLICATION_BLOCKID = 8 - }; - - /// BlockInfoCodes - The blockinfo block contains metadata about user-defined - /// blocks. - enum BlockInfoCodes { - // DEFINE_ABBREV has magic semantics here, applying to the current SETBID'd - // block, instead of the BlockInfo block. - - BLOCKINFO_CODE_SETBID = 1, // SETBID: [blockid#] - // The following two codes were removed - // because the PNaCl reader could read - // them, but couldn't be generated by - // the writer. - BLOCKINFO_CODE_BLOCKNAME = 2, // Not used in PNaCl. - BLOCKINFO_CODE_SETRECORDNAME = 3 // Not used in PNaCl. - }; - -} // End naclbitc namespace - -/// NaClBitCodeAbbrevOp - This describes one or more operands in an abbreviation. -/// This is actually a union of two different things: -/// 1. It could be a literal integer value ("the operand is always 17"). -/// 2. It could be an encoding specification ("this operand encoded like so"). -/// -class NaClBitCodeAbbrevOp { -public: - enum Encoding { - Literal = 0, // Value is literal value. - Fixed = 1, // A fixed width field, Val specifies number of bits. - VBR = 2, // A VBR field where Val specifies the width of each chunk. - Array = 3, // A sequence of fields, next field species elt encoding. - Char6 = 4, // A 6-bit fixed field which maps to [a-zA-Z0-9._]. - Encoding_MAX = Char6 - }; - - explicit NaClBitCodeAbbrevOp(uint64_t V) : Enc(Literal), Val(V) {} - explicit NaClBitCodeAbbrevOp(Encoding E, uint64_t Data = 0); - - Encoding getEncoding() const { return Enc; } - - static bool isValidEncoding(uint64_t Enc) { return Enc <= Encoding_MAX; } - - uint64_t getValue() const { return Val; } - - bool hasValue() const { - return hasValue(Enc); - } - static bool hasValue(Encoding E) { - return E <= Encoding_MAX && HasValueArray[E]; - } - - bool isValid() const { return isValid(Enc, Val); } - static bool isValid(Encoding E, uint64_t Val); - static bool isValid(Encoding E) { return isValid(E, 0); } - - bool isLiteral() const { return Enc == Literal; } - - bool isArrayOp() const { return Enc == Array; } - - /// Returns the number of arguments expected by this abbrevation operator. - unsigned NumArguments() const { - if (isArrayOp()) - return 1; - else - return 0; - } - - // Returns the name of the encoding - static const char *getEncodingName(Encoding E) { - if (E > Encoding_MAX) - return "???"; - return EncodingNameArray[E]; - } - - /// Prints out the abbreviation operator to the given stream. - void Print(raw_ostream &Stream) const; - - /// isChar6 - Return true if this character is legal in the Char6 encoding. - static bool isChar6(char C) { - if (C >= 'a' && C <= 'z') return true; - if (C >= 'A' && C <= 'Z') return true; - if (C >= '0' && C <= '9') return true; - if (C == '.' || C == '_') return true; - return false; - } - static unsigned EncodeChar6(char C) { - if (C >= 'a' && C <= 'z') return C-'a'; - if (C >= 'A' && C <= 'Z') return C-'A'+26; - if (C >= '0' && C <= '9') return C-'0'+26+26; - if (C == '.') return 62; - if (C == '_') return 63; - llvm_unreachable("Not a value Char6 character!"); - } - - static char DecodeChar6(unsigned V) { - assert((V & ~63) == 0 && "Not a Char6 encoded character!"); - if (V < 26) return V+'a'; - if (V < 26+26) return V-26+'A'; - if (V < 26+26+10) return V-26-26+'0'; - if (V == 62) return '.'; - if (V == 63) return '_'; - llvm_unreachable("Not a value Char6 character!"); - } - - /// \brief Compares this to Op. Returns <0 if this is less than Op, - /// Returns 0 if they are equal, and >0 if this is greater than Op. - int Compare(const NaClBitCodeAbbrevOp &Op) const { - // Compare encoding values. - int EncodingDiff = static_cast(Enc) - static_cast(Op.Enc); - if (EncodingDiff != 0) return EncodingDiff; - - // Encodings don't differ, so now base on data associated with the - // encoding. - return ValCompare(Op); - } - -private: - Encoding Enc; // The encoding to use. - uint64_t Val; // Data associated with encoding (if any). - - int ValCompare(const NaClBitCodeAbbrevOp &Op) const { - if (Val < Op.Val) - return -1; - else if (Val > Op.Val) - return 1; - else - return 0; - } - static const bool HasValueArray[]; - static const char *EncodingNameArray[]; -}; - -template <> struct isPodLike { - static const bool value=true; -}; - -static inline bool operator<(const NaClBitCodeAbbrevOp &Op1, - const NaClBitCodeAbbrevOp &Op2) { - return Op1.Compare(Op2) < 0; -} - -static inline bool operator<=(const NaClBitCodeAbbrevOp &Op1, - const NaClBitCodeAbbrevOp &Op2) { - return Op1.Compare(Op2) <= 0; -} - -static inline bool operator==(const NaClBitCodeAbbrevOp &Op1, - const NaClBitCodeAbbrevOp &Op2) { - return Op1.Compare(Op2) == 0; -} - -static inline bool operator!=(const NaClBitCodeAbbrevOp &Op1, - const NaClBitCodeAbbrevOp &Op2) { - return Op1.Compare(Op2) != 0; -} - -static inline bool operator>=(const NaClBitCodeAbbrevOp &Op1, - const NaClBitCodeAbbrevOp &Op2) { - return Op1.Compare(Op2) >= 0; -} - -static inline bool operator>(const NaClBitCodeAbbrevOp &Op1, - const NaClBitCodeAbbrevOp &Op2) { - return Op1.Compare(Op2) > 0; -} - -/// NaClBitCodeAbbrev - This class represents an abbreviation record. An -/// abbreviation allows a complex record that has redundancy to be stored in a -/// specialized format instead of the fully-general, fully-vbr, format. -class NaClBitCodeAbbrev { - SmallVector OperandList; - unsigned char RefCount; // Number of things using this. - ~NaClBitCodeAbbrev() {} -public: - NaClBitCodeAbbrev() : RefCount(1) {} - - void addRef() { ++RefCount; } - void dropRef() { if (--RefCount == 0) delete this; } - - unsigned getNumOperandInfos() const { - return static_cast(OperandList.size()); - } - const NaClBitCodeAbbrevOp &getOperandInfo(unsigned N) const { - return OperandList[N]; - } - - void Add(const NaClBitCodeAbbrevOp &OpInfo) { - OperandList.push_back(OpInfo); - } - - // Returns a simplified version of the abbreviation. Used - // to recognize equivalent abbrevations. - NaClBitCodeAbbrev *Simplify() const; - - // Returns true if the abbreviation is valid wrt to the bitcode reader. - bool isValid() const; - - int Compare(const NaClBitCodeAbbrev &Abbrev) const { - // First order based on number of operands. - size_t OperandListSize = OperandList.size(); - size_t AbbrevOperandListSize = Abbrev.OperandList.size(); - if (OperandListSize < AbbrevOperandListSize) - return -1; - else if (OperandListSize > AbbrevOperandListSize) - return 1; - - // Same number of operands, so compare element by element. - for (size_t I = 0; I < OperandListSize; ++I) { - if (int Diff = OperandList[I].Compare(Abbrev.OperandList[I])) - return Diff; - } - return 0; - } - - // Returns true if all records matching the abbreviation must be - // of fixed length. - bool IsFixedSize() const { - unsigned Size = getNumOperandInfos(); - if (Size < 2) return true; - return !OperandList[Size-2].isArrayOp(); - } - - // Returns the smallest record size that will match this - // abbreviation. - size_t GetMinRecordSize() const { - size_t Min = getNumOperandInfos(); - if (!IsFixedSize()) Min -= 2; - return Min; - } - - void Print(raw_ostream &Stream, bool AddNewline=true) const; - - NaClBitCodeAbbrev *Copy() const { - NaClBitCodeAbbrev *AbbrevCopy = new NaClBitCodeAbbrev(); - for (unsigned I = 0, IEnd = getNumOperandInfos(); - I != IEnd; ++I) { - AbbrevCopy->Add(NaClBitCodeAbbrevOp(getOperandInfo(I))); - } - return AbbrevCopy; - } -}; - -static inline bool operator<(const NaClBitCodeAbbrev &A1, - const NaClBitCodeAbbrev &A2) { - return A1.Compare(A2) < 0; -} - -static inline bool operator<=(const NaClBitCodeAbbrev &A1, - const NaClBitCodeAbbrev &A2) { - return A1.Compare(A2) <= 0; -} -static inline bool operator==(const NaClBitCodeAbbrev &A1, - const NaClBitCodeAbbrev &A2) { - return A1.Compare(A2) == 0; -} - -static inline bool operator!=(const NaClBitCodeAbbrev &A1, - const NaClBitCodeAbbrev &A2) { - return A1.Compare(A2) != 0; -} -static inline bool operator>=(const NaClBitCodeAbbrev &A1, - const NaClBitCodeAbbrev &A2) { - return A1.Compare(A2) >= 0; -} - -static inline bool operator>(const NaClBitCodeAbbrev &A1, - const NaClBitCodeAbbrev &A2) { - return A1.Compare(A2) > 0; -} - -/// \brief Returns number of bits needed to encode -/// value for dense FIXED encoding. -inline unsigned NaClBitsNeededForValue(unsigned Value) { - // Note: Need to handle case where Value=0xFFFFFFFF as special case, - // since we can't add 1 to it. - if (Value >= 0x80000000) return 32; - return Log2_32_Ceil(Value+1); -} - -/// \brief Encode a signed value by moving the sign to the LSB for dense -/// VBR encoding. -inline uint64_t NaClEncodeSignRotatedValue(int64_t V) { - return (V >= 0) ? (V << 1) : ((-V << 1) | 1); -} - -/// \brief Decode a signed value stored with the sign bit in -/// the LSB for dense VBR encoding. -inline uint64_t NaClDecodeSignRotatedValue(uint64_t V) { - if ((V & 1) == 0) - return V >> 1; - if (V != 1) - return -(V >> 1); - // There is no such thing as -0 with integers. "-0" really means MININT. - return 1ULL << 63; -} - -/// \brief This class determines whether a FIXED or VBR -/// abbreviation should be used for the selector, and the number of bits -/// needed to capture such selectors. -class NaClBitcodeSelectorAbbrev { - -public: - // If true, use a FIXED abbreviation. Otherwise, use a VBR abbreviation. - bool IsFixed; - // Number of bits needed for selector. - unsigned NumBits; - - // Creates a selector range for the given values. - NaClBitcodeSelectorAbbrev(bool IF, unsigned NB) - : IsFixed(IF), NumBits(NB) {} - - // Creates a selector range when no abbreviations are defined. - NaClBitcodeSelectorAbbrev() - : IsFixed(true), - NumBits(NaClBitsNeededForValue(naclbitc::DEFAULT_MAX_ABBREV)) {} - - // Creates a selector range to handle fixed abbrevations up to - // the specified value. - explicit NaClBitcodeSelectorAbbrev(unsigned MaxAbbrev) - : IsFixed(true), - NumBits(NaClBitsNeededForValue(MaxAbbrev)) {} -}; -} // End llvm namespace - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClBitcodeAbbrevDist.h b/include/llvm/Bitcode/NaCl/NaClBitcodeAbbrevDist.h deleted file mode 100644 index e9bbc61bab7..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClBitcodeAbbrevDist.h +++ /dev/null @@ -1,118 +0,0 @@ -//===-- NaClBitcodeAbbrevDist.h ---------------------------------------------===// -// Defines distribution maps for abbreviations associated with -// bitcode records. -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Defines distribution maps for tracking abbreviations associated -// with bitcode records. - -#ifndef LLVM_BITCODE_NACL_NACLBITCODEABBREVDIST_H -#define LLVM_BITCODE_NACL_NACLBITCODEABBREVDIST_H - -#include "llvm/Bitcode/NaCl/NaClBitcodeDist.h" -#include "llvm/Bitcode/NaCl/NaClCompressCodeDist.h" - -namespace llvm { - -/// Collects the number of instances associated with a given abbreviation -/// index of a bitcode record. Note: Uses naclbitc::UNABBREV_RECORD index -/// to denote bitcode records that did not use an abbreviation. -class NaClBitcodeAbbrevDistElement : public NaClBitcodeDistElement { - NaClBitcodeAbbrevDistElement(const NaClBitcodeAbbrevDistElement&) = delete; - void operator=(const NaClBitcodeAbbrevDistElement&) = delete; - -public: - static bool classof(const NaClBitcodeDistElement *Element) { - return Element->getKind() >= RDE_AbbrevDist && - Element->getKind() < RDE_AbbrevDistLast; - } - - explicit NaClBitcodeAbbrevDistElement(unsigned BlockID=0) - : NaClBitcodeDistElement(RDE_AbbrevDist), - CodeDist(BlockID, &NaClCompressCodeDistElement::Sentinel) { - NestedDists.push_back(&CodeDist); - } - - // Sentinel to create instances of this. - static NaClBitcodeAbbrevDistElement Sentinel; - - virtual ~NaClBitcodeAbbrevDistElement(); - - virtual NaClBitcodeDistElement *CreateElement( - NaClBitcodeDistValue Value) const; - - virtual void GetValueList(const NaClBitcodeRecord &Record, - ValueListType &ValueList) const; - - virtual void AddRecord(const NaClBitcodeRecord &Record); - - virtual const char *GetTitle() const; - - virtual const char *GetValueHeader() const; - - virtual void PrintRowValue(raw_ostream &Stream, - NaClBitcodeDistValue Value, - const NaClBitcodeDist *Distribution) const; - - virtual const SmallVectorImpl * - GetNestedDistributions() const; - - NaClBitcodeDist &GetCodeDist() { - return CodeDist; - } - -private: - // Nested blocks used by GetNestedDistributions. - SmallVector NestedDists; - - /// The records associated with the given abbreviation. - NaClBitcodeCodeDist CodeDist; -}; - -/// Separates record codes based on abbreviations. This is done so -/// that when we add abbreviations, they will be refinements of -/// existing abbreviations. This should guarantee that we don't lose -/// separation defined by previous iterations on calls to -/// pnacl-bccompress. -class NaClBitcodeAbbrevDist : public NaClBitcodeDist { -public: - static bool classof(const NaClBitcodeDist *Dist) { - return Dist->getKind() >= RD_AbbrevDist && - Dist->getKind() < RD_AbbrevDistLast; - } - - explicit NaClBitcodeAbbrevDist( - unsigned BlockID, - NaClBitcodeAbbrevDistElement *Sentinel - = &NaClBitcodeAbbrevDistElement::Sentinel, - NaClBitcodeDistKind Kind=RD_AbbrevDist) - : NaClBitcodeDist(RecordStorage, Sentinel, Kind), - BlockID(BlockID) { - } - - virtual ~NaClBitcodeAbbrevDist(); - - // Returns the block id associated with the abbreviations in this - // distribution map. - unsigned GetBlockID() const { - return BlockID; - } - - virtual NaClBitcodeDistElement* - CreateElement(NaClBitcodeDistValue Value) const; - -private: - // The block id associated with the abbreviations in this - // distribution map. - unsigned BlockID; -}; - -} - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClBitcodeAnalyzer.h b/include/llvm/Bitcode/NaCl/NaClBitcodeAnalyzer.h deleted file mode 100644 index d93f7aa4071..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClBitcodeAnalyzer.h +++ /dev/null @@ -1,66 +0,0 @@ -//===-- NaClBitcodeAnalyzer.h - Bitcode Analyzer --------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -// Analytical information about a bitcode file. Intended as an aid to developers -// of bitcode reading and writing software. It produces a summary of the bitcode -// file that shows various statistics about the contents of the file. By default -// this information is detailed and contains information about individual -// bitcode blocks and the functions in the module. The tool is also able to -// print a bitcode file in a straight forward text format that shows the -// containment and relationships of the information in the bitcode file (-dump -// option). -// -//===----------------------------------------------------------------------===// - -#ifndef NACL_BITCODE_ANALYZER_H -#define NACL_BITCODE_ANALYZER_H - -#include - -namespace llvm { - -class MemoryBuffer; -class StringRef; -class raw_ostream; - -// Analysis options. See the command-line documentation in pnacl-bcanalyzer -// for a description. -struct AnalysisDumpOptions { - AnalysisDumpOptions() - : DumpRecords(false), DumpDetails(false), OpsPerLine(0) - {} - - // When true, dump the records. When false, print out distribution - // statistics. - bool DumpRecords; - - // When true, print out abbreviations, abbreviation ID's, and - // other (non-record specific) details when dumping records. - bool DumpDetails; - - // The number of record operands to be dumped per text line. - unsigned OpsPerLine; - - // When true, prints block statistics based on block ID rather than - // size. When false, prints block statistics base on percentage of - // file. - bool OrderBlocksByID; -}; - -/// Run analysis on the given file. Output goes to OS. -int AnalyzeBitcodeInFile(const StringRef &InputFilename, raw_ostream &OS, - const AnalysisDumpOptions &DumpOptions); - -/// Run analysis on a memory buffer with bitcode. Output goes to -/// OS. The buffer is owned by the caller. -int AnalyzeBitcodeInBuffer(const std::unique_ptr &Buf, - raw_ostream &OS, - const AnalysisDumpOptions &DumpOptions); - -} // namespace llvm - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClBitcodeBitsAndAbbrevsDist.h b/include/llvm/Bitcode/NaCl/NaClBitcodeBitsAndAbbrevsDist.h deleted file mode 100644 index 13666b9351c..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClBitcodeBitsAndAbbrevsDist.h +++ /dev/null @@ -1,69 +0,0 @@ -//===- NaClBitcodeBitsAndAbbrevsDist.h --------------------*- C++ -*-===// -// Maps distributions of values with corresponding number of bits, -// and percentage of abbreviations used in PNaCl bitcode records. -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Creates a distribution map of values and the -// correspdonding bits and abbreviations in PNaCl bitcode records. - -#ifndef LLVM_BITCODE_NACL_NACLBITCODEBITSANDABBREVSDIST_H -#define LLVM_BITCODE_NACL_NACLBITCODEBITSANDABBREVSDIST_H - -#include "llvm/Bitcode/NaCl/NaClBitcodeBitsDist.h" - -namespace llvm { - -/// Defines the element type of a PNaCl bitcode distribution map when -/// we want to count both the number of instances, and the number of -/// bits used by each record. Also tracks the number to times an -/// abbreviation was used to parse the corresponding record. -class NaClBitcodeBitsAndAbbrevsDistElement : public NaClBitcodeBitsDistElement { - NaClBitcodeBitsAndAbbrevsDistElement( - const NaClBitcodeBitsAndAbbrevsDistElement&) = delete; - void operator=(const NaClBitcodeBitsAndAbbrevsDistElement&) = delete; - -public: - static bool classof(const NaClBitcodeDistElement *Dist) { - return Dist->getKind() >= RDE_BitsAndAbbrevsDist - && Dist->getKind() < RDE_BitsAndAbbrevsDistLast; - } - - // Create an element with no instances. - explicit NaClBitcodeBitsAndAbbrevsDistElement( - NaClBitcodeDistElementKind Kind=RDE_BitsAndAbbrevsDist) - : NaClBitcodeBitsDistElement(Kind), - NumAbbrevs(0) - {} - - virtual ~NaClBitcodeBitsAndAbbrevsDistElement(); - - virtual void AddRecord(const NaClBitcodeRecord &Record); - - // Note: No AddBlock method override because abbrevations only - // apply to records. - - // Returns the number of times an abbreviation was used to represent - // the value. - unsigned GetNumAbbrevs() const { - return NumAbbrevs; - } - - virtual void PrintStatsHeader(raw_ostream &Stream) const; - - virtual void PrintRowStats(raw_ostream &Stream, - const NaClBitcodeDist *Distribution) const; - -private: - // Number of times an abbreviation is used for the value. - unsigned NumAbbrevs; -}; - -} - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClBitcodeBitsDist.h b/include/llvm/Bitcode/NaCl/NaClBitcodeBitsDist.h deleted file mode 100644 index 3067bebff11..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClBitcodeBitsDist.h +++ /dev/null @@ -1,68 +0,0 @@ -//===- NaClBitcodeBitsDist.h ------------------------------------*- C++ -*-===// -// Maps distributions of values and corresponding number of -// bits in PNaCl bitcode records. -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Creates a (nestable) distribution map of values, and the correspdonding -// bits, in PNaCl bitcode records. These distributions are built directly -// on top of the NaClBitcodeDistElement class. - -#ifndef LLVM_BITCODE_NACL_NACLBITCODEBITSDIST_H -#define LLVM_BITCODE_NACL_NACLBITCODEBITSDIST_H - -#include "llvm/Bitcode/NaCl/NaClBitcodeDist.h" - -namespace llvm { - -/// Defines the element type of a PNaCl bitcode distribution map when -/// we want to count both the number of instances, and the number of -/// bits used by each record. Also tracks the number to times an -/// abbreviation was used to parse the corresponding record. -class NaClBitcodeBitsDistElement : public NaClBitcodeDistElement { - NaClBitcodeBitsDistElement(const NaClBitcodeBitsDistElement&) = delete; - void operator=(const NaClBitcodeBitsDistElement&) = delete; - -public: - static bool classof(const NaClBitcodeDistElement *Dist) { - return Dist->getKind() >= RDE_BitsDist - && Dist->getKind() < RDE_BitsDistLast; - } - - // Create an element with no instances. - explicit NaClBitcodeBitsDistElement( - NaClBitcodeDistElementKind Kind=RDE_BitsDist) - : NaClBitcodeDistElement(Kind), - TotalBits(0) - {} - - virtual ~NaClBitcodeBitsDistElement(); - - virtual void AddRecord(const NaClBitcodeRecord &Record); - - virtual void AddBlock(const NaClBitcodeBlock &Block); - - // Returns the total number of bits used to represent all instances - // of this value. - uint64_t GetTotalBits() const { - return TotalBits; - } - - virtual void PrintStatsHeader(raw_ostream &Stream) const; - - virtual void PrintRowStats(raw_ostream &Stream, - const NaClBitcodeDist *Distribution) const; - -private: - // Number of bits used to represent all instances of the value. - uint64_t TotalBits; -}; - -} - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClBitcodeBlockDist.h b/include/llvm/Bitcode/NaCl/NaClBitcodeBlockDist.h deleted file mode 100644 index e74a40564ca..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClBitcodeBlockDist.h +++ /dev/null @@ -1,95 +0,0 @@ -//===-- NaClBitcodeBlockDist.h -----------------------------------------===// -// Defines distribution maps for blocks within PNaCl bitcode. -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Defines a distribution map for blocks which tracks the number of bits -// in each block, as well as the percentage of the file each bitcode block -// ID holds. - - -#ifndef LLVM_BITCODE_NACL_NACLBITCODEBLOCKDIST_H -#define LLVM_BITCODE_NACL_NACLBITCODEBLOCKDIST_H - -#include "llvm/Bitcode/NaCl/NaClBitcodeBitsDist.h" - -namespace llvm { - -class NaClBitcodeBlockDistElement : public NaClBitcodeBitsDistElement { - NaClBitcodeBlockDistElement(const NaClBitcodeBlockDistElement&) = delete; - void operator=(const NaClBitcodeBlockDistElement&); - -public: - static bool classof(const NaClBitcodeDistElement *Element) { - return Element->getKind() >= RDE_BlockDist && - Element->getKind() < RDE_BlockDistLast; - } - - // Top-level constructor to create instances of this class. - explicit NaClBitcodeBlockDistElement( - NaClBitcodeDistElementKind Kind=RDE_BlockDist) - : NaClBitcodeBitsDistElement(Kind) {} - - virtual ~NaClBitcodeBlockDistElement(); - - virtual NaClBitcodeDistElement *CreateElement( - NaClBitcodeDistValue Value) const; - - // Sorts by %file, rather than number of instances. - virtual double GetImportance(NaClBitcodeDistValue value) const; - - virtual const char *GetTitle() const; - - virtual const char *GetValueHeader() const; - - /// Prints out header for row of statistics associated with instances - /// of this distribution element. - virtual void PrintStatsHeader(raw_ostream &Stream) const; - - /// Prints out statistics for the row with the given value. - virtual void PrintRowStats(raw_ostream &Stream, - const NaClBitcodeDist *Distribution) const; - - virtual void PrintRowValue(raw_ostream &Stream, - NaClBitcodeDistValue Value, - const NaClBitcodeDist *Distribution) const; -}; - -class NaClBitcodeBlockDist : public NaClBitcodeDist { - NaClBitcodeBlockDist(const NaClBitcodeBlockDist&) = delete; - void operator=(const NaClBitcodeBlockDist&) = delete; - -public: - static bool classof(const NaClBitcodeDist *Dist) { - return Dist->getKind() >= RD_BlockDist && - Dist->getKind() < RD_BlockDistLast; - } - - static NaClBitcodeBlockDistElement DefaultSentinal; - - explicit NaClBitcodeBlockDist( - const NaClBitcodeBlockDistElement *Sentinal=&DefaultSentinal) - : NaClBitcodeDist(BlockStorage, Sentinal, RD_BlockDist) - {} - - virtual ~NaClBitcodeBlockDist(); - - // Returns the total number of bits in all blocks in the distribution. - uint64_t GetTotalBits() const; - - // Returns the printable name associated with the given BlockID. - // - // Note: If the name is not known, an "UnknownBlock" name is - // generated and returned. - static std::string GetName(unsigned BlockID); - -}; - -} - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClBitcodeCodeDist.h b/include/llvm/Bitcode/NaCl/NaClBitcodeCodeDist.h deleted file mode 100644 index 6f794116482..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClBitcodeCodeDist.h +++ /dev/null @@ -1,111 +0,0 @@ -//===-- NaClBitcodeCodeDist.h ---------------------------------------------===// -// Defines distribution maps for various values in bitcode records. -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Defines simple (non-nested) distribution maps for record codes -// appearing in bitcode records (instances of class NaClBitcodeRecord -// in NaClBitcodeParser.h). - -#ifndef LLVM_BITCODE_NACL_NACLBITCODECODEDIST_H -#define LLVM_BITCODE_NACL_NACLBITCODECODEDIST_H - -#include "llvm/Bitcode/NaCl/NaClBitcodeBitsAndAbbrevsDist.h" - -namespace llvm { - -// Collects the distribution of record codes/number of bits used for a -// particular blockID and Code ID. -class NaClBitcodeCodeDistElement - : public NaClBitcodeBitsAndAbbrevsDistElement { - NaClBitcodeCodeDistElement(const NaClBitcodeCodeDistElement&) - = delete; - void operator=(const NaClBitcodeCodeDistElement&) - = delete; - -public: - static bool classof(const NaClBitcodeDistElement *Element) { - return Element->getKind() >= RDE_CodeDist - && Element->getKind() < RDE_CodeDistLast; - } - - explicit NaClBitcodeCodeDistElement( - NaClBitcodeDistElementKind Kind=RDE_CodeDist) - : NaClBitcodeBitsAndAbbrevsDistElement(Kind) - {} - - virtual ~NaClBitcodeCodeDistElement(); - - virtual NaClBitcodeDistElement *CreateElement( - NaClBitcodeDistValue Value) const; - - virtual void GetValueList(const NaClBitcodeRecord &Record, - ValueListType &ValueList) const; - - virtual const char *GetTitle() const; - - virtual const char *GetValueHeader() const; - - virtual void PrintRowValue(raw_ostream &Stream, - NaClBitcodeDistValue Value, - const NaClBitcodeDist *Distribution) const; -}; - -// Collects the distribution of record codes/number of bits used for a -// particular blockID. Assumes distribution elements are instances of -// NaClBitcodeCodeDistElement. -class NaClBitcodeCodeDist : public NaClBitcodeDist { - NaClBitcodeCodeDist(const NaClBitcodeCodeDist&) = delete; - void operator=(const NaClBitcodeCodeDist&) = delete; - -public: - static bool classof(const NaClBitcodeDist *Dist) { - return Dist->getKind() >= RD_CodeDist - && Dist->getKind() < RD_CodeDistLast; - } - -protected: - NaClBitcodeCodeDist(NaClBitcodeDistElement *Sentinal, - unsigned BlockID, - NaClBitcodeDistKind Kind=RD_CodeDist) - : NaClBitcodeDist(RecordStorage, Sentinal, Kind), BlockID(BlockID) - {} - - static NaClBitcodeCodeDistElement DefaultSentinel; - -public: - explicit NaClBitcodeCodeDist( - unsigned BlockID, - NaClBitcodeCodeDistElement *Sentinel = &DefaultSentinel, - NaClBitcodeDistKind Kind=RD_CodeDist) - : NaClBitcodeDist(RecordStorage, Sentinel, Kind), - BlockID(BlockID) - {} - - virtual ~NaClBitcodeCodeDist(); - - unsigned GetBlockID() const { - return BlockID; - } - - // Returns the printable name for record code CodeID in blocks - // associated with BlockID. - // - // Note: If the name is not known, an "UnknownCode" name is - // generated and return. - static std::string GetCodeName(unsigned CodeID, unsigned BlockID); - -private: - // The blockID associated with the record code distribution. - // Used so that we can look up the print name for each record code. - unsigned BlockID; -}; - -} - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClBitcodeDecoders.h b/include/llvm/Bitcode/NaCl/NaClBitcodeDecoders.h deleted file mode 100644 index a3250e0c221..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClBitcodeDecoders.h +++ /dev/null @@ -1,74 +0,0 @@ -//===- NaClBitcodeDecoders.h -------------------------------------*- C++ -*-===// -// Functions used to decode values in PNaCl bitcode files. -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This header file provides a public API for value decoders defined in -// the PNaCl bitcode reader. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_NACL_NACLBITCODEDECODERS_H -#define LLVM_BITCODE_NACL_NACLBITCODEDECODERS_H - -#include "llvm/IR/CallingConv.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Instruction.h" -#include "llvm/Bitcode/NaCl/NaClLLVMBitCodes.h" - -namespace llvm { -namespace naclbitc { - -/// Converts the NaCl (bitcode file) cast opcode to the corresponding -/// LLVM cast opcode. Returns true if the conversion -/// succeeds. Otherwise sets LLVMOpcode to Instruction::BitCast and -/// returns false. -bool DecodeCastOpcode(uint64_t NaClOpcode, - Instruction::CastOps &LLVMOpcode); - -/// Converts the NaCl (bitcode file) linkage type to the corresponding -/// LLVM linkage type. Returns true if the conversion -/// succeeds. Otherwise sets LLVMLinkage to -/// GlobalValue::InternalLinkage and returns false. -bool DecodeLinkage(uint64_t NaClLinkage, - GlobalValue::LinkageTypes &LLVMLinkage); - -/// Converts the NaCl (bitcode file) binary opcode to the -/// corresponding LLVM binary opcode, assuming that the operator -/// operates on OpType. Returns true if the conversion -/// succeeds. Otherwise sets LLVMOpcode to Instruction::Add and -/// returns false. -bool DecodeBinaryOpcode(uint64_t NaClOpcode, Type *OpType, - Instruction::BinaryOps &LLVMOpcode); - -/// Converts the NaCl (bitcode file) calling convention value to the -/// corresponding LLVM calling conventions. Returns true if the -/// conversion succeeds. Otherwise sets LLVMCallingConv to -/// CallingConv::C and returns false. -bool DecodeCallingConv(uint64_t NaClCallingConv, - CallingConv::ID &LLVMCallingConv); - -/// Converts the NaCl (bitcode file) float comparison predicate to the -/// corresponding LLVM float comparison predicate. Returns true if the -/// conversion succeeds. Otherwise sets LLVMPredicate to -/// CmpInst::FCMP_FALSE and returns false. -bool DecodeFcmpPredicate(uint64_t NaClPredicate, - CmpInst::Predicate &LLVMPredicate); - -/// Converts the NaCl (bitcode file) integer comparison predicate to -/// the corresponding LLVM integer comparison predicate. Returns true -/// if the conversion succeeds. Otherwise sets LLVMPredicate to -/// CmpInst::ICMP_EQ and returns false. -bool DecodeIcmpPredicate(uint64_t NaClPredicate, - CmpInst::Predicate &LLVMPredicate); - -} -} - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClBitcodeDefs.h b/include/llvm/Bitcode/NaCl/NaClBitcodeDefs.h deleted file mode 100644 index bb1792ff0c1..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClBitcodeDefs.h +++ /dev/null @@ -1,53 +0,0 @@ -//===- NaClBitcodeDefs.h ----------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Defines some common types/constants used by bitcode readers and -// writers. It is intended to make clear assumptions made in -// representing bitcode files. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_NACL_NACLBITCODEDEFS_H -#define LLVM_BITCODE_NACL_NACLBITCODEDEFS_H - -namespace llvm { - -namespace naclbitc { - -// Special record codes used to model codes for predefined records. -// They are very large so that they do not conflict with existing -// record codes for user-defined blocks. -enum SpecialBlockCodes { - BLK_CODE_ENTER = 65535, - BLK_CODE_EXIT = 65534, - BLK_CODE_DEFINE_ABBREV = 65533, - BLK_CODE_HEADER = 65532 -}; - -} // end of namespace naclbitc - -/// Defines type for value indicies in bitcode. Like a size_t, but -/// fixed across platforms. -typedef uint32_t NaClBcIndexSize_t; - -/// Signed version of NaClBcIndexSize_t. Used to define relative indices. -typedef int32_t NaClRelBcIndexSize_t; - -/// Defines maximum allowed bitcode index in bitcode files. -static const size_t NaClBcIndexSize_t_Max = - std::numeric_limits::max(); - -/// Defines the maximum number of initializers allowed, based on ILP32. -static const size_t MaxNaClGlobalVarInits = - std::numeric_limits::max(); - -} // end of namespace llvm - - -#endif // LLVM_BITCODE_NACL_NACLBITCODEDEFS_H diff --git a/include/llvm/Bitcode/NaCl/NaClBitcodeDist.h b/include/llvm/Bitcode/NaCl/NaClBitcodeDist.h deleted file mode 100644 index 60ecabf4965..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClBitcodeDist.h +++ /dev/null @@ -1,507 +0,0 @@ -//===- NaClBitcodeDist.h ---------------------------------------*- C++ -*-===// -// Maps distributions of values in PNaCl bitcode files. -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Creates a (nestable) distribution map of values in PNaCl bitcode. -// The domain of these maps is the set of record values being -// tracked. The range is the information associated with each block -// and/or record value, including the number of instances of that value. The -// distribution map is nested if the range element contains another -// distribution map. -// -// The goal of distribution maps is to build a (histogram) -// distribution of values in bitcode records and blocks, of a PNaCl -// bitcode file. From appropriately built distribution maps, one can -// infer possible new abbreviations that can be used in the PNaCl -// bitcode file. Hence, one of the primary goals of distribution maps -// is to support tools pnacl-bcanalyzer and pnacl-bccompress. -// -// Distribution maps are constructed either from NaClBitcodeBlock's or -// NaClBitcodeRecord's (in NaClBitcodeParser.h), but not both. It is -// assumed that only blocks, or records (but not both) are added to a -// distribution map. To add data to the distribution map, one calls -// AddRecord and/or AddBlock. If the distribution map contains record -// values, you must call AddRecord for each record to be put into the -// distribution map. If the distribution map contains block values (i.e. -// block ID's), you must call AddBlock for each block to be put into -// the distribution map. -// -// While it may counterintuitive, one can call both AddRecord and -// AddBlock, for each corresponding record and block processed. The -// reason for this is that an internal flag StorageKind is kept within -// distribution maps. If the flag value doesn't correspond to the -// type of called add method, no update is done. This behaviour is -// done so that nested distribution maps can be updated via blind -// calls in NaClBitcodeAnalyzer.cpp. -// -// Via inheritance, and overriding the (virtual) AddRecord -// method for a distribution map, we can redirect the add to look up -// the distribution element associated with the block of the record, -// and then update the corresponding record distribution map. In general, -// it only makes sense (for nested distribution maps) to be able to -// redirect record additions. Redirecting blocks within a record (since -// a record is only associated with one block) does not make sense. Hence, -// we have not made AddBlock virtual. -// -// When updating a block distribution map, the domain value is the -// BlockID of the corresponding block being added. -// -// On the other hand, values associated with record distribution maps -// are many possible values (the code, the abbreviation, the values -// etc). To make the API uniform, record distribution maps are updated -// using NaClBitcodeRecords (in NaClBitcodeParser.h). The values from -// the record are defined by the extract method GetValueList, and -// added via method AddRecord. -// -// Distribution maps are implemented using two classes: -// -// NaClBitcodeDist -// A generic distribution map. -// -// NaClBitcodeDistElement -// The implementation of elements in the range of the distribution -// map. -// -// The code has been written to put the (virtual) logic of -// distribution maps into derived classes of NaClBitcodeDistElement -// whenever possible. This is intentional, in that it keeps all -// knowledge of how to handle/print elements in one class. However, -// because some distributions have external data that is needed by all -// elements, the virtual methods of class NaClBitcodeDist can be -// overridden, and not delegate to NaClBitcodeDistElement. -// -// To do this, an NaClBitcodeDist requires a "sentinel" (derived) -// instance of NaClBitcodeDistElement. This sentinel is used to define -// behaviour needed by distribution maps. -// -// By having control passed to the (derived) instances of -// NaClBitcodeDistElement, it also makes handling nested distributions -// relatively easy. One just extends the methods AddRecord and/or -// AddBlock to also update the corresponding nested distribution. -// -// The exception to this rule is printing, since header information is -// dependent on properties of any possible nested distribution maps -// (for example, we copy column headers after each nested distribution -// map so that it is easier to read the output). To fix this, we let -// virtual method NaClBitcodeDistElement::GetNestedDistributions -// return the array of nested distribution pointers for the nested -// distributions of that map. The order in the array is the order the -// nested distributions will be printed. Typically, this is -// implemented as a field of the distribution element, and is -// initialized to contain the pointers of all nested distributions in -// the element. This field can then be returned from method -// GetNestedDistributions. -// -// Distribution maps are sortable (via method GetDistribution). The -// purpose of sorting is to find interesting elements. This is done by -// sorting the values in the domain of the distribution map, based on -// the GetImportance method of the range element. -// -// Method GetImportance defines how (potentially) interesting the -// value is in the distribution. "Interesting" is based on the notion -// of how likely will the value show a case where adding an -// abbreviation will shrink the size of the corresponding bitcode -// file. For most distributions, the number of instances associated -// with the value is the best measure. -// -// However, for cases where multiple domain entries are created for -// the same NaClBitcodeRecord (i.e. method GetValueList defines more -// than one value), things are not so simple. - -// For example, for some distributions (such as value index distributions) -// the numbers of instances isn't sufficient. In such cases, you may -// have to look at nested distributions to find important cases. -// -// In the case of value index distributions, when the size of the -// records is the same, all value indices have the same number of -// instances. In this case, "interesting" may be measured in terms of -// the (nested) distribution of the values that can appear at that -// index, and how often each value appears. -// -// The larger the importance, the more interesting the value is -// considered, and sorting is based on moving interesting values to -// the front of the sorted list. -// -// When printing distribution maps, the values are sorted based on -// the importance. By default, importance is based on the number of -// times the value appears in records, putting the most used values -// at the top of the printed list. -// -// Since sorting is expensive, the sorted distribution is built once -// and cached. This cache is flushed whenever the distribution map is -// updated, so that a new sorted distribuition will be generated. -// -// Printing of distribution maps are stylized, so that virtuals can -// easily fill in the necessary data. -// -// For concrete instances of NaClBitcodeDistElement, the following -// virtual method must be defined: -// -// CreateElement -// Creates a new instance of the distribution element, to -// be put into the corresponding distribution map when a new -// value is added to the distribution map. -// -// In addition, if the distribution element is based on record values, -// the virtual method GetValueList must be defined, to extract values -// out of the bitcode record. - -#ifndef LLVM_BITCODE_NACL_NACLBITCODEDIST_H -#define LLVM_BITCODE_NACL_NACLBITCODEDIST_H - -#include "llvm/Bitcode/NaCl/NaClBitcodeParser.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" - -#include -#include - -namespace llvm { - -/// The domain type of PNaCl bitcode record distribution maps. -typedef uint64_t NaClBitcodeDistValue; - -/// Base class of the range type of PNaCl bitcode record distribution -/// maps. -class NaClBitcodeDistElement; - -/// Type defining the list of values extracted from the corresponding -/// bitcode record. Typically, the list size is one. However, there -/// are cases where a record defines more than one value (i.e. value -/// indices). Hence, this type defines the more generic API for -/// values. -typedef std::vector ValueListType; - -typedef ValueListType::const_iterator ValueListIterator; - -/// Defines a PNaCl bitcode record distribution map. The distribution -/// map is a map from a (record) value, to the corresponding data -/// associated with that value. Assumes distributions elements are -/// instances of NaClBitcodeDistElement. -class NaClBitcodeDist { - NaClBitcodeDist(const NaClBitcodeDist&) = delete; - void operator=(const NaClBitcodeDist&) = delete; - friend class NaClBitcodeDistElement; - -public: - /// Define kinds for isa, dyn_cast, etc. support (see - /// llvm/Support/Casting.h). Only defined for concrete classes. - enum NaClBitcodeDistKind { - RD_Dist, // class NaClBitcodeDist. - RD_BlockDist, // class NaClBitcodeBlockDist. - RD_BlockDistLast, - RD_CodeDist, // class NaClBitcodeCodeDist. - RD_CodeDistLast, - RD_AbbrevDist, // class NaClBitcodeAbbrevDist. - RD_AbbrevDistLast, - RD_SubblockDist, // class NaClBlockSubblockDist. - RD_SubblockDistLast, - RD_ValueDist, // class NaClBitcodeValueDist. - RD_ValueDistLast, - RD_DistLast - }; - - NaClBitcodeDistKind getKind() const { return Kind; } - -private: - const NaClBitcodeDistKind Kind; - - static bool classof(const NaClBitcodeDist *Dist) { - return Dist->getKind() >= RD_Dist && Dist->getKind() < RD_DistLast; - } - -public: - /// Type defining the mapping used to define the distribution. - typedef std::map MappedElement; - - typedef MappedElement::const_iterator const_iterator; - - /// Type defining a pair of values used to sort the - /// distribution. The first element is defined by method - /// GetImportance, and the second is the distribution value - /// associated with that importance. - typedef std::pair DistPair; - - /// Type defining the sorted list of (domain) values in the - /// corresponding distribution map. - typedef std::vector Distribution; - - /// Defines whether blocks or records are stored in the distribution map. - /// Used to decide if AddRecord/AddBlock methods should fire. - enum StorageSelector { - BlockStorage, - RecordStorage - }; - - NaClBitcodeDist(StorageSelector StorageKind, - const NaClBitcodeDistElement *Sentinel, - NaClBitcodeDistKind Kind=RD_Dist) - : Kind(Kind), StorageKind(StorageKind), Sentinel(Sentinel), - TableMap(), CachedDistribution(0), Total(0) { - } - - virtual ~NaClBitcodeDist(); - - /// Number of elements in the distribution map. - size_t size() const { - return TableMap.size(); - } - - /// Iterator at beginning of distribution map. - const_iterator begin() const { - return TableMap.begin(); - } - - /// Iterator at end of distribution map. - const_iterator end() const { - return TableMap.end(); - } - - /// Returns true if the distribution map is empty. - bool empty() const { - return TableMap.empty(); - } - - /// Returns the element associated with the given distribution - /// value. Creates the element if needed. - inline NaClBitcodeDistElement *GetElement(NaClBitcodeDistValue Value); - - /// Returns the element associated with the given distribution - /// value. - NaClBitcodeDistElement *at(NaClBitcodeDistValue Value) const { - return TableMap.at(Value); - } - - // Creates a new instance of this element for the given value. Used - // by class NaClBitcodeDist to create instances. Default method - // simply dispatches to the CreateElement method of the sentinel. - virtual NaClBitcodeDistElement *CreateElement( - NaClBitcodeDistValue Value) const; - - /// Interrogates the block record, and returns the corresponding - /// values that are being tracked by the distribution map. Default - /// method simply dispatches to the GetValueList of the sentinel. - virtual void GetValueList(const NaClBitcodeRecord &Record, - ValueListType &ValueList) const; - - /// Returns the total number of instances held in the distribution - /// map. - unsigned GetTotal() const { - return Total; - } - - /// Adds the value(s) in the given bitcode record to the - /// distribution map. The value(s) based on method GetValueList. - /// Note: Default requires that GetStorageKind() == RecordStorage. - /// Override if you want special handling for nested distributions - /// in a block distribution map. - virtual void AddRecord(const NaClBitcodeRecord &Record); - - /// Adds the BlockID of the given bitcode block to the distribution - /// map, if applicable (based on the value of method UseBlockID). - /// Note: Requires that GetStorageKind() == BlockStorage. - virtual void AddBlock(const NaClBitcodeBlock &Block); - - /// Builds the distribution associated with the distribution map. - /// Warning: The distribution is cached, and hence, only valid while - /// it's contents is not changed. - const Distribution *GetDistribution() const { - if (CachedDistribution == 0) Sort(); - return CachedDistribution; - } - - /// Prints out the contents of the distribution map to Stream. - void Print(raw_ostream &Stream, const std::string &Indent) const; - - void Print(raw_ostream &Stream) const { - std::string Indent; - Print(Stream, Indent); - } - -protected: - /// If the distribution is cached, remove it. Should be called - /// whenever the distribution map is changed. - void RemoveCachedDistribution() const { - if (CachedDistribution) { - delete CachedDistribution; - CachedDistribution = 0; - } - } - - /// Sorts the distribution, based on the importance of each element. - void Sort() const; - -private: - // Defines whether values in distribution map are from blocks or records. - const StorageSelector StorageKind; - // Sentinel element used to do generic operations for distribution. - const NaClBitcodeDistElement *Sentinel; - // Map from the distribution value to the corresponding distribution - // element. - MappedElement TableMap; - // Pointer to the cached distribution. - mutable Distribution *CachedDistribution; - // The total number of instances in the map. - unsigned Total; -}; - -/// Defines the element type of a PNaCl bitcode distribution map. -/// This is the base class for all element types used in -/// NaClBitcodeDist. By default, only the number of instances -/// of the corresponding distribution values is recorded. -class NaClBitcodeDistElement { - NaClBitcodeDistElement(const NaClBitcodeDistElement &) - = delete; - void operator=(const NaClBitcodeDistElement &) - = delete; - -public: - /// Define kinds for isa, dyn_cast, etc. support. Only defined - /// for concrete classes. - enum NaClBitcodeDistElementKind { - RDE_Dist, // class NaClBitcodeDistElement. - RDE_AbbrevDist, // class NaClBitcodeAbbrevDistElement. - RDE_AbbrevDistLast, - RDE_BitsDist, // class NaClBitcodeBitsDistElement. - RDE_BitsAndAbbrevsDist, // class NaClBitcodeBitsAndAbbrevsDistElement. - RDE_CodeDist, // class NaClBitcodeCodeDistElement. - RDE_CompressCodeDist, // class NaClCompressCodeDistElement. - RDE_CompressCodeDistLast, - RDE_CodeDistLast, - RDE_BitsAndAbbrevsDistLast, - RDE_BitsDistLast, - RDE_BlockDist, // class NaClBitcodeBlockDistElement. - RDE_NaClAnalBlockDist, // class NaClAnalyzerBlockDistElement. - RDE_NaClAnalBlockDistLast, - RDE_PNaClCompressBlockDist, // class NaClCompressBlockDistElement. - RDE_PNaClCompressBlockDistLast, - RDE_BlockDistLast, - RDE_SizeDist, // class NaClBitcodeSizeDistElement. - RDE_SizeDistLast, - RDE_SubblockDist, // class NaClBitcodeSubblockDistElement - RDE_SubblockDistLast, - RDE_ValueDist, // class NaClBitcodeValueDistElement. - RDE_ValueDistLast, - RDE_ValueIndexDist, // class NaClBitcodeValueIndexDistElement. - RDE_ValueIndexDistLast, - RDE_DistLast - }; - - NaClBitcodeDistElementKind getKind() const { return Kind; } - - static bool classof(const NaClBitcodeDistElement *Element) { - return Element->getKind() >= RDE_Dist && Element->getKind() < RDE_DistLast; - } - -private: - const NaClBitcodeDistElementKind Kind; - -public: - - // Constructor to use in derived classes. - NaClBitcodeDistElement( - NaClBitcodeDistElementKind Kind=RDE_Dist) - : Kind(Kind), NumInstances(0) - {} - - virtual ~NaClBitcodeDistElement(); - - // Adds an instance of the given record to this element. - virtual void AddRecord(const NaClBitcodeRecord &Record); - - // Adds an instance of the given block to this element. - virtual void AddBlock(const NaClBitcodeBlock &Block); - - // Returns the number of instances associated with this element. - unsigned GetNumInstances() const { - return NumInstances; - } - - // Creates a new instance of this element for the given value. Used - // by class NaClBitcodeDist to create instances. - virtual NaClBitcodeDistElement *CreateElement( - NaClBitcodeDistValue Value) const = 0; - - /// Interrogates the block record, and returns the corresponding - /// values that are being tracked by the distribution map. Must be - /// defined in derived classes. - virtual void GetValueList(const NaClBitcodeRecord &Record, - ValueListType &ValueList) const; - - // Returns the importance of this element. In many cases, it will be - // the number of instances associated with it. However, it need not - // be correlated to the number of instance. Used to sort the - // distribution map, where values with larger importance appear - // first. Value is the domain value associated with the element in - // the distribution map. - virtual double GetImportance(NaClBitcodeDistValue Value) const; - - /// Returns the title to use when printing the title associated - /// with instances of this distribution element. - virtual const char *GetTitle() const; - - /// Prints out the title of the distribution map associated with - /// instances of this distribution element. - virtual void PrintTitle(raw_ostream &Stream, - const NaClBitcodeDist *Distribution) const; - - /// Returns the header to use when printing the value associated - /// with instances of this distribution element. - virtual const char *GetValueHeader() const; - - /// Prints out header for row of statistics associated with instances - /// of this distribution element. - virtual void PrintStatsHeader(raw_ostream &Stream) const; - - /// Prints out the header to the printed distribution map associated - /// with instances of this distribution element. - void PrintHeader(raw_ostream &Stream) const; - - /// Prints out statistics for the row with the given value. - virtual void PrintRowStats(raw_ostream &Stream, - const NaClBitcodeDist *Distribution) const; - - /// Prints out Value (in a row) to Stream. - virtual void PrintRowValue(raw_ostream &Stream, - NaClBitcodeDistValue Value, - const NaClBitcodeDist *Distribution) const; - - /// Prints out a row in the printed distribution map. - virtual void PrintRow(raw_ostream &Stream, - NaClBitcodeDistValue Value, - const NaClBitcodeDist *Distribution) const; - - /// Returns a pointer to the list of nested distributions that - /// should be printed when this element is printed. Return 0 if no - /// nested distributions should be printed. - virtual const SmallVectorImpl * - GetNestedDistributions() const; - - /// Prints out any nested distributions, if defined for the element. - /// Returns true if a nested distribution was printed. - bool PrintNestedDistIfApplicable( - raw_ostream &Stream, const std::string &Indent) const; - -private: - // The number of instances associated with this element. - unsigned NumInstances; -}; - -inline NaClBitcodeDistElement *NaClBitcodeDist:: -GetElement(NaClBitcodeDistValue Value) { - if (TableMap.find(Value) == TableMap.end()) { - TableMap[Value] = CreateElement(Value); - } - return TableMap[Value]; -} - -} - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClBitcodeHeader.h b/include/llvm/Bitcode/NaCl/NaClBitcodeHeader.h deleted file mode 100644 index 50ca5aaed86..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClBitcodeHeader.h +++ /dev/null @@ -1,263 +0,0 @@ -//===-- llvm/Bitcode/NaCl/NaClBitcodeHeader.h - ----------------*- C++ -*-===// -// NaCl Bitcode header reader. -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This header defines interfaces to read and write NaCl bitcode wire format -// file headers. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_NACL_NACLBITCODEHEADER_H -#define LLVM_BITCODE_NACL_NACLBITCODEHEADER_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/DataTypes.h" -#include -#include - -namespace llvm { -class MemoryObject; - -// Class representing a variable-size metadata field in the bitcode header. -// Also contains the list of known (typed) Tag IDs. -// -// The serialized format has 2 fixed subfields (ID:type and data length) and the -// variable-length data subfield -class NaClBitcodeHeaderField { - NaClBitcodeHeaderField(const NaClBitcodeHeaderField &) = delete; - void operator=(const NaClBitcodeHeaderField &) = delete; - -public: - // Defines the ID associated with the value. Valid values are in - // {0x0, ..., 0xFFF} - typedef enum { - kInvalid = 0, // KUnknownType. - kPNaClVersion = 1, // kUint32Type. - kAlignBitcodeRecords = 2, // kFlagType. - kTag_MAX = kAlignBitcodeRecords - } Tag; - // Defines the type of value. - typedef enum { - kBufferType, // Buffer of form uint8_t[len]. - kUInt32Type, - kFlagType, - kUnknownType, - kFieldType_MAX = kUnknownType - } FieldType; - // Defines the number of bytes in a (32-bit) word. - static const int WordSize = 4; - - // Defines the encoding of the fixed fields {i.e. ID:type and data length). - typedef uint16_t FixedSubfield; - - // Create an invalid header field. - NaClBitcodeHeaderField(); - - // Creates a header field where MyID is a flag. - NaClBitcodeHeaderField(Tag MyID); - - // Create a header field with an uint32_t value. - NaClBitcodeHeaderField(Tag MyID, uint32_t value); - - // Create a header field for the given data. - NaClBitcodeHeaderField(Tag MyID, size_t MyLen, uint8_t *MyData); - - virtual ~NaClBitcodeHeaderField() { - if (Data) - delete[] Data; - } - - /// \brief Number of bytes used to represent header field. - size_t GetTotalSize() const { - // Round up to 4 byte alignment - return (kTagLenSize + Len + (WordSize - 1)) & ~(WordSize - 1); - } - - /// \brief Write field into Buf[BufLen]. - bool Write(uint8_t *Buf, size_t BufLen) const; - - /// \brief Read field from Buf[BufLen]. - bool Read(const uint8_t *Buf, size_t BufLen); - - /// \brief Returns string describing ID of field. - static const char *IDName(Tag ID); - const char *IDName() const { - return IDName(ID); - } - - /// \brief Returns string describing type of field. - static const char *TypeName(FieldType FType); - const char *TypeName() const { - return TypeName(FType); - } - - /// \brief Returns string describing field. - std::string Contents() const; - - /// \brief Get the data size from a serialized field to allow allocation. - static size_t GetDataSizeFromSerialized(const uint8_t *Buf) { - FixedSubfield Length; - ReadFixedSubfield(&Length, Buf + sizeof(FixedSubfield)); - return Length; - } - - /// \brief Return the ID of the field. - Tag GetID() const { return ID; } - - FieldType GetType() const { return FType; } - - /// \brief Return the length of the data (in bytes). - size_t GetLen() const { return Len; } - - /// \brief Return the data. Data is array getData()[getLen()]. - const uint8_t *GetData() const { return Data; } - - /// \brief Returns the uint32_t value stored. Requires that - /// getType() == kUint32Type - uint32_t GetUInt32Value() const; - -private: - // Convert ID:Type into a fixed subfield - FixedSubfield EncodeTypedID() const { return (ID << 4) | FType; } - // Extract out ID and Type from a fixed subfield. - void DecodeTypedID(FixedSubfield Subfield, Tag &ID, FieldType &FType) { - FixedSubfield PossibleID = Subfield >> 4; - ID = (PossibleID > kTag_MAX ? kInvalid : static_cast(PossibleID)); - FixedSubfield PossibleFType = Subfield & 0xF; - FType = (PossibleFType > kFieldType_MAX - ? kUnknownType : static_cast(PossibleFType)); - } - // Combined size of the fixed subfields - const static size_t kTagLenSize = 2 * sizeof(FixedSubfield); - static void WriteFixedSubfield(FixedSubfield Value, uint8_t *Buf) { - Buf[0] = Value & 0xFF; - Buf[1] = (Value >> 8) & 0xFF; - } - static void ReadFixedSubfield(FixedSubfield *Value, const uint8_t *Buf) { - *Value = Buf[0] | Buf[1] << 8; - } - Tag ID; - FieldType FType; - size_t Len; - uint8_t *Data; -}; - -/// \brief Class holding parsed header fields in PNaCl bitcode file. -class NaClBitcodeHeader { - NaClBitcodeHeader(const NaClBitcodeHeader &) = delete; - void operator=(const NaClBitcodeHeader &) = delete; - - // The set of parsed header fields. The header takes ownership of - // all fields in this vector. - std::vector Fields; - // The number of bytes in the PNaCl header. - size_t HeaderSize; - // String defining why it is unsupported (if unsupported). - std::string UnsupportedMessage; - // Flag defining if header is supported. - bool IsSupportedFlag; - // Flag defining if the corresponding bitcode file is readable. - bool IsReadableFlag; - // Defines the PNaCl version defined by the header file. - uint32_t PNaClVersion; - // Byte align bitcode records when nonzero. - bool AlignBitcodeRecords = false; - -public: - static const int WordSize = NaClBitcodeHeaderField::WordSize; - - NaClBitcodeHeader(); - ~NaClBitcodeHeader(); - - /// \brief Installs the fields of the header, defining if the header - /// is readable and supported. Sets UnsupportedMessage on failure. - void InstallFields(); - - /// \brief Adds a field to the list of fields in a header. Takes ownership - /// of fields added. - void push_back(NaClBitcodeHeaderField *Field) { - Fields.push_back(Field); - } - - /// \brief Read the PNaCl bitcode header, The format of the header is: - /// - /// 1) 'PEXE' - The four character sequence defining the magic number. - /// 2) uint_16 num_fields - The number of NaClBitcodeHeaderField's. - /// 3) uint_16 num_bytes - The number of bytes to hold fields in - /// the header. - /// 4) NaClBitcodeHeaderField f1 - The first bitcode header field. - /// ... - /// 2 + num_fields) NaClBitcodeHeaderField fn - The last bitcode header - /// field. - /// - /// Returns false if able to read (all of) the bitcode header. - bool Read(const unsigned char *BufPtr, const unsigned char *BufEnd); - - // \brief Read the PNaCl bitcode header, recording the fields found - // in the header. Returns false if able to read (all of) the bitcode header. - bool Read(MemoryObject *Bytes); - - // \brief Returns the number of bytes read to consume the header. - size_t getHeaderSize() { return HeaderSize; } - - /// \brief Returns string describing why the header describes - /// an unsupported PNaCl Bitcode file. - const std::string &Unsupported() const { return UnsupportedMessage; } - - /// \brief Returns true if supported. That is, it can be run in the - /// browser. - bool IsSupported() const { return IsSupportedFlag; } - - /// \brief Returns true if the bitcode file should be readable. Note - /// that just because it is readable, it doesn't necessarily mean that - /// it is supported. - bool IsReadable() const { return IsReadableFlag; } - - /// \brief Returns number of fields defined. - size_t NumberFields() const { return Fields.size(); } - - /// \brief Returns a pointer to the field with the given ID - /// (0 if no such field). - NaClBitcodeHeaderField *GetTaggedField(NaClBitcodeHeaderField::Tag ID) const; - - /// \brief Returns a pointer to the Nth field in the header - /// (0 if no such field). - NaClBitcodeHeaderField *GetField(size_t index) const; - - /// \brief Returns the PNaClVersion, as defined by the header. - uint32_t GetPNaClVersion() const { return PNaClVersion; } - - /// \brief Returns if one should byte align bitcode records. - bool getAlignBitcodeRecords() const { return AlignBitcodeRecords; } - -private: - // Reads and verifies the first 8 bytes of the header, consisting - // of the magic number 'PEXE', and the value defining the number - // of fields and number of bytes used to hold fields. - // Returns false if successful, sets UnsupportedMessage otherwise. - bool ReadPrefix(const unsigned char *BufPtr, const unsigned char *BufEnd, - unsigned &NumFields, unsigned &NumBytes); - - // Reads and verifies the fields in the header. - // Returns false if successful, sets UnsupportedMessage otherwise. - bool ReadFields(const unsigned char *BufPtr, const unsigned char *BufEnd, - unsigned NumFields, unsigned NumBytes); - - // Sets the Unsupported error message and returns true. - bool UnsupportedError(StringRef Message) { - UnsupportedMessage = Message.str(); - return true; - } - -}; - -} // namespace llvm - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClBitcodeMunge.h b/include/llvm/Bitcode/NaCl/NaClBitcodeMunge.h deleted file mode 100644 index 058af99bb6c..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClBitcodeMunge.h +++ /dev/null @@ -1,303 +0,0 @@ -//===- NaClBitcodeMunge.h - Bitcode Munger ----------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Test harness for generating a PNaCl bitcode memory buffer from -// an array, and parse/objdump/compress the resulting contents. -// -// Generates a bitcode memory buffer from an array containing 1 or -// more PNaCl records. Used to test errors in PNaCl bitcode. -// -// Bitcode records are modeled using arrays using the format -// specified in NaClBitcodeMungeUtils.h. -// -// Note: Since the header record doesn't have any abbreviation indices -// associated with it, one can use any value. The value will simply be -// ignored. -// -// In addition to specifying the sequence of records, one can also -// define a sequence of edits to be applied to the original sequence -// of records. This allows the same record sequence to be used in -// multiple tests. Again, see NaClBitcodeMungeUtils.h for the -// format of editing arrays. -// -// Generally, you can generate any legal/illegal record -// sequence. However, abbreviations are intimately tied to the -// internals of the bitstream writer and can't contain illegal -// data. Whenever class NaClBitcodeMunger is unable to accept illegal -// data, a corresponding "Fatal" error is generated and execution -// is terminated. -// -// ===---------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_NACL_NACLBITCODEMUNGE_H -#define LLVM_BITCODE_NACL_NACLBITCODEMUNGE_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" - -#include - -namespace llvm { - -class NaClBitCodeAbbrev; - -/// Base class to run tests on munged bitcode files. -class NaClBitcodeMunger { -public: - /// Creates a bitcode munger, based on the given array of values. - NaClBitcodeMunger(const uint64_t Records[], size_t RecordsSize, - uint64_t RecordTerminator) - : MungedBitcode(Records, RecordsSize, RecordTerminator), - RecordTerminator(RecordTerminator), - DumpResults("Error: No previous dump results!\n"), - DumpStream(nullptr), FoundErrors(false), RunAsDeathTest(false) {} - - /// Returns true if running as death test. - bool getRunAsDeathTest() const { - return RunAsDeathTest; - } - - /// Sets death test flag. When true, output will be redirected to - /// the errs() (rather than buffered) so that the test can be - /// debugged. - void setRunAsDeathTest(bool NewValue) { - RunAsDeathTest = NewValue; - } - - /// Creates MungedInput and DumpStream for running tests, based on - /// given Munges. Returns true if able to set up test. - bool setupTest(const uint64_t Munges[], size_t MungesSize, bool AddHeader); - - // TODO(kschimpf): The following function is deprecated and only - // provided until subzero is updated to use the new API that no - // longer uses test names. - bool setupTest(const char *, const uint64_t Munges[], size_t MungesSize, - bool AddHeader) { - return setupTest(Munges, MungesSize, AddHeader); - } - - /// Cleans up state after a test. Returns true if no errors found. - bool cleanupTest(); - - /// Returns the resulting string generated by the corresponding test. - const std::string &getTestResults() const { - return DumpResults; - } - - /// Returns the lines containing the given Substring, from the - /// string getTestResults(). - std::string getLinesWithSubstring(const std::string &Substring) const { - return getLinesWithTextMatch(Substring, false); - } - - /// Returns the lines starting with the given Prefix, from the string - /// getTestResults(). - std::string getLinesWithPrefix(const std::string &Prefix) const { - return getLinesWithTextMatch(Prefix, true); - } - - /// When NewValue, use error recovery when writing bitcode during - /// next test. - void setTryToRecoverOnWrite(bool NewValue) { - WriteFlags.setTryToRecover(NewValue); - } - - /// When NewValue, write bad abbreviation index into bitcode when - /// writing during next test. - void setWriteBadAbbrevIndex(bool NewValue) { - WriteFlags.setWriteBadAbbrevIndex(NewValue); - } - - /// Get access to munged bitcodes. - NaClMungedBitcode &getMungedBitcode() { - return MungedBitcode; - } - - /// Apply given munges to the munged bitcode. - void munge(const uint64_t Munges[], size_t MungesSize) { - MungedBitcode.munge(Munges, MungesSize, RecordTerminator); - } - -protected: - // The bitcode records being munged. - NaClMungedBitcode MungedBitcode; - // The value used as record terminator. - uint64_t RecordTerminator; - // The results buffer of the last dump. - std::string DumpResults; - // The memory buffer containing the munged input. - std::unique_ptr MungedInput; - // The stream containing errors and the objdump of the generated bitcode file. - raw_ostream *DumpStream; - // True if any errors were reported. - bool FoundErrors; - // The buffer for the contents of the munged input. - SmallVector MungedInputBuffer; - /// The write flags to use when writing bitcode. - NaClMungedBitcode::WriteFlags WriteFlags; - // Flag to redirect dump stream if running death test. - bool RunAsDeathTest; - - // Records that an error occurred, and returns stream to print error - // message to. - raw_ostream &Error() { - FoundErrors = true; - return getDumpStream() << "Error: "; - } - - // Returns the lines containing the given Substring, from the string - // getTestResults(). If MustBePrefix, then Substring must match at - // the beginning of the line. - std::string getLinesWithTextMatch(const std::string &Substring, - bool MustBePrefix = false) const; - - // Returns the log stream to use. When running death tests, redirect output - // to the error stream (rather than buffering in DumpStream), so that - // the output can be seen in gtest death tests. - raw_ostream &getDumpStream() const { - return RunAsDeathTest ? errs() : *DumpStream; - } -}; - -/// Class to run tests writing munged bitcode. -class NaClWriteMunger : public NaClBitcodeMunger { -public: - NaClWriteMunger(const uint64_t Records[], size_t RecordsSize, - uint64_t RecordTerminator) - : NaClBitcodeMunger(Records, RecordsSize, RecordTerminator) {} - - /// Writes munged bitcode and puts error messages into DumpResults. - /// Returns true if successful. - bool runTest(const uint64_t Munges[], size_t MungesSize); - - /// Same as above, but without any edits. - bool runTest() { - uint64_t NoMunges[] = {0}; - return runTest(NoMunges, 0); - } -}; - -/// Class to run tests for function llvm::NaClObjDump. -class NaClObjDumpMunger : public NaClBitcodeMunger { -public: - - /// Creates a bitcode munger, based on the given array of values. - NaClObjDumpMunger(const uint64_t Records[], size_t RecordsSize, - uint64_t RecordTerminator) - : NaClBitcodeMunger(Records, RecordsSize, RecordTerminator) {} - - /// Runs function NaClObjDump on the sequence of records associated - /// with the instance. The memory buffer containing the bitsequence - /// associated with the record is automatically generated, and - /// passed to NaClObjDump. If AddHeader is true, test assumes that the - /// sequence of records doesn't contain a header record, and the - /// test should add one. Arguments NoRecords and NoAssembly are - /// passed to NaClObjDump. Returns true if test succeeds without - /// errors. - bool runTestWithFlags(bool AddHeader, bool NoRecords, bool NoAssembly) { - uint64_t NoMunges[] = {0}; - return runTestWithFlags(NoMunges, 0, AddHeader, NoRecords, NoAssembly); - } - - /// Same as above except it runs function NaClObjDump with flags - /// NoRecords and NoAssembly set to false, and AddHeader set to true. - bool runTest() { - return runTestWithFlags(true, false, false); - } - - // TODO(kschimpf): The following function is deprecated and only - // provided until subzero is updated to use the new API that no - // longer uses test names. - bool runTest(const char *) { - return runTest(); - } - - /// Same as above, but only print out assembly and errors. - bool runTestForAssembly() { - return runTestWithFlags(true, true, false); - } - /// Same as above, but only generate error messages. - bool runTestForErrors() { - return runTestWithFlags(true, true, true); - } - - /// Runs function llvm::NaClObjDump on the sequence of records - /// associated with the instance. Array Munges contains the sequence - /// of edits to apply to the sequence of records when generating the - /// bitsequence in a memory buffer. This generated bitsequence is - /// then passed to NaClObjDump. TestName is the name associated - /// with the memory buffer. Arguments NoRecords and NoAssembly are - /// passed to NaClObjDump. Returns true if test succeeds without - /// errors. - bool runTestWithFlags(const uint64_t Munges[], size_t MungesSize, - bool AddHeader, bool NoRecords, bool NoAssembly); - - /// Same as above except it runs function NaClObjDump with flags - /// NoRecords and NoAssembly set to false, and AddHeader set to - /// true. - bool runTest(const uint64_t Munges[], size_t MungesSize) { - return runTestWithFlags(Munges, MungesSize, true, false, false); - } - - bool runTestForAssembly(const uint64_t Munges[], size_t MungesSize) { - return runTestWithFlags(Munges, MungesSize, true, true, false); - } - - // TODO(kschimpf): The following function is deprecated and only - // provided until subzero is updated to use the new API that no - // longer uses test names. - bool runTestForAssembly(const char *, const uint64_t Munges[], - size_t MungesSize) { - return runTestForAssembly(Munges, MungesSize); - } - - - bool runTestForErrors(const uint64_t Munges[], size_t MungesSize) { - return runTestWithFlags(Munges, MungesSize, true, true, true); - } -}; - -// Class to run tests for function NaClParseBitcodeFile. -class NaClParseBitcodeMunger : public NaClBitcodeMunger { -public: - NaClParseBitcodeMunger(const uint64_t Records[], size_t RecordsSize, - uint64_t RecordTerminator) - : NaClBitcodeMunger(Records, RecordsSize, RecordTerminator) {} - - /// Runs function llvm::NaClParseBitcodeFile, and puts error messages - /// into DumpResults. Returns true if parse is successful. - bool runTest(const uint64_t Munges[], size_t MungesSize, bool VerboseErrors); - - // Same as above, but without any edits. - bool runTest(bool VerboseErrors) { - uint64_t NoMunges[] = {0}; - return runTest(NoMunges, 0, VerboseErrors); - } -}; - -// Class to run tests for NaClBitcodeCompressor.compress(). -class NaClCompressMunger : public NaClBitcodeMunger { -public: - NaClCompressMunger(const uint64_t Records[], size_t RecordsSize, - uint64_t RecordTerminator) - : NaClBitcodeMunger(Records, RecordsSize, RecordTerminator) {} - - bool runTest(const uint64_t Munges[], size_t MungesSize); - - bool runTest() { - uint64_t NoMunges[] = {0}; - return runTest(NoMunges, 0); - } -}; - -} // end namespace llvm. - -#endif // LLVM_BITCODE_NACL_NACLBITCODEMUNGE_H diff --git a/include/llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h b/include/llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h deleted file mode 100644 index 0b749a87f38..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h +++ /dev/null @@ -1,492 +0,0 @@ -//===- NaClBitcodeMungeUtils.h - Munge bitcode records --------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines utility class NaClMungedBitcode to edit a base -// sequence of PNaCl bitcode records. It is intended to be used for -// both unit testing, and for fuzzing bitcode files. -// -// The editing actions are defined in terms of the base sequence of -// bitcode records, and do not actually modify that base sequence. As -// such, all edits are defined relative to a record index in the base -// sequence of bitcode records. Using record indices into the base -// sequence means that succeeding edits need not modify record indices -// based on the effects of preceding edits. Rather, the record index -// remains constant across all editing actions. -// -// There are two steps in creating munged bitcode. The first step -// defines the initial (base) sequence of bitcode records to be -// edited. The second is to apply editing actions to the base sequence -// of records. -// -// Defining the initial sequence of bitcode records is done by -// using NaClMungedBitcode's constructor. -// -// There are four kinds of editing actions: -// -// 1) Add a record before a (base) record index. -// 2) Add a record after a (base) record index. -// 3) Remove a record at a (base) record index. -// 4) Replace a record at a (base) record index. -// -// Each of the editing actions are defined by the methods addBefore(), -// addAfter(), remove(), and replace(). The edited sequence of records -// is defined by an iterator, and is accessible using methods begin() -// and end(). -// -// If multiple records are added before/after a record index, the -// order of the added records correspond to the order they were added. -// -// For unit testing, simple array interfaces are provided. The first -// interface defines the initial base sequence of bitcode records. The -// second interface, method munge(), defines a sequence of editing -// actions to apply to the base sequence of records. -// -// These arrays are defined using type uint64_t. A bitcode record is -// defined as a sequence of values of the form: -// -// AbbrevIndex, RecordCode, Value1, ..., ValueN , Terminator -// -// Terminator is a (user-specified) designated constant used to mark -// the end of bitcode records. A record can contain zero or more -// values. -// -// An editing action is defined as one of the following sequences of -// values: -// -// RecordIndex, AddBefore, AbbrevIndex, RecordCode, Value, ..., Terminator -// RecordIndex, AddAfter, AbbrevIndex, RecordCode, Value, ..., Terminator -// RecordIndex, Remove -// RecordIndex, Replace, AbbrevIndex, RecordCode, Value, ..., Terminator. -// -// RecordIndex defines where the action applies, relative to the base -// sequence of records. EditAction defines the editing action to -// apply. The remaining fields define an optional record associated -// with the editing action. -// -// ===---------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_NACL_NACLBITCODEMUNGEUTILS_H -#define LLVM_BITCODE_NACL_NACLBITCODEMUNGEUTILS_H - -#include "llvm/Bitcode/NaCl/NaClBitcodeParser.h" -#include "llvm/Support/MemoryBuffer.h" - -#include -#include - -namespace llvm { - -class NaClBitcodeAbbrevRecord; // bitcode record. -class NaClMungedBitcodeIter; // iterator over edited bitcode records. - -/// \brief Defines a list of bitcode records. -typedef std::vector> - NaClBitcodeRecordList; - -// TODO(kschimpf): Modify following two methods to return error_code. - -/// \brief Extracts out the records in Records, and puts them into RecordList. -/// -/// \brief RecordList[in/out] Record list to read into. -/// \brief Records Array containing data defining records. -/// \brief RecordsSize The size of array Records. -/// \brief RecordTerminator The value used to terminate records. -void readNaClBitcodeRecordList(NaClBitcodeRecordList &RecordList, - const uint64_t Records[], - size_t RecordsSize, - uint64_t RecordTerminator); - -/// Read in the list of records from binary bitcode from a memory buffer. -void readNaClBitcodeRecordList(NaClBitcodeRecordList &RecordList, - std::unique_ptr InputBuffer); - -/// Read in the list of records from textual bitcode from a memory buffer. -std::error_code readNaClTextBcRecordList( - NaClBitcodeRecordList &RecordList, - std::unique_ptr InputBuffer); - -/// Read textual bitcode records from Filename, and fill Buffer with -/// corresponding bitcode. Return error_code describing success of -/// read. Verbose (if not nullptr) is used to generate more human -/// readable error messages than the text in the returned error -/// message. -std::error_code readNaClRecordTextAndBuildBitcode( - StringRef Filename, SmallVectorImpl &Buffer, - raw_ostream *Verbose = nullptr); - -/// Write out RecordList (as text) to Buffer. Returns true when -/// successful. Error message are written to ErrStream. -bool writeNaClBitcodeRecordList(NaClBitcodeRecordList &RecordList, - SmallVectorImpl &Buffer, - raw_ostream &ErrStream); - -/// \brief An edited (i.e. munged) list of bitcode records. Edits are -/// always relative to the initial list of records. -class NaClMungedBitcode { - friend class NaClMungedBitcodeIter; - NaClMungedBitcode() = delete; - NaClMungedBitcode(const NaClMungedBitcode &) = delete; - NaClMungedBitcode &operator=(const NaClMungedBitcode &) = delete; - -public: - /// \brief Iterator over edited records. - typedef NaClMungedBitcodeIter iterator; - - /// \brief Read in initial list of records from bitcode in a memory buffer. - explicit NaClMungedBitcode(std::unique_ptr InputBuffer, - bool ReadAsText=false) - : BaseRecords(new NaClBitcodeRecordList()) { - if (ReadAsText) - readNaClTextBcRecordList(*BaseRecords, std::move(InputBuffer)); - else - readNaClBitcodeRecordList(*BaseRecords, std::move(InputBuffer)); - } - - /// \brief Initialize the list of records to be edited. - explicit NaClMungedBitcode(std::unique_ptr BaseRecords) - : BaseRecords(std::move(BaseRecords)) {} - - /// \brief Initialize the list of records to be edited using - /// array specification. - /// - /// \brief Records Array containing data defining records. - /// \brief RecordsSize The size of array Records. - /// \brief RecordTerminator The value used to terminate records. - NaClMungedBitcode(const uint64_t Records[], size_t RecordsSize, - uint64_t RecordTerminator); - - ~NaClMungedBitcode(); - - /// \brief Iterator pointing to first record in edited records. - NaClMungedBitcodeIter begin() const; - - /// \brief Iterator pointing after last record in edited records. - NaClMungedBitcodeIter end() const; - - /// \brief Insert Record immediately before the record at RecordIndex. - /// - /// \param RecordIndex The index (within BaseRecords) to add before. - /// \param Record The record to add. - void addBefore(size_t RecordIndex, NaClBitcodeAbbrevRecord &Record); - - /// \brief Insert Record after the record at RecordIndex (and after - /// any previously added after records for RecordIndex). - /// - /// \param RecordIndex The index (within BaseRecords) to add after. - /// \param Record The record to add. - void addAfter(size_t RecordIndex, NaClBitcodeAbbrevRecord &Record); - - /// \brief Remove the record at RecordIndex. Note that because - /// the record index is based on the base records, and those records - /// are not modified, this editing action effectively undoes all - /// previous remove/replace editing actions for this index. - void remove(size_t RecordIndex); - - /// \brief Replace the record at RecordIndex with Record. Note that - /// because the record index is based on the base records, and those - /// records are not modified, this editing action effectively undoes - /// all previous remove/replace editing actions for this index. - void replace(size_t RecordIndex, NaClBitcodeAbbrevRecord &Record); - - /// \brief Print out the resulting edited list of records. - void print(raw_ostream &Out) const; - - /// Defines set of possible write flags. - struct WriteFlags { - /// True if error recovery should be applied. - bool getTryToRecover() const { return TryToRecover; } - - /// Define that error recovery should be applied when writing. - void setTryToRecover(bool NewValue) { - TryToRecover = NewValue; - assert(!(TryToRecover && WriteBadAbbrevIndex)); - } - - /// True if a bad abbreviation index should be written (rather than - /// trying error recovery) so that bitcode readers can be tested for - /// this condition. - bool getWriteBadAbbrevIndex() const { return WriteBadAbbrevIndex; } - - /// Define that the first bad abbreviation index should be written, - /// and corresponding minimal context added so that the bitcode can - /// be used to test reading the erroneous written bitcode. - void setWriteBadAbbrevIndex(bool NewValue) { - WriteBadAbbrevIndex = NewValue; - assert(!(TryToRecover && WriteBadAbbrevIndex)); - } - - /// Get the stream to print errors while writing bitcode. - raw_ostream &getErrStream() const { - return ErrStream ? *ErrStream : errs(); - } - - /// Set the stream to print errors to. - void setErrStream(raw_ostream &NewValue) { - ErrStream = &NewValue; - } - - void reset() { - TryToRecover = false; - WriteBadAbbrevIndex = false; - ErrStream = nullptr; - } - - private: - bool TryToRecover = false; - bool WriteBadAbbrevIndex = false; - raw_ostream *ErrStream = nullptr; - }; - - /// Defines the results associated with writing bitcode. - struct WriteResults { - /// Number of errors generated. - size_t NumErrors = 0; - /// Number of repairs (via error recovery) that were applied. - size_t NumRepairs = 0; - /// True if a bad abbreviation index were written. - bool WroteBadAbbrevIndex = false; - }; - - /// \brief Write out the edited list of bitcode records using - /// the given buffer. - /// - /// \param Buffer The buffer to write into. - /// \param AddHeader Add header block when true. - /// \param Flags Write flags to use. - /// - /// \return Returns the results of the write. - WriteResults writeMaybeRepair( - SmallVectorImpl &Buffer, bool AddHeader, - const WriteFlags &Flags) const; - - bool write(SmallVectorImpl &Buffer, bool AddHeader, - const WriteFlags &Flags) const { - WriteResults Results = writeMaybeRepair(Buffer, AddHeader, Flags); - return Results.NumErrors == 0 - || (Flags.getTryToRecover() && Results.NumErrors == Results.NumRepairs); - } - - bool write(SmallVectorImpl &Buffer, bool AddHeader) const { - WriteFlags Flags; - return write(Buffer, AddHeader, Flags); - } - - /// \brief The types of editing actions that can be applied. - enum EditAction { - AddBefore, // Insert new record before base record at index. - AddAfter, // Insert new record after base record at index. - Remove, // Remove record at index. - Replace // Replace base record at index with new record. - }; - - /// \brief Apply a set of edits defined in the given array. - /// - /// Actions are a sequence of values, followed by a (common) - /// terminator value. Valid action sequences are: - /// - /// RecordIndex AddBefore Abbrev Code Values Terminator - /// - /// RecordIndex AddAfter Abbrev Code Values Terminator - /// - /// RecordIndex Remove - /// - /// RecordIndex Replace Abbrev Code Values Terminator - /// - /// \param Munges The array containing the edits to apply. - /// \param MungesSize The size of Munges. - /// \param Terminator The value used to terminate records in editing actions. - void munge(const uint64_t Munges[], size_t MungesSize, uint64_t Terminator); - - /// \brief Removes all editing actions and resets back to the original - /// set of base records. - void removeEdits(); - - /// Returns the unedited list of bitcode records. - const NaClBitcodeRecordList &getBaseRecords() const { - return *BaseRecords; - } - -private: - typedef std::list RecordListType; - typedef std::map InsertionsMapType; - typedef std::map ReplaceMapType; - - /// \brief The list of base records that will be edited. - std::unique_ptr BaseRecords; - // Holds map from record index to list of records added before - // the corresponding record in the list of base records. - InsertionsMapType BeforeInsertionsMap; - // Holds map from record index to the list of records added after - // the corresponding record in the list of base records. - InsertionsMapType AfterInsertionsMap; - // Holds map from record index to the record that replaces the - // corresponding record in the list of base records. Note: If the - // range is the nullptr, it corresponds to a remove instead of a - // replace. - ReplaceMapType ReplaceMap; - - // Returns the list of records associated with Index in Map. - RecordListType &at(InsertionsMapType &Map, size_t Index) { - InsertionsMapType::iterator Pos = Map.find(Index); - if (Pos == Map.end()) { - RecordListType *List = new RecordListType(); - Map.emplace(Index, List); - return *List; - } - return *Pos->second; - } - - // Creates a (heap allocated) copy of the given record. - NaClBitcodeAbbrevRecord *copy(const NaClBitcodeAbbrevRecord &Record); - - // Delete nested objects within insertions map. - void destroyInsertionsMap(NaClMungedBitcode::InsertionsMapType &Map); -}; - -/// \brief Defines a bitcode record with its associated abbreviation index. -class NaClBitcodeAbbrevRecord : public NaClBitcodeRecordData { - NaClBitcodeAbbrevRecord &operator=(NaClBitcodeAbbrevRecord &) = delete; - -public: - /// \brief The abbreviation associated with the bitcode record. - unsigned Abbrev; - - /// \brief Creates a bitcode record. - /// - /// \param Abbrev Abbreviation index associated with record. - /// \param Code The selector code of the record. - /// \param Values The values associated with the selector code. - NaClBitcodeAbbrevRecord(unsigned Abbrev, unsigned Code, - const NaClRecordVector &Values) - : NaClBitcodeRecordData(Code, Values), Abbrev(Abbrev) {} - - /// \brief Creates a copy of the given abbreviated bitcode record. - explicit NaClBitcodeAbbrevRecord(const NaClBitcodeAbbrevRecord &Rcd) - : NaClBitcodeRecordData(Rcd), Abbrev(Rcd.Abbrev) {} - - /// \brief Creates a default abbreviated bitcode record. - NaClBitcodeAbbrevRecord() : Abbrev(naclbitc::UNABBREV_RECORD) {} - - ~NaClBitcodeAbbrevRecord() {} - - /// \brief Replaces the contents of the abbreviated bitcode record with - /// the corresponding contents in the array. - /// - /// \param Values The array to get values from. - /// \param ValuesSize The length of the Values array. - /// \param Terminator The value defining the end of the record in Values. - /// \param Index The index of the first value to be used in Values. - void read(const uint64_t Values[], size_t ValuesSize, - const uint64_t Terminator, size_t &Index); - - void print(raw_ostream &out) const; -}; - -inline raw_ostream &operator<<(raw_ostream &Out, - const NaClBitcodeAbbrevRecord &Record) { - Record.print(Out); - return Out; -} - -/// \brief Defines an iterator to walk over elements of an edited -/// record list. -class NaClMungedBitcodeIter { - -public: - /// \brief Returns an iterator pointing to the first record in the - /// edited list of records. - static NaClMungedBitcodeIter begin(const NaClMungedBitcode &MungedBitcode) { - return NaClMungedBitcodeIter(MungedBitcode, 0); - } - - /// \brief Returns an iterator pointing past the last record in the - /// edited list of records. - static NaClMungedBitcodeIter end(const NaClMungedBitcode &MungedBitcode) { - return NaClMungedBitcodeIter(MungedBitcode, - MungedBitcode.BaseRecords->size()); - } - - bool operator==(const NaClMungedBitcodeIter &Iter) const; - - bool operator!=(const NaClMungedBitcodeIter &Iter) const { - return !operator==(Iter); - } - - /// \brief Advances the iterator over one record in the list of - /// edited records. - NaClMungedBitcodeIter &operator++(); - - /// \brief Returns the bitcode record the iterator is before. - NaClBitcodeAbbrevRecord &operator*(); - -private: - /// \brief Defines position of the iterator, relative to the corresponding - /// record index in the base list of records. - enum MungedPosition { - /// Processing the list of records inserted before the record - /// index of the base list of records. - InBeforeInsertions, - /// Processing the record at the given record index of the base - /// list of records. - AtIndex, - /// Processing the list of records inserted after the record index - /// of the base list of records. - InAfterInsertions, - }; - - // The edited list of records to iterate over. - const NaClMungedBitcode *MungedBitcode; - // The corresponding index, wrt to the edited list of records, that - // is being processed. - size_t Index; - // The position of the iterator wrt to Index. - MungedPosition Position; - // An iterator defining the current position within a - // BeforeInsertions or AfterInsertions list. When the iterator is - // not in the corresponding position (i.e. InBeforeInsertions or - // InAfterInsertions) this iterator is undefined. - NaClMungedBitcode::RecordListType::const_iterator InsertionsIter; - // An iterator defining the end position of the corresponding list - // of records defined by InsertionsIter. Only defined when - // InsertionsIter is defined. - NaClMungedBitcode::RecordListType::const_iterator InsertionsIterEnd; - // Dummy list to initialize InsertionsIter if no such list exists. - NaClMungedBitcode::RecordListType EmptyList; - - // \brief Defines an iterator at the beginning of the - // BeforeInsertions list associated with the given Index in - // MungedBitcode. - NaClMungedBitcodeIter(const NaClMungedBitcode &MungedBitcode, size_t Index) - : MungedBitcode(&MungedBitcode), Index(Index), - Position(InBeforeInsertions), InsertionsIter(), InsertionsIterEnd() { - placeAt(MungedBitcode.BeforeInsertionsMap, 0); - updatePosition(); - } - - // \brief Places the corresponding insertions iterator based on the - // list of records defined at Index for the given insertions Map. - void placeAt(const NaClMungedBitcode::InsertionsMapType &Map, size_t Index) { - NaClMungedBitcode::InsertionsMapType::const_iterator Pos = Map.find(Index); - if (Pos == Map.end()) { - InsertionsIter = EmptyList.end(); - InsertionsIterEnd = EmptyList.end(); - } else { - InsertionsIter = Pos->second->begin(); - InsertionsIterEnd = Pos->second->end(); - } - } - - // \brief Moves the iterator to the position of the next edited - // record. - void updatePosition(); -}; - -} // end namespace llvm. - -#endif // LLVM_BITCODE_NACL_NACLBITCODEMUNGE_H diff --git a/include/llvm/Bitcode/NaCl/NaClBitcodeParser.h b/include/llvm/Bitcode/NaCl/NaClBitcodeParser.h deleted file mode 100644 index 5efd7df19d0..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClBitcodeParser.h +++ /dev/null @@ -1,649 +0,0 @@ -//===- NaClBitcodeParser.h -----------------------------------*- C++ -*-===// -// Low-level bitcode driver to parse PNaCl bitcode files. -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Parses and processes low-level PNaCl bitcode files. Defines class -// NaClBitcodeParser. -// -// The concepts of PNaCl bitcode files are basically the same as for -// LLVM bitcode files (see http://llvm.org/docs/BitCodeFormat.html for -// details). -// -// The bitstream format is an abstract encoding of structured data, -// very similar to XML in some ways. Like XML, bitstream files contain -// tags, and nested structures, and you can parse the file without -// having to understand the tags. Unlike XML, the bitstream format is -// a binary encoding, and provides a mechanism for the file to -// self-describe "abbreviations". Abbreviations are effectively size -// optimizations for the content. -// -// The bitcode file is conceptually a sequence of "blocks", defining -// the content. Blocks contain a sequence of records and -// blocks. Nested content is defined using nested blocks. A (data) -// "record" is a tag, and a vector of (unsigned integer) values. -// -// Blocks are identified using Block IDs. Each kind of block has a -// unique block "ID". Records have two elements: -// -// a) A "code" identifying what type of record it is. -// b) A vector of "values" defining the contents of the record. -// -// The bitstream "reader" (defined in NaClBitstreamReader.h) defines -// the implementation that converts the low-level bit file into -// records and blocks. The bit stream is processed by moving a -// "cursor" over the sequence of bits. -// -// The bitstream reader assumes that each block/record is read in by -// first reading the "entry". The entry defines whether it corresponds -// to one of the following: -// -// a) At the beginning of a (possibly nested) block -// b) At the end of the current block. -// c) The input defines an abberviation. -// d) The input defines a record. -// -// An entry contains two values, a "kind" and an "ID". The kind -// defines which of the four cases above occurs. The ID provides -// identifying information on how to further process the input. For -// case (a), the ID is the identifier associated with the the block -// being processed. For case (b) and (c) the ID is ignored. For case -// (d) the ID identifies the abbreviation that should be used to parse -// the values. -// -// The class NaClBitcodeParser defines a bitcode parser that extracts -// the blocks and records, which are then processed using virtual -// callbacks. In general, you will want to implement derived classes -// for each type of block, so that the corresponding data is processed -// appropriately. -// -// The class NaClBitcodeParser parses a bitcode block, and defines a -// set of callbacks for that block, including: -// -// a) EnterBlock: What to do once we have entered the block. -// b) ProcessRecord: What to do with each parsed record. -// c) ParseBlock: Parse the (nested) block with the given ID. -// d) ExitBlock: What to do once we have finished processing the block. -// -// Note that a separate instance of NaClBitcodeParser (or a -// corresponding derived class) is created for each nested block. Each -// instance is responsible for only parsing a single block. Method -// ParseBlock creates new instances to parse nested blocks. Method -// GetEnclosingParser() can be used to refer to the parser associated -// with the enclosing block. -// -// Currently, the default processing of abbreviations is handled by -// the PNaCl bitstream reader, rather than by the parser. -// -// If you need to process abbreviations processed by the PNaCl -// bitstream reader, you must explicitly define a -// NaClBitcodeParserListener to listen (within the bitstream reader), -// and make appropriate call backs to the NaClBitcodeParser. -// The listener is glued to parsers using method SetListener. -// -// TODO(kschimpf): Define an intermediate derived class of -// NaClBitcodeParser that defines callbacks based on the actual -// structure of PNaCl bitcode files. That is, it has callbacks for -// each of the types of blocks (i.e. module, types, global variables, -// function, symbol tables etc). This derivied class can then be used -// as the base class for the bitcode reader. -// ===----------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_NACL_NACLBITCODEPARSER_H -#define LLVM_BITCODE_NACL_NACLBITCODEPARSER_H - -#include "llvm/Bitcode/NaCl/NaClBitstreamReader.h" -#include "llvm/Bitcode/NaCl/NaClBitcodeDefs.h" -#include "llvm/Support/raw_ostream.h" -#include - -namespace llvm { - -class NaClBitcodeRecord; -class NaClBitcodeParser; -class NaClBitcodeParserListener; - -// Defines the base class for data extracted from the input bitstream -// (i.e blocks and records). -class NaClBitcodeData { - void operator=(const NaClBitcodeData&) = delete; - -public: - /// Create data element to be read from input cursor. - explicit NaClBitcodeData(NaClBitstreamCursor &Cursor) - : Cursor(Cursor), StartBit(Cursor.GetCurrentBitNo()) - {} - - /// Create copy of the given data element. - explicit NaClBitcodeData(const NaClBitcodeData &Data) - : Cursor(Data.Cursor), StartBit(Data.StartBit) - {} - - /// Returns the bitstream reader being used. - NaClBitstreamReader &GetReader() const { - return *Cursor.getBitStreamReader(); - } - - /// Returns the cursor position within the bitstream. - NaClBitstreamCursor &GetCursor() const { - return Cursor; - } - - /// Returns the number of bits defined by the data. - uint64_t GetNumBits() const { - return GetCursor().GetCurrentBitNo() - StartBit; - } - - /// Returns the first bit of the stream data. - uint64_t GetStartBit() const { - return StartBit; - } - -protected: - /// Change the start bit for the data to the new value. - void SetStartBit(uint64_t NewValue) { - StartBit = NewValue; - } - -private: - // The bitstream cursor defining location within the bitcode file. - NaClBitstreamCursor &Cursor; - - // Start bit for the record. - uint64_t StartBit; -}; - -/// Models the block defined by a (begin) block record, through the -/// (end) block record. -class NaClBitcodeBlock : public NaClBitcodeData { - NaClBitcodeBlock(const NaClBitcodeBlock &) = delete; - void operator=(const NaClBitcodeBlock &) = delete; - -public: - /// Given the found (begin) block record for block BlockID, create - /// the corresponding data associated with that block. - NaClBitcodeBlock(unsigned BlockID, const NaClBitcodeRecord &Record); - - /// Create block data for block BlockID, using the input cursor. - NaClBitcodeBlock(unsigned BlockID, NaClBitstreamCursor &Cursor) - : NaClBitcodeData(Cursor), - BlockID(BlockID), - EnclosingBlock(0) - { - LocalStartBit = GetStartBit(); - } - - /// Print the contents out to the given stream. - void Print(raw_ostream& os) const; - - /// Returns pointer to the enclosing block. - const NaClBitcodeBlock *GetEnclosingBlock() const { - return EnclosingBlock; - } - - /// Returns the block ID of the block. - unsigned GetBlockID() const { - return BlockID; - } - - /// Returns the number of bits in the block associated with the - /// bitcode parser parsing this block, excluding nested blocks. - unsigned GetLocalNumBits() const { - return GetCursor().GetCurrentBitNo() - LocalStartBit; - } - -protected: - // The block ID associated with this record. - unsigned BlockID; - // The enclosing block, if defined. - const NaClBitcodeBlock *EnclosingBlock; - // Start bit for the block, updated to skip nested blocks. - uint64_t LocalStartBit; - - // Note: We friend class NaClBitcodeParser, so that it can - // update field LocalStartBit. - friend class NaClBitcodeParser; -}; - -typedef NaClBitcodeRecordVector NaClRecordVector; - -class NaClBitcodeRecordData { - NaClBitcodeRecordData &operator=(const NaClBitcodeRecordData &) = delete; -public: - NaClBitcodeRecordData(unsigned Code, const NaClRecordVector &Values) - : Code(Code), Values(Values) {} - explicit NaClBitcodeRecordData(const NaClBitcodeRecordData &Record) - : Code(Record.Code), Values(Record.Values) {} - NaClBitcodeRecordData() : Code(0) {} - // The selector code associated with the record. - unsigned Code; - // The sequence of values defining the parsed record. - NaClRecordVector Values; - - void Print(raw_ostream &strm) const; -}; - -inline raw_ostream &operator<<(raw_ostream &Strm, - const NaClBitcodeRecordData &Data) { - Data.Print(Strm); - return Strm; -} - -/// Simple container class to convert the values of the corresponding -/// read record to a simpler form, only containing values. -struct NaClBitcodeValues { -public: - NaClBitcodeValues(const NaClBitcodeRecordData &Record) - : Record(Record) {} - - size_t size() const { - return Record.Values.size()+1; - } - - uint64_t operator[](size_t index) const { - return index == 0 ? Record.Code : Record.Values[index-1]; - } - -private: - const NaClBitcodeRecordData &Record; -}; - -/// Defines the data associated with reading a block record in the -/// PNaCl bitcode stream. -class NaClBitcodeRecord : public NaClBitcodeData { -public: - /// Type for vector of values representing a record. - typedef NaClRecordVector RecordVector; - - /// Creates a bitcode record, starting at the position defined - /// by cursor. - explicit NaClBitcodeRecord(const NaClBitcodeBlock &Block) - : NaClBitcodeData(Block.GetCursor()), - Block(Block) - {} - - /// Print the contents out to the given stream. - void Print(raw_ostream& os) const; - - /// The block the record appears in. - const NaClBitcodeBlock &GetBlock() const { - return Block; - } - - /// Returns the block ID associated with the record. - unsigned GetBlockID() const { - return Block.GetBlockID(); - } - - /// Returns the kind of entry read from the input stream. - unsigned GetEntryKind() const { - return Entry.Kind; - } - - /// Returns the code value (i.e. selector) associated with the - /// record. - unsigned GetCode() const { - return Data.Code; - } - - /// Returns the EntryID (e.g. abbreviation if != - /// naclbitc::UNABBREV_RECORD) associated with the record. Note: - /// for block-enter, block-exit, and define-abbreviation, EntryID is - /// not the corresponding abbreviation. - unsigned GetEntryID() const { - return Entry.ID; - } - - /// Returns the (value) record associated with the read record. - const RecordVector &GetValues() const { - return Data.Values; - } - - /// Allows lower level access to data representing record. - const NaClBitcodeRecordData &GetRecordData() const { - return Data; - } - - /// Returns true if the record was read using an abbreviation. - bool UsedAnAbbreviation() const { - return GetEntryKind() == NaClBitstreamEntry::Record && - GetEntryID() != naclbitc::UNABBREV_RECORD; - } - - /// Returns the abbrevation index used to read the record. - /// Returns naclbitc::UNABBREV_RECORD if not applicable. - unsigned GetAbbreviationIndex() const { - return UsedAnAbbreviation() - ? GetEntryID() : static_cast(naclbitc::UNABBREV_RECORD); - } - - /// Destructively change the abbreviation ID to the given value. - void SetAbbreviationIndex(unsigned Index) { - Entry.ID = Index; - } - -protected: - // The block associated with the record. - const NaClBitcodeBlock &Block; - // The data of the record. - NaClBitcodeRecordData Data; - // The entry (i.e. value(s) preceding the record that define what - // value comes next). - NaClBitstreamEntry Entry; - -private: - // Allows class NaClBitcodeParser to read values into the - // record, thereby hiding the details of how to read values. - friend class NaClBitcodeParser; - friend class NaClBitcodeParserListener; - - /// Read bitstream entry. Defines what construct appears next in the - /// bitstream. - void ReadEntry() { - SetStartBit(GetCursor().GetCurrentBitNo()); - Entry = GetCursor(). - advance(NaClBitstreamCursor::AF_DontAutoprocessAbbrevs, 0); - } - - /// Reads in a record's values, if the entry defines a record (Must - /// be called after ReadEntry). - void ReadValues() { - Data.Values.clear(); - Data.Code = GetCursor().readRecord(Entry.ID, Data.Values); - } - - NaClBitcodeRecord(const NaClBitcodeRecord &Rcd) = delete; - void operator=(const NaClBitcodeRecord &Rcd) = delete; -}; - -inline raw_ostream &operator<<(raw_ostream &Strm, - const NaClBitcodeRecord &Record) { - Record.Print(Strm); - return Strm; -} - -/// Defines a listener to handle abbreviations within a bitcode file. -/// In particular, abbreviations and the BlockInfo block are made more -/// explicit, and then sent to the parser through virtuals -/// ProcessAbbreviation and SetBID. -class NaClBitcodeParserListener : public NaClAbbrevListener { - friend class NaClBitcodeParser; -public: - // Constructs a listener for the given parser. Note: All nested - // parsers automatically inherit this listener. - NaClBitcodeParserListener(NaClBitcodeParser *Parser) - : Parser(Parser), GlobalBlockID(naclbitc::BLOCKINFO_BLOCK_ID) { - } - - virtual ~NaClBitcodeParserListener() {} - -private: - virtual void BeginBlockInfoBlock(unsigned NumWords); - - virtual void SetBID(); - - virtual void EndBlockInfoBlock(); - - virtual void ProcessAbbreviation(NaClBitCodeAbbrev *Abbrev, - bool IsLocal); - - /// The block parser currently being listened to. - NaClBitcodeParser *Parser; - - /// The block ID to use if a global abbreviation. Note: This field is - /// updated by calls to method SetBID. - unsigned GlobalBlockID; -}; - -/// Parses a block in the PNaCl bitcode stream. -class NaClBitcodeParser { - // Allow listener privledges, so that it can update/call the parser - // using a clean API. - friend class NaClBitcodeParserListener; - - // Implements an error handler for errors in the bitstream reader. - // Redirects bitstream reader errors to corresponding parrser error - // reporting function. - class ErrorHandler : public NaClBitstreamCursor::ErrorHandler { - NaClBitcodeParser *Parser; - public: - ErrorHandler(NaClBitcodeParser *Parser, - NaClBitstreamCursor &Cursor): - NaClBitstreamCursor::ErrorHandler(Cursor), Parser(Parser) {} - LLVM_ATTRIBUTE_NORETURN - void Fatal(const std::string &ErrorMessage) const final { - Parser->FatalAt(getCurrentBitNo(), ErrorMessage); - llvm_unreachable("GCC treats noreturn virtual functions as returning"); - } - ~ErrorHandler() override {} - }; - -public: - // Creates a parser to parse the the block at the given cursor in - // the PNaCl bitcode stream. This instance is a "dummy" instance - // that starts the parser. - explicit NaClBitcodeParser(NaClBitstreamCursor &Cursor) - : EnclosingParser(0), - Block(ILLEGAL_BLOCK_ID, Cursor), - Record(Block), - Listener(0), - ErrStream(&errs()) { - std::unique_ptr - ErrHandler(new ErrorHandler(this, Cursor)); - Cursor.setErrorHandler(ErrHandler); - } - - virtual ~NaClBitcodeParser(); - - /// Reads the (top-level) block associated with the given block - /// record at the stream cursor. Returns true if unable to parse. - /// Can be called multiple times to parse multiple blocks. - bool Parse(); - - // Called once the bitstream reader has entered the corresponding - // subblock. Argument NumWords is set to the number of words in the - // corresponding subblock. - virtual void EnterBlock(unsigned /*NumWords*/) {} - - // Called when the corresponding EndBlock of the block being parsed - // is found. - virtual void ExitBlock() {} - - // Called after each record (within the block) is read (into field Record). - virtual void ProcessRecord() {} - - // Called if a SetBID record is encountered in the BlockInfo block, - // and the parser has a listener. - virtual void SetBID() {} - - // Called to process an abbreviation if the parser has a listener. - virtual void ProcessAbbreviation(unsigned /*BlockID*/, - NaClBitCodeAbbrev * /*Abbrev*/, - bool /*IsLocal*/) {} - - // Creates an instance of the NaClBitcodeParser to use to parse the - // block with the given block ID, and then call's method - // ParseThisBlock() to parse the corresponding block. Note: - // Each derived class should define it's own version of this - // method, following the pattern below. - virtual bool ParseBlock(unsigned BlockID) { - // Default implementation just builds a parser that does nothing. - NaClBitcodeParser Parser(BlockID, this); - return Parser.ParseThisBlock(); - } - - // Changes the stream to print errors to, and returns the old error stream. - // There are two use cases: - // 1) To change (from the default errs()) inside the constructor of the - // derived class. In this context, it will be used for all error - // messages for the derived class. - // 2) Temporarily modify it for a single error message. - raw_ostream &setErrStream(raw_ostream &Stream) { - raw_ostream &OldErrStream = *ErrStream; - ErrStream = &Stream; - return OldErrStream; - } - - // Called when an error occurs. BitPosition is the bit position the - // error was found, and Message is the error to report. Always - // returns true (the error return value of Parse). Level is - // the severity of the error. - virtual bool ErrorAt(naclbitc::ErrorLevel Level, uint64_t BitPosition, - const std::string &Message); - - bool ErrorAt(uint64_t BitPosition, const std::string &Message) { - return ErrorAt(naclbitc::Error, BitPosition, Message); - } - - // Called when an error occurs. Message is the error to - // report. Always returns true (the error return value of Parse). - bool Error(const std::string &Message) { - return ErrorAt(Record.GetStartBit(), Message); - } - - // Called when a fatal error occurs. BitPosition is the bit position - // the error was found, and Message is the error to report. Does not - // return. - LLVM_ATTRIBUTE_NORETURN - void FatalAt(uint64_t BitPosition, const std::string &Message) { - ErrorAt(naclbitc::Fatal, BitPosition, Message); - llvm_unreachable("Fatal errors should not return"); - } - - // Called when a fatal error occurs. Message is the error to - // report. Does not return. - LLVM_ATTRIBUTE_NORETURN - void Fatal(const std::string &Message) { - FatalAt(Record.GetStartBit(), Message); - llvm_unreachable("GCC treats noreturn virtual functions as returning"); - } - - // Generates fatal generic error message. - LLVM_ATTRIBUTE_NORETURN - void Fatal() { - Fatal("Fatal error occurred!"); - } - - // Returns the number of bits in this block, including nested blocks. - unsigned GetBlockNumBits() const { - return Block.GetNumBits(); - } - - // Returns the number of bits in this block, excluding nested blocks. - unsigned GetBlockLocalNumBits() const { - return Block.GetLocalNumBits(); - } - - /// Returns the block ID associated with the Parser. - unsigned GetBlockID() const { - return Block.GetBlockID(); - } - - NaClBitcodeBlock &GetBlock() { - return Block; - } - - /// Returns the enclosing parser of this block. - NaClBitcodeParser *GetEnclosingParser() const { - // Note: The top-level parser instance is a dummy instance - // and is not considered an enclosing parser. - return EnclosingParser->EnclosingParser ? EnclosingParser : 0; - } - - // Parses the block using the parser defined by - // ParseBlock(unsigned). Returns true if unable to parse the - // block. Note: Should only be called by virtual ParseBlock(unsigned). - bool ParseThisBlock() { - bool Results; - if (Listener) { - NaClBitcodeParser *CallingParser = Listener->Parser; - Listener->Parser = this; - Results = ParseThisBlockInternal(); - Listener->Parser = CallingParser; - } else { - Results = ParseThisBlockInternal(); - } - return Results; - } - - /// Skips the current block, assuming the parser is at the beginning - /// of the block. That is, Record.GetEntryKind() equals - /// NaClBitstreamEntry::SubBlock. Returns false if - /// successful. Otherwise returns 1. - bool SkipBlock() { - if (Record.GetEntryKind() != NaClBitstreamEntry::SubBlock) - return Error("SkipBlock on non-block record"); - return Record.GetCursor().SkipBlock(); - } - -protected: - // The containing parser. - NaClBitcodeParser *EnclosingParser; - - // The block the parser is associated with. - NaClBitcodeBlock Block; - - // The current record (within the block) being processed. - NaClBitcodeRecord Record; - - // The listener (if any) to use. - NaClBitcodeParserListener *Listener; - - // The error stream to use if non-null (uses errs() if null). - raw_ostream *ErrStream; - - // Creates a block parser to parse the block associated with the - // bitcode entry that defines the beginning of a block. This - // instance actually parses the corresponding block. - NaClBitcodeParser(unsigned BlockID, NaClBitcodeParser *EnclosingParser) - : EnclosingParser(EnclosingParser), - Block(BlockID, EnclosingParser->Record), - Record(Block), - Listener(EnclosingParser->Listener), - ErrStream(EnclosingParser->ErrStream) - {} - - /// Defines the listener for this block, and all enclosing blocks, - /// to be the given listener. Should be set in the constructor. - void SetListener(NaClBitcodeParserListener* UseListener) { - Listener = UseListener; - } - -private: - // Special constant identifying the top-level instance. - static const unsigned ILLEGAL_BLOCK_ID = UINT_MAX; - - // Parses the block. Returns true if unable to parse the - // block. Note: Should only be called by virtual ParseThisBlock. - bool ParseThisBlockInternal() { - bool Results; - if (GetBlockID() == naclbitc::BLOCKINFO_BLOCK_ID) { - Results = ParseBlockInfoInternal(); - } else { - Results = ParseBlockInternal(); - ExitBlock(); - } - return Results; - } - - // Parses a BlockInfo block, where processing is handled through - // a listener in the bitstream reader. - bool ParseBlockInfoInternal(); - - // Parses the non-BlockInfo block. Returns true if unable to parse the - // block. - bool ParseBlockInternal(); - - void operator=(const NaClBitcodeParser &Parser) = delete; - NaClBitcodeParser(const NaClBitcodeParser &Parser) = delete; - -}; - -} // namespace llvm - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClBitcodeSizeDist.h b/include/llvm/Bitcode/NaCl/NaClBitcodeSizeDist.h deleted file mode 100644 index 0155d94b65f..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClBitcodeSizeDist.h +++ /dev/null @@ -1,78 +0,0 @@ -//===-- NaClBitcodeSizeDist.h ---------------------------------------------===// -// Defines distribution maps for bitcode record sizes (arity). -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Defines distribution maps for tracking bitcode record sizes -// (arity). - -#ifndef LLVM_BITCODE_NACL_NACLBITCODESIZEDIST_H -#define LLVM_BITCODE_NACL_NACLBITCODESIZEDIST_H - -#include "llvm/Bitcode/NaCl/NaClBitcodeDist.h" -#include "llvm/Bitcode/NaCl/NaClBitcodeValueDist.h" - -namespace llvm { - -/// Collects the number of bitcode record instances with the same number -/// of elements in the vector of values, with nested value distribution maps. -class NaClBitcodeSizeDistElement : public NaClBitcodeDistElement { - NaClBitcodeSizeDistElement(const NaClBitcodeSizeDistElement&) = delete; - void operator=(const NaClBitcodeSizeDistElement&) = delete; - -public: - static bool classof(const NaClBitcodeDistElement *Element) { - return Element->getKind() >= RDE_SizeDist && - Element->getKind() < RDE_SizeDistLast; - } - - NaClBitcodeSizeDistElement() - : NaClBitcodeDistElement(RDE_SizeDist), - ValueIndexDist(NaClBitcodeDist::RecordStorage, - &NaClBitcodeValueIndexDistElement::Sentinel) { - NestedDists.push_back(&ValueIndexDist); - } - - static NaClBitcodeSizeDistElement Sentinel; - - virtual ~NaClBitcodeSizeDistElement(); - - virtual NaClBitcodeDistElement *CreateElement( - NaClBitcodeDistValue Value) const; - - virtual void GetValueList(const NaClBitcodeRecord &Record, - ValueListType &ValueList) const; - - virtual void AddRecord(const NaClBitcodeRecord &Record); - - virtual const SmallVectorImpl * - GetNestedDistributions() const; - - virtual const char *GetTitle() const; - - virtual const char *GetValueHeader() const; - - virtual void PrintRowValue(raw_ostream &Stream, - NaClBitcodeDistValue Value, - const NaClBitcodeDist *Distribution) const; - - NaClBitcodeDist &GetValueIndexDist() { - return ValueIndexDist; - } - -private: - // Nested blocks used by GetNestedDistributions. - SmallVector NestedDists; - - // The value distributions associated with records of the given size. - NaClBitcodeDist ValueIndexDist; -}; - -} - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClBitcodeSubblockDist.h b/include/llvm/Bitcode/NaCl/NaClBitcodeSubblockDist.h deleted file mode 100644 index 7729edffe42..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClBitcodeSubblockDist.h +++ /dev/null @@ -1,76 +0,0 @@ -//===-- NaClBitcodeSubblockDist.h -----------------------------------------===// -// Defines distribution maps for subblock values within an -// (externally specified) block. -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Defines the notion subblock distribution map. Shows what subblocks appear -// within a given block (defined externally to the distribution map). - -#ifndef LLVM_BITCODE_NACL_NACLBITCODESUBBLOCKDIST_H -#define LLVM_BITCODE_NACL_NACLBITCODESUBBLOCKDIST_H - -#include "llvm/Bitcode/NaCl/NaClBitcodeDist.h" - -namespace llvm { - -/// Collects the distribution of subblocks within an (externally defined) -/// block. -class NaClBitcodeSubblockDistElement : public NaClBitcodeDistElement { - NaClBitcodeSubblockDistElement(const NaClBitcodeSubblockDistElement &) - = delete; - void operator=(const NaClBitcodeSubblockDistElement&); - -public: - static bool classof(const NaClBitcodeDistElement *Element) { - return Element->getKind() >= RDE_SubblockDist && - Element->getKind() < RDE_SubblockDistLast; - } - - NaClBitcodeSubblockDistElement() - : NaClBitcodeDistElement(RDE_SubblockDist) {} - - virtual ~NaClBitcodeSubblockDistElement(); - - virtual NaClBitcodeDistElement *CreateElement( - NaClBitcodeDistValue Value) const; - - virtual const char *GetTitle() const; - - virtual const char *GetValueHeader() const; - - virtual void PrintRowValue(raw_ostream &Stream, - NaClBitcodeDistValue Value, - const NaClBitcodeDist *Distribution) const; -}; - -/// Collects the distribution of subblocks within an (externally -/// defined) block. Assumes distribution elements are instances of -/// NaClBitcodeSubblockDistElement. -class NaClBitcodeSubblockDist : public NaClBitcodeDist { - NaClBitcodeSubblockDist(const NaClBitcodeSubblockDist&) = delete; - void operator=(const NaClBitcodeSubblockDist&) = delete; - -public: - static bool classof(const NaClBitcodeDist *Dist) { - return Dist->getKind() >= RD_SubblockDist && - Dist->getKind() < RD_SubblockDistLast; - } - - static NaClBitcodeSubblockDistElement DefaultSentinal; - - NaClBitcodeSubblockDist() - : NaClBitcodeDist(BlockStorage, &DefaultSentinal, RD_SubblockDist) - {} - - virtual ~NaClBitcodeSubblockDist(); -}; - -} - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClBitcodeValueDist.h b/include/llvm/Bitcode/NaCl/NaClBitcodeValueDist.h deleted file mode 100644 index c992627f5e6..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClBitcodeValueDist.h +++ /dev/null @@ -1,182 +0,0 @@ -//===-- NaClBitcodeValueDist.h ---------------------------------------------===// -// Defines distribution maps to separate out values at each index -// in a bitcode record. -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_NACL_NACLBITCODEVALUEDIST_H -#define LLVM_BITCODE_NACL_NACLBITCODEVALUEDIST_H - -#include "llvm/Bitcode/NaCl/NaClBitcodeDist.h" - -namespace llvm { - -/// Defines the value index cutoff where we no longer track values associated -/// with specific value indices of bitcode records. -static const unsigned NaClValueIndexCutoff = 6; - -/// Defines an (inclusive) range of values in a bitcode record, -/// defined by the given pair of values. Note that values are stored -/// as ranges. For small values, each value is in a separate range, so -/// that potential constants for abbreviations can be found. For -/// larger values, values are coalesced together into multiple element -/// ranges, since we don't look for constants and are only interested -/// in the overall distribution of values. -typedef std::pair NaClValueRangeType; - -/// Models a range index. Ranges are encoded as a consecutive sequence -/// of indices, starting at zero. The actual ranges chosen to -/// represent bitcode records are internal, and is defined by function -/// GetValueRange index below. -typedef NaClBitcodeDistValue NaClValueRangeIndexType; - -/// Converts a bitcode record value to the corresponding range index that -/// contains the value. -NaClValueRangeIndexType GetNaClValueRangeIndex(NaClBitcodeDistValue Value); - -/// Converts a range index into the corresponding range of values. -NaClValueRangeType GetNaClValueRange(NaClValueRangeIndexType RangeIndex); - -/// Defines the distribution of range indices. -class NaClBitcodeValueDistElement : public NaClBitcodeDistElement { - NaClBitcodeValueDistElement(const NaClBitcodeValueDistElement&) = delete; - void operator=(const NaClBitcodeValueDistElement&) = delete; - -public: - static bool classof(const NaClBitcodeDistElement *Element) { - return Element->getKind() >= RDE_ValueDist && - Element->getKind() < RDE_ValueDistLast; - } - - NaClBitcodeValueDistElement() - : NaClBitcodeDistElement(RDE_ValueDist) - {} - - static NaClBitcodeValueDistElement Sentinel; - - virtual ~NaClBitcodeValueDistElement(); - - virtual NaClBitcodeDistElement *CreateElement( - NaClBitcodeDistValue Value) const; - - /// Returns the number of instances, normalized over the - /// range of values, using a uniform distribution. - virtual double GetImportance(NaClBitcodeDistValue Value) const; - - virtual const char *GetTitle() const; - - virtual const char *GetValueHeader() const; - - virtual void PrintRowValue(raw_ostream &Stream, - NaClBitcodeDistValue Value, - const NaClBitcodeDist *Distribution) const; -}; - -/// Defines the distribution of values for a set of value indices for -/// bitcode records. -class NaClBitcodeValueDist : public NaClBitcodeDist { - NaClBitcodeValueDist(const NaClBitcodeValueDist&) = delete; - void operator=(const NaClBitcodeValueDist&) = delete; - -public: - static bool classof(const NaClBitcodeDist *Dist) { - return Dist->getKind() >= RD_ValueDist && - Dist->getKind() < RD_ValueDistLast; - } - - /// Builds a value distribution for the given set of value indices. - /// If AllRemainingIndices is false, only value Index is considered. - /// Otherwise, builds a value distribution for all values stored in - /// record value indices >= Index. - explicit NaClBitcodeValueDist(unsigned Index, - bool AllRemainingIndices=false); - - virtual ~NaClBitcodeValueDist(); - - unsigned GetIndex() const { - return Index; - } - - bool HoldsAllRemainingIndices() const { - return AllRemainingIndices; - } - - virtual void GetValueList(const NaClBitcodeRecord &Record, - ValueListType &ValueList) const; - -private: - // The range index being tracked. - unsigned Index; - - // If true, then tracks all indices >= Index. Otherwise only Index. - bool AllRemainingIndices; -}; - -/// Defines the value distribution for each value index in corresponding -/// bitcode records. This is a helper class used to separate each element -/// in the bitcode record, so that we can determine the proper abbreviation -/// for each element. -class NaClBitcodeValueIndexDistElement : public NaClBitcodeDistElement { - NaClBitcodeValueIndexDistElement( - const NaClBitcodeValueIndexDistElement&) = delete; - void operator=( - const NaClBitcodeValueIndexDistElement&) = delete; - -public: - static bool classof(const NaClBitcodeDistElement *Element) { - return Element->getKind() <= RDE_ValueIndexDist && - Element->getKind() < RDE_ValueIndexDistLast; - } - - explicit NaClBitcodeValueIndexDistElement(unsigned Index=0) - : NaClBitcodeDistElement(RDE_ValueIndexDist), - ValueDist(Index) { - NestedDists.push_back(&ValueDist); - } - - static NaClBitcodeValueIndexDistElement Sentinel; - - virtual ~NaClBitcodeValueIndexDistElement(); - - virtual NaClBitcodeDistElement *CreateElement( - NaClBitcodeDistValue Value) const; - - virtual void GetValueList(const NaClBitcodeRecord &Record, - ValueListType &ValueList) const; - - virtual double GetImportance(NaClBitcodeDistValue Value) const; - - virtual void AddRecord(const NaClBitcodeRecord &Record); - - virtual const char *GetTitle() const; - - virtual const char *GetValueHeader() const; - - virtual void PrintRowValue(raw_ostream &Stream, - NaClBitcodeDistValue Value, - const NaClBitcodeDist *Distribution) const; - - virtual const SmallVectorImpl * - GetNestedDistributions() const; - - NaClBitcodeValueDist &GetValueDist() { - return ValueDist; - } - -private: - // Nested blocks used by GetNestedDistributions. - SmallVector NestedDists; - - // The value distribution associated with the given index. - NaClBitcodeValueDist ValueDist; -}; - -} - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClBitcodeWriterPass.h b/include/llvm/Bitcode/NaCl/NaClBitcodeWriterPass.h deleted file mode 100644 index 6a7cf71a9c7..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClBitcodeWriterPass.h +++ /dev/null @@ -1,51 +0,0 @@ -//===-- NaClBitcodeWriterPass.h - Bitcode writing pass ----------*- 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 a bitcode writing pass. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_NACL_BITCODE_WRITER_PASS_H -#define LLVM_BITCODE_NACL_BITCODE_WRITER_PASS_H - -#include "llvm/ADT/StringRef.h" - -namespace llvm { -class Module; -class ModulePass; -class raw_ostream; -class PreservedAnalyses; - -/// \brief Create and return a pass that writes the module to the specified -/// ostream. Note that this pass is designed for use with the legacy pass -/// manager. -ModulePass *createNaClBitcodeWriterPass(raw_ostream &Str); - -/// \brief Pass for writing a module of IR out to a bitcode file. -/// -/// Note that this is intended for use with the new pass manager. To construct -/// a pass for the legacy pass manager, use the function above. -class NaClBitcodeWriterPass { - raw_ostream &OS; - -public: - /// \brief Construct a bitcode writer pass around a particular output stream. - explicit NaClBitcodeWriterPass(raw_ostream &OS) : OS(OS) {} - - /// \brief Run the bitcode writer pass, and output the module to the selected - /// output stream. - PreservedAnalyses run(Module *M); - - static StringRef name() { return "NaClBitcodeWriterPass"; } -}; - -} - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClBitstreamReader.h b/include/llvm/Bitcode/NaCl/NaClBitstreamReader.h deleted file mode 100644 index 05cd91eb2aa..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClBitstreamReader.h +++ /dev/null @@ -1,688 +0,0 @@ -//===- NaClBitstreamReader.h -----------------------------------*- C++ -*-===// -// Low-level bitstream reader interface -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This header defines the BitstreamReader class. This class can be used to -// read an arbitrary bitstream, regardless of its contents. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_NACL_NACLBITSTREAMREADER_H -#define LLVM_BITCODE_NACL_NACLBITSTREAMREADER_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h" -#include "llvm/Bitcode/NaCl/NaClLLVMBitCodes.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/StreamingMemoryObject.h" -#include -#include - -namespace llvm { - -class Deserializer; - -namespace naclbitc { - -/// Returns the Bit as a Byte:BitInByte string. -std::string getBitAddress(uint64_t Bit); - -/// Severity levels for reporting errors. -enum ErrorLevel { - Warning, - Error, - Fatal -}; - -// Basic printing routine to generate the beginning of an error -// message. BitPosition is the bit position the error was found. -// Level is the severity of the error. -raw_ostream &ErrorAt(raw_ostream &Out, ErrorLevel Level, - uint64_t BitPosition); - -} // End namespace naclbitc. - -/// This class is used to read from a NaCl bitcode wire format stream, -/// maintaining information that is global to decoding the entire file. -/// While a file is being read, multiple cursors can be independently -/// advanced or skipped around within the file. These are represented by -/// the NaClBitstreamCursor class. -class NaClBitstreamReader { -public: - /// This contains information emitted to BLOCKINFO_BLOCK blocks. These - /// describe abbreviations that all blocks of the specified ID inherit. - struct BlockInfo { - unsigned BlockID; - std::vector Abbrevs; - }; -private: - friend class NaClBitstreamCursor; - - std::unique_ptr BitcodeBytes; - - std::vector BlockInfoRecords; - - /// \brief Holds the offset of the first byte after the header. - size_t InitialAddress; - - // True if filler should be added to byte align records. - bool AlignBitcodeRecords = false; - NaClBitstreamReader(const NaClBitstreamReader&) = delete; - void operator=(const NaClBitstreamReader&) = delete; - - - void initFromHeader(NaClBitcodeHeader &Header) { - InitialAddress = Header.getHeaderSize(); - AlignBitcodeRecords = Header.getAlignBitcodeRecords(); - } - -public: - /// Read stream from sequence of bytes [Start .. End) after parsing - /// the given bitcode header. - NaClBitstreamReader(const unsigned char *Start, const unsigned char *End, - NaClBitcodeHeader &Header) - : BitcodeBytes(getNonStreamedMemoryObject(Start, End)) { - initFromHeader(Header); - } - - /// Read stream from Bytes, after parsing the given bitcode header. - NaClBitstreamReader(MemoryObject *Bytes, NaClBitcodeHeader &Header) - : BitcodeBytes(Bytes) { - initFromHeader(Header); - } - - /// Read stream from bytes, starting at the given initial address. - /// Provides simple API for unit testing. - NaClBitstreamReader(MemoryObject *Bytes, size_t InitialAddress) - : BitcodeBytes(Bytes), InitialAddress(InitialAddress) { - } - - // Returns the memory object that is being read. - MemoryObject &getBitcodeBytes() { return *BitcodeBytes; } - - ~NaClBitstreamReader() { - // Free the BlockInfoRecords. - while (!BlockInfoRecords.empty()) { - BlockInfo &Info = BlockInfoRecords.back(); - // Free blockinfo abbrev info. - for (unsigned i = 0, e = static_cast(Info.Abbrevs.size()); - i != e; ++i) - Info.Abbrevs[i]->dropRef(); - BlockInfoRecords.pop_back(); - } - } - - /// \brief Returns the initial address (after the header) of the input stream. - size_t getInitialAddress() const { - return InitialAddress; - } - - //===--------------------------------------------------------------------===// - // Block Manipulation - //===--------------------------------------------------------------------===// - - /// Return true if we've already read and processed the block info block for - /// this Bitstream. We only process it for the first cursor that walks over - /// it. - bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); } - - /// If there is block info for the specified ID, return it, otherwise return - /// null. - const BlockInfo *getBlockInfo(unsigned BlockID) const { - // Common case, the most recent entry matches BlockID. - if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) - return &BlockInfoRecords.back(); - - for (unsigned i = 0, e = static_cast(BlockInfoRecords.size()); - i != e; ++i) - if (BlockInfoRecords[i].BlockID == BlockID) - return &BlockInfoRecords[i]; - return nullptr; - } - - BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { - if (const BlockInfo *BI = getBlockInfo(BlockID)) - return *const_cast(BI); - - // Otherwise, add a new record. - BlockInfoRecords.push_back(BlockInfo()); - BlockInfoRecords.back().BlockID = BlockID; - return BlockInfoRecords.back(); - } -}; - -/// When advancing through a bitstream cursor, each advance can discover a few -/// different kinds of entries: -struct NaClBitstreamEntry { - enum { - Error, // Malformed bitcode was found. - EndBlock, // We've reached the end of the current block, (or the end of the - // file, which is treated like a series of EndBlock records. - SubBlock, // This is the start of a new subblock of a specific ID. - Record // This is a record with a specific AbbrevID. - } Kind; - - unsigned ID; - - static NaClBitstreamEntry getError() { - NaClBitstreamEntry E; E.Kind = Error; return E; - } - static NaClBitstreamEntry getEndBlock() { - NaClBitstreamEntry E; E.Kind = EndBlock; return E; - } - static NaClBitstreamEntry getSubBlock(unsigned ID) { - NaClBitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E; - } - static NaClBitstreamEntry getRecord(unsigned AbbrevID) { - NaClBitstreamEntry E; E.Kind = Record; E.ID = AbbrevID; return E; - } -}; - -/// Models default view of a bitcode record. -typedef SmallVector NaClBitcodeRecordVector; - -/// Class NaClAbbrevListener is used to allow instances of class -/// NaClBitcodeParser to listen to record details when processing -/// abbreviations. The major reason for using a listener is that the -/// NaCl bitcode reader would require a major rewrite (including the -/// introduction of more overhead) if we were to lift abbreviations up -/// to the bitcode reader. That is, not only would we have to lift the -/// block processing up into the readers (i.e. many blocks in -/// NaClBitcodeReader and NaClBitcodeParser), but add many new API's -/// to allow the readers to update internals of the bit stream reader -/// appropriately. -class NaClAbbrevListener { - NaClAbbrevListener(const NaClAbbrevListener&) = delete; - void operator=(const NaClAbbrevListener&) = delete; -public: - NaClAbbrevListener() {} - virtual ~NaClAbbrevListener() {} - - /// Called to process the read abbreviation. - virtual void ProcessAbbreviation(NaClBitCodeAbbrev *Abbrev, - bool IsLocal) = 0; - - /// Called after entering block. NumWords is the number of words - /// in the block. - virtual void BeginBlockInfoBlock(unsigned NumWords) = 0; - - /// Called if a naclbitc::BLOCKINFO_CODE_SETBID record is found in - /// NaClBitstreamCursor::ReadBlockInfoBlock. - virtual void SetBID() = 0; - - /// Called just before an EndBlock record is processed by - /// NaClBitstreamCursor::ReadBlockInfoBlock - virtual void EndBlockInfoBlock() = 0; - - /// The values of the bitcode record associated with the called - /// virtual function. - NaClBitcodeRecordVector Values; - - /// Start bit for current record being processed in - /// NaClBitstreamCursor::ReadBlockInfoBlock. - uint64_t StartBit; -}; - -/// This represents a position within a bitcode file. There may be multiple -/// independent cursors reading within one bitstream, each maintaining their -/// own local state. -/// -/// Unlike iterators, NaClBitstreamCursors are heavy-weight objects -/// that should not be passed by value. -class NaClBitstreamCursor { -public: - /// This class handles errors in the bitstream reader. Redirects - /// fatal error messages to virtual method Fatal. - class ErrorHandler { - ErrorHandler(const ErrorHandler &) = delete; - ErrorHandler &operator=(const ErrorHandler &) = delete; - public: - explicit ErrorHandler(NaClBitstreamCursor &Cursor) : Cursor(Cursor) {} - LLVM_ATTRIBUTE_NORETURN - virtual void Fatal(const std::string &ErrorMessage) const; - virtual ~ErrorHandler() {} - uint64_t getCurrentBitNo() const { - return Cursor.GetCurrentBitNo(); - } - private: - NaClBitstreamCursor &Cursor; - }; - -private: - friend class Deserializer; - NaClBitstreamReader *BitStream; - size_t NextChar; - // The current error handler for the bitstream reader. - std::unique_ptr ErrHandler; - - // The size of the bitcode. 0 if we don't know it yet. - size_t Size; - - /// This is the current data we have pulled from the stream but have not - /// returned to the client. This is specifically and intentionally defined to - /// follow the word size of the host machine for efficiency. We use word_t in - /// places that are aware of this to make it perfectly explicit what is going - /// on. - typedef size_t word_t; - word_t CurWord; - - /// This is the number of bits in CurWord that are valid. This - /// is always from [0...bits_of(word_t)-1] inclusive. - unsigned BitsInCurWord; - - /// This is the declared size of code values used for the current - /// block, in bits. - NaClBitcodeSelectorAbbrev CurCodeSize; - - /// Abbrevs installed in this block. - std::vector CurAbbrevs; - - struct Block { - NaClBitcodeSelectorAbbrev PrevCodeSize; - std::vector PrevAbbrevs; - Block() : PrevCodeSize() {} - explicit Block(const NaClBitcodeSelectorAbbrev& PCS) - : PrevCodeSize(PCS) {} - }; - - /// This tracks the codesize of parent blocks. - SmallVector BlockScope; - - NaClBitstreamCursor(const NaClBitstreamCursor &) = delete; - NaClBitstreamCursor &operator=(const NaClBitstreamCursor &) = delete; - -public: - NaClBitstreamCursor() : ErrHandler(new ErrorHandler(*this)) { - init(nullptr); - } - - explicit NaClBitstreamCursor(NaClBitstreamReader &R) - : ErrHandler(new ErrorHandler(*this)) { init(&R); } - - void init(NaClBitstreamReader *R) { - freeState(); - BitStream = R; - NextChar = (BitStream == nullptr) ? 0 : BitStream->getInitialAddress(); - Size = 0; - BitsInCurWord = 0; - } - - ~NaClBitstreamCursor() { - freeState(); - } - - void freeState(); - - // Replaces the current bitstream error handler with the new - // handler. Takes ownership of the new handler and deletes it when - // it is no longer needed. - void setErrorHandler(std::unique_ptr &NewHandler) { - ErrHandler = std::move(NewHandler); - } - - bool canSkipToPos(size_t pos) const { - // pos can be skipped to if it is a valid address or one byte past the end. - return pos == 0 || BitStream->getBitcodeBytes().isValidAddress( - static_cast(pos - 1)); - } - - bool AtEndOfStream() { - if (BitsInCurWord != 0) - return false; - if (Size != 0) - return Size == NextChar; - fillCurWord(); - return BitsInCurWord == 0; - } - - /// Return the number of bits used to encode an abbrev #. - unsigned getAbbrevIDWidth() const { return CurCodeSize.NumBits; } - - /// Return the bit # of the bit we are reading. - uint64_t GetCurrentBitNo() const { - return NextChar*CHAR_BIT - BitsInCurWord; - } - - NaClBitstreamReader *getBitStreamReader() { - return BitStream; - } - const NaClBitstreamReader *getBitStreamReader() const { - return BitStream; - } - - /// Returns the current bit address (string) of the bit cursor. - std::string getCurrentBitAddress() const { - return naclbitc::getBitAddress(GetCurrentBitNo()); - } - - /// Flags that modify the behavior of advance(). - enum { - /// If this flag is used, the advance() method does not automatically pop - /// the block scope when the end of a block is reached. - AF_DontPopBlockAtEnd = 1, - - /// If this flag is used, abbrev entries are returned just like normal - /// records. - AF_DontAutoprocessAbbrevs = 2 - }; - - /// Advance the current bitstream, returning the next entry in the stream. - /// Use the given abbreviation listener (if provided). - NaClBitstreamEntry advance(unsigned Flags, NaClAbbrevListener *Listener) { - while (1) { - unsigned Code = ReadCode(); - if (Code == naclbitc::END_BLOCK) { - // Pop the end of the block unless Flags tells us not to. - if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd()) - return NaClBitstreamEntry::getError(); - return NaClBitstreamEntry::getEndBlock(); - } - - if (Code == naclbitc::ENTER_SUBBLOCK) - return NaClBitstreamEntry::getSubBlock(ReadSubBlockID()); - - if (Code == naclbitc::DEFINE_ABBREV && - !(Flags & AF_DontAutoprocessAbbrevs)) { - // We read and accumulate abbrev's, the client can't do anything with - // them anyway. - ReadAbbrevRecord(true, Listener); - continue; - } - - return NaClBitstreamEntry::getRecord(Code); - } - } - - /// This is a convenience function for clients that don't expect any - /// subblocks. This just skips over them automatically. - NaClBitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) { - while (1) { - // If we found a normal entry, return it. - NaClBitstreamEntry Entry = advance(Flags, 0); - if (Entry.Kind != NaClBitstreamEntry::SubBlock) - return Entry; - - // If we found a sub-block, just skip over it and check the next entry. - if (SkipBlock()) - return NaClBitstreamEntry::getError(); - } - } - - /// Reset the stream to the specified bit number. - void JumpToBit(uint64_t BitNo) { - uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1); - unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); - if (!canSkipToPos(ByteNo)) - reportInvalidJumpToBit(BitNo); - - // Move the cursor to the right word. - NextChar = ByteNo; - BitsInCurWord = 0; - - // Skip over any bits that are already consumed. - if (WordBitNo) - Read(WordBitNo); - } - - void fillCurWord() { - assert(Size == 0 || NextChar < (unsigned)Size); - - // Read the next word from the stream. - uint8_t Array[sizeof(word_t)] = {0}; - - uint64_t BytesRead = - BitStream->getBitcodeBytes().readBytes(Array, sizeof(Array), NextChar); - - // If we run out of data, stop at the end of the stream. - if (BytesRead == 0) { - Size = NextChar; - return; - } - - CurWord = - support::endian::read( - Array); - NextChar += BytesRead; - BitsInCurWord = BytesRead * 8; - } - - word_t Read(unsigned NumBits) { - static const unsigned BitsInWord = sizeof(word_t) * 8; - - assert(NumBits && NumBits <= BitsInWord && - "Cannot return zero or more than BitsInWord bits!"); - - static const unsigned Mask = sizeof(word_t) > 4 ? 0x3f : 0x1f; - - // If the field is fully contained by CurWord, return it quickly. - if (BitsInCurWord >= NumBits) { - word_t R = CurWord & (~word_t(0) >> (BitsInWord - NumBits)); - - // Use a mask to avoid undefined behavior. - CurWord >>= (NumBits & Mask); - - BitsInCurWord -= NumBits; - return R; - } - - word_t R = BitsInCurWord ? CurWord : 0; - unsigned BitsLeft = NumBits - BitsInCurWord; - - fillCurWord(); - - // If we run out of data, stop at the end of the stream. - if (BitsLeft > BitsInCurWord) - return 0; - - word_t R2 = CurWord & (~word_t(0) >> (BitsInWord - BitsLeft)); - - // Use a mask to avoid undefined behavior. - CurWord >>= (BitsLeft & Mask); - - BitsInCurWord -= BitsLeft; - - R |= R2 << (NumBits - BitsLeft); - - return R; - } - - uint32_t ReadVBR(unsigned NumBits) { - uint32_t Piece = Read(NumBits); - if ((Piece & (1U << (NumBits-1))) == 0) - return Piece; - - uint32_t Result = 0; - unsigned NextBit = 0; - while (1) { - Result |= (Piece & ((1U << (NumBits-1))-1)) << NextBit; - - if ((Piece & (1U << (NumBits-1))) == 0) - return Result; - - NextBit += NumBits-1; - Piece = Read(NumBits); - } - } - - // Read a VBR that may have a value up to 64-bits in size. The chunk size of - // the VBR must still be <= 32 bits though. - uint64_t ReadVBR64(unsigned NumBits) { - uint32_t Piece = Read(NumBits); - if ((Piece & (1U << (NumBits-1))) == 0) - return uint64_t(Piece); - - uint64_t Result = 0; - unsigned NextBit = 0; - while (1) { - Result |= uint64_t(Piece & ((1U << (NumBits-1))-1)) << NextBit; - - if ((Piece & (1U << (NumBits-1))) == 0) - return Result; - - NextBit += NumBits-1; - Piece = Read(NumBits); - } - } - -private: - void SkipToByteBoundary() { - unsigned BitsToSkip = BitsInCurWord % CHAR_BIT; - if (BitsToSkip) { - CurWord >>= BitsToSkip; - BitsInCurWord -= BitsToSkip; - } - } - - void SkipToByteBoundaryIfAligned() { - if (BitStream->AlignBitcodeRecords) - SkipToByteBoundary(); - } - - void SkipToFourByteBoundary() { - // If word_t is 64-bits and if we've read less than 32 bits, just dump - // the bits we have up to the next 32-bit boundary. - if (sizeof(word_t) > 4 && - BitsInCurWord >= 32) { - CurWord >>= BitsInCurWord-32; - BitsInCurWord = 32; - return; - } - - BitsInCurWord = 0; - } -public: - - unsigned ReadCode() { - return CurCodeSize.IsFixed - ? Read(CurCodeSize.NumBits) - : ReadVBR(CurCodeSize.NumBits); - } - - // Block header: - // [ENTER_SUBBLOCK, blockid, newcodelen, , blocklen] - - /// Having read the ENTER_SUBBLOCK code, read the BlockID for the block. - unsigned ReadSubBlockID() { - return ReadVBR(naclbitc::BlockIDWidth); - } - - /// Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip over the body - /// of this block. If the block record is malformed, return true. - bool SkipBlock() { - // Read and ignore the codelen value. Since we are skipping this block, we - // don't care what code widths are used inside of it. - ReadVBR(naclbitc::CodeLenWidth); - SkipToFourByteBoundary(); - unsigned NumFourBytes = Read(naclbitc::BlockSizeWidth); - - // Check that the block wasn't partially defined, and that the offset isn't - // bogus. - size_t SkipTo = GetCurrentBitNo() + NumFourBytes*4*8; - if (AtEndOfStream() || !canSkipToPos(SkipTo/8)) - return true; - - JumpToBit(SkipTo); - return false; - } - - /// Having read the ENTER_SUBBLOCK abbrevid, enter the block, and return true - /// if the block has an error. - bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = nullptr); - - bool ReadBlockEnd() { - if (BlockScope.empty()) return true; - - // Block tail: - // [END_BLOCK, ] - SkipToFourByteBoundary(); - - popBlockScope(); - return false; - } - -private: - - void popBlockScope() { - CurCodeSize = BlockScope.back().PrevCodeSize; - - // Delete abbrevs from popped scope. - for (unsigned i = 0, e = static_cast(CurAbbrevs.size()); - i != e; ++i) - CurAbbrevs[i]->dropRef(); - - BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); - BlockScope.pop_back(); - } - - //===--------------------------------------------------------------------===// - // Record Processing - //===--------------------------------------------------------------------===// - -private: - // Returns abbreviation encoding associated with Value. - NaClBitCodeAbbrevOp::Encoding getEncoding(uint64_t Value); - - void skipAbbreviatedField(const NaClBitCodeAbbrevOp &Op); - - // Reads the next Value using the abbreviation Op. Returns true only - // if Op is an array (and sets Value to the number of elements in the - // array). - inline bool readRecordAbbrevField(const NaClBitCodeAbbrevOp &Op, - uint64_t &Value); - - // Reads and returns the next value using the abbreviation Op, - // assuming Op appears after an array abbreviation. - inline uint64_t readArrayAbbreviatedField(const NaClBitCodeAbbrevOp &Op); - - // Reads the array abbreviation Op, NumArrayElements times, putting - // the read values in Vals. - inline void readArrayAbbrev(const NaClBitCodeAbbrevOp &Op, - unsigned NumArrayElements, - SmallVectorImpl &Vals); - - // Reports that that abbreviation Index is not valid. - void reportInvalidAbbrevNumber(unsigned Index) const; - - // Reports that jumping to Bit is not valid. - void reportInvalidJumpToBit(uint64_t Bit) const; - -public: - - /// Return the abbreviation for the specified AbbrevId. - const NaClBitCodeAbbrev *getAbbrev(unsigned AbbrevID) const { - unsigned AbbrevNo = AbbrevID-naclbitc::FIRST_APPLICATION_ABBREV; - if (AbbrevNo >= CurAbbrevs.size()) - reportInvalidAbbrevNumber(AbbrevID); - return CurAbbrevs[AbbrevNo]; - } - - /// Read the current record and discard it. - void skipRecord(unsigned AbbrevID); - - unsigned readRecord(unsigned AbbrevID, SmallVectorImpl &Vals); - - //===--------------------------------------------------------------------===// - // Abbrev Processing - //===--------------------------------------------------------------------===// - // IsLocal indicates where the abbreviation occurs. If it is in the - // BlockInfo block, IsLocal is false. In all other cases, IsLocal is - // true. - void ReadAbbrevRecord(bool IsLocal, - NaClAbbrevListener *Listener); - - // Skips over an abbreviation record. Duplicates code of ReadAbbrevRecord, - // except that no abbreviation is built. - void SkipAbbrevRecord(); - - bool ReadBlockInfoBlock(NaClAbbrevListener *Listener); -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClBitstreamWriter.h b/include/llvm/Bitcode/NaCl/NaClBitstreamWriter.h deleted file mode 100644 index 39a5009c865..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClBitstreamWriter.h +++ /dev/null @@ -1,553 +0,0 @@ -//===- NaClBitstreamWriter.h - NaCl bitstream writer ------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This header defines the BitstreamWriter class. This class can be used to -// write an arbitrary bitstream, regardless of its contents. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_NACL_NACLBITSTREAMWRITER_H -#define LLVM_BITCODE_NACL_NACLBITSTREAMWRITER_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Bitcode/NaCl/NaClBitCodes.h" -#include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h" -#include - -namespace llvm { - -class NaClBitstreamWriter { - SmallVectorImpl &Out; - - /// CurBit - Always between 0 and 31 inclusive, specifies the next bit to use. - unsigned CurBit; - - /// CurValue - The current value. Only bits < CurBit are valid. - uint32_t CurValue; - - /// CurCodeSize - This is the declared size of code values used for the - /// current block, in bits. - NaClBitcodeSelectorAbbrev CurCodeSize; - - /// BlockInfoCurBID - When emitting a BLOCKINFO_BLOCK, this is the currently - /// selected BLOCK ID. - unsigned BlockInfoCurBID; - - /// CurAbbrevs - Abbrevs installed at in this block. - std::vector CurAbbrevs; - - struct Block { - const NaClBitcodeSelectorAbbrev PrevCodeSize; - const unsigned StartSizeWord; - std::vector PrevAbbrevs; - const unsigned AbbreviationIndexLimit; - Block(const NaClBitcodeSelectorAbbrev& PCS, unsigned SSW, - unsigned AbbreviationIndexLimit) - : PrevCodeSize(PCS), StartSizeWord(SSW), - AbbreviationIndexLimit(AbbreviationIndexLimit) {} - }; - - /// BlockScope - This tracks the current blocks that we have entered. - std::vector BlockScope; - - /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. - /// These describe abbreviations that all blocks of the specified ID inherit. - struct BlockInfo { - unsigned BlockID; - std::vector Abbrevs; - }; - std::vector BlockInfoRecords; - - // True if filler should be added to byte align records. - bool AlignBitcodeRecords = false; - - /// AbbrevValues - Wrapper class that allows the bitstream writer to - /// prefix a code to the set of values, associated with a record to - /// emit, without having to destructively change the contents of - /// values. - template - struct AbbrevValues { - AbbrevValues(uintty Code, const SmallVectorImpl &Values) - : Code(Code), Values(Values) {} - - size_t size() const { - return Values.size() + 1; - } - - uintty operator[](size_t Index) const { - return Index == 0 ? Code : Values[Index-1]; - } - - private: - // The code to use (if not DONT_USE_CODE). - uintty Code; - const SmallVectorImpl &Values; - }; - -public: - // BackpatchWord - Backpatch a 32-bit word in the output with the specified - // value. - void BackpatchWord(unsigned ByteNo, unsigned NewWord) { - Out[ByteNo++] = (unsigned char)(NewWord >> 0); - Out[ByteNo++] = (unsigned char)(NewWord >> 8); - Out[ByteNo++] = (unsigned char)(NewWord >> 16); - Out[ByteNo ] = (unsigned char)(NewWord >> 24); - } - -private: - void WriteByte(unsigned char Value) { - Out.push_back(Value); - } - - void WriteWord(unsigned Value) { - unsigned char Bytes[4] = { - (unsigned char)(Value >> 0), - (unsigned char)(Value >> 8), - (unsigned char)(Value >> 16), - (unsigned char)(Value >> 24) }; - Out.append(&Bytes[0], &Bytes[4]); - } - - unsigned GetBufferOffset() const { - return Out.size(); - } - - unsigned GetWordIndex() const { - unsigned Offset = GetBufferOffset(); - assert((Offset & 3) == 0 && "Not 32-bit aligned"); - return Offset / 4; - } - -public: - explicit NaClBitstreamWriter(SmallVectorImpl &O) - : Out(O), CurBit(0), CurValue(0), CurCodeSize() {} - - ~NaClBitstreamWriter() { - assert(CurBit == 0 && "Unflushed data remaining"); - assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance"); - - // Free the BlockInfoRecords. - while (!BlockInfoRecords.empty()) { - BlockInfo &Info = BlockInfoRecords.back(); - // Free blockinfo abbrev info. - for (unsigned i = 0, e = static_cast(Info.Abbrevs.size()); - i != e; ++i) - Info.Abbrevs[i]->dropRef(); - BlockInfoRecords.pop_back(); - } - } - - void initFromHeader(const NaClBitcodeHeader &Header) { - AlignBitcodeRecords = Header.getAlignBitcodeRecords(); - } - - /// \brief Retrieve the current position in the stream, in bits. - uint64_t GetCurrentBitNo() const { return GetBufferOffset() * 8 + CurBit; } - - /// \brief Returns the maximum abbreviation index allowed for the - /// current block. - size_t getMaxCurAbbrevIndex() const { - return CurAbbrevs.size() + naclbitc::DEFAULT_MAX_ABBREV; - } - - //===--------------------------------------------------------------------===// - // Basic Primitives for emitting bits to the stream. - //===--------------------------------------------------------------------===// - - // Max Number of bits that can be written using Emit. - static const unsigned MaxEmitNumBits = 32; - - void Emit(uint32_t Val, unsigned NumBits) { - assert(NumBits && NumBits <= MaxEmitNumBits && "Invalid value size!"); - assert((Val & - ~(~0U >> (MaxEmitNumBits-NumBits))) == 0 && "High bits set!"); - CurValue |= Val << CurBit; - if (CurBit + NumBits < MaxEmitNumBits) { - CurBit += NumBits; - return; - } - - // Add the current word. - WriteWord(CurValue); - - if (CurBit) - CurValue = Val >> (MaxEmitNumBits-CurBit); - else - CurValue = 0; - CurBit = (CurBit+NumBits) & (MaxEmitNumBits-1); - } - - void Emit64(uint64_t Val, unsigned NumBits) { - while (NumBits > MaxEmitNumBits) { - Emit((uint32_t)Val, MaxEmitNumBits); - Val >>= MaxEmitNumBits; - NumBits -= MaxEmitNumBits; - } - Emit((uint32_t)Val, NumBits); - } - - void flushToByte() { - unsigned BitsToFlush = (32 - CurBit) % CHAR_BIT; - if (BitsToFlush) - Emit(0, BitsToFlush); - } - - void flushToByteIfAligned() { - if (AlignBitcodeRecords) - flushToByte(); - } - - void FlushToWord() { - if (CurBit) { - WriteWord(CurValue); - CurBit = 0; - CurValue = 0; - } - } - - void EmitVBR(uint32_t Val, unsigned NumBits) { - assert(NumBits <= 32 && "Too many bits to emit!"); - assert(NumBits > 1 && "Too few bits to emit!"); - uint32_t Threshold = 1U << (NumBits-1); - - // Emit the bits with VBR encoding, NumBits-1 bits at a time. - while (Val >= Threshold) { - Emit((Val & ((1 << (NumBits-1))-1)) | (1 << (NumBits-1)), NumBits); - Val >>= NumBits-1; - } - - Emit(Val, NumBits); - } - - void EmitVBR64(uint64_t Val, unsigned NumBits) { - assert(NumBits <= 32 && "Too many bits to emit!"); - assert(NumBits > 1 && "Too few bits to emit!"); - if ((uint32_t)Val == Val) - return EmitVBR((uint32_t)Val, NumBits); - - uint32_t Threshold = 1U << (NumBits-1); - - // Emit the bits with VBR encoding, NumBits-1 bits at a time. - while (Val >= Threshold) { - Emit(((uint32_t)Val & ((1 << (NumBits-1))-1)) | - (1 << (NumBits-1)), NumBits); - Val >>= NumBits-1; - } - - Emit((uint32_t)Val, NumBits); - } - - /// EmitCode - Emit the specified code. - void EmitCode(unsigned Val) { - if (CurCodeSize.IsFixed) - Emit(Val, CurCodeSize.NumBits); - else - EmitVBR(Val, CurCodeSize.NumBits); - } - - //===--------------------------------------------------------------------===// - // Block Manipulation - //===--------------------------------------------------------------------===// - - /// getBlockInfo - If there is block info for the specified ID, return it, - /// otherwise return null. - BlockInfo *getBlockInfo(unsigned BlockID) { - // Common case, the most recent entry matches BlockID. - if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) - return &BlockInfoRecords.back(); - - for (unsigned i = 0, e = static_cast(BlockInfoRecords.size()); - i != e; ++i) - if (BlockInfoRecords[i].BlockID == BlockID) - return &BlockInfoRecords[i]; - return 0; - } - -private: - // Enter block using CodeLen bits to read the size of the code - // selector associated with the block. - void EnterSubblock(unsigned BlockID, - const NaClBitcodeSelectorAbbrev& CodeLen, - BlockInfo *Info) { - // Block header: - // [ENTER_SUBBLOCK, blockid, newcodelen, , blocklen] - EmitCode(naclbitc::ENTER_SUBBLOCK); - EmitVBR(BlockID, naclbitc::BlockIDWidth); - assert(CodeLen.IsFixed && "Block codelens must be fixed"); - EmitVBR(CodeLen.NumBits, naclbitc::CodeLenWidth); - FlushToWord(); - - unsigned BlockSizeWordIndex = GetWordIndex(); - NaClBitcodeSelectorAbbrev OldCodeSize(CurCodeSize); - - // Emit a placeholder, which will be replaced when the block is popped. - Emit(0, naclbitc::BlockSizeWidth); - - CurCodeSize = CodeLen; - - // Push the outer block's abbrev set onto the stack, start out with an - // empty abbrev set. - BlockScope.push_back(Block(OldCodeSize, BlockSizeWordIndex, - 1 << CodeLen.NumBits)); - BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); - - // If there is a blockinfo for this BlockID, add all the predefined abbrevs - // to the abbrev list. - if (Info) { - for (unsigned i = 0, e = static_cast(Info->Abbrevs.size()); - i != e; ++i) { - CurAbbrevs.push_back(Info->Abbrevs[i]); - Info->Abbrevs[i]->addRef(); - } - } - } - -public: - /// \brief Enter block using CodeLen bits to read the size of the code - /// selector associated with the block. - void EnterSubblock(unsigned BlockID, - const NaClBitcodeSelectorAbbrev& CodeLen) { - EnterSubblock(BlockID, CodeLen, getBlockInfo(BlockID)); - } - - /// \brief Enter block, using a code length based on the number of - /// (global) BlockInfo entries defined for the block. Note: This - /// should be used only if the block doesn't define any local abbreviations. - void EnterSubblock(unsigned BlockID) { - BlockInfo *Info = getBlockInfo(BlockID); - size_t NumAbbrevs = Info ? Info->Abbrevs.size() : 0; - NaClBitcodeSelectorAbbrev DefaultCodeLen( - naclbitc::DEFAULT_MAX_ABBREV+NumAbbrevs); - EnterSubblock(BlockID, DefaultCodeLen, Info); - } - - /// \brief Enter block with the given number of abbreviations. - void EnterSubblock(unsigned BlockID, unsigned NumAbbrev) { - NaClBitcodeSelectorAbbrev CodeLenAbbrev(NumAbbrev); - EnterSubblock(BlockID, CodeLenAbbrev); - } - - void ExitBlock() { - assert(!BlockScope.empty() && "Block scope imbalance!"); - - // Delete all abbrevs. - for (unsigned i = 0, e = static_cast(CurAbbrevs.size()); - i != e; ++i) - CurAbbrevs[i]->dropRef(); - - const Block &B = BlockScope.back(); - - // Block tail: - // [END_BLOCK, ] - EmitCode(naclbitc::END_BLOCK); - FlushToWord(); - - // Compute the size of the block, in words, not counting the size field. - unsigned SizeInWords = GetWordIndex() - B.StartSizeWord - 1; - unsigned ByteNo = B.StartSizeWord*4; - - // Update the block size field in the header of this sub-block. - BackpatchWord(ByteNo, SizeInWords); - - // Restore the inner block's code size and abbrev table. - CurCodeSize = B.PrevCodeSize; - BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); - BlockScope.pop_back(); - } - - //===--------------------------------------------------------------------===// - // Record Emission - //===--------------------------------------------------------------------===// - -private: - /// EmitAbbreviatedField - Emit a single scalar field value with the specified - /// encoding. - template - void EmitAbbreviatedField(const NaClBitCodeAbbrevOp &Op, uintty V) { - switch (Op.getEncoding()) { - case NaClBitCodeAbbrevOp::Literal: - // This is a no-op, since the abbrev specifies the literal to use. - assert(V == Op.getValue() && "Invalid abbrev for record!"); - break; - case NaClBitCodeAbbrevOp::Fixed: - if (Op.getValue()) - Emit((unsigned)V, (unsigned)Op.getValue()); - break; - case NaClBitCodeAbbrevOp::VBR: - if (Op.getValue()) - EmitVBR64(V, (unsigned)Op.getValue()); - break; - case NaClBitCodeAbbrevOp::Array: - report_fatal_error("Not to be used with array abbreviation op!"); - case NaClBitCodeAbbrevOp::Char6: - Emit(NaClBitCodeAbbrevOp::EncodeChar6((char)V), 6); - break; - } - } - - /// EmitRecordWithAbbrevImpl - This is the core implementation of the record - /// emission code. - template - void EmitRecordWithAbbrevImpl(unsigned Abbrev, - const AbbrevValues &Vals) { - const NaClBitCodeAbbrev *Abbv = getAbbreviation(Abbrev); - assert(Abbv && "Abbreviation index is invalid"); - - EmitCode(Abbrev); - - unsigned RecordIdx = 0; - for (unsigned i = 0, e = static_cast(Abbv->getNumOperandInfos()); - i != e; ++i) { - const NaClBitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); - if (Op.getEncoding() == NaClBitCodeAbbrevOp::Array) { - // Array case. - assert(i+2 == e && "array op not second to last?"); - const NaClBitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i); - - // Emit a vbr6 to indicate the number of elements present. - EmitVBR(static_cast(Vals.size()-RecordIdx), 6); - - // Emit each field. - for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx) - EmitAbbreviatedField(EltEnc, Vals[RecordIdx]); - } else { - assert(RecordIdx < Vals.size() && "Invalid abbrev/record"); - EmitAbbreviatedField(Op, Vals[RecordIdx]); - ++RecordIdx; - } - } - assert(RecordIdx == Vals.size() && "Not all record operands emitted!"); - } - -public: - - /// Returns a pointer to the abbreviation currently associated with - /// the abbreviation index. Returns nullptr if no such abbreviation. - const NaClBitCodeAbbrev *getAbbreviation(unsigned Index) const { - if (Index < naclbitc::FIRST_APPLICATION_ABBREV) - return nullptr; - if (Index >= BlockScope.back().AbbreviationIndexLimit) - return nullptr; - unsigned AbbrevNo = Index - naclbitc::FIRST_APPLICATION_ABBREV; - if (AbbrevNo >= CurAbbrevs.size()) - return nullptr; - return CurAbbrevs[AbbrevNo]; - } - - /// EmitRecord - Emit the specified record to the stream, using an abbrev if - /// we have one to compress the output. - template - void EmitRecord(unsigned Code, const SmallVectorImpl &Vals, - unsigned Abbrev = 0) { - if (!Abbrev) { - // If we don't have an abbrev to use, emit this in its fully unabbreviated - // form. - EmitCode(naclbitc::UNABBREV_RECORD); - EmitVBR(Code, 6); - EmitVBR(static_cast(Vals.size()), 6); - for (unsigned i = 0, e = static_cast(Vals.size()); i != e; ++i) - EmitVBR64(Vals[i], 6); - flushToByteIfAligned(); - return; - } - - // combine code and values, and then emit. - AbbrevValues AbbrevVals(Code, Vals); - EmitRecordWithAbbrevImpl(Abbrev, AbbrevVals); - flushToByteIfAligned(); - } - - //===--------------------------------------------------------------------===// - // Abbrev Emission - //===--------------------------------------------------------------------===// - -private: - // Emit the abbreviation as a DEFINE_ABBREV record. - void EncodeAbbrev(NaClBitCodeAbbrev *Abbv) { - EmitCode(naclbitc::DEFINE_ABBREV); - EmitVBR(Abbv->getNumOperandInfos(), 5); - for (unsigned i = 0, e = static_cast(Abbv->getNumOperandInfos()); - i != e; ++i) { - const NaClBitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); - bool IsLiteral = Op.isLiteral(); - Emit(IsLiteral, 1); - if (IsLiteral) { - EmitVBR64(Op.getValue(), 8); - } else { - Emit(Op.getEncoding(), 3); - if (Op.hasValue()) - EmitVBR64(Op.getValue(), 5); - } - } - flushToByteIfAligned(); - } -public: - - /// EmitAbbrev - This emits an abbreviation to the stream. Note that this - /// method takes ownership of the specified abbrev. - unsigned EmitAbbrev(NaClBitCodeAbbrev *Abbv) { - assert(Abbv->isValid() && "Can't emit invalid abbreviation!"); - // Emit the abbreviation as a record. - EncodeAbbrev(Abbv); - CurAbbrevs.push_back(Abbv); - return static_cast(CurAbbrevs.size())-1 + - naclbitc::FIRST_APPLICATION_ABBREV; - } - - //===--------------------------------------------------------------------===// - // BlockInfo Block Emission - //===--------------------------------------------------------------------===// - - /// EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK. - void EnterBlockInfoBlock() { - EnterSubblock(naclbitc::BLOCKINFO_BLOCK_ID); - BlockInfoCurBID = ~0U; - } -private: - /// SwitchToBlockID - If we aren't already talking about the specified block - /// ID, emit a BLOCKINFO_CODE_SETBID record. - void SwitchToBlockID(unsigned BlockID) { - if (BlockInfoCurBID == BlockID) return; - SmallVector V; - V.push_back(BlockID); - EmitRecord(naclbitc::BLOCKINFO_CODE_SETBID, V); - BlockInfoCurBID = BlockID; - } - - BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { - if (BlockInfo *BI = getBlockInfo(BlockID)) - return *BI; - - // Otherwise, add a new record. - BlockInfoRecords.push_back(BlockInfo()); - BlockInfoRecords.back().BlockID = BlockID; - return BlockInfoRecords.back(); - } - -public: - - /// EmitBlockInfoAbbrev - Emit a DEFINE_ABBREV record for the specified - /// BlockID. - unsigned EmitBlockInfoAbbrev(unsigned BlockID, NaClBitCodeAbbrev *Abbv) { - SwitchToBlockID(BlockID); - EncodeAbbrev(Abbv); - - // Add the abbrev to the specified block record. - BlockInfo &Info = getOrCreateBlockInfo(BlockID); - Info.Abbrevs.push_back(Abbv); - - return Info.Abbrevs.size()-1+naclbitc::FIRST_APPLICATION_ABBREV; - } -}; - - -} // End llvm namespace - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClCompress.h b/include/llvm/Bitcode/NaCl/NaClCompress.h deleted file mode 100644 index 41bfe7c2af3..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClCompress.h +++ /dev/null @@ -1,61 +0,0 @@ -//===-- NaClCompress.h - Bitcode (abbrev) compression ---------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Defines API's to read in a PNaCl bitcode buffer, and write it out to -// a corresponding ostream. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_NACL_NACLCOMPRESS_H -#define LLVM_BITCODE_NACL_NACLCOMPRESS_H - -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" - -namespace llvm { - -/// Analyzes and (optionally) compresses a bitcode file. -class NaClBitcodeCompressor { -public: - /// The flags to use when compressing. - struct CompressFlags { - CompressFlags() - : TraceGeneratedAbbreviations(false), - ShowValueDistributions(false), - ShowAbbrevLookupTries(false), - ShowAbbreviationFrequencies(false), - RemoveAbbreviations(false) {} - bool TraceGeneratedAbbreviations; - bool ShowValueDistributions; - bool ShowAbbrevLookupTries; - bool ShowAbbreviationFrequencies; - bool RemoveAbbreviations; - }; - CompressFlags Flags; - - NaClBitcodeCompressor() {} - - /// Analyzes bitcode in MemBuf for applicable abbreviations for - /// compression. Output is the stream to write data associated with - /// "show" flags (ShowValueDistributions, ShowAbbrevLookupTries, // - /// and ShowAbbreviationFrequencies). - bool analyze(MemoryBuffer *MemBuf, raw_ostream &Output = outs()); - - /// Reads bitcode in MemBuf, finds new applicable abbreviations for - /// compression, and then rewrites out the bitcode out using these - /// new abbreviations to BitcodeOutput. Returns true iff successful. - /// ShowOutput captures analysis output generated by "show" flags - /// (see method analyze). - bool compress(MemoryBuffer *MemBuf, raw_ostream &BitcodeOutput, - raw_ostream &ShowOutput = errs()); -}; - -} // namespace llvm - -#endif // LLVM_BITCODE_NACL_NACLCOMPRESS_H diff --git a/include/llvm/Bitcode/NaCl/NaClCompressBlockDist.h b/include/llvm/Bitcode/NaCl/NaClCompressBlockDist.h deleted file mode 100644 index 66c3bdc99b9..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClCompressBlockDist.h +++ /dev/null @@ -1,62 +0,0 @@ -//===-- NaClCompressBlockDist.h -------------------------------------------===// -// Defines distribution maps used to collect block and record -// distributions for tool pnacl-bccompress. -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_NACL_NACLCOMPRESSBLOCKDIST_H -#define LLVM_BITCODE_NACL_NACLCOMPRESSBLOCKDIST_H - - -#include "llvm/Bitcode/NaCl/NaClBitcodeAbbrevDist.h" -#include "llvm/Bitcode/NaCl/NaClBitcodeBlockDist.h" - -namespace llvm { - -/// Nests record distributions within the block they appear in, -/// in a block distribution. The record distributions are refined -/// by separating record codes that use the same abbreviation. -class NaClCompressBlockDistElement : public NaClBitcodeBlockDistElement { -public: - static bool classof(const NaClBitcodeDistElement *Element) { - return Element->getKind() >= RDE_PNaClCompressBlockDist - && Element->getKind() < RDE_PNaClCompressBlockDistLast; - } - - explicit NaClCompressBlockDistElement(unsigned BlockID=0) - : NaClBitcodeBlockDistElement(RDE_PNaClCompressBlockDist), - AbbrevDist(BlockID) { - NestedDists.push_back(&AbbrevDist); - } - - virtual ~NaClCompressBlockDistElement(); - - virtual NaClBitcodeDistElement* - CreateElement(NaClBitcodeDistValue Value) const; - - virtual const SmallVectorImpl * - GetNestedDistributions() const; - - NaClBitcodeDist &GetAbbrevDist() { - return AbbrevDist; - } - - // Sentinel for generating elements of this type. - static NaClCompressBlockDistElement Sentinel; - -private: - // Nested blocks used by GetNestedDistributions. - SmallVector NestedDists; - - // The abbreviations/records associated with the corresponding block. - NaClBitcodeAbbrevDist AbbrevDist; -}; - -} - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClCompressCodeDist.h b/include/llvm/Bitcode/NaCl/NaClCompressCodeDist.h deleted file mode 100644 index 71b1775482a..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClCompressCodeDist.h +++ /dev/null @@ -1,63 +0,0 @@ -//===-- NaClCompressCodeDist.h -------------------------------------------===// -// Defines distribution maps for record codes for pnacl-bccompress. -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_NACL_NACLCOMPRESSCODEDIST_H -#define LLVM_BITCODE_NACL_NACLCOMPRESSCODEDIST_H - -#include "llvm/Bitcode/NaCl/NaClBitcodeCodeDist.h" -#include "llvm/Bitcode/NaCl/NaClBitcodeSizeDist.h" - -namespace llvm { - -/// Defines a record code distribution, with nested distributions separating -/// the code distributions based on size and values. -class NaClCompressCodeDistElement : public NaClBitcodeCodeDistElement { -public: - static bool classof(const NaClBitcodeDistElement *Element) { - return Element->getKind() >= RDE_CompressCodeDist && - Element->getKind() < RDE_CompressCodeDistLast; - } - - NaClCompressCodeDistElement() - : NaClBitcodeCodeDistElement(RDE_CompressCodeDist), - SizeDist(NaClBitcodeDist::RecordStorage, - &NaClBitcodeSizeDistElement::Sentinel) { - NestedDists.push_back(&SizeDist); - } - - virtual ~NaClCompressCodeDistElement(); - - virtual NaClBitcodeDistElement *CreateElement( - NaClBitcodeDistValue Value) const; - - virtual void AddRecord(const NaClBitcodeRecord &Record); - - virtual const SmallVectorImpl * - GetNestedDistributions() const; - - NaClBitcodeDist &GetSizeDist() { - return SizeDist; - } - - /// The sentinel used to generate instances of this in - /// a record code distribution map. - static NaClCompressCodeDistElement Sentinel; - -private: - // Nested blocks used by GetNestedDistributions. - SmallVector NestedDists; - - /// The distribution of values, based on size. - NaClBitcodeDist SizeDist; -}; - -} - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClFuzz.h b/include/llvm/Bitcode/NaCl/NaClFuzz.h deleted file mode 100644 index 1d6524dbfd9..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClFuzz.h +++ /dev/null @@ -1,94 +0,0 @@ -//===- NaClFuzz.h - Fuzz PNaCl bitcode records ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines a basic fuzzer for a list of PNaCl bitcode records. -// -// *** WARNING *** The implementation of the fuzzer uses a random -// number generator. As a result, this code is not thread safe. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_NACL_NACLFUZZ_H -#define LLVM_BITCODE_NACL_NACLFUZZ_H - -#include "llvm/Bitcode/NaCl/NaClBitcodeMungeUtils.h" -#include "llvm/Bitcode/NaCl/NaClRandNumGen.h" - -namespace naclfuzz { - -using namespace llvm; - -/// \brief Fuzzes a list of editable bitcode records. -class RecordFuzzer { - RecordFuzzer(const RecordFuzzer&) = delete; - void operator=(const RecordFuzzer&) = delete; -public: - typedef NaClMungedBitcode::iterator iterator; - - /// \brief The set of possible fuzzing actions. - enum EditAction { - /// \brief Inserts a new record into the list of bitcode records. - InsertRecord, - /// \brief Mutate contents of an existing bitcode record. - MutateRecord, - /// \brief Removes an existing record from the list of bitcode - /// records. - RemoveRecord, - /// \brief Replaces an existing record with a new bitcode record. - ReplaceRecord, - /// \brief Swaps two records in the bitcode record list. - SwapRecord - }; - - virtual ~RecordFuzzer(); - - /// \brief Generates a random mutation of the bitcode, using the - /// provided random number generator. Percentage (a value between 0 - /// and 1 defined by Count/Base) is used to define the number of - /// fuzzing actions applied to the bitcode. Returns true if fuzzing - /// succeeded. - /// - /// May be called an arbitrary number of times. Results are left in - /// the munged bitcode records passed into static method - /// createSimpleRecordFuzzer. - virtual bool fuzz(unsigned Count, unsigned Base=100) = 0; - - /// \brief Shows how many times each record was edited in the - /// corresponding (input) bitcode, over all calls to fuzz. - virtual void showRecordDistribution(raw_ostream &Out) const = 0; - - /// \brief Shows how many times each type of edit action was applied - /// to the corresponding bitcode, over all calls to fuzz. - virtual void showEditDistribution(raw_ostream &Out) const = 0; - - // Creates an instance of a fuzzer for the given bitcode. - static RecordFuzzer - *createSimpleRecordFuzzer(NaClMungedBitcode &Bitcode, - RandomNumberGenerator &RandGenerator); - - /// Returns printable name for the edit action. - static const char *actionName(EditAction Action); - -protected: - RecordFuzzer(NaClMungedBitcode &Bitcode, RandomNumberGenerator &Generator); - - // Holds the bitcode being munged. - NaClMungedBitcode &Bitcode; - - // Hold the random number generator. - RandomNumberGenerator &Generator; - - // Erases the last fuzzing result from the munged bitcode records - // in Bitcode. - virtual void clear(); -}; - -} // end of namespace naclfuzz - -#endif // LLVM_BITCODE_NACL_NACLFUZZ_H diff --git a/include/llvm/Bitcode/NaCl/NaClLLVMBitCodes.h b/include/llvm/Bitcode/NaCl/NaClLLVMBitCodes.h deleted file mode 100644 index adc554c7897..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClLLVMBitCodes.h +++ /dev/null @@ -1,374 +0,0 @@ -//===- NaClLLVMBitCodes.h ---------------------------------------*- C++ -*-===// -// Enum values for the NaCl bitcode wire format -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This header defines Bitcode enum values for NaCl bitcode wire format. -// -// The enum values defined in this file should be considered permanent. If -// new features are added, they should have values added at the end of the -// respective lists. -// -// Note: PNaCl version 1 is no longer supported, and has been removed from -// comments. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_NACL_NACLLLVMBITCODES_H -#define LLVM_BITCODE_NACL_NACLLLVMBITCODES_H - -#include "llvm/Bitcode/NaCl/NaClBitCodes.h" - -namespace llvm { -namespace naclbitc { - // The only top-level block type defined is for a module. - enum NaClBlockIDs { - // Blocks - MODULE_BLOCK_ID = FIRST_APPLICATION_BLOCKID, - - // Module sub-block id's. - PARAMATTR_BLOCK_ID, // Not used in PNaCl. - PARAMATTR_GROUP_BLOCK_ID, // Not used in PNaCl. - - CONSTANTS_BLOCK_ID, - FUNCTION_BLOCK_ID, - - UNUSED_ID1, - - VALUE_SYMTAB_BLOCK_ID, - METADATA_BLOCK_ID, // Not used in PNaCl. - METADATA_ATTACHMENT_ID, // Not used in PNaCl. - - TYPE_BLOCK_ID_NEW, - - USELIST_BLOCK_ID, // Not used in PNaCl. - GLOBALVAR_BLOCK_ID - }; - - - /// MODULE blocks have a number of optional fields and subblocks. - enum NaClModuleCodes { - MODULE_CODE_VERSION = 1, // VERSION: [version#] - MODULE_CODE_TRIPLE = 2, // Not used in PNaCl - MODULE_CODE_DATALAYOUT = 3, // Not used in PNaCl - MODULE_CODE_ASM = 4, // Not used in PNaCl - MODULE_CODE_SECTIONNAME = 5, // Not used in PNaCl - MODULE_CODE_DEPLIB = 6, // Not used in PNaCl - MODULE_CODE_GLOBALVAR = 7, // Not used in PNaCl - // FUNCTION: [type, callingconv, isproto, linkage] - MODULE_CODE_FUNCTION = 8, - MODULE_CODE_ALIAS = 9, // Not used in PNaCl - MODULE_CODE_PURGEVALS = 10, // Not used in PNaCl - MODULE_CODE_GCNAME = 11 // Not used in PNaCl - }; - - /// PARAMATTR blocks have code for defining a parameter attribute set. - enum NaClAttributeCodes { - // FIXME: Remove `PARAMATTR_CODE_ENTRY_OLD' in 4.0 - PARAMATTR_CODE_ENTRY_OLD = 1, // ENTRY: [paramidx0, attr0, - // paramidx1, attr1...] - PARAMATTR_CODE_ENTRY = 2, // ENTRY: [paramidx0, attrgrp0, - // paramidx1, attrgrp1, ...] - PARAMATTR_GRP_CODE_ENTRY = 3 // ENTRY: [id, attr0, att1, ...] - }; - - /// TYPE blocks have codes for each type primitive they use. - enum NaClTypeCodes { - TYPE_CODE_NUMENTRY = 1, // NUMENTRY: [numentries] - - // Type Codes - TYPE_CODE_VOID = 2, // VOID - TYPE_CODE_FLOAT = 3, // FLOAT - TYPE_CODE_DOUBLE = 4, // DOUBLE - // TODO(mseaborn): Remove LABEL when we drop support for v1 of the - // PNaCl bitcode format. The writer no longer generates it. - TYPE_CODE_LABEL = 5, // LABEL - TYPE_CODE_OPAQUE = 6, // Not used in PNaCl. - TYPE_CODE_INTEGER = 7, // INTEGER: [width] - TYPE_CODE_POINTER = 8, // POINTER: [pointee type] - - TYPE_CODE_FUNCTION_OLD = 9, // Not used in PNaCl. - - TYPE_CODE_HALF = 10, // Not used in PNaCl. - - TYPE_CODE_ARRAY = 11, // Not used in PNaCl. - TYPE_CODE_VECTOR = 12, // VECTOR: [numelts, eltty] - - // These are not with the other floating point types because they're - // a late addition, and putting them in the right place breaks - // binary compatibility. - TYPE_CODE_X86_FP80 = 13, // Not used in PNaCl. - TYPE_CODE_FP128 = 14, // Not used in PNaCl. - TYPE_CODE_PPC_FP128= 15, // Not used in PNaCl. - - TYPE_CODE_METADATA = 16, // Not used in PNaCl. - - TYPE_CODE_X86_MMX = 17, // Not used in PNaCl. - - TYPE_CODE_STRUCT_ANON = 18, // Not used in PNaCl. - TYPE_CODE_STRUCT_NAME = 19, // Not used in PNaCl. - TYPE_CODE_STRUCT_NAMED = 20,// Not used in PNaCl. - - TYPE_CODE_FUNCTION = 21 // FUNCTION: [vararg, retty, paramty x N] - }; - - // The type symbol table only has one code (TST_ENTRY_CODE). - enum NaClTypeSymtabCodes { - TST_CODE_ENTRY = 1 // TST_ENTRY: [typeid, namechar x N] - }; - - // The value symbol table only has one code (VST_ENTRY_CODE). - enum NaClValueSymtabCodes { - VST_CODE_ENTRY = 1, // VST_ENTRY: [valid, namechar x N] - VST_CODE_BBENTRY = 2 // VST_BBENTRY: [bbid, namechar x N] - }; - - // Not used in PNaCl. - enum NaClMetadataCodes { - METADATA_STRING = 1, // MDSTRING: [values] - // 2 is unused. - // 3 is unused. - METADATA_NAME = 4, // STRING: [values] - // 5 is unused. - METADATA_KIND = 6, // [n x [id, name]] - // 7 is unused. - METADATA_NODE = 8, // NODE: [n x (type num, value num)] - METADATA_FN_NODE = 9, // FN_NODE: [n x (type num, value num)] - METADATA_NAMED_NODE = 10, // NAMED_NODE: [n x mdnodes] - METADATA_ATTACHMENT = 11 // [m x [value, [n x [id, mdnode]]] - }; - - // The constants block (CONSTANTS_BLOCK_ID) describes emission for each - // constant and maintains an implicit current type value. - enum NaClConstantsCodes { - CST_CODE_SETTYPE = 1, // SETTYPE: [typeid] - CST_CODE_NULL = 2, // Not used in PNaCl. - CST_CODE_UNDEF = 3, // UNDEF - CST_CODE_INTEGER = 4, // INTEGER: [intval] - CST_CODE_WIDE_INTEGER = 5, // Not used in PNaCl. - CST_CODE_FLOAT = 6, // FLOAT: [fpval] - CST_CODE_AGGREGATE = 7, // Not used in PNaCl. - CST_CODE_STRING = 8, // Not used in PNaCl. - CST_CODE_CSTRING = 9, // Not used in PNaCl. - CST_CODE_CE_BINOP = 10, // Not used in PNaCl. - CST_CODE_CE_CAST = 11, // Not used in PNaCl. - CST_CODE_CE_GEP = 12, // Not used in PNaCl. - CST_CODE_CE_SELECT = 13, // Not used in PNaCl. - CST_CODE_CE_EXTRACTELT = 14, // Not used in PNaCl. - CST_CODE_CE_INSERTELT = 15, // Not used in PNaCl. - CST_CODE_CE_SHUFFLEVEC = 16, // Not used in PNaCl. - CST_CODE_CE_CMP = 17, // Not used in PNaCl. - CST_CODE_INLINEASM_OLD = 18, // No longer used. - CST_CODE_CE_SHUFVEC_EX = 19, // Not used in PNaCl. - CST_CODE_CE_INBOUNDS_GEP = 20,// Not used in PNaCl. - CST_CODE_BLOCKADDRESS = 21, // Not used in PNaCl. - CST_CODE_DATA = 22, // Not used in PNaCl. - CST_CODE_INLINEASM = 23 // Not used in PNaCl. - }; - - /// GlobalVarOpcodes - These are values used in the bitcode files to - /// encode records defining global variables. - /// - /// The structure of global variables can be summarized as follows: - /// - /// The global variable block begins with a GLOBALVAR_COUNT, defining - /// the number of global variables in the bitcode file. After that, - /// each global variable is defined. - /// - /// Global variables are defined by a GLOBALVAR_VAR record, followed - /// by 1 or more records defining its initial value. Simple - /// variables have a single initializer. Structured variables are - /// defined by an initial GLOBALVAR_COMPOUND record defining the - /// number of fields in the structure, followed by an initializer - /// for each of its fields. In this context, a field is either data, - /// or a relocation. A data field is defined by a - /// GLOBALVAR_ZEROFILL or GLOBALVAR_DATA record. A relocation field - /// is defined by a GLOBALVAR_RELOC record. - enum NaClGlobalVarOpcodes { - GLOBALVAR_VAR = 0, // VAR: [align, isconst] - GLOBALVAR_COMPOUND = 1, // COMPOUND: [size] - GLOBALVAR_ZEROFILL = 2, // ZEROFILL: [size] - GLOBALVAR_DATA = 3, // DATA: [b0, b1, ...] - GLOBALVAR_RELOC = 4, // RELOC: [val, [addend]] - GLOBALVAR_COUNT = 5 // COUNT: [n] - }; - - /// CastOpcodes - These are values used in the bitcode files to encode which - /// cast a CST_CODE_CE_CAST or a XXX refers to. The values of these enums - /// have no fixed relation to the LLVM IR enum values. Changing these will - /// break compatibility with old files. - enum NaClCastOpcodes { - CAST_TRUNC = 0, - CAST_ZEXT = 1, - CAST_SEXT = 2, - CAST_FPTOUI = 3, - CAST_FPTOSI = 4, - CAST_UITOFP = 5, - CAST_SITOFP = 6, - CAST_FPTRUNC = 7, - CAST_FPEXT = 8, - // 9 was CAST_PTRTOINT; not used in PNaCl. - // 10 was CAST_INTTOPTR; not used in PNaCl. - CAST_BITCAST = 11 - }; - - /// BinaryOpcodes - These are values used in the bitcode files to encode which - /// binop a CST_CODE_CE_BINOP or a XXX refers to. The values of these enums - /// have no fixed relation to the LLVM IR enum values. Changing these will - /// break compatibility with old files. - enum NaClBinaryOpcodes { - BINOP_ADD = 0, - BINOP_SUB = 1, - BINOP_MUL = 2, - BINOP_UDIV = 3, - BINOP_SDIV = 4, // overloaded for FP - BINOP_UREM = 5, - BINOP_SREM = 6, // overloaded for FP - BINOP_SHL = 7, - BINOP_LSHR = 8, - BINOP_ASHR = 9, - BINOP_AND = 10, - BINOP_OR = 11, - BINOP_XOR = 12 - }; - - /// OverflowingBinaryOperatorOptionalFlags - Flags for serializing - /// OverflowingBinaryOperator's SubclassOptionalData contents. - /// Note: This enum is no longer used in PNaCl, because these - /// flags can't exist in files that meet the PNaCl ABI. - enum NaClOverflowingBinaryOperatorOptionalFlags { - OBO_NO_UNSIGNED_WRAP = 0, - OBO_NO_SIGNED_WRAP = 1 - }; - - /// PossiblyExactOperatorOptionalFlags - Flags for serializing - /// PossiblyExactOperator's SubclassOptionalData contents. - /// Note: This enum is no longer used in PNaCl, because these - /// flags can't exist in files that meet the PNaCl ABI. - enum NaClPossiblyExactOperatorOptionalFlags { - PEO_EXACT = 0 - }; - - /// \brief Flags for serializing floating point binary operators's - /// SubclassOptionalData contents. - /// Note: This enum is no longer used in PNaCl, because these - /// flags shouldn't exist in files that meet the PNaCl ABI, unless - /// they are old. In the latter case, they are ignored by the reader. - enum NaClFloatingPointBinaryOperatorOptionalFlags { - FPO_UNSAFE_ALGEBRA = 0, - FPO_NO_NANS = 1, - FPO_NO_INFS = 2, - FPO_NO_SIGNED_ZEROS = 3, - FPO_ALLOW_RECIPROCAL = 4 - }; - - /// Encoded function calling conventions. - enum NaClCallingConventions { - C_CallingConv = 0 - }; - - /// Encoded comparison predicates. - enum NaClComparisonPredicates { - // Opcode U L G E Intuitive operation - FCMP_FALSE = 0, ///< 0 0 0 0 Always false (always folded) - FCMP_OEQ = 1, ///< 0 0 0 1 True if ordered and equal - FCMP_OGT = 2, ///< 0 0 1 0 True if ordered and greater than - FCMP_OGE = 3, ///< 0 0 1 1 True if ordered and greater than or equal - FCMP_OLT = 4, ///< 0 1 0 0 True if ordered and less than - FCMP_OLE = 5, ///< 0 1 0 1 True if ordered and less than or equal - FCMP_ONE = 6, ///< 0 1 1 0 True if ordered and operands are unequal - FCMP_ORD = 7, ///< 0 1 1 1 True if ordered (no nans) - FCMP_UNO = 8, ///< 1 0 0 0 True if unordered: isnan(X) | isnan(Y) - FCMP_UEQ = 9, ///< 1 0 0 1 True if unordered or equal - FCMP_UGT = 10, ///< 1 0 1 0 True if unordered or greater than - FCMP_UGE = 11, ///< 1 0 1 1 True if unordered, greater than, or equal - FCMP_ULT = 12, ///< 1 1 0 0 True if unordered or less than - FCMP_ULE = 13, ///< 1 1 0 1 True if unordered, less than, or equal - FCMP_UNE = 14, ///< 1 1 1 0 True if unordered or not equal - FCMP_TRUE = 15, ///< 1 1 1 1 Always true (always folded) - ICMP_EQ = 32, ///< equal - ICMP_NE = 33, ///< not equal - ICMP_UGT = 34, ///< unsigned greater than - ICMP_UGE = 35, ///< unsigned greater or equal - ICMP_ULT = 36, ///< unsigned less than - ICMP_ULE = 37, ///< unsigned less or equal - ICMP_SGT = 38, ///< signed greater than - ICMP_SGE = 39, ///< signed greater or equal - ICMP_SLT = 40, ///< signed less than - ICMP_SLE = 41 ///< signed less or equal - }; - - enum NaClLinkageTypes { - LINKAGE_EXTERNAL = 0, - LINKAGE_INTERNAL = 3 - }; - - // The function body block (FUNCTION_BLOCK_ID) describes function bodies. It - // can contain a constant block (CONSTANTS_BLOCK_ID). - enum NaClFunctionCodes { - FUNC_CODE_DECLAREBLOCKS = 1, // DECLAREBLOCKS: [n] - - FUNC_CODE_INST_BINOP = 2, // BINOP: [opval, opval, opcode] - // Note: because old PNaCl bitcode files - // may contain flags (which we now ignore), - // the reader must also support: - // BINOP: [opval, opval, opcode, flags] - FUNC_CODE_INST_CAST = 3, // CAST: [opval, destty, castopc] - FUNC_CODE_INST_GEP = 4, // Not used in PNaCl. - FUNC_CODE_INST_SELECT = 5, // Not used in PNaCl. Replaced by VSELECT. - FUNC_CODE_INST_EXTRACTELT = 6, // EXTRACTELT: [opval, opval] - FUNC_CODE_INST_INSERTELT = 7, // INSERTELT: [opval, opval, opval] - FUNC_CODE_INST_SHUFFLEVEC = 8, // Not used in PNaCl. - FUNC_CODE_INST_CMP = 9, // Not used in PNaCl. Replaced by CMP2. - FUNC_CODE_INST_RET = 10, // RET: [opval] - FUNC_CODE_INST_BR = 11, // BR: [bb#, bb#, cond] or [bb#] - FUNC_CODE_INST_SWITCH = 12, // SWITCH: [opty, op0, op1, ...] - FUNC_CODE_INST_INVOKE = 13, // Not used in PNaCl. - // 14 is unused. - FUNC_CODE_INST_UNREACHABLE = 15, // UNREACHABLE - - FUNC_CODE_INST_PHI = 16, // PHI: [ty, val0,bb0, ...] - // 17 is unused. - // 18 is unused. - FUNC_CODE_INST_ALLOCA = 19, // ALLOCA: [op, align] - FUNC_CODE_INST_LOAD = 20, // LOAD: [op, align, ty] - // 21 is unused. - // 22 is unused. - FUNC_CODE_INST_VAARG = 23, // Not used in PNaCl. - FUNC_CODE_INST_STORE = 24, // STORE: [ptr, val, align] - // 25 is unused. - FUNC_CODE_INST_EXTRACTVAL = 26, // Not used in PNaCl. - FUNC_CODE_INST_INSERTVAL = 27, // Not used in PNaCl. - // fcmp/icmp returning Int1TY or vector of Int1Ty. Same as CMP, exists to - // support legacy vicmp/vfcmp instructions. - FUNC_CODE_INST_CMP2 = 28, // CMP2: [opval, opval, pred] - // new select on i1 or [N x i1] - FUNC_CODE_INST_VSELECT = 29, // VSELECT: [opval, opval, pred] - FUNC_CODE_INST_INBOUNDS_GEP= 30, // Not used in PNaCl. - FUNC_CODE_INST_INDIRECTBR = 31, // Not used in PNaCl. - // 32 is unused. - FUNC_CODE_DEBUG_LOC_AGAIN = 33, // Not used in PNaCl. - - FUNC_CODE_INST_CALL = 34, // CALL: [cc, fnid, args...] - // See FUNC_CODE_INST_CALL_INDIRECT below. - FUNC_CODE_DEBUG_LOC = 35, // Not used in PNaCl. - FUNC_CODE_INST_FENCE = 36, // Not used in PNaCl. - FUNC_CODE_INST_CMPXCHG = 37, // Not used in PNaCl. - FUNC_CODE_INST_ATOMICRMW = 38, // Not used in PNaCl. - FUNC_CODE_INST_RESUME = 39, // Not used in PNaCl. - FUNC_CODE_INST_LANDINGPAD = 40, // Not used in PNaCl. - FUNC_CODE_INST_LOADATOMIC = 41, // Not used in PNaCl. - FUNC_CODE_INST_STOREATOMIC = 42, // Not used in PNaCl. - FUNC_CODE_INST_FORWARDTYPEREF = 43, // TYPE: [opval, ty] - // CALL_INDIRECT: [cc, fnid, returnty, args...] - FUNC_CODE_INST_CALL_INDIRECT = 44 - }; -} // End naclbitc namespace -} // End llvm namespace - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClObjDumpStream.h b/include/llvm/Bitcode/NaCl/NaClObjDumpStream.h deleted file mode 100644 index fd119ca6651..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClObjDumpStream.h +++ /dev/null @@ -1,967 +0,0 @@ -//===- NaClObjDumpStream.h --------------------------------------*- C++ -*-===// -// Models an objdump stream (bitcode records/assembly code). -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_NACL_NACLOBJDUMPSTREAM_H -#define LLVM_BITCODE_NACL_NACLOBJDUMPSTREAM_H - -#include "llvm/ADT/STLExtras.h" -#include "llvm/Bitcode/NaCl/NaClBitcodeParser.h" -#include "llvm/Support/raw_ostream.h" -#include -#include - -namespace llvm { -namespace naclbitc { - -// The default string assumed for a tab. -static const char *DefaultTab = " "; - -/// Class that implements text indenting for pretty printing text. -class TextIndenter { -public: - /// Creates a text indenter that indents using the given tab. - TextIndenter(const char* Tab = DefaultTab) - : Indent(""), - Tab(Tab), - TabSize(strlen(Tab)), - NumTabs(0) { - Values.push_back(Indent); - } - - virtual ~TextIndenter() {} - - /// Returns the current indentation to use. - const std::string &GetIndent() const { - return Indent; - } - - /// Returns the indent with the given number of tabs. - const std::string &GetIndent(unsigned Count) { - if (Count >= Values.size()) { - // Indents not yet generated, fill in cache to size needed. - std::string Results; - if (Values.size() > 0) Results = Values.back(); - for (size_t i = Values.size(); i <= Count; ++i) { - Results += Tab; - Values.push_back(Results); - } - } - return Values[Count]; - } - - /// Increments the current indentation by one tab. - void Inc() { - ++NumTabs; - if (NumTabs < Values.size()) { - Indent = Values[NumTabs]; - } else { - Indent += Tab; - Values.push_back(Indent); - } - } - - /// Decrements the current indentation by one tab. - void Dec() { - // Be sure not to underflow! - if (NumTabs) { - --NumTabs; - Indent = Values[NumTabs]; - } - } - - /// Returns the current number of tabs in the current indentation. - unsigned GetNumTabs() const { - return NumTabs; - } - - const char *GetTab() const { - return Tab; - } - - size_t GetTabSize() const { - return TabSize; - } - -private: - // The current indentation to use. - std::string Indent; - // The set of (previously computed) identations, based on the number - // of tabs. - std::vector Values; - // The text defining a tab. - const char *Tab; - // The size of the tab. - size_t TabSize; - // The number of tabs currently being used. - unsigned NumTabs; -}; - -class TextFormatter; - -/// This template class maintains a simply pool of directives for -/// a text formatter. Assumes that all elements in pool are associated -/// with the same formatter. -template -class DirectiveMemoryPool { -public: - DirectiveMemoryPool() {} - - ~DirectiveMemoryPool() { - DeleteContainerPointers(FreeList); - } - - Directive *Allocate(TextFormatter *Fmtr) { - if (FreeList.empty()) return new Directive(Fmtr); - Directive *Element = FreeList.back(); - assert(&Element->GetFormatter() == Fmtr - && "Directive memory pool formatter mismatch"); - FreeList.pop_back(); - return Element; - } - - void Free(Directive *Dir) { - FreeList.push_back(Dir); - } - -private: - std::vector FreeList; -}; - -/// This class defines a simple formatter for a stream that consists -/// of a sequence of instructions. In general, this class assumes that -/// instructions are a single line. In addition, some instructions -/// define a block around a sequence of instructions. Each block of -/// instructions is indented to clarify the block structure over that -/// set of instructions. -/// -/// To handle line indentation of blocks, this class inherits class -/// TextIndenter. The TextIndenter controls how blocks of lines are -/// indented. At the beginning of a block, the user should call method -/// Inc. It should then write out the sequence of instructions to be -/// indented. Then, after the last indented instruction of the block -/// is printed, the user should call method Dec. Nested blocks are -/// handled by nesting methods Inc and Dec appropriately. -/// -/// This class mainly focuses on the tools needed to format an -/// instruction, given a specified viewing width. The issue is that -/// while instructions should be on a single line, some instructions -/// are too wide to fit into the viewing width. Hence, we need a way -/// to deal with line overflow. -/// -/// The way this class handles the line overflow problem is to -/// basically force the user to break up the output into a sequence of -/// tokens. This is done using two streams. The text stream is used to -/// buffer tokens. The base stream is the stream to write tokens to -/// once they have been identified and positioned. The goal of the -/// formatter is to decide where the instruction text should be cut -/// (i.e. between tokens), so that the instruction does not overflow -/// the viewing width. It also handles the automatic insertion of line -/// indentation into the base stream when needed. -/// -/// To make it easy to print tokens to the text stream, we use text -/// directives. Whenever a text directive is written to the text -/// stream, it is assumed that all text written to the text stream -/// (since the last directive) is an (indivisible) token. The first -/// thing directives do is move the token from the text stream (if -/// present) to the base stream. -/// -/// In addition to defining tokens, text directives can also be -/// defined to query the formatter state and apply an appropriate -/// action. An example of this is the space text directive. It only -/// adds a space if the formatter isn't at the beginning of a new line -/// (since a newline can act as whitespace). -/// -/// The text formatter also has a notion of clustering -/// tokens. Clustering forces a consecutive sequence of tokens to -/// be treated as a single token, when deciding where to wrap long -/// lines. In particular, clustered tokens will not be broken up -/// unless there is no other way to print them, because the cluster is -/// larger than what can fit in a line. -/// -/// Clustering is implemented using two passes. In the first pass, the -/// sequence of tokens/directives are collected to find the clustered -/// text. They are also applied to collect any text internal to the -/// directives. Actions that can change (intraline) indenting are -/// turned off. -/// -/// Once the first pass is done, the second pass starts. It begins -/// with a check to see if the clustered text can fit on the current -/// line, and adds a newline if necessary. Then it replays the -/// directives to put the tokens of the cluster into the base stream. -/// The replay also changes (intraline) indenting as necessary. -/// -/// Clusters can be nested. In such cases, they are stripped one layer -/// per pass. Nested clusters are replayed after line wrapping of -/// outer clusters have been resolved. -class TextFormatter : public TextIndenter { -public: - - /// Creates a text formatter to print instructions onto the given - /// Base Stream. The viewing width is defined by LineWidth. The - /// given tab is the assumed value for tab characters and line - /// indents. - explicit TextFormatter(raw_ostream &BaseStream, - unsigned LineWidth = 80, - const char *Tab = DefaultTab); - - ~TextFormatter() override; - - /// Returns the user-level text stream of the formatter that tokens - /// should be written to. - raw_ostream &Tokens() { - return TextStream; - } - - /// Changes the line width to the given value. - void SetLineWidth(unsigned NewLineWidth) { - LineWidth = NewLineWidth; - if (MinLineWidth > LineWidth) MinLineWidth = LineWidth; - } - - // Changes the (default) line-wrap, continuation indent. - void SetContinuationIndent(const std::string &Indent) { - ContinuationIndent = Indent; - } - - /// Base class for all directives. The basic functionality is that it - /// has a reference to the text formatter, and is applied by calling - /// method apply. This method apply is encorporated into the - /// stream operator<<, so that they can be used as part of the - /// streamed output. - /// - /// Method apply extracts any tokens in the text stream. Moves them - /// into the base stream. Finally, it calls virtual method MyApply - /// to do the actions of the directive. - class Directive { - Directive(const Directive&) = delete; - void operator=(const Directive&) = delete; - public: - /// Creates a directive for the given stream. - explicit Directive(TextFormatter *Formatter) - : Formatter(Formatter) {} - - virtual ~Directive() {} - - /// Returns the formatter associated with the directive. - TextFormatter &GetFormatter() const { - return *Formatter; - } - - /// Does action of directive. - void Apply() const { - // Start by writing token if Tokens() buffer (if non-empty). - Formatter->WriteToken(); - // Apply the directive. - MyApply(false); - // Save the directive for replay if we are clustering. - MaybeSaveForReplay(); - } - - protected: - // The formatter associated with the directive. - TextFormatter *Formatter; - - // Like Apply, but called instead of Apply whey doing a replay. - void Reapply() const; - - // Does directive specific action. Replay is true only if the - // directive was in a cluster, and it is being called to replay - // the directive a second time. - virtual void MyApply(bool Replay) const = 0; - - // Adds the directive to the clustered directives if appropriate - // (i.e. inside a cluster). - virtual void MaybeSaveForReplay() const { - if (IsClustering()) AppendForReplay(this); - } - - // *********************************************************** - // Note: The following have been added so that derived classes - // have public access to protected text formatter methods. - // (Otherwise, you get a compiler error that they are protected - // in derived classes). - // *********************************************************** - - bool IsClustering() const { - return Formatter->IsClustering(); - } - - unsigned GetClusteringLevel() const { - return Formatter->GetClusteringLevel(); - } - - void AppendForReplay(const Directive *D) const { - Formatter->AppendForReplay(D); - } - - raw_ostream &Tokens() const { - return Formatter->Tokens(); - } - - void WriteToken(const std::string &Token) const { - Formatter->WriteToken(Token); - } - - void WriteEndline() const { - Formatter->WriteEndline(); - } - - void PopIndent() const { - Formatter->PopIndent(); - } - - void PushIndent() const { - Formatter->PushIndent(); - } - - bool AddLineWrapIfNeeded(unsigned TextSize) const { - return Formatter->AddLineWrapIfNeeded(TextSize); - } - - void StartClustering() const { - Formatter->StartClustering(); - } - - void FinishClustering() const { - Formatter->FinishClustering(); - } - }; - -protected: - // The base stream to send formatted text to. - raw_ostream &BaseStream; - // Buffer that holds token text. - std::string TextBuffer; - // The user-level stream for (token) text and directives. - raw_string_ostream TextStream; - // The buffered token waiting to be flushed to the base stream. - // std::string BufferedToken; - // The expected line width the formatter should try and match. - unsigned LineWidth; - // The current position (i.e. column of previous character on line) - // associated with the current line in the base stream. - unsigned LinePosition; - // The stack of (intraline) indents added by PushIndent. - std::vector IntralineIndents; - // The current intraline indent to use. - unsigned CurrentIndent; - // The minimum line width. Used to limit indents so that there - // will always be at least this amount of space on the line. - unsigned MinLineWidth; - // True if no characters have moved to the base stream for the - // instruction being printed. Note: This is different than - // LinePosition == 0. The latter can be true, when - // AtInstructionBeginning is false, if the current line is a - // continuation line caused by line overflow. - bool AtInstructionBeginning; - // The indent string to use for indenting each line of the instruction. - std::string LineIndent; - // The indent to add on continuation (i.e. overflow) lines for an - // instruction. - std::string ContinuationIndent; - // Counts how nested we are within clustering directives. - unsigned ClusteringLevel; - // Contains the number of columns needed to hold the generated text, - // while clustering. Computed so that we can test if it fits on the - // current line. - unsigned ClusteredTextSize; - // Contains the sequence of directives (including tokens) during - // clustering, so that it can be replayed after we determine if a - // new line needs to be added. - std::vector ClusteredDirectives; - - // Returns if we are currently inside a cluster. - bool IsClustering() const { - return ClusteringLevel > 0; - } - - // Returns the clustering level of the formatter. - unsigned GetClusteringLevel() const { - return ClusteringLevel; - } - - // Appends the given directive to the list of directives to - // replay, if clustering. - void AppendForReplay(const Directive *D) { - ClusteredDirectives.push_back(D); - } - - /// Writes out the token in the text stream. If necessary, moves to - // a new line first. - void WriteToken() { - WriteToken(GetToken()); - } - - /// Writes out the given token. If necessary, moves to a new line first. - void WriteToken(const std::string &Token) { - if (Token.empty()) return; - AddLineWrapIfNeeded(Token.size()); - Write(Token); - } - - // Extracts the text that has been added to the text stream, and - // returns it. - std::string GetToken(); - - /// Writes out a non-newline character to the base stream. - void Write(char ch); - - /// Writes out a string. - void Write(const std::string &Text); - - /// Starts a new cluster of tokens. - /// Note: We do not allow nested clusterings. - void StartClustering(); - - /// Ends the existing cluster of tokens. - void FinishClustering(); - - /// Adds a newline that ends the current instruction being printed. - void WriteEndline(); - - /// Called just before the first character on a line is printed, to - /// add indentation text for the line. - virtual void WriteLineIndents(); - - /// Analyzes the formatter state to determine if a token of the - /// given TextSize can fit on the current line. If it can't fit, - /// it wraps the input line. Returns true only if line wrap was - /// added by this method. - bool AddLineWrapIfNeeded(unsigned TextSize) { - if (IsClustering()) { - // Don't consider line wrapping until all text is clustered. That - // way we have full information on what we should do. - return false; - } else { - // If the text fits on the current line, there is nothing to do. - // Otherwise, we should add a newline, unless we are already - // at the new line. If we are already at the newline, we can't - // split up the token, so just allow line overflow. - if (LinePosition + TextSize <= LineWidth - || LinePosition == 0) - return false; - // If reached, it must not fit, so add a line wrap. - Write('\n'); - return true; - } - } - - /// Pops the current (intraline) indentation and restores it to the - /// previous indentation. Used to restore the indentation of - /// parenthesized subexpressions, where this should be called on the - /// close parenthesis. - void PopIndent() { - // Be pragmatic. If there is underflow, assume that it was due to - // the fact that the caller of this text formatter used a close - // directive for a pair of matching parenthesis that crossed - // multiple (i.e. instruction) lines. - if (IsClustering() || IntralineIndents.empty()) return; - CurrentIndent = IntralineIndents.back(); - IntralineIndents.pop_back(); - } - - /// Pushes the current (intraline) indentation to match the current - /// position within the line. Used to indent parenthesized - /// subexpressions, where this should be called on the open - /// parenthesis. - void PushIndent() { - if (IsClustering()) return; - IntralineIndents.push_back(CurrentIndent); - CurrentIndent = FixIndentValue(LinePosition); - } - - /// Fixes the given position, to the appropriate value for setting - /// CurrentIndent. That is, it makes sure there is always MinLineWidth - /// printable characters on a line. - unsigned FixIndentValue(unsigned Position) { - return std::min(Position, LineWidth - MinLineWidth); - } - -private: - /// Directive that generates temporary instances to hold tokens from - /// the Tokens() stream. Generated when GetToken() is called. Used - /// during clustering to regenerate the corresponding extracted - /// tokens during a replay. - class GetTokenDirective : public Directive { - friend class DirectiveMemoryPool; - GetTokenDirective(TextFormatter *Formatter) - : Directive(Formatter) {} - - public: - ~GetTokenDirective() override {} - - /// Allocates an instance of a GetTokenDirective. - /// Note: Will be reclaimed when MyApply is called. - static Directive *Allocate(TextFormatter *Formatter, - const std::string &Text); - - protected: - void MyApply(bool Replay) const override { - WriteToken(Text); - if (!IsClustering()) - Formatter->GetTokenFreeList.Free(const_cast(this)); - } - - private: - // The token text. - std::string Text; - }; - - // The set of freed GetTokenDirectives, that can be reused. - DirectiveMemoryPool GetTokenFreeList; -}; - -inline raw_ostream &operator<<(raw_ostream &Stream, - const TextFormatter::Directive &Directive) { - // Be sure that the directive is defined for the given stream, - // before applying the directive, since directives may have - // different meanings on different text streams. - assert(&Stream == &Directive.GetFormatter().Tokens()); - Directive.Apply(); - return Stream; -} - -/// Defines a directive that only tokenizes the text in the Tokens() -/// stream. -class TokenizeTextDirective : public TextFormatter::Directive { -public: - explicit TokenizeTextDirective(TextFormatter *Formatter) - : TextFormatter::Directive(Formatter) {} - - ~TokenizeTextDirective() override {} - -protected: - void MyApply(bool Replay) const override {} -}; - -/// Defines a token which doesn't need whitespace on either side of -/// the token to be a valid token (such as punctuation). -class TokenTextDirective : public TextFormatter::Directive { -public: - TokenTextDirective(TextFormatter *Formatter, const std::string &Str) - : TextFormatter::Directive(Formatter), Text(Str) { - } - - ~TokenTextDirective() override {} - -protected: - void MyApply(bool Replay) const override { - WriteToken(Text); - } - -private: - std::string Text; -}; - -/// Writes out the current token. Then adds a space if the base -/// stream is not at the beginning of a continuation line. -class SpaceTextDirective : public TextFormatter::Directive { -public: - SpaceTextDirective(TextFormatter *Formatter, const std::string &Space) - : TextFormatter::Directive(Formatter), Space(Space) {} - - explicit SpaceTextDirective(TextFormatter *Formatter) - : TextFormatter::Directive(Formatter), Space(" ") {} - - ~SpaceTextDirective() {} - -protected: - void MyApply(bool Replay) const override { - if (!AddLineWrapIfNeeded(Space.size())) - WriteToken(Space); - } -private: - std::string Space; -}; - -/// Adds a newline that ends the current instruction being printed. -class EndlineTextDirective : public TextFormatter::Directive { -public: - explicit EndlineTextDirective(TextFormatter *Formatter) - : TextFormatter::Directive(Formatter) {} - - ~EndlineTextDirective() override {} - -protected: - void MyApply(bool Replay) const override { - WriteEndline(); - } -}; - -/// Inserts a token and then pushes the current indent to the position -/// after the token. Used to model a open parenthesis. -class OpenTextDirective : public TokenTextDirective { -public: - - // Creates an open using the given indent. - OpenTextDirective(TextFormatter *Formatter, const std::string &Text) - : TokenTextDirective(Formatter, Text) {} - - ~OpenTextDirective() override {} - -protected: - void MyApply(bool Replay) const override { - TokenTextDirective::MyApply(Replay); - PushIndent(); - } -}; - -/// Inserts a token and then pops current indent. Used to model a -/// close parenthesis. -class CloseTextDirective : public TokenTextDirective { -public: - CloseTextDirective(TextFormatter *Formatter, const std::string &Text) - : TokenTextDirective(Formatter, Text) {} - - ~CloseTextDirective() override {} - -protected: - void MyApply(bool Replay) const override { - TokenTextDirective::MyApply(Replay); - PopIndent(); - } -}; - -/// Defines the beginning of a token cluster, which should be put on the -/// same line if possible. -class StartClusteringDirective : public TextFormatter::Directive { -public: - explicit StartClusteringDirective(TextFormatter *Formatter) - : TextFormatter::Directive(Formatter) {} - - ~StartClusteringDirective() override {} - -protected: - void MyApply(bool Replay) const override { - StartClustering(); - } - - void MaybeSaveForReplay() const override { - if (GetClusteringLevel() > 1) AppendForReplay(this); - } -}; - -class FinishClusteringDirective : public TextFormatter::Directive { -public: - explicit FinishClusteringDirective(TextFormatter *Formatter) - : TextFormatter::Directive(Formatter) {} - - ~FinishClusteringDirective() override {} - -protected: - void MyApply(bool Replay) const override { - FinishClustering(); - } -}; - -class ObjDumpStream; - -/// Models that an abbreviation index is not specified when dumping a -/// bitcode record. -static int32_t ABBREV_INDEX_NOT_SPECIFIED = -1; - -/// The formatter used for dumping records in ObjDumpStream. -class RecordTextFormatter : public TextFormatter { - RecordTextFormatter(const RecordTextFormatter&) = delete; - RecordTextFormatter &operator=(const RecordTextFormatter&) = delete; -public: - /// The address write width used to print a bit address, when - /// printing records. - static const unsigned AddressWriteWidth = 10; - - explicit RecordTextFormatter(ObjDumpStream *ObjDump); - - ~RecordTextFormatter() override {} - - /// Writes out the given record of values as an instruction. - void WriteValues(uint64_t Bit, - const llvm::NaClBitcodeValues &Values, - int32_t AbbrevIndex = ABBREV_INDEX_NOT_SPECIFIED); - - /// Returns text corresponding to an empty label column. - std::string GetEmptyLabelColumn(); - -protected: - void WriteLineIndents() override; - -private: - // The address label associated with the current line. - std::string Label; - // The open brace '<' for a record. - OpenTextDirective OpenBrace; - // The close brace '>' for a record. - CloseTextDirective CloseBrace; - // A comma between elements in a record. - TokenTextDirective Comma; - // A space inside a record. - SpaceTextDirective Space; - // End the line. - EndlineTextDirective Endline; - // Start clustering tokens. - StartClusteringDirective StartCluster; - // End clustering tokens. - FinishClusteringDirective FinishCluster; - - // Generates an address label with padding to match AddressWriteWidth; - std::string getBitAddress(uint64_t Bit); -}; - -/// Implements a stream to print out bitcode records, assembly code, -/// comments, and errors. The general format is to print records and -/// assembly side by side. Comments and errors (associated with the -/// record and/or assembly code) follow each printed record. -/// -/// Alignment of records, assembly, comments, and errors is done by -/// buffering assembly, comments, and errors until a write or flush -/// occurs. Then, the various streams are stitched together to -/// produce the corresponding output text. There are two buffers: one -/// holds the assembly, and the other holds comments and errors. -/// -/// There are exactly two methods that can cause text to be added to -/// the objdump stream. Method Flush just flushes out the assembly and -/// comments/errors buffer without printing a record. If there is no -/// buffered assembly/comments/errors, nothing is done. Method Write -/// prints the given record, and also flushes out the assembly and -/// comments/errors buffer. Hence, in general, comments and errors -/// follow the record/assembly. However, if you want them to appear -/// before, use method Flush. -/// -/// The constructor is defined with two flags: DumpRecords and -/// DumpAssembly. Comments and errors are flushed on every write, -/// independent of these flags. Records are printed out only if -/// DumpRecords is true. Assembly is flushed only if DumpAssembly is -/// true. -/// -/// To buffer assembly, call method Assembly to get a (string) stream -/// to buffer the assembly code. To buffer comments, call method -/// Comments() to get a (string) stream to buffer the comments. -/// -/// To buffer an error, call method Error. This method will increment -/// the error count, and return the comments stream after writing -/// "Error(byte:bit): ". -/// -/// If a single line of text is buffered into the assembly stream, no -/// new line is needed. The corresponding call to Write will -/// automatically insert the newline for you, if you did not add -/// it. If multiple lines are to be buffered into the assembly stream, -/// each line must be separated with a newline character. It is -/// always safe to end all assembly lines with a newline character. -/// -/// Also note that this class takes care of formatting records to fit -/// into a calculated record width (based on value set to -/// RecordWidth). On the other hand, we assume that the assembly is -/// formatted by the caller (i.e. owner of this object). -class ObjDumpStream { - ObjDumpStream(const ObjDumpStream&) = delete; - void operator=(const ObjDumpStream&) = delete; -public: - /// The default number of error messages that will be printed before - /// execution is stopped due to too many errors. - static unsigned DefaultMaxErrors; - - /// The default value for the column that separates records and - /// assembly, when DumpRecords and DumpAssembly is true. - static unsigned ComboObjDumpSeparatorColumn; - - /// The default value for line width when DumpRecords is true, - /// and DumpAssembly is false. This value is typically larger - /// than ComboObjDumpSeparatorColumn, since the entire line - /// can be used to print records. - static unsigned RecordObjectDumpLength; - - /// Creates an objdump stream which will dump records, assembly, - /// comments and errors into a single (user proved Stream). When - /// DumpRecords is true, the contents of records will be - /// dumped. When DumpAssembly is true, the corresponding assembly - /// will be printed. When both are true, the records and assembly - /// will be printed side by side. When both are false, only comments - /// and errors will be printed. - ObjDumpStream(raw_ostream &Stream, bool DumpRecords, bool DumpAssembly); - - ~ObjDumpStream() { Flush(); } - - /// Returns stream to buffer assembly that will be printed during the - /// next write call. - raw_ostream &Assembly() { - return AssemblyStream; - } - - /// Returns stream to buffer records that will be printed during the - /// next write call. - raw_ostream &Records() { - return RecordStream; - } - - /// Returns stream to buffer messages that will be printed during the - // next write call. - raw_ostream &Comments() { - return MessageStream; - } - - /// Prints "Warning(Bit/8:Bit%8): " onto the comments stream, and - /// then returns the comments stream. In general, warnings will be - /// printed after the next record, unless a call to Flush is made. - raw_ostream &Warning() { - return WarningAt(LastKnownBit); - } - - /// Prints "Warning(Bit/8:Bit%8): " onto the comments stream, and - /// then returns the comments stream. In general, warnings will be - /// printed after the next record, unless a call to Flush is made. - raw_ostream &WarningAt(uint64_t Bit) { - LastKnownBit = Bit; - return naclbitc::ErrorAt(Comments(), naclbitc::Warning, Bit); - } - - /// Prints "Error(Bit/8:Bit%8): " onto the comments stream using the - /// last know bit position of the input. Then, it records that an - /// error has occurred and returns the comments stream. In general - /// errors will be printed after the next record, unless a call to - /// Flush is made. - raw_ostream &Error() { - return ErrorAt(LastKnownBit); - } - - /// Prints "Error(Bit/8:Bit%8): " onto the comments stream at the - /// given Bit position. Then, it records that an error has occurred - /// and returns the comments stream. In general errors will be - /// printed after the next record, unless a call to Flush is made. - raw_ostream &ErrorAt(uint64_t Bit) { - return ErrorAt(naclbitc::Error, Bit); - } - - /// Prints "Level(Bit/8:Bit%8): " onto the comments stream at the - /// given bit position and severity Level. Then, it records that an - /// error has occurred and then returns the comments stream. In - /// general errors will be printed after the next record, unless a - /// call to Flush is made. - raw_ostream &ErrorAt(naclbitc::ErrorLevel Level, uint64_t Bit); - - /// Dumps a record (at the given bit), along with all buffered assembly, - /// comments, and errors, into the objdump stream. - void Write(uint64_t Bit, - const llvm::NaClBitcodeRecordData &Record, - int32_t AbbrevIndex = ABBREV_INDEX_NOT_SPECIFIED) { - LastKnownBit = Bit; - NaClBitcodeValues Values(Record); - RecordFormatter.WriteValues(Bit, Values, AbbrevIndex); - Flush(); - } - - /// Dumps the buffered assembly, comments, and errors, without any - /// corresponding record, into the objdump stream. - void Flush(); - - /// Flushes out the last record and/or error, and then stops - /// the executable. Should be called immediately after generating - /// the error message using ErrorAt(naclbitc::Fatal,...). - void FlushThenQuit(); - - /// Increments the record indent by one. - void IncRecordIndent() { - RecordFormatter.Inc(); - } - - /// Decrements the record indent by one. - void DecRecordIndent() { - RecordFormatter.Dec(); - } - - /// Returns the record indenter being used by the objdump stream, for - /// the purposes of querying state. - const TextIndenter &GetRecordIndenter() { - return RecordFormatter; - } - - /// Returns the number of errors reported to the dump stream. - unsigned GetNumErrors() const { - return NumErrors; - } - - // Returns true if dumping record. - bool GetDumpRecords() const { - return DumpRecords; - } - - // Returns true if dumping assembly. - bool GetDumpAssembly() const { - return DumpAssembly; - } - - /// Changes the maximum number of errors allowed. - void SetMaxErrors(unsigned NewMax) { - MaxErrors = NewMax; - } - - /// Changes the width allowed for records (from the default). - void SetRecordWidth(unsigned Width) { - RecordWidth = Width; - } - - unsigned GetRecordWidth() const { - return RecordWidth; - } - - /// Changes the column separator character to the given value. - void SetColumnSeparator(char Separator) { - ColumnSeparator = Separator; - } - - /// Changes the internal state, to assume one is processing a record - /// at the given bit. - void SetRecordBitAddress(uint64_t Bit) { - LastKnownBit = Bit; - } - -private: - // The stream to dump to. - raw_ostream &Stream; - // True if records should be dumped to the dump stream. - bool DumpRecords; - // True if assembly text should be dumped to the dump stream. - bool DumpAssembly; - // The number of errors reported. - unsigned NumErrors; - // The maximum number of errors before quitting. - unsigned MaxErrors; - // The number of columns available to print bitcode records. - unsigned RecordWidth; - // The buffer for assembly to be printed during the next write. - std::string AssemblyBuffer; - // The stream to buffer assembly into the assembly buffer. - raw_string_ostream AssemblyStream; - // The buffer for comments and errors. - std::string MessageBuffer; - // The stream to buffer comments and errors into the message. - raw_string_ostream MessageStream; - // The character used to separate records from assembly. - char ColumnSeparator; - // The last known bit passed to the objdump object. Used as default - // for automatically generated errors. - uint64_t LastKnownBit; - /// The buffer for records to be printed to during the next write. - std::string RecordBuffer; - /// The stream to buffer recordds into the record buffer. - raw_string_ostream RecordStream; - /// The text formatter for generating records. - RecordTextFormatter RecordFormatter; - - // Resets assembly and buffers. - void ResetBuffers() { - RecordBuffer.clear(); - AssemblyBuffer.clear(); - MessageBuffer.clear(); - } -}; - -} -} - -#endif diff --git a/include/llvm/Bitcode/NaCl/NaClRandNumGen.h b/include/llvm/Bitcode/NaCl/NaClRandNumGen.h deleted file mode 100644 index 620eadc4aa9..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClRandNumGen.h +++ /dev/null @@ -1,65 +0,0 @@ -//===- NaClRandNumGen.h - random number generator ---------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines a random number generator API for 64-bit unsigned -// values, and a corresponding default implementation. -// -// *** WARNING *** One should assume that random number generators are not -// thread safe. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_NACL_NACLRANDNUMGEN_H -#define LLVM_BITCODE_NACL_NACLRANDNUMGEN_H - -#include "llvm/ADT/StringRef.h" -#include -#include - -namespace naclfuzz { - -/// Defines API for a random number generator to use with fuzzing. -class RandomNumberGenerator { - RandomNumberGenerator(const RandomNumberGenerator&) = delete; - void operator=(const RandomNumberGenerator&) = delete; -public: - virtual ~RandomNumberGenerator(); - /// Returns a random number. - virtual uint64_t operator()() = 0; - // Returns a random value in [0..Limit) - uint64_t chooseInRange(uint64_t Limit) { - return (*this)() % Limit; - } -protected: - RandomNumberGenerator() {} -}; - -/// Defines a random number generator based on C++ generator std::mt19937_64. -class DefaultRandomNumberGenerator : public RandomNumberGenerator { - DefaultRandomNumberGenerator(const DefaultRandomNumberGenerator&) = delete; - void operator=(const DefaultRandomNumberGenerator&) = delete; -public: - DefaultRandomNumberGenerator(llvm::StringRef Seed); - uint64_t operator()() final; - ~DefaultRandomNumberGenerator() final {} - // Resets random number seed by salting the seed of constructor with Salt. - void saltSeed(uint64_t Salt); -private: - // 64-bit Mersenne Twister by Matsumoto and Nishimura, 2000 - // http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine - // This RNG is deterministically portable across C++11 - // implementations. - std::mt19937_64 Generator; - // Seed for the random number generator. - std::string Seed; -}; - -} // end of namespace naclfuzz - -#endif // LLVM_BITCODE_NACL_NACLRANDNUMGEN_H diff --git a/include/llvm/Bitcode/NaCl/NaClReaderWriter.h b/include/llvm/Bitcode/NaCl/NaClReaderWriter.h deleted file mode 100644 index 6ac74722b3e..00000000000 --- a/include/llvm/Bitcode/NaCl/NaClReaderWriter.h +++ /dev/null @@ -1,142 +0,0 @@ -//===-- llvm/Bitcode/NaCl/NaClReaderWriter.h - ------------------*- C++ -*-===// -// NaCl Bitcode reader/writer. -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This header defines interfaces to read and write NaCl bitcode wire format -// files. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_NACL_NACLREADERWRITER_H -#define LLVM_BITCODE_NACL_NACLREADERWRITER_H - -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/ErrorOr.h" -#include "llvm/Support/MemoryBuffer.h" - -#include - -namespace llvm { - class LLVMContext; - class Module; - class NaClBitcodeHeader; - class NaClBitstreamWriter; - class StreamingMemoryObject; - class raw_ostream; - - /// Defines the data layout used for PNaCl bitcode files. We set the - /// data layout of the module in the bitcode readers rather than in - /// pnacl-llc so that 'opt' will also use the correct data layout if - /// it is run on a pexe. - extern const char *PNaClDataLayout; - - /// Allows (function) local symbol tables (unsupported) in PNaCl bitcode - /// files. - extern cl::opt PNaClAllowLocalSymbolTables; - - /// \brief Defines the integer bit size used to model pointers in PNaCl. - static const unsigned PNaClIntPtrTypeBitSize = 32; - - /// Read the header of the specified bitcode buffer and prepare for lazy - /// deserialization of function bodies. If successful, this takes ownership - /// of 'Buffer' (extending its lifetime). On error, this returns an error code - /// and deletes Buffer. - /// - /// When Verbose is non-null, more descriptive error messages are also - /// written to Verbose. - /// - /// The AcceptSupportedOnly argument is used to decide which PNaCl versions - /// of the PNaCl bitcode to accept. There are three forms: - /// 1) Readable and supported. - /// 2) Readable and unsupported. Allows testing of code before becoming - /// supported, as well as running experiments on the bitcode format. - /// 3) Unreadable. - /// When AcceptSupportedOnly is true, only form 1 is allowed. When - /// AcceptSupportedOnly is false, forms 1 and 2 are allowed. - ErrorOr getNaClLazyBitcodeModule( - std::unique_ptr &&Buffer, LLVMContext &Context, - raw_ostream *Verbose = nullptr, bool AcceptSupportedOnly = true); - - /// Read the header of the specified stream and prepare for lazy - /// deserialization and streaming of function bodies. On error, - /// this returns null, and fills in *ErrMsg with an error description - /// if ErrMsg is non-null. - /// - /// See getNaClLazyBitcodeModule for an explanation of arguments - /// Verbose, AcceptSupportedOnly. - /// TODO(kschimpf): Refactor this and getStreamedBitcodeModule to use - /// ErrorOr API so that all methods have the same interface. - Module *getNaClStreamedBitcodeModule(const std::string &name, - StreamingMemoryObject *streamer, - LLVMContext &Context, - raw_ostream *Verbose = nullptr, - std::string *ErrMsg = nullptr, - bool AcceptSupportedOnly = true); - - /// Read the bitcode file from a buffer, returning the module. - /// - /// See getNaClLazyBitcodeModule for an explanation of arguments - /// Verbose, AcceptSupportedOnly. - ErrorOr NaClParseBitcodeFile(MemoryBufferRef Buffer, - LLVMContext &Context, - raw_ostream *Verbose = nullptr, - bool AcceptSupportedOnly = true); - - /// Read the textual bitcode records in Filename, returning the module. - /// Note: If Filename is "-", stdin will be read. - /// - /// See getNaClLazyBitcodeModule for an explanation of argument Verbose. - ErrorOr parseNaClBitcodeText(const std::string &Filename, - LLVMContext &Context, - raw_ostream *Verbose = nullptr); - - /// Write the specified module to the specified raw output stream, using - /// PNaCl wire format. For streams where it matters, the given stream - /// should be in "binary" mode. - /// - /// The AcceptSupportedOnly argument is used to decide which PNaCl versions - /// of the PNaCl bitcode to generate. There are two forms: - /// 1) Writable and supported. - /// 2) Writable and unsupported. Allows testing of code before becoming - /// supported, as well as running experiments on the bitcode format. - /// When AcceptSupportedOnly is true, only form 1 is allowed. When - /// AcceptSupportedOnly is false, forms 1 and 2 are allowed. - void NaClWriteBitcodeToFile(const Module *M, raw_ostream &Out, - bool AcceptSupportedOnly = true); - - /// isNaClBitcode - Return true if the given bytes are the magic bytes for - /// PNaCl bitcode wire format. - /// - inline bool isNaClBitcode(const unsigned char *BufPtr, - const unsigned char *BufEnd) { - return BufPtr+4 <= BufEnd && - BufPtr[0] == 'P' && - BufPtr[1] == 'E' && - BufPtr[2] == 'X' && - BufPtr[3] == 'E'; - } - - /// NaClWriteHeader - Generate a default header (using the version - /// number defined by kPNaClVersion) and write to the corresponding - /// bitcode stream. - void NaClWriteHeader(NaClBitstreamWriter &Stream, bool AcceptSupportedOnly); - - // NaClWriteHeader - Write the contents of the bitcode header to the - // corresponding bitcode stream. - void NaClWriteHeader(const NaClBitcodeHeader &Header, - NaClBitstreamWriter &Stream); - - /// NaClObjDump - Read PNaCl bitcode file from input, and print a - /// textual representation of its contents. NoRecords and NoAssembly - /// define what should not be included in the dump. - bool NaClObjDump(MemoryBufferRef Input, raw_ostream &output, - bool NoRecords, bool NoAssembly); - -} // end llvm namespace -#endif diff --git a/include/llvm/Bitcode/ReaderWriter.h b/include/llvm/Bitcode/ReaderWriter.h index e73552992bf..6f92e2e1b3c 100644 --- a/include/llvm/Bitcode/ReaderWriter.h +++ b/include/llvm/Bitcode/ReaderWriter.h @@ -15,6 +15,7 @@ #define LLVM_BITCODE_READERWRITER_H #include "llvm/IR/DiagnosticInfo.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/MemoryBuffer.h" #include @@ -22,17 +23,17 @@ namespace llvm { class BitstreamWriter; + class DataStreamer; class LLVMContext; class Module; class ModulePass; - class StreamingMemoryObject; // @LOCALMOD class raw_ostream; /// Read the header of the specified bitcode buffer and prepare for lazy /// deserialization of function bodies. If ShouldLazyLoadMetadata is true, /// lazily load metadata as well. If successful, this moves Buffer. On /// error, this *does not* move Buffer. - ErrorOr + ErrorOr> getLazyBitcodeModule(std::unique_ptr &&Buffer, LLVMContext &Context, DiagnosticHandlerFunction DiagnosticHandler = nullptr, @@ -41,7 +42,8 @@ namespace llvm { /// Read the header of the specified stream and prepare for lazy /// deserialization and streaming of function bodies. ErrorOr> getStreamedBitcodeModule( - StringRef Name, StreamingMemoryObject *Streamer, LLVMContext &Context, //@LOCALMOD + StringRef Name, std::unique_ptr Streamer, + LLVMContext &Context, DiagnosticHandlerFunction DiagnosticHandler = nullptr); /// Read the header of the specified bitcode buffer and extract just the @@ -52,7 +54,7 @@ namespace llvm { DiagnosticHandlerFunction DiagnosticHandler = nullptr); /// Read the specified bitcode file, returning the module. - ErrorOr + ErrorOr> parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context, DiagnosticHandlerFunction DiagnosticHandler = nullptr); @@ -132,14 +134,8 @@ namespace llvm { // Must contain the header! if (BufEnd-BufPtr < KnownHeaderSize) return true; - unsigned Offset = ( BufPtr[OffsetField ] | - (BufPtr[OffsetField+1] << 8) | - (BufPtr[OffsetField+2] << 16) | - (BufPtr[OffsetField+3] << 24)); - unsigned Size = ( BufPtr[SizeField ] | - (BufPtr[SizeField +1] << 8) | - (BufPtr[SizeField +2] << 16) | - (BufPtr[SizeField +3] << 24)); + unsigned Offset = support::endian::read32le(&BufPtr[OffsetField]); + unsigned Size = support::endian::read32le(&BufPtr[SizeField]); // Verify that Offset+Size fits in the file. if (VerifyBufferSize && Offset+Size > unsigned(BufEnd-BufPtr)) @@ -150,7 +146,7 @@ namespace llvm { } const std::error_category &BitcodeErrorCategory(); - enum class BitcodeError { InvalidBitcodeSignature, CorruptedBitcode }; + enum class BitcodeError { InvalidBitcodeSignature = 1, CorruptedBitcode }; inline std::error_code make_error_code(BitcodeError E) { return std::error_code(static_cast(E), BitcodeErrorCategory()); } @@ -163,7 +159,7 @@ namespace llvm { BitcodeDiagnosticInfo(std::error_code EC, DiagnosticSeverity Severity, const Twine &Msg); void print(DiagnosticPrinter &DP) const override; - std::error_code getError() const { return EC; }; + std::error_code getError() const { return EC; } static bool classof(const DiagnosticInfo *DI) { return DI->getKind() == DK_Bitcode; diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h index c4b94ede4f5..82d1e8ada17 100644 --- a/include/llvm/CodeGen/Analysis.h +++ b/include/llvm/CodeGen/Analysis.h @@ -64,7 +64,7 @@ inline unsigned ComputeLinearIndex(Type *Ty, /// If Offsets is non-null, it points to a vector to be filled in /// with the in-memory offsets of each of the individual values. /// -void ComputeValueVTs(const TargetLowering &TLI, Type *Ty, +void ComputeValueVTs(const TargetLowering &TLI, const DataLayout &DL, Type *Ty, SmallVectorImpl &ValueVTs, SmallVectorImpl *Offsets = nullptr, uint64_t StartingOffset = 0); diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 3eddfa4ba57..6a81bb8543f 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -19,6 +19,7 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/DwarfStringPoolEntry.h" #include "llvm/IR/InlineAsm.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" @@ -53,6 +54,7 @@ class MCSection; class MCStreamer; class MCSubtargetInfo; class MCSymbol; +class MCTargetOptions; class MDNode; class DwarfDebug; class Mangler; @@ -78,7 +80,7 @@ class AsmPrinter : public MachineFunctionPass { /// This is the MCStreamer object for the file we are generating. This /// contains the transient state for the current translation unit that we are /// generating (such as the current section etc). - MCStreamer &OutStreamer; + std::unique_ptr OutStreamer; /// The current machine function. const MachineFunction *MF; @@ -163,6 +165,9 @@ class AsmPrinter : public MachineFunctionPass { /// Return information about data layout. const DataLayout &getDataLayout() const; + /// Return the pointer size from the TargetMachine + unsigned getPointerSize() const; + /// Return information about subtarget. const MCSubtargetInfo &getSubtargetInfo() const; @@ -233,6 +238,11 @@ class AsmPrinter : public MachineFunctionPass { /// void EmitJumpTableInfo(); + /// Emit the control variable for an emulated TLS variable. + virtual void EmitEmulatedTLSControlVariable(const GlobalVariable *GV, + MCSymbol *EmittedSym, + bool AllZeroInitValue); + /// Emit the specified global variable to the .s file. virtual void EmitGlobalVariable(const GlobalVariable *GV); @@ -252,7 +262,7 @@ class AsmPrinter : public MachineFunctionPass { const MCExpr *lowerConstant(const Constant *CV); /// \brief Print a general LLVM constant to the .s file. - void EmitGlobalConstant(const Constant *CV); + void EmitGlobalConstant(const DataLayout &DL, const Constant *CV); /// \brief Unnamed constant global variables solely contaning a pointer to /// another globals variable act like a global variable "proxy", or GOT @@ -276,18 +286,6 @@ class AsmPrinter : public MachineFunctionPass { // Targets can, or in the case of EmitInstruction, must implement these to // customize output. - // @LOCALMOD-START - /// UseReadOnlyJumpTables - true if JumpTableInfo must be in rodata. - virtual bool UseReadOnlyJumpTables() const { return false; } - /// GetTargetBasicBlockAlign - the target alignment for basic blocks. - virtual unsigned GetTargetBasicBlockAlign() const { return 0; } - /// GetTargetLabelAlign - Get optional alignment for TargetOpcode - /// labels E.g., EH_LABEL. - virtual unsigned GetTargetLabelAlign(const MachineInstr *MI) const { - return 0; - } - // @LOCALMOD-END - /// This virtual method can be overridden by targets that want to emit /// something at the start of their file. virtual void EmitStartOfAsmFile(Module &) {} @@ -302,12 +300,7 @@ class AsmPrinter : public MachineFunctionPass { /// Targets can override this to emit stuff after the last basic block in the /// function. - virtual void EmitFunctionBodyEnd() { - // @LOCALMOD-START - unsigned NextFunctionAlignment = GetTargetBasicBlockAlign(); - if (NextFunctionAlignment) EmitAlignment(NextFunctionAlignment); - // @LOCALMOD-END - } + virtual void EmitFunctionBodyEnd() {} /// Targets can override this to emit stuff at the start of a basic block. /// By default, this method prints the label for the specified @@ -332,7 +325,9 @@ class AsmPrinter : public MachineFunctionPass { /// Targets can override this to change how global constants that are part of /// a C++ static/global constructor list are emitted. - virtual void EmitXXStructor(const Constant *CV) { EmitGlobalConstant(CV); } + virtual void EmitXXStructor(const DataLayout &DL, const Constant *CV) { + EmitGlobalConstant(DL, CV); + } /// Return true if the basic block has exactly one predecessor and the control /// transfer mechanism between the predecessor and this block is a @@ -433,10 +428,18 @@ class AsmPrinter : public MachineFunctionPass { /// Emit reference to a ttype global with a specified encoding. void EmitTTypeReference(const GlobalValue *GV, unsigned Encoding) const; - /// Emit the 4-byte offset of Label from the start of its section. This can - /// be done with a special directive if the target supports it (e.g. cygwin) - /// or by emitting it as an offset from a label at the start of the section. - void emitSectionOffset(const MCSymbol *Label) const; + /// Emit a reference to a symbol for use in dwarf. Different object formats + /// represent this in different ways. Some use a relocation others encode + /// the label offset in its section. + void emitDwarfSymbolReference(const MCSymbol *Label, + bool ForceOffset = false) const; + + /// Emit the 4-byte offset of a string from the start of its section. + /// + /// When possible, emit a DwarfStringPool section offset without any + /// relocations, and without using the symbol. Otherwise, defers to \a + /// emitDwarfSymbolReference(). + void emitDwarfStringOffset(DwarfStringPoolEntryRef S) const; /// Get the value for DW_AT_APPLE_isa. Zero if no isa encoding specified. virtual unsigned getISAEncoding() { return 0; } @@ -510,11 +513,12 @@ class AsmPrinter : public MachineFunctionPass { mutable unsigned Counter; /// This method emits the header for the current function. - void EmitFunctionHeader(); + virtual void EmitFunctionHeader(); /// Emit a blob of inline asm to the output streamer. void EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI, + const MCTargetOptions &MCOptions, const MDNode *LocMDNode = nullptr, InlineAsm::AsmDialect AsmDialect = InlineAsm::AD_ATT) const; @@ -538,7 +542,8 @@ class AsmPrinter : public MachineFunctionPass { void EmitLLVMUsedList(const ConstantArray *InitList); /// Emit llvm.ident metadata in an '.ident' directive. void EmitModuleIdents(Module &M); - void EmitXXStructorList(const Constant *List, bool isCtor); + void EmitXXStructorList(const DataLayout &DL, const Constant *List, + bool isCtor); GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy &C); }; } diff --git a/include/llvm/CodeGen/BasicTTIImpl.h b/include/llvm/CodeGen/BasicTTIImpl.h index c5efef32d07..796a78c16ac 100644 --- a/include/llvm/CodeGen/BasicTTIImpl.h +++ b/include/llvm/CodeGen/BasicTTIImpl.h @@ -91,8 +91,10 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { } protected: - explicit BasicTTIImplBase(const TargetMachine *TM) - : BaseT(TM->getDataLayout()) {} + explicit BasicTTIImplBase(const TargetMachine *TM, const DataLayout &DL) + : BaseT(DL) {} + + using TargetTransformInfoImplBase::DL; public: // Provide value semantics. MSVC requires that we spell all of these out. @@ -100,14 +102,6 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { : BaseT(static_cast(Arg)) {} BasicTTIImplBase(BasicTTIImplBase &&Arg) : BaseT(std::move(static_cast(Arg))) {} - BasicTTIImplBase &operator=(const BasicTTIImplBase &RHS) { - BaseT::operator=(static_cast(RHS)); - return *this; - } - BasicTTIImplBase &operator=(BasicTTIImplBase &&RHS) { - BaseT::operator=(std::move(static_cast(RHS))); - return *this; - } /// \name Scalar TTI Implementations /// @{ @@ -125,35 +119,40 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { } 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(DL, 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(DL, AM, Ty, AddrSpace); } bool isTruncateFree(Type *Ty1, Type *Ty2) { return getTLI()->isTruncateFree(Ty1, Ty2); } + bool isZExtFree(Type *Ty1, Type *Ty2) const { + return getTLI()->isZExtFree(Ty1, Ty2); + } + bool isProfitableToHoist(Instruction *I) { return getTLI()->isProfitableToHoist(I); } bool isTypeLegal(Type *Ty) { - EVT VT = getTLI()->getValueType(Ty); + EVT VT = getTLI()->getValueType(DL, Ty); return getTLI()->isTypeLegal(VT); } @@ -191,7 +190,7 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { bool haveFastSqrt(Type *Ty) { const TargetLoweringBase *TLI = getTLI(); - EVT VT = TLI->getValueType(Ty); + EVT VT = TLI->getValueType(DL, Ty); return TLI->isTypeLegal(VT) && TLI->isOperationLegalOrCustom(ISD::FSQRT, VT); } @@ -281,11 +280,11 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { /// \name Vector TTI Implementations /// @{ - unsigned getNumberOfRegisters(bool Vector) { return 1; } + unsigned getNumberOfRegisters(bool Vector) { return Vector ? 0 : 1; } unsigned getRegisterBitWidth(bool Vector) { return 32; } - unsigned getMaxInterleaveFactor() { return 1; } + unsigned getMaxInterleaveFactor(unsigned VF) { return 1; } unsigned getArithmeticInstrCost( unsigned Opcode, Type *Ty, @@ -298,7 +297,7 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { int ISD = TLI->InstructionOpcodeToISD(Opcode); assert(ISD && "Invalid opcode"); - std::pair LT = TLI->getTypeLegalizationCost(Ty); + std::pair LT = TLI->getTypeLegalizationCost(DL, Ty); bool IsFloat = Ty->getScalarType()->isFloatingPointTy(); // Assume that floating point arithmetic operations cost twice as much as @@ -348,9 +347,8 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { const TargetLoweringBase *TLI = getTLI(); int ISD = TLI->InstructionOpcodeToISD(Opcode); assert(ISD && "Invalid opcode"); - - std::pair SrcLT = TLI->getTypeLegalizationCost(Src); - std::pair DstLT = TLI->getTypeLegalizationCost(Dst); + std::pair SrcLT = TLI->getTypeLegalizationCost(DL, Src); + std::pair DstLT = TLI->getTypeLegalizationCost(DL, Dst); // Check for NOOP conversions. if (SrcLT.first == DstLT.first && @@ -454,8 +452,7 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { if (CondTy->isVectorTy()) ISD = ISD::VSELECT; } - - std::pair LT = TLI->getTypeLegalizationCost(ValTy); + std::pair LT = TLI->getTypeLegalizationCost(DL, ValTy); if (!(ValTy->isVectorTy() && !LT.second.isVector()) && !TLI->isOperationExpand(ISD, LT.second)) { @@ -484,7 +481,7 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { unsigned getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) { std::pair LT = - getTLI()->getTypeLegalizationCost(Val->getScalarType()); + getTLI()->getTypeLegalizationCost(DL, Val->getScalarType()); return LT.first; } @@ -492,7 +489,7 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, unsigned AddressSpace) { assert(!Src->isVoidTy() && "Invalid type"); - std::pair LT = getTLI()->getTypeLegalizationCost(Src); + std::pair LT = getTLI()->getTypeLegalizationCost(DL, Src); // Assuming that all loads of legal types cost 1. unsigned Cost = LT.first; @@ -503,7 +500,7 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { // itself. Unless the corresponding extending load or truncating store is // legal, then this will scalarize. TargetLowering::LegalizeAction LA = TargetLowering::Expand; - EVT MemVT = getTLI()->getValueType(Src, true); + EVT MemVT = getTLI()->getValueType(DL, Src, true); if (MemVT.isSimple() && MemVT != MVT::Other) { if (Opcode == Instruction::Store) LA = getTLI()->getTruncStoreAction(LT.second, MemVT.getSimpleVT()); @@ -522,6 +519,73 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { return Cost; } + unsigned getInterleavedMemoryOpCost(unsigned Opcode, Type *VecTy, + unsigned Factor, + ArrayRef Indices, + unsigned Alignment, + unsigned AddressSpace) { + VectorType *VT = dyn_cast(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 Tys) { unsigned ISD = 0; @@ -632,7 +696,7 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { } const TargetLoweringBase *TLI = getTLI(); - std::pair LT = TLI->getTypeLegalizationCost(RetTy); + std::pair LT = TLI->getTypeLegalizationCost(DL, RetTy); if (TLI->isOperationLegalOrPromote(ISD, LT.second)) { // The operation is legal. Assume it costs 1. @@ -703,7 +767,7 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase { } unsigned getNumberOfParts(Type *Tp) { - std::pair LT = getTLI()->getTypeLegalizationCost(Tp); + std::pair LT = getTLI()->getTypeLegalizationCost(DL, Tp); return LT.first; } @@ -748,18 +812,6 @@ class BasicTTIImpl : public BasicTTIImplBase { BasicTTIImpl(BasicTTIImpl &&Arg) : BaseT(std::move(static_cast(Arg))), ST(std::move(Arg.ST)), TLI(std::move(Arg.TLI)) {} - BasicTTIImpl &operator=(const BasicTTIImpl &RHS) { - BaseT::operator=(static_cast(RHS)); - ST = RHS.ST; - TLI = RHS.TLI; - return *this; - } - BasicTTIImpl &operator=(BasicTTIImpl &&RHS) { - BaseT::operator=(std::move(static_cast(RHS))); - ST = std::move(RHS.ST); - TLI = std::move(RHS.TLI); - return *this; - } }; } diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h index e2b744f08eb..1fd4eeb46b3 100644 --- a/include/llvm/CodeGen/CallingConvLower.h +++ b/include/llvm/CodeGen/CallingConvLower.h @@ -19,6 +19,7 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/IR/CallingConv.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/Target/TargetCallingConv.h" namespace llvm { diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h index 9f86429cbf1..8ac7555dfb0 100644 --- a/include/llvm/CodeGen/CommandFlags.h +++ b/include/llvm/CodeGen/CommandFlags.h @@ -16,11 +16,18 @@ #ifndef LLVM_CODEGEN_COMMANDFLAGS_H #define LLVM_CODEGEN_COMMANDFLAGS_H +#include "llvm/ADT/StringExtras.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Module.h" #include "llvm/MC/MCTargetOptionsCommandFlags.h" +#include "llvm//MC/SubtargetFeature.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Host.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRecip.h" #include using namespace llvm; @@ -123,11 +130,6 @@ EnableHonorSignDependentRoundingFPMath("enable-sign-dependent-rounding-fp-math", cl::desc("Force codegen to assume rounding mode can change dynamically"), cl::init(false)); -cl::opt -GenerateSoftFloatCalls("soft-float", - cl::desc("Generate software floating point library calls"), - cl::init(false)); - cl::opt FloatABIForCalls("float-abi", cl::desc("Choose float ABI type"), @@ -151,9 +153,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 +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 DontPlaceZerosInBSS("nozero-initialized-in-bss", cl::desc("Don't place zero-initialized symbols into bss section"), @@ -198,6 +206,10 @@ cl::opt StartAfter("start-after", cl::value_desc("pass-name"), cl::init("")); +cl::opt + RunPass("run-pass", cl::desc("Run compiler only for one specific pass"), + cl::value_desc("pass-name"), cl::init("")); + cl::opt DataSections("data-sections", cl::desc("Emit data into separate sections"), cl::init(false)); @@ -207,6 +219,10 @@ FunctionSections("function-sections", cl::desc("Emit functions into separate sections"), cl::init(false)); +cl::opt EmulatedTLS("emulated-tls", + cl::desc("Use emulated TLS model"), + cl::init(false)); + cl::opt UniqueSectionNames("unique-section-names", cl::desc("Give unique names to every section"), cl::init(true)); @@ -226,80 +242,108 @@ JTableType("jump-table-type", "Create one table per unique function type."), clEnumValEnd)); -cl::opt -FCFI("fcfi", - cl::desc("Apply forward-edge control-flow integrity"), - cl::init(false)); - -cl::opt -CFIType("cfi-type", - cl::desc("Choose the type of Control-Flow Integrity check to add"), - cl::init(CFIntegrity::Sub), - cl::values( - clEnumValN(CFIntegrity::Sub, "sub", - "Subtract the pointer from the table base, then mask."), - clEnumValN(CFIntegrity::Ror, "ror", - "Use rotate to check the offset from a table base."), - clEnumValN(CFIntegrity::Add, "add", - "Mask out the high bits and add to an aligned base."), - clEnumValEnd)); - -cl::opt -CFIEnforcing("cfi-enforcing", - cl::desc("Enforce CFI or pass the violation to a function."), - cl::init(false)); - -// Note that this option is linked to the cfi-enforcing option above: if -// cfi-enforcing is set, then the cfi-func-name option is entirely ignored. If -// cfi-enforcing is false and no cfi-func-name is set, then a default function -// will be generated that ignores all CFI violations. The expected signature for -// functions called with CFI violations is -// -// void (i8*, i8*) -// -// The first pointer is a C string containing the name of the function in which -// the violation occurs, and the second pointer is the pointer that violated -// CFI. -cl::opt -CFIFuncName("cfi-func-name", cl::desc("The name of the CFI function to call"), - cl::init("")); - // Common utility function tightly tied to the options listed here. Initializes // a TargetOptions object with CodeGen flags and returns it. static inline TargetOptions InitTargetOptionsFromCodeGenFlags() { TargetOptions Options; Options.LessPreciseFPMADOption = EnableFPMAD; - Options.NoFramePointerElim = DisableFPElim; Options.AllowFPOpFusion = FuseFPOps; + Options.Reciprocals = TargetRecip(ReciprocalOps); Options.UnsafeFPMath = EnableUnsafeFPMath; Options.NoInfsFPMath = EnableNoInfsFPMath; Options.NoNaNsFPMath = EnableNoNaNsFPMath; Options.HonorSignDependentRoundingFPMathOption = EnableHonorSignDependentRoundingFPMath; - Options.UseSoftFloat = GenerateSoftFloatCalls; if (FloatABIForCalls != FloatABI::Default) Options.FloatABIType = FloatABIForCalls; Options.NoZerosInBSS = DontPlaceZerosInBSS; Options.GuaranteedTailCallOpt = EnableGuaranteedTailCallOpt; - Options.DisableTailCalls = DisableTailCalls; Options.StackAlignmentOverride = OverrideStackAlignment; - Options.TrapFuncName = TrapFuncName; Options.PositionIndependentExecutable = EnablePIE; Options.UseInitArray = !UseCtors; Options.DataSections = DataSections; Options.FunctionSections = FunctionSections; Options.UniqueSectionNames = UniqueSectionNames; + Options.EmulatedTLS = EmulatedTLS; Options.MCOptions = InitMCTargetOptionsFromFlags(); Options.JTType = JTableType; - Options.FCFI = FCFI; - Options.CFIType = CFIType; - Options.CFIEnforcing = CFIEnforcing; - Options.CFIFuncName = CFIFuncName; Options.ThreadModel = TMModel; return Options; } +static inline std::string getCPUStr() { + // If user asked for the 'native' CPU, autodetect here. If autodection fails, + // this will set the CPU to an empty string which tells the target to + // pick a basic default. + if (MCPU == "native") + return sys::getHostCPUName(); + + return MCPU; +} + +static inline std::string getFeaturesStr() { + SubtargetFeatures Features; + + // If user asked for the 'native' CPU, we need to autodetect features. + // This is necessary for x86 where the CPU might not support all the + // features the autodetected CPU name lists in the target. For example, + // not all Sandybridge processors support AVX. + if (MCPU == "native") { + StringMap HostFeatures; + if (sys::getHostCPUFeatures(HostFeatures)) + for (auto &F : HostFeatures) + Features.AddFeature(F.first(), F.second); + } + + for (unsigned i = 0; i != MAttrs.size(); ++i) + Features.AddFeature(MAttrs[i]); + + return Features.getString(); +} + +/// \brief Set function attributes of functions in Module M based on CPU, +/// Features, and command line flags. +static inline void setFunctionAttributes(StringRef CPU, StringRef Features, + Module &M) { + for (auto &F : M) { + auto &Ctx = F.getContext(); + AttributeSet Attrs = F.getAttributes(), NewAttrs; + + if (!CPU.empty()) + NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex, + "target-cpu", CPU); + + if (!Features.empty()) + NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex, + "target-features", Features); + + if (DisableFPElim.getNumOccurrences() > 0) + NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex, + "no-frame-pointer-elim", + DisableFPElim ? "true" : "false"); + + if (DisableTailCalls.getNumOccurrences() > 0) + NewAttrs = NewAttrs.addAttribute(Ctx, AttributeSet::FunctionIndex, + "disable-tail-calls", + toStringRef(DisableTailCalls)); + + if (TrapFuncName.getNumOccurrences() > 0) + for (auto &B : F) + for (auto &I : B) + if (auto *Call = dyn_cast(&I)) + if (const auto *F = Call->getCalledFunction()) + if (F->getIntrinsicID() == Intrinsic::debugtrap || + F->getIntrinsicID() == Intrinsic::trap) + Call->addAttribute(llvm::AttributeSet::FunctionIndex, + "trap-func-name", TrapFuncName); + + // Let NewAttrs override Attrs. + NewAttrs = Attrs.addAttributes(Ctx, AttributeSet::FunctionIndex, NewAttrs); + F.setAttributes(NewAttrs); + } +} + #endif diff --git a/include/llvm/CodeGen/DFAPacketizer.h b/include/llvm/CodeGen/DFAPacketizer.h index f9cdc2a469f..c44a7e0b673 100644 --- a/include/llvm/CodeGen/DFAPacketizer.h +++ b/include/llvm/CodeGen/DFAPacketizer.h @@ -91,7 +91,7 @@ class DFAPacketizer { // API call is made to prune the dependence. class VLIWPacketizerList { protected: - const MachineFunction &MF; + MachineFunction &MF; const TargetInstrInfo *TII; // The VLIW Scheduler. diff --git a/include/llvm/CodeGen/DIE.h b/include/llvm/CodeGen/DIE.h index 7803898a8d4..f07712a676d 100644 --- a/include/llvm/CodeGen/DIE.h +++ b/include/llvm/CodeGen/DIE.h @@ -15,7 +15,10 @@ #define LLVM_LIB_CODEGEN_ASMPRINTER_DIE_H #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/DwarfStringPoolEntry.h" #include "llvm/Support/Dwarf.h" #include @@ -103,153 +106,14 @@ class DIEAbbrev : public FoldingSetNode { #endif }; -//===--------------------------------------------------------------------===// -/// DIE - A structured debug information entry. Has an abbreviation which -/// describes its organization. -class DIEValue; - -class DIE { -protected: - /// Offset - Offset in debug info section. - /// - unsigned Offset; - - /// Size - Size of instance + children. - /// - unsigned Size; - - /// Abbrev - Buffer for constructing abbreviation. - /// - DIEAbbrev Abbrev; - - /// Children DIEs. - /// - // This can't be a vector because pointer validity is requirent for the - // Parent pointer and DIEEntry. - // It can't be a list because some clients need pointer validity before - // the object has been added to any child list - // (eg: DwarfUnit::constructVariableDIE). These aren't insurmountable, but may - // be more convoluted than beneficial. - std::vector> Children; - - DIE *Parent; - - /// Attribute values. - /// - SmallVector Values; - -protected: - DIE() - : Offset(0), Size(0), Abbrev((dwarf::Tag)0, dwarf::DW_CHILDREN_no), - Parent(nullptr) {} - -public: - explicit DIE(dwarf::Tag Tag) - : Offset(0), Size(0), Abbrev((dwarf::Tag)Tag, dwarf::DW_CHILDREN_no), - Parent(nullptr) {} - - // Accessors. - DIEAbbrev &getAbbrev() { return Abbrev; } - const DIEAbbrev &getAbbrev() const { return Abbrev; } - unsigned getAbbrevNumber() const { return Abbrev.getNumber(); } - dwarf::Tag getTag() const { return Abbrev.getTag(); } - unsigned getOffset() const { return Offset; } - unsigned getSize() const { return Size; } - const std::vector> &getChildren() const { - return Children; - } - const SmallVectorImpl &getValues() const { return Values; } - DIE *getParent() const { return Parent; } - /// Climb up the parent chain to get the compile or type unit DIE this DIE - /// belongs to. - const DIE *getUnit() const; - /// Similar to getUnit, returns null when DIE is not added to an - /// owner yet. - const DIE *getUnitOrNull() const; - void setOffset(unsigned O) { Offset = O; } - void setSize(unsigned S) { Size = S; } - - /// addValue - Add a value and attributes to a DIE. - /// - void addValue(dwarf::Attribute Attribute, dwarf::Form Form, DIEValue *Value) { - Abbrev.AddAttribute(Attribute, Form); - Values.push_back(Value); - } - - /// addChild - Add a child to the DIE. - /// - void addChild(std::unique_ptr Child) { - assert(!Child->getParent()); - Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); - Child->Parent = this; - Children.push_back(std::move(Child)); - } - - /// findAttribute - Find a value in the DIE with the attribute given, - /// returns NULL if no such attribute exists. - DIEValue *findAttribute(dwarf::Attribute Attribute) const; - -#ifndef NDEBUG - void print(raw_ostream &O, unsigned IndentCount = 0) const; - void dump(); -#endif -}; - -//===--------------------------------------------------------------------===// -/// DIEValue - A debug information entry value. Some of these roughly correlate -/// to DWARF attribute classes. -/// -class DIEValue { - virtual void anchor(); - -public: - enum Type { - isInteger, - isString, - isExpr, - isLabel, - isDelta, - isEntry, - isTypeSignature, - isBlock, - isLoc, - isLocList, - }; - -protected: - /// Ty - Type of data stored in the value. - /// - Type Ty; - - explicit DIEValue(Type T) : Ty(T) {} - virtual ~DIEValue() {} - -public: - // Accessors - Type getType() const { return Ty; } - - /// EmitValue - Emit value via the Dwarf writer. - /// - virtual void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const = 0; - - /// SizeOf - Return the size of a value in bytes. - /// - virtual unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const = 0; - -#ifndef NDEBUG - virtual void print(raw_ostream &O) const = 0; - void dump() const; -#endif -}; - //===--------------------------------------------------------------------===// /// DIEInteger - An integer value DIE. /// -class DIEInteger : public DIEValue { +class DIEInteger { uint64_t Integer; public: - explicit DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {} + explicit DIEInteger(uint64_t I) : Integer(I) {} /// BestForm - Choose the best form for integer. /// @@ -273,137 +137,94 @@ class DIEInteger : public DIEValue { return dwarf::DW_FORM_data8; } - /// EmitValue - Emit integer of appropriate size. - /// - void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const override; - uint64_t getValue() const { return Integer; } void setValue(uint64_t Val) { Integer = Val; } - /// SizeOf - Determine size of integer value in bytes. - /// - unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const override; - - // Implement isa/cast/dyncast. - static bool classof(const DIEValue *I) { return I->getType() == isInteger; } + void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const; #ifndef NDEBUG - void print(raw_ostream &O) const override; + void print(raw_ostream &O) const; #endif }; //===--------------------------------------------------------------------===// /// DIEExpr - An expression DIE. // -class DIEExpr : public DIEValue { +class DIEExpr { const MCExpr *Expr; public: - explicit DIEExpr(const MCExpr *E) : DIEValue(isExpr), Expr(E) {} - - /// EmitValue - Emit expression value. - /// - void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const override; + explicit DIEExpr(const MCExpr *E) : Expr(E) {} /// getValue - Get MCExpr. /// const MCExpr *getValue() const { return Expr; } - /// SizeOf - Determine size of expression value in bytes. - /// - unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const override; - - // Implement isa/cast/dyncast. - static bool classof(const DIEValue *E) { return E->getType() == isExpr; } + void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const; #ifndef NDEBUG - void print(raw_ostream &O) const override; + void print(raw_ostream &O) const; #endif }; //===--------------------------------------------------------------------===// /// DIELabel - A label DIE. // -class DIELabel : public DIEValue { +class DIELabel { const MCSymbol *Label; public: - explicit DIELabel(const MCSymbol *L) : DIEValue(isLabel), Label(L) {} - - /// EmitValue - Emit label value. - /// - void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const override; + explicit DIELabel(const MCSymbol *L) : Label(L) {} /// getValue - Get MCSymbol. /// const MCSymbol *getValue() const { return Label; } - /// SizeOf - Determine size of label value in bytes. - /// - unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const override; - - // Implement isa/cast/dyncast. - static bool classof(const DIEValue *L) { return L->getType() == isLabel; } + void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const; #ifndef NDEBUG - void print(raw_ostream &O) const override; + void print(raw_ostream &O) const; #endif }; //===--------------------------------------------------------------------===// /// DIEDelta - A simple label difference DIE. /// -class DIEDelta : public DIEValue { +class DIEDelta { const MCSymbol *LabelHi; const MCSymbol *LabelLo; public: - DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo) - : DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {} - - /// EmitValue - Emit delta value. - /// - void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const override; - - /// SizeOf - Determine size of delta value in bytes. - /// - unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const override; + DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo) : LabelHi(Hi), LabelLo(Lo) {} - // Implement isa/cast/dyncast. - static bool classof(const DIEValue *D) { return D->getType() == isDelta; } + void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const; #ifndef NDEBUG - void print(raw_ostream &O) const override; + void print(raw_ostream &O) const; #endif }; //===--------------------------------------------------------------------===// /// DIEString - A container for string values. /// -class DIEString : public DIEValue { - const DIEValue *Access; - StringRef Str; +class DIEString { + DwarfStringPoolEntryRef S; public: - DIEString(const DIEValue *Acc, StringRef S) - : DIEValue(isString), Access(Acc), Str(S) {} + DIEString(DwarfStringPoolEntryRef S) : S(S) {} /// getString - Grab the string out of the object. - StringRef getString() const { return Str; } + StringRef getString() const { return S.getString(); } - /// EmitValue - Emit delta value. - /// - void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const override; - - /// SizeOf - Determine size of delta value in bytes. - /// - unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const override; - - // Implement isa/cast/dyncast. - static bool classof(const DIEValue *D) { return D->getType() == isString; } + void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const; #ifndef NDEBUG - void print(raw_ostream &O) const override; + void print(raw_ostream &O) const; #endif }; @@ -411,72 +232,524 @@ class DIEString : public DIEValue { /// DIEEntry - A pointer to another debug information entry. An instance of /// this class can also be used as a proxy for a debug information entry not /// yet defined (ie. types.) -class DIEEntry : public DIEValue { - DIE &Entry; +class DIE; +class DIEEntry { + DIE *Entry; + + DIEEntry() = delete; public: - explicit DIEEntry(DIE &E) : DIEValue(isEntry), Entry(E) { - } + explicit DIEEntry(DIE &E) : Entry(&E) {} - DIE &getEntry() const { return Entry; } + DIE &getEntry() const { return *Entry; } - /// EmitValue - Emit debug information entry offset. - /// - void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const override; + /// Returns size of a ref_addr entry. + static unsigned getRefAddrSize(const AsmPrinter *AP); - /// SizeOf - Determine size of debug information entry in bytes. - /// - unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const override { + void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { return Form == dwarf::DW_FORM_ref_addr ? getRefAddrSize(AP) : sizeof(int32_t); } - /// Returns size of a ref_addr entry. - static unsigned getRefAddrSize(const AsmPrinter *AP); - - // Implement isa/cast/dyncast. - static bool classof(const DIEValue *E) { return E->getType() == isEntry; } - #ifndef NDEBUG - void print(raw_ostream &O) const override; + void print(raw_ostream &O) const; #endif }; //===--------------------------------------------------------------------===// /// \brief A signature reference to a type unit. -class DIETypeSignature : public DIEValue { - const DwarfTypeUnit &Unit; +class DIETypeSignature { + const DwarfTypeUnit *Unit; -public: - explicit DIETypeSignature(const DwarfTypeUnit &Unit) - : DIEValue(isTypeSignature), Unit(Unit) {} + DIETypeSignature() = delete; - /// \brief Emit type unit signature. - void EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const override; +public: + explicit DIETypeSignature(const DwarfTypeUnit &Unit) : Unit(&Unit) {} - /// Returns size of a ref_sig8 entry. - unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const override { + void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const { assert(Form == dwarf::DW_FORM_ref_sig8); return 8; } - // \brief Implement isa/cast/dyncast. - static bool classof(const DIEValue *E) { - return E->getType() == isTypeSignature; +#ifndef NDEBUG + void print(raw_ostream &O) const; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIELocList - Represents a pointer to a location list in the debug_loc +/// section. +// +class DIELocList { + // Index into the .debug_loc vector. + size_t Index; + +public: + DIELocList(size_t I) : Index(I) {} + + /// getValue - Grab the current index out. + size_t getValue() const { return Index; } + + void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const; + +#ifndef NDEBUG + void print(raw_ostream &O) const; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEValue - A debug information entry value. Some of these roughly correlate +/// to DWARF attribute classes. +/// +class DIEBlock; +class DIELoc; +class DIEValue { +public: + enum Type { + isNone, +#define HANDLE_DIEVALUE(T) is##T, +#include "llvm/CodeGen/DIEValue.def" + }; + +private: + /// Ty - Type of data stored in the value. + /// + Type Ty = isNone; + dwarf::Attribute Attribute = (dwarf::Attribute)0; + dwarf::Form Form = (dwarf::Form)0; + + /// Storage for the value. + /// + /// All values that aren't standard layout (or are larger than 8 bytes) + /// should be stored by reference instead of by value. + typedef AlignedCharArrayUnion ValTy; + static_assert(sizeof(ValTy) <= sizeof(uint64_t) || + sizeof(ValTy) <= sizeof(void *), + "Expected all large types to be stored via pointer"); + + /// Underlying stored value. + ValTy Val; + + template void construct(T V) { + static_assert(std::is_standard_layout::value || + std::is_pointer::value, + "Expected standard layout or pointer"); + new (reinterpret_cast(Val.buffer)) T(V); + } + + template T *get() { return reinterpret_cast(Val.buffer); } + template const T *get() const { + return reinterpret_cast(Val.buffer); + } + template void destruct() { get()->~T(); } + + /// Destroy the underlying value. + /// + /// This should get optimized down to a no-op. We could skip it if we could + /// add a static assert on \a std::is_trivially_copyable(), but we currently + /// support versions of GCC that don't understand that. + void destroyVal() { + switch (Ty) { + case isNone: + return; +#define HANDLE_DIEVALUE_SMALL(T) \ + case is##T: \ + destruct(); + return; +#define HANDLE_DIEVALUE_LARGE(T) \ + case is##T: \ + destruct(); + return; +#include "llvm/CodeGen/DIEValue.def" + } + } + + /// Copy the underlying value. + /// + /// This should get optimized down to a simple copy. We need to actually + /// construct the value, rather than calling memcpy, to satisfy strict + /// aliasing rules. + void copyVal(const DIEValue &X) { + switch (Ty) { + case isNone: + return; +#define HANDLE_DIEVALUE_SMALL(T) \ + case is##T: \ + construct(*X.get()); \ + return; +#define HANDLE_DIEVALUE_LARGE(T) \ + case is##T: \ + construct(*X.get()); \ + return; +#include "llvm/CodeGen/DIEValue.def" + } + } + +public: + DIEValue() = default; + DIEValue(const DIEValue &X) : Ty(X.Ty), Attribute(X.Attribute), Form(X.Form) { + copyVal(X); + } + DIEValue &operator=(const DIEValue &X) { + destroyVal(); + Ty = X.Ty; + Attribute = X.Attribute; + Form = X.Form; + copyVal(X); + return *this; + } + ~DIEValue() { destroyVal(); } + +#define HANDLE_DIEVALUE_SMALL(T) \ + DIEValue(dwarf::Attribute Attribute, dwarf::Form Form, const DIE##T &V) \ + : Ty(is##T), Attribute(Attribute), Form(Form) { \ + construct(V); \ } +#define HANDLE_DIEVALUE_LARGE(T) \ + DIEValue(dwarf::Attribute Attribute, dwarf::Form Form, const DIE##T *V) \ + : Ty(is##T), Attribute(Attribute), Form(Form) { \ + assert(V && "Expected valid value"); \ + construct(V); \ + } +#include "llvm/CodeGen/DIEValue.def" + + // Accessors + Type getType() const { return Ty; } + dwarf::Attribute getAttribute() const { return Attribute; } + dwarf::Form getForm() const { return Form; } + explicit operator bool() const { return Ty; } + +#define HANDLE_DIEVALUE_SMALL(T) \ + const DIE##T &getDIE##T() const { \ + assert(getType() == is##T && "Expected " #T); \ + return *get(); \ + } +#define HANDLE_DIEVALUE_LARGE(T) \ + const DIE##T &getDIE##T() const { \ + assert(getType() == is##T && "Expected " #T); \ + return **get(); \ + } +#include "llvm/CodeGen/DIEValue.def" + + /// EmitValue - Emit value via the Dwarf writer. + /// + void EmitValue(const AsmPrinter *AP) const; + + /// SizeOf - Return the size of a value in bytes. + /// + unsigned SizeOf(const AsmPrinter *AP) const; + #ifndef NDEBUG - void print(raw_ostream &O) const override; + void print(raw_ostream &O) const; void dump() const; #endif }; +struct IntrusiveBackListNode { + PointerIntPair Next; + IntrusiveBackListNode() : Next(this, true) {} + + IntrusiveBackListNode *getNext() const { + return Next.getInt() ? nullptr : Next.getPointer(); + } +}; + +struct IntrusiveBackListBase { + typedef IntrusiveBackListNode Node; + Node *Last = nullptr; + + bool empty() const { return !Last; } + void push_back(Node &N) { + assert(N.Next.getPointer() == &N && "Expected unlinked node"); + assert(N.Next.getInt() == true && "Expected unlinked node"); + + if (Last) { + N.Next = Last->Next; + Last->Next.setPointerAndInt(&N, false); + } + Last = &N; + } +}; + +template class IntrusiveBackList : IntrusiveBackListBase { +public: + using IntrusiveBackListBase::empty; + void push_back(T &N) { IntrusiveBackListBase::push_back(N); } + T &back() { return *static_cast(Last); } + const T &back() const { return *static_cast(Last); } + + class const_iterator; + class iterator + : public iterator_facade_base { + friend class const_iterator; + Node *N = nullptr; + + public: + iterator() = default; + explicit iterator(T *N) : N(N) {} + + iterator &operator++() { + N = N->getNext(); + return *this; + } + + explicit operator bool() const { return N; } + T &operator*() const { return *static_cast(N); } + + bool operator==(const iterator &X) const { return N == X.N; } + bool operator!=(const iterator &X) const { return N != X.N; } + }; + + class const_iterator + : public iterator_facade_base { + const Node *N = nullptr; + + public: + const_iterator() = default; + // Placate MSVC by explicitly scoping 'iterator'. + const_iterator(typename IntrusiveBackList::iterator X) : N(X.N) {} + explicit const_iterator(const T *N) : N(N) {} + + const_iterator &operator++() { + N = N->getNext(); + return *this; + } + + explicit operator bool() const { return N; } + const T &operator*() const { return *static_cast(N); } + + bool operator==(const const_iterator &X) const { return N == X.N; } + bool operator!=(const const_iterator &X) const { return N != X.N; } + }; + + iterator begin() { + return Last ? iterator(static_cast(Last->Next.getPointer())) : end(); + } + const_iterator begin() const { + return const_cast(this)->begin(); + } + iterator end() { return iterator(); } + const_iterator end() const { return const_iterator(); } + + static iterator toIterator(T &N) { return iterator(&N); } + static const_iterator toIterator(const T &N) { return const_iterator(&N); } +}; + +/// A list of DIE values. +/// +/// This is a singly-linked list, but instead of reversing the order of +/// insertion, we keep a pointer to the back of the list so we can push in +/// order. +/// +/// There are two main reasons to choose a linked list over a customized +/// vector-like data structure. +/// +/// 1. For teardown efficiency, we want DIEs to be BumpPtrAllocated. Using a +/// linked list here makes this way easier to accomplish. +/// 2. Carrying an extra pointer per \a DIEValue isn't expensive. 45% of DIEs +/// have 2 or fewer values, and 90% have 5 or fewer. A vector would be +/// over-allocated by 50% on average anyway, the same cost as the +/// linked-list node. +class DIEValueList { + struct Node : IntrusiveBackListNode { + DIEValue V; + explicit Node(DIEValue V) : V(V) {} + }; + + typedef IntrusiveBackList ListTy; + ListTy List; + +public: + bool empty() const { return List.empty(); } + + class const_iterator; + class iterator + : public iterator_adaptor_base { + friend class const_iterator; + typedef iterator_adaptor_base iterator_adaptor; + + public: + iterator() = default; + explicit iterator(ListTy::iterator X) : iterator_adaptor(X) {} + + explicit operator bool() const { return bool(wrapped()); } + DIEValue &operator*() const { return wrapped()->V; } + }; + + class const_iterator + : public iterator_adaptor_base { + typedef iterator_adaptor_base iterator_adaptor; + + public: + const_iterator() = default; + const_iterator(DIEValueList::iterator X) : iterator_adaptor(X.wrapped()) {} + explicit const_iterator(ListTy::const_iterator X) : iterator_adaptor(X) {} + + explicit operator bool() const { return bool(wrapped()); } + const DIEValue &operator*() const { return wrapped()->V; } + }; + + iterator insert(BumpPtrAllocator &Alloc, DIEValue V) { + List.push_back(*new (Alloc) Node(V)); + return iterator(ListTy::toIterator(List.back())); + } + template + iterator emplace(BumpPtrAllocator &Alloc, Ts &&... Args) { + return insert(Alloc, DIEValue(std::forward(Args)...)); + } + + iterator begin() { return iterator(List.begin()); } + iterator end() { return iterator(List.end()); } + const_iterator begin() const { return const_iterator(List.begin()); } + const_iterator end() const { return const_iterator(List.end()); } +}; + +//===--------------------------------------------------------------------===// +/// DIE - A structured debug information entry. Has an abbreviation which +/// describes its organization. +class DIE : IntrusiveBackListNode { + friend class IntrusiveBackList; + +protected: + /// Offset - Offset in debug info section. + /// + unsigned Offset; + + /// Size - Size of instance + children. + /// + unsigned Size; + + unsigned AbbrevNumber = ~0u; + + /// Tag - Dwarf tag code. + /// + dwarf::Tag Tag = (dwarf::Tag)0; + + /// Children DIEs. + IntrusiveBackList Children; + + DIE *Parent = nullptr; + + /// Attribute values. + /// + DIEValueList Values; + +protected: + DIE() : Offset(0), Size(0) {} + +private: + explicit DIE(dwarf::Tag Tag) : Offset(0), Size(0), Tag(Tag) {} + +public: + static DIE *get(BumpPtrAllocator &Alloc, dwarf::Tag Tag) { + return new (Alloc) DIE(Tag); + } + + // Accessors. + unsigned getAbbrevNumber() const { return AbbrevNumber; } + dwarf::Tag getTag() const { return Tag; } + unsigned getOffset() const { return Offset; } + unsigned getSize() const { return Size; } + bool hasChildren() const { return !Children.empty(); } + + typedef IntrusiveBackList::iterator child_iterator; + typedef IntrusiveBackList::const_iterator const_child_iterator; + typedef iterator_range child_range; + typedef iterator_range const_child_range; + + child_range children() { + return llvm::make_range(Children.begin(), Children.end()); + } + const_child_range children() const { + return llvm::make_range(Children.begin(), Children.end()); + } + + typedef DIEValueList::iterator value_iterator; + typedef iterator_range value_range; + + value_range values() { + return llvm::make_range(Values.begin(), Values.end()); + } + + typedef DIEValueList::const_iterator const_value_iterator; + typedef iterator_range const_value_range; + + const_value_range values() const { + return llvm::make_range(Values.begin(), Values.end()); + } + + DIE *getParent() const { return Parent; } + + /// Generate the abbreviation for this DIE. + /// + /// Calculate the abbreviation for this, which should be uniqued and + /// eventually used to call \a setAbbrevNumber(). + DIEAbbrev generateAbbrev() const; + + /// Set the abbreviation number for this DIE. + void setAbbrevNumber(unsigned I) { AbbrevNumber = I; } + + /// Climb up the parent chain to get the compile or type unit DIE this DIE + /// belongs to. + const DIE *getUnit() const; + /// Similar to getUnit, returns null when DIE is not added to an + /// owner yet. + const DIE *getUnitOrNull() const; + void setOffset(unsigned O) { Offset = O; } + void setSize(unsigned S) { Size = S; } + + /// addValue - Add a value and attributes to a DIE. + /// + value_iterator addValue(BumpPtrAllocator &Alloc, DIEValue Value) { + return Values.insert(Alloc, Value); + } + template + value_iterator addValue(BumpPtrAllocator &Alloc, dwarf::Attribute Attribute, + dwarf::Form Form, T &&Value) { + return Values.emplace(Alloc, Attribute, Form, std::forward(Value)); + } + + /// Add a child to the DIE. + DIE &addChild(DIE *Child) { + assert(!Child->getParent() && "Child should be orphaned"); + Child->Parent = this; + Children.push_back(*Child); + return Children.back(); + } + + /// Find a value in the DIE with the attribute given. + /// + /// Returns a default-constructed DIEValue (where \a DIEValue::getType() + /// gives \a DIEValue::isNone) if no such attribute exists. + DIEValue findAttribute(dwarf::Attribute Attribute) const; + +#ifndef NDEBUG + void print(raw_ostream &O, unsigned IndentCount = 0) const; + void dump(); +#endif +}; + //===--------------------------------------------------------------------===// /// DIELoc - Represents an expression location. // -class DIELoc : public DIEValue, public DIE { +class DIELoc : public DIE { mutable unsigned Size; // Size in bytes excluding size header. + public: - DIELoc() : DIEValue(isLoc), Size(0) {} + DIELoc() : Size(0) {} /// ComputeSize - Calculate the size of the location expression. /// @@ -497,29 +770,22 @@ class DIELoc : public DIEValue, public DIE { return dwarf::DW_FORM_block; } - /// EmitValue - Emit location data. - /// - void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const override; - - /// SizeOf - Determine size of location data in bytes. - /// - unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const override; - - // Implement isa/cast/dyncast. - static bool classof(const DIEValue *E) { return E->getType() == isLoc; } + void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const; #ifndef NDEBUG - void print(raw_ostream &O) const override; + void print(raw_ostream &O) const; #endif }; //===--------------------------------------------------------------------===// /// DIEBlock - Represents a block of values. // -class DIEBlock : public DIEValue, public DIE { +class DIEBlock : public DIE { mutable unsigned Size; // Size in bytes excluding size header. + public: - DIEBlock() : DIEValue(isBlock), Size(0) {} + DIEBlock() : Size(0) {} /// ComputeSize - Calculate the size of the location expression. /// @@ -537,49 +803,11 @@ class DIEBlock : public DIEValue, public DIE { return dwarf::DW_FORM_block; } - /// EmitValue - Emit location data. - /// - void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const override; - - /// SizeOf - Determine size of location data in bytes. - /// - unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const override; - - // Implement isa/cast/dyncast. - static bool classof(const DIEValue *E) { return E->getType() == isBlock; } - -#ifndef NDEBUG - void print(raw_ostream &O) const override; -#endif -}; - -//===--------------------------------------------------------------------===// -/// DIELocList - Represents a pointer to a location list in the debug_loc -/// section. -// -class DIELocList : public DIEValue { - // Index into the .debug_loc vector. - size_t Index; - -public: - DIELocList(size_t I) : DIEValue(isLocList), Index(I) {} - - /// getValue - Grab the current index out. - size_t getValue() const { return Index; } - - /// EmitValue - Emit location data. - /// - void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const override; - - /// SizeOf - Determine size of location data in bytes. - /// - unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const override; - - // Implement isa/cast/dyncast. - static bool classof(const DIEValue *E) { return E->getType() == isLocList; } + void EmitValue(const AsmPrinter *AP, dwarf::Form Form) const; + unsigned SizeOf(const AsmPrinter *AP, dwarf::Form Form) const; #ifndef NDEBUG - void print(raw_ostream &O) const override; + void print(raw_ostream &O) const; #endif }; diff --git a/include/llvm/CodeGen/DIEValue.def b/include/llvm/CodeGen/DIEValue.def new file mode 100644 index 00000000000..2cfae7b608c --- /dev/null +++ b/include/llvm/CodeGen/DIEValue.def @@ -0,0 +1,47 @@ +//===- llvm/CodeGen/DIEValue.def - DIEValue types ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Macros for running through all types of DIEValue. +// +//===----------------------------------------------------------------------===// + +#if !(defined HANDLE_DIEVALUE || defined HANDLE_DIEVALUE_SMALL || \ + defined HANDLE_DIEVALUE_LARGE) +#error "Missing macro definition of HANDLE_DIEVALUE" +#endif + +// Handler for all values. +#ifndef HANDLE_DIEVALUE +#define HANDLE_DIEVALUE(T) +#endif + +// Handler for small values. +#ifndef HANDLE_DIEVALUE_SMALL +#define HANDLE_DIEVALUE_SMALL(T) HANDLE_DIEVALUE(T) +#endif + +// Handler for large values. +#ifndef HANDLE_DIEVALUE_LARGE +#define HANDLE_DIEVALUE_LARGE(T) HANDLE_DIEVALUE(T) +#endif + +HANDLE_DIEVALUE_SMALL(Integer) +HANDLE_DIEVALUE_SMALL(String) +HANDLE_DIEVALUE_SMALL(Expr) +HANDLE_DIEVALUE_SMALL(Label) +HANDLE_DIEVALUE_LARGE(Delta) +HANDLE_DIEVALUE_SMALL(Entry) +HANDLE_DIEVALUE_SMALL(TypeSignature) +HANDLE_DIEVALUE_LARGE(Block) +HANDLE_DIEVALUE_LARGE(Loc) +HANDLE_DIEVALUE_SMALL(LocList) + +#undef HANDLE_DIEVALUE +#undef HANDLE_DIEVALUE_SMALL +#undef HANDLE_DIEVALUE_LARGE diff --git a/include/llvm/CodeGen/DwarfStringPoolEntry.h b/include/llvm/CodeGen/DwarfStringPoolEntry.h new file mode 100644 index 00000000000..fc2b5ddd2d2 --- /dev/null +++ b/include/llvm/CodeGen/DwarfStringPoolEntry.h @@ -0,0 +1,51 @@ +//===- llvm/CodeGen/DwarfStringPoolEntry.h - String pool entry --*- 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_DWARFSTRINGPOOLENTRY_H +#define LLVM_CODEGEN_DWARFSTRINGPOOLENTRY_H + +#include "llvm/ADT/StringMap.h" + +namespace llvm { + +class MCSymbol; + +/// Data for a string pool entry. +struct DwarfStringPoolEntry { + MCSymbol *Symbol; + unsigned Offset; + unsigned Index; +}; + +/// String pool entry reference. +struct DwarfStringPoolEntryRef { + const StringMapEntry *I = nullptr; + +public: + DwarfStringPoolEntryRef() = default; + explicit DwarfStringPoolEntryRef( + const StringMapEntry &I) + : I(&I) {} + + explicit operator bool() const { return I; } + MCSymbol *getSymbol() const { + assert(I->second.Symbol && "No symbol available!"); + return I->second.Symbol; + } + unsigned getOffset() const { return I->second.Offset; } + unsigned getIndex() const { return I->second.Index; } + StringRef getString() const { return I->first(); } + + bool operator==(const DwarfStringPoolEntryRef &X) const { return I == X.I; } + bool operator!=(const DwarfStringPoolEntryRef &X) const { return I != X.I; } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 1dca2ce1ab2..f04a7cd6966 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -69,7 +69,7 @@ class FastISel { unsigned NumFixedArgs; CallingConv::ID CallConv; const Value *Callee; - const char *SymName; + MCSymbol *Symbol; ArgListTy Args; ImmutableCallSite *CS; MachineInstr *Call; @@ -88,7 +88,7 @@ class FastISel { : RetTy(nullptr), RetSExt(false), RetZExt(false), IsVarArg(false), IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true), IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C), - Callee(nullptr), SymName(nullptr), CS(nullptr), Call(nullptr), + Callee(nullptr), Symbol(nullptr), CS(nullptr), Call(nullptr), ResultReg(0), NumResultRegs(0), IsPatchPoint(false) {} CallLoweringInfo &setCallee(Type *ResultTy, FunctionType *FuncTy, @@ -114,12 +114,12 @@ class FastISel { } CallLoweringInfo &setCallee(Type *ResultTy, FunctionType *FuncTy, - const char *Target, ArgListTy &&ArgsList, + MCSymbol *Target, ArgListTy &&ArgsList, ImmutableCallSite &Call, unsigned FixedArgs = ~0U) { RetTy = ResultTy; Callee = Call.getCalledValue(); - SymName = Target; + Symbol = Target; IsInReg = Call.paramHasAttr(0, Attribute::InReg); DoesNotReturn = Call.doesNotReturn(); @@ -148,11 +148,16 @@ class FastISel { return *this; } - CallLoweringInfo &setCallee(CallingConv::ID CC, Type *ResultTy, + CallLoweringInfo &setCallee(const DataLayout &DL, MCContext &Ctx, + CallingConv::ID CC, Type *ResultTy, const char *Target, ArgListTy &&ArgsList, + unsigned FixedArgs = ~0U); + + CallLoweringInfo &setCallee(CallingConv::ID CC, Type *ResultTy, + MCSymbol *Target, ArgListTy &&ArgsList, unsigned FixedArgs = ~0U) { RetTy = ResultTy; - SymName = Target; + Symbol = Target; CallConv = CC; Args = std::move(ArgsList); NumFixedArgs = (FixedArgs == ~0U) ? Args.size() : FixedArgs; @@ -504,7 +509,9 @@ class FastISel { CmpInst::Predicate optimizeCmpPredicate(const CmpInst *CI) const; - bool lowerCallTo(const CallInst *CI, const char *SymName, unsigned NumArgs); + bool lowerCallTo(const CallInst *CI, MCSymbol *Symbol, unsigned NumArgs); + bool lowerCallTo(const CallInst *CI, const char *SymbolName, + unsigned NumArgs); bool lowerCallTo(CallLoweringInfo &CLI); bool isCommutativeIntrinsic(IntrinsicInst const *II) { diff --git a/include/llvm/CodeGen/FaultMaps.h b/include/llvm/CodeGen/FaultMaps.h new file mode 100644 index 00000000000..f4b64632214 --- /dev/null +++ b/include/llvm/CodeGen/FaultMaps.h @@ -0,0 +1,220 @@ +//===------------------- FaultMaps.h - The "FaultMaps" section --*- 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 "llvm/Support/Endian.h" +#include "llvm/Support/Format.h" + +#include +#include + +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 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 + FunctionInfos; + AsmPrinter &AP; + + void emitFunctionInfo(const MCSymbol *FnLabel, const FunctionFaultInfos &FFI); +}; + +/// A parser for the __llvm_faultmaps section generated by the FaultMaps class +/// above. This parser is version locked with with the __llvm_faultmaps section +/// generated by the version of LLVM that includes it. No guarantees are made +/// with respect to forward or backward compatibility. +class FaultMapParser { + typedef uint8_t FaultMapVersionType; + static const size_t FaultMapVersionOffset = 0; + + typedef uint8_t Reserved0Type; + static const size_t Reserved0Offset = + FaultMapVersionOffset + sizeof(FaultMapVersionType); + + typedef uint16_t Reserved1Type; + static const size_t Reserved1Offset = Reserved0Offset + sizeof(Reserved0Type); + + typedef uint32_t NumFunctionsType; + static const size_t NumFunctionsOffset = + Reserved1Offset + sizeof(Reserved1Type); + + static const size_t FunctionInfosOffset = + NumFunctionsOffset + sizeof(NumFunctionsType); + + const uint8_t *P; + const uint8_t *E; + + template static T read(const uint8_t *P, const uint8_t *E) { + assert(P + sizeof(T) <= E && "out of bounds read!"); + return support::endian::read(P); + } + +public: + class FunctionFaultInfoAccessor { + typedef uint32_t FaultKindType; + static const size_t FaultKindOffset = 0; + + typedef uint32_t FaultingPCOffsetType; + static const size_t FaultingPCOffsetOffset = + FaultKindOffset + sizeof(FaultKindType); + + typedef uint32_t HandlerPCOffsetType; + static const size_t HandlerPCOffsetOffset = + FaultingPCOffsetOffset + sizeof(FaultingPCOffsetType); + + const uint8_t *P; + const uint8_t *E; + + public: + static const size_t Size = + HandlerPCOffsetOffset + sizeof(HandlerPCOffsetType); + + explicit FunctionFaultInfoAccessor(const uint8_t *P, const uint8_t *E) + : P(P), E(E) {} + + FaultKindType getFaultKind() const { + return read(P + FaultKindOffset, E); + } + + FaultingPCOffsetType getFaultingPCOffset() const { + return read(P + FaultingPCOffsetOffset, E); + } + + HandlerPCOffsetType getHandlerPCOffset() const { + return read(P + HandlerPCOffsetOffset, E); + } + }; + + class FunctionInfoAccessor { + typedef uint64_t FunctionAddrType; + static const size_t FunctionAddrOffset = 0; + + typedef uint32_t NumFaultingPCsType; + static const size_t NumFaultingPCsOffset = + FunctionAddrOffset + sizeof(FunctionAddrType); + + typedef uint32_t ReservedType; + static const size_t ReservedOffset = + NumFaultingPCsOffset + sizeof(NumFaultingPCsType); + + static const size_t FunctionFaultInfosOffset = + ReservedOffset + sizeof(ReservedType); + + static const size_t FunctionInfoHeaderSize = FunctionFaultInfosOffset; + + const uint8_t *P; + const uint8_t *E; + + public: + FunctionInfoAccessor() : P(nullptr), E(nullptr) {} + + explicit FunctionInfoAccessor(const uint8_t *P, const uint8_t *E) + : P(P), E(E) {} + + FunctionAddrType getFunctionAddr() const { + return read(P + FunctionAddrOffset, E); + } + + NumFaultingPCsType getNumFaultingPCs() const { + return read(P + NumFaultingPCsOffset, E); + } + + FunctionFaultInfoAccessor getFunctionFaultInfoAt(uint32_t Index) const { + assert(Index < getNumFaultingPCs() && "index out of bounds!"); + const uint8_t *Begin = P + FunctionFaultInfosOffset + + FunctionFaultInfoAccessor::Size * Index; + return FunctionFaultInfoAccessor(Begin, E); + } + + FunctionInfoAccessor getNextFunctionInfo() const { + size_t MySize = FunctionInfoHeaderSize + + getNumFaultingPCs() * FunctionFaultInfoAccessor::Size; + + const uint8_t *Begin = P + MySize; + assert(Begin < E && "out of bounds!"); + return FunctionInfoAccessor(Begin, E); + } + }; + + explicit FaultMapParser(const uint8_t *Begin, const uint8_t *End) + : P(Begin), E(End) {} + + FaultMapVersionType getFaultMapVersion() const { + auto Version = read(P + FaultMapVersionOffset, E); + assert(Version == 1 && "only version 1 supported!"); + return Version; + } + + NumFunctionsType getNumFunctions() const { + return read(P + NumFunctionsOffset, E); + } + + FunctionInfoAccessor getFirstFunctionInfo() const { + const uint8_t *Begin = P + FunctionInfosOffset; + return FunctionInfoAccessor(Begin, E); + } +}; + +raw_ostream & +operator<<(raw_ostream &OS, const FaultMapParser::FunctionFaultInfoAccessor &); + +raw_ostream &operator<<(raw_ostream &OS, + const FaultMapParser::FunctionInfoAccessor &); + +raw_ostream &operator<<(raw_ostream &OS, const FaultMapParser &); + +} // namespace llvm + +#endif diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h index e12866e04df..82c762ed850 100644 --- a/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -18,6 +18,7 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/ISDOpcodes.h" @@ -73,6 +74,16 @@ class FunctionLoweringInfo { /// cross-basic-block values. DenseMap ValueMap; + // Keep track of frame indices allocated for statepoints as they could be used + // across basic block boundaries. + // Key of the map is statepoint instruction, value is a map from spilled + // llvm Value to the optional stack stack slot index. + // If optional is unspecified it means that we have visited this value + // but didn't spill it. + typedef DenseMap> StatepointSpilledValueMapTy; + DenseMap + StatepointRelocatedValues; + /// StaticAllocaMap - Keep track of frame indices for fixed sized allocas in /// the entry block. This allows the allocas to be efficiently referenced /// anywhere in the function. @@ -221,6 +232,8 @@ class FunctionLoweringInfo { int getArgumentFrameIndex(const Argument *A); private: + void addSEHHandlersForLPads(ArrayRef LPads); + /// LiveOutRegInfo - Information about live out vregs. IndexedMap LiveOutRegInfo; }; diff --git a/include/llvm/CodeGen/GCMetadata.h b/include/llvm/CodeGen/GCMetadata.h index 357b2d8a7ca..e883bd196ea 100644 --- a/include/llvm/CodeGen/GCMetadata.h +++ b/include/llvm/CodeGen/GCMetadata.h @@ -121,7 +121,7 @@ class GCFunctionInfo { /// label just prior to the safe point (if the code generator is using /// MachineModuleInfo). void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) { - SafePoints.push_back(GCPoint(Kind, Label, DL)); + SafePoints.emplace_back(Kind, Label, DL); } /// getFrameSize/setFrameSize - Records the function's frame size. diff --git a/include/llvm/CodeGen/GCs.h b/include/llvm/CodeGen/GCs.h index 5bae41ea030..5207f801c84 100644 --- a/include/llvm/CodeGen/GCs.h +++ b/include/llvm/CodeGen/GCs.h @@ -21,6 +21,9 @@ class GCMetadataPrinter; /// FIXME: Collector instances are not useful on their own. These no longer /// serve any purpose except to link in the plugins. +/// Creates a CoreCLR-compatible garbage collector. +void linkCoreCLRGC(); + /// Creates an ocaml-compatible garbage collector. void linkOcamlGC(); diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index 9b439df0abb..49c002bf5f4 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -72,10 +72,13 @@ namespace ISD { /// the parent's frame or return address, and so on. FRAMEADDR, RETURNADDR, - /// FRAME_ALLOC_RECOVER - Represents the llvm.framerecover - /// intrinsic. Materializes the offset from the frame pointer of another - /// function to the result of llvm.frameallocate. - FRAME_ALLOC_RECOVER, + /// LOCAL_RECOVER - Represents the llvm.localrecover intrinsic. + /// Materializes the offset from the local object pointer of another + /// function to a particular local object passed to llvm.localescape. The + /// operand is the MCSymbol label used to represent this offset, since + /// typically the offset is not known until after code generation of the + /// parent. + LOCAL_RECOVER, /// READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on /// the DAG, which implements the named register global variables extension. @@ -105,6 +108,10 @@ namespace ISD { /// and returns an outchain. EH_SJLJ_LONGJMP, + /// OUTCHAIN = EH_SJLJ_SETUP_DISPATCH(INCHAIN) + /// The target initializes the dispatch table here. + EH_SJLJ_SETUP_DISPATCH, + /// TargetConstant* - Like Constant*, but the DAG does not do any folding, /// simplification, or lowering of the constant. They are used for constants /// which are known to fit in the immediate fields of their users, or for @@ -124,6 +131,8 @@ namespace ISD { TargetExternalSymbol, TargetBlockAddress, + MCSymbol, + /// TargetIndex - Like a constant pool entry, but with completely /// target-dependent semantics. Holds target flags, a 32-bit index, and a /// 64-bit index. Targets can use this however they like. @@ -239,8 +248,8 @@ namespace ISD { FMAD, /// FCOPYSIGN(X, Y) - Return the value of X with the sign of Y. NOTE: This - /// DAG node does not require that X and Y have the same type, just that the - /// are both floating point. X and the result must have the same type. + /// DAG node does not require that X and Y have the same type, just that + /// they are both floating point. X and the result must have the same type. /// FCOPYSIGN(f32, f64) is allowed. FCOPYSIGN, @@ -308,6 +317,10 @@ namespace ISD { /// part. MULHU, MULHS, + /// [US]{MIN/MAX} - Binary minimum or maximum or signed or unsigned + /// integers. + SMIN, SMAX, UMIN, UMAX, + /// Bitwise operators - logical and, logical or, logical xor. AND, OR, XOR, @@ -325,6 +338,10 @@ namespace ISD { /// Byte Swap and Counting operators. BSWAP, CTTZ, CTLZ, CTPOP, + /// [SU]ABSDIFF - Signed/Unsigned absolute difference of two input integer + /// vector. These nodes are generated from llvm.*absdiff* intrinsics. + SABSDIFF, UABSDIFF, + /// Bit counting operators with an undefined result for zero inputs. CTTZ_ZERO_UNDEF, CTLZ_ZERO_UNDEF, @@ -687,19 +704,28 @@ namespace ISD { ATOMIC_LOAD_UMIN, ATOMIC_LOAD_UMAX, - // Masked load and store + // Masked load and store - consecutive vector load and store operations + // with additional mask operand that prevents memory accesses to the + // masked-off lanes. MLOAD, MSTORE, + // Masked gather and scatter - load and store operations for a vector of + // random addresses with additional mask operand that prevents memory + // accesses to the masked-off lanes. + MGATHER, MSCATTER, + /// This corresponds to the llvm.lifetime.* intrinsics. The first operand /// is the chain and the second operand is the alloca pointer. LIFETIME_START, LIFETIME_END, - // @LOCALMOD-BEGIN - // NACL_* - Native Client instrinsics. - // NACL_READ_TP is a fast built-in version of NaCl's tls_get() IRT - // interface. - NACL_READ_TP, - // @LOCALMOD-END + /// GC_TRANSITION_START/GC_TRANSITION_END - These operators mark the + /// beginning and end of GC transition sequence, and carry arbitrary + /// information that target might need for lowering. The first operand is + /// a chain, the rest are specified by the target and not touched by the DAG + /// optimizers. GC_TRANSITION_START..GC_TRANSITION_END pairs may not be + /// nested. + GC_TRANSITION_START, + GC_TRANSITION_END, /// BUILTIN_OP_END - This must be the last enum value in this list. /// The target-specific pre-isel opcode values start here. @@ -710,7 +736,7 @@ namespace ISD { /// which do not reference a specific memory location should be less than /// this value. Those that do must not be less than this value, and can /// be used with SelectionDAG::getMemIntrinsicNode. - static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+200; + static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+300; //===--------------------------------------------------------------------===// /// MemIndexedMode enum - This enum defines the load / store indexed diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h index aa217d5519e..7d7e48af2a0 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -45,7 +45,7 @@ typedef std::pair InsnRange; class LexicalScope { public: - LexicalScope(LexicalScope *P, const MDLocalScope *D, const MDLocation *I, + LexicalScope(LexicalScope *P, const DILocalScope *D, const DILocation *I, bool A) : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A), LastInsn(nullptr), FirstInsn(nullptr), DFSIn(0), DFSOut(0) { @@ -58,8 +58,8 @@ class LexicalScope { // Accessors. LexicalScope *getParent() const { return Parent; } const MDNode *getDesc() const { return Desc; } - const MDLocation *getInlinedAt() const { return InlinedAtLocation; } - const MDLocalScope *getScopeNode() const { return Desc; } + const DILocation *getInlinedAt() const { return InlinedAtLocation; } + const DILocalScope *getScopeNode() const { return Desc; } bool isAbstractScope() const { return AbstractScope; } SmallVectorImpl &getChildren() { return Children; } SmallVectorImpl &getRanges() { return Ranges; } @@ -119,8 +119,8 @@ class LexicalScope { private: LexicalScope *Parent; // Parent to this scope. - const MDLocalScope *Desc; // Debug info descriptor. - const MDLocation *InlinedAtLocation; // Location at which this + const DILocalScope *Desc; // Debug info descriptor. + const DILocation *InlinedAtLocation; // Location at which this // scope is inlined. bool AbstractScope; // Abstract Scope SmallVector Children; // Scopes defined in scope. @@ -159,16 +159,16 @@ class LexicalScopes { /// getMachineBasicBlocks - Populate given set using machine basic blocks /// which have machine instructions that belong to lexical scope identified by /// DebugLoc. - void getMachineBasicBlocks(const MDLocation *DL, + void getMachineBasicBlocks(const DILocation *DL, SmallPtrSetImpl &MBBs); /// dominates - Return true if DebugLoc's lexical scope dominates at least one /// machine instruction's lexical scope in a given machine basic block. - bool dominates(const MDLocation *DL, MachineBasicBlock *MBB); + bool dominates(const DILocation *DL, MachineBasicBlock *MBB); /// findLexicalScope - Find lexical scope, either regular or inlined, for the /// given DebugLoc. Return NULL if not found. - LexicalScope *findLexicalScope(const MDLocation *DL); + LexicalScope *findLexicalScope(const DILocation *DL); /// getAbstractScopesList - Return a reference to list of abstract scopes. ArrayRef getAbstractScopesList() const { @@ -176,19 +176,19 @@ class LexicalScopes { } /// findAbstractScope - Find an abstract scope or return null. - LexicalScope *findAbstractScope(const MDLocalScope *N) { + LexicalScope *findAbstractScope(const DILocalScope *N) { auto I = AbstractScopeMap.find(N); return I != AbstractScopeMap.end() ? &I->second : nullptr; } /// findInlinedScope - Find an inlined scope for the given scope/inlined-at. - LexicalScope *findInlinedScope(const MDLocalScope *N, const MDLocation *IA) { + LexicalScope *findInlinedScope(const DILocalScope *N, const DILocation *IA) { auto I = InlinedLexicalScopeMap.find(std::make_pair(N, IA)); return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr; } /// findLexicalScope - Find regular lexical scope or return null. - LexicalScope *findLexicalScope(const MDLocalScope *N) { + LexicalScope *findLexicalScope(const DILocalScope *N) { auto I = LexicalScopeMap.find(N); return I != LexicalScopeMap.end() ? &I->second : nullptr; } @@ -197,24 +197,24 @@ class LexicalScopes { void dump(); /// getOrCreateAbstractScope - Find or create an abstract lexical scope. - LexicalScope *getOrCreateAbstractScope(const MDLocalScope *Scope); + LexicalScope *getOrCreateAbstractScope(const DILocalScope *Scope); private: /// getOrCreateLexicalScope - Find lexical scope for the given Scope/IA. If /// not available then create new lexical scope. - LexicalScope *getOrCreateLexicalScope(const MDLocalScope *Scope, - const MDLocation *IA = nullptr); - LexicalScope *getOrCreateLexicalScope(const MDLocation *DL) { + LexicalScope *getOrCreateLexicalScope(const DILocalScope *Scope, + const DILocation *IA = nullptr); + LexicalScope *getOrCreateLexicalScope(const DILocation *DL) { return DL ? getOrCreateLexicalScope(DL->getScope(), DL->getInlinedAt()) : nullptr; } /// getOrCreateRegularScope - Find or create a regular lexical scope. - LexicalScope *getOrCreateRegularScope(const MDLocalScope *Scope); + LexicalScope *getOrCreateRegularScope(const DILocalScope *Scope); /// getOrCreateInlinedScope - Find or create an inlined lexical scope. - LexicalScope *getOrCreateInlinedScope(const MDLocalScope *Scope, - const MDLocation *InlinedAt); + LexicalScope *getOrCreateInlinedScope(const DILocalScope *Scope, + const DILocation *InlinedAt); /// extractLexicalScopes - Extract instruction ranges for each lexical scopes /// for the given machine function. @@ -230,18 +230,18 @@ class LexicalScopes { /// LexicalScopeMap - Tracks the scopes in the current function. // Use an unordered_map to ensure value pointer validity over insertion. - std::unordered_map LexicalScopeMap; + std::unordered_map LexicalScopeMap; /// InlinedLexicalScopeMap - Tracks inlined function scopes in current /// function. - std::unordered_map, + std::unordered_map, LexicalScope, - pair_hash> + pair_hash> InlinedLexicalScopeMap; /// AbstractScopeMap - These scopes are not included LexicalScopeMap. // Use an unordered_map to ensure value pointer validity over insertion. - std::unordered_map AbstractScopeMap; + std::unordered_map AbstractScopeMap; /// AbstractScopesList - Tracks abstract scopes constructed while processing /// a function. diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index 4c07a68fb60..fee131e4a3c 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -34,11 +34,9 @@ namespace { (void) llvm::createFastRegisterAllocator(); (void) llvm::createBasicRegisterAllocator(); (void) llvm::createGreedyRegisterAllocator(); -#if !defined(__native_client__) - // Not needed by sandboxed translator. (void) llvm::createDefaultPBQPRegisterAllocator(); -#endif + llvm::linkCoreCLRGC(); llvm::linkOcamlGC(); llvm::linkErlangGC(); llvm::linkShadowStackGC(); diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index 9673f80e085..47ba1ff0454 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -147,13 +147,12 @@ extern cl::opt UseSegmentSetForPhysRegs; LiveInterval::Segment addSegmentToEndOfBlock(unsigned reg, MachineInstr* startInst); - /// shrinkToUses - After removing some uses of a register, shrink its live - /// range to just the remaining uses. This method does not compute reaching - /// defs for new uses, and it doesn't remove dead defs. - /// Dead PHIDef values are marked as unused. - /// New dead machine instructions are added to the dead vector. - /// Return true if the interval may have been separated into multiple - /// connected components. + /// After removing some uses of a register, shrink its live range to just + /// the remaining uses. This method does not compute reaching defs for new + /// uses, and it doesn't remove dead defs. + /// Dead PHIDef values are marked as unused. New dead machine instructions + /// are added to the dead vector. Returns true if the interval may have been + /// separated into multiple connected components. bool shrinkToUses(LiveInterval *li, SmallVectorImpl *dead = nullptr); @@ -161,6 +160,8 @@ extern cl::opt UseSegmentSetForPhysRegs; /// shrinkToUses(LiveInterval *li, SmallVectorImpl *dead) /// that works on a subregister live range and only looks at uses matching /// the lane mask of the subregister range. + /// This may leave the subrange empty which needs to be cleaned up with + /// LiveInterval::removeEmptySubranges() afterwards. void shrinkToUses(LiveInterval::SubRange &SR, unsigned Reg); /// extendToIndices - Extend the live range of LI to reach all points in diff --git a/include/llvm/CodeGen/LiveIntervalUnion.h b/include/llvm/CodeGen/LiveIntervalUnion.h index 967f0cbac71..f0f1637dc92 100644 --- a/include/llvm/CodeGen/LiveIntervalUnion.h +++ b/include/llvm/CodeGen/LiveIntervalUnion.h @@ -203,6 +203,11 @@ class LiveIntervalUnion { assert(idx < Size && "idx out of bounds"); return LIUs[idx]; } + + const LiveIntervalUnion& operator[](unsigned Idx) const { + assert(Idx < Size && "Idx out of bounds"); + return LIUs[Idx]; + } }; }; diff --git a/include/llvm/CodeGen/LivePhysRegs.h b/include/llvm/CodeGen/LivePhysRegs.h index f44d627d717..6475e7b4af3 100644 --- a/include/llvm/CodeGen/LivePhysRegs.h +++ b/include/llvm/CodeGen/LivePhysRegs.h @@ -93,7 +93,8 @@ class LivePhysRegs { } /// \brief Removes physical registers clobbered by the regmask operand @p MO. - void removeRegsInMask(const MachineOperand &MO); + void removeRegsInMask(const MachineOperand &MO, + SmallVectorImpl> *Clobbers); /// \brief Returns true if register @p Reg is contained in the set. This also /// works if only the super register of @p Reg has been defined, because we @@ -109,21 +110,21 @@ class LivePhysRegs { /// instruction(bundle): Remove killed-uses, add defs. This is the not /// recommended way, because it depends on accurate kill flags. If possible /// use stepBackwards() instead of this function. - void stepForward(const MachineInstr &MI); - - /// \brief Adds all live-in registers of basic block @p MBB. - void addLiveIns(const MachineBasicBlock *MBB) { - for (MachineBasicBlock::livein_iterator LI = MBB->livein_begin(), - LE = MBB->livein_end(); LI != LE; ++LI) - addReg(*LI); - } - - /// \brief Adds all live-out registers of basic block @p MBB. - void addLiveOuts(const MachineBasicBlock *MBB) { - for (MachineBasicBlock::const_succ_iterator SI = MBB->succ_begin(), - SE = MBB->succ_end(); SI != SE; ++SI) - addLiveIns(*SI); - } + /// The clobbers set will be the list of registers either defined or clobbered + /// by a regmask. The operand will identify whether this is a regmask or + /// register operand. + void stepForward(const MachineInstr &MI, + SmallVectorImpl> &Clobbers); + + /// \brief Adds all live-in registers of basic block @p MBB; After prologue/ + /// epilogue insertion \p AddPristines should be set to true to insert the + /// pristine registers. + void addLiveIns(const MachineBasicBlock *MBB, bool AddPristines = false); + + /// \brief Adds all live-out registers of basic block @p MBB; After prologue/ + /// epilogue insertion \p AddPristines should be set to true to insert the + /// pristine registers. + void addLiveOuts(const MachineBasicBlock *MBB, bool AddPristines = false); typedef SparseSet::const_iterator const_iterator; const_iterator begin() const { return LiveRegs.begin(); } diff --git a/include/llvm/CodeGen/LiveRangeEdit.h b/include/llvm/CodeGen/LiveRangeEdit.h index de855f2fe7a..c97c636abbb 100644 --- a/include/llvm/CodeGen/LiveRangeEdit.h +++ b/include/llvm/CodeGen/LiveRangeEdit.h @@ -102,6 +102,10 @@ class LiveRangeEdit : private MachineRegisterInfo::Delegate { /// registers are created. void MRI_NoteNewVirtualRegister(unsigned VReg) override; + /// \brief Check if MachineOperand \p MO is a last use/kill either in the + /// main live range of \p LI or in one of the matching subregister ranges. + bool useIsKill(const LiveInterval &LI, const MachineOperand &MO) const; + public: /// Create a LiveRangeEdit for breaking down parent into smaller pieces. /// @param parent The register being spilled or split. diff --git a/include/llvm/CodeGen/LiveRegMatrix.h b/include/llvm/CodeGen/LiveRegMatrix.h index 878b4d9836f..e169058ca56 100644 --- a/include/llvm/CodeGen/LiveRegMatrix.h +++ b/include/llvm/CodeGen/LiveRegMatrix.h @@ -32,13 +32,11 @@ namespace llvm { class LiveInterval; class LiveIntervalAnalysis; -class MachineRegisterInfo; class TargetRegisterInfo; class VirtRegMap; class LiveRegMatrix : public MachineFunctionPass { const TargetRegisterInfo *TRI; - MachineRegisterInfo *MRI; LiveIntervals *LIS; VirtRegMap *VRM; @@ -114,6 +112,9 @@ class LiveRegMatrix : public MachineFunctionPass { /// the assignment and updates VirtRegMap accordingly. void unassign(LiveInterval &VirtReg); + /// Returns true if the given \p PhysReg has any live intervals assigned. + bool isPhysRegUsed(unsigned PhysReg) const; + //===--------------------------------------------------------------------===// // Low-level interface. //===--------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/MIRParser/MIRParser.h b/include/llvm/CodeGen/MIRParser/MIRParser.h new file mode 100644 index 00000000000..67b756d5e88 --- /dev/null +++ b/include/llvm/CodeGen/MIRParser/MIRParser.h @@ -0,0 +1,81 @@ +//===- MIRParser.h - MIR serialization format parser ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This MIR serialization library is currently a work in progress. It can't +// serialize machine functions at this time. +// +// This file declares the functions that parse the MIR serialization format +// files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MIRPARSER_MIRPARSER_H +#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 + +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 Impl; + +public: + MIRParser(std::unique_ptr 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 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 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 which will be used for the parsed LLVM IR module. +std::unique_ptr createMIRParserFromFile(StringRef Filename, + SMDiagnostic &Error, + LLVMContext &Context); + +/// This function is another interface to the MIR serialization format parser. +/// +/// 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 Context - Context which will be used for the parsed LLVM IR module. +std::unique_ptr +createMIRParser(std::unique_ptr Contents, LLVMContext &Context); + +} // end namespace llvm + +#endif diff --git a/include/llvm/CodeGen/MIRYamlMapping.h b/include/llvm/CodeGen/MIRYamlMapping.h new file mode 100644 index 00000000000..777819f3eae --- /dev/null +++ b/include/llvm/CodeGen/MIRYamlMapping.h @@ -0,0 +1,434 @@ +//===- MIRYAMLMapping.h - Describes the mapping between MIR and YAML ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The MIR serialization library is currently a work in progress. It can't +// serialize machine functions at this time. +// +// This file implements the mapping between various MIR data structures and +// their corresponding YAML representation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_CODEGEN_MIRYAMLMAPPING_H +#define LLVM_LIB_CODEGEN_MIRYAMLMAPPING_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/Support/YAMLTraits.h" +#include + +namespace llvm { +namespace yaml { + +/// A wrapper around std::string which contains a source range that's being +/// set during parsing. +struct StringValue { + std::string Value; + SMRange SourceRange; + + StringValue() {} + StringValue(std::string Value) : Value(std::move(Value)) {} + + bool operator==(const StringValue &Other) const { + return Value == Other.Value; + } +}; + +template <> struct ScalarTraits { + static void output(const StringValue &S, void *, llvm::raw_ostream &OS) { + OS << S.Value; + } + + static StringRef input(StringRef Scalar, void *Ctx, StringValue &S) { + S.Value = Scalar.str(); + if (const auto *Node = + reinterpret_cast(Ctx)->getCurrentNode()) + S.SourceRange = Node->getSourceRange(); + return ""; + } + + static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); } +}; + +struct FlowStringValue : StringValue { + FlowStringValue() {} + FlowStringValue(std::string Value) : StringValue(Value) {} +}; + +template <> struct ScalarTraits { + static void output(const FlowStringValue &S, void *, llvm::raw_ostream &OS) { + return ScalarTraits::output(S, nullptr, OS); + } + + static StringRef input(StringRef Scalar, void *Ctx, FlowStringValue &S) { + return ScalarTraits::input(Scalar, Ctx, S); + } + + static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); } +}; + +/// A wrapper around unsigned which contains a source range that's being set +/// during parsing. +struct UnsignedValue { + unsigned Value; + SMRange SourceRange; + + UnsignedValue() : Value(0) {} + UnsignedValue(unsigned Value) : Value(Value) {} + + bool operator==(const UnsignedValue &Other) const { + return Value == Other.Value; + } +}; + +template <> struct ScalarTraits { + static void output(const UnsignedValue &Value, void *Ctx, raw_ostream &OS) { + return ScalarTraits::output(Value.Value, Ctx, OS); + } + + static StringRef input(StringRef Scalar, void *Ctx, UnsignedValue &Value) { + if (const auto *Node = + reinterpret_cast(Ctx)->getCurrentNode()) + Value.SourceRange = Node->getSourceRange(); + return ScalarTraits::input(Scalar, Ctx, Value.Value); + } + + static bool mustQuote(StringRef Scalar) { + return ScalarTraits::mustQuote(Scalar); + } +}; + +template <> struct ScalarEnumerationTraits { + static void enumeration(yaml::IO &IO, + MachineJumpTableInfo::JTEntryKind &EntryKind) { + IO.enumCase(EntryKind, "block-address", + MachineJumpTableInfo::EK_BlockAddress); + IO.enumCase(EntryKind, "gp-rel64-block-address", + MachineJumpTableInfo::EK_GPRel64BlockAddress); + IO.enumCase(EntryKind, "gp-rel32-block-address", + MachineJumpTableInfo::EK_GPRel32BlockAddress); + IO.enumCase(EntryKind, "label-difference32", + MachineJumpTableInfo::EK_LabelDifference32); + IO.enumCase(EntryKind, "inline", MachineJumpTableInfo::EK_Inline); + IO.enumCase(EntryKind, "custom32", MachineJumpTableInfo::EK_Custom32); + } +}; + +} // end namespace yaml +} // end namespace llvm + +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::StringValue) +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue) +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::UnsignedValue) + +namespace llvm { +namespace yaml { + +struct VirtualRegisterDefinition { + UnsignedValue ID; + StringValue Class; + StringValue PreferredRegister; + // TODO: Serialize the target specific register hints. +}; + +template <> struct MappingTraits { + static void mapping(IO &YamlIO, VirtualRegisterDefinition &Reg) { + YamlIO.mapRequired("id", Reg.ID); + YamlIO.mapRequired("class", Reg.Class); + YamlIO.mapOptional("preferred-register", Reg.PreferredRegister, + StringValue()); // Don't print out when it's empty. + } + + static const bool flow = true; +}; + +struct MachineFunctionLiveIn { + StringValue Register; + StringValue VirtualRegister; +}; + +template <> struct MappingTraits { + static void mapping(IO &YamlIO, MachineFunctionLiveIn &LiveIn) { + YamlIO.mapRequired("reg", LiveIn.Register); + YamlIO.mapOptional( + "virtual-reg", LiveIn.VirtualRegister, + StringValue()); // Don't print the virtual register when it's empty. + } + + static const bool flow = true; +}; + +struct MachineBasicBlock { + unsigned ID; + StringValue Name; + StringValue IRBlock; + unsigned Alignment = 0; + bool IsLandingPad = false; + bool AddressTaken = false; + std::vector Successors; + std::vector SuccessorWeights; + std::vector LiveIns; + std::vector Instructions; +}; + +template <> struct MappingTraits { + static void mapping(IO &YamlIO, MachineBasicBlock &MBB) { + YamlIO.mapRequired("id", MBB.ID); + YamlIO.mapOptional("name", MBB.Name, + StringValue()); // Don't print out an empty name. + YamlIO.mapOptional("ir-block", MBB.IRBlock, + StringValue()); // Don't print out an empty BB reference. + YamlIO.mapOptional("alignment", MBB.Alignment); + YamlIO.mapOptional("isLandingPad", MBB.IsLandingPad); + YamlIO.mapOptional("addressTaken", MBB.AddressTaken); + YamlIO.mapOptional("successors", MBB.Successors); + YamlIO.mapOptional("weights", MBB.SuccessorWeights); + YamlIO.mapOptional("liveins", MBB.LiveIns); + YamlIO.mapOptional("instructions", MBB.Instructions); + } +}; + +/// Serializable representation of stack object from the MachineFrameInfo class. +/// +/// The flags 'isImmutable' and 'isAliased' aren't serialized, as they are +/// determined by the object's type and frame information flags. +/// Dead stack objects aren't serialized. +/// +/// TODO: Determine isPreallocated flag by mapping between objects and local +/// objects (Serialize local objects). +struct MachineStackObject { + enum ObjectType { DefaultType, SpillSlot, VariableSized }; + unsigned ID; + StringValue Name; + // TODO: Serialize unnamed LLVM alloca reference. + ObjectType Type = DefaultType; + int64_t Offset = 0; + uint64_t Size = 0; + unsigned Alignment = 0; + StringValue CalleeSavedRegister; +}; + +template <> struct ScalarEnumerationTraits { + static void enumeration(yaml::IO &IO, MachineStackObject::ObjectType &Type) { + IO.enumCase(Type, "default", MachineStackObject::DefaultType); + IO.enumCase(Type, "spill-slot", MachineStackObject::SpillSlot); + IO.enumCase(Type, "variable-sized", MachineStackObject::VariableSized); + } +}; + +template <> struct MappingTraits { + static void mapping(yaml::IO &YamlIO, MachineStackObject &Object) { + YamlIO.mapRequired("id", Object.ID); + YamlIO.mapOptional("name", Object.Name, + StringValue()); // Don't print out an empty name. + YamlIO.mapOptional( + "type", Object.Type, + MachineStackObject::DefaultType); // Don't print the default type. + YamlIO.mapOptional("offset", Object.Offset); + if (Object.Type != MachineStackObject::VariableSized) + YamlIO.mapRequired("size", Object.Size); + YamlIO.mapOptional("alignment", Object.Alignment); + YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister, + StringValue()); // Don't print it out when it's empty. + } + + static const bool flow = true; +}; + +/// Serializable representation of the fixed stack object from the +/// MachineFrameInfo class. +struct FixedMachineStackObject { + enum ObjectType { DefaultType, SpillSlot }; + unsigned ID; + ObjectType Type = DefaultType; + int64_t Offset = 0; + uint64_t Size = 0; + unsigned Alignment = 0; + bool IsImmutable = false; + bool IsAliased = false; + StringValue CalleeSavedRegister; +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(yaml::IO &IO, + FixedMachineStackObject::ObjectType &Type) { + IO.enumCase(Type, "default", FixedMachineStackObject::DefaultType); + IO.enumCase(Type, "spill-slot", FixedMachineStackObject::SpillSlot); + } +}; + +template <> struct MappingTraits { + static void mapping(yaml::IO &YamlIO, FixedMachineStackObject &Object) { + YamlIO.mapRequired("id", Object.ID); + YamlIO.mapOptional( + "type", Object.Type, + FixedMachineStackObject::DefaultType); // Don't print the default type. + YamlIO.mapOptional("offset", Object.Offset); + YamlIO.mapOptional("size", Object.Size); + YamlIO.mapOptional("alignment", Object.Alignment); + if (Object.Type != FixedMachineStackObject::SpillSlot) { + YamlIO.mapOptional("isImmutable", Object.IsImmutable); + YamlIO.mapOptional("isAliased", Object.IsAliased); + } + YamlIO.mapOptional("callee-saved-register", Object.CalleeSavedRegister, + StringValue()); // Don't print it out when it's empty. + } + + static const bool flow = true; +}; + +struct MachineConstantPoolValue { + UnsignedValue ID; + StringValue Value; + unsigned Alignment = 0; +}; + +template <> struct MappingTraits { + static void mapping(IO &YamlIO, MachineConstantPoolValue &Constant) { + YamlIO.mapRequired("id", Constant.ID); + YamlIO.mapOptional("value", Constant.Value); + YamlIO.mapOptional("alignment", Constant.Alignment); + } +}; + +struct MachineJumpTable { + struct Entry { + unsigned ID; + std::vector Blocks; + }; + + MachineJumpTableInfo::JTEntryKind Kind = MachineJumpTableInfo::EK_Custom32; + std::vector Entries; +}; + +template <> struct MappingTraits { + static void mapping(IO &YamlIO, MachineJumpTable::Entry &Entry) { + YamlIO.mapRequired("id", Entry.ID); + YamlIO.mapOptional("blocks", Entry.Blocks); + } +}; + +} // end namespace yaml +} // end namespace llvm + +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineFunctionLiveIn) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::VirtualRegisterDefinition) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineBasicBlock) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineStackObject) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::FixedMachineStackObject) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineConstantPoolValue) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::MachineJumpTable::Entry) + +namespace llvm { +namespace yaml { + +template <> struct MappingTraits { + static void mapping(IO &YamlIO, MachineJumpTable &JT) { + YamlIO.mapRequired("kind", JT.Kind); + YamlIO.mapOptional("entries", JT.Entries); + } +}; + +/// Serializable representation of MachineFrameInfo. +/// +/// Doesn't serialize attributes like 'StackAlignment', 'IsStackRealignable' and +/// 'RealignOption' as they are determined by the target and LLVM function +/// attributes. +/// It also doesn't serialize attributes like 'NumFixedObject' and +/// 'HasVarSizedObjects' as they are determined by the frame objects themselves. +struct MachineFrameInfo { + bool IsFrameAddressTaken = false; + bool IsReturnAddressTaken = false; + bool HasStackMap = false; + bool HasPatchPoint = false; + uint64_t StackSize = 0; + int OffsetAdjustment = 0; + unsigned MaxAlignment = 0; + bool AdjustsStack = false; + bool HasCalls = false; + // TODO: Serialize StackProtectorIdx and FunctionContextIdx + unsigned MaxCallFrameSize = 0; + // TODO: Serialize local frame objects. + bool HasOpaqueSPAdjustment = false; + bool HasVAStart = false; + bool HasMustTailInVarArgFunc = false; + StringValue SavePoint; + StringValue RestorePoint; +}; + +template <> struct MappingTraits { + static void mapping(IO &YamlIO, MachineFrameInfo &MFI) { + YamlIO.mapOptional("isFrameAddressTaken", MFI.IsFrameAddressTaken); + YamlIO.mapOptional("isReturnAddressTaken", MFI.IsReturnAddressTaken); + YamlIO.mapOptional("hasStackMap", MFI.HasStackMap); + YamlIO.mapOptional("hasPatchPoint", MFI.HasPatchPoint); + YamlIO.mapOptional("stackSize", MFI.StackSize); + YamlIO.mapOptional("offsetAdjustment", MFI.OffsetAdjustment); + YamlIO.mapOptional("maxAlignment", MFI.MaxAlignment); + YamlIO.mapOptional("adjustsStack", MFI.AdjustsStack); + YamlIO.mapOptional("hasCalls", MFI.HasCalls); + YamlIO.mapOptional("maxCallFrameSize", MFI.MaxCallFrameSize); + YamlIO.mapOptional("hasOpaqueSPAdjustment", MFI.HasOpaqueSPAdjustment); + YamlIO.mapOptional("hasVAStart", MFI.HasVAStart); + YamlIO.mapOptional("hasMustTailInVarArgFunc", MFI.HasMustTailInVarArgFunc); + YamlIO.mapOptional("savePoint", MFI.SavePoint, + StringValue()); // Don't print it out when it's empty. + YamlIO.mapOptional("restorePoint", MFI.RestorePoint, + StringValue()); // Don't print it out when it's empty. + } +}; + +struct MachineFunction { + StringRef Name; + unsigned Alignment = 0; + bool ExposesReturnsTwice = false; + bool HasInlineAsm = false; + // Register information + bool IsSSA = false; + bool TracksRegLiveness = false; + bool TracksSubRegLiveness = false; + std::vector VirtualRegisters; + std::vector LiveIns; + // TODO: Serialize the various register masks. + // Frame information + MachineFrameInfo FrameInfo; + std::vector FixedStackObjects; + std::vector StackObjects; + std::vector Constants; /// Constant pool. + MachineJumpTable JumpTableInfo; + + std::vector BasicBlocks; +}; + +template <> struct MappingTraits { + static void mapping(IO &YamlIO, MachineFunction &MF) { + YamlIO.mapRequired("name", MF.Name); + YamlIO.mapOptional("alignment", MF.Alignment); + YamlIO.mapOptional("exposesReturnsTwice", MF.ExposesReturnsTwice); + YamlIO.mapOptional("hasInlineAsm", MF.HasInlineAsm); + YamlIO.mapOptional("isSSA", MF.IsSSA); + YamlIO.mapOptional("tracksRegLiveness", MF.TracksRegLiveness); + YamlIO.mapOptional("tracksSubRegLiveness", MF.TracksSubRegLiveness); + YamlIO.mapOptional("registers", MF.VirtualRegisters); + YamlIO.mapOptional("liveins", MF.LiveIns); + YamlIO.mapOptional("frameInfo", MF.FrameInfo); + YamlIO.mapOptional("fixedStack", MF.FixedStackObjects); + YamlIO.mapOptional("stack", MF.StackObjects); + YamlIO.mapOptional("constants", MF.Constants); + if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty()) + YamlIO.mapOptional("jumpTable", MF.JumpTableInfo); + YamlIO.mapOptional("body", MF.BasicBlocks); + } +}; + +} // end namespace yaml +} // end namespace llvm + +#endif diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index 1440b967aea..aba64ff9a1a 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -25,6 +25,7 @@ class Pass; class BasicBlock; class MachineFunction; class MCSymbol; +class MIRPrinter; class SlotIndexes; class StringRef; class raw_ostream; @@ -315,9 +316,18 @@ class MachineBasicBlock : public ilist_node { // LiveIn management methods. - /// addLiveIn - Add the specified register as a live in. Note that it - /// is an error to add the same register to the same set more than once. - void addLiveIn(unsigned Reg) { LiveIns.push_back(Reg); } + /// Adds the specified register as a live in. Note that it is an error to add + /// the same register to the same set more than once unless the intention is + /// to call sortUniqueLiveIns after all registers are added. + void addLiveIn(unsigned Reg) { LiveIns.push_back(Reg); } + + /// Sorts and uniques the LiveIns vector. It can be significantly faster to do + /// this than repeatedly calling isLiveIn before calling addLiveIn for every + /// LiveIn insertion. + void sortUniqueLiveIns() { + std::sort(LiveIns.begin(), LiveIns.end()); + LiveIns.erase(std::unique(LiveIns.begin(), LiveIns.end()), LiveIns.end()); + } /// Add PhysReg as live in to this block, and ensure that there is a copy of /// PhysReg to a virtual register of class RC. Return the virtual register @@ -415,6 +425,9 @@ class MachineBasicBlock : public ilist_node { /// which refer to fromMBB to refer to this. void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *fromMBB); + /// Return true if any of the successors have weights attached to them. + bool hasSuccessorWeights() const { return !Weights.empty(); } + /// isPredecessor - Return true if the specified MBB is a predecessor of this /// block. bool isPredecessor(const MachineBasicBlock *MBB) const; @@ -452,16 +465,27 @@ class MachineBasicBlock : public ilist_node { /// instruction of this basic block. If a terminator does not exist, /// it returns end() iterator getFirstTerminator(); - const_iterator getFirstTerminator() const; + const_iterator getFirstTerminator() const { + return const_cast(this)->getFirstTerminator(); + } /// getFirstInstrTerminator - Same getFirstTerminator but it ignores bundles /// and return an instr_iterator instead. instr_iterator getFirstInstrTerminator(); + /// getFirstNonDebugInstr - returns an iterator to the first non-debug + /// instruction in the basic block, or end() + iterator getFirstNonDebugInstr(); + const_iterator getFirstNonDebugInstr() const { + return const_cast(this)->getFirstNonDebugInstr(); + } + /// getLastNonDebugInstr - returns an iterator to the last non-debug /// instruction in the basic block, or end() iterator getLastNonDebugInstr(); - const_iterator getLastNonDebugInstr() const; + const_iterator getLastNonDebugInstr() const { + return const_cast(this)->getLastNonDebugInstr(); + } /// SplitCriticalEdge - Split the critical edge from this block to the /// given successor block, and return the newly created block, or null @@ -624,21 +648,24 @@ class MachineBasicBlock : public ilist_node { ///< neighborhood. }; - /// computeRegisterLiveness - Return whether (physical) register \c Reg - /// has been ined and not ed as of just before \c MI. + /// Return whether (physical) register \p Reg has been ined and not + /// ed as of just before \p Before. /// - /// Search is localised to a neighborhood of - /// \c Neighborhood instructions before (searching for defs or kills) and - /// Neighborhood instructions after (searching just for defs) MI. + /// Search is localised to a neighborhood of \p Neighborhood instructions + /// before (searching for defs or kills) and \p Neighborhood instructions + /// after (searching just for defs) \p Before. /// - /// \c Reg must be a physical register. + /// \p Reg must be a physical register. LivenessQueryResult computeRegisterLiveness(const TargetRegisterInfo *TRI, - unsigned Reg, MachineInstr *MI, - unsigned Neighborhood=10); + unsigned Reg, + const_iterator Before, + unsigned Neighborhood=10) const; // Debugging methods. void dump() const; void print(raw_ostream &OS, SlotIndexes* = nullptr) const; + void print(raw_ostream &OS, ModuleSlotTracker &MST, + SlotIndexes * = nullptr) const; // Printing method used by LoopInfo. void printAsOperand(raw_ostream &OS, bool PrintType = true) const; @@ -662,6 +689,7 @@ class MachineBasicBlock : public ilist_node { const_weight_iterator getWeightIterator(const_succ_iterator I) const; friend class MachineBranchProbabilityInfo; + friend class MIRPrinter; /// getSuccWeight - Return weight of the edge from this block to MBB. This /// method should NOT be called directly, but by using getEdgeWeight method diff --git a/include/llvm/CodeGen/MachineConstantPool.h b/include/llvm/CodeGen/MachineConstantPool.h index 20fb181b5c5..628400322f6 100644 --- a/include/llvm/CodeGen/MachineConstantPool.h +++ b/include/llvm/CodeGen/MachineConstantPool.h @@ -58,17 +58,6 @@ class MachineConstantPoolValue { virtual void addSelectionDAGCSEId(FoldingSetNodeID &ID) = 0; - // @LOCALMOD-START - /// getJumpTableIndex - Check if this is a reference to a jump table. - /// If so, return a pointer to the jump table index value that is stored - /// in the constant pool, else return 0. - /// The default behavior is to indicate that the value is not a jump table - /// index. This is used by BranchFolder::runOnMachineFunction() and only in - /// conjunction with ARM targets - /// TODO: this should be cleaned up as it does tripple duty: tester, setter, getter - virtual unsigned *getJumpTableIndex() { return 0; } - // @LOCALMOD-END - /// print - Implement operator<< virtual void print(raw_ostream &O) const = 0; }; @@ -146,17 +135,18 @@ class MachineConstantPoolEntry { /// address of the function constant pool values. /// @brief The machine constant pool. class MachineConstantPool { - const TargetMachine &TM; ///< The target machine. unsigned PoolAlignment; ///< The alignment for the pool. std::vector Constants; ///< The pool of constants. /// MachineConstantPoolValues that use an existing MachineConstantPoolEntry. DenseSet MachineCPVsSharingEntries; + const DataLayout &DL; + + const DataLayout &getDataLayout() const { return DL; } - const DataLayout *getDataLayout() const; public: /// @brief The only constructor. - explicit MachineConstantPool(const TargetMachine &TM) - : TM(TM), PoolAlignment(1) {} + explicit MachineConstantPool(const DataLayout &DL) + : PoolAlignment(1), DL(DL) {} ~MachineConstantPool(); /// getConstantPoolAlignment - Return the alignment required by diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h index 4428fa618fb..0ac8a5d0e2a 100644 --- a/include/llvm/CodeGen/MachineDominators.h +++ b/include/llvm/CodeGen/MachineDominators.h @@ -29,8 +29,8 @@ inline void DominatorTreeBase::addRoot(MachineBasicBlock* MBB this->Roots.push_back(MBB); } -EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase); -EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase); +extern template class DomTreeNodeBase; +extern template class DominatorTreeBase; typedef DomTreeNodeBase MachineDomTreeNode; @@ -263,6 +263,21 @@ template <> struct GraphTraits { } }; +template <> struct GraphTraits { + typedef const MachineDomTreeNode NodeType; + typedef NodeType::const_iterator ChildIteratorType; + + static NodeType *getEntryNode(NodeType *N) { + return N; + } + static inline ChildIteratorType child_begin(NodeType* N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType* N) { + return N->end(); + } +}; + template <> struct GraphTraits : public GraphTraits { static NodeType *getEntryNode(MachineDominatorTree *DT) { diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index 1e7fee666fc..943ea5d6728 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -79,9 +79,9 @@ class CalleeSavedInfo { /// @brief Abstract Stack Frame Information class MachineFrameInfo { - // StackObject - Represent a single object allocated on the stack. + // Represent a single object allocated on the stack. struct StackObject { - // SPOffset - The offset of this object from the stack pointer on entry to + // The offset of this object from the stack pointer on entry to // the function. This field has no meaning for a variable sized element. int64_t SPOffset; @@ -89,23 +89,23 @@ class MachineFrameInfo { // ~0ULL means a dead object. uint64_t Size; - // Alignment - The required alignment of this stack slot. + // The required alignment of this stack slot. unsigned Alignment; - // isImmutable - If true, the value of the stack object is set before + // If true, the value of the stack object is set before // entering the function and is not modified inside the function. By // default, fixed objects are immutable unless marked otherwise. bool isImmutable; - // isSpillSlot - If true the stack object is used as spill slot. It + // If true the stack object is used as spill slot. It // cannot alias any other memory objects. bool isSpillSlot; - /// Alloca - If this stack object is originated from an Alloca instruction + /// If this stack object is originated from an Alloca instruction /// this value saves the original IR allocation. Can be NULL. const AllocaInst *Alloca; - // PreAllocated - If true, the object was mapped into the local frame + // If true, the object was mapped into the local frame // block and doesn't need additional handling for allocation beyond that. bool PreAllocated; @@ -121,51 +121,47 @@ class MachineFrameInfo { isSpillSlot(isSS), Alloca(Val), PreAllocated(false), isAliased(A) {} }; - /// StackAlignment - The alignment of the stack. + /// The alignment of the stack. unsigned StackAlignment; - /// StackRealignable - Can the stack be realigned. + /// Can the stack be realigned. bool StackRealignable; - /// Objects - The list of stack objects allocated... - /// + /// The list of stack objects allocated. std::vector Objects; - /// NumFixedObjects - This contains the number of fixed objects contained on + /// This contains the number of fixed objects contained on /// the stack. Because fixed objects are stored at a negative index in the /// Objects list, this is also the index to the 0th object in the list. - /// unsigned NumFixedObjects; - /// HasVarSizedObjects - This boolean keeps track of whether any variable + /// This boolean keeps track of whether any variable /// sized objects have been allocated yet. - /// bool HasVarSizedObjects; - /// FrameAddressTaken - This boolean keeps track of whether there is a call + /// This boolean keeps track of whether there is a call /// to builtin \@llvm.frameaddress. bool FrameAddressTaken; - /// ReturnAddressTaken - This boolean keeps track of whether there is a call + /// This boolean keeps track of whether there is a call /// to builtin \@llvm.returnaddress. bool ReturnAddressTaken; - /// HasStackMap - This boolean keeps track of whether there is a call + /// This boolean keeps track of whether there is a call /// to builtin \@llvm.experimental.stackmap. bool HasStackMap; - /// HasPatchPoint - This boolean keeps track of whether there is a call + /// This boolean keeps track of whether there is a call /// to builtin \@llvm.experimental.patchpoint. bool HasPatchPoint; - /// StackSize - The prolog/epilog code inserter calculates the final stack + /// The prolog/epilog code inserter calculates the final stack /// offsets for all of the fixed size objects, updating the Objects list /// above. It then updates StackSize to contain the number of bytes that need /// to be allocated on entry to the function. - /// uint64_t StackSize; - /// OffsetAdjustment - The amount that a frame offset needs to be adjusted to + /// The amount that a frame offset needs to be adjusted to /// have the actual offset from the stack/frame pointer. The exact usage of /// this is target-dependent, but it is typically used to adjust between /// SP-relative and FP-relative offsets. E.G., if objects are accessed via @@ -176,52 +172,49 @@ class MachineFrameInfo { /// corresponding adjustments are performed directly. int OffsetAdjustment; - /// MaxAlignment - The prolog/epilog code inserter may process objects - /// that require greater alignment than the default alignment the target - /// provides. To handle this, MaxAlignment is set to the maximum alignment + /// The prolog/epilog code inserter may process objects that require greater + /// alignment than the default alignment the target provides. + /// To handle this, MaxAlignment is set to the maximum alignment /// needed by the objects on the current frame. If this is greater than the /// native alignment maintained by the compiler, dynamic alignment code will /// be needed. /// unsigned MaxAlignment; - /// AdjustsStack - Set to true if this function adjusts the stack -- e.g., + /// Set to true if this function adjusts the stack -- e.g., /// when calling another function. This is only valid during and after /// prolog/epilog code insertion. bool AdjustsStack; - /// HasCalls - Set to true if this function has any function calls. + /// Set to true if this function has any function calls. bool HasCalls; - /// StackProtectorIdx - The frame index for the stack protector. + /// The frame index for the stack protector. int StackProtectorIdx; - /// FunctionContextIdx - The frame index for the function context. Used for - /// SjLj exceptions. + /// The frame index for the function context. Used for SjLj exceptions. int FunctionContextIdx; - /// MaxCallFrameSize - This contains the size of the largest call frame if the - /// target uses frame setup/destroy pseudo instructions (as defined in the - /// TargetFrameInfo class). This information is important for frame pointer - /// elimination. If is only valid during and after prolog/epilog code - /// insertion. - /// + /// This contains the size of the largest call frame if the target uses frame + /// setup/destroy pseudo instructions (as defined in the TargetFrameInfo + /// class). This information is important for frame pointer elimination. + /// If is only valid during and after prolog/epilog code insertion. unsigned MaxCallFrameSize; - /// CSInfo - The prolog/epilog code inserter fills in this vector with each + /// The prolog/epilog code inserter fills in this vector with each /// callee saved register saved in the frame. Beyond its use by the prolog/ /// epilog code inserter, this data used for debug info and exception /// handling. std::vector CSInfo; - /// CSIValid - Has CSInfo been set yet? + /// Has CSInfo been set yet? bool CSIValid; - /// LocalFrameObjects - References to frame indices which are mapped + /// References to frame indices which are mapped /// into the local frame allocation block. SmallVector, 32> LocalFrameObjects; - /// LocalFrameSize - Size of the pre-allocated local frame block. + /// Size of the pre-allocated local frame block. int64_t LocalFrameSize; /// Required alignment of the local object blob, which is the strictest @@ -236,9 +229,9 @@ class MachineFrameInfo { /// Whether the "realign-stack" option is on. bool RealignOption; - /// True if the function includes inline assembly that adjusts the stack - /// pointer. - bool HasInlineAsmWithSPAdjust; + /// True if the function dynamically adjusts the stack pointer through some + /// opaque mechanism like inline assembly or Win32 EH. + bool HasOpaqueSPAdjustment; /// True if the function contains a call to the llvm.vastart intrinsic. bool HasVAStart; @@ -246,6 +239,16 @@ class MachineFrameInfo { /// True if this is a varargs function that contains a musttail call. bool HasMustTailInVarArgFunc; + /// True if this function contains a tail call. If so immutable objects like + /// function arguments are no longer so. A tail call *can* override fixed + /// stack objects like arguments so we can't treat them as immutable. + bool HasTailCall; + + /// Not null, if shrink-wrapping found a better place for the prologue. + MachineBasicBlock *Save; + /// Not null, if shrink-wrapping found a better place for the epilogue. + MachineBasicBlock *Restore; + public: explicit MachineFrameInfo(unsigned StackAlign, bool isStackRealign, bool RealignOpt) @@ -266,107 +269,101 @@ class MachineFrameInfo { LocalFrameSize = 0; LocalFrameMaxAlign = 0; UseLocalStackAllocationBlock = false; - HasInlineAsmWithSPAdjust = false; + HasOpaqueSPAdjustment = false; HasVAStart = false; HasMustTailInVarArgFunc = false; + Save = nullptr; + Restore = nullptr; + HasTailCall = false; } - /// hasStackObjects - Return true if there are any stack objects in this - /// function. - /// + /// Return true if there are any stack objects in this function. bool hasStackObjects() const { return !Objects.empty(); } - /// hasVarSizedObjects - This method may be called any time after instruction + /// This method may be called any time after instruction /// selection is complete to determine if the stack frame for this function /// contains any variable sized objects. - /// bool hasVarSizedObjects() const { return HasVarSizedObjects; } - /// getStackProtectorIndex/setStackProtectorIndex - Return the index for the - /// stack protector object. - /// + /// Return the index for the stack protector object. int getStackProtectorIndex() const { return StackProtectorIdx; } void setStackProtectorIndex(int I) { StackProtectorIdx = I; } - /// getFunctionContextIndex/setFunctionContextIndex - Return the index for the - /// function context object. This object is used for SjLj exceptions. + /// Return the index for the function context object. + /// This object is used for SjLj exceptions. int getFunctionContextIndex() const { return FunctionContextIdx; } void setFunctionContextIndex(int I) { FunctionContextIdx = I; } - /// isFrameAddressTaken - This method may be called any time after instruction + /// This method may be called any time after instruction /// selection is complete to determine if there is a call to /// \@llvm.frameaddress in this function. bool isFrameAddressTaken() const { return FrameAddressTaken; } void setFrameAddressIsTaken(bool T) { FrameAddressTaken = T; } - /// isReturnAddressTaken - This method may be called any time after + /// This method may be called any time after /// instruction selection is complete to determine if there is a call to /// \@llvm.returnaddress in this function. bool isReturnAddressTaken() const { return ReturnAddressTaken; } void setReturnAddressIsTaken(bool s) { ReturnAddressTaken = s; } - /// hasStackMap - This method may be called any time after instruction + /// This method may be called any time after instruction /// selection is complete to determine if there is a call to builtin /// \@llvm.experimental.stackmap. bool hasStackMap() const { return HasStackMap; } void setHasStackMap(bool s = true) { HasStackMap = s; } - /// hasPatchPoint - This method may be called any time after instruction + /// This method may be called any time after instruction /// selection is complete to determine if there is a call to builtin /// \@llvm.experimental.patchpoint. bool hasPatchPoint() const { return HasPatchPoint; } void setHasPatchPoint(bool s = true) { HasPatchPoint = s; } - /// getObjectIndexBegin - Return the minimum frame object index. - /// + /// Return the minimum frame object index. int getObjectIndexBegin() const { return -NumFixedObjects; } - /// getObjectIndexEnd - Return one past the maximum frame object index. - /// + /// Return one past the maximum frame object index. int getObjectIndexEnd() const { return (int)Objects.size()-NumFixedObjects; } - /// getNumFixedObjects - Return the number of fixed objects. + /// Return the number of fixed objects. unsigned getNumFixedObjects() const { return NumFixedObjects; } - /// getNumObjects - Return the number of objects. - /// + /// Return the number of objects. unsigned getNumObjects() const { return Objects.size(); } - /// mapLocalFrameObject - Map a frame index into the local object block + /// Map a frame index into the local object block void mapLocalFrameObject(int ObjectIndex, int64_t Offset) { LocalFrameObjects.push_back(std::pair(ObjectIndex, Offset)); Objects[ObjectIndex + NumFixedObjects].PreAllocated = true; } - /// getLocalFrameObjectMap - Get the local offset mapping for a for an object - std::pair getLocalFrameObjectMap(int i) { + /// Get the local offset mapping for a for an object. + std::pair getLocalFrameObjectMap(int i) const { assert (i >= 0 && (unsigned)i < LocalFrameObjects.size() && "Invalid local object reference!"); return LocalFrameObjects[i]; } - /// getLocalFrameObjectCount - Return the number of objects allocated into - /// the local object block. - int64_t getLocalFrameObjectCount() { return LocalFrameObjects.size(); } + /// Return the number of objects allocated into the local object block. + int64_t getLocalFrameObjectCount() const { return LocalFrameObjects.size(); } - /// setLocalFrameSize - Set the size of the local object blob. + /// Set the size of the local object blob. void setLocalFrameSize(int64_t sz) { LocalFrameSize = sz; } - /// getLocalFrameSize - Get the size of the local object blob. + /// Get the size of the local object blob. int64_t getLocalFrameSize() const { return LocalFrameSize; } - /// setLocalFrameMaxAlign - Required alignment of the local object blob, + /// Required alignment of the local object blob, /// which is the strictest alignment of any object in it. void setLocalFrameMaxAlign(unsigned Align) { LocalFrameMaxAlign = Align; } - /// getLocalFrameMaxAlign - Return the required alignment of the local - /// object blob. + /// Return the required alignment of the local object blob. unsigned getLocalFrameMaxAlign() const { return LocalFrameMaxAlign; } - /// getUseLocalStackAllocationBlock - Get whether the local allocation blob - /// should be allocated together or let PEI allocate the locals in it - /// directly. - bool getUseLocalStackAllocationBlock() {return UseLocalStackAllocationBlock;} + /// Get whether the local allocation blob should be allocated together or + /// let PEI allocate the locals in it directly. + bool getUseLocalStackAllocationBlock() const { + return UseLocalStackAllocationBlock; + } /// setUseLocalStackAllocationBlock - Set whether the local allocation blob /// should be allocated together or let PEI allocate the locals in it @@ -375,30 +372,28 @@ class MachineFrameInfo { UseLocalStackAllocationBlock = v; } - /// isObjectPreAllocated - Return true if the object was pre-allocated into - /// the local block. + /// Return true if the object was pre-allocated into the local block. bool isObjectPreAllocated(int ObjectIdx) const { assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && "Invalid Object Idx!"); return Objects[ObjectIdx+NumFixedObjects].PreAllocated; } - /// getObjectSize - Return the size of the specified object. - /// + /// Return the size of the specified object. int64_t getObjectSize(int ObjectIdx) const { assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && "Invalid Object Idx!"); return Objects[ObjectIdx+NumFixedObjects].Size; } - /// setObjectSize - Change the size of the specified stack object. + /// Change the size of the specified stack object. void setObjectSize(int ObjectIdx, int64_t Size) { assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && "Invalid Object Idx!"); Objects[ObjectIdx+NumFixedObjects].Size = Size; } - /// getObjectAlignment - Return the alignment of the specified stack object. + /// Return the alignment of the specified stack object. unsigned getObjectAlignment(int ObjectIdx) const { assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && "Invalid Object Idx!"); @@ -413,7 +408,7 @@ class MachineFrameInfo { ensureMaxAlignment(Align); } - /// getObjectAllocation - Return the underlying Alloca of the specified + /// Return the underlying Alloca of the specified /// stack object if it exists. Returns 0 if none exists. const AllocaInst* getObjectAllocation(int ObjectIdx) const { assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && @@ -421,9 +416,8 @@ class MachineFrameInfo { return Objects[ObjectIdx+NumFixedObjects].Alloca; } - /// getObjectOffset - Return the assigned stack offset of the specified object + /// Return the assigned stack offset of the specified object /// from the incoming stack pointer. - /// int64_t getObjectOffset(int ObjectIdx) const { assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && "Invalid Object Idx!"); @@ -432,9 +426,8 @@ class MachineFrameInfo { return Objects[ObjectIdx+NumFixedObjects].SPOffset; } - /// setObjectOffset - Set the stack frame offset of the specified object. The + /// Set the stack frame offset of the specified object. The /// offset is relative to the stack pointer on entry to the function. - /// void setObjectOffset(int ObjectIdx, int64_t SPOffset) { assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && "Invalid Object Idx!"); @@ -443,50 +436,43 @@ class MachineFrameInfo { Objects[ObjectIdx+NumFixedObjects].SPOffset = SPOffset; } - /// getStackSize - Return the number of bytes that must be allocated to hold + /// Return the number of bytes that must be allocated to hold /// all of the fixed size frame objects. This is only valid after /// Prolog/Epilog code insertion has finalized the stack frame layout. - /// uint64_t getStackSize() const { return StackSize; } - /// setStackSize - Set the size of the stack... - /// + /// Set the size of the stack. void setStackSize(uint64_t Size) { StackSize = Size; } /// Estimate and return the size of the stack frame. unsigned estimateStackSize(const MachineFunction &MF) const; - /// getOffsetAdjustment - Return the correction for frame offsets. - /// + /// Return the correction for frame offsets. int getOffsetAdjustment() const { return OffsetAdjustment; } - /// setOffsetAdjustment - Set the correction for frame offsets. - /// + /// Set the correction for frame offsets. void setOffsetAdjustment(int Adj) { OffsetAdjustment = Adj; } - /// getMaxAlignment - Return the alignment in bytes that this function must be - /// aligned to, which is greater than the default stack alignment provided by - /// the target. - /// + /// Return the alignment in bytes that this function must be aligned to, + /// which is greater than the default stack alignment provided by the target. unsigned getMaxAlignment() const { return MaxAlignment; } - /// ensureMaxAlignment - Make sure the function is at least Align bytes - /// aligned. + /// Make sure the function is at least Align bytes aligned. void ensureMaxAlignment(unsigned Align); - /// AdjustsStack - Return true if this function adjusts the stack -- e.g., + /// Return true if this function adjusts the stack -- e.g., /// when calling another function. This is only valid during and after /// prolog/epilog code insertion. bool adjustsStack() const { return AdjustsStack; } void setAdjustsStack(bool V) { AdjustsStack = V; } - /// hasCalls - Return true if the current function has any function calls. + /// Return true if the current function has any function calls. bool hasCalls() const { return HasCalls; } void setHasCalls(bool V) { HasCalls = V; } - /// Returns true if the function contains any stack-adjusting inline assembly. - bool hasInlineAsmWithSPAdjust() const { return HasInlineAsmWithSPAdjust; } - void setHasInlineAsmWithSPAdjust(bool B) { HasInlineAsmWithSPAdjust = B; } + /// Returns true if the function contains opaque dynamic stack adjustments. + bool hasOpaqueSPAdjustment() const { return HasOpaqueSPAdjustment; } + void setHasOpaqueSPAdjustment(bool B) { HasOpaqueSPAdjustment = B; } /// Returns true if the function calls the llvm.va_start intrinsic. bool hasVAStart() const { return HasVAStart; } @@ -496,7 +482,11 @@ class MachineFrameInfo { bool hasMustTailInVarArgFunc() const { return HasMustTailInVarArgFunc; } void setHasMustTailInVarArgFunc(bool B) { HasMustTailInVarArgFunc = B; } - /// getMaxCallFrameSize - Return the maximum size of a call frame that must be + /// Returns true if the function contains a tail call. + bool hasTailCall() const { return HasTailCall; } + void setHasTailCall() { HasTailCall = true; } + + /// Return the maximum size of a call frame that must be /// allocated for an outgoing function call. This is only available if /// CallFrameSetup/Destroy pseudo instructions are used by the target, and /// then only during or after prolog/epilog code insertion. @@ -504,25 +494,23 @@ class MachineFrameInfo { unsigned getMaxCallFrameSize() const { return MaxCallFrameSize; } void setMaxCallFrameSize(unsigned S) { MaxCallFrameSize = S; } - /// CreateFixedObject - Create a new object at a fixed location on the stack. + /// Create a new object at a fixed location on the stack. /// All fixed objects should be created before other objects are created for /// efficiency. By default, fixed objects are not pointed to by LLVM IR /// values. This returns an index with a negative value. - /// int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool Immutable, bool isAliased = false); - /// CreateFixedSpillStackObject - Create a spill slot at a fixed location - /// on the stack. Returns an index with a negative value. + /// Create a spill slot at a fixed location on the stack. + /// Returns an index with a negative value. int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset); - /// isFixedObjectIndex - Returns true if the specified index corresponds to a - /// fixed stack object. + /// Returns true if the specified index corresponds to a fixed stack object. bool isFixedObjectIndex(int ObjectIdx) const { return ObjectIdx < 0 && (ObjectIdx >= -(int)NumFixedObjects); } - /// isAliasedObjectIndex - Returns true if the specified index corresponds + /// Returns true if the specified index corresponds /// to an object that might be pointed to by an LLVM IR value. bool isAliasedObjectIndex(int ObjectIdx) const { assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && @@ -533,84 +521,89 @@ class MachineFrameInfo { /// isImmutableObjectIndex - Returns true if the specified index corresponds /// to an immutable object. bool isImmutableObjectIndex(int ObjectIdx) const { + // Tail calling functions can clobber their function arguments. + if (HasTailCall) + return false; assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && "Invalid Object Idx!"); return Objects[ObjectIdx+NumFixedObjects].isImmutable; } - /// isSpillSlotObjectIndex - Returns true if the specified index corresponds - /// to a spill slot.. + /// Returns true if the specified index corresponds to a spill slot. bool isSpillSlotObjectIndex(int ObjectIdx) const { assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && "Invalid Object Idx!"); return Objects[ObjectIdx+NumFixedObjects].isSpillSlot; } - /// isDeadObjectIndex - Returns true if the specified index corresponds to - /// a dead object. + /// Returns true if the specified index corresponds to a dead object. bool isDeadObjectIndex(int ObjectIdx) const { assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && "Invalid Object Idx!"); return Objects[ObjectIdx+NumFixedObjects].Size == ~0ULL; } - /// CreateStackObject - Create a new statically sized stack object, returning + /// Returns true if the specified index corresponds to a variable sized + /// object. + bool isVariableSizedObjectIndex(int ObjectIdx) const { + assert(unsigned(ObjectIdx + NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + return Objects[ObjectIdx + NumFixedObjects].Size == 0; + } + + /// Create a new statically sized stack object, returning /// a nonnegative identifier to represent it. - /// int CreateStackObject(uint64_t Size, unsigned Alignment, bool isSS, const AllocaInst *Alloca = nullptr); - /// CreateSpillStackObject - Create a new statically sized stack object that - /// represents a spill slot, returning a nonnegative identifier to represent - /// it. - /// + /// Create a new statically sized stack object that represents a spill slot, + /// returning a nonnegative identifier to represent it. int CreateSpillStackObject(uint64_t Size, unsigned Alignment); - /// RemoveStackObject - Remove or mark dead a statically sized stack object. - /// + /// Remove or mark dead a statically sized stack object. void RemoveStackObject(int ObjectIdx) { // Mark it dead. Objects[ObjectIdx+NumFixedObjects].Size = ~0ULL; } - /// CreateVariableSizedObject - Notify the MachineFrameInfo object that a - /// variable sized object has been created. This must be created whenever a - /// variable sized object is created, whether or not the index returned is - /// actually used. - /// + /// Notify the MachineFrameInfo object that a variable sized object has been + /// created. This must be created whenever a variable sized object is + /// created, whether or not the index returned is actually used. int CreateVariableSizedObject(unsigned Alignment, const AllocaInst *Alloca); - /// getCalleeSavedInfo - Returns a reference to call saved info vector for the - /// current function. + /// Returns a reference to call saved info vector for the current function. const std::vector &getCalleeSavedInfo() const { return CSInfo; } - /// setCalleeSavedInfo - Used by prolog/epilog inserter to set the function's - /// callee saved information. + /// Used by prolog/epilog inserter to set the function's callee saved + /// information. void setCalleeSavedInfo(const std::vector &CSI) { CSInfo = CSI; } - /// isCalleeSavedInfoValid - Has the callee saved info been calculated yet? + /// Has the callee saved info been calculated yet? bool isCalleeSavedInfoValid() const { return CSIValid; } void setCalleeSavedInfoValid(bool v) { CSIValid = v; } - /// getPristineRegs - Return a set of physical registers that are pristine on - /// entry to the MBB. + MachineBasicBlock *getSavePoint() const { return Save; } + void setSavePoint(MachineBasicBlock *NewSave) { Save = NewSave; } + MachineBasicBlock *getRestorePoint() const { return Restore; } + void setRestorePoint(MachineBasicBlock *NewRestore) { Restore = NewRestore; } + + /// Return a set of physical registers that are pristine. /// /// Pristine registers hold a value that is useless to the current function, - /// but that must be preserved - they are callee saved registers that have not - /// been saved yet. + /// but that must be preserved - they are callee saved registers that are not + /// saved. /// /// Before the PrologueEpilogueInserter has placed the CSR spill code, this /// method always returns an empty set. - BitVector getPristineRegs(const MachineBasicBlock *MBB) const; + BitVector getPristineRegs(const MachineFunction &MF) const; - /// print - Used by the MachineFunction printer to print information about - /// stack objects. Implemented in MachineFunction.cpp - /// + /// Used by the MachineFunction printer to print information about + /// stack objects. Implemented in MachineFunction.cpp. void print(const MachineFunction &MF, raw_ostream &OS) const; /// dump - Print the function to stderr. diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 94610cabf56..6297defb1c5 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -155,6 +155,9 @@ class MachineFunction { MachineModuleInfo &getMMI() const { return MMI; } MCContext &getContext() const { return Ctx; } + /// Return the DataLayout attached to the Module associated to this MF. + const DataLayout &getDataLayout() const; + /// getFunction - Return the LLVM function that this machine code represents /// const Function *getFunction() const { return Fn; } @@ -472,6 +475,9 @@ class MachineFunction { extractStoreMemRefs(MachineInstr::mmo_iterator Begin, MachineInstr::mmo_iterator End); + /// Allocate a string and populate it with the given external symbol name. + const char *createExternalSymbolName(StringRef Name); + //===--------------------------------------------------------------------===// // Label Manipulation. // diff --git a/include/llvm/CodeGen/MachineFunctionAnalysis.h b/include/llvm/CodeGen/MachineFunctionAnalysis.h index 023eeb1b4d0..4c0f5e63ea1 100644 --- a/include/llvm/CodeGen/MachineFunctionAnalysis.h +++ b/include/llvm/CodeGen/MachineFunctionAnalysis.h @@ -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 @@ struct MachineFunctionAnalysis : public FunctionPass { 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; } diff --git a/include/llvm/CodeGen/MachineFunctionInitializer.h b/include/llvm/CodeGen/MachineFunctionInitializer.h new file mode 100644 index 00000000000..ff4c29cc014 --- /dev/null +++ b/include/llvm/CodeGen/MachineFunctionInitializer.h @@ -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 diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 9097150ab62..be0b629a697 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -42,7 +42,7 @@ class MachineFunction; class MachineMemOperand; //===----------------------------------------------------------------------===// -/// MachineInstr - Representation of each machine instruction. +/// Representation of each machine instruction. /// /// This class isn't a POD type, but it must have a trivial destructor. When a /// MachineFunction is deleted, all the contained MachineInstrs are deallocated @@ -103,12 +103,12 @@ class MachineInstr : public ilist_node { friend struct ilist_traits; void setParent(MachineBasicBlock *P) { Parent = P; } - /// MachineInstr ctor - This constructor creates a copy of the given + /// This constructor creates a copy of the given /// MachineInstr in the given MachineFunction. MachineInstr(MachineFunction &, const MachineInstr &); - /// MachineInstr ctor - This constructor create a MachineInstr and add the - /// implicit operands. It reserves space for number of operands specified by + /// This constructor create a MachineInstr and add the implicit operands. + /// It reserves space for number of operands specified by /// MCInstrDesc. An explicit DebugLoc is supplied. MachineInstr(MachineFunction &, const MCInstrDesc &MCID, DebugLoc dl, bool NoImp = false); @@ -120,43 +120,38 @@ class MachineInstr : public ilist_node { const MachineBasicBlock* getParent() const { return Parent; } MachineBasicBlock* getParent() { return Parent; } - /// getAsmPrinterFlags - Return the asm printer flags bitvector. - /// + /// Return the asm printer flags bitvector. uint8_t getAsmPrinterFlags() const { return AsmPrinterFlags; } - /// clearAsmPrinterFlags - clear the AsmPrinter bitvector - /// + /// Clear the AsmPrinter bitvector. void clearAsmPrinterFlags() { AsmPrinterFlags = 0; } - /// getAsmPrinterFlag - Return whether an AsmPrinter flag is set. - /// + /// Return whether an AsmPrinter flag is set. bool getAsmPrinterFlag(CommentFlag Flag) const { return AsmPrinterFlags & Flag; } - /// setAsmPrinterFlag - Set a flag for the AsmPrinter. - /// + /// Set a flag for the AsmPrinter. void setAsmPrinterFlag(CommentFlag Flag) { AsmPrinterFlags |= (uint8_t)Flag; } - /// clearAsmPrinterFlag - clear specific AsmPrinter flags - /// + /// Clear specific AsmPrinter flags. void clearAsmPrinterFlag(CommentFlag Flag) { AsmPrinterFlags &= ~Flag; } - /// getFlags - Return the MI flags bitvector. + /// Return the MI flags bitvector. uint8_t getFlags() const { return Flags; } - /// getFlag - Return whether an MI flag is set. + /// Return whether an MI flag is set. bool getFlag(MIFlag Flag) const { return Flags & Flag; } - /// setFlag - Set a MI flag. + /// Set a MI flag. void setFlag(MIFlag Flag) { Flags |= (uint8_t)Flag; } @@ -172,8 +167,7 @@ class MachineInstr : public ilist_node { Flags &= ~((uint8_t)Flag); } - /// isInsideBundle - Return true if MI is in a bundle (but not the first MI - /// in a bundle). + /// Return true if MI is in a bundle (but not the first MI in a bundle). /// /// A bundle looks like this before it's finalized: /// ---------------- @@ -212,7 +206,7 @@ class MachineInstr : public ilist_node { return getFlag(BundledPred); } - /// isBundled - Return true if this instruction part of a bundle. This is true + /// Return true if this instruction part of a bundle. This is true /// if either itself or its following instruction is marked "InsideBundle". bool isBundled() const { return isBundledWithPred() || isBundledWithSucc(); @@ -240,26 +234,25 @@ class MachineInstr : public ilist_node { /// Break bundle below this instruction. void unbundleFromSucc(); - /// getDebugLoc - Returns the debug location id of this MachineInstr. - /// + /// Returns the debug location id of this MachineInstr. const DebugLoc &getDebugLoc() const { return debugLoc; } - /// \brief Return the debug variable referenced by + /// Return the debug variable referenced by /// this DBG_VALUE instruction. - DIVariable getDebugVariable() const { + const DILocalVariable *getDebugVariable() const { assert(isDebugValue() && "not a DBG_VALUE"); - return cast(getOperand(2).getMetadata()); + return cast(getOperand(2).getMetadata()); } - /// \brief Return the complex address expression referenced by + /// Return the complex address expression referenced by /// this DBG_VALUE instruction. - DIExpression getDebugExpression() const { + const DIExpression *getDebugExpression() const { assert(isDebugValue() && "not a DBG_VALUE"); - return cast(getOperand(3).getMetadata()); + return cast(getOperand(3).getMetadata()); } - /// emitError - Emit an error referring to the source location of this - /// instruction. This should only be used for inline assembly that is somehow + /// Emit an error referring to the source location of this instruction. + /// This should only be used for inline assembly that is somehow /// impossible to compile. Other errors should have been handled much /// earlier. /// @@ -267,13 +260,11 @@ class MachineInstr : public ilist_node { /// void emitError(StringRef Msg) const; - /// getDesc - Returns the target instruction descriptor of this - /// MachineInstr. + /// Returns the target instruction descriptor of this MachineInstr. const MCInstrDesc &getDesc() const { return *MCID; } - /// getOpcode - Returns the opcode of this MachineInstr. - /// - int getOpcode() const { return MCID->Opcode; } + /// Returns the opcode of this MachineInstr. + unsigned getOpcode() const { return MCID->Opcode; } /// Access to explicit operands of the instruction. /// @@ -288,8 +279,7 @@ class MachineInstr : public ilist_node { return Operands[i]; } - /// getNumExplicitOperands - Returns the number of non-implicit operands. - /// + /// Returns the number of non-implicit operands. unsigned getNumExplicitOperands() const; /// iterator/begin/end - Iterate over all operands of a machine instruction. @@ -324,23 +314,34 @@ class MachineInstr : public ilist_node { return iterator_range(explicit_operands().end(), operands_end()); } + /// Returns a range over all explicit operands that are register definitions. + /// Implicit definition are not included! iterator_range defs() { return iterator_range( operands_begin(), operands_begin() + getDesc().getNumDefs()); } + /// \copydoc defs() iterator_range defs() const { return iterator_range( operands_begin(), operands_begin() + getDesc().getNumDefs()); } + /// Returns a range that includes all operands that are register uses. + /// This may include unrelated operands which are not register uses. iterator_range uses() { return iterator_range( operands_begin() + getDesc().getNumDefs(), operands_end()); } + /// \copydoc uses() iterator_range uses() const { return iterator_range( operands_begin() + getDesc().getNumDefs(), operands_end()); } + /// Returns the number of the operand iterator \p I points to. + unsigned getOperandNo(const_mop_iterator I) const { + return I - operands_begin(); + } + /// Access to memory operands of the instruction mmo_iterator memoperands_begin() const { return MemRefs; } mmo_iterator memoperands_end() const { return MemRefs + NumMemRefs; } @@ -353,8 +354,7 @@ class MachineInstr : public ilist_node { return iterator_range(memoperands_begin(), memoperands_end()); } - /// hasOneMemOperand - Return true if this instruction has exactly one - /// MachineMemOperand. + /// Return true if this instruction has exactly one MachineMemOperand. bool hasOneMemOperand() const { return NumMemRefs == 1; } @@ -368,7 +368,7 @@ class MachineInstr : public ilist_node { AllInBundle // Return true if all instructions in bundle have property }; - /// hasProperty - Return true if the instruction (or in the case of a bundle, + /// Return true if the instruction (or in the case of a bundle, /// the instructions inside the bundle) has the specified property. /// The first argument is the property being queried. /// The second argument indicates whether the query should look inside @@ -382,23 +382,22 @@ class MachineInstr : public ilist_node { return hasPropertyInBundle(1 << MCFlag, Type); } - /// isVariadic - Return true if this instruction can have a variable number of - /// operands. In this case, the variable operands will be after the normal + /// Return true if this instruction can have a variable number of operands. + /// In this case, the variable operands will be after the normal /// operands but before the implicit definitions and uses (if any are /// present). bool isVariadic(QueryType Type = IgnoreBundle) const { return hasProperty(MCID::Variadic, Type); } - /// hasOptionalDef - Set if this instruction has an optional definition, e.g. + /// Set if this instruction has an optional definition, e.g. /// ARM instructions which can set condition code if 's' bit is set. bool hasOptionalDef(QueryType Type = IgnoreBundle) const { return hasProperty(MCID::HasOptionalDef, Type); } - /// isPseudo - Return true if this is a pseudo instruction that doesn't + /// Return true if this is a pseudo instruction that doesn't /// correspond to a real machine instruction. - /// bool isPseudo(QueryType Type = IgnoreBundle) const { return hasProperty(MCID::Pseudo, Type); } @@ -411,16 +410,15 @@ class MachineInstr : public ilist_node { return hasProperty(MCID::Call, Type); } - /// isBarrier - Returns true if the specified instruction stops control flow + /// Returns true if the specified instruction stops control flow /// from executing the instruction immediately following it. Examples include /// unconditional branches and return instructions. bool isBarrier(QueryType Type = AnyInBundle) const { return hasProperty(MCID::Barrier, Type); } - /// isTerminator - Returns true if this instruction part of the terminator for - /// a basic block. Typically this is things like return and branch - /// instructions. + /// Returns true if this instruction part of the terminator for a basic block. + /// Typically this is things like return and branch instructions. /// /// Various passes use this to insert code into the bottom of a basic block, /// but before control flow occurs. @@ -428,21 +426,21 @@ class MachineInstr : public ilist_node { return hasProperty(MCID::Terminator, Type); } - /// isBranch - Returns true if this is a conditional, unconditional, or - /// indirect branch. Predicates below can be used to discriminate between + /// Returns true if this is a conditional, unconditional, or indirect branch. + /// Predicates below can be used to discriminate between /// these cases, and the TargetInstrInfo::AnalyzeBranch method can be used to /// get more information. bool isBranch(QueryType Type = AnyInBundle) const { return hasProperty(MCID::Branch, Type); } - /// isIndirectBranch - Return true if this is an indirect branch, such as a + /// Return true if this is an indirect branch, such as a /// branch through a register. bool isIndirectBranch(QueryType Type = AnyInBundle) const { return hasProperty(MCID::IndirectBranch, Type); } - /// isConditionalBranch - Return true if this is a branch which may fall + /// Return true if this is a branch which may fall /// through to the next instruction or may transfer control flow to some other /// block. The TargetInstrInfo::AnalyzeBranch method can be used to get more /// information about this branch. @@ -450,7 +448,7 @@ class MachineInstr : public ilist_node { return isBranch(Type) & !isBarrier(Type) & !isIndirectBranch(Type); } - /// isUnconditionalBranch - Return true if this is a branch which always + /// Return true if this is a branch which always /// transfers control flow to some other block. The /// TargetInstrInfo::AnalyzeBranch method can be used to get more information /// about this branch. @@ -468,43 +466,48 @@ class MachineInstr : public ilist_node { return hasProperty(MCID::Predicable, Type); } - /// isCompare - Return true if this instruction is a comparison. + /// Return true if this instruction is a comparison. bool isCompare(QueryType Type = IgnoreBundle) const { return hasProperty(MCID::Compare, Type); } - /// isMoveImmediate - Return true if this instruction is a move immediate + /// Return true if this instruction is a move immediate /// (including conditional moves) instruction. bool isMoveImmediate(QueryType Type = IgnoreBundle) const { return hasProperty(MCID::MoveImm, Type); } - /// isBitcast - Return true if this instruction is a bitcast instruction. - /// + /// Return true if this instruction is a bitcast instruction. bool isBitcast(QueryType Type = IgnoreBundle) const { return hasProperty(MCID::Bitcast, Type); } - /// isSelect - Return true if this instruction is a select instruction. - /// + /// Return true if this instruction is a select instruction. bool isSelect(QueryType Type = IgnoreBundle) const { return hasProperty(MCID::Select, Type); } - /// isNotDuplicable - Return true if this instruction cannot be safely - /// duplicated. For example, if the instruction has a unique labels attached + /// Return true if this instruction cannot be safely duplicated. + /// For example, if the instruction has a unique labels attached /// to it, duplicating it would cause multiple definition errors. bool isNotDuplicable(QueryType Type = AnyInBundle) const { return hasProperty(MCID::NotDuplicable, Type); } - /// hasDelaySlot - Returns true if the specified instruction has a delay slot + /// Return true if this instruction is convergent. + /// Convergent instructions can only be moved to locations that are + /// control-equivalent to their initial position. + bool isConvergent(QueryType Type = AnyInBundle) const { + return hasProperty(MCID::Convergent, Type); + } + + /// Returns true if the specified instruction has a delay slot /// which must be filled by the code generator. bool hasDelaySlot(QueryType Type = AnyInBundle) const { return hasProperty(MCID::DelaySlot, Type); } - /// canFoldAsLoad - Return true for instructions that can be folded as + /// Return true for instructions that can be folded as /// memory operands in other instructions. The most common use for this /// is instructions that are simple loads from memory that don't modify /// the loaded value in any way, but it can also be used for instructions @@ -563,7 +566,7 @@ class MachineInstr : public ilist_node { // Side Effect Analysis //===--------------------------------------------------------------------===// - /// mayLoad - Return true if this instruction could possibly read memory. + /// Return true if this instruction could possibly read memory. /// Instructions with this flag set are not necessarily simple load /// instructions, they may load a value and modify it, for example. bool mayLoad(QueryType Type = AnyInBundle) const { @@ -575,8 +578,7 @@ class MachineInstr : public ilist_node { return hasProperty(MCID::MayLoad, Type); } - - /// mayStore - Return true if this instruction could possibly modify memory. + /// Return true if this instruction could possibly modify memory. /// Instructions with this flag set are not necessarily simple store /// instructions, they may store a modified value based on their operands, or /// may not actually modify anything, for example. @@ -589,11 +591,16 @@ class MachineInstr : public ilist_node { return hasProperty(MCID::MayStore, Type); } + /// Return true if this instruction could possibly read or modify memory. + bool mayLoadOrStore(QueryType Type = AnyInBundle) const { + return mayLoad(Type) || mayStore(Type); + } + //===--------------------------------------------------------------------===// // Flags that indicate whether an instruction can be modified by a method. //===--------------------------------------------------------------------===// - /// isCommutable - Return true if this may be a 2- or 3-address + /// Return true if this may be a 2- or 3-address /// instruction (of the form "X = op Y, Z, ..."), which produces the same /// result if Y and Z are exchanged. If this flag is set, then the /// TargetInstrInfo::commuteInstruction method may be used to hack on the @@ -607,7 +614,7 @@ class MachineInstr : public ilist_node { return hasProperty(MCID::Commutable, Type); } - /// isConvertibleTo3Addr - Return true if this is a 2-address instruction + /// Return true if this is a 2-address instruction /// which can be changed into a 3-address instruction if needed. Doing this /// transformation can be profitable in the register allocator, because it /// means that the instruction can use a 2-address form if possible, but @@ -625,7 +632,7 @@ class MachineInstr : public ilist_node { return hasProperty(MCID::ConvertibleTo3Addr, Type); } - /// usesCustomInsertionHook - Return true if this instruction requires + /// Return true if this instruction requires /// custom insertion support when the DAG scheduler is inserting it into a /// machine basic block. If this is true for the instruction, it basically /// means that it is a pseudo instruction used at SelectionDAG time that is @@ -637,7 +644,7 @@ class MachineInstr : public ilist_node { return hasProperty(MCID::UsesCustomInserter, Type); } - /// hasPostISelHook - Return true if this instruction requires *adjustment* + /// Return true if this instruction requires *adjustment* /// after instruction selection by calling a target hook. For example, this /// can be used to fill in ARM 's' optional operand depending on whether /// the conditional flag register is used. @@ -645,8 +652,8 @@ class MachineInstr : public ilist_node { return hasProperty(MCID::HasPostISelHook, Type); } - /// isRematerializable - Returns true if this instruction is a candidate for - /// remat. This flag is deprecated, please don't use it anymore. If this + /// Returns true if this instruction is a candidate for remat. + /// This flag is deprecated, please don't use it anymore. If this /// flag is set, the isReallyTriviallyReMaterializable() method is called to /// verify the instruction is really rematable. bool isRematerializable(QueryType Type = AllInBundle) const { @@ -655,9 +662,9 @@ class MachineInstr : public ilist_node { return hasProperty(MCID::Rematerializable, Type); } - /// isAsCheapAsAMove - Returns true if this instruction has the same cost (or - /// less) than a move instruction. This is useful during certain types of - /// optimizations (e.g., remat during two-address conversion or machine licm) + /// Returns true if this instruction has the same cost (or less) than a move + /// instruction. This is useful during certain types of optimizations + /// (e.g., remat during two-address conversion or machine licm) /// where we would like to remat or hoist the instruction, but not if it costs /// more than moving the instruction into the appropriate register. Note, we /// are not marking copies from and to the same register class with this flag. @@ -666,7 +673,7 @@ class MachineInstr : public ilist_node { return hasProperty(MCID::CheapAsAMove, Type); } - /// hasExtraSrcRegAllocReq - Returns true if this instruction source operands + /// Returns true if this instruction source operands /// have special register allocation requirements that are not captured by the /// operand register classes. e.g. ARM::STRD's two source registers must be an /// even / odd pair, ARM::STM registers have to be in ascending order. @@ -676,7 +683,7 @@ class MachineInstr : public ilist_node { return hasProperty(MCID::ExtraSrcRegAllocReq, Type); } - /// hasExtraDefRegAllocReq - Returns true if this instruction def operands + /// Returns true if this instruction def operands /// have special register allocation requirements that are not captured by the /// operand register classes. e.g. ARM::LDRD's two def registers must be an /// even / odd pair, ARM::LDM registers have to be in ascending order. @@ -694,7 +701,7 @@ class MachineInstr : public ilist_node { IgnoreVRegDefs // Ignore virtual register definitions }; - /// isIdenticalTo - Return true if this instruction is identical to (same + /// Return true if this instruction is identical to (same /// opcode and same operands as) the specified instruction. bool isIdenticalTo(const MachineInstr *Other, MICheckType Check = CheckDefs) const; @@ -735,8 +742,7 @@ class MachineInstr : public ilist_node { bool isEHLabel() const { return getOpcode() == TargetOpcode::EH_LABEL; } bool isGCLabel() const { return getOpcode() == TargetOpcode::GC_LABEL; } - /// isLabel - Returns true if the MachineInstr represents a label. - /// + /// Returns true if the MachineInstr represents a label. bool isLabel() const { return isEHLabel() || isGCLabel(); } bool isCFIInstruction() const { return getOpcode() == TargetOpcode::CFI_INSTRUCTION; @@ -785,19 +791,19 @@ class MachineInstr : public ilist_node { return getOpcode() == TargetOpcode::EXTRACT_SUBREG; } - /// isCopyLike - Return true if the instruction behaves like a copy. + /// Return true if the instruction behaves like a copy. /// This does not include native copy instructions. bool isCopyLike() const { return isCopy() || isSubregToReg(); } - /// isIdentityCopy - Return true is the instruction is an identity copy. + /// Return true is the instruction is an identity copy. bool isIdentityCopy() const { return isCopy() && getOperand(0).getReg() == getOperand(1).getReg() && getOperand(0).getSubReg() == getOperand(1).getSubReg(); } - /// isTransient - Return true if this is a transient instruction that is + /// Return true if this is a transient instruction that is /// either very likely to be eliminated during register allocation (such as /// copy-like instructions), or if this instruction doesn't have an /// execution-time cost. @@ -828,8 +834,8 @@ class MachineInstr : public ilist_node { /// skips, 0 for unbundled instructions. unsigned getBundleSize() const; - /// readsRegister - Return true if the MachineInstr reads the specified - /// register. If TargetRegisterInfo is passed, then it also checks if there + /// Return true if the MachineInstr reads the specified register. + /// If TargetRegisterInfo is passed, then it also checks if there /// is a read of a super-register. /// This does not count partial redefines of virtual registers as reads: /// %reg1024:6 = OP. @@ -838,30 +844,29 @@ class MachineInstr : public ilist_node { return findRegisterUseOperandIdx(Reg, false, TRI) != -1; } - /// readsVirtualRegister - Return true if the MachineInstr reads the specified - /// virtual register. Take into account that a partial define is a + /// Return true if the MachineInstr reads the specified virtual register. + /// Take into account that a partial define is a /// read-modify-write operation. bool readsVirtualRegister(unsigned Reg) const { return readsWritesVirtualRegister(Reg).first; } - /// readsWritesVirtualRegister - Return a pair of bools (reads, writes) - /// indicating if this instruction reads or writes Reg. This also considers - /// partial defines. + /// Return a pair of bools (reads, writes) indicating if this instruction + /// reads or writes Reg. This also considers partial defines. /// If Ops is not null, all operand indices for Reg are added. std::pair readsWritesVirtualRegister(unsigned Reg, SmallVectorImpl *Ops = nullptr) const; - /// killsRegister - Return true if the MachineInstr kills the specified - /// register. If TargetRegisterInfo is passed, then it also checks if there is + /// Return true if the MachineInstr kills the specified register. + /// If TargetRegisterInfo is passed, then it also checks if there is /// a kill of a super-register. bool killsRegister(unsigned Reg, const TargetRegisterInfo *TRI = nullptr) const { return findRegisterUseOperandIdx(Reg, true, TRI) != -1; } - /// definesRegister - Return true if the MachineInstr fully defines the - /// specified register. If TargetRegisterInfo is passed, then it also checks + /// Return true if the MachineInstr fully defines the specified register. + /// If TargetRegisterInfo is passed, then it also checks /// if there is a def of a super-register. /// NOTE: It's ignoring subreg indices on virtual registers. bool definesRegister(unsigned Reg, @@ -869,28 +874,28 @@ class MachineInstr : public ilist_node { return findRegisterDefOperandIdx(Reg, false, false, TRI) != -1; } - /// modifiesRegister - Return true if the MachineInstr modifies (fully define - /// or partially define) the specified register. + /// Return true if the MachineInstr modifies (fully define or partially + /// define) the specified register. /// NOTE: It's ignoring subreg indices on virtual registers. bool modifiesRegister(unsigned Reg, const TargetRegisterInfo *TRI) const { return findRegisterDefOperandIdx(Reg, false, true, TRI) != -1; } - /// registerDefIsDead - Returns true if the register is dead in this machine - /// instruction. If TargetRegisterInfo is passed, then it also checks + /// Returns true if the register is dead in this machine instruction. + /// If TargetRegisterInfo is passed, then it also checks /// if there is a dead def of a super-register. bool registerDefIsDead(unsigned Reg, const TargetRegisterInfo *TRI = nullptr) const { return findRegisterDefOperandIdx(Reg, true, false, TRI) != -1; } - /// findRegisterUseOperandIdx() - Returns the operand index that is a use of - /// the specific register or -1 if it is not found. It further tightens - /// the search criteria to a use that kills the register if isKill is true. + /// Returns the operand index that is a use of the specific register or -1 + /// if it is not found. It further tightens the search criteria to a use + /// that kills the register if isKill is true. int findRegisterUseOperandIdx(unsigned Reg, bool isKill = false, const TargetRegisterInfo *TRI = nullptr) const; - /// findRegisterUseOperand - Wrapper for findRegisterUseOperandIdx, it returns + /// Wrapper for findRegisterUseOperandIdx, it returns /// a pointer to the MachineOperand rather than an index. MachineOperand *findRegisterUseOperand(unsigned Reg, bool isKill = false, const TargetRegisterInfo *TRI = nullptr) { @@ -898,17 +903,17 @@ class MachineInstr : public ilist_node { return (Idx == -1) ? nullptr : &getOperand(Idx); } - /// findRegisterDefOperandIdx() - Returns the operand index that is a def of - /// the specified register or -1 if it is not found. If isDead is true, defs - /// that are not dead are skipped. If Overlap is true, then it also looks for - /// defs that merely overlap the specified register. If TargetRegisterInfo is - /// non-null, then it also checks if there is a def of a super-register. + /// Returns the operand index that is a def of the specified register or + /// -1 if it is not found. If isDead is true, defs that are not dead are + /// skipped. If Overlap is true, then it also looks for defs that merely + /// overlap the specified register. If TargetRegisterInfo is non-null, + /// then it also checks if there is a def of a super-register. /// This may also return a register mask operand when Overlap is true. int findRegisterDefOperandIdx(unsigned Reg, bool isDead = false, bool Overlap = false, const TargetRegisterInfo *TRI = nullptr) const; - /// findRegisterDefOperand - Wrapper for findRegisterDefOperandIdx, it returns + /// Wrapper for findRegisterDefOperandIdx, it returns /// a pointer to the MachineOperand rather than an index. MachineOperand *findRegisterDefOperand(unsigned Reg, bool isDead = false, const TargetRegisterInfo *TRI = nullptr) { @@ -916,12 +921,12 @@ class MachineInstr : public ilist_node { return (Idx == -1) ? nullptr : &getOperand(Idx); } - /// findFirstPredOperandIdx() - Find the index of the first operand in the + /// Find the index of the first operand in the /// operand list that is used to represent the predicate. It returns -1 if /// none is found. int findFirstPredOperandIdx() const; - /// findInlineAsmFlagIdx() - Find the index of the flag word operand that + /// Find the index of the flag word operand that /// corresponds to operand OpIdx on an inline asm instruction. Returns -1 if /// getOperand(OpIdx) does not belong to an inline asm operand group. /// @@ -933,11 +938,11 @@ class MachineInstr : public ilist_node { /// int findInlineAsmFlagIdx(unsigned OpIdx, unsigned *GroupNo = nullptr) const; - /// getRegClassConstraint - Compute the static register class constraint for - /// operand OpIdx. For normal instructions, this is derived from the - /// MCInstrDesc. For inline assembly it is derived from the flag words. + /// Compute the static register class constraint for operand OpIdx. + /// 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* @@ -949,10 +954,10 @@ class MachineInstr : public ilist_node { /// 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. /// @@ -965,7 +970,7 @@ class MachineInstr : public ilist_node { /// \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. /// @@ -976,20 +981,20 @@ class MachineInstr : public ilist_node { const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const; - /// tieOperands - Add a tie between the register operands at DefIdx and - /// UseIdx. The tie will cause the register allocator to ensure that the two + /// Add a tie between the register operands at DefIdx and UseIdx. + /// The tie will cause the register allocator to ensure that the two /// operands are assigned the same physical register. /// /// Tied operands are managed automatically for explicit operands in the /// MCInstrDesc. This method is for exceptional cases like inline asm. void tieOperands(unsigned DefIdx, unsigned UseIdx); - /// findTiedOperandIdx - Given the index of a tied register operand, find the + /// Given the index of a tied register operand, find the /// operand it is tied to. Defs are tied to uses and vice versa. Returns the /// index of the tied operand which must exist. unsigned findTiedOperandIdx(unsigned OpIdx) const; - /// isRegTiedToUseOperand - Given the index of a register def operand, + /// Given the index of a register def operand, /// check if the register def is tied to a source operand, due to either /// two-address elimination or inline assembly constraints. Returns the /// first tied use operand index by reference if UseOpIdx is not null. @@ -1003,9 +1008,9 @@ class MachineInstr : public ilist_node { return true; } - /// isRegTiedToDefOperand - Return true if the use operand of the specified - /// index is tied to a def operand. It also returns the def operand index by - /// reference if DefOpIdx is not null. + /// Return true if the use operand of the specified index is tied to a def + /// operand. It also returns the def operand index by reference if DefOpIdx + /// is not null. bool isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx = nullptr) const { const MachineOperand &MO = getOperand(UseOpIdx); @@ -1016,16 +1021,15 @@ class MachineInstr : public ilist_node { return true; } - /// clearKillInfo - Clears kill flags on all operands. - /// + /// Clears kill flags on all operands. void clearKillInfo(); - /// substituteRegister - Replace all occurrences of FromReg with ToReg:SubIdx, + /// Replace all occurrences of FromReg with ToReg:SubIdx, /// properly composing subreg indices where necessary. void substituteRegister(unsigned FromReg, unsigned ToReg, unsigned SubIdx, const TargetRegisterInfo &RegInfo); - /// addRegisterKilled - We have determined MI kills a register. Look for the + /// We have determined MI kills a register. Look for the /// operand that uses it and mark it as IsKill. If AddIfNotFound is true, /// add a implicit operand if it's not found. Returns true if the operand /// exists / is added. @@ -1033,11 +1037,11 @@ class MachineInstr : public ilist_node { const TargetRegisterInfo *RegInfo, bool AddIfNotFound = false); - /// clearRegisterKills - Clear all kill flags affecting Reg. If RegInfo is + /// Clear all kill flags affecting Reg. If RegInfo is /// provided, this includes super-register kills. void clearRegisterKills(unsigned Reg, const TargetRegisterInfo *RegInfo); - /// addRegisterDead - We have determined MI defined a register without a use. + /// We have determined MI defined a register without a use. /// Look for the operand that defines it and mark it as IsDead. If /// AddIfNotFound is true, add a implicit operand if it's not found. Returns /// true if the operand exists / is added. @@ -1052,12 +1056,12 @@ class MachineInstr : public ilist_node { /// otherwise undefined super register. void addRegisterDefReadUndef(unsigned Reg); - /// addRegisterDefined - We have determined MI defines a register. Make sure - /// there is an operand defining Reg. + /// We have determined MI defines a register. Make sure there is an operand + /// defining Reg. void addRegisterDefined(unsigned Reg, const TargetRegisterInfo *RegInfo = nullptr); - /// setPhysRegsDeadExcept - Mark every physreg used by this instruction as + /// Mark every physreg used by this instruction as /// dead except those in the UsedRegs list. /// /// On instructions with register mask operands, also add implicit-def @@ -1065,32 +1069,30 @@ class MachineInstr : public ilist_node { void setPhysRegsDeadExcept(ArrayRef UsedRegs, const TargetRegisterInfo &TRI); - /// isSafeToMove - Return true if it is safe to move this instruction. If + /// Return true if it is safe to move this instruction. If /// SawStore is set to true, it means that there is a store (or call) between /// the instruction's location and its intended destination. - bool isSafeToMove(const TargetInstrInfo *TII, AliasAnalysis *AA, - bool &SawStore) const; + bool isSafeToMove(AliasAnalysis *AA, bool &SawStore) const; - /// hasOrderedMemoryRef - Return true if this instruction may have an ordered + /// Return true if this instruction may have an ordered /// or volatile memory reference, or if the information describing the memory /// reference is not available. Return false if it is known to have no /// ordered or volatile memory references. bool hasOrderedMemoryRef() const; - /// isInvariantLoad - Return true if this instruction is loading from a + /// Return true if this instruction is loading from a /// location whose value is invariant across the function. For example, /// loading a value from the constant pool or from the argument area of /// a function if it does not change. This should only return true of *all* /// loads the instruction does are invariant (if it does multiple loads). bool isInvariantLoad(AliasAnalysis *AA) const; - /// isConstantValuePHI - If the specified instruction is a PHI that always - /// merges together the same virtual register, return the register, otherwise - /// return 0. + /// If the specified instruction is a PHI that always merges together the + /// same virtual register, return the register, otherwise return 0. unsigned isConstantValuePHI() const; - /// hasUnmodeledSideEffects - Return true if this instruction has side - /// effects that are not modeled by mayLoad / mayStore, etc. + /// Return true if this instruction has side effects that are not modeled + /// by mayLoad / mayStore, etc. /// For all instructions, the property is encoded in MCInstrDesc::Flags /// (see MCInstrDesc::hasUnmodeledSideEffects(). The only exception is /// INLINEASM instruction, in which case the side effect property is encoded @@ -1098,11 +1100,10 @@ class MachineInstr : public ilist_node { /// bool hasUnmodeledSideEffects() const; - /// allDefsAreDead - Return true if all the defs of this instruction are dead. - /// + /// Return true if all the defs of this instruction are dead. bool allDefsAreDead() const; - /// copyImplicitOps - Copy implicit register operands from specified + /// Copy implicit register operands from specified /// instruction to this instruction. void copyImplicitOps(MachineFunction &MF, const MachineInstr *MI); @@ -1110,6 +1111,8 @@ class MachineInstr : public ilist_node { // Debugging support // void print(raw_ostream &OS, bool SkipOpers = false) const; + void print(raw_ostream &OS, ModuleSlotTracker &MST, + bool SkipOpers = false) const; void dump() const; //===--------------------------------------------------------------------===// @@ -1134,50 +1137,41 @@ class MachineInstr : public ilist_node { /// preferred. void addOperand(const MachineOperand &Op); - /// setDesc - Replace the instruction descriptor (thus opcode) of + /// Replace the instruction descriptor (thus opcode) of /// the current instruction with a new one. - /// void setDesc(const MCInstrDesc &tid) { MCID = &tid; } - /// setDebugLoc - Replace current source information with new such. + /// Replace current source information with new such. /// Avoid using this, the constructor argument is preferable. - /// void setDebugLoc(DebugLoc dl) { debugLoc = std::move(dl); assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); } - /// RemoveOperand - Erase an operand from an instruction, leaving it with one + /// Erase an operand from an instruction, leaving it with one /// fewer operand than it started with. - /// void RemoveOperand(unsigned i); - /// addMemOperand - Add a MachineMemOperand to the machine instruction. + /// Add a MachineMemOperand to the machine instruction. /// This function should be used only occasionally. The setMemRefs function /// is the primary method for setting up a MachineInstr's MemRefs list. void addMemOperand(MachineFunction &MF, MachineMemOperand *MO); - /// setMemRefs - Assign this MachineInstr's memory reference descriptor - /// list. This does not transfer ownership. + /// Assign this MachineInstr's memory reference descriptor list. + /// This does not transfer ownership. void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd) { MemRefs = NewMemRefs; NumMemRefs = uint8_t(NewMemRefsEnd - NewMemRefs); assert(NumMemRefs == NewMemRefsEnd - NewMemRefs && "Too many memrefs"); } - /// clearMemRefs - Clear this MachineInstr's memory reference descriptor list. + /// Clear this MachineInstr's memory reference descriptor list. void clearMemRefs() { MemRefs = nullptr; NumMemRefs = 0; } -private: - /// getRegInfo - If this instruction is embedded into a MachineFunction, - /// return the MachineRegisterInfo object for the current function, otherwise - /// return null. - MachineRegisterInfo *getRegInfo(); - - /// untieRegOperand - Break any tie involving OpIdx. + /// Break any tie involving OpIdx. void untieRegOperand(unsigned OpIdx) { MachineOperand &MO = getOperand(OpIdx); if (MO.isReg() && MO.isTied()) { @@ -1186,22 +1180,27 @@ class MachineInstr : public ilist_node { } } - /// addImplicitDefUseOperands - Add all implicit def and use operands to - /// this instruction. + +private: + /// If this instruction is embedded into a MachineFunction, return the + /// MachineRegisterInfo object for the current function, otherwise + /// return null. + MachineRegisterInfo *getRegInfo(); + + /// Add all implicit def and use operands to this instruction. void addImplicitDefUseOperands(MachineFunction &MF); - /// RemoveRegOperandsFromUseLists - Unlink all of the register operands in - /// this instruction from their respective use lists. This requires that the - /// operands already be on their use lists. + /// Unlink all of the register operands in this instruction from their + /// respective use lists. This requires that the operands already be on their + /// use lists. void RemoveRegOperandsFromUseLists(MachineRegisterInfo&); - /// AddRegOperandsToUseLists - Add all of the register operands in - /// this instruction from their respective use lists. This requires that the - /// operands not be on their use lists yet. + /// Add all of the register operands in this instruction from their + /// respective use lists. This requires that the operands not be on their + /// use lists yet. void AddRegOperandsToUseLists(MachineRegisterInfo&); - /// hasPropertyInBundle - Slow path for hasProperty when we're dealing with a - /// bundle. + /// Slow path for hasProperty when we're dealing with a bundle. bool hasPropertyInBundle(unsigned Mask, QueryType Type) const; /// \brief Implements the logic of getRegClassConstraintEffectForVReg for the @@ -1212,8 +1211,8 @@ class MachineInstr : public ilist_node { const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const; }; -/// MachineInstrExpressionTrait - Special DenseMapInfo traits to compare -/// MachineInstr* by *value* of the instruction rather than by pointer value. +/// Special DenseMapInfo traits to compare MachineInstr* by *value* of the +/// instruction rather than by pointer value. /// The hashing and equality testing functions ignore definitions so this is /// useful for CSE, etc. struct MachineInstrExpressionTrait : DenseMapInfo { diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index 15000aa1774..e5e106e71cf 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -49,11 +49,10 @@ class MachineInstrBuilder { MachineInstrBuilder() : MF(nullptr), MI(nullptr) {} /// Create a MachineInstrBuilder for manipulating an existing instruction. - /// F must be the machine function that was used to allocate I. + /// F must be the machine function that was used to allocate I. MachineInstrBuilder(MachineFunction &F, MachineInstr *I) : MF(&F), MI(I) {} /// Allow automatic conversion to the machine instruction we are working on. - /// operator MachineInstr*() const { return MI; } MachineInstr *operator->() const { return MI; } operator MachineBasicBlock::iterator() const { return MI; } @@ -62,11 +61,9 @@ class MachineInstrBuilder { /// explicitly. MachineInstr *getInstr() const { return MI; } - /// addReg - Add a new virtual register operand... - /// - const - MachineInstrBuilder &addReg(unsigned RegNo, unsigned flags = 0, - unsigned SubReg = 0) const { + /// Add a new virtual register operand. + const MachineInstrBuilder &addReg(unsigned RegNo, unsigned flags = 0, + unsigned SubReg = 0) const { assert((flags & 0x1) == 0 && "Passing in 'true' to addReg is forbidden! Use enums instead."); MI->addOperand(*MF, MachineOperand::CreateReg(RegNo, @@ -82,8 +79,7 @@ class MachineInstrBuilder { return *this; } - /// addImm - Add a new immediate operand. - /// + /// Add a new immediate operand. const MachineInstrBuilder &addImm(int64_t Val) const { MI->addOperand(*MF, MachineOperand::CreateImm(Val)); return *this; @@ -176,7 +172,7 @@ class MachineInstrBuilder { MI->addOperand(*MF, MachineOperand::CreateMetadata(MD)); assert((MI->isDebugValue() ? static_cast(MI->getDebugVariable()) : true) && - "first MDNode argument of a DBG_VALUE not a DIVariable"); + "first MDNode argument of a DBG_VALUE not a variable"); return *this; } @@ -185,8 +181,9 @@ class MachineInstrBuilder { return *this; } - const MachineInstrBuilder &addSym(MCSymbol *Sym) const { - MI->addOperand(*MF, MachineOperand::CreateMCSymbol(Sym)); + const MachineInstrBuilder &addSym(MCSymbol *Sym, + unsigned char TargetFlags = 0) const { + MI->addOperand(*MF, MachineOperand::CreateMCSymbol(Sym, TargetFlags)); return *this; } @@ -229,18 +226,15 @@ class MachineInstrBuilder { } }; -/// BuildMI - Builder interface. Specify how to create the initial instruction -/// itself. -/// +/// Builder interface. Specify how to create the initial instruction itself. inline MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID) { return MachineInstrBuilder(MF, MF.CreateMachineInstr(MCID, DL)); } -/// BuildMI - This version of the builder sets up the first operand as a +/// This version of the builder sets up the first operand as a /// destination virtual register. -/// inline MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID, @@ -249,10 +243,9 @@ inline MachineInstrBuilder BuildMI(MachineFunction &MF, .addReg(DestReg, RegState::Define); } -/// BuildMI - This version of the builder inserts the newly-built -/// instruction before the given position in the given MachineBasicBlock, and -/// sets up the first operand as a destination virtual register. -/// +/// This version of the builder inserts the newly-built instruction before +/// the given position in the given MachineBasicBlock, and sets up the first +/// operand as a destination virtual register. inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineBasicBlock::iterator I, DebugLoc DL, @@ -289,10 +282,9 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, return BuildMI(BB, MII, DL, MCID, DestReg); } -/// BuildMI - This version of the builder inserts the newly-built -/// instruction before the given position in the given MachineBasicBlock, and -/// does NOT take a destination register. -/// +/// This version of the builder inserts the newly-built instruction before the +/// given position in the given MachineBasicBlock, and does NOT take a +/// destination register. inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineBasicBlock::iterator I, DebugLoc DL, @@ -326,35 +318,17 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, return BuildMI(BB, MII, DL, MCID); } -// @LOCALMOD-BEGIN -/// BuildMI - This version of the builder inserts the newly-built -/// instruction before the given position in the given MachineBasicBlock, -/// does NOT take a destination register, and does not add implicit operands. -/// -inline MachineInstrBuilder BuildMI_NoImp(MachineBasicBlock &BB, - MachineBasicBlock::iterator I, - DebugLoc DL, - const MCInstrDesc &MCID) { - MachineInstr *MI = BB.getParent()->CreateMachineInstr(MCID, DL, true); - BB.insert(I, MI); - return MachineInstrBuilder(*BB.getParent(), MI); -} -// @LOCALMOD-END - -/// BuildMI - This version of the builder inserts the newly-built -/// instruction at the end of the given MachineBasicBlock, and does NOT take a -/// destination register. -/// +/// This version of the builder inserts the newly-built instruction at the end +/// of the given MachineBasicBlock, and does NOT take a destination register. inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, DebugLoc DL, const MCInstrDesc &MCID) { return BuildMI(*BB, BB->end(), DL, MCID); } -/// BuildMI - This version of the builder inserts the newly-built -/// instruction at the end of the given MachineBasicBlock, and sets up the first -/// operand as a destination virtual register. -/// +/// This version of the builder inserts the newly-built instruction at the +/// end of the given MachineBasicBlock, and sets up the first operand as a +/// destination virtual register. inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, DebugLoc DL, const MCInstrDesc &MCID, @@ -362,18 +336,17 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, return BuildMI(*BB, BB->end(), DL, MCID, DestReg); } -/// BuildMI - This version of the builder builds a DBG_VALUE intrinsic +/// This version of the builder builds a DBG_VALUE intrinsic /// for either a value in a register or a register-indirect+offset /// address. The convention is that a DBG_VALUE is indirect iff the /// second operand is an immediate. -/// inline MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID, bool IsIndirect, unsigned Reg, unsigned Offset, const MDNode *Variable, const MDNode *Expr) { - assert(isa(Variable) && "not a DIVariable"); - assert(cast(Expr)->isValid() && "not a DIExpression"); - assert(cast(Variable)->isValidLocationForIntrinsic(DL) && + assert(isa(Variable) && "not a variable"); + assert(cast(Expr)->isValid() && "not an expression"); + assert(cast(Variable)->isValidLocationForIntrinsic(DL) && "Expected inlined-at fields to agree"); if (IsIndirect) return BuildMI(MF, DL, MCID) @@ -391,17 +364,16 @@ inline MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, } } -/// BuildMI - This version of the builder builds a DBG_VALUE intrinsic +/// This version of the builder builds a DBG_VALUE intrinsic /// for either a value in a register or a register-indirect+offset /// address and inserts it at position I. -/// inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, MachineBasicBlock::iterator I, DebugLoc DL, const MCInstrDesc &MCID, bool IsIndirect, unsigned Reg, unsigned Offset, const MDNode *Variable, const MDNode *Expr) { - assert(isa(Variable) && "not a DIVariable"); - assert(cast(Expr)->isValid() && "not a DIExpression"); + assert(isa(Variable) && "not a variable"); + assert(cast(Expr)->isValid() && "not an expression"); MachineFunction &MF = *BB.getParent(); MachineInstr *MI = BuildMI(MF, DL, MCID, IsIndirect, Reg, Offset, Variable, Expr); diff --git a/include/llvm/CodeGen/MachineLoopInfo.h b/include/llvm/CodeGen/MachineLoopInfo.h index f7bcf45d93c..4868b7363f8 100644 --- a/include/llvm/CodeGen/MachineLoopInfo.h +++ b/include/llvm/CodeGen/MachineLoopInfo.h @@ -37,10 +37,8 @@ namespace llvm { // Implementation in LoopInfoImpl.h -#ifdef __GNUC__ class MachineLoop; -__extension__ extern template class LoopBase; -#endif +extern template class LoopBase; class MachineLoop : public LoopBase { public: @@ -65,10 +63,7 @@ class MachineLoop : public LoopBase { }; // Implementation in LoopInfoImpl.h -#ifdef __GNUC__ -__extension__ extern template -class LoopInfoBase; -#endif +extern template class LoopInfoBase; class MachineLoopInfo : public MachineFunctionPass { LoopInfoBase LI; @@ -114,7 +109,7 @@ class MachineLoopInfo : public MachineFunctionPass { } // isLoopHeader - True if the block is a loop header node - inline bool isLoopHeader(MachineBasicBlock *BB) const { + inline bool isLoopHeader(const MachineBasicBlock *BB) const { return LI.isLoopHeader(BB); } diff --git a/include/llvm/CodeGen/MachineMemOperand.h b/include/llvm/CodeGen/MachineMemOperand.h index a16c294a074..a73b92f9a25 100644 --- a/include/llvm/CodeGen/MachineMemOperand.h +++ b/include/llvm/CodeGen/MachineMemOperand.h @@ -27,6 +27,7 @@ namespace llvm { class FoldingSetNodeID; class MDNode; class raw_ostream; +class ModuleSlotTracker; /// MachinePointerInfo - This class contains a discriminated union of /// information about pointers in memory operands, relating them back to LLVM IR @@ -200,6 +201,12 @@ class MachineMemOperand { /// void Profile(FoldingSetNodeID &ID) const; + /// Support for operator<<. + /// @{ + void print(raw_ostream &OS) const; + void print(raw_ostream &OS, ModuleSlotTracker &MST) const; + /// @} + friend bool operator==(const MachineMemOperand &LHS, const MachineMemOperand &RHS) { return LHS.getValue() == RHS.getValue() && @@ -219,7 +226,10 @@ class MachineMemOperand { } }; -raw_ostream &operator<<(raw_ostream &OS, const MachineMemOperand &MRO); +inline raw_ostream &operator<<(raw_ostream &OS, const MachineMemOperand &MRO) { + MRO.print(OS); + return OS; +} } // End llvm namespace diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 3965b1dea70..4cdfe2463c9 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -51,6 +51,7 @@ namespace llvm { // Forward declarations. class Constant; class GlobalVariable; +class BlockAddress; class MDNode; class MMIAddrLabelMap; class MachineBasicBlock; @@ -60,6 +61,14 @@ class PointerType; class StructType; struct WinEHFuncInfo; +struct SEHHandler { + // Filter or finally function. Null indicates a catch-all. + const Function *FilterOrFinally; + + // Address of block to recover at. Null for a finally handler. + const BlockAddress *RecoverBA; +}; + //===----------------------------------------------------------------------===// /// LandingPadInfo - This structure is used to retain landing pad info for /// the current function. @@ -68,7 +77,7 @@ struct LandingPadInfo { MachineBasicBlock *LandingPadBlock; // Landing pad block. SmallVector BeginLabels; // Labels prior to invoke. SmallVector EndLabels; // Labels after invoke. - SmallVector ClauseLabels; // Labels for each clause. + SmallVector SEHHandlers; // SEH handlers active at this lpad. MCSymbol *LandingPadLabel; // Label at beginning of landing pad. const Function *Personality; // Personality function. std::vector TypeIds; // List of type ids (filters negative). @@ -148,11 +157,6 @@ class MachineModuleInfo : public ImmutablePass { /// emit common EH frames. std::vector 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 UsedFunctions; - /// AddrLabelSymbols - This map keeps track of which symbol is being used for /// the specified basic block's address of label. MMIAddrLabelMap *AddrLabelSymbols; @@ -184,13 +188,13 @@ class MachineModuleInfo : public ImmutablePass { static char ID; // Pass identification, replacement for typeid struct VariableDbgInfo { - const MDLocalVariable *Var; - const MDExpression *Expr; + const DILocalVariable *Var; + const DIExpression *Expr; unsigned Slot; - const MDLocation *Loc; + const DILocation *Loc; - VariableDbgInfo(const MDLocalVariable *Var, const MDExpression *Expr, - unsigned Slot, const MDLocation *Loc) + VariableDbgInfo(const DILocalVariable *Var, const DIExpression *Expr, + unsigned Slot, const DILocation *Loc) : Var(Var), Expr(Expr), Slot(Slot), Loc(Loc) {} }; typedef SmallVector VariableDbgInfoMapTy; @@ -237,10 +241,6 @@ class MachineModuleInfo : public ImmutablePass { return const_cast(this)->getObjFileInfo(); } - /// 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; } @@ -284,12 +284,14 @@ class MachineModuleInfo : public ImmutablePass { /// getAddrLabelSymbol - Return the symbol to be used for the specified basic /// block when its address is taken. This cannot be its normal LBB label /// because the block may be accessed outside its containing function. - MCSymbol *getAddrLabelSymbol(const BasicBlock *BB); + MCSymbol *getAddrLabelSymbol(const BasicBlock *BB) { + return getAddrLabelSymbolToEmit(BB).front(); + } /// getAddrLabelSymbolToEmit - Return the symbol to be used for the specified /// basic block when its address is taken. If other blocks were RAUW'd to /// this one, we may have to emit them as well, return the whole set. - std::vector getAddrLabelSymbolToEmit(const BasicBlock *BB); + ArrayRef getAddrLabelSymbolToEmit(const BasicBlock *BB); /// takeDeletedSymbolsForFunction - If the specified function has had any /// references to address-taken blocks generated, but the block got deleted, @@ -318,6 +320,7 @@ class MachineModuleInfo : public ImmutablePass { /// information. void addPersonality(MachineBasicBlock *LandingPad, const Function *Personality); + void addPersonality(const Function *Personality); void addWinEHState(MachineBasicBlock *LandingPad, int State); @@ -330,13 +333,6 @@ class MachineModuleInfo : public ImmutablePass { 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, @@ -351,10 +347,11 @@ class MachineModuleInfo : public ImmutablePass { /// void addCleanup(MachineBasicBlock *LandingPad); - /// Add a clause for a landing pad. Returns a new label for the clause. This - /// is used by EH schemes that have more than one landing pad. In this case, - /// each clause gets its own basic block. - MCSymbol *addClauseForLandingPad(MachineBasicBlock *LandingPad); + void addSEHCatchHandler(MachineBasicBlock *LandingPad, const Function *Filter, + const BlockAddress *RecoverLabel); + + void addSEHCleanupHandler(MachineBasicBlock *LandingPad, + const Function *Cleanup); /// getTypeIDFor - Return the type id for the specified typeinfo. This is /// function wide. @@ -438,8 +435,8 @@ class MachineModuleInfo : public ImmutablePass { /// setVariableDbgInfo - Collect information used to emit debugging /// information of a variable. - void setVariableDbgInfo(const MDLocalVariable *Var, const MDExpression *Expr, - unsigned Slot, const MDLocation *Loc) { + void setVariableDbgInfo(const DILocalVariable *Var, const DIExpression *Expr, + unsigned Slot, const DILocation *Loc) { VariableDbgInfos.emplace_back(Var, Expr, Slot, Loc); } diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index 04d5361ed5d..c43e47c36d0 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -27,6 +27,7 @@ class MachineBasicBlock; class MachineInstr; class MachineRegisterInfo; class MDNode; +class ModuleSlotTracker; class TargetMachine; class TargetRegisterInfo; class hash_code; @@ -65,7 +66,7 @@ class MachineOperand { private: /// OpKind - Specify what kind of operand this is. This discriminates the /// union. - MachineOperandType OpKind; + MachineOperandType OpKind : 8; /// Subregister number for MO_Register. A value of 0 indicates the /// MO_Register has no subReg. @@ -218,6 +219,8 @@ class MachineOperand { void clearParent() { ParentMI = nullptr; } void print(raw_ostream &os, const TargetRegisterInfo *TRI = nullptr) const; + void print(raw_ostream &os, ModuleSlotTracker &MST, + const TargetRegisterInfo *TRI = nullptr) const; //===--------------------------------------------------------------------===// // Accessors that tell you what kind of MachineOperand you're looking at. @@ -450,11 +453,12 @@ class MachineOperand { return Contents.CFIIndex; } - /// getOffset - Return the offset from the symbol in this operand. This always - /// returns 0 for ExternalSymbol operands. + /// Return the offset from the symbol in this operand. This always returns 0 + /// for ExternalSymbol operands. int64_t getOffset() const { - assert((isGlobal() || isSymbol() || isCPI() || isTargetIndex() || - isBlockAddress()) && "Wrong MachineOperand accessor"); + assert((isGlobal() || isSymbol() || isMCSymbol() || isCPI() || + isTargetIndex() || isBlockAddress()) && + "Wrong MachineOperand accessor"); return int64_t(uint64_t(Contents.OffsetedInfo.OffsetHi) << 32) | SmallContents.OffsetLo; } @@ -512,8 +516,9 @@ class MachineOperand { } void setOffset(int64_t Offset) { - assert((isGlobal() || isSymbol() || isCPI() || isTargetIndex() || - isBlockAddress()) && "Wrong MachineOperand accessor"); + assert((isGlobal() || isSymbol() || isMCSymbol() || isCPI() || + isTargetIndex() || isBlockAddress()) && + "Wrong MachineOperand accessor"); SmallContents.OffsetLo = unsigned(Offset); Contents.OffsetedInfo.OffsetHi = int(Offset >> 32); } @@ -554,6 +559,12 @@ class MachineOperand { /// already, the setFPImm method should be used. void ChangeToFPImmediate(const ConstantFP *FPImm); + /// ChangeToES - Replace this operand with a new external symbol operand. + void ChangeToES(const char *SymName, unsigned char TargetFlags = 0); + + /// ChangeToMCSymbol - Replace this operand with a new MC symbol operand. + void ChangeToMCSymbol(MCSymbol *Sym); + /// ChangeToRegister - Replace this operand with a new register operand of /// the specified value. If an operand is known to be an register already, /// the setReg method should be used. @@ -697,9 +708,12 @@ class MachineOperand { return Op; } - static MachineOperand CreateMCSymbol(MCSymbol *Sym) { + static MachineOperand CreateMCSymbol(MCSymbol *Sym, + unsigned char TargetFlags = 0) { MachineOperand Op(MachineOperand::MO_MCSymbol); Op.Contents.Sym = Sym; + Op.setOffset(0); + Op.setTargetFlags(TargetFlags); return Op; } diff --git a/include/llvm/CodeGen/MachineRegionInfo.h b/include/llvm/CodeGen/MachineRegionInfo.h index cf49c297c28..df9823f741d 100644 --- a/include/llvm/CodeGen/MachineRegionInfo.h +++ b/include/llvm/CodeGen/MachineRegionInfo.h @@ -172,10 +172,9 @@ template <> struct GraphTraits } }; -EXTERN_TEMPLATE_INSTANTIATION(class RegionBase>); -EXTERN_TEMPLATE_INSTANTIATION(class RegionNodeBase>); -EXTERN_TEMPLATE_INSTANTIATION(class RegionInfoBase>); - +extern template class RegionBase>; +extern template class RegionNodeBase>; +extern template class RegionInfoBase>; } #endif diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index e5b837aeea2..2f823b44801 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -95,20 +95,8 @@ class MachineRegisterInfo { return MO->Contents.Reg.Next; } - /// UsedRegUnits - This is a bit vector that is computed and set by the - /// register allocator, and must be kept up to date by passes that run after - /// register allocation (though most don't modify this). This is used - /// so that the code generator knows which callee save registers to save and - /// for other target specific uses. - /// This vector has bits set for register units that are modified in the - /// current function. It doesn't include registers clobbered by function - /// calls with register mask operands. - BitVector UsedRegUnits; - /// UsedPhysRegMask - Additional used physregs including aliases. /// This bit vector represents all the registers clobbered by function calls. - /// It can model things that UsedRegUnits can't, such as function calls that - /// clobber ymm7 but preserve the low half in xmm7. BitVector UsedPhysRegMask; /// ReservedRegs - This is a bit vector of reserved registers. The target @@ -626,6 +614,12 @@ class MachineRegisterInfo { RegAllocHints[VReg].second = PrefReg; } + /// Specify the preferred register allocation hint for the specified virtual + /// register. + void setSimpleHint(unsigned VReg, unsigned PrefReg) { + setRegAllocationHint(VReg, /*Type=*/0, PrefReg); + } + /// getRegAllocationHint - Return the register allocation hint for the /// specified virtual register. std::pair @@ -647,40 +641,11 @@ class MachineRegisterInfo { /// deleted during LiveDebugVariables analysis. void markUsesInDebugValueAsUndef(unsigned Reg) const; - //===--------------------------------------------------------------------===// - // Physical Register Use Info - //===--------------------------------------------------------------------===// - - /// isPhysRegUsed - Return true if the specified register is used in this - /// function. Also check for clobbered aliases and registers clobbered by - /// function calls with register mask operands. - /// - /// This only works after register allocation. It is primarily used by - /// PrologEpilogInserter to determine which callee-saved registers need - /// spilling. - bool isPhysRegUsed(unsigned Reg) const { - if (UsedPhysRegMask.test(Reg)) - return true; - for (MCRegUnitIterator Units(Reg, getTargetRegisterInfo()); - Units.isValid(); ++Units) - if (UsedRegUnits.test(*Units)) - return true; - return false; - } - - /// Mark the specified register unit as used in this function. - /// This should only be called during and after register allocation. - void setRegUnitUsed(unsigned RegUnit) { - UsedRegUnits.set(RegUnit); - } - - /// setPhysRegUsed - Mark the specified register used in this function. - /// This should only be called during and after register allocation. - void setPhysRegUsed(unsigned Reg) { - for (MCRegUnitIterator Units(Reg, getTargetRegisterInfo()); - Units.isValid(); ++Units) - UsedRegUnits.set(*Units); - } + /// Return true if the specified register is modified in this function. + /// This checks that no defining machine operands exist for the register or + /// any of its aliases. Definitions found on functions marked noreturn are + /// ignored. + bool isPhysRegModified(unsigned PhysReg) const; /// addPhysRegsUsedFromRegMask - Mark any registers not in RegMask as used. /// This corresponds to the bit mask attached to register mask operands. @@ -688,16 +653,6 @@ class MachineRegisterInfo { UsedPhysRegMask.setBitsNotInMask(RegMask); } - /// setPhysRegUnused - Mark the specified register unused in this function. - /// This should only be called during and after register allocation. - void setPhysRegUnused(unsigned Reg) { - UsedPhysRegMask.reset(Reg); - for (MCRegUnitIterator Units(Reg, getTargetRegisterInfo()); - Units.isValid(); ++Units) - UsedRegUnits.reset(*Units); - } - - //===--------------------------------------------------------------------===// // Reserved Register Info //===--------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index e80e14e5ccf..dee2b7107a4 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -915,7 +915,7 @@ class PostGenericScheduler : public GenericSchedulerBase { MachineBasicBlock::iterator End, unsigned NumRegionInstrs) override { /* no configurable policy */ - }; + } /// PostRA scheduling does not track pressure. bool shouldTrackPressure() const override { return false; } diff --git a/include/llvm/CodeGen/MachineValueType.h b/include/llvm/CodeGen/MachineValueType.h index 3eb4d0b85de..a728df35467 100644 --- a/include/llvm/CodeGen/MachineValueType.h +++ b/include/llvm/CodeGen/MachineValueType.h @@ -26,7 +26,7 @@ namespace llvm { /// MVT - Machine Value Type. Every type that is supported natively by some /// processor targeted by LLVM occurs here. This means that any legal value /// type can be represented by an MVT. - class MVT { +class MVT { public: enum SimpleValueType { // INVALID_SIMPLE_VALUE_TYPE - Simple value types less than zero are @@ -86,22 +86,23 @@ namespace llvm { v4i64 = 39, // 4 x i64 v8i64 = 40, // 8 x i64 v16i64 = 41, // 16 x i64 - + v1i128 = 42, // 1 x i128 + FIRST_INTEGER_VECTOR_VALUETYPE = v2i1, - LAST_INTEGER_VECTOR_VALUETYPE = v16i64, - - v2f16 = 42, // 2 x f16 - v4f16 = 43, // 4 x f16 - v8f16 = 44, // 8 x f16 - v1f32 = 45, // 1 x f32 - v2f32 = 46, // 2 x f32 - v4f32 = 47, // 4 x f32 - v8f32 = 48, // 8 x f32 - v16f32 = 49, // 16 x f32 - v1f64 = 50, // 1 x f64 - v2f64 = 51, // 2 x f64 - v4f64 = 52, // 4 x f64 - v8f64 = 53, // 8 x f64 + LAST_INTEGER_VECTOR_VALUETYPE = v1i128, + + v2f16 = 43, // 2 x f16 + v4f16 = 44, // 4 x f16 + v8f16 = 45, // 8 x f16 + v1f32 = 46, // 1 x f32 + v2f32 = 47, // 2 x f32 + v4f32 = 48, // 4 x f32 + v8f32 = 49, // 8 x f32 + v16f32 = 50, // 16 x f32 + v1f64 = 51, // 1 x f64 + v2f64 = 52, // 2 x f64 + v4f64 = 53, // 4 x f64 + v8f64 = 54, // 8 x f64 FIRST_FP_VECTOR_VALUETYPE = v2f16, LAST_FP_VECTOR_VALUETYPE = v8f64, @@ -109,18 +110,18 @@ namespace llvm { FIRST_VECTOR_VALUETYPE = v2i1, LAST_VECTOR_VALUETYPE = v8f64, - x86mmx = 54, // This is an X86 MMX value + x86mmx = 55, // This is an X86 MMX value - Glue = 55, // This glues nodes together during pre-RA sched + Glue = 56, // This glues nodes together during pre-RA sched - isVoid = 56, // This has no value + isVoid = 57, // This has no value - Untyped = 57, // This value takes a register, but has + Untyped = 58, // This value takes a register, but has // unspecified type. The register class // will be determined by the opcode. FIRST_VALUETYPE = 0, // This is always the beginning of the list. - LAST_VALUETYPE = 58, // This always remains at the end of the list. + LAST_VALUETYPE = 59, // This always remains at the end of the list. // This is the current maximum for LAST_VALUETYPE. // MVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors @@ -222,10 +223,10 @@ namespace llvm { /// is128BitVector - Return true if this is a 128-bit vector type. bool is128BitVector() const { - return (SimpleTy == MVT::v16i8 || SimpleTy == MVT::v8i16 || - SimpleTy == MVT::v4i32 || SimpleTy == MVT::v2i64 || - SimpleTy == MVT::v8f16 || SimpleTy == MVT::v4f32 || - SimpleTy == MVT::v2f64); + return (SimpleTy == MVT::v16i8 || SimpleTy == MVT::v8i16 || + SimpleTy == MVT::v4i32 || SimpleTy == MVT::v2i64 || + SimpleTy == MVT::v1i128 || SimpleTy == MVT::v8f16 || + SimpleTy == MVT::v4f32 || SimpleTy == MVT::v2f64); } /// is256BitVector - Return true if this is a 256-bit vector type. @@ -310,6 +311,7 @@ namespace llvm { case v4i64: case v8i64: case v16i64: return i64; + case v1i128: return i128; case v2f16: case v4f16: case v8f16: return f16; @@ -368,6 +370,7 @@ namespace llvm { case v1i16: case v1i32: case v1i64: + case v1i128: case v1f32: case v1f64: return 1; } @@ -427,6 +430,7 @@ namespace llvm { case v8i16: case v4i32: case v2i64: + case v1i128: case v8f16: case v4f32: case v2f64: return 128; @@ -562,6 +566,9 @@ namespace llvm { if (NumElements == 8) return MVT::v8i64; if (NumElements == 16) return MVT::v16i64; break; + case MVT::i128: + if (NumElements == 1) return MVT::v1i128; + break; case MVT::f16: if (NumElements == 2) return MVT::v2f16; if (NumElements == 4) return MVT::v4f16; diff --git a/include/llvm/CodeGen/PBQP/Graph.h b/include/llvm/CodeGen/PBQP/Graph.h index efb723cab39..f73383ed100 100644 --- a/include/llvm/CodeGen/PBQP/Graph.h +++ b/include/llvm/CodeGen/PBQP/Graph.h @@ -21,6 +21,7 @@ #include #include #include +#include namespace llvm { namespace PBQP { diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 2505c04a720..5d829217447 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -17,11 +17,11 @@ #include "llvm/Pass.h" #include "llvm/Target/TargetMachine.h" +#include #include namespace llvm { -class FunctionPass; class MachineFunctionPass; class PassConfigImpl; class PassInfo; @@ -101,7 +101,7 @@ class TargetPassConfig : public ImmutablePass { private: PassManagerBase *PM; - AnalysisID StartAfter; + AnalysisID StartBefore, StartAfter; AnalysisID StopAfter; bool Started; bool Stopped; @@ -120,6 +120,9 @@ class TargetPassConfig : public ImmutablePass { /// Default setting for -enable-tail-merge on this target. bool EnableTailMerge; + /// Default setting for -enable-shrink-wrap on this target. + bool EnableShrinkWrap; + public: TargetPassConfig(TargetMachine *tm, PassManagerBase &pm); // Dummy constructor. @@ -139,16 +142,24 @@ class TargetPassConfig : public ImmutablePass { CodeGenOpt::Level getOptLevel() const { return TM->getOptLevel(); } - /// setStartStopPasses - Set the StartAfter and StopAfter passes to allow - /// running only a portion of the normal code-gen pass sequence. If the - /// Start pass ID is zero, then compilation will begin at the normal point; - /// otherwise, clear the Started flag to indicate that passes should not be - /// added until the starting pass is seen. If the Stop pass ID is zero, - /// then compilation will continue to the end. - void setStartStopPasses(AnalysisID Start, AnalysisID Stop) { - StartAfter = Start; - StopAfter = Stop; - Started = (StartAfter == nullptr); + /// Set the StartAfter, StartBefore and StopAfter passes to allow running only + /// a portion of the normal code-gen pass sequence. + /// + /// If the StartAfter and StartBefore pass ID is zero, then compilation will + /// begin at the normal point; otherwise, clear the Started flag to indicate + /// that passes should not be added until the starting pass is seen. If the + /// Stop pass ID is zero, then compilation will continue to the end. + /// + /// This function expects that at least one of the StartAfter or the + /// StartBefore pass IDs is null. + void setStartStopPasses(AnalysisID StartBefore, AnalysisID StartAfter, + AnalysisID StopAfter) { + if (StartAfter) + assert(!StartBefore && "Start after and start before passes are given"); + this->StartBefore = StartBefore; + this->StartAfter = StartAfter; + this->StopAfter = StopAfter; + Started = (StartAfter == nullptr) && (StartBefore == nullptr); } void setDisableVerify(bool Disable) { setOpt(DisableVerify, Disable); } @@ -179,6 +190,9 @@ class TargetPassConfig : public ImmutablePass { /// Return true if the optimized regalloc pipeline is enabled. bool getOptimizeRegAlloc() const; + /// Return true if shrink wrapping is enabled. + bool getEnableShrinkWrap() const; + /// Return true if the default global register allocator is in use and /// has not be overriden on the command line with '-regalloc=...' bool usingDefaultRegAlloc() const; @@ -368,6 +382,10 @@ namespace llvm { createMachineFunctionPrinterPass(raw_ostream &OS, const std::string &Banner =""); + /// MIRPrinting pass - this pass prints out the LLVM IR into the given stream + /// using the MIR serialization format. + MachineFunctionPass *createPrintMIRPass(raw_ostream &OS); + /// createCodeGenPreparePass - Transform the code to expose more pattern /// matching during instruction selection. FunctionPass *createCodeGenPreparePass(const TargetMachine *TM = nullptr); @@ -426,6 +444,10 @@ namespace llvm { /// basic blocks. extern char &SpillPlacementID; + /// ShrinkWrap pass. Look for the best place to insert save and restore + // instruction and update the MachineFunctionInfo with that information. + extern char &ShrinkWrapID; + /// VirtRegRewriter pass. Rewrite virtual registers to physical registers as /// assigned in VirtRegMap. extern char &VirtRegRewriterID; @@ -478,6 +500,10 @@ namespace llvm { /// MachineFunctionPrinterPass - This pass prints out MachineInstr's. extern char &MachineFunctionPrinterPassID; + /// MIRPrintingPass - this pass prints out the LLVM IR using the MIR + /// serialization format. + extern char &MIRPrintingPassID; + /// TailDuplicate - Duplicate blocks with unconditional branches /// into tails of their predecessors. extern char &TailDuplicateID; @@ -501,6 +527,8 @@ namespace llvm { /// IfConverter - This pass performs machine code if conversion. extern char &IfConverterID; + FunctionPass *createIfConverter(std::function Ftor); + /// MachineBlockPlacement - This pass places basic blocks based on branch /// probabilities. extern char &MachineBlockPlacementID; @@ -532,6 +560,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; @@ -573,7 +605,7 @@ namespace llvm { /// createSjLjEHPreparePass - This pass adapts exception handling code to use /// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow. /// - FunctionPass *createSjLjEHPreparePass(const TargetMachine *TM); + FunctionPass *createSjLjEHPreparePass(); /// LocalStackSlotAllocation - This pass assigns local frame indices to stack /// slots relative to one another and allocates base registers to access them @@ -595,6 +627,9 @@ namespace llvm { /// UnpackMachineBundles - This pass unpack machine instruction bundles. extern char &UnpackMachineBundlesID; + FunctionPass * + createUnpackMachineBundles(std::function Ftor); + /// FinalizeMachineBundles - This pass finalize machine instruction /// bundles (created earlier, e.g. during pre-RA scheduling). extern char &FinalizeMachineBundlesID; @@ -610,6 +645,11 @@ namespace llvm { /// createForwardControlFlowIntegrityPass - This pass adds control-flow /// integrity. ModulePass *createForwardControlFlowIntegrityPass(); + + /// InterleavedAccess Pass - This pass identifies and matches interleaved + /// memory accesses to target specific intrinsics. + /// + FunctionPass *createInterleavedAccessPass(const TargetMachine *TM); } // End llvm namespace /// Target machine pass initializer for passes with dependencies. Use with diff --git a/include/llvm/CodeGen/PseudoSourceValue.h b/include/llvm/CodeGen/PseudoSourceValue.h index cc3e25aeb89..a518b623325 100644 --- a/include/llvm/CodeGen/PseudoSourceValue.h +++ b/include/llvm/CodeGen/PseudoSourceValue.h @@ -29,8 +29,7 @@ namespace llvm { /// space), or constant pool. class PseudoSourceValue { private: - friend raw_ostream &llvm::operator<<(raw_ostream &OS, - const MachineMemOperand &MMO); + friend class MachineMemOperand; // For printCustom(). /// printCustom - Implement printing for PseudoSourceValue. This is called /// from Value::print or Value's operator<<. diff --git a/include/llvm/CodeGen/RegisterPressure.h b/include/llvm/CodeGen/RegisterPressure.h index fcb6feed68c..9d8843d1d74 100644 --- a/include/llvm/CodeGen/RegisterPressure.h +++ b/include/llvm/CodeGen/RegisterPressure.h @@ -135,6 +135,8 @@ class PressureDiff { void addPressureChange(unsigned RegUnit, bool IsDec, const MachineRegisterInfo *MRI); + + LLVM_DUMP_METHOD void dump(const TargetRegisterInfo &TRI) const; }; /// Array of PressureDiffs. diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h index 474861e45df..df3fd34e0af 100644 --- a/include/llvm/CodeGen/RegisterScavenging.h +++ b/include/llvm/CodeGen/RegisterScavenging.h @@ -9,7 +9,7 @@ // // This file declares the machine register scavenger class. It can provide // information such as unused register at any point in a machine basic block. -// It also provides a mechanism to make registers availbale by evicting them +// It also provides a mechanism to make registers available by evicting them // to spill slots. // //===----------------------------------------------------------------------===// @@ -36,8 +36,7 @@ class RegScavenger { MachineBasicBlock::iterator MBBI; unsigned NumRegUnits; - /// Tracking - True if RegScavenger is currently tracking the liveness of - /// registers. + /// True if RegScavenger is currently tracking the liveness of registers. bool Tracking; /// Information on scavenged registers (held in a spill slot). @@ -58,8 +57,8 @@ class RegScavenger { /// A vector of information on scavenged registers. SmallVector Scavenged; - /// RegUnitsAvailable - The current state of each reg unit immediatelly - /// before MBBI. One bit per register unit. If bit is not set it means any + /// The current state of each reg unit immediately before MBBI. + /// One bit per register unit. If bit is not set it means any /// register containing that register unit is currently being used. BitVector RegUnitsAvailable; @@ -72,18 +71,17 @@ class RegScavenger { RegScavenger() : MBB(nullptr), NumRegUnits(0), Tracking(false) {} - /// enterBasicBlock - Start tracking liveness from the begin of the specific - /// basic block. + /// Start tracking liveness from the begin of the specific basic block. void enterBasicBlock(MachineBasicBlock *mbb); - /// initRegState - allow resetting register state info for multiple + /// Allow resetting register state info for multiple /// passes over/within the same function. void initRegState(); - /// forward - Move the internal MBB iterator and update register states. + /// Move the internal MBB iterator and update register states. void forward(); - /// forward - Move the internal MBB iterator and update register states until + /// Move the internal MBB iterator and update register states until /// it has processed the specific iterator. void forward(MachineBasicBlock::iterator I) { if (!Tracking && MBB->begin() != I) forward(); @@ -99,7 +97,7 @@ class RegScavenger { while (MBBI != I) unprocess(); } - /// skipTo - Move the internal MBB iterator but do not update register states. + /// Move the internal MBB iterator but do not update register states. void skipTo(MachineBasicBlock::iterator I) { if (I == MachineBasicBlock::iterator(nullptr)) Tracking = false; @@ -110,14 +108,13 @@ class RegScavenger { return MBBI; } - /// isRegUsed - return if a specific register is currently used. + /// Return if a specific register is currently used. bool isRegUsed(unsigned Reg, bool includeReserved = true) const; - /// getRegsAvailable - Return all available registers in the register class - /// in Mask. + /// Return all available registers in the register class in Mask. BitVector getRegsAvailable(const TargetRegisterClass *RC); - /// FindUnusedReg - Find a unused register of the specified register class. + /// Find an unused register of the specified register class. /// Return 0 if none is found. unsigned FindUnusedReg(const TargetRegisterClass *RegClass) const; @@ -144,7 +141,7 @@ class RegScavenger { A.push_back(I->FrameIndex); } - /// scavengeRegister - Make a register of the specific register class + /// Make a register of the specific register class /// available and do the appropriate bookkeeping. SPAdj is the stack /// adjustment due to call frame, it's passed along to eliminateFrameIndex(). /// Returns the scavenged register. @@ -154,11 +151,10 @@ class RegScavenger { return scavengeRegister(RegClass, MBBI, SPAdj); } - /// setRegUsed - Tell the scavenger a register is used. - /// + /// Tell the scavenger a register is used. void setRegUsed(unsigned Reg); private: - /// isReserved - Returns true if a register is reserved. It is never "unused". + /// Returns true if a register is reserved. It is never "unused". bool isReserved(unsigned Reg) const { return MRI->isReserved(Reg); } /// setUsed / setUnused - Mark the state of one or a number of register units. @@ -177,9 +173,8 @@ class RegScavenger { /// Add all Reg Units that Reg contains to BV. void addRegUnits(BitVector &BV, unsigned Reg); - /// findSurvivorReg - Return the candidate register that is unused for the - /// longest after StartMI. UseMI is set to the instruction where the search - /// stopped. + /// Return the candidate register that is unused for the longest after + /// StartMI. UseMI is set to the instruction where the search stopped. /// /// No more than InstrLimit instructions are inspected. unsigned findSurvivorReg(MachineBasicBlock::iterator StartMI, diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 83913141656..539756ef502 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -374,7 +374,7 @@ namespace llvm { /// correspond to schedulable entities (e.g. instructions) and do not have a /// valid ID. Consequently, always check for boundary nodes before accessing /// an assoicative data structure keyed on node ID. - bool isBoundaryNode() const { return NodeNum == BoundaryID; }; + bool isBoundaryNode() const { return NodeNum == BoundaryID; } /// setNode - Assign the representative SDNode for this SUnit. /// This may be used during pre-regalloc scheduling. diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h index 1196783e820..b56d5ec8ce6 100644 --- a/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -260,7 +260,7 @@ namespace llvm { #ifndef NDEBUG const SUnit *Addr = SUnits.empty() ? nullptr : &SUnits[0]; #endif - SUnits.push_back(SUnit(MI, (unsigned)SUnits.size())); + SUnits.emplace_back(MI, (unsigned)SUnits.size()); assert((Addr == nullptr || Addr == &SUnits[0]) && "SUnits std::vector reallocated on the fly!"); SUnits.back().OrigNode = &SUnits.back(); diff --git a/include/llvm/CodeGen/SchedulerRegistry.h b/include/llvm/CodeGen/SchedulerRegistry.h index 51ac7f28527..a7a6227664d 100644 --- a/include/llvm/CodeGen/SchedulerRegistry.h +++ b/include/llvm/CodeGen/SchedulerRegistry.h @@ -52,12 +52,6 @@ class RegisterScheduler : public MachinePassRegistryNode { static RegisterScheduler *getList() { return (RegisterScheduler *)Registry.getList(); } - static FunctionPassCtor getDefault() { - return (FunctionPassCtor)Registry.getDefault(); - } - static void setDefault(FunctionPassCtor C) { - Registry.setDefault((MachinePassCtor)C); - } static void setListener(MachinePassRegistryListener *L) { Registry.setListener(L); } diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index 582febda085..1ee92380e69 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -112,6 +112,7 @@ template<> struct ilist_traits : public ilist_default_traits { /// motion, and debug info for them is potentially useful even if the parameter /// is unused. Right now only byval parameters are handled separately. class SDDbgInfo { + BumpPtrAllocator Alloc; SmallVector DbgValues; SmallVector ByvalParmDbgValues; typedef DenseMap > DbgValMapType; @@ -138,8 +139,11 @@ class SDDbgInfo { DbgValMap.clear(); DbgValues.clear(); ByvalParmDbgValues.clear(); + Alloc.Reset(); } + BumpPtrAllocator &getAlloc() { return Alloc; } + bool empty() const { return DbgValues.empty() && ByvalParmDbgValues.empty(); } @@ -277,6 +281,7 @@ class SelectionDAG { void clear(); MachineFunction &getMachineFunction() const { return *MF; } + const DataLayout &getDataLayout() const { return MF->getDataLayout(); } const TargetMachine &getTarget() const { return TM; } const TargetSubtargetInfo &getSubtarget() const { return MF->getSubtarget(); } const TargetLowering &getTargetLoweringInfo() const { return *TLI; } @@ -318,6 +323,14 @@ class SelectionDAG { return AllNodes.size(); } + iterator_range allnodes() { + return iterator_range(allnodes_begin(), allnodes_end()); + } + iterator_range allnodes() const { + return iterator_range(allnodes_begin(), + allnodes_end()); + } + /// Return the root tag of the SelectionDAG. const SDValue &getRoot() const { return Root; } @@ -413,36 +426,40 @@ class SelectionDAG { //===--------------------------------------------------------------------===// // Node creation methods. // - SDValue getConstant(uint64_t Val, EVT VT, bool isTarget = false, + SDValue getConstant(uint64_t Val, SDLoc DL, EVT VT, bool isTarget = false, bool isOpaque = false); - SDValue getConstant(const APInt &Val, EVT VT, bool isTarget = false, + SDValue getConstant(const APInt &Val, SDLoc DL, EVT VT, bool isTarget = false, bool isOpaque = false); - SDValue getConstant(const ConstantInt &Val, EVT VT, bool isTarget = false, - bool isOpaque = false); - SDValue getIntPtrConstant(uint64_t Val, bool isTarget = false); - SDValue getTargetConstant(uint64_t Val, EVT VT, bool isOpaque = false) { - return getConstant(Val, VT, true, isOpaque); + SDValue getConstant(const ConstantInt &Val, SDLoc DL, EVT VT, + bool isTarget = false, bool isOpaque = false); + SDValue getIntPtrConstant(uint64_t Val, SDLoc DL, bool isTarget = false); + SDValue getTargetConstant(uint64_t Val, SDLoc DL, EVT VT, + bool isOpaque = false) { + return getConstant(Val, DL, VT, true, isOpaque); } - SDValue getTargetConstant(const APInt &Val, EVT VT, bool isOpaque = false) { - return getConstant(Val, VT, true, isOpaque); + SDValue getTargetConstant(const APInt &Val, SDLoc DL, EVT VT, + bool isOpaque = false) { + return getConstant(Val, DL, VT, true, isOpaque); } - SDValue getTargetConstant(const ConstantInt &Val, EVT VT, + SDValue getTargetConstant(const ConstantInt &Val, SDLoc DL, EVT VT, bool isOpaque = false) { - return getConstant(Val, VT, true, isOpaque); + return getConstant(Val, DL, VT, true, isOpaque); } // The forms below that take a double should only be used for simple // constants that can be exactly represented in VT. No checks are made. - SDValue getConstantFP(double Val, EVT VT, bool isTarget = false); - SDValue getConstantFP(const APFloat& Val, EVT VT, bool isTarget = false); - SDValue getConstantFP(const ConstantFP &CF, EVT VT, bool isTarget = false); - SDValue getTargetConstantFP(double Val, EVT VT) { - return getConstantFP(Val, VT, true); + SDValue getConstantFP(double Val, SDLoc DL, EVT VT, bool isTarget = false); + SDValue getConstantFP(const APFloat& Val, SDLoc DL, EVT VT, + bool isTarget = false); + SDValue getConstantFP(const ConstantFP &CF, SDLoc DL, EVT VT, + bool isTarget = false); + SDValue getTargetConstantFP(double Val, SDLoc DL, EVT VT) { + return getConstantFP(Val, DL, VT, true); } - SDValue getTargetConstantFP(const APFloat& Val, EVT VT) { - return getConstantFP(Val, VT, true); + SDValue getTargetConstantFP(const APFloat& Val, SDLoc DL, EVT VT) { + return getConstantFP(Val, DL, VT, true); } - SDValue getTargetConstantFP(const ConstantFP &Val, EVT VT) { - return getConstantFP(Val, VT, true); + SDValue getTargetConstantFP(const ConstantFP &Val, SDLoc DL, EVT VT) { + return getConstantFP(Val, DL, VT, true); } SDValue getGlobalAddress(const GlobalValue *GV, SDLoc DL, EVT VT, int64_t offset = 0, bool isTargetGA = false, @@ -487,6 +504,8 @@ class SelectionDAG { SDValue getExternalSymbol(const char *Sym, SDLoc dl, EVT VT); SDValue getTargetExternalSymbol(const char *Sym, EVT VT, unsigned char TargetFlags = 0); + SDValue getMCSymbol(MCSymbol *Sym, EVT VT); + SDValue getValueType(EVT); SDValue getRegister(unsigned Reg, EVT VT); SDValue getRegisterMask(const uint32_t *RegMask); @@ -648,35 +667,39 @@ class SelectionDAG { /// Gets or creates the specified node. /// + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, + ArrayRef Ops); + SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, + ArrayRef Ops); + SDValue getNode(unsigned Opcode, SDLoc DL, ArrayRef ResultTys, + ArrayRef Ops); + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, + ArrayRef Ops); + + // Specialize based on number of operands. SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT); SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N); SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, - bool nuw = false, bool nsw = false, bool exact = false); + const SDNodeFlags *Flags = nullptr); SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, SDValue N3); SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, SDValue N3, SDValue N4); SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N1, SDValue N2, SDValue N3, SDValue N4, SDValue N5); - SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, ArrayRef Ops); - SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, - ArrayRef Ops); - SDValue getNode(unsigned Opcode, SDLoc DL, - ArrayRef ResultTys, - ArrayRef Ops); - SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, - ArrayRef Ops); + + // Specialize again based on number of operands for nodes with a VTList + // rather than a single VT. SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs); SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N); - SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, - SDValue N1, SDValue N2); - SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, - SDValue N1, SDValue N2, SDValue N3); - SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, - SDValue N1, SDValue N2, SDValue N3, SDValue N4); - SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, - SDValue N1, SDValue N2, SDValue N3, SDValue N4, - SDValue N5); + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1, + SDValue N2); + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1, + SDValue N2, SDValue N3); + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1, + SDValue N2, SDValue N3, SDValue N4); + SDValue getNode(unsigned Opcode, SDLoc DL, SDVTList VTs, SDValue N1, + SDValue N2, SDValue N3, SDValue N4, SDValue N5); /// Compute a TokenFactor to force all the incoming stack arguments to be /// loaded from the stack. This is used in tail call lowering to protect @@ -856,12 +879,20 @@ class SelectionDAG { SDValue getMaskedStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, SDValue Mask, EVT MemVT, MachineMemOperand *MMO, bool IsTrunc); + SDValue getMaskedGather(SDVTList VTs, EVT VT, SDLoc dl, + ArrayRef Ops, MachineMemOperand *MMO); + SDValue getMaskedScatter(SDVTList VTs, EVT VT, SDLoc dl, + ArrayRef Ops, MachineMemOperand *MMO); /// Construct a node to track a Value* through the backend. SDValue getSrcValue(const Value *v); /// Return an MDNodeSDNode which holds an MDNode. SDValue getMDNode(const MDNode *MD); + /// Return a bitcast using the SDLoc of the value operand, and casting to the + /// provided type. Use getNode to set a custom SDLoc. + SDValue getBitcast(EVT VT, SDValue V); + /// Return an AddrSpaceCastSDNode. SDValue getAddrSpaceCast(SDLoc dl, EVT VT, SDValue Ptr, unsigned SrcAS, unsigned DestAS); @@ -970,8 +1001,7 @@ class SelectionDAG { /// Get the specified node if it's already available, or else return NULL. SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTs, ArrayRef Ops, - bool nuw = false, bool nsw = false, - bool exact = false); + const SDNodeFlags *Flags = nullptr); /// Creates a SDDbgValue node. SDDbgValue *getDbgValue(MDNode *Var, MDNode *Expr, SDNode *N, unsigned R, @@ -1113,9 +1143,13 @@ class SelectionDAG { /// either of the specified value types. SDValue CreateStackTemporary(EVT VT1, EVT VT2); - SDValue FoldConstantArithmetic(unsigned Opcode, EVT VT, + SDValue FoldConstantArithmetic(unsigned Opcode, SDLoc DL, EVT VT, SDNode *Cst1, SDNode *Cst2); + SDValue FoldConstantArithmetic(unsigned Opcode, SDLoc DL, EVT VT, + const ConstantSDNode *Cst1, + const ConstantSDNode *Cst2); + /// Constant fold a setcc to true or false. SDValue FoldSetCC(EVT VT, SDValue N1, SDValue N2, ISD::CondCode Cond, SDLoc dl); @@ -1229,8 +1263,20 @@ class SelectionDAG { void allnodes_clear(); BinarySDNode *GetBinarySDNode(unsigned Opcode, SDLoc DL, SDVTList VTs, - SDValue N1, SDValue N2, bool nuw, bool nsw, - bool exact); + SDValue N1, SDValue N2, + const SDNodeFlags *Flags = nullptr); + + /// Look up the node specified by ID in CSEMap. If it exists, return it. If + /// not, return the insertion token that will make insertion faster. This + /// overload is for nodes other than Constant or ConstantFP, use the other one + /// for those. + SDNode *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos); + + /// Look up the node specified by ID in CSEMap. If it exists, return it. If + /// not, return the insertion token that will make insertion faster. Performs + /// additional processing for constant nodes. + SDNode *FindNodeOrInsertPos(const FoldingSetNodeID &ID, DebugLoc DL, + void *&InsertPos); /// List of non-single value types. FoldingSet VTListMap; @@ -1243,6 +1289,7 @@ class SelectionDAG { StringMap ExternalSymbols; std::map,SDNode*> TargetExternalSymbols; + DenseMap MCSymbols; }; template <> struct GraphTraits : public GraphTraits { diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index a8743754f40..a011e4c338c 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -199,7 +199,7 @@ class SelectionDAGISel : public MachineFunctionPass { /// SelectInlineAsmMemoryOperands - Calls to this are automatically generated /// by tblgen. Others should not call it. - void SelectInlineAsmMemoryOperands(std::vector &Ops); + void SelectInlineAsmMemoryOperands(std::vector &Ops, SDLoc DL); public: @@ -260,7 +260,10 @@ class SelectionDAGISel : public MachineFunctionPass { SDNode *MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTs, ArrayRef Ops, unsigned EmitNodeInfo); - void PrepareEHLandingPad(); + /// Prepares the landing pad to take incoming values or do other EH + /// personality specific tasks. Returns true if the block should be + /// instruction selected, false if no code should be emitted for it. + bool PrepareEHLandingPad(); /// \brief Perform instruction selection on all basic blocks in the function. void SelectAllBasicBlocks(const Function &Fn); diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 66f060c6b5a..4821d1aae9e 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -140,7 +140,7 @@ class SDValue { } // Return true if this node is an operand of N. - bool isOperandOf(SDNode *N) const; + bool isOperandOf(const SDNode *N) const; /// Return the ValueType of the referenced return value. inline EVT getValueType() const; @@ -357,9 +357,6 @@ class SDNode : public FoldingSetNode, public ilist_node { /// The number of entries in the Operand/Value list. unsigned short NumOperands, NumValues; - /// Source line information. - DebugLoc debugLoc; - // The ordering of the SDNodes. It roughly corresponds to the ordering of the // original LLVM instructions. // This is used for turning off scheduling, because we'll forgo @@ -367,6 +364,9 @@ class SDNode : public FoldingSetNode, public ilist_node { // this ordering. unsigned IROrder; + /// Source line information. + DebugLoc debugLoc; + /// Return a pointer to the specified value type. static const EVT *getValueTypeList(EVT VT); @@ -532,10 +532,10 @@ class SDNode : public FoldingSetNode, public ilist_node { bool hasAnyUseOfValue(unsigned Value) const; /// Return true if this node is the only use of N. - bool isOnlyUserOf(SDNode *N) const; + bool isOnlyUserOf(const SDNode *N) const; /// Return true if this node is an operand of N. - bool isOperandOf(SDNode *N) const; + bool isOperandOf(const SDNode *N) const; /// Return true if this node is a predecessor of N. /// NOTE: Implemented on top of hasPredecessor and every bit as @@ -579,6 +579,23 @@ class SDNode : public FoldingSetNode, public ilist_node { op_iterator op_end() const { return OperandList+NumOperands; } ArrayRef ops() const { return makeArrayRef(op_begin(), op_end()); } + /// Iterator for directly iterating over the operand SDValue's. + struct value_op_iterator + : iterator_adaptor_base { + explicit value_op_iterator(SDUse *U = nullptr) + : iterator_adaptor_base(U) {} + + const SDValue &operator*() const { return I->get(); } + }; + + iterator_range op_values() const { + return iterator_range(value_op_iterator(op_begin()), + value_op_iterator(op_end())); + } + SDVTList getVTList() const { SDVTList X = { ValueList, NumValues }; return X; @@ -715,7 +732,7 @@ class SDNode : public FoldingSetNode, public ilist_node { SubclassData(0), NodeId(-1), OperandList(Ops.size() ? new SDUse[Ops.size()] : nullptr), ValueList(VTs.VTs), UseList(nullptr), NumOperands(Ops.size()), - NumValues(VTs.NumVTs), debugLoc(std::move(dl)), IROrder(Order) { + NumValues(VTs.NumVTs), IROrder(Order), debugLoc(std::move(dl)) { assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); assert(NumOperands == Ops.size() && "NumOperands wasn't wide enough for its operands!"); @@ -735,7 +752,7 @@ class SDNode : public FoldingSetNode, public ilist_node { : NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false), SubclassData(0), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs), UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), - debugLoc(std::move(dl)), IROrder(Order) { + IROrder(Order), debugLoc(std::move(dl)) { assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); assert(NumValues == VTs.NumVTs && "NumValues wasn't wide enough for its operands!"); @@ -926,6 +943,62 @@ inline void SDUse::setNode(SDNode *N) { if (N) N->addUse(*this); } +/// These are IR-level optimization flags that may be propagated to SDNodes. +/// TODO: This data structure should be shared by the IR optimizer and the +/// the backend. +struct SDNodeFlags { +private: + bool NoUnsignedWrap : 1; + bool NoSignedWrap : 1; + bool Exact : 1; + bool UnsafeAlgebra : 1; + bool NoNaNs : 1; + bool NoInfs : 1; + bool NoSignedZeros : 1; + bool AllowReciprocal : 1; + +public: + /// Default constructor turns off all optimization flags. + SDNodeFlags() { + NoUnsignedWrap = false; + NoSignedWrap = false; + Exact = false; + UnsafeAlgebra = false; + NoNaNs = false; + NoInfs = false; + NoSignedZeros = false; + AllowReciprocal = false; + } + + // These are mutators for each flag. + void setNoUnsignedWrap(bool b) { NoUnsignedWrap = b; } + void setNoSignedWrap(bool b) { NoSignedWrap = b; } + void setExact(bool b) { Exact = b; } + void setUnsafeAlgebra(bool b) { UnsafeAlgebra = b; } + void setNoNaNs(bool b) { NoNaNs = b; } + void setNoInfs(bool b) { NoInfs = b; } + void setNoSignedZeros(bool b) { NoSignedZeros = b; } + void setAllowReciprocal(bool b) { AllowReciprocal = b; } + + // These are accessors for each flag. + bool hasNoUnsignedWrap() const { return NoUnsignedWrap; } + bool hasNoSignedWrap() const { return NoSignedWrap; } + bool hasExact() const { return Exact; } + bool hasUnsafeAlgebra() const { return UnsafeAlgebra; } + bool hasNoNaNs() const { return NoNaNs; } + bool hasNoInfs() const { return NoInfs; } + bool hasNoSignedZeros() const { return NoSignedZeros; } + bool hasAllowReciprocal() const { return AllowReciprocal; } + + /// Return a raw encoding of the flags. + /// This function should only be used to add data to the NodeID value. + unsigned getRawFlags() const { + return (NoUnsignedWrap << 0) | (NoSignedWrap << 1) | (Exact << 2) | + (UnsafeAlgebra << 3) | (NoNaNs << 4) | (NoInfs << 5) | + (NoSignedZeros << 6) | (AllowReciprocal << 7); + } +}; + /// This class is used for single-operand SDNodes. This is solely /// to allow co-allocation of node operands with the node itself. class UnarySDNode : public SDNode { @@ -961,6 +1034,11 @@ static bool isBinOpWithFlags(unsigned Opcode) { case ISD::ADD: case ISD::SUB: case ISD::SHL: + case ISD::FADD: + case ISD::FDIV: + case ISD::FMUL: + case ISD::FREM: + case ISD::FSUB: return true; default: return false; @@ -970,27 +1048,11 @@ static bool isBinOpWithFlags(unsigned Opcode) { /// This class is an extension of BinarySDNode /// used from those opcodes that have associated extra flags. class BinaryWithFlagsSDNode : public BinarySDNode { - enum { NUW = (1 << 0), NSW = (1 << 1), EXACT = (1 << 2) }; - public: + SDNodeFlags Flags; BinaryWithFlagsSDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs, - SDValue X, SDValue Y) - : BinarySDNode(Opc, Order, dl, VTs, X, Y) {} - /// Return the SubclassData value, which contains an encoding of the flags. - /// This function should be used to add subclass data to the NodeID value. - unsigned getRawSubclassData() const { return SubclassData; } - void setHasNoUnsignedWrap(bool b) { - SubclassData = (SubclassData & ~NUW) | (b ? NUW : 0); - } - void setHasNoSignedWrap(bool b) { - SubclassData = (SubclassData & ~NSW) | (b ? NSW : 0); - } - void setIsExact(bool b) { - SubclassData = (SubclassData & ~EXACT) | (b ? EXACT : 0); - } - bool hasNoUnsignedWrap() const { return SubclassData & NUW; } - bool hasNoSignedWrap() const { return SubclassData & NSW; } - bool isExact() const { return SubclassData & EXACT; } + SDValue X, SDValue Y, const SDNodeFlags &NodeFlags) + : BinarySDNode(Opc, Order, dl, VTs, X, Y), Flags(NodeFlags) {} static bool classof(const SDNode *N) { return isBinOpWithFlags(N->getOpcode()); } @@ -1041,7 +1103,7 @@ class AddrSpaceCastSDNode : public UnarySDNode { } }; -/// Abstact virtual class for operations for memory operations +/// This is an abstract virtual class for memory operations. class MemSDNode : public SDNode { private: // VT of in-memory value. @@ -1151,12 +1213,14 @@ class MemSDNode : public SDNode { N->getOpcode() == ISD::ATOMIC_STORE || N->getOpcode() == ISD::MLOAD || N->getOpcode() == ISD::MSTORE || + N->getOpcode() == ISD::MGATHER || + N->getOpcode() == ISD::MSCATTER || N->isMemIntrinsic() || N->isTargetMemoryOpcode(); } }; -/// A SDNode reprenting atomic operations. +/// This is an SDNode representing atomic operations. class AtomicSDNode : public MemSDNode { SDUse Ops[4]; @@ -1359,9 +1423,10 @@ class ShuffleVectorSDNode : public SDNode { class ConstantSDNode : public SDNode { const ConstantInt *Value; friend class SelectionDAG; - ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val, EVT VT) + ConstantSDNode(bool isTarget, bool isOpaque, const ConstantInt *val, + DebugLoc DL, EVT VT) : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, - 0, DebugLoc(), getSDVTList(VT)), Value(val) { + 0, DL, getSDVTList(VT)), Value(val) { SubclassData |= (uint16_t)isOpaque; } public: @@ -1386,9 +1451,9 @@ class ConstantSDNode : public SDNode { class ConstantFPSDNode : public SDNode { const ConstantFP *Value; friend class SelectionDAG; - ConstantFPSDNode(bool isTarget, const ConstantFP *val, EVT VT) + ConstantFPSDNode(bool isTarget, const ConstantFP *val, DebugLoc DL, EVT VT) : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, - 0, DebugLoc(), getSDVTList(VT)), Value(val) { + 0, DL, getSDVTList(VT)), Value(val) { } public: @@ -1762,6 +1827,21 @@ class ExternalSymbolSDNode : public SDNode { } }; +class MCSymbolSDNode : public SDNode { + MCSymbol *Symbol; + + friend class SelectionDAG; + MCSymbolSDNode(MCSymbol *Symbol, EVT VT) + : SDNode(ISD::MCSymbol, 0, DebugLoc(), getSDVTList(VT)), Symbol(Symbol) {} + +public: + MCSymbol *getMCSymbol() const { return Symbol; } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MCSymbol; + } +}; + class CondCodeSDNode : public SDNode { ISD::CondCode Condition; friend class SelectionDAG; @@ -1987,6 +2067,82 @@ class MaskedStoreSDNode : public MaskedLoadStoreSDNode { } }; +/// This is a base class used to represent +/// MGATHER and MSCATTER nodes +/// +class MaskedGatherScatterSDNode : public MemSDNode { + // Operands + SDUse Ops[5]; +public: + friend class SelectionDAG; + MaskedGatherScatterSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl, + ArrayRef Operands, SDVTList VTs, EVT MemVT, + MachineMemOperand *MMO) + : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { + assert(Operands.size() == 5 && "Incompatible number of operands"); + InitOperands(Ops, Operands.data(), Operands.size()); + } + + // In the both nodes address is Op1, mask is Op2: + // MaskedGatherSDNode (Chain, src0, mask, base, index), src0 is a passthru value + // MaskedScatterSDNode (Chain, value, mask, base, index) + // Mask is a vector of i1 elements + const SDValue &getBasePtr() const { return getOperand(3); } + const SDValue &getIndex() const { return getOperand(4); } + const SDValue &getMask() const { return getOperand(2); } + const SDValue &getValue() const { return getOperand(1); } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MGATHER || + N->getOpcode() == ISD::MSCATTER; + } +}; + +/// This class is used to represent an MGATHER node +/// +class MaskedGatherSDNode : public MaskedGatherScatterSDNode { +public: + friend class SelectionDAG; + MaskedGatherSDNode(unsigned Order, DebugLoc dl, ArrayRef Operands, + SDVTList VTs, EVT MemVT, MachineMemOperand *MMO) + : MaskedGatherScatterSDNode(ISD::MGATHER, Order, dl, Operands, VTs, MemVT, + MMO) { + assert(getValue().getValueType() == getValueType(0) && + "Incompatible type of the PathThru value in MaskedGatherSDNode"); + assert(getMask().getValueType().getVectorNumElements() == + getValueType(0).getVectorNumElements() && + "Vector width mismatch between mask and data"); + assert(getMask().getValueType().getScalarType() == MVT::i1 && + "Vector width mismatch between mask and data"); + } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MGATHER; + } +}; + +/// This class is used to represent an MSCATTER node +/// +class MaskedScatterSDNode : public MaskedGatherScatterSDNode { + +public: + friend class SelectionDAG; + MaskedScatterSDNode(unsigned Order, DebugLoc dl,ArrayRef Operands, + SDVTList VTs, EVT MemVT, MachineMemOperand *MMO) + : MaskedGatherScatterSDNode(ISD::MSCATTER, Order, dl, Operands, VTs, MemVT, + MMO) { + assert(getMask().getValueType().getVectorNumElements() == + getValue().getValueType().getVectorNumElements() && + "Vector width mismatch between mask and data"); + assert(getMask().getValueType().getScalarType() == MVT::i1 && + "Vector width mismatch between mask and data"); + } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MSCATTER; + } +}; + /// An SDNode that represents everything that will be needed /// to construct a MachineInstr. These nodes are created during the /// instruction selection proper phase. @@ -2078,7 +2234,7 @@ template <> struct GraphTraits { }; /// The largest SDNode class. -typedef AtomicSDNode LargestSDNode; +typedef MaskedGatherScatterSDNode LargestSDNode; /// The SDNode class with the greatest alignment requirement. typedef GlobalAddressSDNode MostAlignedSDNode; diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h index caec994bc37..fdc1a9143ed 100644 --- a/include/llvm/CodeGen/StackMaps.h +++ b/include/llvm/CodeGen/StackMaps.h @@ -1,5 +1,4 @@ //===------------------- StackMaps.h - StackMaps ----------------*- C++ -*-===// - // // The LLVM Compiler Infrastructure // @@ -42,10 +41,12 @@ class PatchPointOpers { public: /// Enumerate the meta operands. enum { IDPos, NBytesPos, TargetPos, NArgPos, CCPos, MetaEnd }; + private: const MachineInstr *MI; bool HasDef; bool IsAnyReg; + public: explicit PatchPointOpers(const MachineInstr *MI); @@ -66,8 +67,8 @@ class PatchPointOpers { /// Get the operand index of the variable list of non-argument operands. /// These hold the "live state". unsigned getVarIdx() const { - return getMetaIdx() + MetaEnd - + MI->getOperand(getMetaIdx(NArgPos)).getImm(); + return getMetaIdx() + MetaEnd + + MI->getOperand(getMetaIdx(NArgPos)).getImm(); } /// Get the index at which stack map locations will be recorded. @@ -85,38 +86,36 @@ class PatchPointOpers { /// MI-level Statepoint operands /// /// Statepoint operands take the form: -/// , , [call arguments], -/// , , +/// , , , , +/// [call arguments], , , +/// , , /// , , [other args], /// [gc values] class StatepointOpers { private: - enum { - NCallArgsPos = 0, - CallTargetPos = 1 - }; + // These values are aboolute offsets into the operands of the statepoint + // instruction. + enum { IDPos, NBytesPos, NCallArgsPos, CallTargetPos, MetaEnd }; + + // These values are relative offests from the start of the statepoint meta + // arguments (i.e. the end of the call arguments). + enum { CCOffset = 1, FlagsOffset = 3, NumVMSArgsOffset = 5 }; public: - explicit StatepointOpers(const MachineInstr *MI): - MI(MI) { } + explicit StatepointOpers(const MachineInstr *MI) : MI(MI) {} /// Get starting index of non call related arguments - /// (statepoint flags, vm state and gc state). + /// (calling convention, statepoint flags, vm state and gc state). unsigned getVarIdx() const { - return MI->getOperand(NCallArgsPos).getImm() + 2; + return MI->getOperand(NCallArgsPos).getImm() + MetaEnd; } - /// Returns the index of the operand containing the number of non-gc non-call - /// arguments. - unsigned getNumVMSArgsIdx() const { - return getVarIdx() + 3; - } + /// Return the ID for the given statepoint. + uint64_t getID() const { return MI->getOperand(IDPos).getImm(); } - /// Returns the number of non-gc non-call arguments attached to the - /// statepoint. Note that this is the number of arguments, not the number of - /// operands required to represent those arguments. - unsigned getNumVMSArgs() const { - return MI->getOperand(getNumVMSArgsIdx()).getImm(); + /// Return the number of patchable bytes the given statepoint should emit. + uint32_t getNumPatchBytes() const { + return MI->getOperand(NBytesPos).getImm(); } /// Returns the target of the underlying call. @@ -131,31 +130,32 @@ class StatepointOpers { class StackMaps { public: struct Location { - enum LocationType { Unprocessed, Register, Direct, Indirect, Constant, - ConstantIndex }; - LocationType LocType; + enum LocationType { + Unprocessed, + Register, + Direct, + Indirect, + Constant, + ConstantIndex + }; + LocationType Type; unsigned Size; unsigned Reg; int64_t Offset; - Location() : LocType(Unprocessed), Size(0), Reg(0), Offset(0) {} - Location(LocationType LocType, unsigned Size, unsigned Reg, int64_t Offset) - : LocType(LocType), Size(Size), Reg(Reg), Offset(Offset) {} + Location() : Type(Unprocessed), Size(0), Reg(0), Offset(0) {} + Location(LocationType Type, unsigned Size, unsigned Reg, int64_t Offset) + : Type(Type), Size(Size), Reg(Reg), Offset(Offset) {} }; struct LiveOutReg { unsigned short Reg; - unsigned short RegNo; + unsigned short DwarfRegNum; unsigned short Size; - LiveOutReg() : Reg(0), RegNo(0), Size(0) {} - LiveOutReg(unsigned short Reg, unsigned short RegNo, unsigned short Size) - : Reg(Reg), RegNo(RegNo), Size(Size) {} - - void MarkInvalid() { Reg = 0; } - - // Only sort by the dwarf register number. - bool operator< (const LiveOutReg &LO) const { return RegNo < LO.RegNo; } - static bool IsInvalid(const LiveOutReg &LO) { return LO.Reg == 0; } + LiveOutReg() : Reg(0), DwarfRegNum(0), Size(0) {} + LiveOutReg(unsigned short Reg, unsigned short DwarfRegNum, + unsigned short Size) + : Reg(Reg), DwarfRegNum(DwarfRegNum), Size(Size) {} }; // OpTypes are used to encode information about the following logical @@ -202,8 +202,8 @@ class StackMaps { CallsiteInfo() : CSOffsetExpr(nullptr), ID(0) {} CallsiteInfo(const MCExpr *CSOffsetExpr, uint64_t ID, LocationVec &&Locations, LiveOutVec &&LiveOuts) - : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(std::move(Locations)), - LiveOuts(std::move(LiveOuts)) {} + : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(std::move(Locations)), + LiveOuts(std::move(LiveOuts)) {} }; typedef std::vector CallsiteInfoList; @@ -215,8 +215,8 @@ class StackMaps { MachineInstr::const_mop_iterator parseOperand(MachineInstr::const_mop_iterator MOI, - MachineInstr::const_mop_iterator MOE, - LocationVec &Locs, LiveOutVec &LiveOuts) const; + MachineInstr::const_mop_iterator MOE, LocationVec &Locs, + LiveOutVec &LiveOuts) const; /// \brief Create a live-out register record for the given register @p Reg. LiveOutReg createLiveOutReg(unsigned Reg, @@ -251,7 +251,6 @@ class StackMaps { void print(raw_ostream &OS); void debug() { print(dbgs()); } }; - } #endif diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index a868cbd020f..9a3abc4dc1f 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -41,25 +41,24 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile { ~TargetLoweringObjectFileELF() override {} - void emitPersonalityValue(MCStreamer &Streamer, const TargetMachine &TM, + void emitPersonalityValue(MCStreamer &Streamer, const DataLayout &TM, const MCSymbol *Sym) const override; /// Given a constant with the SectionKind, return a section that it should be /// placed in. - const MCSection *getSectionForConstant(SectionKind Kind, - const Constant *C) const override; + MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind, + const Constant *C) const override; - const MCSection *getExplicitSectionGlobal(const GlobalValue *GV, - SectionKind Kind, Mangler &Mang, - const TargetMachine &TM) const override; + MCSection *getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler &Mang, + const TargetMachine &TM) const override; - const MCSection *SelectSectionForGlobal(const GlobalValue *GV, - SectionKind Kind, Mangler &Mang, - const TargetMachine &TM) const override; + MCSection *SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler &Mang, + const TargetMachine &TM) const override; - const MCSection * - getSectionForJumpTable(const Function &F, Mangler &Mang, - const TargetMachine &TM) const override; + MCSection *getSectionForJumpTable(const Function &F, Mangler &Mang, + const TargetMachine &TM) const override; bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference, const Function &F) const override; @@ -78,10 +77,10 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile { MachineModuleInfo *MMI) const override; void InitializeELF(bool UseInitArray_); - const MCSection *getStaticCtorSection(unsigned Priority, - const MCSymbol *KeySym) const override; - const MCSection *getStaticDtorSection(unsigned Priority, - const MCSymbol *KeySym) const override; + MCSection *getStaticCtorSection(unsigned Priority, + const MCSymbol *KeySym) const override; + MCSection *getStaticDtorSection(unsigned Priority, + const MCSymbol *KeySym) const override; }; @@ -91,27 +90,21 @@ class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile { ~TargetLoweringObjectFileMachO() override {} TargetLoweringObjectFileMachO(); - /// Extract the dependent library name from a linker option string. Returns - /// StringRef() if the option does not specify a library. - StringRef getDepLibFromLinkerOpt(StringRef LinkerOption) const override; - /// Emit the module flags that specify the garbage collection information. void emitModuleFlags(MCStreamer &Streamer, ArrayRef ModuleFlags, Mangler &Mang, const TargetMachine &TM) const override; - const MCSection * - SelectSectionForGlobal(const GlobalValue *GV, - SectionKind Kind, Mangler &Mang, - const TargetMachine &TM) const override; + MCSection *SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler &Mang, + const TargetMachine &TM) const override; - const MCSection * - getExplicitSectionGlobal(const GlobalValue *GV, - SectionKind Kind, Mangler &Mang, - const TargetMachine &TM) const override; + MCSection *getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler &Mang, + const TargetMachine &TM) const override; - const MCSection *getSectionForConstant(SectionKind Kind, - const Constant *C) const override; + MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind, + const Constant *C) const override; /// The mach-o version of this method defaults to returning a stub reference. const MCExpr * @@ -138,27 +131,20 @@ class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile { public: ~TargetLoweringObjectFileCOFF() override {} - const MCSection * - getExplicitSectionGlobal(const GlobalValue *GV, - SectionKind Kind, Mangler &Mang, - const TargetMachine &TM) const override; + MCSection *getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler &Mang, + const TargetMachine &TM) const override; - const MCSection * - SelectSectionForGlobal(const GlobalValue *GV, - SectionKind Kind, Mangler &Mang, - const TargetMachine &TM) const override; + MCSection *SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler &Mang, + const TargetMachine &TM) const override; void getNameWithPrefix(SmallVectorImpl &OutName, const GlobalValue *GV, bool CannotUsePrivateLabel, Mangler &Mang, const TargetMachine &TM) const override; - const MCSection * - getSectionForJumpTable(const Function &F, Mangler &Mang, - const TargetMachine &TM) const override; - - /// Extract the dependent library name from a linker option string. Returns - /// StringRef() if the option does not specify a library. - StringRef getDepLibFromLinkerOpt(StringRef LinkerOption) const override; + MCSection *getSectionForJumpTable(const Function &F, Mangler &Mang, + const TargetMachine &TM) const override; /// Emit Obj-C garbage collection and linker options. Only linker option /// emission is implemented for COFF. @@ -166,10 +152,13 @@ class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile { ArrayRef ModuleFlags, Mangler &Mang, const TargetMachine &TM) const override; - const MCSection *getStaticCtorSection(unsigned Priority, - const MCSymbol *KeySym) const override; - const MCSection *getStaticDtorSection(unsigned Priority, - const MCSymbol *KeySym) const override; + MCSection *getStaticCtorSection(unsigned Priority, + const MCSymbol *KeySym) const override; + MCSection *getStaticDtorSection(unsigned Priority, + const MCSymbol *KeySym) const override; + + void emitLinkerFlagsForGlobal(raw_ostream &OS, const GlobalValue *GV, + const Mangler &Mang) const override; }; } // end namespace llvm diff --git a/include/llvm/CodeGen/TargetSchedule.h b/include/llvm/CodeGen/TargetSchedule.h index b6136665b96..81054aba066 100644 --- a/include/llvm/CodeGen/TargetSchedule.h +++ b/include/llvm/CodeGen/TargetSchedule.h @@ -40,6 +40,9 @@ class TargetSchedModel { SmallVector ResourceFactors; unsigned MicroOpFactor; // Multiply to normalize microops to resource units. unsigned ResourceLCM; // Resource units per cycle. Latency normalization factor. + + unsigned computeInstrLatency(const MCSchedClassDesc &SCDesc) const; + public: TargetSchedModel(): SchedModel(MCSchedModel::GetDefaultSchedModel()), STI(nullptr), TII(nullptr) {} @@ -78,6 +81,12 @@ class TargetSchedModel { return nullptr; } + /// \brief Return true if this machine model includes an instruction-level + /// scheduling model or cycle-to-cycle itinerary data. + bool hasInstrSchedModelOrItineraries() const { + return hasInstrSchedModel() || hasInstrItineraries(); + } + /// \brief Identify the processor corresponding to the current subtarget. unsigned getProcessorID() const { return SchedModel.getProcessorID(); } diff --git a/include/llvm/CodeGen/ValueTypes.td b/include/llvm/CodeGen/ValueTypes.td index 756262f6dad..2b30f14f902 100644 --- a/include/llvm/CodeGen/ValueTypes.td +++ b/include/llvm/CodeGen/ValueTypes.td @@ -62,25 +62,26 @@ def v2i64 : ValueType<128, 38>; // 2 x i64 vector value def v4i64 : ValueType<256, 39>; // 4 x i64 vector value def v8i64 : ValueType<512, 40>; // 8 x i64 vector value def v16i64 : ValueType<1024,41>; // 16 x i64 vector value +def v1i128 : ValueType<128, 42>; // 1 x i128 vector value -def v2f16 : ValueType<32 , 42>; // 2 x f16 vector value -def v4f16 : ValueType<64 , 43>; // 4 x f16 vector value -def v8f16 : ValueType<128, 44>; // 8 x f16 vector value -def v1f32 : ValueType<32 , 45>; // 1 x f32 vector value -def v2f32 : ValueType<64 , 46>; // 2 x f32 vector value -def v4f32 : ValueType<128, 47>; // 4 x f32 vector value -def v8f32 : ValueType<256, 48>; // 8 x f32 vector value -def v16f32 : ValueType<512, 49>; // 16 x f32 vector value -def v1f64 : ValueType<64, 50>; // 1 x f64 vector value -def v2f64 : ValueType<128, 51>; // 2 x f64 vector value -def v4f64 : ValueType<256, 52>; // 4 x f64 vector value -def v8f64 : ValueType<512, 53>; // 8 x f64 vector value +def v2f16 : ValueType<32 , 43>; // 2 x f16 vector value +def v4f16 : ValueType<64 , 44>; // 4 x f16 vector value +def v8f16 : ValueType<128, 45>; // 8 x f16 vector value +def v1f32 : ValueType<32 , 46>; // 1 x f32 vector value +def v2f32 : ValueType<64 , 47>; // 2 x f32 vector value +def v4f32 : ValueType<128, 48>; // 4 x f32 vector value +def v8f32 : ValueType<256, 49>; // 8 x f32 vector value +def v16f32 : ValueType<512, 50>; // 16 x f32 vector value +def v1f64 : ValueType<64, 51>; // 1 x f64 vector value +def v2f64 : ValueType<128, 52>; // 2 x f64 vector value +def v4f64 : ValueType<256, 53>; // 4 x f64 vector value +def v8f64 : ValueType<512, 54>; // 8 x f64 vector value -def x86mmx : ValueType<64 , 54>; // X86 MMX value -def FlagVT : ValueType<0 , 55>; // Pre-RA sched glue -def isVoid : ValueType<0 , 56>; // Produces no value -def untyped: ValueType<8 , 57>; // Produces an untyped value +def x86mmx : ValueType<64 , 55>; // X86 MMX value +def FlagVT : ValueType<0 , 56>; // Pre-RA sched glue +def isVoid : ValueType<0 , 57>; // Produces no value +def untyped: ValueType<8 , 58>; // Produces an untyped value def MetadataVT: ValueType<0, 250>; // Metadata // Pseudo valuetype mapped to the current pointer size to any address space. diff --git a/include/llvm/CodeGen/WinEHFuncInfo.h b/include/llvm/CodeGen/WinEHFuncInfo.h index 5fc2b126db8..75638a058a3 100644 --- a/include/llvm/CodeGen/WinEHFuncInfo.h +++ b/include/llvm/CodeGen/WinEHFuncInfo.h @@ -22,7 +22,8 @@ namespace llvm { class BasicBlock; class Constant; class Function; -class GlobalValue; +class GlobalVariable; +class InvokeInst; class IntrinsicInst; class LandingPadInst; class MCSymbol; @@ -90,7 +91,7 @@ class CatchHandler : public ActionHandler { // When the parseEHActions function is called to populate a vector of // instances of this class, the ExceptionObjectVar field will be nullptr // and the ExceptionObjectIndex will be the index of the exception object in - // the parent function's frameescape block. + // the parent function's localescape block. const Value *ExceptionObjectVar; int ExceptionObjectIndex; TinyPtrVector ReturnTargets; @@ -107,8 +108,7 @@ class CleanupHandler : public ActionHandler { }; void parseEHActions(const IntrinsicInst *II, - SmallVectorImpl &Actions); - + SmallVectorImpl> &Actions); // The following structs respresent the .xdata for functions using C++ // exceptions on Windows. @@ -132,22 +132,34 @@ struct WinEHTryBlockMapEntry { }; struct WinEHFuncInfo { + DenseMap RootLPad; + DenseMap LastInvoke; + DenseMap HandlerEnclosedState; + DenseMap LastInvokeVisited; DenseMap LandingPadStateMap; DenseMap CatchHandlerParentFrameObjIdx; DenseMap CatchHandlerParentFrameObjOffset; DenseMap CatchHandlerMaxState; + DenseMap HandlerBaseState; SmallVector UnwindMap; SmallVector TryBlockMap; SmallVector, 4> IPToStateList; - int UnwindHelpFrameIdx; - int UnwindHelpFrameOffset; + int UnwindHelpFrameIdx = INT_MAX; + int UnwindHelpFrameOffset = -1; + unsigned NumIPToStateFuncsVisited = 0; - unsigned NumIPToStateFuncsVisited; + /// localescape 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 +/// describes the state numbers and tables used by __CxxFrameHandler3. This +/// analysis assumes that WinEHPrepare has already been run. +void calculateWinCXXEHStateNumbers(const Function *ParentFn, + WinEHFuncInfo &FuncInfo); + } #endif // LLVM_CODEGEN_WINEHFUNCINFO_H diff --git a/include/llvm/Config/SZTargets.def.in b/include/llvm/Config/SZTargets.def.in deleted file mode 100644 index 72d7d4532f3..00000000000 --- a/include/llvm/Config/SZTargets.def.in +++ /dev/null @@ -1,28 +0,0 @@ -/*===- llvm/Config/SZTargets.def - Subzero Target Architectures -*- C++ -*-===*\ -|* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| -|* *| -|*===----------------------------------------------------------------------===*| -|* *| -|* This file enumerates all of the target architectures supported by *| -|* this build of Subzero. Clients of this file should define the *| -|* SUBZERO_TARGET macro to be a function-like macro with a single *| -|* parameter (the name of the target); including this file will then *| -|* enumerate all of the targets. *| -|* *| -|* The set of targets supported by LLVM is generated at configuration *| -|* time, at which point this header is generated. Do not modify this *| -|* header directly. *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifndef SUBZERO_TARGET -# error Please define the macro SUBZERO_TARGET(TargetName) -#endif - -@SUBZERO_ENUM_TARGETS@ - -#undef SUBZERO_TARGET diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index bd50d6ee1d6..b9fd4504ad7 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -125,12 +125,12 @@ /* Define if you have the libdl library or equivalent. */ #cmakedefine HAVE_LIBDL ${HAVE_LIBDL} -/* Define to 1 if you have the `imagehlp' library (-limagehlp). */ -#cmakedefine HAVE_LIBIMAGEHLP ${HAVE_LIBIMAGEHLP} - /* Define to 1 if you have the `m' library (-lm). */ #undef HAVE_LIBM +/* Define to 1 if you have the `ole32' library (-lole32). */ +#undef HAVE_LIBOLE32 + /* Define to 1 if you have the `psapi' library (-lpsapi). */ #cmakedefine HAVE_LIBPSAPI ${HAVE_LIBPSAPI} @@ -411,12 +411,103 @@ /* Have host's ___chkstk_ms */ #cmakedefine HAVE____CHKSTK_MS ${HAVE____CHKSTK_MS} -/* Define if we link Polly to the tools */ -#cmakedefine LINK_POLLY_INTO_TOOLS +/* Linker version detected at compile time. */ +#undef HOST_LINK_VERSION + +/* Installation directory for binary executables */ +#cmakedefine LLVM_BINDIR "${LLVM_BINDIR}" + +/* Time at which LLVM was configured */ +#cmakedefine LLVM_CONFIGTIME "${LLVM_CONFIGTIME}" + +/* Installation directory for data files */ +#cmakedefine LLVM_DATADIR "${LLVM_DATADIR}" + +/* Target triple LLVM will generate code for by default */ +#cmakedefine LLVM_DEFAULT_TARGET_TRIPLE "${LLVM_DEFAULT_TARGET_TRIPLE}" + +/* Installation directory for documentation */ +#cmakedefine LLVM_DOCSDIR "${LLVM_DOCSDIR}" + +/* Define if LLVM is built with asserts and checks that change the layout of + client-visible data structures. */ +#cmakedefine LLVM_ENABLE_ABI_BREAKING_CHECKS + +/* Define if threads enabled */ +#cmakedefine01 LLVM_ENABLE_THREADS /* Define if zlib compression is available */ #cmakedefine01 LLVM_ENABLE_ZLIB +/* Installation directory for config files */ +#cmakedefine LLVM_ETCDIR "${LLVM_ETCDIR}" + +/* Has gcc/MSVC atomic intrinsics */ +#cmakedefine01 LLVM_HAS_ATOMICS + +/* Host triple LLVM will be executed on */ +#cmakedefine LLVM_HOST_TRIPLE "${LLVM_HOST_TRIPLE}" + +/* Installation directory for include files */ +#cmakedefine LLVM_INCLUDEDIR "${LLVM_INCLUDEDIR}" + +/* Installation directory for .info files */ +#cmakedefine LLVM_INFODIR "${LLVM_INFODIR}" + +/* Installation directory for man pages */ +#cmakedefine LLVM_MANDIR "${LLVM_MANDIR}" + +/* LLVM architecture name for the native architecture, if available */ +#cmakedefine LLVM_NATIVE_ARCH ${LLVM_NATIVE_ARCH} + +/* LLVM name for the native AsmParser init function, if available */ +#cmakedefine LLVM_NATIVE_ASMPARSER LLVMInitialize${LLVM_NATIVE_ARCH}AsmParser + +/* LLVM name for the native AsmPrinter init function, if available */ +#cmakedefine LLVM_NATIVE_ASMPRINTER LLVMInitialize${LLVM_NATIVE_ARCH}AsmPrinter + +/* LLVM name for the native Disassembler init function, if available */ +#cmakedefine LLVM_NATIVE_DISASSEMBLER LLVMInitialize${LLVM_NATIVE_ARCH}Disassembler + +/* LLVM name for the native Target init function, if available */ +#cmakedefine LLVM_NATIVE_TARGET LLVMInitialize${LLVM_NATIVE_ARCH}Target + +/* LLVM name for the native TargetInfo init function, if available */ +#cmakedefine LLVM_NATIVE_TARGETINFO LLVMInitialize${LLVM_NATIVE_ARCH}TargetInfo + +/* LLVM name for the native target MC init function, if available */ +#cmakedefine LLVM_NATIVE_TARGETMC LLVMInitialize${LLVM_NATIVE_ARCH}TargetMC + +/* Define if this is Unixish platform */ +#cmakedefine LLVM_ON_UNIX ${LLVM_ON_UNIX} + +/* Define if this is Win32ish platform */ +#cmakedefine LLVM_ON_WIN32 ${LLVM_ON_WIN32} + +/* Installation prefix directory */ +#cmakedefine LLVM_PREFIX "${LLVM_PREFIX}" + +/* Define if we have the Intel JIT API runtime support library */ +#cmakedefine LLVM_USE_INTEL_JITEVENTS 1 + +/* Define if we have the oprofile JIT-support library */ +#cmakedefine LLVM_USE_OPROFILE 1 + +/* Major version of the LLVM API */ +#define LLVM_VERSION_MAJOR ${LLVM_VERSION_MAJOR} + +/* Minor version of the LLVM API */ +#define LLVM_VERSION_MINOR ${LLVM_VERSION_MINOR} + +/* Patch version of the LLVM API */ +#define LLVM_VERSION_PATCH ${LLVM_VERSION_PATCH} + +/* LLVM version string */ +#define LLVM_VERSION_STRING "${PACKAGE_VERSION}" + +/* Define if we link Polly to the tools */ +#cmakedefine LINK_POLLY_INTO_TOOLS + /* Define if the OS needs help to load dependent libraries for dlopen(). */ #cmakedefine LTDL_DLOPEN_DEPLIBS ${LTDL_DLOPEN_DEPLIBS} diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index 67d7c8485a4..09706499ea3 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -3,9 +3,15 @@ #ifndef CONFIG_H #define CONFIG_H +/* Exported configuration */ +#include "llvm/Config/llvm-config.h" + /* Bug report URL. */ #undef BUG_REPORT_URL +/* Default OpenMP runtime used by -fopenmp. */ +#undef CLANG_DEFAULT_OPENMP_RUNTIME + /* Define if we have libxml2 */ #undef CLANG_HAVE_LIBXML @@ -131,12 +137,12 @@ /* Define if libedit is available on this platform. */ #undef HAVE_LIBEDIT -/* Define to 1 if you have the `imagehlp' library (-limagehlp). */ -#undef HAVE_LIBIMAGEHLP - /* Define to 1 if you have the `m' library (-lm). */ #undef HAVE_LIBM +/* Define to 1 if you have the `ole32' library (-lole32). */ +#undef HAVE_LIBOLE32 + /* Define to 1 if you have the `psapi' library (-lpsapi). */ #undef HAVE_LIBPSAPI diff --git a/include/llvm/Config/llvm-config.h.cmake b/include/llvm/Config/llvm-config.h.cmake index bb7dc067ea0..e0f30678c0a 100644 --- a/include/llvm/Config/llvm-config.h.cmake +++ b/include/llvm/Config/llvm-config.h.cmake @@ -29,6 +29,10 @@ /* Installation directory for documentation */ #cmakedefine LLVM_DOCSDIR "${LLVM_DOCSDIR}" +/* Define if LLVM is built with asserts and checks that change the layout of + client-visible data structures. */ +#cmakedefine LLVM_ENABLE_ABI_BREAKING_CHECKS + /* Define if threads enabled */ #cmakedefine01 LLVM_ENABLE_THREADS @@ -101,8 +105,4 @@ /* Define if we link Polly to the tools */ #cmakedefine LINK_POLLY_INTO_TOOLS -/* Define if LLVM is built with asserts and checks that change the layout of - client-visible data structures. */ -#cmakedefine LLVM_ENABLE_ABI_BREAKING_CHECKS - #endif diff --git a/include/llvm/Config/llvm-config.h.in b/include/llvm/Config/llvm-config.h.in index 03e482ac175..2dd5d0af7b5 100644 --- a/include/llvm/Config/llvm-config.h.in +++ b/include/llvm/Config/llvm-config.h.in @@ -29,6 +29,9 @@ /* Installation directory for documentation */ #undef LLVM_DOCSDIR +/* Define to enable checks that alter the LLVM C++ ABI */ +#undef LLVM_ENABLE_ABI_BREAKING_CHECKS + /* Define if threads enabled */ #undef LLVM_ENABLE_THREADS @@ -98,7 +101,4 @@ /* LLVM version string */ #undef LLVM_VERSION_STRING -/* Define to enable checks that alter the LLVM C++ ABI */ -#undef LLVM_ENABLE_ABI_BREAKING_CHECKS - #endif diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h new file mode 100644 index 00000000000..bdfd6683f80 --- /dev/null +++ b/include/llvm/DebugInfo/DIContext.h @@ -0,0 +1,178 @@ +//===-- DIContext.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines DIContext, an abstract data structure that holds +// debug information data. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DICONTEXT_H +#define LLVM_DEBUGINFO_DICONTEXT_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Object/RelocVisitor.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { + +class raw_ostream; + +/// DILineInfo - a format-neutral container for source line information. +struct DILineInfo { + std::string FileName; + std::string FunctionName; + uint32_t Line; + uint32_t Column; + + DILineInfo() + : FileName(""), FunctionName(""), Line(0), Column(0) {} + + bool operator==(const DILineInfo &RHS) const { + return Line == RHS.Line && Column == RHS.Column && + FileName == RHS.FileName && FunctionName == RHS.FunctionName; + } + bool operator!=(const DILineInfo &RHS) const { + return !(*this == RHS); + } +}; + +typedef SmallVector, 16> DILineInfoTable; + +/// DIInliningInfo - a format-neutral container for inlined code description. +class DIInliningInfo { + SmallVector Frames; + public: + DIInliningInfo() {} + DILineInfo getFrame(unsigned Index) const { + assert(Index < Frames.size()); + return Frames[Index]; + } + uint32_t getNumberOfFrames() const { + return Frames.size(); + } + void addFrame(const DILineInfo &Frame) { + Frames.push_back(Frame); + } +}; + +/// A DINameKind is passed to name search methods to specify a +/// preference regarding the type of name resolution the caller wants. +enum class DINameKind { None, ShortName, LinkageName }; + +/// DILineInfoSpecifier - controls which fields of DILineInfo container +/// should be filled with data. +struct DILineInfoSpecifier { + enum class FileLineInfoKind { None, Default, AbsoluteFilePath }; + typedef DINameKind FunctionNameKind; + + FileLineInfoKind FLIKind; + FunctionNameKind FNKind; + + DILineInfoSpecifier(FileLineInfoKind FLIKind = FileLineInfoKind::Default, + FunctionNameKind FNKind = FunctionNameKind::None) + : FLIKind(FLIKind), FNKind(FNKind) {} +}; + +/// Selects which debug sections get dumped. +enum DIDumpType { + DIDT_Null, + DIDT_All, + DIDT_Abbrev, + DIDT_AbbrevDwo, + DIDT_Aranges, + DIDT_Frames, + DIDT_Info, + DIDT_InfoDwo, + DIDT_Types, + DIDT_TypesDwo, + DIDT_Line, + DIDT_LineDwo, + DIDT_Loc, + DIDT_LocDwo, + DIDT_Ranges, + DIDT_Pubnames, + DIDT_Pubtypes, + DIDT_GnuPubnames, + DIDT_GnuPubtypes, + DIDT_Str, + DIDT_StrDwo, + DIDT_StrOffsetsDwo, + DIDT_AppleNames, + DIDT_AppleTypes, + DIDT_AppleNamespaces, + DIDT_AppleObjC +}; + +class DIContext { +public: + enum DIContextKind { + CK_DWARF, + CK_PDB + }; + DIContextKind getKind() const { return Kind; } + + DIContext(DIContextKind K) : Kind(K) {} + virtual ~DIContext() {} + + virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) = 0; + + virtual DILineInfo getLineInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; + virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address, + uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; + virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; +private: + const DIContextKind Kind; +}; + +/// An inferface for inquiring the load address of a loaded object file +/// to be used by the DIContext implementations when applying relocations +/// on the fly. +class LoadedObjectInfo { +public: + virtual ~LoadedObjectInfo() = default; + + /// Obtain the Load Address of a section by SectionRef. + /// + /// Calculate the address of the given section. + /// The section need not be present in the local address space. The addresses + /// need to be consistent with the addresses used to query the DIContext and + /// the output of this function should be deterministic, i.e. repeated calls with + /// the same Sec should give the same address. + virtual uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const = 0; + + /// If conveniently available, return the content of the given Section. + /// + /// When the section is available in the local address space, in relocated (loaded) + /// form, e.g. because it was relocated by a JIT for execution, this function + /// should provide the contents of said section in `Data`. If the loaded section + /// is not available, or the cost of retrieving it would be prohibitive, this + /// function should return false. In that case, relocations will be read from the + /// local (unrelocated) object file and applied on the fly. Note that this method + /// is used purely for optimzation purposes in the common case of JITting in the + /// local address space, so returning false should always be correct. + virtual bool getLoadedSectionContents(const object::SectionRef &Sec, + StringRef &Data) const { + return false; + } + + /// Obtain a copy of this LoadedObjectInfo. + /// + /// The caller is responsible for deallocation once the copy is no longer required. + virtual std::unique_ptr clone() const = 0; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARF/DIContext.h b/include/llvm/DebugInfo/DWARF/DIContext.h deleted file mode 100644 index 622aa699c43..00000000000 --- a/include/llvm/DebugInfo/DWARF/DIContext.h +++ /dev/null @@ -1,150 +0,0 @@ -//===-- DIContext.h ---------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines DIContext, an abstract data structure that holds -// debug information data. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_DEBUGINFO_DICONTEXT_H -#define LLVM_DEBUGINFO_DICONTEXT_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Object/RelocVisitor.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/DataTypes.h" -#include - -namespace llvm { - -class raw_ostream; - -/// DILineInfo - a format-neutral container for source line information. -struct DILineInfo { - std::string FileName; - std::string FunctionName; - uint32_t Line; - uint32_t Column; - - DILineInfo() - : FileName(""), FunctionName(""), Line(0), Column(0) {} - - bool operator==(const DILineInfo &RHS) const { - return Line == RHS.Line && Column == RHS.Column && - FileName == RHS.FileName && FunctionName == RHS.FunctionName; - } - bool operator!=(const DILineInfo &RHS) const { - return !(*this == RHS); - } -}; - -typedef SmallVector, 16> DILineInfoTable; - -/// DIInliningInfo - a format-neutral container for inlined code description. -class DIInliningInfo { - SmallVector Frames; - public: - DIInliningInfo() {} - DILineInfo getFrame(unsigned Index) const { - assert(Index < Frames.size()); - return Frames[Index]; - } - uint32_t getNumberOfFrames() const { - return Frames.size(); - } - void addFrame(const DILineInfo &Frame) { - Frames.push_back(Frame); - } -}; - -/// A DINameKind is passed to name search methods to specify a -/// preference regarding the type of name resolution the caller wants. -enum class DINameKind { None, ShortName, LinkageName }; - -/// DILineInfoSpecifier - controls which fields of DILineInfo container -/// should be filled with data. -struct DILineInfoSpecifier { - enum class FileLineInfoKind { None, Default, AbsoluteFilePath }; - typedef DINameKind FunctionNameKind; - - FileLineInfoKind FLIKind; - FunctionNameKind FNKind; - - DILineInfoSpecifier(FileLineInfoKind FLIKind = FileLineInfoKind::Default, - FunctionNameKind FNKind = FunctionNameKind::None) - : FLIKind(FLIKind), FNKind(FNKind) {} -}; - -/// Selects which debug sections get dumped. -enum DIDumpType { - DIDT_Null, - DIDT_All, - DIDT_Abbrev, - DIDT_AbbrevDwo, - DIDT_Aranges, - DIDT_Frames, - DIDT_Info, - DIDT_InfoDwo, - DIDT_Types, - DIDT_TypesDwo, - DIDT_Line, - DIDT_LineDwo, - DIDT_Loc, - DIDT_LocDwo, - DIDT_Ranges, - DIDT_Pubnames, - DIDT_Pubtypes, - DIDT_GnuPubnames, - DIDT_GnuPubtypes, - DIDT_Str, - DIDT_StrDwo, - DIDT_StrOffsetsDwo, - DIDT_AppleNames, - DIDT_AppleTypes, - DIDT_AppleNamespaces, - DIDT_AppleObjC -}; - -// In place of applying the relocations to the data we've read from disk we use -// a separate mapping table to the side and checking that at locations in the -// dwarf where we expect relocated values. This adds a bit of complexity to the -// dwarf parsing/extraction at the benefit of not allocating memory for the -// entire size of the debug info sections. -typedef DenseMap > RelocAddrMap; - -class DIContext { -public: - enum DIContextKind { - CK_DWARF - }; - DIContextKind getKind() const { return Kind; } - - DIContext(DIContextKind K) : Kind(K) {} - virtual ~DIContext(); - - /// getDWARFContext - get a context for binary DWARF data. - static DIContext *getDWARFContext(const object::ObjectFile &Obj); - - virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) = 0; - - virtual DILineInfo getLineInfoForAddress(uint64_t Address, - DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; - virtual DILineInfoTable getLineInfoForAddressRange(uint64_t Address, - uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; - virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address, - DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; -private: - const DIContextKind Kind; -}; - -} - -#endif diff --git a/include/llvm/DebugInfo/DWARF/DWARFContext.h b/include/llvm/DebugInfo/DWARF/DWARFContext.h index 677242b1216..423c0d32f1b 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ b/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -12,7 +12,7 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/DebugInfo/DWARF/DIContext.h" +#include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h" #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" @@ -25,6 +25,13 @@ namespace llvm { +// In place of applying the relocations to the data we've read from disk we use +// a separate mapping table to the side and checking that at locations in the +// dwarf where we expect relocated values. This adds a bit of complexity to the +// dwarf parsing/extraction at the benefit of not allocating memory for the +// entire size of the debug info sections. +typedef DenseMap > RelocAddrMap; + /// DWARFContext /// This data structure is the top level entity that deals with dwarf debug /// information parsing. The actual data is supplied through pure virtual @@ -248,7 +255,8 @@ class DWARFContextInMemory : public DWARFContext { SmallVector, 4> UncompressedSections; public: - DWARFContextInMemory(const object::ObjectFile &Obj); + DWARFContextInMemory(const object::ObjectFile &Obj, + const LoadedObjectInfo *L = nullptr); bool isLittleEndian() const override { return IsLittleEndian; } uint8_t getAddressSize() const override { return AddressSize; } const DWARFSection &getInfoSection() override { return InfoSection; } diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h b/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h index 1080327adad..f29d5fe9ecd 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h @@ -11,7 +11,7 @@ #define LLVM_LIB_DEBUGINFO_DWARFDEBUGINFOENTRY_H #include "llvm/ADT/SmallVector.h" -#include "llvm/DebugInfo/DWARF/DIContext.h" +#include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/Support/DataTypes.h" diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h index 0c564c49f62..93e7c790ccf 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -10,7 +10,7 @@ #ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGLINE_H #define LLVM_LIB_DEBUGINFO_DWARFDEBUGLINE_H -#include "llvm/DebugInfo/DWARF/DIContext.h" +#include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include "llvm/Support/DataExtractor.h" #include @@ -38,12 +38,12 @@ class DWARFDebugLine { // The size in bytes of the statement information for this compilation unit // (not including the total_length field itself). - uint32_t TotalLength; + uint64_t TotalLength; // Version identifier for the statement information format. uint16_t Version; // The number of bytes following the prologue_length field to the beginning // of the first byte of the statement program itself. - uint32_t PrologueLength; + uint64_t PrologueLength; // The size in bytes of the smallest target machine instruction. Statement // program opcodes that alter the address register first multiply their // operands by this value. @@ -63,14 +63,22 @@ class DWARFDebugLine { std::vector IncludeDirectories; std::vector FileNames; + bool IsDWARF64; + uint32_t sizeofTotalLength() const { + return IsDWARF64 ? 12 : 4; + } + uint32_t sizeofPrologueLength() const { + return IsDWARF64 ? 8 : 4; + } + // Length of the prologue in bytes. uint32_t getLength() const { - return PrologueLength + sizeof(TotalLength) + sizeof(Version) + - sizeof(PrologueLength); + return PrologueLength + sizeofTotalLength() + sizeof(Version) + + sizeofPrologueLength(); } // Length of the line table data in bytes (not including the prologue). uint32_t getStatementTableLength() const { - return TotalLength + sizeof(TotalLength) - getLength(); + return TotalLength + sizeofTotalLength() - getLength(); } int32_t getMaxLineIncrementForSpecialOpcode() const { return LineBase + (int8_t)LineRange - 1; @@ -163,6 +171,9 @@ class DWARFDebugLine { struct LineTable { LineTable(); + // Represents an invalid row + const uint32_t UnknownRowIndex = UINT32_MAX; + void appendRow(const DWARFDebugLine::Row &R) { Rows.push_back(R); } @@ -171,7 +182,7 @@ class DWARFDebugLine { } // Returns the index of the row with file/line info for a given address, - // or -1 if there is no such row. + // or UnknownRowIndex if there is no such row. uint32_t lookupAddress(uint64_t address) const; bool lookupAddressRange(uint64_t address, uint64_t size, @@ -203,6 +214,10 @@ class DWARFDebugLine { typedef SequenceVector::const_iterator SequenceIter; RowVector Rows; SequenceVector Sequences; + + private: + uint32_t findRowInSeq(const DWARFDebugLine::Sequence &seq, + uint64_t address) const; }; const LineTable *getLineTable(uint32_t offset) const; diff --git a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h index 02f468189d2..7ddcc0d81d5 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -87,6 +87,8 @@ class DWARFFormValue { static ArrayRef getFixedFormSizes(uint8_t AddrSize, uint16_t Version); +private: + void dumpString(raw_ostream &OS, const DWARFUnit *U) const; }; } diff --git a/include/llvm/DebugInfo/DWARF/DWARFSection.h b/include/llvm/DebugInfo/DWARF/DWARFSection.h index f52004cac8e..3e27b529e97 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFSection.h +++ b/include/llvm/DebugInfo/DWARF/DWARFSection.h @@ -11,6 +11,7 @@ #define LLVM_LIB_DEBUGINFO_DWARFSECTION_H #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" +#include "llvm/ADT/StringRef.h" namespace llvm { diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h index 2b377a9ad2f..5604b93f220 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -195,9 +195,8 @@ class DWARFUnit { BaseAddr = base_addr; } - const DWARFDebugInfoEntryMinimal * - getCompileUnitDIE(bool extract_cu_die_only = true) { - extractDIEsIfNeeded(extract_cu_die_only); + const DWARFDebugInfoEntryMinimal *getUnitDIE(bool ExtractUnitDIEOnly = true) { + extractDIEsIfNeeded(ExtractUnitDIEOnly); return DieArray.empty() ? nullptr : &DieArray[0]; } @@ -226,8 +225,7 @@ class DWARFUnit { /// It is illegal to call this method with a DIE that hasn't be /// created by this unit. In other word, it's illegal to call this /// method on a DIE that isn't accessible by following - /// children/sibling links starting from this unit's - /// getCompileUnitDIE(). + /// children/sibling links starting from this unit's getUnitDIE(). uint32_t getDIEIndex(const DWARFDebugInfoEntryMinimal *DIE) { assert(!DieArray.empty() && DIE >= &DieArray[0] && DIE < &DieArray[0] + DieArray.size()); diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASession.h b/include/llvm/DebugInfo/PDB/DIA/DIASession.h index 6c72c3e6fc6..9a8600fb85e 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIASession.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIASession.h @@ -21,12 +21,20 @@ class DIASession : public IPDBSession { static PDB_ErrorCode createFromPdb(StringRef Path, std::unique_ptr &Session); + static PDB_ErrorCode createFromExe(StringRef Path, + std::unique_ptr &Session); uint64_t getLoadAddress() const override; void setLoadAddress(uint64_t Address) override; std::unique_ptr getGlobalScope() const override; std::unique_ptr getSymbolById(uint32_t SymbolId) const override; + std::unique_ptr + findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override; + + std::unique_ptr + findLineNumbersByAddress(uint64_t Address, uint32_t Length) const override; + std::unique_ptr getAllSourceFiles() const override; std::unique_ptr getSourceFilesForCompiland( const PDBSymbolCompiland &Compiland) const override; diff --git a/include/llvm/DebugInfo/PDB/IPDBSession.h b/include/llvm/DebugInfo/PDB/IPDBSession.h index 60d6f62068e..a130a38a653 100644 --- a/include/llvm/DebugInfo/PDB/IPDBSession.h +++ b/include/llvm/DebugInfo/PDB/IPDBSession.h @@ -43,6 +43,11 @@ class IPDBSession { return std::unique_ptr(ConcreteSymbol); } + virtual std::unique_ptr + findSymbolByAddress(uint64_t Address, PDB_SymType Type) const = 0; + virtual std::unique_ptr + findLineNumbersByAddress(uint64_t Address, uint32_t Length) const = 0; + virtual std::unique_ptr getAllSourceFiles() const = 0; virtual std::unique_ptr getSourceFilesForCompiland(const PDBSymbolCompiland &Compiland) const = 0; diff --git a/include/llvm/DebugInfo/PDB/PDB.h b/include/llvm/DebugInfo/PDB/PDB.h index 67878e9ccf6..5df3be85e38 100644 --- a/include/llvm/DebugInfo/PDB/PDB.h +++ b/include/llvm/DebugInfo/PDB/PDB.h @@ -16,8 +16,11 @@ namespace llvm { class StringRef; -PDB_ErrorCode createPDBReader(PDB_ReaderType Type, StringRef Path, - std::unique_ptr &Session); +PDB_ErrorCode loadDataForPDB(PDB_ReaderType Type, StringRef Path, + std::unique_ptr &Session); + +PDB_ErrorCode loadDataForEXE(PDB_ReaderType Type, StringRef Path, + std::unique_ptr &Session); } #endif diff --git a/include/llvm/DebugInfo/PDB/PDBContext.h b/include/llvm/DebugInfo/PDB/PDBContext.h new file mode 100644 index 00000000000..2bb97463f90 --- /dev/null +++ b/include/llvm/DebugInfo/PDB/PDBContext.h @@ -0,0 +1,60 @@ +//===-- PDBContext.h --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===/ + +#ifndef LLVM_DEBUGINFO_PDB_PDBCONTEXT_H +#define LLVM_DEBUGINFO_PDB_PDBCONTEXT_H + +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" + +namespace llvm { + +namespace object { +class COFFObjectFile; +} + +/// PDBContext +/// This data structure is the top level entity that deals with PDB debug +/// information parsing. This data structure exists only when there is a +/// need for a transparent interface to different debug information formats +/// (e.g. PDB and DWARF). More control and power over the debug information +/// access can be had by using the PDB interfaces directly. +class PDBContext : public DIContext { + + PDBContext(PDBContext &) = delete; + PDBContext &operator=(PDBContext &) = delete; + +public: + PDBContext(const object::COFFObjectFile &Object, + std::unique_ptr PDBSession, + bool RelativeAddress); + + static bool classof(const DIContext *DICtx) { + return DICtx->getKind() == CK_PDB; + } + + void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) override; + + DILineInfo getLineInfoForAddress( + uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + DILineInfoTable getLineInfoForAddressRange( + uint64_t Address, uint64_t Size, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + DIInliningInfo getInliningInfoForAddress( + uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + +private: + std::string getFunctionName(uint64_t Address, DINameKind NameKind) const; + std::unique_ptr Session; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/PDB/PDBTypes.h b/include/llvm/DebugInfo/PDB/PDBTypes.h index 686e08f81a1..2d19e792d3d 100644 --- a/include/llvm/DebugInfo/PDB/PDBTypes.h +++ b/include/llvm/DebugInfo/PDB/PDBTypes.h @@ -21,6 +21,7 @@ class PDBSymbol; class IPDBDataStream; template class IPDBEnumChildren; +class IPDBLineNumber; class IPDBRawSymbol; class IPDBSession; class IPDBSourceFile; @@ -28,6 +29,7 @@ class IPDBSourceFile; typedef IPDBEnumChildren IPDBEnumSymbols; typedef IPDBEnumChildren IPDBEnumSourceFiles; typedef IPDBEnumChildren IPDBEnumDataStreams; +typedef IPDBEnumChildren IPDBEnumLineNumbers; class PDBSymbolExe; class PDBSymbolCompiland; @@ -426,7 +428,8 @@ enum class PDB_ErrorCode { InvalidParameter, AlreadyLoaded, UnknownError, - NoMemory + NoMemory, + DebugInfoMismatch }; struct VersionInfo { diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index 4b2add8bf5d..a7302602dcd 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -31,6 +31,7 @@ #include #include #include +#include namespace llvm { @@ -89,6 +90,8 @@ class ExecutionEngineState { uint64_t RemoveMapping(StringRef Name); }; +using FunctionCreator = std::function; + /// \brief Abstract interface for implementation execution of LLVM modules, /// designed to support both interpreter and just-in-time (JIT) compiler /// implementations. @@ -101,7 +104,12 @@ class ExecutionEngine { ExecutionEngineState EEState; /// The target data for the platform for which execution is being performed. - const DataLayout *DL; + /// + /// Note: the DataLayout is LLVMContext specific because it has an + /// internal cache based on type pointers. It makes unsafe to reuse the + /// ExecutionEngine across context, we don't enforce this rule but undefined + /// behavior can occurs if the user tries to do it. + const DataLayout DL; /// Whether lazy JIT compilation is enabled. bool CompilingLazily; @@ -123,8 +131,6 @@ class ExecutionEngine { /// optimize for the case where there is only one module. SmallVector, 1> Modules; - void setDataLayout(const DataLayout *Val) { DL = Val; } - /// getMemoryforGV - Allocate memory for a global variable. virtual char *getMemoryForGV(const GlobalVariable *GV); @@ -147,7 +153,7 @@ class ExecutionEngine { /// LazyFunctionCreator - If an unknown function is needed, this function /// pointer is invoked to create it. If this returns null, the JIT will /// abort. - void *(*LazyFunctionCreator)(const std::string &); + FunctionCreator LazyFunctionCreator; /// getMangledName - Get mangled name. std::string getMangledName(const GlobalValue *GV); @@ -191,21 +197,26 @@ class ExecutionEngine { //===--------------------------------------------------------------------===// - const DataLayout *getDataLayout() const { return DL; } + const DataLayout &getDataLayout() const { return DL; } /// removeModule - Remove a Module from the list of modules. Returns true if /// M is found. virtual bool removeModule(Module *M); - /// FindFunctionNamed - Search all of the active modules to find the one that + /// FindFunctionNamed - Search all of the active modules to find the function that /// defines FnName. This is very slow operation and shouldn't be used for /// general code. virtual Function *FindFunctionNamed(const char *FnName); + /// FindGlobalVariableNamed - Search all of the active modules to find the global variable + /// that defines Name. This is very slow operation and shouldn't be used for + /// general code. + virtual GlobalVariable *FindGlobalVariableNamed(const char *Name, bool AllowInternal = false); + /// runFunction - Execute the specified function with the specified arguments, /// and return the result. virtual GenericValue runFunction(Function *F, - const std::vector &ArgValues) = 0; + ArrayRef ArgValues) = 0; /// getPointerToNamedFunction - This method returns the address of the /// specified function by using the dlsym function call. As such it is only @@ -465,12 +476,13 @@ class ExecutionEngine { /// InstallLazyFunctionCreator - If an unknown function is needed, the /// specified function pointer is invoked to create it. If it returns null, /// the JIT will abort. - void InstallLazyFunctionCreator(void* (*P)(const std::string &)) { - LazyFunctionCreator = P; + void InstallLazyFunctionCreator(FunctionCreator C) { + LazyFunctionCreator = C; } protected: - ExecutionEngine() {} + ExecutionEngine(const DataLayout DL) : DL(std::move(DL)){} + explicit ExecutionEngine(DataLayout DL, std::unique_ptr M); explicit ExecutionEngine(std::unique_ptr M); void emitGlobals(); @@ -480,6 +492,9 @@ class ExecutionEngine { GenericValue getConstantValue(const Constant *C); void LoadValueFromMemory(GenericValue &Result, GenericValue *Ptr, Type *Ty); + +private: + void Init(std::unique_ptr M); }; namespace EngineKind { diff --git a/include/llvm/ExecutionEngine/Orc/CloneSubModule.h b/include/llvm/ExecutionEngine/Orc/CloneSubModule.h deleted file mode 100644 index 1bd3955e879..00000000000 --- a/include/llvm/ExecutionEngine/Orc/CloneSubModule.h +++ /dev/null @@ -1,60 +0,0 @@ -//===-- CloneSubModule.h - Utilities for extracting sub-modules -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Contains utilities for extracting sub-modules. Useful for breaking up modules -// for lazy jitting. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_CLONESUBMODULE_H -#define LLVM_EXECUTIONENGINE_ORC_CLONESUBMODULE_H - -#include "llvm/ADT/DenseSet.h" -#include "llvm/Transforms/Utils/ValueMapper.h" -#include - -namespace llvm { - -class Function; -class GlobalVariable; -class Module; - -namespace orc { - -/// @brief Functor type for describing how CloneSubModule should mutate a -/// GlobalVariable. -typedef std::function HandleGlobalVariableFtor; - -/// @brief Functor type for describing how CloneSubModule should mutate a -/// Function. -typedef std::function - HandleFunctionFtor; - -/// @brief Copies the initializer from Orig to New. -/// -/// Type is suitable for implicit conversion to a HandleGlobalVariableFtor. -void copyGVInitializer(GlobalVariable &New, const GlobalVariable &Orig, - ValueToValueMapTy &VMap); - -/// @brief Copies the body of Orig to New. -/// -/// Type is suitable for implicit conversion to a HandleFunctionFtor. -void copyFunctionBody(Function &New, const Function &Orig, - ValueToValueMapTy &VMap); - -/// @brief Clone a subset of the module Src into Dst. -void CloneSubModule(Module &Dst, const Module &Src, - HandleGlobalVariableFtor HandleGlobalVariable, - HandleFunctionFtor HandleFunction, bool KeepInlineAsm); - -} // End namespace orc. -} // End namespace llvm. - -#endif // LLVM_EXECUTIONENGINE_ORC_CLONESUBMODULE_H diff --git a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h index 30f7f1cd5f5..9694b80d192 100644 --- a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h +++ b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h @@ -17,158 +17,92 @@ #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" #include +#include + +#include "llvm/Support/Debug.h" namespace llvm { namespace orc { /// @brief Compile-on-demand layer. /// -/// Modules added to this layer have their calls indirected, and are then -/// broken up into a set of single-function modules, each of which is added -/// to the layer below in a singleton set. The lower layer can be any layer that -/// accepts IR module sets. -/// -/// It is expected that this layer will frequently be used on top of a -/// LazyEmittingLayer. The combination of the two ensures that each function is -/// compiled only when it is first called. -template +/// When a module is added to this layer a stub is created for each of its +/// function definitions. The stubs and other global values are immediately +/// 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 (Function&)>> class CompileOnDemandLayer { private: - /// @brief Lookup helper that provides compatibility with the classic - /// static-compilation symbol resolution process. - /// - /// The CompileOnDemand (COD) layer splits modules up into multiple - /// sub-modules, each held in its own llvm::Module instance, in order to - /// support lazy compilation. When a module that contains private symbols is - /// broken up symbol linkage changes may be required to enable access to - /// "private" data that now resides in a different llvm::Module instance. To - /// retain expected symbol resolution behavior for clients of the COD layer, - /// the CODScopedLookup class uses a two-tiered lookup system to resolve - /// symbols. Lookup first scans sibling modules that were split from the same - /// original module (logical-module scoped lookup), then scans all other - /// modules that have been added to the lookup scope (logical-dylib scoped - /// lookup). - class CODScopedLookup { - private: - typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT; - typedef std::vector SiblingHandlesList; - typedef std::list PseudoDylibModuleSetHandlesList; + // Utility class for MapValue. Only materializes declarations for global + // variables. + class GlobalDeclMaterializer : public ValueMaterializer { public: - /// @brief Handle for a logical module. - typedef typename PseudoDylibModuleSetHandlesList::iterator LMHandle; - - /// @brief Construct a scoped lookup. - CODScopedLookup(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {} - - virtual ~CODScopedLookup() {} - - /// @brief Start a new context for a single logical module. - LMHandle createLogicalModule() { - Handles.push_back(SiblingHandlesList()); - return std::prev(Handles.end()); - } - - /// @brief Add a concrete Module's handle to the given logical Module's - /// lookup scope. - void addToLogicalModule(LMHandle LMH, BaseLayerModuleSetHandleT H) { - LMH->push_back(H); - } - - /// @brief Remove a logical Module from the CODScopedLookup entirely. - void removeLogicalModule(LMHandle LMH) { Handles.erase(LMH); } - - /// @brief Look up a symbol in this context. - JITSymbol findSymbol(LMHandle LMH, const std::string &Name) { - if (auto Symbol = findSymbolIn(LMH, Name)) - return Symbol; - - for (auto I = Handles.begin(), E = Handles.end(); I != E; ++I) - if (I != LMH) - if (auto Symbol = findSymbolIn(I, Name)) - return Symbol; - - return nullptr; - } - - /// @brief Find an external symbol (via the user supplied SymbolResolver). - virtual RuntimeDyld::SymbolInfo - externalLookup(const std::string &Name) const = 0; - - private: - - JITSymbol findSymbolIn(LMHandle LMH, const std::string &Name) { - for (auto H : *LMH) - if (auto Symbol = BaseLayer.findSymbolIn(H, Name, false)) - return Symbol; + typedef std::set StubSet; + + GlobalDeclMaterializer(Module &Dst, const StubSet *StubsToClone = nullptr) + : Dst(Dst), StubsToClone(StubsToClone) {} + + Value* materializeValueFor(Value *V) final { + if (auto *GV = dyn_cast(V)) + return cloneGlobalVariableDecl(Dst, *GV); + else if (auto *F = dyn_cast(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; } - - BaseLayerT &BaseLayer; - PseudoDylibModuleSetHandlesList Handles; - }; - - template - class CODScopedLookupImpl : public CODScopedLookup { - public: - CODScopedLookupImpl(BaseLayerT &BaseLayer, ResolverPtrT Resolver) - : CODScopedLookup(BaseLayer), Resolver(std::move(Resolver)) {} - - RuntimeDyld::SymbolInfo - externalLookup(const std::string &Name) const override { - return Resolver->findSymbol(Name); - } - private: - ResolverPtrT Resolver; + Module &Dst; + const StubSet *StubsToClone; }; - template - static std::shared_ptr - createCODScopedLookup(BaseLayerT &BaseLayer, - ResolverPtrT Resolver) { - typedef CODScopedLookupImpl Impl; - return std::make_shared(BaseLayer, std::move(Resolver)); - } - typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT; - typedef std::vector BaseLayerModuleSetHandleListT; - - struct ModuleSetInfo { - // Symbol lookup - just one for the whole module set. - std::shared_ptr Lookup; - // Logical module handles. - std::vector LMHandles; - - // List of vectors of module set handles: - // One vector per logical module - each vector holds the handles for the - // exploded modules for that logical module in the base layer. - BaseLayerModuleSetHandleListT BaseLayerModuleSetHandles; - - ModuleSetInfo(std::shared_ptr Lookup) - : Lookup(std::move(Lookup)) {} + struct LogicalModuleResources { + std::shared_ptr SourceModule; + std::set StubsToClone; + }; - void releaseResources(BaseLayerT &BaseLayer) { - for (auto LMH : LMHandles) - Lookup->removeLogicalModule(LMH); - for (auto H : BaseLayerModuleSetHandles) - BaseLayer.removeModuleSet(H); - } + struct LogicalDylibResources { + typedef std::function + SymbolResolverFtor; + SymbolResolverFtor ExternalSymbolResolver; + PartitioningFtor Partitioner; }; - typedef std::list ModuleSetInfoListT; + typedef LogicalDylib CODLogicalDylib; + + typedef typename CODLogicalDylib::LogicalModuleHandle LogicalModuleHandle; + typedef std::list LogicalDylibList; public: /// @brief Handle to a set of loaded modules. - typedef typename ModuleSetInfoListT::iterator ModuleSetHandleT; + 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 findSymbol(Name); + }; + + LDResources.Partitioner = + [](Function &F) { + std::set Partition; + Partition.insert(&F); + return Partition; + }; // Process each of the modules in this module set. for (auto &M : Ms) - partitionAndAdd(*M, MSI); + addLogicalModule(LogicalDylibs.back(), + std::shared_ptr(std::move(M))); - return H; + return std::prev(LogicalDylibs.end()); } /// @brief Remove the module represented by the given handle. @@ -200,8 +142,7 @@ class CompileOnDemandLayer { /// This will remove all modules in the layers below that were derived from /// the module represented by H. void removeModuleSet(ModuleSetHandleT H) { - H->releaseResources(BaseLayer); - ModuleSetInfos.erase(H); + LogicalDylibs.erase(H); } /// @brief Search for the given named symbol. @@ -216,164 +157,194 @@ class CompileOnDemandLayer { /// below this one. JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name, bool ExportedSymbolsOnly) { - - for (auto &BH : H->BaseLayerModuleSetHandles) { - if (auto Symbol = BaseLayer.findSymbolIn(BH, Name, ExportedSymbolsOnly)) - return Symbol; - } - return nullptr; + return H->findSymbol(Name, ExportedSymbolsOnly); } private: - void partitionAndAdd(Module &M, ModuleSetInfo &MSI) { - const char *AddrSuffix = "$orc_addr"; - const char *BodySuffix = "$orc_body"; - - // We're going to break M up into a bunch of sub-modules, but we want - // internal linkage symbols to still resolve sensibly. CODScopedLookup - // provides the "logical module" concept to make this work, so create a - // new logical module for M. - auto DylibLookup = MSI.Lookup; - auto LogicalModule = DylibLookup->createLogicalModule(); - MSI.LMHandles.push_back(LogicalModule); - - // Partition M into a "globals and stubs" module, a "common symbols" module, - // and a list of single-function modules. - auto PartitionedModule = fullyPartition(M); - auto StubsModule = std::move(PartitionedModule.GlobalVars); - auto CommonsModule = std::move(PartitionedModule.Commons); - auto FunctionModules = std::move(PartitionedModule.Functions); - - // Emit the commons stright away. - auto CommonHandle = addModule(std::move(CommonsModule), MSI, LogicalModule); - BaseLayer.emitAndFinalize(CommonHandle); - - // Map of definition names to callback-info data structures. We'll use - // this to build the compile actions for the stubs below. - typedef std::map - StubInfoMap; - StubInfoMap StubInfos; - - // Now we need to take each of the extracted Modules and add them to - // base layer. Each Module will be added individually to make sure they - // can be compiled separately, and each will get its own lookaside - // memory manager that will resolve within this logical module first. - for (auto &SubM : FunctionModules) { - - // Keep track of the stubs we create for this module so that we can set - // their compile actions. - std::vector NewStubInfos; - - // Search for function definitions and insert stubs into the stubs - // module. - for (auto &F : *SubM) { - if (F.isDeclaration()) - continue; - - std::string Name = F.getName(); - Function *Proto = StubsModule->getFunction(Name); - assert(Proto && "Failed to clone function decl into stubs module."); - auto CallbackInfo = - CompileCallbackMgr.getCompileCallback(Proto->getContext()); - GlobalVariable *FunctionBodyPointer = - createImplPointer(*Proto->getType(), *Proto->getParent(), - Name + AddrSuffix, - createIRTypedAddress(*Proto->getFunctionType(), - CallbackInfo.getAddress())); - makeStub(*Proto, *FunctionBodyPointer); - - F.setName(Name + BodySuffix); - F.setVisibility(GlobalValue::HiddenVisibility); - - auto KV = std::make_pair(std::move(Name), std::move(CallbackInfo)); - NewStubInfos.push_back(StubInfos.insert(StubInfos.begin(), KV)); - } - - auto H = addModule(std::move(SubM), MSI, LogicalModule); - - // Set the compile actions for this module: - for (auto &KVPair : NewStubInfos) { - std::string BodyName = Mangle(KVPair->first + BodySuffix, - M.getDataLayout()); - auto &CCInfo = KVPair->second; - CCInfo.setCompileAction( - [=](){ - return BaseLayer.findSymbolIn(H, BodyName, false).getAddress(); - }); - } - + void addLogicalModule(CODLogicalDylib &LD, std::shared_ptr SrcM) { + + // Bump the linkage and rename any anonymous/privote members in SrcM to + // ensure that everything will resolve properly after we partition SrcM. + makeAllSymbolsExternallyAccessible(*SrcM); + + // 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( + (SrcM->getName() + ".globals_and_stubs").str(), + SrcM->getContext()); + GVsAndStubsM->setDataLayout(SrcM->getDataLayout()); + ValueToValueMapTy VMap; + + // 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 &F : *SrcM) { + + // 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); + }); } - // Ok - we've processed all the partitioned modules. Now add the - // stubs/globals module and set the update actions. - auto StubsH = - addModule(std::move(StubsModule), MSI, LogicalModule); - - for (auto &KVPair : StubInfos) { - std::string AddrName = Mangle(KVPair.first + AddrSuffix, - M.getDataLayout()); - auto &CCInfo = KVPair.second; - CCInfo.setUpdateAction( - getLocalFPUpdater(BaseLayer, StubsH, AddrName)); - } - } - - // Add the given Module to the base layer using a memory manager that will - // perform the appropriate scoped lookup (i.e. will look first with in the - // module from which it was extracted, then into the set to which that module - // belonged, and finally externally). - BaseLayerModuleSetHandleT addModule( - std::unique_ptr M, - ModuleSetInfo &MSI, - typename CODScopedLookup::LMHandle LogicalModule) { - - // Add this module to the JIT with a memory manager that uses the - // DylibLookup to resolve symbols. - std::vector> MSet; - MSet.push_back(std::move(M)); - - auto DylibLookup = MSI.Lookup; - auto Resolver = - createLambdaResolver( - [=](const std::string &Name) { - if (auto Symbol = DylibLookup->findSymbol(LogicalModule, Name)) - return RuntimeDyld::SymbolInfo(Symbol.getAddress(), - Symbol.getFlags()); - return DylibLookup->externalLookup(Name); + // Now clone the global variable declarations. + GlobalDeclMaterializer GDMat(*GVsAndStubsM); + for (auto &GV : SrcM->globals()) + if (!GV.isDeclaration()) + cloneGlobalVariableDecl(*GVsAndStubsM, GV, &VMap); + + // Then clone the initializers. + for (auto &GV : SrcM->globals()) + if (!GV.isDeclaration()) + moveGlobalVariableInitializer(GV, VMap, &GDMat); + + // Build a resolver for the stubs module and add it to the base layer. + auto GVsAndStubsResolver = createLambdaResolver( + [&LD](const std::string &Name) { + return LD.getDylibResources().ExternalSymbolResolver(Name); }, - [=](const std::string &Name) -> RuntimeDyld::SymbolInfo { - if (auto Symbol = DylibLookup->findSymbol(LogicalModule, Name)) - return RuntimeDyld::SymbolInfo(Symbol.getAddress(), - Symbol.getFlags()); - return nullptr; + [](const std::string &Name) { + return RuntimeDyld::SymbolInfo(nullptr); }); - BaseLayerModuleSetHandleT H = - BaseLayer.addModuleSet(std::move(MSet), - make_unique(), - std::move(Resolver)); - // Add this module to the logical module lookup. - DylibLookup->addToLogicalModule(LogicalModule, H); - MSI.BaseLayerModuleSetHandles.push_back(H); - - return H; + std::vector> GVsAndStubsMSet; + GVsAndStubsMSet.push_back(std::move(GVsAndStubsM)); + auto GVsAndStubsH = + BaseLayer.addModuleSet(std::move(GVsAndStubsMSet), + llvm::make_unique(), + std::move(GVsAndStubsResolver)); + LD.addToLogicalModule(LMH, GVsAndStubsH); } static std::string Mangle(StringRef Name, const DataLayout &DL) { - Mangler M(&DL); std::string MangledName; { raw_string_ostream MangledNameStream(MangledName); - M.getNameWithPrefix(MangledNameStream, Name); + Mangler::getNameWithPrefix(MangledNameStream, Name, DL); } 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( + static_cast(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 + 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(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(); + 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> PartMSet; + PartMSet.push_back(std::move(M)); + return BaseLayer.addModuleSet(std::move(PartMSet), std::move(MemMgr), + std::move(Resolver)); + } + BaseLayerT &BaseLayer; CompileCallbackMgrT &CompileCallbackMgr; - ModuleSetInfoListT ModuleSetInfos; + LogicalDylibList LogicalDylibs; + bool CloneStubsIntoPartitions; }; } // End namespace orc. diff --git a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h index 7b4f611393f..4b7fc5e84b9 100644 --- a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h +++ b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h @@ -15,11 +15,13 @@ #define LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H #include "JITSymbol.h" +#include "LambdaResolver.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" +#include "llvm/Transforms/Utils/ValueMapper.h" #include namespace llvm { @@ -31,28 +33,22 @@ class JITCompileCallbackManagerBase { public: typedef std::function CompileFtor; - typedef std::function UpdateFtor; /// @brief Handle to a newly created compile callback. Can be used to get an /// IR constant representing the address of the trampoline, and to set - /// the compile and update actions for the callback. + /// the compile action for the callback. class CompileCallbackInfo { public: - CompileCallbackInfo(TargetAddress Addr, CompileFtor &Compile, - UpdateFtor &Update) - : Addr(Addr), Compile(Compile), Update(Update) {} + CompileCallbackInfo(TargetAddress Addr, CompileFtor &Compile) + : Addr(Addr), Compile(Compile) {} TargetAddress getAddress() const { return Addr; } void setCompileAction(CompileFtor Compile) { this->Compile = std::move(Compile); } - void setUpdateAction(UpdateFtor Update) { - this->Update = std::move(Update); - } private: TargetAddress Addr; CompileFtor &Compile; - UpdateFtor &Update; }; /// @brief Construct a JITCompileCallbackManagerBase. @@ -70,8 +66,8 @@ class JITCompileCallbackManagerBase { /// @brief Execute the callback for the given trampoline id. Called by the JIT /// to compile functions on demand. - TargetAddress executeCompileCallback(TargetAddress TrampolineID) { - TrampolineMapT::iterator I = ActiveTrampolines.find(TrampolineID); + TargetAddress executeCompileCallback(TargetAddress TrampolineAddr) { + auto I = ActiveTrampolines.find(TrampolineAddr); // FIXME: Also raise an error in the Orc error-handler when we finally have // one. if (I == ActiveTrampolines.end()) @@ -83,31 +79,43 @@ class JITCompileCallbackManagerBase { // Moving the trampoline ID back to the available list first means there's at // least one available trampoline if the compile action triggers a request for // a new one. - AvailableTrampolines.push_back(I->first); - auto CallbackHandler = std::move(I->second); + auto Compile = std::move(I->second); ActiveTrampolines.erase(I); + AvailableTrampolines.push_back(TrampolineAddr); - if (auto Addr = CallbackHandler.Compile()) { - CallbackHandler.Update(Addr); + if (auto Addr = Compile()) return Addr; - } + return ErrorHandlerAddress; } - /// @brief Get/create a compile callback with the given signature. + /// @brief Reserve a compile callback. virtual CompileCallbackInfo getCompileCallback(LLVMContext &Context) = 0; -protected: + /// @brief Get a CompileCallbackInfo for an existing callback. + CompileCallbackInfo getCompileCallbackInfo(TargetAddress TrampolineAddr) { + auto I = ActiveTrampolines.find(TrampolineAddr); + assert(I != ActiveTrampolines.end() && "Not an active trampoline."); + return CompileCallbackInfo(I->first, I->second); + } - struct CallbackHandler { - CompileFtor Compile; - UpdateFtor Update; - }; + /// @brief Release a compile callback. + /// + /// Note: Callbacks are auto-released after they execute. This method should + /// only be called to manually release a callback that is not going to + /// execute. + void releaseCompileCallback(TargetAddress TrampolineAddr) { + auto I = ActiveTrampolines.find(TrampolineAddr); + assert(I != ActiveTrampolines.end() && "Not an active trampoline."); + ActiveTrampolines.erase(I); + AvailableTrampolines.push_back(TrampolineAddr); + } +protected: TargetAddress ErrorHandlerAddress; unsigned NumTrampolinesPerBlock; - typedef std::map TrampolineMapT; + typedef std::map TrampolineMapT; TrampolineMapT ActiveTrampolines; std::vector AvailableTrampolines; }; @@ -139,11 +147,8 @@ class JITCompileCallbackManager : public JITCompileCallbackManagerBase { /// @brief Get/create a compile callback with the given signature. CompileCallbackInfo getCompileCallback(LLVMContext &Context) final { TargetAddress TrampolineAddr = getAvailableTrampolineAddr(Context); - auto &CallbackHandler = - this->ActiveTrampolines[TrampolineAddr]; - - return CompileCallbackInfo(TrampolineAddr, CallbackHandler.Compile, - CallbackHandler.Update); + auto &Compile = this->ActiveTrampolines[TrampolineAddr]; + return CompileCallbackInfo(TrampolineAddr, Compile); } private: @@ -159,9 +164,16 @@ class JITCompileCallbackManager : public JITCompileCallbackManagerBase { std::unique_ptr M(new Module("resolver_block_module", Context)); TargetT::insertResolverBlock(*M, *this); + auto NonResolver = + createLambdaResolver( + [](const std::string &Name) -> RuntimeDyld::SymbolInfo { + llvm_unreachable("External symbols in resolver block?"); + }, + [](const std::string &Name) -> RuntimeDyld::SymbolInfo { + llvm_unreachable("Dylib symbols in resolver block?"); + }); auto H = JIT.addModuleSet(SingletonSet(std::move(M)), &MemMgr, - static_cast( - nullptr)); + std::move(NonResolver)); JIT.emitAndFinalize(H); auto ResolverBlockSymbol = JIT.findSymbolIn(H, TargetT::ResolverBlockName, false); @@ -186,9 +198,16 @@ class JITCompileCallbackManager : public JITCompileCallbackManagerBase { TargetT::insertCompileCallbackTrampolines(*M, ResolverBlockAddr, this->NumTrampolinesPerBlock, this->ActiveTrampolines.size()); + auto NonResolver = + createLambdaResolver( + [](const std::string &Name) -> RuntimeDyld::SymbolInfo { + llvm_unreachable("External symbols in trampoline block?"); + }, + [](const std::string &Name) -> RuntimeDyld::SymbolInfo { + llvm_unreachable("Dylib symbols in trampoline block?"); + }); auto H = JIT.addModuleSet(SingletonSet(std::move(M)), &MemMgr, - static_cast( - nullptr)); + std::move(NonResolver)); JIT.emitAndFinalize(H); for (unsigned I = 0; I < this->NumTrampolinesPerBlock; ++I) { std::string Name = GetLabelName(I); @@ -203,22 +222,6 @@ class JITCompileCallbackManager : public JITCompileCallbackManagerBase { TargetAddress ResolverBlockAddr; }; -/// @brief Get an update functor that updates the value of a named function -/// pointer. -template -JITCompileCallbackManagerBase::UpdateFtor -getLocalFPUpdater(JITLayerT &JIT, typename JITLayerT::ModuleSetHandleT H, - std::string Name) { - // FIXME: Move-capture Name once we can use C++14. - return [=,&JIT](TargetAddress Addr) { - auto FPSym = JIT.findSymbolIn(H, Name, true); - assert(FPSym && "Cannot find function pointer to update."); - void *FPAddr = reinterpret_cast( - static_cast(FPSym.getAddress())); - memcpy(FPAddr, &Addr, sizeof(uintptr_t)); - }; - } - /// @brief Build a function pointer of FunctionType with the given constant /// address. /// @@ -235,27 +238,56 @@ GlobalVariable* createImplPointer(PointerType &PT, Module &M, /// indirect call using the given function pointer. void makeStub(Function &F, GlobalVariable &ImplPointer); -typedef std::map> ModulePartitionMap; - -/// @brief Extract subsections of a Module into the given Module according to -/// the given ModulePartitionMap. -void partition(Module &M, const ModulePartitionMap &PMap); - -/// @brief Struct for trivial "complete" partitioning of a module. -class FullyPartitionedModule { -public: - std::unique_ptr GlobalVars; - std::unique_ptr Commons; - std::vector> Functions; - - FullyPartitionedModule() = default; - FullyPartitionedModule(FullyPartitionedModule &&S) - : GlobalVars(std::move(S.GlobalVars)), Commons(std::move(S.Commons)), - Functions(std::move(S.Functions)) {} -}; +/// @brief Raise linkage types and rename as necessary to ensure that all +/// symbols are accessible for other modules. +/// +/// This should be called before partitioning a module to ensure that the +/// partitions retain access to each other's symbols. +void makeAllSymbolsExternallyAccessible(Module &M); -/// @brief Extract every function in M into a separate module. -FullyPartitionedModule fullyPartition(Module &M); +/// @brief Clone a function declaration into a new module. +/// +/// This function can be used as the first step towards creating a callback +/// stub (see makeStub), or moving a function body (see moveFunctionBody). +/// +/// If the VMap argument is non-null, a mapping will be added between F and +/// the new declaration, and between each of F's arguments and the new +/// declaration's arguments. This map can then be passed in to moveFunction to +/// move the function body if required. Note: When moving functions between +/// modules with these utilities, all decls should be cloned (and added to a +/// single VMap) before any bodies are moved. This will ensure that references +/// between functions all refer to the versions in the new module. +Function* cloneFunctionDecl(Module &Dst, const Function &F, + ValueToValueMapTy *VMap = nullptr); + +/// @brief Move the body of function 'F' to a cloned function declaration in a +/// different module (See related cloneFunctionDecl). +/// +/// If the target function declaration is not supplied via the NewF parameter +/// then it will be looked up via the VMap. +/// +/// This will delete the body of function 'F' from its original parent module, +/// but leave its declaration. +void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap, + ValueMaterializer *Materializer = nullptr, + Function *NewF = nullptr); + +/// @brief Clone a global variable declaration into a new module. +GlobalVariable* cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV, + ValueToValueMapTy *VMap = nullptr); + +/// @brief Move global variable GV from its parent module to cloned global +/// declaration in a different module. +/// +/// If the target global declaration is not supplied via the NewGV parameter +/// then it will be looked up via the VMap. +/// +/// This will delete the initializer of GV from its original parent module, +/// but leave its declaration. +void moveGlobalVariableInitializer(GlobalVariable &OrigGV, + ValueToValueMapTy &VMap, + ValueMaterializer *Materializer = nullptr, + GlobalVariable *NewGV = nullptr); } // End namespace orc. } // End namespace llvm. diff --git a/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h b/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h index 71c83f7e05f..93ba02b3870 100644 --- a/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h +++ b/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h @@ -193,7 +193,7 @@ template class LazyEmittingLayer { auto Symbols = llvm::make_unique>(); for (const auto &M : Ms) { - Mangler Mang(&M->getDataLayout()); + Mangler Mang; for (const auto &V : M->globals()) if (auto GV = addGlobalValue(*Symbols, V, Mang, SearchName, diff --git a/include/llvm/ExecutionEngine/Orc/LogicalDylib.h b/include/llvm/ExecutionEngine/Orc/LogicalDylib.h new file mode 100644 index 00000000000..28700ef347d --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/LogicalDylib.h @@ -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 +class LogicalDylib { +public: + typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT; +private: + + typedef std::vector BaseLayerHandleList; + + struct LogicalModule { + LogicalModuleResources Resources; + BaseLayerHandleList BaseLayerHandles; + }; + typedef std::vector 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 diff --git a/include/llvm/ExecutionEngine/Orc/NullResolver.h b/include/llvm/ExecutionEngine/Orc/NullResolver.h new file mode 100644 index 00000000000..1560c6d86e0 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/NullResolver.h @@ -0,0 +1,36 @@ +//===------ NullResolver.h - Reject symbol lookup requests ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines a RuntimeDyld::SymbolResolver subclass that rejects all symbol +// resolution requests, for clients that have no cross-object fixups. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H +#define LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H + +#include "llvm/ExecutionEngine/RuntimeDyld.h" + +namespace llvm { +namespace orc { + +/// SymbolResolver impliementation that rejects all resolution requests. +/// Useful for clients that have no cross-object fixups. +class NullResolver : public RuntimeDyld::SymbolResolver { +public: + RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) final; + + RuntimeDyld::SymbolInfo + findSymbolInLogicalDylib(const std::string &Name) final; +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H diff --git a/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h b/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h new file mode 100644 index 00000000000..7af66208547 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/ObjectTransformLayer.h @@ -0,0 +1,112 @@ +//===- ObjectTransformLayer.h - Run all objects through functor -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Run all objects passed in through a user supplied functor. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTTRANSFORMLAYER_H +#define LLVM_EXECUTIONENGINE_ORC_OBJECTTRANSFORMLAYER_H + +#include "JITSymbol.h" + +namespace llvm { +namespace orc { + +/// @brief Object mutating layer. +/// +/// This layer accepts sets of ObjectFiles (via addObjectSet). It +/// immediately applies the user supplied functor to each object, then adds +/// the set of transformed objects to the layer below. +template +class ObjectTransformLayer { +public: + /// @brief Handle to a set of added objects. + typedef typename BaseLayerT::ObjSetHandleT ObjSetHandleT; + + /// @brief Construct an ObjectTransformLayer with the given BaseLayer + ObjectTransformLayer(BaseLayerT &BaseLayer, + TransformFtor Transform = TransformFtor()) + : BaseLayer(BaseLayer), Transform(std::move(Transform)) {} + + /// @brief Apply the transform functor to each object in the object set, then + /// add the resulting set of objects to the base layer, along with the + /// memory manager and symbol resolver. + /// + /// @return A handle for the added objects. + template + ObjSetHandleT addObjectSet(ObjSetT &Objects, MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { + + for (auto I = Objects.begin(), E = Objects.end(); I != E; ++I) + *I = Transform(std::move(*I)); + + return BaseLayer.addObjectSet(Objects, std::move(MemMgr), + std::move(Resolver)); + } + + /// @brief Remove the object set associated with the handle H. + void removeObjectSet(ObjSetHandleT H) { BaseLayer.removeObjectSet(H); } + + /// @brief Search for the given named symbol. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it exists. + JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { + return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); + } + + /// @brief Get the address of the given symbol in the context of the set of + /// objects represented by the handle H. This call is forwarded to the + /// base layer's implementation. + /// @param H The handle for the object set to search in. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it is found in the + /// given object set. + JITSymbol findSymbolIn(ObjSetHandleT H, const std::string &Name, + bool ExportedSymbolsOnly) { + return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly); + } + + /// @brief Immediately emit and finalize the object set represented by the + /// given handle. + /// @param H Handle for object set to emit/finalize. + void emitAndFinalize(ObjSetHandleT H) { BaseLayer.emitAndFinalize(H); } + + /// @brief Map section addresses for the objects associated with the handle H. + void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress, + TargetAddress TargetAddr) { + BaseLayer.mapSectionAddress(H, LocalAddress, TargetAddr); + } + + // Ownership hack. + // FIXME: Remove this as soon as RuntimeDyldELF can apply relocations without + // referencing the original object. + template + void takeOwnershipOfBuffers(ObjSetHandleT H, OwningMBSet MBs) { + BaseLayer.takeOwnershipOfBuffers(H, std::move(MBs)); + } + + /// @brief Access the transform functor directly. + TransformFtor &getTransform() { return Transform; } + + /// @brief Access the mumate functor directly. + const TransformFtor &getTransform() const { return Transform; } + +private: + BaseLayerT &BaseLayer; + TransformFtor Transform; +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_OBJECTTRANSFORMLAYER_H diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index 5723f058f72..17c5fbd5649 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -15,8 +15,12 @@ #define LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H #include "JITSymbolFlags.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Support/Memory.h" +#include "llvm/DebugInfo/DIContext.h" +#include #include namespace llvm { @@ -54,31 +58,39 @@ class RuntimeDyld { }; /// \brief Information about the loaded object. - class LoadedObjectInfo { + class LoadedObjectInfo : public llvm::LoadedObjectInfo { friend class RuntimeDyldImpl; public: - LoadedObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, - unsigned EndIdx) - : RTDyld(RTDyld), BeginIdx(BeginIdx), EndIdx(EndIdx) { } + typedef std::map ObjSectionToIDMap; - virtual ~LoadedObjectInfo() {} + LoadedObjectInfo(RuntimeDyldImpl &RTDyld, ObjSectionToIDMap ObjSecToIDMap) + : RTDyld(RTDyld), ObjSecToIDMap(ObjSecToIDMap) { } virtual object::OwningBinary getObjectForDebug(const object::ObjectFile &Obj) const = 0; - uint64_t getSectionLoadAddress(StringRef Name) const; + uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const; protected: virtual void anchor(); RuntimeDyldImpl &RTDyld; - unsigned BeginIdx, EndIdx; + ObjSectionToIDMap ObjSecToIDMap; + }; + + template struct LoadedObjectInfoHelper : LoadedObjectInfo { + LoadedObjectInfoHelper(RuntimeDyldImpl &RTDyld, + LoadedObjectInfo::ObjSectionToIDMap ObjSecToIDMap) + : LoadedObjectInfo(RTDyld, std::move(ObjSecToIDMap)) {} + std::unique_ptr clone() const override { + return llvm::make_unique(static_cast(*this)); + } }; /// \brief Memory Management. class MemoryManager { public: - virtual ~MemoryManager() {}; + virtual ~MemoryManager() {} /// Allocate a memory block of (at least) the given size suitable for /// executable code. The SectionID is a unique identifier assigned by the @@ -140,10 +152,14 @@ class RuntimeDyld { /// \brief Symbol resolution. class SymbolResolver { public: - virtual ~SymbolResolver() {}; + virtual ~SymbolResolver() {} /// This method returns the address of the specified function or variable. /// It is used to resolve symbols during module linking. + /// + /// If the returned symbol's address is equal to ~0ULL then RuntimeDyld will + /// skip all relocations for that symbol, and the client will be responsible + /// for handling them manually. virtual SymbolInfo findSymbol(const std::string &Name) = 0; /// This method returns the address of the specified symbol if it exists diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h index dd76a90aa5e..fc04fe71cbf 100644 --- a/include/llvm/IR/Argument.h +++ b/include/llvm/IR/Argument.h @@ -64,6 +64,11 @@ class Argument : public Value, public ilist_node { /// containing function, return the number of bytes known to be /// dereferenceable. Otherwise, zero is returned. uint64_t getDereferenceableBytes() const; + + /// \brief If this argument has the dereferenceable_or_null attribute on + /// it in its containing function, return the number of bytes known to be + /// dereferenceable. Otherwise, zero is returned. + uint64_t getDereferenceableOrNullBytes() const; /// \brief Return true if this argument has the byval attribute on it in its /// containing function. diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index d0d1b5e57a9..4d6d7da1fa5 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -73,6 +73,7 @@ class Attribute { ByVal, ///< Pass structure by value InAlloca, ///< Pass structure in an alloca Cold, ///< Marks function as being in a cold path. + Convergent, ///< Can only be moved to control-equivalent blocks InlineHint, ///< Source said inlining was desirable InReg, ///< Force argument to be passed in register JumpTable, ///< Build jump-instruction tables and replace refs. @@ -97,6 +98,8 @@ class Attribute { OptimizeNone, ///< Function must not be optimized. ReadNone, ///< Function does not access memory ReadOnly, ///< Function only reads from memory + ArgMemOnly, ///< Funciton can access memory only using pointers + ///< based on its arguments. Returned, ///< Return value is always equal to this argument ReturnsTwice, ///< Function can return twice SExt, ///< Sign extended before/after call @@ -107,6 +110,7 @@ class Attribute { 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. @@ -260,42 +264,48 @@ class AttributeSet { ArrayRef Kind); static AttributeSet get(LLVMContext &C, unsigned Index, const AttrBuilder &B); - /// \brief Add an attribute to the attribute set at the given index. Since + /// \brief Add an attribute to the attribute set at the given index. Because /// attribute sets are immutable, this returns a new set. AttributeSet addAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Attr) const; - /// \brief Add an attribute to the attribute set at the given index. Since + /// \brief Add an attribute to the attribute set at the given index. Because /// attribute sets are immutable, this returns a new set. AttributeSet addAttribute(LLVMContext &C, unsigned Index, StringRef Kind) const; AttributeSet addAttribute(LLVMContext &C, unsigned Index, StringRef Kind, StringRef Value) const; - /// \brief Add attributes to the attribute set at the given index. Since + /// \brief Add attributes to the attribute set at the given index. Because /// attribute sets are immutable, this returns a new set. AttributeSet addAttributes(LLVMContext &C, unsigned Index, AttributeSet Attrs) const; /// \brief Remove the specified attribute at the specified index from this - /// attribute list. Since attribute lists are immutable, this returns the new - /// list. + /// attribute list. Because attribute lists are immutable, this returns the + /// new list. AttributeSet removeAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Attr) const; /// \brief Remove the specified attributes at the specified index from this - /// attribute list. Since attribute lists are immutable, this returns the new - /// list. + /// attribute list. Because attribute lists are immutable, this returns the + /// new list. AttributeSet removeAttributes(LLVMContext &C, unsigned Index, AttributeSet Attrs) const; + /// \brief Remove the specified attributes at the specified index from this + /// attribute list. Because attribute lists are immutable, this returns the + /// new list. + AttributeSet removeAttributes(LLVMContext &C, unsigned Index, + const AttrBuilder &Attrs) const; + /// \brief Add the dereferenceable attribute to the attribute set at the given - /// index. Since attribute sets are immutable, this returns a new set. + /// index. Because attribute sets are immutable, this returns a new set. AttributeSet addDereferenceableAttr(LLVMContext &C, unsigned Index, uint64_t Bytes) const; /// \brief Add the dereferenceable_or_null attribute to the attribute set at - /// the given index. Since attribute sets are immutable, this returns a new + /// the given index. Because attribute sets are immutable, this returns a new /// set. AttributeSet addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index, uint64_t Bytes) const; @@ -430,13 +440,17 @@ class AttrBuilder { uint64_t DerefBytes; uint64_t DerefOrNullBytes; public: - AttrBuilder() : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) {} + AttrBuilder() + : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0), + DerefOrNullBytes(0) {} explicit AttrBuilder(uint64_t Val) - : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) { + : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0), + DerefOrNullBytes(0) { addRawValue(Val); } AttrBuilder(const Attribute &A) - : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) { + : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0), + DerefOrNullBytes(0) { addAttribute(A); } AttrBuilder(AttributeSet AS, unsigned Idx); @@ -464,6 +478,13 @@ class AttrBuilder { /// \brief Add the attributes from the builder. AttrBuilder &merge(const AttrBuilder &B); + /// \brief Remove the attributes from the builder. + AttrBuilder &remove(const AttrBuilder &B); + + /// \brief Return true if the builder has any attribute that's in the + /// specified builder. + bool overlaps(const AttrBuilder &B) const; + /// \brief Return true if the builder has the specified attribute. bool contains(Attribute::AttrKind A) const { assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!"); @@ -552,7 +573,7 @@ class AttrBuilder { namespace AttributeFuncs { /// \brief Which attributes cannot be applied to a type. -AttributeSet typeIncompatible(Type *Ty, uint64_t Index); +AttrBuilder typeIncompatible(const Type *Ty); } // end AttributeFuncs namespace diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h index a71946eda6e..08e30bdc941 100644 --- a/include/llvm/IR/BasicBlock.h +++ b/include/llvm/IR/BasicBlock.h @@ -116,6 +116,7 @@ class BasicBlock : public Value, // Basic blocks are data objects also /// /// Note: this is undefined behavior if the block does not have a parent. const Module *getModule() const; + Module *getModule(); /// \brief Returns the terminator instruction if the block is well formed or /// null if the block is not well formed. @@ -206,9 +207,19 @@ class BasicBlock : public Value, // Basic blocks are data objects also return const_cast(this)->getUniquePredecessor(); } - /// Return the successor of this block if it has a unique successor. - /// Otherwise return a null pointer. This method is analogous to - /// getUniquePredeccessor above. + /// \brief Return the successor of this block if it has a single successor. + /// Otherwise return a null pointer. + /// + /// This method is analogous to getSinglePredecessor above. + BasicBlock *getSingleSuccessor(); + const BasicBlock *getSingleSuccessor() const { + return const_cast(this)->getSingleSuccessor(); + } + + /// \brief Return the successor of this block if it has a unique successor. + /// Otherwise return a null pointer. + /// + /// This method is analogous to getUniquePredecessor above. BasicBlock *getUniqueSuccessor(); const BasicBlock *getUniqueSuccessor() const { return const_cast(this)->getUniqueSuccessor(); @@ -272,6 +283,8 @@ class BasicBlock : public Value, // Basic blocks are data objects also /// should be called while the predecessor still refers to this block. void removePredecessor(BasicBlock *Pred, bool DontDeleteUselessPHIs = false); + bool canSplitPredecessors() const; + /// \brief Split the basic block into two basic blocks at the specified /// instruction. /// @@ -298,6 +311,9 @@ class BasicBlock : public Value, // Basic blocks are data objects also /// basic block \p New instead of to it. void replaceSuccessorsPhiUsesWith(BasicBlock *New); + /// \brief Return true if this basic block is an exception handling block. + bool isEHPad() const { return getFirstNonPHI()->isEHPad(); } + /// \brief Return true if this basic block is a landing pad. /// /// Being a ``landing pad'' means that the basic block is the destination of diff --git a/include/llvm/IR/CallSite.h b/include/llvm/IR/CallSite.h index ebace3395ac..2841781e8a9 100644 --- a/include/llvm/IR/CallSite.h +++ b/include/llvm/IR/CallSite.h @@ -27,6 +27,7 @@ #define LLVM_IR_CALLSITE_H #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/Instructions.h" @@ -37,6 +38,7 @@ class CallInst; class InvokeInst; template () const { return I.getPointer(); } explicit operator bool() const { return I.getPointer(); } + /// Get the basic block containing the call site + BBTy* getParent() const { return getInstruction()->getParent(); } + /// getCalledValue - Return the pointer to function that is being called. /// ValTy *getCalledValue() const { @@ -150,6 +155,9 @@ class CallSiteBase { } IterTy arg_end() const { return (*this)->op_end() - getArgumentEndOffset(); } + iterator_range args() const { + return iterator_range(arg_begin(), arg_end()); + } bool arg_empty() const { return arg_end() == arg_begin(); } unsigned arg_size() const { return unsigned(arg_end() - arg_begin()); } @@ -185,6 +193,20 @@ class CallSiteBase { else \ cast(II)->METHOD + unsigned getNumArgOperands() const { + CALLSITE_DELEGATE_GETTER(getNumArgOperands()); + } + + ValTy *getArgOperand(unsigned i) const { + CALLSITE_DELEGATE_GETTER(getArgOperand(i)); + } + + bool isInlineAsm() const { + if (isCall()) + return cast(getInstruction())->isInlineAsm(); + return false; + } + /// getCallingConv/setCallingConv - get or set the calling convention of the /// call. CallingConv::ID getCallingConv() const { @@ -194,6 +216,14 @@ class CallSiteBase { CALLSITE_DELEGATE_SETTER(setCallingConv(CC)); } + FunctionType *getFunctionType() const { + CALLSITE_DELEGATE_GETTER(getFunctionType()); + } + + void mutateFunctionType(FunctionType *Ty) const { + CALLSITE_DELEGATE_SETTER(mutateFunctionType(Ty)); + } + /// getAttributes/setAttributes - get or set the parameter attributes of /// the call. const AttributeSet &getAttributes() const { @@ -223,7 +253,13 @@ class CallSiteBase { uint64_t getDereferenceableBytes(uint16_t i) const { CALLSITE_DELEGATE_GETTER(getDereferenceableBytes(i)); } - + + /// @brief Extract the number of dereferenceable_or_null bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableOrNullBytes(uint16_t i) const { + CALLSITE_DELEGATE_GETTER(getDereferenceableOrNullBytes(i)); + } + /// \brief Return true if the call should not be treated as a call to a /// builtin. bool isNoBuiltin() const { @@ -254,6 +290,15 @@ class CallSiteBase { CALLSITE_DELEGATE_SETTER(setOnlyReadsMemory()); } + /// @brief Determine if the call can access memmory only using pointers based + /// on its arguments. + bool onlyAccessesArgMemory() const { + CALLSITE_DELEGATE_GETTER(onlyAccessesArgMemory()); + } + void setOnlyAccessesArgMemory() { + CALLSITE_DELEGATE_SETTER(setOnlyAccessesArgMemory()); + } + /// @brief Determine if the call cannot return. bool doesNotReturn() const { CALLSITE_DELEGATE_GETTER(doesNotReturn()); @@ -348,8 +393,9 @@ class CallSiteBase { } }; -class CallSite : public CallSiteBase { +class CallSite : public CallSiteBase { public: CallSite() {} CallSite(CallSiteBase B) : CallSiteBase(B) {} diff --git a/include/llvm/IR/CallingConv.h b/include/llvm/IR/CallingConv.h index 9872e6ec794..f7a45afc9ca 100644 --- a/include/llvm/IR/CallingConv.h +++ b/include/llvm/IR/CallingConv.h @@ -69,6 +69,9 @@ namespace CallingConv { // (almost) all registers. PreserveAll = 15, + // Swift - Calling convention for Swift. + Swift = 16, + // Target - This is the start of the target-specific calling conventions, // e.g. fastcall and thiscall on X86. FirstTargetCC = 64, diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h index 75499e0a4db..019b4343a13 100644 --- a/include/llvm/IR/Constant.h +++ b/include/llvm/IR/Constant.h @@ -47,9 +47,6 @@ class Constant : public User { Constant(Type *ty, ValueTy vty, Use *Ops, unsigned NumOps) : User(ty, vty, Ops, NumOps) {} - void destroyConstantImpl(); - void replaceUsesOfWithOnConstantImpl(Constant *Replacement); - public: /// isNullValue - Return true if this is the value that would be returned by /// getNullValue. @@ -126,14 +123,14 @@ class Constant : public User { /// vector of constant integers, all equal, and the common value is returned. const APInt &getUniqueInteger() const; - /// destroyConstant - Called if some element of this constant is no longer - /// valid. At this point only other constants may be on the use_list for this + /// Called if some element of this constant is no longer valid. + /// At this point only other constants may be on the use_list for this /// constant. Any constants on our Use list must also be destroy'd. The /// implementation must be sure to remove the constant from the list of - /// available cached constants. Implementations should call - /// destroyConstantImpl as the last thing they do, to destroy all users and - /// delete this. - virtual void destroyConstant() { llvm_unreachable("Not reached!"); } + /// available cached constants. Implementations should implement + /// destroyConstantImpl to remove constants from any pools/maps they are + /// contained it. + void destroyConstant(); //// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Value *V) { @@ -141,8 +138,8 @@ class Constant : public User { V->getValueID() <= ConstantLastVal; } - /// replaceUsesOfWithOnConstant - This method is a special form of - /// User::replaceUsesOfWith (which does not work on constants) that does work + /// This method is a special form of User::replaceUsesOfWith + /// (which does not work on constants) that does work /// on constants. Basically this method goes through the trouble of building /// a new constant that is equivalent to the current one, with all uses of /// From replaced with uses of To. After this construction is completed, all @@ -151,15 +148,7 @@ class Constant : public User { /// use Value::replaceAllUsesWith, which automatically dispatches to this /// method as needed. /// - virtual void replaceUsesOfWithOnConstant(Value *, Value *, Use *) { - // Provide a default implementation for constants (like integers) that - // cannot use any other values. This cannot be called at runtime, but needs - // to be here to avoid link errors. - assert(getNumOperands() == 0 && "replaceUsesOfWithOnConstant must be " - "implemented for all constants that have operands!"); - llvm_unreachable("Constants that do not have operands cannot be using " - "'From'!"); - } + void handleOperandChange(Value *, Value *, Use *); static Constant *getNullValue(Type* Ty); diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 70437e66cbf..0c7a84fc8bf 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -12,7 +12,7 @@ /// which represent the different flavors of constant values that live in LLVM. /// Note that Constants are immutable (once created they never change) and are /// fully shared by structural equivalence. This means that two structurally -/// equivalent constants will always have the same address. Constant's are +/// equivalent constants will always have the same address. Constants are /// created on demand as needed and never deleted: thus clients don't have to /// worry about the lifetime of the objects. // @@ -50,6 +50,11 @@ class ConstantInt : public Constant { ConstantInt(const ConstantInt &) = delete; ConstantInt(IntegerType *Ty, const APInt& V); APInt Val; + + friend class Constant; + void destroyConstantImpl(); + Value *handleOperandChangeImpl(Value *From, Value *To, Use *U); + protected: // allocate space for exactly zero operands void *operator new(size_t s) { @@ -231,6 +236,11 @@ class ConstantFP : public Constant { void *operator new(size_t, unsigned) = delete; ConstantFP(const ConstantFP &) = delete; friend class LLVMContextImpl; + + friend class Constant; + void destroyConstantImpl(); + Value *handleOperandChangeImpl(Value *From, Value *To, Use *U); + protected: ConstantFP(Type *Ty, const APFloat& V); protected: @@ -251,6 +261,7 @@ class ConstantFP : public Constant { static Constant *get(Type* Ty, double V); static Constant *get(Type* Ty, StringRef Str); static ConstantFP *get(LLVMContext &Context, const APFloat &V); + static Constant *getNaN(Type *Ty, bool Negative = false, unsigned type = 0); static Constant *getNegativeZero(Type *Ty); static Constant *getInfinity(Type *Ty, bool Negative = false); @@ -296,6 +307,11 @@ class ConstantFP : public Constant { class ConstantAggregateZero : public Constant { void *operator new(size_t, unsigned) = delete; ConstantAggregateZero(const ConstantAggregateZero &) = delete; + + friend class Constant; + void destroyConstantImpl(); + Value *handleOperandChangeImpl(Value *From, Value *To, Use *U); + protected: explicit ConstantAggregateZero(Type *ty) : Constant(ty, ConstantAggregateZeroVal, nullptr, 0) {} @@ -307,8 +323,6 @@ class ConstantAggregateZero : public Constant { public: static ConstantAggregateZero *get(Type *Ty); - void destroyConstant() override; - /// getSequentialElement - If this CAZ has array or vector type, return a zero /// with the right element type. Constant *getSequentialElement() const; @@ -342,6 +356,11 @@ class ConstantAggregateZero : public Constant { class ConstantArray : public Constant { friend struct ConstantAggrKeyType; ConstantArray(const ConstantArray &) = delete; + + friend class Constant; + void destroyConstantImpl(); + Value *handleOperandChangeImpl(Value *From, Value *To, Use *U); + protected: ConstantArray(ArrayType *T, ArrayRef Val); public: @@ -362,9 +381,6 @@ class ConstantArray : public Constant { return cast(Value::getType()); } - void destroyConstant() override; - void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) override; - /// Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Value *V) { return V->getValueID() == ConstantArrayVal; @@ -384,6 +400,11 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantArray, Constant) class ConstantStruct : public Constant { friend struct ConstantAggrKeyType; ConstantStruct(const ConstantStruct &) = delete; + + friend class Constant; + void destroyConstantImpl(); + Value *handleOperandChangeImpl(Value *From, Value *To, Use *U); + protected: ConstantStruct(StructType *T, ArrayRef Val); public: @@ -420,9 +441,6 @@ class ConstantStruct : public Constant { return cast(Value::getType()); } - void destroyConstant() override; - void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) override; - /// Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Value *V) { return V->getValueID() == ConstantStructVal; @@ -443,6 +461,11 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantStruct, Constant) class ConstantVector : public Constant { friend struct ConstantAggrKeyType; ConstantVector(const ConstantVector &) = delete; + + friend class Constant; + void destroyConstantImpl(); + Value *handleOperandChangeImpl(Value *From, Value *To, Use *U); + protected: ConstantVector(VectorType *T, ArrayRef Val); public: @@ -471,9 +494,6 @@ class ConstantVector : public Constant { /// elements have the same value, return that value. Otherwise return NULL. Constant *getSplatValue() const; - void destroyConstant() override; - void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) override; - /// Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Value *V) { return V->getValueID() == ConstantVectorVal; @@ -493,6 +513,11 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantVector, Constant) class ConstantPointerNull : public Constant { void *operator new(size_t, unsigned) = delete; ConstantPointerNull(const ConstantPointerNull &) = delete; + + friend class Constant; + void destroyConstantImpl(); + Value *handleOperandChangeImpl(Value *From, Value *To, Use *U); + protected: explicit ConstantPointerNull(PointerType *T) : Constant(T, @@ -507,8 +532,6 @@ class ConstantPointerNull : public Constant { /// get() - Static factory methods - Return objects of the specified value static ConstantPointerNull *get(PointerType *T); - void destroyConstant() override; - /// getType - Specialize the getType() method to always return an PointerType, /// which reduces the amount of casting needed in parts of the compiler. /// @@ -544,6 +567,11 @@ class ConstantDataSequential : public Constant { ConstantDataSequential *Next; void *operator new(size_t, unsigned) = delete; ConstantDataSequential(const ConstantDataSequential &) = delete; + + friend class Constant; + void destroyConstantImpl(); + Value *handleOperandChangeImpl(Value *From, Value *To, Use *U); + protected: explicit ConstantDataSequential(Type *ty, ValueTy VT, const char *Data) : Constant(ty, VT, nullptr, 0), DataElements(Data), Next(nullptr) {} @@ -634,8 +662,6 @@ class ConstantDataSequential : public Constant { /// host endianness of the data elements. StringRef getRawDataValues() const; - void destroyConstant() override; - /// Methods for support type inquiry through isa, cast, and dyn_cast: /// static bool classof(const Value *V) { @@ -777,6 +803,11 @@ class BlockAddress : public Constant { void *operator new(size_t, unsigned) = delete; void *operator new(size_t s) { return User::operator new(s, 2); } BlockAddress(Function *F, BasicBlock *BB); + + friend class Constant; + void destroyConstantImpl(); + Value *handleOperandChangeImpl(Value *From, Value *To, Use *U); + public: /// get - Return a BlockAddress for the specified function and basic block. static BlockAddress *get(Function *F, BasicBlock *BB); @@ -797,9 +828,6 @@ class BlockAddress : public Constant { Function *getFunction() const { return (Function*)Op<0>().get(); } BasicBlock *getBasicBlock() const { return (BasicBlock*)Op<1>().get(); } - void destroyConstant() override; - void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) override; - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Value *V) { return V->getValueID() == BlockAddressVal; @@ -824,6 +852,10 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BlockAddress, Value) class ConstantExpr : public Constant { friend struct ConstantExprKeyType; + friend class Constant; + void destroyConstantImpl(); + Value *handleOperandChangeImpl(Value *From, Value *To, Use *U); + protected: ConstantExpr(Type *ty, unsigned Opcode, Use *Ops, unsigned NumOps) : Constant(ty, ConstantExprVal, Ops, NumOps) { @@ -1054,7 +1086,7 @@ class ConstantExpr : public Constant { bool OnlyIfReduced = false); /// Getelementptr form. Value* is only accepted for convenience; - /// all elements must be Constant's. + /// all elements must be Constants. /// /// \param OnlyIfReducedTy see \a getWithOperands() docs. static Constant *getGetElementPtr(Type *Ty, Constant *C, @@ -1145,8 +1177,9 @@ class ConstantExpr : public Constant { Constant *getWithOperands(ArrayRef Ops, Type *Ty, bool OnlyIfReduced = false) const; - /// getAsInstruction - Returns an Instruction which implements the same operation - /// as this ConstantExpr. The instruction is not linked to any basic block. + /// getAsInstruction - Returns an Instruction which implements the same + /// operation as this ConstantExpr. The instruction is not linked to any basic + /// block. /// /// A better approach to this could be to have a constructor for Instruction /// which would take a ConstantExpr parameter, but that would have spread @@ -1154,9 +1187,6 @@ class ConstantExpr : public Constant { /// would make it harder to remove ConstantExprs altogether. Instruction *getAsInstruction(); - void destroyConstant() override; - void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) override; - /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Value *V) { return V->getValueID() == ConstantExprVal; @@ -1190,6 +1220,11 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantExpr, Constant) class UndefValue : public Constant { void *operator new(size_t, unsigned) = delete; UndefValue(const UndefValue &) = delete; + + friend class Constant; + void destroyConstantImpl(); + Value *handleOperandChangeImpl(Value *From, Value *To, Use *U); + protected: explicit UndefValue(Type *T) : Constant(T, UndefValueVal, nullptr, 0) {} protected: @@ -1222,8 +1257,6 @@ class UndefValue : public Constant { /// \brief Return the number of elements in the array, vector, or struct. unsigned getNumElements() const; - void destroyConstant() override; - /// Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const Value *V) { return V->getValueID() == UndefValueVal; diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h index db876549ca8..8aca266ce77 100644 --- a/include/llvm/IR/DIBuilder.h +++ b/include/llvm/IR/DIBuilder.h @@ -36,14 +36,9 @@ namespace llvm { Module &M; LLVMContext &VMContext; - TempMDTuple TempEnumTypes; - TempMDTuple TempRetainTypes; - TempMDTuple TempSubprograms; - TempMDTuple TempGVs; - TempMDTuple TempImportedModules; - - Function *DeclareFn; // llvm.dbg.declare - Function *ValueFn; // llvm.dbg.value + DICompileUnit *CUNode; ///< The one compile unit created by this DIBuiler. + Function *DeclareFn; ///< llvm.dbg.declare + Function *ValueFn; ///< llvm.dbg.value SmallVector AllEnumTypes; /// Track the RetainTypes, since they can be updated later on. @@ -52,7 +47,7 @@ namespace llvm { SmallVector AllGVs; SmallVector AllImportedModules; - /// \brief Track nodes that may be unresolved. + /// Track nodes that may be unresolved. SmallVector UnresolvedNodes; bool AllowUnresolvedNodes; @@ -62,612 +57,654 @@ namespace llvm { DIBuilder(const DIBuilder &) = delete; void operator=(const DIBuilder &) = delete; - /// \brief Create a temporary. + /// Create a temporary. /// /// Create an \a temporary node and track it in \a UnresolvedNodes. void trackIfUnresolved(MDNode *N); public: - /// \brief Construct a builder for a module. + /// Construct a builder for a module. /// /// If \c AllowUnresolved, collect unresolved nodes attached to the module /// in order to resolve cycles during \a finalize(). explicit DIBuilder(Module &M, bool AllowUnresolved = true); enum DebugEmissionKind { FullDebug=1, LineTablesOnly }; - /// finalize - Construct any deferred debug info descriptors. + /// Construct any deferred debug info descriptors. void finalize(); - /// createCompileUnit - A CompileUnit provides an anchor for all debugging + /// A CompileUnit provides an anchor for all debugging /// information generated during this instance of compilation. - /// @param Lang Source programming language, eg. dwarf::DW_LANG_C99 - /// @param File File name - /// @param Dir Directory - /// @param Producer Identify the producer of debugging information and code. - /// Usually this is a compiler version string. - /// @param isOptimized A boolean flag which indicates whether optimization - /// is ON or not. - /// @param Flags This string lists command line options. This string is - /// directly embedded in debug info output which may be used - /// by a tool analyzing generated debugging information. - /// @param RV This indicates runtime version for languages like - /// Objective-C. - /// @param SplitName The name of the file that we'll split debug info out - /// into. - /// @param Kind The kind of debug information to generate. - /// @param EmitDebugInfo A boolean flag which indicates whether debug - /// information should be written to the final - /// output or not. When this is false, debug - /// information annotations will be present in - /// the IL but they are not written to the final - /// assembly or object file. This supports tracking - /// source location information in the back end - /// without actually changing the output (e.g., - /// when using optimization remarks). - MDCompileUnit *createCompileUnit(unsigned Lang, StringRef File, - StringRef Dir, StringRef Producer, - bool isOptimized, StringRef Flags, - unsigned RV, StringRef SplitName = "", - DebugEmissionKind Kind = FullDebug, - bool EmitDebugInfo = true); - - /// createFile - Create a file descriptor to hold debugging information + /// \param Lang Source programming language, eg. dwarf::DW_LANG_C99 + /// \param File File name + /// \param Dir Directory + /// \param Producer Identify the producer of debugging information + /// and code. Usually this is a compiler + /// version string. + /// \param isOptimized A boolean flag which indicates whether optimization + /// is enabled or not. + /// \param Flags This string lists command line options. This + /// string is directly embedded in debug info + /// output which may be used by a tool + /// analyzing generated debugging information. + /// \param RV This indicates runtime version for languages like + /// Objective-C. + /// \param SplitName The name of the file that we'll split debug info + /// out into. + /// \param Kind The kind of debug information to generate. + /// \param DWOId The DWOId if this is a split skeleton compile unit. + /// \param EmitDebugInfo A boolean flag which indicates whether + /// debug information should be written to + /// the final output or not. When this is + /// false, debug information annotations will + /// be present in the IL but they are not + /// written to the final assembly or object + /// file. This supports tracking source + /// location information in the back end + /// without actually changing the output + /// (e.g., when using optimization remarks). + DICompileUnit * + createCompileUnit(unsigned Lang, StringRef File, StringRef Dir, + StringRef Producer, bool isOptimized, StringRef Flags, + unsigned RV, StringRef SplitName = StringRef(), + DebugEmissionKind Kind = FullDebug, uint64_t DWOId = 0, + bool EmitDebugInfo = true); + + /// Create a file descriptor to hold debugging information /// for a file. - MDFile *createFile(StringRef Filename, StringRef Directory); + DIFile *createFile(StringRef Filename, StringRef Directory); - /// createEnumerator - Create a single enumerator value. - MDEnumerator *createEnumerator(StringRef Name, int64_t Val); + /// Create a single enumerator value. + DIEnumerator *createEnumerator(StringRef Name, int64_t Val); - /// \brief Create a DWARF unspecified type. - MDBasicType *createUnspecifiedType(StringRef Name); + /// Create a DWARF unspecified type. + DIBasicType *createUnspecifiedType(StringRef Name); - /// \brief Create C++11 nullptr type. - MDBasicType *createNullPtrType(); + /// Create C++11 nullptr type. + DIBasicType *createNullPtrType(); - /// createBasicType - Create debugging information entry for a basic + /// Create debugging information entry for a basic /// type. - /// @param Name Type name. - /// @param SizeInBits Size of the type. - /// @param AlignInBits Type alignment. - /// @param Encoding DWARF encoding code, e.g. dwarf::DW_ATE_float. - MDBasicType *createBasicType(StringRef Name, uint64_t SizeInBits, + /// \param Name Type name. + /// \param SizeInBits Size of the type. + /// \param AlignInBits Type alignment. + /// \param Encoding DWARF encoding code, e.g. dwarf::DW_ATE_float. + DIBasicType *createBasicType(StringRef Name, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding); - /// createQualifiedType - Create debugging information entry for a qualified + /// Create debugging information entry for a qualified /// type, e.g. 'const int'. - /// @param Tag Tag identifing type, e.g. dwarf::TAG_volatile_type - /// @param FromTy Base Type. - MDDerivedType *createQualifiedType(unsigned Tag, MDType *FromTy); - - /// createPointerType - Create debugging information entry for a pointer. - /// @param PointeeTy Type pointed by this pointer. - /// @param SizeInBits Size. - /// @param AlignInBits Alignment. (optional) - /// @param Name Pointer type name. (optional) - MDDerivedType *createPointerType(MDType *PointeeTy, uint64_t SizeInBits, + /// \param Tag Tag identifing type, e.g. dwarf::TAG_volatile_type + /// \param FromTy Base Type. + DIDerivedType *createQualifiedType(unsigned Tag, DIType *FromTy); + + /// Create debugging information entry for a pointer. + /// \param PointeeTy Type pointed by this pointer. + /// \param SizeInBits Size. + /// \param AlignInBits Alignment. (optional) + /// \param Name Pointer type name. (optional) + DIDerivedType *createPointerType(DIType *PointeeTy, uint64_t SizeInBits, uint64_t AlignInBits = 0, StringRef Name = ""); - /// \brief Create debugging information entry for a pointer to member. - /// @param PointeeTy Type pointed to by this pointer. - /// @param SizeInBits Size. - /// @param AlignInBits Alignment. (optional) - /// @param Class Type for which this pointer points to members of. - MDDerivedType *createMemberPointerType(MDType *PointeeTy, MDType *Class, + /// Create debugging information entry for a pointer to member. + /// \param PointeeTy Type pointed to by this pointer. + /// \param SizeInBits Size. + /// \param AlignInBits Alignment. (optional) + /// \param Class Type for which this pointer points to members of. + DIDerivedType *createMemberPointerType(DIType *PointeeTy, DIType *Class, uint64_t SizeInBits, uint64_t AlignInBits = 0); - /// createReferenceType - Create debugging information entry for a c++ + /// Create debugging information entry for a c++ /// style reference or rvalue reference type. - MDDerivedType *createReferenceType(unsigned Tag, MDType *RTy); + DIDerivedType *createReferenceType(unsigned Tag, DIType *RTy); - /// createTypedef - Create debugging information entry for a typedef. - /// @param Ty Original type. - /// @param Name Typedef name. - /// @param File File where this type is defined. - /// @param LineNo Line number. - /// @param Context The surrounding context for the typedef. - MDDerivedType *createTypedef(MDType *Ty, StringRef Name, MDFile *File, - unsigned LineNo, MDScope *Context); + /// Create debugging information entry for a typedef. + /// \param Ty Original type. + /// \param Name Typedef name. + /// \param File File where this type is defined. + /// \param LineNo Line number. + /// \param Context The surrounding context for the typedef. + DIDerivedType *createTypedef(DIType *Ty, StringRef Name, DIFile *File, + unsigned LineNo, DIScope *Context); - /// createFriend - Create debugging information entry for a 'friend'. - MDDerivedType *createFriend(MDType *Ty, MDType *FriendTy); + /// Create debugging information entry for a 'friend'. + DIDerivedType *createFriend(DIType *Ty, DIType *FriendTy); - /// createInheritance - Create debugging information entry to establish + /// Create debugging information entry to establish /// inheritance relationship between two types. - /// @param Ty Original type. - /// @param BaseTy Base type. Ty is inherits from base. - /// @param BaseOffset Base offset. - /// @param Flags Flags to describe inheritance attribute, + /// \param Ty Original type. + /// \param BaseTy Base type. Ty is inherits from base. + /// \param BaseOffset Base offset. + /// \param Flags Flags to describe inheritance attribute, /// e.g. private - MDDerivedType *createInheritance(MDType *Ty, MDType *BaseTy, + DIDerivedType *createInheritance(DIType *Ty, DIType *BaseTy, uint64_t BaseOffset, unsigned Flags); - /// createMemberType - Create debugging information entry for a member. - /// @param Scope Member scope. - /// @param Name Member name. - /// @param File File where this member is defined. - /// @param LineNo Line number. - /// @param SizeInBits Member size. - /// @param AlignInBits Member alignment. - /// @param OffsetInBits Member offset. - /// @param Flags Flags to encode member attribute, e.g. private - /// @param Ty Parent type. - MDDerivedType *createMemberType(MDScope *Scope, StringRef Name, - MDFile *File, unsigned LineNo, + /// Create debugging information entry for a member. + /// \param Scope Member scope. + /// \param Name Member name. + /// \param File File where this member is defined. + /// \param LineNo Line number. + /// \param SizeInBits Member size. + /// \param AlignInBits Member alignment. + /// \param OffsetInBits Member offset. + /// \param Flags Flags to encode member attribute, e.g. private + /// \param Ty Parent type. + DIDerivedType *createMemberType(DIScope *Scope, StringRef Name, + DIFile *File, unsigned LineNo, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, - MDType *Ty); + DIType *Ty); - /// createStaticMemberType - Create debugging information entry for a + /// Create debugging information entry for a /// C++ static data member. - /// @param Scope Member scope. - /// @param Name Member name. - /// @param File File where this member is declared. - /// @param LineNo Line number. - /// @param Ty Type of the static member. - /// @param Flags Flags to encode member attribute, e.g. private. - /// @param Val Const initializer of the member. - MDDerivedType *createStaticMemberType(MDScope *Scope, StringRef Name, - MDFile *File, unsigned LineNo, - MDType *Ty, unsigned Flags, + /// \param Scope Member scope. + /// \param Name Member name. + /// \param File File where this member is declared. + /// \param LineNo Line number. + /// \param Ty Type of the static member. + /// \param Flags Flags to encode member attribute, e.g. private. + /// \param Val Const initializer of the member. + DIDerivedType *createStaticMemberType(DIScope *Scope, StringRef Name, + DIFile *File, unsigned LineNo, + DIType *Ty, unsigned Flags, llvm::Constant *Val); - /// createObjCIVar - Create debugging information entry for Objective-C + /// Create debugging information entry for Objective-C /// instance variable. - /// @param Name Member name. - /// @param File File where this member is defined. - /// @param LineNo Line number. - /// @param SizeInBits Member size. - /// @param AlignInBits Member alignment. - /// @param OffsetInBits Member offset. - /// @param Flags Flags to encode member attribute, e.g. private - /// @param Ty Parent type. - /// @param PropertyNode Property associated with this ivar. - MDDerivedType *createObjCIVar(StringRef Name, MDFile *File, unsigned LineNo, + /// \param Name Member name. + /// \param File File where this member is defined. + /// \param LineNo Line number. + /// \param SizeInBits Member size. + /// \param AlignInBits Member alignment. + /// \param OffsetInBits Member offset. + /// \param Flags Flags to encode member attribute, e.g. private + /// \param Ty Parent type. + /// \param PropertyNode Property associated with this ivar. + DIDerivedType *createObjCIVar(StringRef Name, DIFile *File, unsigned LineNo, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, - MDType *Ty, MDNode *PropertyNode); + DIType *Ty, MDNode *PropertyNode); - /// createObjCProperty - Create debugging information entry for Objective-C + /// Create debugging information entry for Objective-C /// property. - /// @param Name Property name. - /// @param File File where this property is defined. - /// @param LineNumber Line number. - /// @param GetterName Name of the Objective C property getter selector. - /// @param SetterName Name of the Objective C property setter selector. - /// @param PropertyAttributes Objective C property attributes. - /// @param Ty Type. - MDObjCProperty *createObjCProperty(StringRef Name, MDFile *File, + /// \param Name Property name. + /// \param File File where this property is defined. + /// \param LineNumber Line number. + /// \param GetterName Name of the Objective C property getter selector. + /// \param SetterName Name of the Objective C property setter selector. + /// \param PropertyAttributes Objective C property attributes. + /// \param Ty Type. + DIObjCProperty *createObjCProperty(StringRef Name, DIFile *File, unsigned LineNumber, StringRef GetterName, StringRef SetterName, - unsigned PropertyAttributes, MDType *Ty); - - /// createClassType - Create debugging information entry for a class. - /// @param Scope Scope in which this class is defined. - /// @param Name class name. - /// @param File File where this member is defined. - /// @param LineNumber Line number. - /// @param SizeInBits Member size. - /// @param AlignInBits Member alignment. - /// @param OffsetInBits Member offset. - /// @param Flags Flags to encode member attribute, e.g. private - /// @param Elements class members. - /// @param VTableHolder Debug info of the base class that contains vtable + unsigned PropertyAttributes, DIType *Ty); + + /// Create debugging information entry for a class. + /// \param Scope Scope in which this class is defined. + /// \param Name class name. + /// \param File File where this member is defined. + /// \param LineNumber Line number. + /// \param SizeInBits Member size. + /// \param AlignInBits Member alignment. + /// \param OffsetInBits Member offset. + /// \param Flags Flags to encode member attribute, e.g. private + /// \param Elements class members. + /// \param VTableHolder Debug info of the base class that contains vtable /// for this type. This is used in /// DW_AT_containing_type. See DWARF documentation /// for more info. - /// @param TemplateParms Template type parameters. - /// @param UniqueIdentifier A unique identifier for the class. - MDCompositeType *createClassType(MDScope *Scope, StringRef Name, - MDFile *File, unsigned LineNumber, + /// \param TemplateParms Template type parameters. + /// \param UniqueIdentifier A unique identifier for the class. + DICompositeType *createClassType(DIScope *Scope, StringRef Name, + DIFile *File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, - MDType *DerivedFrom, DIArray Elements, - MDType *VTableHolder = nullptr, + DIType *DerivedFrom, DINodeArray Elements, + DIType *VTableHolder = nullptr, MDNode *TemplateParms = nullptr, StringRef UniqueIdentifier = ""); - /// createStructType - Create debugging information entry for a struct. - /// @param Scope Scope in which this struct is defined. - /// @param Name Struct name. - /// @param File File where this member is defined. - /// @param LineNumber Line number. - /// @param SizeInBits Member size. - /// @param AlignInBits Member alignment. - /// @param Flags Flags to encode member attribute, e.g. private - /// @param Elements Struct elements. - /// @param RunTimeLang Optional parameter, Objective-C runtime version. - /// @param UniqueIdentifier A unique identifier for the struct. - MDCompositeType *createStructType( - MDScope *Scope, StringRef Name, MDFile *File, unsigned LineNumber, + /// Create debugging information entry for a struct. + /// \param Scope Scope in which this struct is defined. + /// \param Name Struct name. + /// \param File File where this member is defined. + /// \param LineNumber Line number. + /// \param SizeInBits Member size. + /// \param AlignInBits Member alignment. + /// \param Flags Flags to encode member attribute, e.g. private + /// \param Elements Struct elements. + /// \param RunTimeLang Optional parameter, Objective-C runtime version. + /// \param UniqueIdentifier A unique identifier for the struct. + DICompositeType *createStructType( + DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, - MDType *DerivedFrom, DIArray Elements, unsigned RunTimeLang = 0, - MDType *VTableHolder = nullptr, StringRef UniqueIdentifier = ""); - - /// createUnionType - Create debugging information entry for an union. - /// @param Scope Scope in which this union is defined. - /// @param Name Union name. - /// @param File File where this member is defined. - /// @param LineNumber Line number. - /// @param SizeInBits Member size. - /// @param AlignInBits Member alignment. - /// @param Flags Flags to encode member attribute, e.g. private - /// @param Elements Union elements. - /// @param RunTimeLang Optional parameter, Objective-C runtime version. - /// @param UniqueIdentifier A unique identifier for the union. - MDCompositeType *createUnionType(MDScope *Scope, StringRef Name, - MDFile *File, unsigned LineNumber, + DIType *DerivedFrom, DINodeArray Elements, unsigned RunTimeLang = 0, + DIType *VTableHolder = nullptr, StringRef UniqueIdentifier = ""); + + /// Create debugging information entry for an union. + /// \param Scope Scope in which this union is defined. + /// \param Name Union name. + /// \param File File where this member is defined. + /// \param LineNumber Line number. + /// \param SizeInBits Member size. + /// \param AlignInBits Member alignment. + /// \param Flags Flags to encode member attribute, e.g. private + /// \param Elements Union elements. + /// \param RunTimeLang Optional parameter, Objective-C runtime version. + /// \param UniqueIdentifier A unique identifier for the union. + DICompositeType *createUnionType(DIScope *Scope, StringRef Name, + DIFile *File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, - unsigned Flags, DIArray Elements, + unsigned Flags, DINodeArray Elements, unsigned RunTimeLang = 0, StringRef UniqueIdentifier = ""); - /// createTemplateTypeParameter - Create debugging information for template + /// Create debugging information for template /// type parameter. - /// @param Scope Scope in which this type is defined. - /// @param Name Type parameter name. - /// @param Ty Parameter type. - MDTemplateTypeParameter * - createTemplateTypeParameter(MDScope *Scope, StringRef Name, MDType *Ty); + /// \param Scope Scope in which this type is defined. + /// \param Name Type parameter name. + /// \param Ty Parameter type. + DITemplateTypeParameter * + createTemplateTypeParameter(DIScope *Scope, StringRef Name, DIType *Ty); - /// createTemplateValueParameter - Create debugging information for template + /// Create debugging information for template /// value parameter. - /// @param Scope Scope in which this type is defined. - /// @param Name Value parameter name. - /// @param Ty Parameter type. - /// @param Val Constant parameter value. - MDTemplateValueParameter *createTemplateValueParameter(MDScope *Scope, + /// \param Scope Scope in which this type is defined. + /// \param Name Value parameter name. + /// \param Ty Parameter type. + /// \param Val Constant parameter value. + DITemplateValueParameter *createTemplateValueParameter(DIScope *Scope, StringRef Name, - MDType *Ty, + DIType *Ty, Constant *Val); - /// \brief Create debugging information for a template template parameter. - /// @param Scope Scope in which this type is defined. - /// @param Name Value parameter name. - /// @param Ty Parameter type. - /// @param Val The fully qualified name of the template. - MDTemplateValueParameter *createTemplateTemplateParameter(MDScope *Scope, + /// Create debugging information for a template template parameter. + /// \param Scope Scope in which this type is defined. + /// \param Name Value parameter name. + /// \param Ty Parameter type. + /// \param Val The fully qualified name of the template. + DITemplateValueParameter *createTemplateTemplateParameter(DIScope *Scope, StringRef Name, - MDType *Ty, + DIType *Ty, StringRef Val); - /// \brief Create debugging information for a template parameter pack. - /// @param Scope Scope in which this type is defined. - /// @param Name Value parameter name. - /// @param Ty Parameter type. - /// @param Val An array of types in the pack. - MDTemplateValueParameter *createTemplateParameterPack(MDScope *Scope, + /// Create debugging information for a template parameter pack. + /// \param Scope Scope in which this type is defined. + /// \param Name Value parameter name. + /// \param Ty Parameter type. + /// \param Val An array of types in the pack. + DITemplateValueParameter *createTemplateParameterPack(DIScope *Scope, StringRef Name, - MDType *Ty, - DIArray Val); - - /// createArrayType - Create debugging information entry for an array. - /// @param Size Array size. - /// @param AlignInBits Alignment. - /// @param Ty Element type. - /// @param Subscripts Subscripts. - MDCompositeType *createArrayType(uint64_t Size, uint64_t AlignInBits, - MDType *Ty, DIArray Subscripts); - - /// createVectorType - Create debugging information entry for a vector type. - /// @param Size Array size. - /// @param AlignInBits Alignment. - /// @param Ty Element type. - /// @param Subscripts Subscripts. - MDCompositeType *createVectorType(uint64_t Size, uint64_t AlignInBits, - MDType *Ty, DIArray Subscripts); - - /// createEnumerationType - Create debugging information entry for an + DIType *Ty, + DINodeArray Val); + + /// Create debugging information entry for an array. + /// \param Size Array size. + /// \param AlignInBits Alignment. + /// \param Ty Element type. + /// \param Subscripts Subscripts. + DICompositeType *createArrayType(uint64_t Size, uint64_t AlignInBits, + DIType *Ty, DINodeArray Subscripts); + + /// Create debugging information entry for a vector type. + /// \param Size Array size. + /// \param AlignInBits Alignment. + /// \param Ty Element type. + /// \param Subscripts Subscripts. + DICompositeType *createVectorType(uint64_t Size, uint64_t AlignInBits, + DIType *Ty, DINodeArray Subscripts); + + /// Create debugging information entry for an /// enumeration. - /// @param Scope Scope in which this enumeration is defined. - /// @param Name Union name. - /// @param File File where this member is defined. - /// @param LineNumber Line number. - /// @param SizeInBits Member size. - /// @param AlignInBits Member alignment. - /// @param Elements Enumeration elements. - /// @param UnderlyingType Underlying type of a C++11/ObjC fixed enum. - /// @param UniqueIdentifier A unique identifier for the enum. - MDCompositeType *createEnumerationType( - MDScope *Scope, StringRef Name, MDFile *File, unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, DIArray Elements, - MDType *UnderlyingType, StringRef UniqueIdentifier = ""); - - /// createSubroutineType - Create subroutine type. - /// @param File File in which this subroutine is defined. - /// @param ParameterTypes An array of subroutine parameter types. This + /// \param Scope Scope in which this enumeration is defined. + /// \param Name Union name. + /// \param File File where this member is defined. + /// \param LineNumber Line number. + /// \param SizeInBits Member size. + /// \param AlignInBits Member alignment. + /// \param Elements Enumeration elements. + /// \param UnderlyingType Underlying type of a C++11/ObjC fixed enum. + /// \param UniqueIdentifier A unique identifier for the enum. + DICompositeType *createEnumerationType( + DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, DINodeArray Elements, + DIType *UnderlyingType, StringRef UniqueIdentifier = ""); + + /// Create subroutine type. + /// \param File File in which this subroutine is defined. + /// \param ParameterTypes An array of subroutine parameter types. This /// includes return type at 0th index. - /// @param Flags E.g.: LValueReference. + /// \param Flags E.g.: LValueReference. /// These flags are used to emit dwarf attributes. - MDSubroutineType *createSubroutineType(MDFile *File, - DITypeArray ParameterTypes, + DISubroutineType *createSubroutineType(DIFile *File, + DITypeRefArray ParameterTypes, unsigned Flags = 0); - /// createArtificialType - Create a new MDType* with "artificial" flag set. - MDType *createArtificialType(MDType *Ty); + /// Create an external type reference. + /// \param Tag Dwarf TAG. + /// \param File File in which the type is defined. + /// \param UniqueIdentifier A unique identifier for the type. + DICompositeType *createExternalTypeRef(unsigned Tag, DIFile *File, + StringRef UniqueIdentifier); + + /// Create a new DIType* with "artificial" flag set. + DIType *createArtificialType(DIType *Ty); - /// createObjectPointerType - Create a new MDType* with the "object pointer" + /// Create a new DIType* with the "object pointer" /// flag set. - MDType *createObjectPointerType(MDType *Ty); + DIType *createObjectPointerType(DIType *Ty); - /// \brief Create a permanent forward-declared type. - MDCompositeType *createForwardDecl(unsigned Tag, StringRef Name, - MDScope *Scope, MDFile *F, unsigned Line, + /// Create a permanent forward-declared type. + DICompositeType *createForwardDecl(unsigned Tag, StringRef Name, + DIScope *Scope, DIFile *F, unsigned Line, unsigned RuntimeLang = 0, uint64_t SizeInBits = 0, uint64_t AlignInBits = 0, StringRef UniqueIdentifier = ""); - /// \brief Create a temporary forward-declared type. - MDCompositeType *createReplaceableCompositeType( - unsigned Tag, StringRef Name, MDScope *Scope, MDFile *F, unsigned Line, + /// Create a temporary forward-declared type. + DICompositeType *createReplaceableCompositeType( + unsigned Tag, StringRef Name, DIScope *Scope, DIFile *F, unsigned Line, unsigned RuntimeLang = 0, uint64_t SizeInBits = 0, - uint64_t AlignInBits = 0, unsigned Flags = DebugNode::FlagFwdDecl, + uint64_t AlignInBits = 0, unsigned Flags = DINode::FlagFwdDecl, StringRef UniqueIdentifier = ""); - /// retainType - Retain MDType* in a module even if it is not referenced + /// Retain DIType* in a module even if it is not referenced /// through debug info anchors. - void retainType(MDType *T); + void retainType(DIType *T); - /// createUnspecifiedParameter - Create unspecified parameter type + /// Create unspecified parameter type /// for a subroutine type. - MDBasicType *createUnspecifiedParameter(); + DIBasicType *createUnspecifiedParameter(); - /// getOrCreateArray - Get a DIArray, create one if required. - DIArray getOrCreateArray(ArrayRef Elements); + /// Get a DINodeArray, create one if required. + DINodeArray getOrCreateArray(ArrayRef Elements); - /// getOrCreateTypeArray - Get a DITypeArray, create one if required. - DITypeArray getOrCreateTypeArray(ArrayRef Elements); + /// Get a DITypeRefArray, create one if required. + DITypeRefArray getOrCreateTypeArray(ArrayRef Elements); - /// getOrCreateSubrange - Create a descriptor for a value range. This + /// Create a descriptor for a value range. This /// implicitly uniques the values returned. - MDSubrange *getOrCreateSubrange(int64_t Lo, int64_t Count); + DISubrange *getOrCreateSubrange(int64_t Lo, int64_t Count); - /// createGlobalVariable - Create a new descriptor for the specified + /// Create a new descriptor for the specified /// variable. - /// @param Context Variable scope. - /// @param Name Name of the variable. - /// @param LinkageName Mangled name of the variable. - /// @param File File where this variable is defined. - /// @param LineNo Line number. - /// @param Ty Variable Type. - /// @param isLocalToUnit Boolean flag indicate whether this variable is + /// \param Context Variable scope. + /// \param Name Name of the variable. + /// \param LinkageName Mangled name of the variable. + /// \param File File where this variable is defined. + /// \param LineNo Line number. + /// \param Ty Variable Type. + /// \param isLocalToUnit Boolean flag indicate whether this variable is /// externally visible or not. - /// @param Val llvm::Value of the variable. - /// @param Decl Reference to the corresponding declaration. - MDGlobalVariable *createGlobalVariable(MDScope *Context, StringRef Name, - StringRef LinkageName, MDFile *File, - unsigned LineNo, MDType *Ty, + /// \param Val llvm::Value of the variable. + /// \param Decl Reference to the corresponding declaration. + DIGlobalVariable *createGlobalVariable(DIScope *Context, StringRef Name, + StringRef LinkageName, DIFile *File, + unsigned LineNo, DIType *Ty, bool isLocalToUnit, llvm::Constant *Val, MDNode *Decl = nullptr); - /// createTempGlobalVariableFwdDecl - Identical to createGlobalVariable + /// Identical to createGlobalVariable /// except that the resulting DbgNode is temporary and meant to be RAUWed. - MDGlobalVariable *createTempGlobalVariableFwdDecl( - MDScope *Context, StringRef Name, StringRef LinkageName, MDFile *File, - unsigned LineNo, MDType *Ty, bool isLocalToUnit, llvm::Constant *Val, + DIGlobalVariable *createTempGlobalVariableFwdDecl( + DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *File, + unsigned LineNo, DIType *Ty, bool isLocalToUnit, llvm::Constant *Val, MDNode *Decl = nullptr); - /// createLocalVariable - Create a new descriptor for the specified - /// local variable. - /// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or - /// DW_TAG_arg_variable. - /// @param Scope Variable scope. - /// @param Name Variable name. - /// @param File File where this variable is defined. - /// @param LineNo Line number. - /// @param Ty Variable Type - /// @param AlwaysPreserve Boolean. Set to true if debug info for this - /// variable should be preserved in optimized build. - /// @param Flags Flags, e.g. artificial variable. - /// @param ArgNo If this variable is an argument then this argument's - /// number. 1 indicates 1st argument. - MDLocalVariable *createLocalVariable(unsigned Tag, MDScope *Scope, - StringRef Name, MDFile *File, - unsigned LineNo, MDType *Ty, + /// Create a new descriptor for an auto variable. This is a local variable + /// that is not a subprogram parameter. + /// + /// \c Scope must be a \a DILocalScope, and thus its scope chain eventually + /// leads to a \a DISubprogram. + /// + /// If \c AlwaysPreserve, this variable will be referenced from its + /// containing subprogram, and will survive some optimizations. + DILocalVariable *createAutoVariable(DIScope *Scope, StringRef Name, + DIFile *File, unsigned LineNo, + DIType *Ty, bool AlwaysPreserve = false, - unsigned Flags = 0, - unsigned ArgNo = 0); + unsigned Flags = 0); - /// createExpression - Create a new descriptor for the specified + /// Create a new descriptor for a parameter variable. + /// + /// \c Scope must be a \a DILocalScope, and thus its scope chain eventually + /// leads to a \a DISubprogram. + /// + /// \c ArgNo is the index (starting from \c 1) of this variable in the + /// subprogram parameters. \c ArgNo should not conflict with other + /// parameters of the same subprogram. + /// + /// If \c AlwaysPreserve, this variable will be referenced from its + /// containing subprogram, and will survive some optimizations. + DILocalVariable *createParameterVariable(DIScope *Scope, StringRef Name, + unsigned ArgNo, DIFile *File, + unsigned LineNo, DIType *Ty, + bool AlwaysPreserve = false, + unsigned Flags = 0); + + /// Create a new descriptor for the specified /// variable which has a complex address expression for its address. - /// @param Addr An array of complex address operations. - MDExpression *createExpression(ArrayRef Addr = None); - MDExpression *createExpression(ArrayRef Addr); + /// \param Addr An array of complex address operations. + DIExpression *createExpression(ArrayRef Addr = None); + DIExpression *createExpression(ArrayRef Addr); - /// createBitPieceExpression - Create a descriptor to describe one part + /// Create a descriptor to describe one part /// of aggregate variable that is fragmented across multiple Values. /// - /// @param OffsetInBits Offset of the piece in bits. - /// @param SizeInBits Size of the piece in bits. - MDExpression *createBitPieceExpression(unsigned OffsetInBits, + /// \param OffsetInBits Offset of the piece in bits. + /// \param SizeInBits Size of the piece in bits. + DIExpression *createBitPieceExpression(unsigned OffsetInBits, unsigned SizeInBits); - /// createFunction - Create a new descriptor for the specified subprogram. - /// See comments in MDSubprogram* for descriptions of these fields. - /// @param Scope Function scope. - /// @param Name Function name. - /// @param LinkageName Mangled function name. - /// @param File File where this variable is defined. - /// @param LineNo Line number. - /// @param Ty Function type. - /// @param isLocalToUnit True if this function is not externally visible. - /// @param isDefinition True if this is a function definition. - /// @param ScopeLine Set to the beginning of the scope this starts - /// @param Flags e.g. is this function prototyped or not. + /// Create a new descriptor for the specified subprogram. + /// See comments in DISubprogram* for descriptions of these fields. + /// \param Scope Function scope. + /// \param Name Function name. + /// \param LinkageName Mangled function name. + /// \param File File where this variable is defined. + /// \param LineNo Line number. + /// \param Ty Function type. + /// \param isLocalToUnit True if this function is not externally visible. + /// \param isDefinition True if this is a function definition. + /// \param ScopeLine Set to the beginning of the scope this starts + /// \param Flags e.g. is this function prototyped or not. /// These flags are used to emit dwarf attributes. - /// @param isOptimized True if optimization is ON. - /// @param Fn llvm::Function pointer. - /// @param TParam Function template parameters. - MDSubprogram * - createFunction(MDScope *Scope, StringRef Name, StringRef LinkageName, - MDFile *File, unsigned LineNo, MDSubroutineType *Ty, + /// \param isOptimized True if optimization is ON. + /// \param Fn llvm::Function pointer. + /// \param TParam Function template parameters. + DISubprogram * + createFunction(DIScope *Scope, StringRef Name, StringRef LinkageName, + DIFile *File, unsigned LineNo, DISubroutineType *Ty, bool isLocalToUnit, bool isDefinition, unsigned ScopeLine, unsigned Flags = 0, bool isOptimized = false, Function *Fn = nullptr, MDNode *TParam = nullptr, MDNode *Decl = nullptr); - /// createTempFunctionFwdDecl - Identical to createFunction, + /// Identical to createFunction, /// except that the resulting DbgNode is meant to be RAUWed. - MDSubprogram *createTempFunctionFwdDecl( - MDScope *Scope, StringRef Name, StringRef LinkageName, MDFile *File, - unsigned LineNo, MDSubroutineType *Ty, bool isLocalToUnit, + DISubprogram *createTempFunctionFwdDecl( + DIScope *Scope, StringRef Name, StringRef LinkageName, DIFile *File, + unsigned LineNo, DISubroutineType *Ty, bool isLocalToUnit, bool isDefinition, unsigned ScopeLine, unsigned Flags = 0, bool isOptimized = false, Function *Fn = nullptr, MDNode *TParam = nullptr, MDNode *Decl = nullptr); /// FIXME: this is added for dragonegg. Once we update dragonegg /// to call resolve function, this will be removed. - MDSubprogram * + DISubprogram * createFunction(DIScopeRef Scope, StringRef Name, StringRef LinkageName, - MDFile *File, unsigned LineNo, MDSubroutineType *Ty, + DIFile *File, unsigned LineNo, DISubroutineType *Ty, bool isLocalToUnit, bool isDefinition, unsigned ScopeLine, unsigned Flags = 0, bool isOptimized = false, Function *Fn = nullptr, MDNode *TParam = nullptr, MDNode *Decl = nullptr); - /// createMethod - Create a new descriptor for the specified C++ method. - /// See comments in MDSubprogram* for descriptions of these fields. - /// @param Scope Function scope. - /// @param Name Function name. - /// @param LinkageName Mangled function name. - /// @param File File where this variable is defined. - /// @param LineNo Line number. - /// @param Ty Function type. - /// @param isLocalToUnit True if this function is not externally visible.. - /// @param isDefinition True if this is a function definition. - /// @param Virtuality Attributes describing virtualness. e.g. pure + /// Create a new descriptor for the specified C++ method. + /// See comments in \a DISubprogram* for descriptions of these fields. + /// \param Scope Function scope. + /// \param Name Function name. + /// \param LinkageName Mangled function name. + /// \param File File where this variable is defined. + /// \param LineNo Line number. + /// \param Ty Function type. + /// \param isLocalToUnit True if this function is not externally visible.. + /// \param isDefinition True if this is a function definition. + /// \param Virtuality Attributes describing virtualness. e.g. pure /// virtual function. - /// @param VTableIndex Index no of this method in virtual table. - /// @param VTableHolder Type that holds vtable. - /// @param Flags e.g. is this function prototyped or not. + /// \param VTableIndex Index no of this method in virtual table. + /// \param VTableHolder Type that holds vtable. + /// \param Flags e.g. is this function prototyped or not. /// This flags are used to emit dwarf attributes. - /// @param isOptimized True if optimization is ON. - /// @param Fn llvm::Function pointer. - /// @param TParam Function template parameters. - MDSubprogram * - createMethod(MDScope *Scope, StringRef Name, StringRef LinkageName, - MDFile *File, unsigned LineNo, MDSubroutineType *Ty, + /// \param isOptimized True if optimization is ON. + /// \param Fn llvm::Function pointer. + /// \param TParam Function template parameters. + DISubprogram * + createMethod(DIScope *Scope, StringRef Name, StringRef LinkageName, + DIFile *File, unsigned LineNo, DISubroutineType *Ty, bool isLocalToUnit, bool isDefinition, unsigned Virtuality = 0, - unsigned VTableIndex = 0, MDType *VTableHolder = nullptr, + unsigned VTableIndex = 0, DIType *VTableHolder = nullptr, unsigned Flags = 0, bool isOptimized = false, Function *Fn = nullptr, MDNode *TParam = nullptr); - /// createNameSpace - This creates new descriptor for a namespace - /// with the specified parent scope. - /// @param Scope Namespace scope - /// @param Name Name of this namespace - /// @param File Source file - /// @param LineNo Line number - MDNamespace *createNameSpace(MDScope *Scope, StringRef Name, MDFile *File, + /// This creates new descriptor for a namespace with the specified + /// parent scope. + /// \param Scope Namespace scope + /// \param Name Name of this namespace + /// \param File Source file + /// \param LineNo Line number + DINamespace *createNameSpace(DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNo); - /// createLexicalBlockFile - This creates a descriptor for a lexical - /// block with a new file attached. This merely extends the existing + /// This creates new descriptor for a module with the specified + /// parent scope. + /// \param Scope Parent scope + /// \param Name Name of this module + /// \param ConfigurationMacros + /// A space-separated shell-quoted list of -D macro + /// definitions as they would appear on a command line. + /// \param IncludePath The path to the module map file. + /// \param ISysRoot The clang system root (value of -isysroot). + DIModule *createModule(DIScope *Scope, StringRef Name, + StringRef ConfigurationMacros, + StringRef IncludePath, + StringRef ISysRoot); + + /// This creates a descriptor for a lexical block with a new file + /// attached. This merely extends the existing /// lexical block as it crosses a file. - /// @param Scope Lexical block. - /// @param File Source file. - /// @param Discriminator DWARF path discriminator value. - MDLexicalBlockFile *createLexicalBlockFile(MDScope *Scope, MDFile *File, + /// \param Scope Lexical block. + /// \param File Source file. + /// \param Discriminator DWARF path discriminator value. + DILexicalBlockFile *createLexicalBlockFile(DIScope *Scope, DIFile *File, unsigned Discriminator = 0); - /// createLexicalBlock - This creates a descriptor for a lexical block - /// with the specified parent context. - /// @param Scope Parent lexical scope. - /// @param File Source file. - /// @param Line Line number. - /// @param Col Column number. - MDLexicalBlock *createLexicalBlock(MDScope *Scope, MDFile *File, + /// This creates a descriptor for a lexical block with the + /// specified parent context. + /// \param Scope Parent lexical scope. + /// \param File Source file. + /// \param Line Line number. + /// \param Col Column number. + DILexicalBlock *createLexicalBlock(DIScope *Scope, DIFile *File, unsigned Line, unsigned Col); - /// \brief Create a descriptor for an imported module. - /// @param Context The scope this module is imported into - /// @param NS The namespace being imported here - /// @param Line Line number - MDImportedEntity *createImportedModule(MDScope *Context, MDNamespace *NS, + /// Create a descriptor for an imported module. + /// \param Context The scope this module is imported into + /// \param NS The namespace being imported here + /// \param Line Line number + DIImportedEntity *createImportedModule(DIScope *Context, DINamespace *NS, unsigned Line); - /// \brief Create a descriptor for an imported module. - /// @param Context The scope this module is imported into - /// @param NS An aliased namespace - /// @param Line Line number - MDImportedEntity *createImportedModule(MDScope *Context, - MDImportedEntity *NS, unsigned Line); + /// Create a descriptor for an imported module. + /// \param Context The scope this module is imported into + /// \param NS An aliased namespace + /// \param Line Line number + DIImportedEntity *createImportedModule(DIScope *Context, + DIImportedEntity *NS, unsigned Line); + + /// Create a descriptor for an imported module. + /// \param Context The scope this module is imported into + /// \param M The module being imported here + /// \param Line Line number + DIImportedEntity *createImportedModule(DIScope *Context, DIModule *M, + unsigned Line); - /// \brief Create a descriptor for an imported function. - /// @param Context The scope this module is imported into - /// @param Decl The declaration (or definition) of a function, type, or + /// Create a descriptor for an imported function. + /// \param Context The scope this module is imported into + /// \param Decl The declaration (or definition) of a function, type, or /// variable - /// @param Line Line number - MDImportedEntity *createImportedDeclaration(MDScope *Context, - DebugNode *Decl, unsigned Line, + /// \param Line Line number + DIImportedEntity *createImportedDeclaration(DIScope *Context, DINode *Decl, + unsigned Line, StringRef Name = ""); - /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. - /// @param Storage llvm::Value of the variable - /// @param VarInfo Variable's debug info descriptor. - /// @param Expr A complex location expression. - /// @param DL Debug info location. - /// @param InsertAtEnd Location for the new intrinsic. - Instruction *insertDeclare(llvm::Value *Storage, MDLocalVariable *VarInfo, - MDExpression *Expr, const MDLocation *DL, + /// Insert a new llvm.dbg.declare intrinsic call. + /// \param Storage llvm::Value of the variable + /// \param VarInfo Variable's debug info descriptor. + /// \param Expr A complex location expression. + /// \param DL Debug info location. + /// \param InsertAtEnd Location for the new intrinsic. + Instruction *insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo, + DIExpression *Expr, const DILocation *DL, BasicBlock *InsertAtEnd); - /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. - /// @param Storage llvm::Value of the variable - /// @param VarInfo Variable's debug info descriptor. - /// @param Expr A complex location expression. - /// @param DL Debug info location. - /// @param InsertBefore Location for the new intrinsic. - Instruction *insertDeclare(llvm::Value *Storage, MDLocalVariable *VarInfo, - MDExpression *Expr, const MDLocation *DL, + /// Insert a new llvm.dbg.declare intrinsic call. + /// \param Storage llvm::Value of the variable + /// \param VarInfo Variable's debug info descriptor. + /// \param Expr A complex location expression. + /// \param DL Debug info location. + /// \param InsertBefore Location for the new intrinsic. + Instruction *insertDeclare(llvm::Value *Storage, DILocalVariable *VarInfo, + DIExpression *Expr, const DILocation *DL, Instruction *InsertBefore); - /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. - /// @param Val llvm::Value of the variable - /// @param Offset Offset - /// @param VarInfo Variable's debug info descriptor. - /// @param Expr A complex location expression. - /// @param DL Debug info location. - /// @param InsertAtEnd Location for the new intrinsic. + /// Insert a new llvm.dbg.value intrinsic call. + /// \param Val llvm::Value of the variable + /// \param Offset Offset + /// \param VarInfo Variable's debug info descriptor. + /// \param Expr A complex location expression. + /// \param DL Debug info location. + /// \param InsertAtEnd Location for the new intrinsic. Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, - MDLocalVariable *VarInfo, - MDExpression *Expr, - const MDLocation *DL, + DILocalVariable *VarInfo, + DIExpression *Expr, + const DILocation *DL, BasicBlock *InsertAtEnd); - /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. - /// @param Val llvm::Value of the variable - /// @param Offset Offset - /// @param VarInfo Variable's debug info descriptor. - /// @param Expr A complex location expression. - /// @param DL Debug info location. - /// @param InsertBefore Location for the new intrinsic. + /// Insert a new llvm.dbg.value intrinsic call. + /// \param Val llvm::Value of the variable + /// \param Offset Offset + /// \param VarInfo Variable's debug info descriptor. + /// \param Expr A complex location expression. + /// \param DL Debug info location. + /// \param InsertBefore Location for the new intrinsic. Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, - MDLocalVariable *VarInfo, - MDExpression *Expr, - const MDLocation *DL, + DILocalVariable *VarInfo, + DIExpression *Expr, + const DILocation *DL, Instruction *InsertBefore); - /// \brief Replace the vtable holder in the given composite type. + /// Replace the vtable holder in the given composite type. /// /// If this creates a self reference, it may orphan some unresolved cycles /// in the operands of \c T, so \a DIBuilder needs to track that. - void replaceVTableHolder(MDCompositeType *&T, - MDCompositeType *VTableHolder); + void replaceVTableHolder(DICompositeType *&T, + DICompositeType *VTableHolder); - /// \brief Replace arrays on a composite type. + /// Replace arrays on a composite type. /// /// If \c T is resolved, but the arrays aren't -- which can happen if \c T /// has a self-reference -- \a DIBuilder needs to track the array to /// resolve cycles. - void replaceArrays(MDCompositeType *&T, DIArray Elements, - DIArray TParems = DIArray()); + void replaceArrays(DICompositeType *&T, DINodeArray Elements, + DINodeArray TParems = DINodeArray()); - /// \brief Replace a temporary node. + /// Replace a temporary node. /// /// Call \a MDNode::replaceAllUsesWith() on \c N, replacing it with \c /// Replacement. diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h index 3e1f9744f9e..892d6c9936c 100644 --- a/include/llvm/IR/DataLayout.h +++ b/include/llvm/IR/DataLayout.h @@ -222,7 +222,9 @@ class DataLayout { /// This representation is in the same format accepted by the string /// constructor above. This should not be used to compare two DataLayout as /// different string can represent the same layout. - std::string getStringRepresentation() const { return StringRepresentation; } + const std::string &getStringRepresentation() const { + return StringRepresentation; + } /// \brief Test if the DataLayout was constructed from an empty string. bool isDefault() const { return StringRepresentation.empty(); } diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h index 18b0c72b008..a06174827ba 100644 --- a/include/llvm/IR/DebugInfo.h +++ b/include/llvm/IR/DebugInfo.h @@ -29,405 +29,20 @@ #include namespace llvm { -class BasicBlock; -class Constant; -class Function; -class GlobalVariable; class Module; -class Type; -class Value; class DbgDeclareInst; class DbgValueInst; -class Instruction; -class Metadata; -class MDNode; -class MDString; -class NamedMDNode; -class LLVMContext; -class raw_ostream; - -class DIFile; -class DISubprogram; -class DILexicalBlock; -class DILexicalBlockFile; -class DIVariable; -class DIType; -class DIScope; -class DIObjCProperty; /// \brief Maps from type identifier to the actual MDNode. -typedef DenseMap DITypeIdentifierMap; - -class DIDescriptor { - MDNode *N; - -public: - DIDescriptor(const MDNode *N = nullptr) : N(const_cast(N)) {} - - operator MDNode *() const { return N; } - MDNode *operator->() const { return N; } - MDNode &operator*() const { return *N; } -}; - -#define DECLARE_SIMPLIFY_DESCRIPTOR(DESC) \ - class DESC; \ - template <> struct simplify_type; \ - template <> struct simplify_type; -DECLARE_SIMPLIFY_DESCRIPTOR(DIDescriptor) -DECLARE_SIMPLIFY_DESCRIPTOR(DISubrange) -DECLARE_SIMPLIFY_DESCRIPTOR(DIEnumerator) -DECLARE_SIMPLIFY_DESCRIPTOR(DIScope) -DECLARE_SIMPLIFY_DESCRIPTOR(DIType) -DECLARE_SIMPLIFY_DESCRIPTOR(DIBasicType) -DECLARE_SIMPLIFY_DESCRIPTOR(DIDerivedType) -DECLARE_SIMPLIFY_DESCRIPTOR(DICompositeType) -DECLARE_SIMPLIFY_DESCRIPTOR(DISubroutineType) -DECLARE_SIMPLIFY_DESCRIPTOR(DIFile) -DECLARE_SIMPLIFY_DESCRIPTOR(DICompileUnit) -DECLARE_SIMPLIFY_DESCRIPTOR(DISubprogram) -DECLARE_SIMPLIFY_DESCRIPTOR(DILexicalBlock) -DECLARE_SIMPLIFY_DESCRIPTOR(DILexicalBlockFile) -DECLARE_SIMPLIFY_DESCRIPTOR(DINameSpace) -DECLARE_SIMPLIFY_DESCRIPTOR(DITemplateTypeParameter) -DECLARE_SIMPLIFY_DESCRIPTOR(DITemplateValueParameter) -DECLARE_SIMPLIFY_DESCRIPTOR(DIGlobalVariable) -DECLARE_SIMPLIFY_DESCRIPTOR(DIVariable) -DECLARE_SIMPLIFY_DESCRIPTOR(DIExpression) -DECLARE_SIMPLIFY_DESCRIPTOR(DILocation) -DECLARE_SIMPLIFY_DESCRIPTOR(DIObjCProperty) -DECLARE_SIMPLIFY_DESCRIPTOR(DIImportedEntity) -#undef DECLARE_SIMPLIFY_DESCRIPTOR - -typedef DebugNodeArray DIArray; -typedef MDTypeRefArray DITypeArray; -typedef DebugNodeRef DIDescriptorRef; -typedef MDScopeRef DIScopeRef; -typedef MDTypeRef DITypeRef; - -class DISubrange { - MDSubrange *N; - -public: - DISubrange(const MDSubrange *N = nullptr) : N(const_cast(N)) {} - - operator MDSubrange *() const { return N; } - MDSubrange *operator->() const { return N; } - MDSubrange &operator*() const { return *N; } -}; - -class DIEnumerator { - MDEnumerator *N; - -public: - DIEnumerator(const MDEnumerator *N = nullptr) - : N(const_cast(N)) {} - - operator MDEnumerator *() const { return N; } - MDEnumerator *operator->() const { return N; } - MDEnumerator &operator*() const { return *N; } -}; - -class DIScope { - MDScope *N; - -public: - DIScope(const MDScope *N = nullptr) : N(const_cast(N)) {} - - operator DIDescriptor() const { return N; } - operator MDScope *() const { return N; } - MDScope *operator->() const { return N; } - MDScope &operator*() const { return *N; } -}; - -class DIType { - MDType *N; - -public: - DIType(const MDType *N = nullptr) : N(const_cast(N)) {} - - operator DIDescriptor() const { return N; } - operator DIScope() const { return N; } - operator MDType *() const { return N; } - MDType *operator->() const { return N; } - MDType &operator*() const { return *N; } -}; - -class DIBasicType { - MDBasicType *N; - -public: - DIBasicType(const MDBasicType *N = nullptr) - : N(const_cast(N)) {} - - operator DIDescriptor() const { return N; } - operator DIType() const { return N; } - operator MDBasicType *() const { return N; } - MDBasicType *operator->() const { return N; } - MDBasicType &operator*() const { return *N; } -}; - -class DIDerivedType { - MDDerivedTypeBase *N; - -public: - DIDerivedType(const MDDerivedTypeBase *N = nullptr) - : N(const_cast(N)) {} - - operator DIDescriptor() const { return N; } - operator DIType() const { return N; } - operator MDDerivedTypeBase *() const { return N; } - MDDerivedTypeBase *operator->() const { return N; } - MDDerivedTypeBase &operator*() const { return *N; } -}; - -class DICompositeType { - MDCompositeTypeBase *N; - -public: - DICompositeType(const MDCompositeTypeBase *N = nullptr) - : N(const_cast(N)) {} - - operator DIDescriptor() const { return N; } - operator DIType() const { return N; } - operator MDCompositeTypeBase *() const { return N; } - MDCompositeTypeBase *operator->() const { return N; } - MDCompositeTypeBase &operator*() const { return *N; } -}; - -class DISubroutineType { - MDSubroutineType *N; - -public: - DISubroutineType(const MDSubroutineType *N = nullptr) - : N(const_cast(N)) {} - - operator DIDescriptor() const { return N; } - operator DIType() const { return N; } - operator DICompositeType() const { return N; } - operator MDSubroutineType *() const { return N; } - MDSubroutineType *operator->() const { return N; } - MDSubroutineType &operator*() const { return *N; } -}; - -class DIFile { - MDFile *N; - -public: - DIFile(const MDFile *N = nullptr) : N(const_cast(N)) {} - - operator DIDescriptor() const { return N; } - operator DIScope() const { return N; } - operator MDFile *() const { return N; } - MDFile *operator->() const { return N; } - MDFile &operator*() const { return *N; } -}; - -class DICompileUnit { - MDCompileUnit *N; - -public: - DICompileUnit(const MDCompileUnit *N = nullptr) - : N(const_cast(N)) {} - - operator DIDescriptor() const { return N; } - operator DIScope() const { return N; } - operator MDCompileUnit *() const { return N; } - MDCompileUnit *operator->() const { return N; } - MDCompileUnit &operator*() const { return *N; } -}; - -class DISubprogram { - MDSubprogram *N; - -public: - DISubprogram(const MDSubprogram *N = nullptr) - : N(const_cast(N)) {} - - operator DIDescriptor() const { return N; } - operator DIScope() const { return N; } - operator MDSubprogram *() const { return N; } - MDSubprogram *operator->() const { return N; } - MDSubprogram &operator*() const { return *N; } -}; - -class DILexicalBlock { - MDLexicalBlockBase *N; - -public: - DILexicalBlock(const MDLexicalBlockBase *N = nullptr) - : N(const_cast(N)) {} - - operator DIDescriptor() const { return N; } - operator MDLexicalBlockBase *() const { return N; } - MDLexicalBlockBase *operator->() const { return N; } - MDLexicalBlockBase &operator*() const { return *N; } -}; - -class DILexicalBlockFile { - MDLexicalBlockFile *N; - -public: - DILexicalBlockFile(const MDLexicalBlockFile *N = nullptr) - : N(const_cast(N)) {} - - operator DIDescriptor() const { return N; } - operator MDLexicalBlockFile *() const { return N; } - MDLexicalBlockFile *operator->() const { return N; } - MDLexicalBlockFile &operator*() const { return *N; } -}; - -class DINameSpace { - MDNamespace *N; - -public: - DINameSpace(const MDNamespace *N = nullptr) - : N(const_cast(N)) {} - - operator DIDescriptor() const { return N; } - operator DIScope() const { return N; } - operator MDNamespace *() const { return N; } - MDNamespace *operator->() const { return N; } - MDNamespace &operator*() const { return *N; } -}; - -class DITemplateTypeParameter { - MDTemplateTypeParameter *N; - -public: - DITemplateTypeParameter(const MDTemplateTypeParameter *N = nullptr) - : N(const_cast(N)) {} - - operator MDTemplateTypeParameter *() const { return N; } - MDTemplateTypeParameter *operator->() const { return N; } - MDTemplateTypeParameter &operator*() const { return *N; } -}; - -class DITemplateValueParameter { - MDTemplateValueParameter *N; - -public: - DITemplateValueParameter(const MDTemplateValueParameter *N = nullptr) - : N(const_cast(N)) {} - - operator MDTemplateValueParameter *() const { return N; } - MDTemplateValueParameter *operator->() const { return N; } - MDTemplateValueParameter &operator*() const { return *N; } -}; - -class DIGlobalVariable { - MDGlobalVariable *N; - -public: - DIGlobalVariable(const MDGlobalVariable *N = nullptr) - : N(const_cast(N)) {} - - operator DIDescriptor() const { return N; } - operator MDGlobalVariable *() const { return N; } - MDGlobalVariable *operator->() const { return N; } - MDGlobalVariable &operator*() const { return *N; } -}; - -class DIVariable { - MDLocalVariable *N; - -public: - DIVariable(const MDLocalVariable *N = nullptr) - : N(const_cast(N)) {} - - operator MDLocalVariable *() const { return N; } - MDLocalVariable *operator->() const { return N; } - MDLocalVariable &operator*() const { return *N; } -}; - -class DIExpression { - MDExpression *N; - -public: - DIExpression(const MDExpression *N = nullptr) - : N(const_cast(N)) {} - - operator MDExpression *() const { return N; } - MDExpression *operator->() const { return N; } - MDExpression &operator*() const { return *N; } -}; - -class DILocation { - MDLocation *N; - -public: - DILocation(const MDLocation *N = nullptr) : N(const_cast(N)) {} - - operator MDLocation *() const { return N; } - MDLocation *operator->() const { return N; } - MDLocation &operator*() const { return *N; } -}; - -class DIObjCProperty { - MDObjCProperty *N; - -public: - DIObjCProperty(const MDObjCProperty *N = nullptr) - : N(const_cast(N)) {} - - operator MDObjCProperty *() const { return N; } - MDObjCProperty *operator->() const { return N; } - MDObjCProperty &operator*() const { return *N; } -}; - -class DIImportedEntity { - MDImportedEntity *N; - -public: - DIImportedEntity(const MDImportedEntity *N = nullptr) - : N(const_cast(N)) {} - - operator DIDescriptor() const { return N; } - operator MDImportedEntity *() const { return N; } - MDImportedEntity *operator->() const { return N; } - MDImportedEntity &operator*() const { return *N; } -}; - -#define SIMPLIFY_DESCRIPTOR(DESC) \ - template <> struct simplify_type { \ - typedef Metadata *SimpleType; \ - static SimpleType getSimplifiedValue(const DESC &DI) { return DI; } \ - }; \ - template <> struct simplify_type : simplify_type {}; -SIMPLIFY_DESCRIPTOR(DIDescriptor) -SIMPLIFY_DESCRIPTOR(DISubrange) -SIMPLIFY_DESCRIPTOR(DIEnumerator) -SIMPLIFY_DESCRIPTOR(DIScope) -SIMPLIFY_DESCRIPTOR(DIType) -SIMPLIFY_DESCRIPTOR(DIBasicType) -SIMPLIFY_DESCRIPTOR(DIDerivedType) -SIMPLIFY_DESCRIPTOR(DICompositeType) -SIMPLIFY_DESCRIPTOR(DISubroutineType) -SIMPLIFY_DESCRIPTOR(DIFile) -SIMPLIFY_DESCRIPTOR(DICompileUnit) -SIMPLIFY_DESCRIPTOR(DISubprogram) -SIMPLIFY_DESCRIPTOR(DILexicalBlock) -SIMPLIFY_DESCRIPTOR(DILexicalBlockFile) -SIMPLIFY_DESCRIPTOR(DINameSpace) -SIMPLIFY_DESCRIPTOR(DITemplateTypeParameter) -SIMPLIFY_DESCRIPTOR(DITemplateValueParameter) -SIMPLIFY_DESCRIPTOR(DIGlobalVariable) -SIMPLIFY_DESCRIPTOR(DIVariable) -SIMPLIFY_DESCRIPTOR(DIExpression) -SIMPLIFY_DESCRIPTOR(DILocation) -SIMPLIFY_DESCRIPTOR(DIObjCProperty) -SIMPLIFY_DESCRIPTOR(DIImportedEntity) -#undef SIMPLIFY_DESCRIPTOR +typedef DenseMap DITypeIdentifierMap; /// \brief Find subprogram that is enclosing this scope. -DISubprogram getDISubprogram(const MDNode *Scope); +DISubprogram *getDISubprogram(const MDNode *Scope); /// \brief Find debug info for a given function. -/// \returns a valid DISubprogram, if found. Otherwise, it returns an empty -/// DISubprogram. -DISubprogram getDISubprogram(const Function *F); - -/// \brief Find underlying composite type. -DICompositeType getDICompositeType(DIType T); +/// +/// \returns a valid subprogram, if found. Otherwise, return \c nullptr. +DISubprogram *getDISubprogram(const Function *F); /// \brief Generate map by visiting all retained types. DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes); @@ -462,8 +77,8 @@ class DebugInfoFinder { void processDeclare(const Module &M, const DbgDeclareInst *DDI); /// \brief Process DbgValueInst. void processValue(const Module &M, const DbgValueInst *DVI); - /// \brief Process DILocation. - void processLocation(const Module &M, DILocation Loc); + /// \brief Process debug info location. + void processLocation(const Module &M, const DILocation *Loc); /// \brief Clear all lists. void reset(); @@ -471,22 +86,23 @@ class DebugInfoFinder { private: void InitializeTypeMap(const Module &M); - void processType(DIType DT); - void processSubprogram(DISubprogram SP); - void processScope(DIScope Scope); - bool addCompileUnit(DICompileUnit CU); - bool addGlobalVariable(DIGlobalVariable DIG); - bool addSubprogram(DISubprogram SP); - bool addType(DIType DT); - bool addScope(DIScope Scope); + void processType(DIType *DT); + void processSubprogram(DISubprogram *SP); + void processScope(DIScope *Scope); + bool addCompileUnit(DICompileUnit *CU); + bool addGlobalVariable(DIGlobalVariable *DIG); + bool addSubprogram(DISubprogram *SP); + bool addType(DIType *DT); + bool addScope(DIScope *Scope); public: - typedef SmallVectorImpl::const_iterator compile_unit_iterator; - typedef SmallVectorImpl::const_iterator subprogram_iterator; - typedef SmallVectorImpl::const_iterator + typedef SmallVectorImpl::const_iterator + compile_unit_iterator; + typedef SmallVectorImpl::const_iterator subprogram_iterator; + typedef SmallVectorImpl::const_iterator global_variable_iterator; - typedef SmallVectorImpl::const_iterator type_iterator; - typedef SmallVectorImpl::const_iterator scope_iterator; + typedef SmallVectorImpl::const_iterator type_iterator; + typedef SmallVectorImpl::const_iterator scope_iterator; iterator_range compile_units() const { return iterator_range(CUs.begin(), CUs.end()); @@ -515,19 +131,19 @@ class DebugInfoFinder { unsigned scope_count() const { return Scopes.size(); } private: - SmallVector CUs; - SmallVector SPs; - SmallVector GVs; - SmallVector TYs; - SmallVector Scopes; - SmallPtrSet NodesSeen; + SmallVector CUs; + SmallVector SPs; + SmallVector GVs; + SmallVector TYs; + SmallVector Scopes; + SmallPtrSet NodesSeen; DITypeIdentifierMap TypeIdentifierMap; /// \brief Specify if TypeIdentifierMap is initialized. bool TypeMapInitialized; }; -DenseMap makeSubprogramMap(const Module &M); +DenseMap makeSubprogramMap(const Module &M); } // end namespace llvm diff --git a/include/llvm/IR/DebugInfoFlags.def b/include/llvm/IR/DebugInfoFlags.def index d5de8683fd3..9756c12264b 100644 --- a/include/llvm/IR/DebugInfoFlags.def +++ b/include/llvm/IR/DebugInfoFlags.def @@ -32,5 +32,6 @@ HANDLE_DI_FLAG((1 << 11), Vector) HANDLE_DI_FLAG((1 << 12), StaticMember) HANDLE_DI_FLAG((1 << 13), LValueReference) HANDLE_DI_FLAG((1 << 14), RValueReference) +HANDLE_DI_FLAG((1 << 15), ExternalTypeRef) #undef HANDLE_DI_FLAG diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h index 62373c4b09f..1f247f59b65 100644 --- a/include/llvm/IR/DebugInfoMetadata.h +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -41,39 +41,39 @@ namespace llvm { -/// \brief Pointer union between a subclass of DebugNode and MDString. +/// \brief Pointer union between a subclass of DINode and MDString. /// -/// \a MDCompositeType can be referenced via an \a MDString unique identifier. +/// \a DICompositeType can be referenced via an \a MDString unique identifier. /// This class allows some type safety in the face of that, requiring either a /// node of a particular type or an \a MDString. -template class TypedDebugNodeRef { +template class TypedDINodeRef { const Metadata *MD = nullptr; public: - TypedDebugNodeRef() = default; - TypedDebugNodeRef(std::nullptr_t) {} + TypedDINodeRef() = default; + TypedDINodeRef(std::nullptr_t) {} /// \brief Construct from a raw pointer. - explicit TypedDebugNodeRef(const Metadata *MD) : MD(MD) { + explicit TypedDINodeRef(const Metadata *MD) : MD(MD) { assert((!MD || isa(MD) || isa(MD)) && "Expected valid ref"); } template - TypedDebugNodeRef( - const TypedDebugNodeRef &X, + TypedDINodeRef( + const TypedDINodeRef &X, typename std::enable_if::value>::type * = nullptr) : MD(X) {} operator Metadata *() const { return const_cast(MD); } - bool operator==(const TypedDebugNodeRef &X) const { return MD == X.MD; }; - bool operator!=(const TypedDebugNodeRef &X) const { return MD != X.MD; }; + bool operator==(const TypedDINodeRef &X) const { return MD == X.MD; } + bool operator!=(const TypedDINodeRef &X) const { return MD != X.MD; } /// \brief Create a reference. /// /// Get a reference to \c N, using an \a MDString reference if available. - static TypedDebugNodeRef get(const T *N); + static TypedDINodeRef get(const T *N); template T *resolve(const MapTy &Map) const { if (!MD) @@ -89,15 +89,15 @@ template class TypedDebugNodeRef { } }; -typedef TypedDebugNodeRef DebugNodeRef; -typedef TypedDebugNodeRef MDScopeRef; -typedef TypedDebugNodeRef MDTypeRef; +typedef TypedDINodeRef DINodeRef; +typedef TypedDINodeRef DIScopeRef; +typedef TypedDINodeRef DITypeRef; -class MDTypeRefArray { +class DITypeRefArray { const MDTuple *N = nullptr; public: - MDTypeRefArray(const MDTuple *N) : N(N) {} + DITypeRefArray(const MDTuple *N) : N(N) {} explicit operator bool() const { return get(); } explicit operator MDTuple *() const { return get(); } @@ -108,16 +108,16 @@ class MDTypeRefArray { // FIXME: Fix callers and remove condition on N. unsigned size() const { return N ? N->getNumOperands() : 0u; } - MDTypeRef operator[](unsigned I) const { return MDTypeRef(N->getOperand(I)); } + DITypeRef operator[](unsigned I) const { return DITypeRef(N->getOperand(I)); } - class iterator : std::iterator { + class iterator : std::iterator { MDNode::op_iterator I = nullptr; public: iterator() = default; explicit iterator(MDNode::op_iterator I) : I(I) {} - MDTypeRef operator*() const { return MDTypeRef(*I); } + DITypeRef operator*() const { return DITypeRef(*I); } iterator &operator++() { ++I; return *this; @@ -139,20 +139,20 @@ class MDTypeRefArray { /// \brief Tagged DWARF-like metadata node. /// /// A metadata node with a DWARF tag (i.e., a constant named \c DW_TAG_*, -/// defined in llvm/Support/Dwarf.h). Called \a DebugNode because it's +/// defined in llvm/Support/Dwarf.h). Called \a DINode because it's /// potentially used for non-DWARF output. -class DebugNode : public MDNode { +class DINode : public MDNode { friend class LLVMContextImpl; friend class MDNode; protected: - DebugNode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, - ArrayRef Ops1, ArrayRef Ops2 = None) + DINode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + ArrayRef Ops1, ArrayRef Ops2 = None) : MDNode(C, ID, Storage, Ops1, Ops2) { assert(Tag < 1u << 16); SubclassData16 = Tag; } - ~DebugNode() = default; + ~DINode() = default; template Ty *getOperandAs(unsigned I) const { return cast_or_null(getOperand(I)); @@ -193,47 +193,47 @@ class DebugNode : public MDNode { static unsigned splitFlags(unsigned Flags, SmallVectorImpl &SplitFlags); - DebugNodeRef getRef() const { return DebugNodeRef::get(this); } + DINodeRef getRef() const { return DINodeRef::get(this); } static bool classof(const Metadata *MD) { switch (MD->getMetadataID()) { default: return false; - case GenericDebugNodeKind: - case MDSubrangeKind: - case MDEnumeratorKind: - case MDBasicTypeKind: - case MDDerivedTypeKind: - case MDCompositeTypeKind: - case MDSubroutineTypeKind: - case MDFileKind: - case MDCompileUnitKind: - case MDSubprogramKind: - case MDLexicalBlockKind: - case MDLexicalBlockFileKind: - case MDNamespaceKind: - case MDTemplateTypeParameterKind: - case MDTemplateValueParameterKind: - case MDGlobalVariableKind: - case MDLocalVariableKind: - case MDObjCPropertyKind: - case MDImportedEntityKind: + case GenericDINodeKind: + case DISubrangeKind: + case DIEnumeratorKind: + case DIBasicTypeKind: + case DIDerivedTypeKind: + case DICompositeTypeKind: + case DISubroutineTypeKind: + case DIFileKind: + case DICompileUnitKind: + case DISubprogramKind: + case DILexicalBlockKind: + case DILexicalBlockFileKind: + case DINamespaceKind: + case DITemplateTypeParameterKind: + case DITemplateValueParameterKind: + case DIGlobalVariableKind: + case DILocalVariableKind: + case DIObjCPropertyKind: + case DIImportedEntityKind: + case DIModuleKind: return true; } } }; -template -struct simplify_type> { +template struct simplify_type> { typedef Metadata *SimpleType; - static SimpleType getSimplifiedValue(const TypedDebugNodeRef &MD) { + static SimpleType getSimplifiedValue(const TypedDINodeRef &MD) { return MD; } }; template -struct simplify_type> - : simplify_type> {}; +struct simplify_type> + : simplify_type> {}; /// \brief Generic tagged DWARF-like metadata node. /// @@ -241,37 +241,33 @@ struct simplify_type> /// (possibly empty) null-separated \a MDString header that contains arbitrary /// fields. The remaining operands are \a dwarf_operands(), and are pointers /// to other metadata. -class GenericDebugNode : public DebugNode { +class GenericDINode : public DINode { friend class LLVMContextImpl; friend class MDNode; - GenericDebugNode(LLVMContext &C, StorageType Storage, unsigned Hash, - unsigned Tag, ArrayRef Ops1, - ArrayRef Ops2) - : DebugNode(C, GenericDebugNodeKind, Storage, Tag, Ops1, Ops2) { + GenericDINode(LLVMContext &C, StorageType Storage, unsigned Hash, + unsigned Tag, ArrayRef Ops1, + ArrayRef Ops2) + : DINode(C, GenericDINodeKind, Storage, Tag, Ops1, Ops2) { setHash(Hash); } - ~GenericDebugNode() { dropAllReferences(); } + ~GenericDINode() { dropAllReferences(); } void setHash(unsigned Hash) { SubclassData32 = Hash; } void recalculateHash(); - static GenericDebugNode *getImpl(LLVMContext &Context, unsigned Tag, - StringRef Header, - ArrayRef DwarfOps, - StorageType Storage, - bool ShouldCreate = true) { + static GenericDINode *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Header, ArrayRef DwarfOps, + StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, getCanonicalMDString(Context, Header), DwarfOps, Storage, ShouldCreate); } - static GenericDebugNode *getImpl(LLVMContext &Context, unsigned Tag, - MDString *Header, - ArrayRef DwarfOps, - StorageType Storage, - bool ShouldCreate = true); + static GenericDINode *getImpl(LLVMContext &Context, unsigned Tag, + MDString *Header, ArrayRef DwarfOps, + StorageType Storage, bool ShouldCreate = true); - TempGenericDebugNode cloneImpl() const { + TempGenericDINode cloneImpl() const { return getTemporary( getContext(), getTag(), getHeader(), SmallVector(dwarf_op_begin(), dwarf_op_end())); @@ -280,15 +276,15 @@ class GenericDebugNode : public DebugNode { public: unsigned getHash() const { return SubclassData32; } - DEFINE_MDNODE_GET(GenericDebugNode, (unsigned Tag, StringRef Header, - ArrayRef DwarfOps), + DEFINE_MDNODE_GET(GenericDINode, (unsigned Tag, StringRef Header, + ArrayRef DwarfOps), (Tag, Header, DwarfOps)) - DEFINE_MDNODE_GET(GenericDebugNode, (unsigned Tag, MDString *Header, - ArrayRef DwarfOps), + DEFINE_MDNODE_GET(GenericDINode, (unsigned Tag, MDString *Header, + ArrayRef DwarfOps), (Tag, Header, DwarfOps)) /// \brief Return a (temporary) clone of this. - TempGenericDebugNode clone() const { return cloneImpl(); } + TempGenericDINode clone() const { return cloneImpl(); } unsigned getTag() const { return SubclassData16; } StringRef getHeader() const { return getStringOperand(0); } @@ -308,7 +304,7 @@ class GenericDebugNode : public DebugNode { } static bool classof(const Metadata *MD) { - return MD->getMetadataID() == GenericDebugNodeKind; + return MD->getMetadataID() == GenericDINodeKind; } }; @@ -316,39 +312,38 @@ class GenericDebugNode : public DebugNode { /// /// TODO: Merge into node for DW_TAG_array_type, which should have a custom /// type. -class MDSubrange : public DebugNode { +class DISubrange : public DINode { friend class LLVMContextImpl; friend class MDNode; int64_t Count; int64_t LowerBound; - MDSubrange(LLVMContext &C, StorageType Storage, int64_t Count, + DISubrange(LLVMContext &C, StorageType Storage, int64_t Count, int64_t LowerBound) - : DebugNode(C, MDSubrangeKind, Storage, dwarf::DW_TAG_subrange_type, - None), + : DINode(C, DISubrangeKind, Storage, dwarf::DW_TAG_subrange_type, None), Count(Count), LowerBound(LowerBound) {} - ~MDSubrange() = default; + ~DISubrange() = default; - static MDSubrange *getImpl(LLVMContext &Context, int64_t Count, + static DISubrange *getImpl(LLVMContext &Context, int64_t Count, int64_t LowerBound, StorageType Storage, bool ShouldCreate = true); - TempMDSubrange cloneImpl() const { + TempDISubrange cloneImpl() const { return getTemporary(getContext(), getCount(), getLowerBound()); } public: - DEFINE_MDNODE_GET(MDSubrange, (int64_t Count, int64_t LowerBound = 0), + DEFINE_MDNODE_GET(DISubrange, (int64_t Count, int64_t LowerBound = 0), (Count, LowerBound)) - TempMDSubrange clone() const { return cloneImpl(); } + TempDISubrange clone() const { return cloneImpl(); } int64_t getLowerBound() const { return LowerBound; } int64_t getCount() const { return Count; } static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDSubrangeKind; + return MD->getMetadataID() == DISubrangeKind; } }; @@ -356,39 +351,39 @@ class MDSubrange : public DebugNode { /// /// TODO: Add a pointer to the context (DW_TAG_enumeration_type) once that no /// longer creates a type cycle. -class MDEnumerator : public DebugNode { +class DIEnumerator : public DINode { friend class LLVMContextImpl; friend class MDNode; int64_t Value; - MDEnumerator(LLVMContext &C, StorageType Storage, int64_t Value, + DIEnumerator(LLVMContext &C, StorageType Storage, int64_t Value, ArrayRef Ops) - : DebugNode(C, MDEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops), + : DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops), Value(Value) {} - ~MDEnumerator() = default; + ~DIEnumerator() = default; - static MDEnumerator *getImpl(LLVMContext &Context, int64_t Value, + static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value, StringRef Name, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Value, getCanonicalMDString(Context, Name), Storage, ShouldCreate); } - static MDEnumerator *getImpl(LLVMContext &Context, int64_t Value, + static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value, MDString *Name, StorageType Storage, bool ShouldCreate = true); - TempMDEnumerator cloneImpl() const { + TempDIEnumerator cloneImpl() const { return getTemporary(getContext(), getValue(), getName()); } public: - DEFINE_MDNODE_GET(MDEnumerator, (int64_t Value, StringRef Name), + DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, StringRef Name), (Value, Name)) - DEFINE_MDNODE_GET(MDEnumerator, (int64_t Value, MDString *Name), + DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, MDString *Name), (Value, Name)) - TempMDEnumerator clone() const { return cloneImpl(); } + TempDIEnumerator clone() const { return cloneImpl(); } int64_t getValue() const { return Value; } StringRef getName() const { return getStringOperand(0); } @@ -396,7 +391,7 @@ class MDEnumerator : public DebugNode { MDString *getRawName() const { return getOperandAs(0); } static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDEnumeratorKind; + return MD->getMetadataID() == DIEnumeratorKind; } }; @@ -406,49 +401,50 @@ class MDEnumerator : public DebugNode { /// contexts). /// /// TODO: Separate the concepts of declaration contexts and lexical scopes. -class MDScope : public DebugNode { +class DIScope : public DINode { protected: - MDScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + DIScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, ArrayRef Ops) - : DebugNode(C, ID, Storage, Tag, Ops) {} - ~MDScope() = default; + : DINode(C, ID, Storage, Tag, Ops) {} + ~DIScope() = default; public: - MDFile *getFile() const { return cast_or_null(getRawFile()); } + DIFile *getFile() const { return cast_or_null(getRawFile()); } inline StringRef getFilename() const; inline StringRef getDirectory() const; StringRef getName() const; - MDScopeRef getScope() const; + DIScopeRef getScope() const; /// \brief Return the raw underlying file. /// - /// An \a MDFile is an \a MDScope, but it doesn't point at a separate file - /// (it\em is the file). If \c this is an \a MDFile, we need to return \c + /// An \a DIFile is an \a DIScope, but it doesn't point at a separate file + /// (it\em is the file). If \c this is an \a DIFile, we need to return \c /// this. Otherwise, return the first operand, which is where all other /// subclasses store their file pointer. Metadata *getRawFile() const { - return isa(this) ? const_cast(this) + return isa(this) ? const_cast(this) : static_cast(getOperand(0)); } - MDScopeRef getRef() const { return MDScopeRef::get(this); } + DIScopeRef getRef() const { return DIScopeRef::get(this); } static bool classof(const Metadata *MD) { switch (MD->getMetadataID()) { default: return false; - case MDBasicTypeKind: - case MDDerivedTypeKind: - case MDCompositeTypeKind: - case MDSubroutineTypeKind: - case MDFileKind: - case MDCompileUnitKind: - case MDSubprogramKind: - case MDLexicalBlockKind: - case MDLexicalBlockFileKind: - case MDNamespaceKind: + case DIBasicTypeKind: + case DIDerivedTypeKind: + case DICompositeTypeKind: + case DISubroutineTypeKind: + case DIFileKind: + case DICompileUnitKind: + case DISubprogramKind: + case DILexicalBlockKind: + case DILexicalBlockFileKind: + case DINamespaceKind: + case DIModuleKind: return true; } } @@ -458,36 +454,36 @@ class MDScope : public DebugNode { /// /// TODO: Merge with directory/file node (including users). /// TODO: Canonicalize paths on creation. -class MDFile : public MDScope { +class DIFile : public DIScope { friend class LLVMContextImpl; friend class MDNode; - MDFile(LLVMContext &C, StorageType Storage, ArrayRef Ops) - : MDScope(C, MDFileKind, Storage, dwarf::DW_TAG_file_type, Ops) {} - ~MDFile() = default; + DIFile(LLVMContext &C, StorageType Storage, ArrayRef Ops) + : DIScope(C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops) {} + ~DIFile() = default; - static MDFile *getImpl(LLVMContext &Context, StringRef Filename, + static DIFile *getImpl(LLVMContext &Context, StringRef Filename, StringRef Directory, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, getCanonicalMDString(Context, Filename), getCanonicalMDString(Context, Directory), Storage, ShouldCreate); } - static MDFile *getImpl(LLVMContext &Context, MDString *Filename, + static DIFile *getImpl(LLVMContext &Context, MDString *Filename, MDString *Directory, StorageType Storage, bool ShouldCreate = true); - TempMDFile cloneImpl() const { + TempDIFile cloneImpl() const { return getTemporary(getContext(), getFilename(), getDirectory()); } public: - DEFINE_MDNODE_GET(MDFile, (StringRef Filename, StringRef Directory), + DEFINE_MDNODE_GET(DIFile, (StringRef Filename, StringRef Directory), (Filename, Directory)) - DEFINE_MDNODE_GET(MDFile, (MDString * Filename, MDString *Directory), + DEFINE_MDNODE_GET(DIFile, (MDString * Filename, MDString *Directory), (Filename, Directory)) - TempMDFile clone() const { return cloneImpl(); } + TempDIFile clone() const { return cloneImpl(); } StringRef getFilename() const { return getStringOperand(0); } StringRef getDirectory() const { return getStringOperand(1); } @@ -496,17 +492,17 @@ class MDFile : public MDScope { MDString *getRawDirectory() const { return getOperandAs(1); } static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDFileKind; + return MD->getMetadataID() == DIFileKind; } }; -StringRef MDScope::getFilename() const { +StringRef DIScope::getFilename() const { if (auto *F = getFile()) return F->getFilename(); return ""; } -StringRef MDScope::getDirectory() const { +StringRef DIScope::getDirectory() const { if (auto *F = getFile()) return F->getDirectory(); return ""; @@ -517,7 +513,7 @@ StringRef MDScope::getDirectory() const { /// TODO: Remove the hardcoded name and context, since many types don't use /// them. /// TODO: Split up flags. -class MDType : public MDScope { +class DIType : public DIScope { unsigned Line; unsigned Flags; uint64_t SizeInBits; @@ -525,17 +521,17 @@ class MDType : public MDScope { uint64_t OffsetInBits; protected: - MDType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + DIType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, ArrayRef Ops) - : MDScope(C, ID, Storage, Tag, Ops), Line(Line), Flags(Flags), + : DIScope(C, ID, Storage, Tag, Ops), Line(Line), Flags(Flags), SizeInBits(SizeInBits), AlignInBits(AlignInBits), OffsetInBits(OffsetInBits) {} - ~MDType() = default; + ~DIType() = default; public: - TempMDType clone() const { - return TempMDType(cast(MDNode::clone().release())); + TempDIType clone() const { + return TempDIType(cast(MDNode::clone().release())); } unsigned getLine() const { return Line; } @@ -544,7 +540,7 @@ class MDType : public MDScope { uint64_t getOffsetInBits() const { return OffsetInBits; } unsigned getFlags() const { return Flags; } - MDScopeRef getScope() const { return MDScopeRef(getRawScope()); } + DIScopeRef getScope() const { return DIScopeRef(getRawScope()); } StringRef getName() const { return getStringOperand(2); } @@ -578,17 +574,18 @@ class MDType : public MDScope { bool isStaticMember() const { return getFlags() & FlagStaticMember; } bool isLValueReference() const { return getFlags() & FlagLValueReference; } bool isRValueReference() const { return getFlags() & FlagRValueReference; } + bool isExternalTypeRef() const { return getFlags() & FlagExternalTypeRef; } - MDTypeRef getRef() const { return MDTypeRef::get(this); } + DITypeRef getRef() const { return DITypeRef::get(this); } static bool classof(const Metadata *MD) { switch (MD->getMetadataID()) { default: return false; - case MDBasicTypeKind: - case MDDerivedTypeKind: - case MDCompositeTypeKind: - case MDSubroutineTypeKind: + case DIBasicTypeKind: + case DIDerivedTypeKind: + case DICompositeTypeKind: + case DISubroutineTypeKind: return true; } } @@ -598,79 +595,55 @@ class MDType : public MDScope { /// /// TODO: Split out DW_TAG_unspecified_type. /// TODO: Drop unused accessors. -class MDBasicType : public MDType { +class DIBasicType : public DIType { friend class LLVMContextImpl; friend class MDNode; unsigned Encoding; - MDBasicType(LLVMContext &C, StorageType Storage, unsigned Tag, + DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding, ArrayRef Ops) - : MDType(C, MDBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, + : DIType(C, DIBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, 0, Ops), Encoding(Encoding) {} - ~MDBasicType() = default; + ~DIBasicType() = default; - static MDBasicType *getImpl(LLVMContext &Context, unsigned Tag, + static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, getCanonicalMDString(Context, Name), SizeInBits, AlignInBits, Encoding, Storage, ShouldCreate); } - static MDBasicType *getImpl(LLVMContext &Context, unsigned Tag, + static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding, StorageType Storage, bool ShouldCreate = true); - TempMDBasicType cloneImpl() const { + TempDIBasicType cloneImpl() const { return getTemporary(getContext(), getTag(), getName(), getSizeInBits(), getAlignInBits(), getEncoding()); } public: - DEFINE_MDNODE_GET(MDBasicType, (unsigned Tag, StringRef Name), + DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name), (Tag, Name, 0, 0, 0)) - DEFINE_MDNODE_GET(MDBasicType, + DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding), (Tag, Name, SizeInBits, AlignInBits, Encoding)) - DEFINE_MDNODE_GET(MDBasicType, + DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, MDString *Name, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding), (Tag, Name, SizeInBits, AlignInBits, Encoding)) - TempMDBasicType clone() const { return cloneImpl(); } + TempDIBasicType clone() const { return cloneImpl(); } unsigned getEncoding() const { return Encoding; } static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDBasicTypeKind; - } -}; - -/// \brief Base class for MDDerivedType and MDCompositeType. -/// -/// TODO: Delete; they're not really related. -class MDDerivedTypeBase : public MDType { -protected: - MDDerivedTypeBase(LLVMContext &C, unsigned ID, StorageType Storage, - unsigned Tag, unsigned Line, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, - ArrayRef Ops) - : MDType(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits, - Flags, Ops) {} - ~MDDerivedTypeBase() = default; - -public: - MDTypeRef getBaseType() const { return MDTypeRef(getRawBaseType()); } - Metadata *getRawBaseType() const { return getOperand(3); } - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDDerivedTypeKind || - MD->getMetadataID() == MDCompositeTypeKind || - MD->getMetadataID() == MDSubroutineTypeKind; + return MD->getMetadataID() == DIBasicTypeKind; } }; @@ -680,20 +653,20 @@ class MDDerivedTypeBase : public MDType { /// class members. /// /// TODO: Split out members (inheritance, fields, methods, etc.). -class MDDerivedType : public MDDerivedTypeBase { +class DIDerivedType : public DIType { friend class LLVMContextImpl; friend class MDNode; - MDDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag, + DIDerivedType(LLVMContext &C, StorageType Storage, unsigned Tag, unsigned Line, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, ArrayRef Ops) - : MDDerivedTypeBase(C, MDDerivedTypeKind, Storage, Tag, Line, SizeInBits, - AlignInBits, OffsetInBits, Flags, Ops) {} - ~MDDerivedType() = default; + : DIType(C, DIDerivedTypeKind, Storage, Tag, Line, SizeInBits, + AlignInBits, OffsetInBits, Flags, Ops) {} + ~DIDerivedType() = default; - static MDDerivedType *getImpl(LLVMContext &Context, unsigned Tag, - StringRef Name, MDFile *File, unsigned Line, - MDScopeRef Scope, MDTypeRef BaseType, + static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, DIFile *File, unsigned Line, + DIScopeRef Scope, DITypeRef BaseType, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, Metadata *ExtraData, StorageType Storage, @@ -702,7 +675,7 @@ class MDDerivedType : public MDDerivedTypeBase { Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, ExtraData, Storage, ShouldCreate); } - static MDDerivedType *getImpl(LLVMContext &Context, unsigned Tag, + static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, uint64_t AlignInBits, @@ -710,7 +683,7 @@ class MDDerivedType : public MDDerivedTypeBase { Metadata *ExtraData, StorageType Storage, bool ShouldCreate = true); - TempMDDerivedType cloneImpl() const { + TempDIDerivedType cloneImpl() const { return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), getScope(), getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(), getFlags(), @@ -718,7 +691,7 @@ class MDDerivedType : public MDDerivedTypeBase { } public: - DEFINE_MDNODE_GET(MDDerivedType, + DEFINE_MDNODE_GET(DIDerivedType, (unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, uint64_t AlignInBits, @@ -726,15 +699,19 @@ class MDDerivedType : public MDDerivedTypeBase { Metadata *ExtraData = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, ExtraData)) - DEFINE_MDNODE_GET(MDDerivedType, - (unsigned Tag, StringRef Name, MDFile *File, unsigned Line, - MDScopeRef Scope, MDTypeRef BaseType, uint64_t SizeInBits, + DEFINE_MDNODE_GET(DIDerivedType, + (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, + DIScopeRef Scope, DITypeRef BaseType, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, Metadata *ExtraData = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, ExtraData)) - TempMDDerivedType clone() const { return cloneImpl(); } + TempDIDerivedType clone() const { return cloneImpl(); } + + //// Get the base type this is derived from. + DITypeRef getBaseType() const { return DITypeRef(getRawBaseType()); } + Metadata *getRawBaseType() const { return getOperand(3); } /// \brief Get extra data associated with this derived type. /// @@ -748,12 +725,12 @@ class MDDerivedType : public MDDerivedTypeBase { /// \brief Get casted version of extra data. /// @{ - MDTypeRef getClassType() const { + DITypeRef getClassType() const { assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); - return MDTypeRef(getExtraData()); + return DITypeRef(getExtraData()); } - MDObjCProperty *getObjCProperty() const { - return dyn_cast_or_null(getExtraData()); + DIObjCProperty *getObjCProperty() const { + return dyn_cast_or_null(getExtraData()); } Constant *getConstant() const { assert(getTag() == dwarf::DW_TAG_member && isStaticMember()); @@ -764,74 +741,7 @@ class MDDerivedType : public MDDerivedTypeBase { /// @} static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDDerivedTypeKind; - } -}; - -/// \brief Base class for MDCompositeType and MDSubroutineType. -/// -/// TODO: Delete; they're not really related. -class MDCompositeTypeBase : public MDDerivedTypeBase { - unsigned RuntimeLang; - -protected: - MDCompositeTypeBase(LLVMContext &C, unsigned ID, StorageType Storage, - unsigned Tag, unsigned Line, unsigned RuntimeLang, - uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, - ArrayRef Ops) - : MDDerivedTypeBase(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, - OffsetInBits, Flags, Ops), - RuntimeLang(RuntimeLang) {} - ~MDCompositeTypeBase() = default; - -public: - /// \brief Get the elements of the composite type. - /// - /// \note Calling this is only valid for \a MDCompositeType. This assertion - /// can be removed once \a MDSubroutineType has been separated from - /// "composite types". - DebugNodeArray getElements() const { - assert(!isa(this) && "no elements for DISubroutineType"); - return cast_or_null(getRawElements()); - } - MDTypeRef getVTableHolder() const { return MDTypeRef(getRawVTableHolder()); } - MDTemplateParameterArray getTemplateParams() const { - return cast_or_null(getRawTemplateParams()); - } - StringRef getIdentifier() const { return getStringOperand(7); } - unsigned getRuntimeLang() const { return RuntimeLang; } - - Metadata *getRawElements() const { return getOperand(4); } - Metadata *getRawVTableHolder() const { return getOperand(5); } - Metadata *getRawTemplateParams() const { return getOperand(6); } - MDString *getRawIdentifier() const { return getOperandAs(7); } - - /// \brief Replace operands. - /// - /// If this \a isUniqued() and not \a isResolved(), on a uniquing collision - /// this will be RAUW'ed and deleted. Use a \a TrackingMDRef to keep track - /// of its movement if necessary. - /// @{ - void replaceElements(DebugNodeArray Elements) { -#ifndef NDEBUG - for (DebugNode *Op : getElements()) - assert(std::find(Elements->op_begin(), Elements->op_end(), Op) && - "Lost a member during member list replacement"); -#endif - replaceOperandWith(4, Elements.get()); - } - void replaceVTableHolder(MDTypeRef VTableHolder) { - replaceOperandWith(5, VTableHolder); - } - void replaceTemplateParams(MDTemplateParameterArray TemplateParams) { - replaceOperandWith(6, TemplateParams.get()); - } - /// @} - - static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDCompositeTypeKind || - MD->getMetadataID() == MDSubroutineTypeKind; + return MD->getMetadataID() == DIDerivedTypeKind; } }; @@ -839,25 +749,27 @@ class MDCompositeTypeBase : public MDDerivedTypeBase { /// /// TODO: Detach from DerivedTypeBase (split out MDEnumType?). /// TODO: Create a custom, unrelated node for DW_TAG_array_type. -class MDCompositeType : public MDCompositeTypeBase { +class DICompositeType : public DIType { friend class LLVMContextImpl; friend class MDNode; - MDCompositeType(LLVMContext &C, StorageType Storage, unsigned Tag, + unsigned RuntimeLang; + + DICompositeType(LLVMContext &C, StorageType Storage, unsigned Tag, unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, ArrayRef Ops) - : MDCompositeTypeBase(C, MDCompositeTypeKind, Storage, Tag, Line, - RuntimeLang, SizeInBits, AlignInBits, OffsetInBits, - Flags, Ops) {} - ~MDCompositeType() = default; + : DIType(C, DICompositeTypeKind, Storage, Tag, Line, SizeInBits, + AlignInBits, OffsetInBits, Flags, Ops), + RuntimeLang(RuntimeLang) {} + ~DICompositeType() = default; - static MDCompositeType * + static DICompositeType * getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File, - unsigned Line, MDScopeRef Scope, MDTypeRef BaseType, + unsigned Line, DIScopeRef Scope, DITypeRef BaseType, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, - uint64_t Flags, DebugNodeArray Elements, unsigned RuntimeLang, - MDTypeRef VTableHolder, MDTemplateParameterArray TemplateParams, + uint64_t Flags, DINodeArray Elements, unsigned RuntimeLang, + DITypeRef VTableHolder, DITemplateParameterArray TemplateParams, StringRef Identifier, StorageType Storage, bool ShouldCreate = true) { return getImpl( Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, @@ -865,7 +777,7 @@ class MDCompositeType : public MDCompositeTypeBase { RuntimeLang, VTableHolder, TemplateParams.get(), getCanonicalMDString(Context, Identifier), Storage, ShouldCreate); } - static MDCompositeType * + static DICompositeType * getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, @@ -873,7 +785,7 @@ class MDCompositeType : public MDCompositeTypeBase { Metadata *VTableHolder, Metadata *TemplateParams, MDString *Identifier, StorageType Storage, bool ShouldCreate = true); - TempMDCompositeType cloneImpl() const { + TempDICompositeType cloneImpl() const { return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), getScope(), getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(), getFlags(), @@ -882,18 +794,18 @@ class MDCompositeType : public MDCompositeTypeBase { } public: - DEFINE_MDNODE_GET(MDCompositeType, - (unsigned Tag, StringRef Name, MDFile *File, unsigned Line, - MDScopeRef Scope, MDTypeRef BaseType, uint64_t SizeInBits, + DEFINE_MDNODE_GET(DICompositeType, + (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, + DIScopeRef Scope, DITypeRef BaseType, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, - unsigned Flags, DebugNodeArray Elements, - unsigned RuntimeLang, MDTypeRef VTableHolder, - MDTemplateParameterArray TemplateParams = nullptr, + unsigned Flags, DINodeArray Elements, unsigned RuntimeLang, + DITypeRef VTableHolder, + DITemplateParameterArray TemplateParams = nullptr, StringRef Identifier = ""), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier)) - DEFINE_MDNODE_GET(MDCompositeType, + DEFINE_MDNODE_GET(DICompositeType, (unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, uint64_t AlignInBits, @@ -905,71 +817,108 @@ class MDCompositeType : public MDCompositeTypeBase { AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, Identifier)) - TempMDCompositeType clone() const { return cloneImpl(); } + TempDICompositeType clone() const { return cloneImpl(); } + + DITypeRef getBaseType() const { return DITypeRef(getRawBaseType()); } + DINodeArray getElements() const { + return cast_or_null(getRawElements()); + } + DITypeRef getVTableHolder() const { return DITypeRef(getRawVTableHolder()); } + DITemplateParameterArray getTemplateParams() const { + return cast_or_null(getRawTemplateParams()); + } + StringRef getIdentifier() const { return getStringOperand(7); } + unsigned getRuntimeLang() const { return RuntimeLang; } + + Metadata *getRawBaseType() const { return getOperand(3); } + Metadata *getRawElements() const { return getOperand(4); } + Metadata *getRawVTableHolder() const { return getOperand(5); } + Metadata *getRawTemplateParams() const { return getOperand(6); } + MDString *getRawIdentifier() const { return getOperandAs(7); } + + /// \brief Replace operands. + /// + /// If this \a isUniqued() and not \a isResolved(), on a uniquing collision + /// this will be RAUW'ed and deleted. Use a \a TrackingMDRef to keep track + /// of its movement if necessary. + /// @{ + void replaceElements(DINodeArray Elements) { +#ifndef NDEBUG + for (DINode *Op : getElements()) + assert(std::find(Elements->op_begin(), Elements->op_end(), Op) && + "Lost a member during member list replacement"); +#endif + replaceOperandWith(4, Elements.get()); + } + void replaceVTableHolder(DITypeRef VTableHolder) { + replaceOperandWith(5, VTableHolder); + } + void replaceTemplateParams(DITemplateParameterArray TemplateParams) { + replaceOperandWith(6, TemplateParams.get()); + } + /// @} static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDCompositeTypeKind; + return MD->getMetadataID() == DICompositeTypeKind; } }; -template TypedDebugNodeRef TypedDebugNodeRef::get(const T *N) { +template TypedDINodeRef TypedDINodeRef::get(const T *N) { if (N) - if (auto *Composite = dyn_cast(N)) + if (auto *Composite = dyn_cast(N)) if (auto *S = Composite->getRawIdentifier()) - return TypedDebugNodeRef(S); - return TypedDebugNodeRef(N); + return TypedDINodeRef(S); + return TypedDINodeRef(N); } /// \brief Type array for a subprogram. /// -/// TODO: Detach from CompositeType, and fold the array of types in directly -/// as operands. -class MDSubroutineType : public MDCompositeTypeBase { +/// TODO: Fold the array of types in directly as operands. +class DISubroutineType : public DIType { friend class LLVMContextImpl; friend class MDNode; - MDSubroutineType(LLVMContext &C, StorageType Storage, unsigned Flags, + DISubroutineType(LLVMContext &C, StorageType Storage, unsigned Flags, ArrayRef Ops) - : MDCompositeTypeBase(C, MDSubroutineTypeKind, Storage, - dwarf::DW_TAG_subroutine_type, 0, 0, 0, 0, 0, Flags, - Ops) {} - ~MDSubroutineType() = default; + : DIType(C, DISubroutineTypeKind, Storage, dwarf::DW_TAG_subroutine_type, + 0, 0, 0, 0, Flags, Ops) {} + ~DISubroutineType() = default; - static MDSubroutineType *getImpl(LLVMContext &Context, unsigned Flags, - MDTypeRefArray TypeArray, + static DISubroutineType *getImpl(LLVMContext &Context, unsigned Flags, + DITypeRefArray TypeArray, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Flags, TypeArray.get(), Storage, ShouldCreate); } - static MDSubroutineType *getImpl(LLVMContext &Context, unsigned Flags, + static DISubroutineType *getImpl(LLVMContext &Context, unsigned Flags, Metadata *TypeArray, StorageType Storage, bool ShouldCreate = true); - TempMDSubroutineType cloneImpl() const { + TempDISubroutineType cloneImpl() const { return getTemporary(getContext(), getFlags(), getTypeArray()); } public: - DEFINE_MDNODE_GET(MDSubroutineType, - (unsigned Flags, MDTypeRefArray TypeArray), + DEFINE_MDNODE_GET(DISubroutineType, + (unsigned Flags, DITypeRefArray TypeArray), (Flags, TypeArray)) - DEFINE_MDNODE_GET(MDSubroutineType, (unsigned Flags, Metadata *TypeArray), + DEFINE_MDNODE_GET(DISubroutineType, (unsigned Flags, Metadata *TypeArray), (Flags, TypeArray)) - TempMDSubroutineType clone() const { return cloneImpl(); } + TempDISubroutineType clone() const { return cloneImpl(); } - MDTypeRefArray getTypeArray() const { + DITypeRefArray getTypeArray() const { return cast_or_null(getRawTypeArray()); } - Metadata *getRawTypeArray() const { return getRawElements(); } + Metadata *getRawTypeArray() const { return getOperand(3); } static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDSubroutineTypeKind; + return MD->getMetadataID() == DISubroutineTypeKind; } }; /// \brief Compile unit. -class MDCompileUnit : public MDScope { +class DICompileUnit : public DIScope { friend class LLVMContextImpl; friend class MDNode; @@ -977,74 +926,76 @@ class MDCompileUnit : public MDScope { bool IsOptimized; unsigned RuntimeVersion; unsigned EmissionKind; + uint64_t DWOId; - MDCompileUnit(LLVMContext &C, StorageType Storage, unsigned SourceLanguage, + DICompileUnit(LLVMContext &C, StorageType Storage, unsigned SourceLanguage, bool IsOptimized, unsigned RuntimeVersion, - unsigned EmissionKind, ArrayRef Ops) - : MDScope(C, MDCompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops), + unsigned EmissionKind, uint64_t DWOId, ArrayRef Ops) + : DIScope(C, DICompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops), SourceLanguage(SourceLanguage), IsOptimized(IsOptimized), - RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind) {} - ~MDCompileUnit() = default; + RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind), + DWOId(DWOId) {} + ~DICompileUnit() = default; - static MDCompileUnit * - getImpl(LLVMContext &Context, unsigned SourceLanguage, MDFile *File, + static DICompileUnit * + getImpl(LLVMContext &Context, unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, - unsigned EmissionKind, MDCompositeTypeArray EnumTypes, - MDTypeArray RetainedTypes, MDSubprogramArray Subprograms, - MDGlobalVariableArray GlobalVariables, - MDImportedEntityArray ImportedEntities, StorageType Storage, - bool ShouldCreate = true) { - return getImpl( - Context, SourceLanguage, File, getCanonicalMDString(Context, Producer), - IsOptimized, getCanonicalMDString(Context, Flags), RuntimeVersion, - getCanonicalMDString(Context, SplitDebugFilename), EmissionKind, - EnumTypes.get(), RetainedTypes.get(), Subprograms.get(), - GlobalVariables.get(), ImportedEntities.get(), Storage, ShouldCreate); - } - static MDCompileUnit * + unsigned EmissionKind, DICompositeTypeArray EnumTypes, + DITypeArray RetainedTypes, DISubprogramArray Subprograms, + DIGlobalVariableArray GlobalVariables, + DIImportedEntityArray ImportedEntities, uint64_t DWOId, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, SourceLanguage, File, + getCanonicalMDString(Context, Producer), IsOptimized, + getCanonicalMDString(Context, Flags), RuntimeVersion, + getCanonicalMDString(Context, SplitDebugFilename), + EmissionKind, EnumTypes.get(), RetainedTypes.get(), + Subprograms.get(), GlobalVariables.get(), + ImportedEntities.get(), DWOId, Storage, ShouldCreate); + } + static DICompileUnit * getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, MDString *Producer, bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, Metadata *Subprograms, Metadata *GlobalVariables, - Metadata *ImportedEntities, StorageType Storage, + Metadata *ImportedEntities, uint64_t DWOId, StorageType Storage, bool ShouldCreate = true); - TempMDCompileUnit cloneImpl() const { + TempDICompileUnit cloneImpl() const { return getTemporary( getContext(), getSourceLanguage(), getFile(), getProducer(), isOptimized(), getFlags(), getRuntimeVersion(), getSplitDebugFilename(), getEmissionKind(), getEnumTypes(), getRetainedTypes(), getSubprograms(), - getGlobalVariables(), getImportedEntities()); + getGlobalVariables(), getImportedEntities(), DWOId); } public: - DEFINE_MDNODE_GET(MDCompileUnit, - (unsigned SourceLanguage, MDFile *File, StringRef Producer, + DEFINE_MDNODE_GET(DICompileUnit, + (unsigned SourceLanguage, DIFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, unsigned EmissionKind, - MDCompositeTypeArray EnumTypes, MDTypeArray RetainedTypes, - MDSubprogramArray Subprograms, - MDGlobalVariableArray GlobalVariables, - MDImportedEntityArray ImportedEntities), + DICompositeTypeArray EnumTypes, DITypeArray RetainedTypes, + DISubprogramArray Subprograms, + DIGlobalVariableArray GlobalVariables, + DIImportedEntityArray ImportedEntities, uint64_t DWOId), (SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, Subprograms, GlobalVariables, - ImportedEntities)) - DEFINE_MDNODE_GET(MDCompileUnit, - (unsigned SourceLanguage, Metadata *File, - MDString *Producer, bool IsOptimized, MDString *Flags, - unsigned RuntimeVersion, MDString *SplitDebugFilename, - unsigned EmissionKind, Metadata *EnumTypes, - Metadata *RetainedTypes, Metadata *Subprograms, - Metadata *GlobalVariables, Metadata *ImportedEntities), - (SourceLanguage, File, Producer, IsOptimized, Flags, - RuntimeVersion, SplitDebugFilename, EmissionKind, - EnumTypes, RetainedTypes, Subprograms, GlobalVariables, - ImportedEntities)) - - TempMDCompileUnit clone() const { return cloneImpl(); } + ImportedEntities, DWOId)) + DEFINE_MDNODE_GET( + DICompileUnit, + (unsigned SourceLanguage, Metadata *File, MDString *Producer, + bool IsOptimized, MDString *Flags, unsigned RuntimeVersion, + MDString *SplitDebugFilename, unsigned EmissionKind, Metadata *EnumTypes, + Metadata *RetainedTypes, Metadata *Subprograms, + Metadata *GlobalVariables, Metadata *ImportedEntities, uint64_t DWOId), + (SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion, + SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, Subprograms, + GlobalVariables, ImportedEntities, DWOId)) + + TempDICompileUnit clone() const { return cloneImpl(); } unsigned getSourceLanguage() const { return SourceLanguage; } bool isOptimized() const { return IsOptimized; } @@ -1053,21 +1004,22 @@ class MDCompileUnit : public MDScope { StringRef getProducer() const { return getStringOperand(1); } StringRef getFlags() const { return getStringOperand(2); } StringRef getSplitDebugFilename() const { return getStringOperand(3); } - MDCompositeTypeArray getEnumTypes() const { + DICompositeTypeArray getEnumTypes() const { return cast_or_null(getRawEnumTypes()); } - MDTypeArray getRetainedTypes() const { + DITypeArray getRetainedTypes() const { return cast_or_null(getRawRetainedTypes()); } - MDSubprogramArray getSubprograms() const { + DISubprogramArray getSubprograms() const { return cast_or_null(getRawSubprograms()); } - MDGlobalVariableArray getGlobalVariables() const { + DIGlobalVariableArray getGlobalVariables() const { return cast_or_null(getRawGlobalVariables()); } - MDImportedEntityArray getImportedEntities() const { + DIImportedEntityArray getImportedEntities() const { return cast_or_null(getRawImportedEntities()); } + unsigned getDWOId() const { return DWOId; } MDString *getRawProducer() const { return getOperandAs(1); } MDString *getRawFlags() const { return getOperandAs(2); } @@ -1084,71 +1036,80 @@ class MDCompileUnit : public MDScope { /// /// If this \a isUniqued() and not \a isResolved(), it will be RAUW'ed and /// deleted on a uniquing collision. In practice, uniquing collisions on \a - /// MDCompileUnit should be fairly rare. + /// DICompileUnit should be fairly rare. /// @{ - void replaceSubprograms(MDSubprogramArray N) { + void replaceEnumTypes(DICompositeTypeArray N) { + replaceOperandWith(4, N.get()); + } + void replaceRetainedTypes(DITypeArray N) { + replaceOperandWith(5, N.get()); + } + void replaceSubprograms(DISubprogramArray N) { replaceOperandWith(6, N.get()); } - void replaceGlobalVariables(MDGlobalVariableArray N) { + void replaceGlobalVariables(DIGlobalVariableArray N) { replaceOperandWith(7, N.get()); } + void replaceImportedEntities(DIImportedEntityArray N) { + replaceOperandWith(8, N.get()); + } /// @} static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDCompileUnitKind; + return MD->getMetadataID() == DICompileUnitKind; } }; /// \brief A scope for locals. /// /// A legal scope for lexical blocks, local variables, and debug info -/// locations. Subclasses are \a MDSubprogram, \a MDLexicalBlock, and \a -/// MDLexicalBlockFile. -class MDLocalScope : public MDScope { +/// locations. Subclasses are \a DISubprogram, \a DILexicalBlock, and \a +/// DILexicalBlockFile. +class DILocalScope : public DIScope { protected: - MDLocalScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + DILocalScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, ArrayRef Ops) - : MDScope(C, ID, Storage, Tag, Ops) {} - ~MDLocalScope() = default; + : DIScope(C, ID, Storage, Tag, Ops) {} + ~DILocalScope() = default; public: /// \brief Get the subprogram for this scope. /// - /// Return this if it's an \a MDSubprogram; otherwise, look up the scope + /// Return this if it's an \a DISubprogram; otherwise, look up the scope /// chain. - MDSubprogram *getSubprogram() const; + DISubprogram *getSubprogram() const; static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDSubprogramKind || - MD->getMetadataID() == MDLexicalBlockKind || - MD->getMetadataID() == MDLexicalBlockFileKind; + return MD->getMetadataID() == DISubprogramKind || + MD->getMetadataID() == DILexicalBlockKind || + MD->getMetadataID() == DILexicalBlockFileKind; } }; /// \brief Debug location. /// /// A debug location in source code, used for debug info and otherwise. -class MDLocation : public MDNode { +class DILocation : public MDNode { friend class LLVMContextImpl; friend class MDNode; - MDLocation(LLVMContext &C, StorageType Storage, unsigned Line, + DILocation(LLVMContext &C, StorageType Storage, unsigned Line, unsigned Column, ArrayRef MDs); - ~MDLocation() { dropAllReferences(); } + ~DILocation() { dropAllReferences(); } - static MDLocation *getImpl(LLVMContext &Context, unsigned Line, + static DILocation *getImpl(LLVMContext &Context, unsigned Line, unsigned Column, Metadata *Scope, Metadata *InlinedAt, StorageType Storage, bool ShouldCreate = true); - static MDLocation *getImpl(LLVMContext &Context, unsigned Line, - unsigned Column, MDLocalScope *Scope, - MDLocation *InlinedAt, StorageType Storage, + static DILocation *getImpl(LLVMContext &Context, unsigned Line, + unsigned Column, DILocalScope *Scope, + DILocation *InlinedAt, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Line, Column, static_cast(Scope), static_cast(InlinedAt), Storage, ShouldCreate); } - TempMDLocation cloneImpl() const { + TempDILocation cloneImpl() const { return getTemporary(getContext(), getLine(), getColumn(), getScope(), getInlinedAt()); } @@ -1157,28 +1118,26 @@ class MDLocation : public MDNode { void replaceOperandWith(unsigned I, Metadata *New) = delete; public: - DEFINE_MDNODE_GET(MDLocation, + DEFINE_MDNODE_GET(DILocation, (unsigned Line, unsigned Column, Metadata *Scope, Metadata *InlinedAt = nullptr), (Line, Column, Scope, InlinedAt)) - DEFINE_MDNODE_GET(MDLocation, - (unsigned Line, unsigned Column, MDLocalScope *Scope, - MDLocation *InlinedAt = nullptr), + DEFINE_MDNODE_GET(DILocation, + (unsigned Line, unsigned Column, DILocalScope *Scope, + DILocation *InlinedAt = nullptr), (Line, Column, Scope, InlinedAt)) /// \brief Return a (temporary) clone of this. - TempMDLocation clone() const { return cloneImpl(); } + TempDILocation clone() const { return cloneImpl(); } unsigned getLine() const { return SubclassData32; } unsigned getColumn() const { return SubclassData16; } - MDLocalScope *getScope() const { - return cast(getRawScope()); - } - MDLocation *getInlinedAt() const { - return cast_or_null(getRawInlinedAt()); + DILocalScope *getScope() const { return cast(getRawScope()); } + DILocation *getInlinedAt() const { + return cast_or_null(getRawInlinedAt()); } - MDFile *getFile() const { return getScope()->getFile(); } + DIFile *getFile() const { return getScope()->getFile(); } StringRef getFilename() const { return getScope()->getFilename(); } StringRef getDirectory() const { return getScope()->getDirectory(); } @@ -1186,7 +1145,7 @@ class MDLocation : public MDNode { /// /// Walk through \a getInlinedAt() and return \a getScope() from the deepest /// location. - MDLocalScope *getInlinedAtScope() const { + DILocalScope *getInlinedAtScope() const { if (auto *IA = getInlinedAt()) return IA->getInlinedAtScope(); return getScope(); @@ -1205,7 +1164,7 @@ class MDLocation : public MDNode { /// FIXME: Add a check for getColumn(). /// FIXME: Change the getFilename() check to getFile() (or add one for /// getDirectory()). - bool canDiscriminate(const MDLocation &RHS) const { + bool canDiscriminate(const DILocation &RHS) const { return getFilename() != RHS.getFilename() || getLine() != RHS.getLine(); } @@ -1232,7 +1191,7 @@ class MDLocation : public MDNode { } static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDLocationKind; + return MD->getMetadataID() == DILocationKind; } }; @@ -1240,7 +1199,7 @@ class MDLocation : public MDNode { /// /// TODO: Remove DisplayName. It's always equal to Name. /// TODO: Split up flags. -class MDSubprogram : public MDLocalScope { +class DISubprogram : public DILocalScope { friend class LLVMContextImpl; friend class MDNode; @@ -1253,25 +1212,25 @@ class MDSubprogram : public MDLocalScope { bool IsDefinition; bool IsOptimized; - MDSubprogram(LLVMContext &C, StorageType Storage, unsigned Line, + DISubprogram(LLVMContext &C, StorageType Storage, unsigned Line, unsigned ScopeLine, unsigned Virtuality, unsigned VirtualIndex, unsigned Flags, bool IsLocalToUnit, bool IsDefinition, bool IsOptimized, ArrayRef Ops) - : MDLocalScope(C, MDSubprogramKind, Storage, dwarf::DW_TAG_subprogram, + : DILocalScope(C, DISubprogramKind, Storage, dwarf::DW_TAG_subprogram, Ops), Line(Line), ScopeLine(ScopeLine), Virtuality(Virtuality), VirtualIndex(VirtualIndex), Flags(Flags), IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition), IsOptimized(IsOptimized) {} - ~MDSubprogram() = default; + ~DISubprogram() = default; - static MDSubprogram * - getImpl(LLVMContext &Context, MDScopeRef Scope, StringRef Name, - StringRef LinkageName, MDFile *File, unsigned Line, - MDSubroutineType *Type, bool IsLocalToUnit, bool IsDefinition, - unsigned ScopeLine, MDTypeRef ContainingType, unsigned Virtuality, + static DISubprogram * + getImpl(LLVMContext &Context, DIScopeRef Scope, StringRef Name, + StringRef LinkageName, DIFile *File, unsigned Line, + DISubroutineType *Type, bool IsLocalToUnit, bool IsDefinition, + unsigned ScopeLine, DITypeRef ContainingType, unsigned Virtuality, unsigned VirtualIndex, unsigned Flags, bool IsOptimized, - Constant *Function, MDTemplateParameterArray TemplateParams, - MDSubprogram *Declaration, MDLocalVariableArray Variables, + Constant *Function, DITemplateParameterArray TemplateParams, + DISubprogram *Declaration, DILocalVariableArray Variables, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), getCanonicalMDString(Context, LinkageName), File, Line, Type, @@ -1281,7 +1240,7 @@ class MDSubprogram : public MDLocalScope { TemplateParams.get(), Declaration, Variables.get(), Storage, ShouldCreate); } - static MDSubprogram * + static DISubprogram * getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, @@ -1290,7 +1249,7 @@ class MDSubprogram : public MDLocalScope { Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables, StorageType Storage, bool ShouldCreate = true); - TempMDSubprogram cloneImpl() const { + TempDISubprogram cloneImpl() const { return getTemporary(getContext(), getScope(), getName(), getLinkageName(), getFile(), getLine(), getType(), isLocalToUnit(), isDefinition(), getScopeLine(), getContainingType(), @@ -1300,22 +1259,22 @@ class MDSubprogram : public MDLocalScope { } public: - DEFINE_MDNODE_GET(MDSubprogram, - (MDScopeRef Scope, StringRef Name, StringRef LinkageName, - MDFile *File, unsigned Line, MDSubroutineType *Type, + DEFINE_MDNODE_GET(DISubprogram, + (DIScopeRef Scope, StringRef Name, StringRef LinkageName, + DIFile *File, unsigned Line, DISubroutineType *Type, bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, - MDTypeRef ContainingType, unsigned Virtuality, + DITypeRef ContainingType, unsigned Virtuality, unsigned VirtualIndex, unsigned Flags, bool IsOptimized, Constant *Function = nullptr, - MDTemplateParameterArray TemplateParams = nullptr, - MDSubprogram *Declaration = nullptr, - MDLocalVariableArray Variables = nullptr), + DITemplateParameterArray TemplateParams = nullptr, + DISubprogram *Declaration = nullptr, + DILocalVariableArray Variables = nullptr), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, IsOptimized, Function, TemplateParams, Declaration, Variables)) DEFINE_MDNODE_GET( - MDSubprogram, + DISubprogram, (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality, @@ -1326,7 +1285,7 @@ class MDSubprogram : public MDLocalScope { ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, IsOptimized, Function, TemplateParams, Declaration, Variables)) - TempMDSubprogram clone() const { return cloneImpl(); } + TempDISubprogram clone() const { return cloneImpl(); } public: unsigned getLine() const { return Line; } @@ -1367,7 +1326,7 @@ class MDSubprogram : public MDLocalScope { return getFlags() & FlagRValueReference; } - MDScopeRef getScope() const { return MDScopeRef(getRawScope()); } + DIScopeRef getScope() const { return DIScopeRef(getRawScope()); } StringRef getName() const { return getStringOperand(2); } StringRef getDisplayName() const { return getStringOperand(3); } @@ -1376,11 +1335,11 @@ class MDSubprogram : public MDLocalScope { MDString *getRawName() const { return getOperandAs(2); } MDString *getRawLinkageName() const { return getOperandAs(4); } - MDSubroutineType *getType() const { - return cast_or_null(getRawType()); + DISubroutineType *getType() const { + return cast_or_null(getRawType()); } - MDTypeRef getContainingType() const { - return MDTypeRef(getRawContainingType()); + DITypeRef getContainingType() const { + return DITypeRef(getRawContainingType()); } Constant *getFunctionConstant() const { @@ -1388,13 +1347,13 @@ class MDSubprogram : public MDLocalScope { return C->getValue(); return nullptr; } - MDTemplateParameterArray getTemplateParams() const { + DITemplateParameterArray getTemplateParams() const { return cast_or_null(getRawTemplateParams()); } - MDSubprogram *getDeclaration() const { - return cast_or_null(getRawDeclaration()); + DISubprogram *getDeclaration() const { + return cast_or_null(getRawDeclaration()); } - MDLocalVariableArray getVariables() const { + DILocalVariableArray getVariables() const { return cast_or_null(getRawVariables()); } @@ -1430,50 +1389,50 @@ class MDSubprogram : public MDLocalScope { bool describes(const Function *F) const; static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDSubprogramKind; + return MD->getMetadataID() == DISubprogramKind; } }; -class MDLexicalBlockBase : public MDLocalScope { +class DILexicalBlockBase : public DILocalScope { protected: - MDLexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, + DILexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, ArrayRef Ops) - : MDLocalScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {} - ~MDLexicalBlockBase() = default; + : DILocalScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {} + ~DILexicalBlockBase() = default; public: - MDLocalScope *getScope() const { return cast(getRawScope()); } + DILocalScope *getScope() const { return cast(getRawScope()); } Metadata *getRawScope() const { return getOperand(1); } /// \brief Forwarding accessors to LexicalBlock. /// - /// TODO: Remove these and update code to use \a MDLexicalBlock directly. + /// TODO: Remove these and update code to use \a DILexicalBlock directly. /// @{ inline unsigned getLine() const; inline unsigned getColumn() const; /// @} static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDLexicalBlockKind || - MD->getMetadataID() == MDLexicalBlockFileKind; + return MD->getMetadataID() == DILexicalBlockKind || + MD->getMetadataID() == DILexicalBlockFileKind; } }; -class MDLexicalBlock : public MDLexicalBlockBase { +class DILexicalBlock : public DILexicalBlockBase { friend class LLVMContextImpl; friend class MDNode; unsigned Line; unsigned Column; - MDLexicalBlock(LLVMContext &C, StorageType Storage, unsigned Line, + DILexicalBlock(LLVMContext &C, StorageType Storage, unsigned Line, unsigned Column, ArrayRef Ops) - : MDLexicalBlockBase(C, MDLexicalBlockKind, Storage, Ops), Line(Line), + : DILexicalBlockBase(C, DILexicalBlockKind, Storage, Ops), Line(Line), Column(Column) {} - ~MDLexicalBlock() = default; + ~DILexicalBlock() = default; - static MDLexicalBlock *getImpl(LLVMContext &Context, MDLocalScope *Scope, - MDFile *File, unsigned Line, unsigned Column, + static DILexicalBlock *getImpl(LLVMContext &Context, DILocalScope *Scope, + DIFile *File, unsigned Line, unsigned Column, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, static_cast(Scope), @@ -1481,59 +1440,59 @@ class MDLexicalBlock : public MDLexicalBlockBase { ShouldCreate); } - static MDLexicalBlock *getImpl(LLVMContext &Context, Metadata *Scope, + static DILexicalBlock *getImpl(LLVMContext &Context, Metadata *Scope, Metadata *File, unsigned Line, unsigned Column, StorageType Storage, bool ShouldCreate = true); - TempMDLexicalBlock cloneImpl() const { + TempDILexicalBlock cloneImpl() const { return getTemporary(getContext(), getScope(), getFile(), getLine(), getColumn()); } public: - DEFINE_MDNODE_GET(MDLexicalBlock, (MDLocalScope * Scope, MDFile *File, + DEFINE_MDNODE_GET(DILexicalBlock, (DILocalScope * Scope, DIFile *File, unsigned Line, unsigned Column), (Scope, File, Line, Column)) - DEFINE_MDNODE_GET(MDLexicalBlock, (Metadata * Scope, Metadata *File, + DEFINE_MDNODE_GET(DILexicalBlock, (Metadata * Scope, Metadata *File, unsigned Line, unsigned Column), (Scope, File, Line, Column)) - TempMDLexicalBlock clone() const { return cloneImpl(); } + TempDILexicalBlock clone() const { return cloneImpl(); } unsigned getLine() const { return Line; } unsigned getColumn() const { return Column; } static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDLexicalBlockKind; + return MD->getMetadataID() == DILexicalBlockKind; } }; -unsigned MDLexicalBlockBase::getLine() const { - if (auto *N = dyn_cast(this)) +unsigned DILexicalBlockBase::getLine() const { + if (auto *N = dyn_cast(this)) return N->getLine(); return 0; } -unsigned MDLexicalBlockBase::getColumn() const { - if (auto *N = dyn_cast(this)) +unsigned DILexicalBlockBase::getColumn() const { + if (auto *N = dyn_cast(this)) return N->getColumn(); return 0; } -class MDLexicalBlockFile : public MDLexicalBlockBase { +class DILexicalBlockFile : public DILexicalBlockBase { friend class LLVMContextImpl; friend class MDNode; unsigned Discriminator; - MDLexicalBlockFile(LLVMContext &C, StorageType Storage, + DILexicalBlockFile(LLVMContext &C, StorageType Storage, unsigned Discriminator, ArrayRef Ops) - : MDLexicalBlockBase(C, MDLexicalBlockFileKind, Storage, Ops), + : DILexicalBlockBase(C, DILexicalBlockFileKind, Storage, Ops), Discriminator(Discriminator) {} - ~MDLexicalBlockFile() = default; + ~DILexicalBlockFile() = default; - static MDLexicalBlockFile *getImpl(LLVMContext &Context, MDLocalScope *Scope, - MDFile *File, unsigned Discriminator, + static DILexicalBlockFile *getImpl(LLVMContext &Context, DILocalScope *Scope, + DIFile *File, unsigned Discriminator, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, static_cast(Scope), @@ -1541,213 +1500,273 @@ class MDLexicalBlockFile : public MDLexicalBlockBase { ShouldCreate); } - static MDLexicalBlockFile *getImpl(LLVMContext &Context, Metadata *Scope, + static DILexicalBlockFile *getImpl(LLVMContext &Context, Metadata *Scope, Metadata *File, unsigned Discriminator, StorageType Storage, bool ShouldCreate = true); - TempMDLexicalBlockFile cloneImpl() const { + TempDILexicalBlockFile cloneImpl() const { return getTemporary(getContext(), getScope(), getFile(), getDiscriminator()); } public: - DEFINE_MDNODE_GET(MDLexicalBlockFile, (MDLocalScope * Scope, MDFile *File, + DEFINE_MDNODE_GET(DILexicalBlockFile, (DILocalScope * Scope, DIFile *File, unsigned Discriminator), (Scope, File, Discriminator)) - DEFINE_MDNODE_GET(MDLexicalBlockFile, + DEFINE_MDNODE_GET(DILexicalBlockFile, (Metadata * Scope, Metadata *File, unsigned Discriminator), (Scope, File, Discriminator)) - TempMDLexicalBlockFile clone() const { return cloneImpl(); } + TempDILexicalBlockFile clone() const { return cloneImpl(); } - // TODO: Remove these once they're gone from MDLexicalBlockBase. + // TODO: Remove these once they're gone from DILexicalBlockBase. unsigned getLine() const = delete; unsigned getColumn() const = delete; unsigned getDiscriminator() const { return Discriminator; } static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDLexicalBlockFileKind; + return MD->getMetadataID() == DILexicalBlockFileKind; } }; -unsigned MDLocation::getDiscriminator() const { - if (auto *F = dyn_cast(getScope())) +unsigned DILocation::getDiscriminator() const { + if (auto *F = dyn_cast(getScope())) return F->getDiscriminator(); return 0; } -class MDNamespace : public MDScope { +class DINamespace : public DIScope { friend class LLVMContextImpl; friend class MDNode; unsigned Line; - MDNamespace(LLVMContext &Context, StorageType Storage, unsigned Line, + DINamespace(LLVMContext &Context, StorageType Storage, unsigned Line, ArrayRef Ops) - : MDScope(Context, MDNamespaceKind, Storage, dwarf::DW_TAG_namespace, + : DIScope(Context, DINamespaceKind, Storage, dwarf::DW_TAG_namespace, Ops), Line(Line) {} - ~MDNamespace() = default; + ~DINamespace() = default; - static MDNamespace *getImpl(LLVMContext &Context, MDScope *Scope, - MDFile *File, StringRef Name, unsigned Line, + static DINamespace *getImpl(LLVMContext &Context, DIScope *Scope, + DIFile *File, StringRef Name, unsigned Line, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, File, getCanonicalMDString(Context, Name), Line, Storage, ShouldCreate); } - static MDNamespace *getImpl(LLVMContext &Context, Metadata *Scope, + static DINamespace *getImpl(LLVMContext &Context, Metadata *Scope, Metadata *File, MDString *Name, unsigned Line, StorageType Storage, bool ShouldCreate = true); - TempMDNamespace cloneImpl() const { + TempDINamespace cloneImpl() const { return getTemporary(getContext(), getScope(), getFile(), getName(), getLine()); } public: - DEFINE_MDNODE_GET(MDNamespace, (MDScope * Scope, MDFile *File, StringRef Name, + DEFINE_MDNODE_GET(DINamespace, (DIScope * Scope, DIFile *File, StringRef Name, unsigned Line), (Scope, File, Name, Line)) - DEFINE_MDNODE_GET(MDNamespace, (Metadata * Scope, Metadata *File, + DEFINE_MDNODE_GET(DINamespace, (Metadata * Scope, Metadata *File, MDString *Name, unsigned Line), (Scope, File, Name, Line)) - TempMDNamespace clone() const { return cloneImpl(); } + TempDINamespace clone() const { return cloneImpl(); } unsigned getLine() const { return Line; } - MDScope *getScope() const { return cast_or_null(getRawScope()); } + DIScope *getScope() const { return cast_or_null(getRawScope()); } StringRef getName() const { return getStringOperand(2); } Metadata *getRawScope() const { return getOperand(1); } MDString *getRawName() const { return getOperandAs(2); } static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDNamespaceKind; + return MD->getMetadataID() == DINamespaceKind; + } +}; + +/// \brief A (clang) module that has been imported by the compile unit. +/// +class DIModule : public DIScope { + friend class LLVMContextImpl; + friend class MDNode; + + DIModule(LLVMContext &Context, StorageType Storage, ArrayRef Ops) + : DIScope(Context, DIModuleKind, Storage, dwarf::DW_TAG_module, Ops) {} + ~DIModule() {} + + static DIModule *getImpl(LLVMContext &Context, DIScope *Scope, + StringRef Name, StringRef ConfigurationMacros, + StringRef IncludePath, StringRef ISysRoot, + StorageType Storage, bool ShouldCreate = true) { + return getImpl(Context, Scope, getCanonicalMDString(Context, Name), + getCanonicalMDString(Context, ConfigurationMacros), + getCanonicalMDString(Context, IncludePath), + getCanonicalMDString(Context, ISysRoot), + Storage, ShouldCreate); + } + static DIModule *getImpl(LLVMContext &Context, Metadata *Scope, + MDString *Name, MDString *ConfigurationMacros, + MDString *IncludePath, MDString *ISysRoot, + StorageType Storage, bool ShouldCreate = true); + + TempDIModule cloneImpl() const { + return getTemporary(getContext(), getScope(), getName(), + getConfigurationMacros(), getIncludePath(), + getISysRoot()); + } + +public: + DEFINE_MDNODE_GET(DIModule, (DIScope *Scope, StringRef Name, + StringRef ConfigurationMacros, StringRef IncludePath, + StringRef ISysRoot), + (Scope, Name, ConfigurationMacros, IncludePath, ISysRoot)) + DEFINE_MDNODE_GET(DIModule, + (Metadata *Scope, MDString *Name, MDString *ConfigurationMacros, + MDString *IncludePath, MDString *ISysRoot), + (Scope, Name, ConfigurationMacros, IncludePath, ISysRoot)) + + TempDIModule clone() const { return cloneImpl(); } + + DIScope *getScope() const { return cast_or_null(getRawScope()); } + StringRef getName() const { return getStringOperand(1); } + StringRef getConfigurationMacros() const { return getStringOperand(2); } + StringRef getIncludePath() const { return getStringOperand(3); } + StringRef getISysRoot() const { return getStringOperand(4); } + + Metadata *getRawScope() const { return getOperand(0); } + MDString *getRawName() const { return getOperandAs(1); } + MDString *getRawConfigurationMacros() const { return getOperandAs(2); } + MDString *getRawIncludePath() const { return getOperandAs(3); } + MDString *getRawISysRoot() const { return getOperandAs(4); } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == DIModuleKind; } }; /// \brief Base class for template parameters. -class MDTemplateParameter : public DebugNode { +class DITemplateParameter : public DINode { protected: - MDTemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage, + DITemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage, unsigned Tag, ArrayRef Ops) - : DebugNode(Context, ID, Storage, Tag, Ops) {} - ~MDTemplateParameter() = default; + : DINode(Context, ID, Storage, Tag, Ops) {} + ~DITemplateParameter() = default; public: StringRef getName() const { return getStringOperand(0); } - MDTypeRef getType() const { return MDTypeRef(getRawType()); } + DITypeRef getType() const { return DITypeRef(getRawType()); } MDString *getRawName() const { return getOperandAs(0); } Metadata *getRawType() const { return getOperand(1); } static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDTemplateTypeParameterKind || - MD->getMetadataID() == MDTemplateValueParameterKind; + return MD->getMetadataID() == DITemplateTypeParameterKind || + MD->getMetadataID() == DITemplateValueParameterKind; } }; -class MDTemplateTypeParameter : public MDTemplateParameter { +class DITemplateTypeParameter : public DITemplateParameter { friend class LLVMContextImpl; friend class MDNode; - MDTemplateTypeParameter(LLVMContext &Context, StorageType Storage, + DITemplateTypeParameter(LLVMContext &Context, StorageType Storage, ArrayRef Ops) - : MDTemplateParameter(Context, MDTemplateTypeParameterKind, Storage, + : DITemplateParameter(Context, DITemplateTypeParameterKind, Storage, dwarf::DW_TAG_template_type_parameter, Ops) {} - ~MDTemplateTypeParameter() = default; + ~DITemplateTypeParameter() = default; - static MDTemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name, - MDTypeRef Type, StorageType Storage, + static DITemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name, + DITypeRef Type, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, getCanonicalMDString(Context, Name), Type, Storage, ShouldCreate); } - static MDTemplateTypeParameter *getImpl(LLVMContext &Context, MDString *Name, + static DITemplateTypeParameter *getImpl(LLVMContext &Context, MDString *Name, Metadata *Type, StorageType Storage, bool ShouldCreate = true); - TempMDTemplateTypeParameter cloneImpl() const { + TempDITemplateTypeParameter cloneImpl() const { return getTemporary(getContext(), getName(), getType()); } public: - DEFINE_MDNODE_GET(MDTemplateTypeParameter, (StringRef Name, MDTypeRef Type), + DEFINE_MDNODE_GET(DITemplateTypeParameter, (StringRef Name, DITypeRef Type), (Name, Type)) - DEFINE_MDNODE_GET(MDTemplateTypeParameter, (MDString * Name, Metadata *Type), + DEFINE_MDNODE_GET(DITemplateTypeParameter, (MDString * Name, Metadata *Type), (Name, Type)) - TempMDTemplateTypeParameter clone() const { return cloneImpl(); } + TempDITemplateTypeParameter clone() const { return cloneImpl(); } static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDTemplateTypeParameterKind; + return MD->getMetadataID() == DITemplateTypeParameterKind; } }; -class MDTemplateValueParameter : public MDTemplateParameter { +class DITemplateValueParameter : public DITemplateParameter { friend class LLVMContextImpl; friend class MDNode; - MDTemplateValueParameter(LLVMContext &Context, StorageType Storage, + DITemplateValueParameter(LLVMContext &Context, StorageType Storage, unsigned Tag, ArrayRef Ops) - : MDTemplateParameter(Context, MDTemplateValueParameterKind, Storage, Tag, + : DITemplateParameter(Context, DITemplateValueParameterKind, Storage, Tag, Ops) {} - ~MDTemplateValueParameter() = default; + ~DITemplateValueParameter() = default; - static MDTemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, - StringRef Name, MDTypeRef Type, + static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, + StringRef Name, DITypeRef Type, Metadata *Value, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type, Value, Storage, ShouldCreate); } - static MDTemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, + static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *Type, Metadata *Value, StorageType Storage, bool ShouldCreate = true); - TempMDTemplateValueParameter cloneImpl() const { + TempDITemplateValueParameter cloneImpl() const { return getTemporary(getContext(), getTag(), getName(), getType(), getValue()); } public: - DEFINE_MDNODE_GET(MDTemplateValueParameter, (unsigned Tag, StringRef Name, - MDTypeRef Type, Metadata *Value), + DEFINE_MDNODE_GET(DITemplateValueParameter, (unsigned Tag, StringRef Name, + DITypeRef Type, Metadata *Value), (Tag, Name, Type, Value)) - DEFINE_MDNODE_GET(MDTemplateValueParameter, (unsigned Tag, MDString *Name, + DEFINE_MDNODE_GET(DITemplateValueParameter, (unsigned Tag, MDString *Name, Metadata *Type, Metadata *Value), (Tag, Name, Type, Value)) - TempMDTemplateValueParameter clone() const { return cloneImpl(); } + TempDITemplateValueParameter clone() const { return cloneImpl(); } Metadata *getValue() const { return getOperand(2); } static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDTemplateValueParameterKind; + return MD->getMetadataID() == DITemplateValueParameterKind; } }; /// \brief Base class for variables. /// /// TODO: Hardcode to DW_TAG_variable. -class MDVariable : public DebugNode { +class DIVariable : public DINode { unsigned Line; protected: - MDVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, + DIVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, unsigned Line, ArrayRef Ops) - : DebugNode(C, ID, Storage, Tag, Ops), Line(Line) {} - ~MDVariable() = default; + : DINode(C, ID, Storage, Tag, Ops), Line(Line) {} + ~DIVariable() = default; public: unsigned getLine() const { return Line; } - MDScope *getScope() const { return cast_or_null(getRawScope()); } + DIScope *getScope() const { return cast_or_null(getRawScope()); } StringRef getName() const { return getStringOperand(1); } - MDFile *getFile() const { return cast_or_null(getRawFile()); } - MDTypeRef getType() const { return MDTypeRef(getRawType()); } + DIFile *getFile() const { return cast_or_null(getRawFile()); } + DITypeRef getType() const { return DITypeRef(getRawType()); } StringRef getFilename() const { if (auto *F = getFile()) @@ -1766,34 +1785,34 @@ class MDVariable : public DebugNode { Metadata *getRawType() const { return getOperand(3); } static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDLocalVariableKind || - MD->getMetadataID() == MDGlobalVariableKind; + return MD->getMetadataID() == DILocalVariableKind || + MD->getMetadataID() == DIGlobalVariableKind; } }; /// \brief Global variables. /// /// TODO: Remove DisplayName. It's always equal to Name. -class MDGlobalVariable : public MDVariable { +class DIGlobalVariable : public DIVariable { friend class LLVMContextImpl; friend class MDNode; bool IsLocalToUnit; bool IsDefinition; - MDGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line, + DIGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line, bool IsLocalToUnit, bool IsDefinition, ArrayRef Ops) - : MDVariable(C, MDGlobalVariableKind, Storage, dwarf::DW_TAG_variable, + : DIVariable(C, DIGlobalVariableKind, Storage, dwarf::DW_TAG_variable, Line, Ops), IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {} - ~MDGlobalVariable() = default; + ~DIGlobalVariable() = default; - static MDGlobalVariable * - getImpl(LLVMContext &Context, MDScope *Scope, StringRef Name, - StringRef LinkageName, MDFile *File, unsigned Line, MDTypeRef Type, + static DIGlobalVariable * + getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, + StringRef LinkageName, DIFile *File, unsigned Line, DITypeRef Type, bool IsLocalToUnit, bool IsDefinition, Constant *Variable, - MDDerivedType *StaticDataMemberDeclaration, StorageType Storage, + DIDerivedType *StaticDataMemberDeclaration, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), getCanonicalMDString(Context, LinkageName), File, Line, Type, @@ -1801,14 +1820,14 @@ class MDGlobalVariable : public MDVariable { Variable ? ConstantAsMetadata::get(Variable) : nullptr, StaticDataMemberDeclaration, Storage, ShouldCreate); } - static MDGlobalVariable * + static DIGlobalVariable * getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, Metadata *StaticDataMemberDeclaration, StorageType Storage, bool ShouldCreate = true); - TempMDGlobalVariable cloneImpl() const { + TempDIGlobalVariable cloneImpl() const { return getTemporary(getContext(), getScope(), getName(), getLinkageName(), getFile(), getLine(), getType(), isLocalToUnit(), isDefinition(), getVariable(), @@ -1816,14 +1835,14 @@ class MDGlobalVariable : public MDVariable { } public: - DEFINE_MDNODE_GET(MDGlobalVariable, - (MDScope * Scope, StringRef Name, StringRef LinkageName, - MDFile *File, unsigned Line, MDTypeRef Type, + DEFINE_MDNODE_GET(DIGlobalVariable, + (DIScope * Scope, StringRef Name, StringRef LinkageName, + DIFile *File, unsigned Line, DITypeRef Type, bool IsLocalToUnit, bool IsDefinition, Constant *Variable, - MDDerivedType *StaticDataMemberDeclaration), + DIDerivedType *StaticDataMemberDeclaration), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, Variable, StaticDataMemberDeclaration)) - DEFINE_MDNODE_GET(MDGlobalVariable, + DEFINE_MDNODE_GET(DIGlobalVariable, (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, @@ -1831,7 +1850,7 @@ class MDGlobalVariable : public MDVariable { (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, Variable, StaticDataMemberDeclaration)) - TempMDGlobalVariable clone() const { return cloneImpl(); } + TempDIGlobalVariable clone() const { return cloneImpl(); } bool isLocalToUnit() const { return IsLocalToUnit; } bool isDefinition() const { return IsDefinition; } @@ -1842,8 +1861,8 @@ class MDGlobalVariable : public MDVariable { return dyn_cast(C->getValue()); return nullptr; } - MDDerivedType *getStaticDataMemberDeclaration() const { - return cast_or_null(getRawStaticDataMemberDeclaration()); + DIDerivedType *getStaticDataMemberDeclaration() const { + return cast_or_null(getRawStaticDataMemberDeclaration()); } MDString *getRawLinkageName() const { return getOperandAs(5); } @@ -1851,7 +1870,7 @@ class MDGlobalVariable : public MDVariable { Metadata *getRawStaticDataMemberDeclaration() const { return getOperand(7); } static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDGlobalVariableKind; + return MD->getMetadataID() == DIGlobalVariableKind; } }; @@ -1860,57 +1879,57 @@ class MDGlobalVariable : public MDVariable { /// TODO: Split between arguments and otherwise. /// TODO: Use \c DW_TAG_variable instead of fake tags. /// TODO: Split up flags. -class MDLocalVariable : public MDVariable { +class DILocalVariable : public DIVariable { friend class LLVMContextImpl; friend class MDNode; unsigned Arg; unsigned Flags; - MDLocalVariable(LLVMContext &C, StorageType Storage, unsigned Tag, + DILocalVariable(LLVMContext &C, StorageType Storage, unsigned Tag, unsigned Line, unsigned Arg, unsigned Flags, ArrayRef Ops) - : MDVariable(C, MDLocalVariableKind, Storage, Tag, Line, Ops), Arg(Arg), + : DIVariable(C, DILocalVariableKind, Storage, Tag, Line, Ops), Arg(Arg), Flags(Flags) {} - ~MDLocalVariable() = default; + ~DILocalVariable() = default; - static MDLocalVariable *getImpl(LLVMContext &Context, unsigned Tag, - MDScope *Scope, StringRef Name, MDFile *File, - unsigned Line, MDTypeRef Type, unsigned Arg, + static DILocalVariable *getImpl(LLVMContext &Context, unsigned Tag, + DIScope *Scope, StringRef Name, DIFile *File, + unsigned Line, DITypeRef Type, unsigned Arg, unsigned Flags, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, Scope, getCanonicalMDString(Context, Name), File, Line, Type, Arg, Flags, Storage, ShouldCreate); } - static MDLocalVariable * + static DILocalVariable * getImpl(LLVMContext &Context, unsigned Tag, Metadata *Scope, MDString *Name, Metadata *File, unsigned Line, Metadata *Type, unsigned Arg, unsigned Flags, StorageType Storage, bool ShouldCreate = true); - TempMDLocalVariable cloneImpl() const { + TempDILocalVariable cloneImpl() const { return getTemporary(getContext(), getTag(), getScope(), getName(), getFile(), getLine(), getType(), getArg(), getFlags()); } public: - DEFINE_MDNODE_GET(MDLocalVariable, - (unsigned Tag, MDLocalScope *Scope, StringRef Name, - MDFile *File, unsigned Line, MDTypeRef Type, unsigned Arg, + DEFINE_MDNODE_GET(DILocalVariable, + (unsigned Tag, DILocalScope *Scope, StringRef Name, + DIFile *File, unsigned Line, DITypeRef Type, unsigned Arg, unsigned Flags), (Tag, Scope, Name, File, Line, Type, Arg, Flags)) - DEFINE_MDNODE_GET(MDLocalVariable, + DEFINE_MDNODE_GET(DILocalVariable, (unsigned Tag, Metadata *Scope, MDString *Name, Metadata *File, unsigned Line, Metadata *Type, unsigned Arg, unsigned Flags), (Tag, Scope, Name, File, Line, Type, Arg, Flags)) - TempMDLocalVariable clone() const { return cloneImpl(); } + TempDILocalVariable clone() const { return cloneImpl(); } /// \brief Get the local scope for this variable. /// /// Variables must be defined in a local scope. - MDLocalScope *getScope() const { - return cast(MDVariable::getScope()); + DILocalScope *getScope() const { + return cast(DIVariable::getScope()); } unsigned getArg() const { return Arg; } @@ -1924,12 +1943,12 @@ class MDLocalVariable : public MDVariable { /// Check that \c DL exists, is in the same subprogram, and has the same /// inlined-at location as \c this. (Otherwise, it's not a valid attachemnt /// to a \a DbgInfoIntrinsic.) - bool isValidLocationForIntrinsic(const MDLocation *DL) const { + bool isValidLocationForIntrinsic(const DILocation *DL) const { return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); } static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDLocalVariableKind; + return MD->getMetadataID() == DILocalVariableKind; } }; @@ -1944,29 +1963,29 @@ class MDLocalVariable : public MDVariable { /// TODO: Co-allocate the expression elements. /// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary /// storage types. -class MDExpression : public MDNode { +class DIExpression : public MDNode { friend class LLVMContextImpl; friend class MDNode; std::vector Elements; - MDExpression(LLVMContext &C, StorageType Storage, ArrayRef Elements) - : MDNode(C, MDExpressionKind, Storage, None), + DIExpression(LLVMContext &C, StorageType Storage, ArrayRef Elements) + : MDNode(C, DIExpressionKind, Storage, None), Elements(Elements.begin(), Elements.end()) {} - ~MDExpression() = default; + ~DIExpression() = default; - static MDExpression *getImpl(LLVMContext &Context, + static DIExpression *getImpl(LLVMContext &Context, ArrayRef Elements, StorageType Storage, bool ShouldCreate = true); - TempMDExpression cloneImpl() const { + TempDIExpression cloneImpl() const { return getTemporary(getContext(), getElements()); } public: - DEFINE_MDNODE_GET(MDExpression, (ArrayRef Elements), (Elements)) + DEFINE_MDNODE_GET(DIExpression, (ArrayRef Elements), (Elements)) - TempMDExpression clone() const { return cloneImpl(); } + TempDIExpression clone() const { return cloneImpl(); } ArrayRef getElements() const { return Elements; } @@ -1991,7 +2010,7 @@ class MDExpression : public MDNode { /// \brief A lightweight wrapper around an expression operand. /// - /// TODO: Store arguments directly and change \a MDExpression to store a + /// TODO: Store arguments directly and change \a DIExpression to store a /// range of these. class ExprOperand { const uint64_t *Op; @@ -2076,73 +2095,68 @@ class MDExpression : public MDNode { bool isValid() const; static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDExpressionKind; + return MD->getMetadataID() == DIExpressionKind; } }; -class MDObjCProperty : public DebugNode { +class DIObjCProperty : public DINode { friend class LLVMContextImpl; friend class MDNode; unsigned Line; unsigned Attributes; - MDObjCProperty(LLVMContext &C, StorageType Storage, unsigned Line, + DIObjCProperty(LLVMContext &C, StorageType Storage, unsigned Line, unsigned Attributes, ArrayRef Ops) - : DebugNode(C, MDObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property, - Ops), + : DINode(C, DIObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property, + Ops), Line(Line), Attributes(Attributes) {} - ~MDObjCProperty() = default; + ~DIObjCProperty() = default; - static MDObjCProperty * - getImpl(LLVMContext &Context, StringRef Name, MDFile *File, unsigned Line, + static DIObjCProperty * + getImpl(LLVMContext &Context, StringRef Name, DIFile *File, unsigned Line, StringRef GetterName, StringRef SetterName, unsigned Attributes, - MDType *Type, StorageType Storage, bool ShouldCreate = true) { + DITypeRef Type, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, getCanonicalMDString(Context, Name), File, Line, getCanonicalMDString(Context, GetterName), getCanonicalMDString(Context, SetterName), Attributes, Type, Storage, ShouldCreate); } - static MDObjCProperty *getImpl(LLVMContext &Context, MDString *Name, + static DIObjCProperty *getImpl(LLVMContext &Context, MDString *Name, Metadata *File, unsigned Line, MDString *GetterName, MDString *SetterName, unsigned Attributes, Metadata *Type, StorageType Storage, bool ShouldCreate = true); - TempMDObjCProperty cloneImpl() const { + TempDIObjCProperty cloneImpl() const { return getTemporary(getContext(), getName(), getFile(), getLine(), getGetterName(), getSetterName(), getAttributes(), getType()); } public: - DEFINE_MDNODE_GET(MDObjCProperty, - (StringRef Name, MDFile *File, unsigned Line, + DEFINE_MDNODE_GET(DIObjCProperty, + (StringRef Name, DIFile *File, unsigned Line, StringRef GetterName, StringRef SetterName, - unsigned Attributes, MDType *Type), + unsigned Attributes, DITypeRef Type), (Name, File, Line, GetterName, SetterName, Attributes, Type)) - DEFINE_MDNODE_GET(MDObjCProperty, + DEFINE_MDNODE_GET(DIObjCProperty, (MDString * Name, Metadata *File, unsigned Line, MDString *GetterName, MDString *SetterName, unsigned Attributes, Metadata *Type), (Name, File, Line, GetterName, SetterName, Attributes, Type)) - TempMDObjCProperty clone() const { return cloneImpl(); } + TempDIObjCProperty clone() const { return cloneImpl(); } unsigned getLine() const { return Line; } unsigned getAttributes() const { return Attributes; } StringRef getName() const { return getStringOperand(0); } - MDFile *getFile() const { return cast_or_null(getRawFile()); } + DIFile *getFile() const { return cast_or_null(getRawFile()); } StringRef getGetterName() const { return getStringOperand(2); } StringRef getSetterName() const { return getStringOperand(3); } - - /// \brief Get the type. - /// - /// \note Objective-C doesn't have an ODR, so there is no benefit in storing - /// the type as a DITypeRef here. - MDType *getType() const { return cast_or_null(getRawType()); } + DITypeRef getType() const { return DITypeRef(getRawType()); } StringRef getFilename() const { if (auto *F = getFile()) @@ -2162,56 +2176,56 @@ class MDObjCProperty : public DebugNode { Metadata *getRawType() const { return getOperand(4); } static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDObjCPropertyKind; + return MD->getMetadataID() == DIObjCPropertyKind; } }; /// \brief An imported module (C++ using directive or similar). -class MDImportedEntity : public DebugNode { +class DIImportedEntity : public DINode { friend class LLVMContextImpl; friend class MDNode; unsigned Line; - MDImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag, + DIImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag, unsigned Line, ArrayRef Ops) - : DebugNode(C, MDImportedEntityKind, Storage, Tag, Ops), Line(Line) {} - ~MDImportedEntity() = default; + : DINode(C, DIImportedEntityKind, Storage, Tag, Ops), Line(Line) {} + ~DIImportedEntity() = default; - static MDImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, - MDScope *Scope, DebugNodeRef Entity, + static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, + DIScope *Scope, DINodeRef Entity, unsigned Line, StringRef Name, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, Scope, Entity, Line, getCanonicalMDString(Context, Name), Storage, ShouldCreate); } - static MDImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, + static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, Metadata *Scope, Metadata *Entity, unsigned Line, MDString *Name, StorageType Storage, bool ShouldCreate = true); - TempMDImportedEntity cloneImpl() const { + TempDIImportedEntity cloneImpl() const { return getTemporary(getContext(), getTag(), getScope(), getEntity(), getLine(), getName()); } public: - DEFINE_MDNODE_GET(MDImportedEntity, - (unsigned Tag, MDScope *Scope, DebugNodeRef Entity, + DEFINE_MDNODE_GET(DIImportedEntity, + (unsigned Tag, DIScope *Scope, DINodeRef Entity, unsigned Line, StringRef Name = ""), (Tag, Scope, Entity, Line, Name)) - DEFINE_MDNODE_GET(MDImportedEntity, + DEFINE_MDNODE_GET(DIImportedEntity, (unsigned Tag, Metadata *Scope, Metadata *Entity, unsigned Line, MDString *Name), (Tag, Scope, Entity, Line, Name)) - TempMDImportedEntity clone() const { return cloneImpl(); } + TempDIImportedEntity clone() const { return cloneImpl(); } unsigned getLine() const { return Line; } - MDScope *getScope() const { return cast_or_null(getRawScope()); } - DebugNodeRef getEntity() const { return DebugNodeRef(getRawEntity()); } + DIScope *getScope() const { return cast_or_null(getRawScope()); } + DINodeRef getEntity() const { return DINodeRef(getRawEntity()); } StringRef getName() const { return getStringOperand(2); } Metadata *getRawScope() const { return getOperand(0); } @@ -2219,7 +2233,7 @@ class MDImportedEntity : public DebugNode { MDString *getRawName() const { return getOperandAs(2); } static bool classof(const Metadata *MD) { - return MD->getMetadataID() == MDImportedEntityKind; + return MD->getMetadataID() == DIImportedEntityKind; } }; diff --git a/include/llvm/IR/DebugLoc.h b/include/llvm/IR/DebugLoc.h index f88a7b156b2..8ea5875e1f8 100644 --- a/include/llvm/IR/DebugLoc.h +++ b/include/llvm/IR/DebugLoc.h @@ -22,14 +22,14 @@ namespace llvm { class LLVMContext; class raw_ostream; - class MDLocation; + class DILocation; /// \brief A debug info location. /// - /// This class is a wrapper around a tracking reference to an \a MDLocation + /// This class is a wrapper around a tracking reference to an \a DILocation /// pointer. /// - /// To avoid extra includes, \a DebugLoc doubles the \a MDLocation API with a + /// To avoid extra includes, \a DebugLoc doubles the \a DILocation API with a /// one based on relatively opaque \a MDNode pointers. class DebugLoc { TrackingMDNodeRef Loc; @@ -47,31 +47,31 @@ namespace llvm { return *this; } - /// \brief Construct from an \a MDLocation. - DebugLoc(const MDLocation *L); + /// \brief Construct from an \a DILocation. + DebugLoc(const DILocation *L); /// \brief Construct from an \a MDNode. /// - /// Note: if \c N is not an \a MDLocation, a verifier check will fail, and + /// Note: if \c N is not an \a DILocation, a verifier check will fail, and /// accessors will crash. However, construction from other nodes is /// supported in order to handle forward references when reading textual /// IR. explicit DebugLoc(const MDNode *N); - /// \brief Get the underlying \a MDLocation. + /// \brief Get the underlying \a DILocation. /// - /// \pre !*this or \c isa(getAsMDNode()). + /// \pre !*this or \c isa(getAsMDNode()). /// @{ - MDLocation *get() const; - operator MDLocation *() const { return get(); } - MDLocation *operator->() const { return get(); } - MDLocation &operator*() const { return *get(); } + DILocation *get() const; + operator DILocation *() const { return get(); } + DILocation *operator->() const { return get(); } + DILocation &operator*() const { return *get(); } /// @} /// \brief Check for null. /// /// Check for null in a way that is safe with broken debug info. Unlike - /// the conversion to \c MDLocation, this doesn't require that \c Loc is of + /// the conversion to \c DILocation, this doesn't require that \c Loc is of /// the right type. Important for cases like \a llvm::StripDebugInfo() and /// \a Instruction::hasMetadata(). explicit operator bool() const { return Loc; } @@ -82,18 +82,18 @@ namespace llvm { /// \brief Create a new DebugLoc. /// /// Create a new DebugLoc at the specified line/col and scope/inline. This - /// forwards to \a MDLocation::get(). + /// forwards to \a DILocation::get(). /// /// If \c !Scope, returns a default-constructed \a DebugLoc. /// - /// FIXME: Remove this. Users should use MDLocation::get(). + /// FIXME: Remove this. Users should use DILocation::get(). static DebugLoc get(unsigned Line, unsigned Col, const MDNode *Scope, const MDNode *InlinedAt = nullptr); unsigned getLine() const; unsigned getCol() const; MDNode *getScope() const; - MDLocation *getInlinedAt() const; + DILocation *getInlinedAt() const; /// \brief Get the fully inlined-at scope for a DebugLoc. /// @@ -105,8 +105,8 @@ namespace llvm { /// Walk up the scope chain of given debug loc and find line number info /// for the function. /// - /// FIXME: Remove this. Users should use MDLocation/MDLocalScope API to - /// find the subprogram, and then MDLocation::get(). + /// FIXME: Remove this. Users should use DILocation/DILocalScope API to + /// find the subprogram, and then DILocation::get(). DebugLoc getFnDebugLoc() const; /// \brief Return \c this as a bar \a MDNode. diff --git a/include/llvm/IR/DerivedTypes.h b/include/llvm/IR/DerivedTypes.h index 76f806434f4..4a94499b4cf 100644 --- a/include/llvm/IR/DerivedTypes.h +++ b/include/llvm/IR/DerivedTypes.h @@ -140,7 +140,8 @@ class FunctionType : public Type { return T->getTypeID() == FunctionTyID; } }; - +static_assert(AlignOf::Alignment >= AlignOf::Alignment, + "Alignment sufficient for objects appended to FunctionType"); /// CompositeType - Common super class of ArrayType, StructType, PointerType /// and VectorType. @@ -464,6 +465,9 @@ class PointerType : public SequentialType { /// element type. static bool isValidElementType(Type *ElemTy); + /// Return true if we can load or store from a pointer to this type. + static bool isLoadableOrStorableType(Type *ElemTy); + /// @brief Return the address space of the Pointer type. inline unsigned getAddressSpace() const { return getSubclassData(); } diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h index 6db5a40c577..f38313f82ea 100644 --- a/include/llvm/IR/DiagnosticInfo.h +++ b/include/llvm/IR/DiagnosticInfo.h @@ -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 @@ class DiagnosticInfoOptimizationRemarkAnalysis 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) diff --git a/include/llvm/IR/DiagnosticPrinter.h b/include/llvm/IR/DiagnosticPrinter.h index db5779a8a8a..1bcd73738b6 100644 --- a/include/llvm/IR/DiagnosticPrinter.h +++ b/include/llvm/IR/DiagnosticPrinter.h @@ -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 @@ class DiagnosticPrinter { // 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. @@ -59,7 +63,7 @@ class DiagnosticPrinterRawOStream : public DiagnosticPrinter { raw_ostream &Stream; public: - DiagnosticPrinterRawOStream(raw_ostream &Stream) : Stream(Stream) {}; + DiagnosticPrinterRawOStream(raw_ostream &Stream) : Stream(Stream) {} // Simple types. DiagnosticPrinter &operator<<(char C) override; @@ -81,6 +85,9 @@ class DiagnosticPrinterRawOStream : public DiagnosticPrinter { // 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 diff --git a/include/llvm/IR/Dominators.h b/include/llvm/IR/Dominators.h index c1f208e3d72..52c2a8e2fc4 100644 --- a/include/llvm/IR/Dominators.h +++ b/include/llvm/IR/Dominators.h @@ -36,18 +36,14 @@ namespace llvm { template class AnalysisManager; class PreservedAnalyses; -EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase); -EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase); - -#define LLVM_COMMA , -EXTERN_TEMPLATE_INSTANTIATION(void Calculate( - DominatorTreeBase::NodeType> &DT LLVM_COMMA - Function &F)); -EXTERN_TEMPLATE_INSTANTIATION( - void Calculate >( - DominatorTreeBase >::NodeType> &DT - LLVM_COMMA Function &F)); -#undef LLVM_COMMA +extern template class DomTreeNodeBase; +extern template class DominatorTreeBase; + +extern template void Calculate( + DominatorTreeBase::NodeType> &DT, Function &F); +extern template void Calculate>( + DominatorTreeBase>::NodeType> &DT, + Function &F); typedef DomTreeNodeBase DomTreeNode; @@ -73,6 +69,9 @@ class DominatorTree : public DominatorTreeBase { typedef DominatorTreeBase Base; DominatorTree() : DominatorTreeBase(false) {} + explicit DominatorTree(Function &F) : DominatorTreeBase(false) { + recalculate(F); + } DominatorTree(DominatorTree &&Arg) : Base(std::move(static_cast(Arg))) {} @@ -151,6 +150,31 @@ template <> struct GraphTraits { } }; +template <> struct GraphTraits { + typedef const DomTreeNode NodeType; + typedef NodeType::const_iterator ChildIteratorType; + + static NodeType *getEntryNode(NodeType *N) { + return N; + } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->end(); + } + + typedef df_iterator nodes_iterator; + + static nodes_iterator nodes_begin(const DomTreeNode *N) { + return df_begin(getEntryNode(N)); + } + + static nodes_iterator nodes_end(const DomTreeNode *N) { + return df_end(getEntryNode(N)); + } +}; + template <> struct GraphTraits : public GraphTraits { static NodeType *getEntryNode(DominatorTree *DT) { diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index a5eed9b68b0..ec9f4cad094 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -19,11 +19,13 @@ #define LLVM_IR_FUNCTION_H #include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/Optional.h" #include "llvm/IR/Argument.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/GlobalObject.h" +#include "llvm/IR/OperandTraits.h" #include "llvm/Support/Compiler.h" namespace llvm { @@ -77,6 +79,17 @@ class Function : public GlobalObject, public ilist_node { * bit 3-6: CallingConvention */ + /// Bits from GlobalObject::GlobalObjectSubclassData. + enum { + /// Whether this function is materializable. + IsMaterializableBit = 1 << 0, + HasMetadataHashEntryBit = 1 << 1 + }; + void setGlobalObjectBit(unsigned Mask, bool Value) { + setGlobalObjectSubClassData((~Mask & getGlobalObjectSubClassData()) | + (Value ? Mask : 0u)); + } + friend class SymbolTableListTraits; void setParent(Module *parent); @@ -97,10 +110,6 @@ class Function : public GlobalObject, public ilist_node { Function(const Function&) = delete; void operator=(const Function&) = delete; - /// Do the actual lookup of an intrinsic ID when the query could not be - /// answered from the cache. - unsigned lookupIntrinsicID() const LLVM_READONLY; - /// Function ctor - If the (optional) Module argument is specified, the /// function is automatically inserted into the end of the function list for /// the module. @@ -111,16 +120,27 @@ class Function : public GlobalObject, public ilist_node { public: static Function *Create(FunctionType *Ty, LinkageTypes Linkage, const Twine &N = "", Module *M = nullptr) { - return new(0) Function(Ty, Linkage, N, M); + return new(1) Function(Ty, Linkage, N, M); } ~Function() override; + /// \brief Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// \brief Get the personality function associated with this function. + bool hasPersonalityFn() const { return getNumOperands() != 0; } + Constant *getPersonalityFn() const { + assert(hasPersonalityFn()); + return cast(Op<0>()); + } + void setPersonalityFn(Constant *C); + Type *getReturnType() const; // Return the type of the ret val FunctionType *getFunctionType() const; // Return the FunctionType for me - /// getContext - Return a pointer to the LLVMContext associated with this - /// function, or NULL if this function is not bound to a context yet. + /// getContext - Return a reference to the LLVMContext associated with this + /// function. LLVMContext &getContext() const; /// isVarArg - Return true if this function takes a variable number of @@ -135,13 +155,17 @@ class Function : public GlobalObject, public ilist_node { /// intrinsic, or if the pointer is null. This value is always defined to be /// zero to allow easy checking for whether a function is intrinsic or not. /// The particular intrinsic functions which correspond to this value are - /// defined in llvm/Intrinsics.h. Results are cached in the LLVM context, - /// subsequent requests for the same ID return results much faster from the - /// cache. - /// - unsigned getIntrinsicID() const LLVM_READONLY; + /// defined in llvm/Intrinsics.h. + Intrinsic::ID getIntrinsicID() const LLVM_READONLY { return IntID; } bool isIntrinsic() const { return getName().startswith("llvm."); } + /// \brief Recalculate the ID for this function if it is an Intrinsic defined + /// in llvm/Intrinsics.h. Sets the intrinsic ID to Intrinsic::not_intrinsic + /// if the name of this function does not match an intrinsic in that header. + /// Note, this method does not need to be called directly, as it is called + /// from Value::setName() whenever the name of this function changes. + void recalculateIntrinsicID(); + /// getCallingConv()/setCallingConv(CC) - These method get and set the /// calling convention of this function. The enum values for the known /// calling conventions are defined in CallingConv.h. @@ -183,6 +207,12 @@ class Function : public GlobalObject, public ilist_node { AttributeSet::FunctionIndex, Kind, Value)); } + /// Set the entry count for this function. + void setEntryCount(uint64_t Count); + + /// Get the entry count for this function. + Optional getEntryCount() const; + /// @brief Return true if the function has the attribute. bool hasFnAttribute(Attribute::AttrKind Kind) const { return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind); @@ -237,7 +267,13 @@ class Function : public GlobalObject, public ilist_node { uint64_t getDereferenceableBytes(unsigned i) const { return AttributeSets.getDereferenceableBytes(i); } - + + /// @brief Extract the number of dereferenceable_or_null bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableOrNullBytes(unsigned i) const { + return AttributeSets.getDereferenceableOrNullBytes(i); + } + /// @brief Determine if the function does not access memory. bool doesNotAccessMemory() const { return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, @@ -257,6 +293,16 @@ class Function : public GlobalObject, public ilist_node { addFnAttr(Attribute::ReadOnly); } + /// @brief Determine if the call can access memmory only using pointers based + /// on its arguments. + bool onlyAccessesArgMemory() const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, + Attribute::ArgMemOnly); + } + void setOnlyAccessesArgMemory() { + addFnAttr(Attribute::ArgMemOnly); + } + /// @brief Determine if the function cannot return. bool doesNotReturn() const { return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, @@ -284,6 +330,16 @@ class Function : public GlobalObject, public ilist_node { addFnAttr(Attribute::NoDuplicate); } + /// @brief Determine if the call is convergent. + bool isConvergent() const { + return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, + Attribute::Convergent); + } + void setConvergent() { + addFnAttr(Attribute::Convergent); + } + + /// @brief True if the ABI mandates (or the user requested) that this /// function be in a unwind table. bool hasUWTable() const { @@ -511,12 +567,50 @@ class Function : public GlobalObject, public ilist_node { /// setjmp or other function that gcc recognizes as "returning twice". bool callsFunctionThatReturnsTwice() const; + /// \brief Check if this has any metadata. + bool hasMetadata() const { return hasMetadataHashEntry(); } + + /// \brief Get the current metadata attachment, if any. + /// + /// Returns \c nullptr if such an attachment is missing. + /// @{ + MDNode *getMetadata(unsigned KindID) const; + MDNode *getMetadata(StringRef Kind) const; + /// @} + + /// \brief Set a particular kind of metadata attachment. + /// + /// Sets the given attachment to \c MD, erasing it if \c MD is \c nullptr or + /// replacing it if it already exists. + /// @{ + void setMetadata(unsigned KindID, MDNode *MD); + void setMetadata(StringRef Kind, MDNode *MD); + /// @} + + /// \brief Get all current metadata attachments. + void + getAllMetadata(SmallVectorImpl> &MDs) const; + + /// \brief Drop metadata not in the given list. + /// + /// Drop all metadata from \c this not included in \c KnownIDs. + void dropUnknownMetadata(ArrayRef KnownIDs); + private: // Shadow Value::setValueSubclassData with a private forwarding method so that // subclasses cannot accidentally use it. void setValueSubclassData(unsigned short D) { Value::setValueSubclassData(D); } + + bool hasMetadataHashEntry() const { + return getGlobalObjectSubClassData() & HasMetadataHashEntryBit; + } + void setHasMetadataHashEntry(bool HasEntry) { + setGlobalObjectBit(HasMetadataHashEntryBit, HasEntry); + } + + void clearMetadata(); }; inline ValueSymbolTable * @@ -529,6 +623,11 @@ ilist_traits::getSymTab(Function *F) { return F ? &F->getValueSymbolTable() : nullptr; } +template <> +struct OperandTraits : public OptionalOperandTraits {}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(Function, Value) + } // End llvm namespace #endif diff --git a/include/llvm/IR/GVMaterializer.h b/include/llvm/IR/GVMaterializer.h index 779f2e01818..1d6c9157f0b 100644 --- a/include/llvm/IR/GVMaterializer.h +++ b/include/llvm/IR/GVMaterializer.h @@ -47,11 +47,11 @@ class GVMaterializer { /// lazily. If the Materializer doesn't support this capability, this method /// is a noop. /// - virtual void Dematerialize(GlobalValue *) {} + virtual void dematerialize(GlobalValue *) {} /// Make sure the entire Module has been completely read. /// - virtual std::error_code MaterializeModule(Module *M) = 0; + virtual std::error_code materializeModule(Module *M) = 0; virtual std::error_code materializeMetadata() = 0; virtual void setStripDebugInfo() = 0; diff --git a/include/llvm/IR/GetElementPtrTypeIterator.h b/include/llvm/IR/GetElementPtrTypeIterator.h index dcf8e64dbb2..7cb13fa33aa 100644 --- a/include/llvm/IR/GetElementPtrTypeIterator.h +++ b/include/llvm/IR/GetElementPtrTypeIterator.h @@ -16,7 +16,9 @@ #define LLVM_IR_GETELEMENTPTRTYPEITERATOR_H #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Operator.h" #include "llvm/IR/User.h" +#include "llvm/ADT/PointerIntPair.h" namespace llvm { template @@ -26,19 +28,28 @@ namespace llvm { Type *, ptrdiff_t> super; ItTy OpIt; - Type *CurTy; + PointerIntPair CurTy; + unsigned AddrSpace; generic_gep_type_iterator() {} public: static generic_gep_type_iterator begin(Type *Ty, ItTy It) { generic_gep_type_iterator I; - I.CurTy = Ty; + I.CurTy.setPointer(Ty); + I.OpIt = It; + return I; + } + static generic_gep_type_iterator begin(Type *Ty, unsigned AddrSpace, + ItTy It) { + generic_gep_type_iterator I; + I.CurTy.setPointer(Ty); + I.CurTy.setInt(true); + I.AddrSpace = AddrSpace; I.OpIt = It; return I; } static generic_gep_type_iterator end(ItTy It) { generic_gep_type_iterator I; - I.CurTy = nullptr; I.OpIt = It; return I; } @@ -51,11 +62,15 @@ namespace llvm { } Type *operator*() const { - return CurTy; + if (CurTy.getInt()) + return CurTy.getPointer()->getPointerTo(AddrSpace); + return CurTy.getPointer(); } Type *getIndexedType() const { - CompositeType *CT = cast(CurTy); + if (CurTy.getInt()) + return CurTy.getPointer(); + CompositeType *CT = cast(CurTy.getPointer()); return CT->getTypeAtIndex(getOperand()); } @@ -63,13 +78,16 @@ namespace llvm { // current type directly. Type *operator->() const { return operator*(); } - Value *getOperand() const { return *OpIt; } + Value *getOperand() const { return const_cast(&**OpIt); } generic_gep_type_iterator& operator++() { // Preincrement - if (CompositeType *CT = dyn_cast(CurTy)) { - CurTy = CT->getTypeAtIndex(getOperand()); + if (CurTy.getInt()) { + CurTy.setInt(false); + } else if (CompositeType *CT = + dyn_cast(CurTy.getPointer())) { + CurTy.setPointer(CT->getTypeAtIndex(getOperand())); } else { - CurTy = nullptr; + CurTy.setPointer(nullptr); } ++OpIt; return *this; @@ -83,15 +101,23 @@ namespace llvm { typedef generic_gep_type_iterator<> gep_type_iterator; inline gep_type_iterator gep_type_begin(const User *GEP) { - return gep_type_iterator::begin - (GEP->getOperand(0)->getType()->getScalarType(), GEP->op_begin()+1); + auto *GEPOp = cast(GEP); + return gep_type_iterator::begin( + GEPOp->getSourceElementType(), + cast(GEPOp->getPointerOperandType()->getScalarType()) + ->getAddressSpace(), + GEP->op_begin() + 1); } inline gep_type_iterator gep_type_end(const User *GEP) { return gep_type_iterator::end(GEP->op_end()); } inline gep_type_iterator gep_type_begin(const User &GEP) { - return gep_type_iterator::begin - (GEP.getOperand(0)->getType()->getScalarType(), GEP.op_begin()+1); + auto &GEPOp = cast(GEP); + return gep_type_iterator::begin( + GEPOp.getSourceElementType(), + cast(GEPOp.getPointerOperandType()->getScalarType()) + ->getAddressSpace(), + GEP.op_begin() + 1); } inline gep_type_iterator gep_type_end(const User &GEP) { return gep_type_iterator::end(GEP.op_end()); diff --git a/include/llvm/IR/GlobalAlias.h b/include/llvm/IR/GlobalAlias.h index d0672c8aac0..ce73b7af8ca 100644 --- a/include/llvm/IR/GlobalAlias.h +++ b/include/llvm/IR/GlobalAlias.h @@ -33,8 +33,8 @@ class GlobalAlias : public GlobalValue, public ilist_node { void setParent(Module *parent); - GlobalAlias(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, - const Twine &Name, Constant *Aliasee, Module *Parent); + GlobalAlias(PointerType *Ty, LinkageTypes Linkage, const Twine &Name, + Constant *Aliasee, Module *Parent); public: // allocate space for exactly one operand @@ -44,19 +44,17 @@ class GlobalAlias : public GlobalValue, public ilist_node { /// If a parent module is specified, the alias is automatically inserted into /// the end of the specified module's alias list. - static GlobalAlias *create(Type *Ty, unsigned AddressSpace, - LinkageTypes Linkage, const Twine &Name, - Constant *Aliasee, Module *Parent); + static GlobalAlias *create(PointerType *Ty, LinkageTypes Linkage, + const Twine &Name, Constant *Aliasee, + Module *Parent); // Without the Aliasee. - static GlobalAlias *create(Type *Ty, unsigned AddressSpace, - LinkageTypes Linkage, const Twine &Name, - Module *Parent); + static GlobalAlias *create(PointerType *Ty, LinkageTypes Linkage, + const Twine &Name, Module *Parent); // The module is taken from the Aliasee. - static GlobalAlias *create(Type *Ty, unsigned AddressSpace, - LinkageTypes Linkage, const Twine &Name, - GlobalValue *Aliasee); + static GlobalAlias *create(PointerType *Ty, LinkageTypes Linkage, + const Twine &Name, GlobalValue *Aliasee); // Type, Parent and AddressSpace taken from the Aliasee. static GlobalAlias *create(LinkageTypes Linkage, const Twine &Name, diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index aeaaef4bd8b..2961369a732 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -28,6 +28,10 @@ class Comdat; class PointerType; class Module; +namespace Intrinsic { + enum ID : unsigned; +} + class GlobalValue : public Constant { GlobalValue(const GlobalValue &) = delete; public: @@ -66,7 +70,7 @@ class GlobalValue : public Constant { : Constant(Ty, VTy, Ops, NumOps), Linkage(Linkage), Visibility(DefaultVisibility), UnnamedAddr(0), DllStorageClass(DefaultStorageClass), - ThreadLocal(NotThreadLocal), Parent(nullptr) { + ThreadLocal(NotThreadLocal), IntID((Intrinsic::ID)0U), Parent(nullptr) { setName(Name); } @@ -79,18 +83,31 @@ class GlobalValue : public Constant { 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; + + friend class Constant; + void destroyConstantImpl(); + Value *handleOperandChangeImpl(Value *From, Value *To, Use *U); + protected: - static const unsigned GlobalValueSubClassDataBits = 19; + /// \brief The intrinsic ID for this subclass (which must be a Function). + /// + /// This member is defined by this class, but not used for anything. + /// Subclasses can use it to store their intrinsic ID, if they have one. + /// + /// This is stored here to save space in Function on 64-bit hosts. + Intrinsic::ID IntID; + 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; } @@ -235,10 +252,9 @@ class GlobalValue : public Constant { /// mistake: when working at the IR level use mayBeOverridden instead as it /// knows about ODR semantics. static bool isWeakForLinker(LinkageTypes Linkage) { - return Linkage == AvailableExternallyLinkage || Linkage == WeakAnyLinkage || - Linkage == WeakODRLinkage || Linkage == LinkOnceAnyLinkage || - Linkage == LinkOnceODRLinkage || Linkage == CommonLinkage || - Linkage == ExternalWeakLinkage; + return Linkage == WeakAnyLinkage || Linkage == WeakODRLinkage || + Linkage == LinkOnceAnyLinkage || Linkage == LinkOnceODRLinkage || + Linkage == CommonLinkage || Linkage == ExternalWeakLinkage; } bool hasExternalLinkage() const { return isExternalLinkage(Linkage); } @@ -317,13 +333,10 @@ class GlobalValue : public Constant { /// If this GlobalValue is read in, and if the GVMaterializer supports it, /// release the memory for the function, and set it up to be materialized /// lazily. If !isDematerializable(), this method is a noop. - void Dematerialize(); + void dematerialize(); /// @} - /// Override from Constant class. - void destroyConstant() override; - /// Return true if the primary definition of this global value is outside of /// the current translation unit. bool isDeclaration() const; @@ -335,6 +348,12 @@ class GlobalValue : public Constant { return isDeclaration(); } + /// Returns true if this global's definition will be the one chosen by the + /// linker. + bool isStrongDefinitionForLinker() const { + return !(isDeclarationForLinker() || isWeakForLinker()); + } + /// This method unlinks 'this' from the containing module, but does not delete /// it. virtual void removeFromParent() = 0; diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h index 9f57705dae7..a0159830ba3 100644 --- a/include/llvm/IR/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -45,7 +45,6 @@ class GlobalVariable : public GlobalObject, public ilist_node { // can change from its initial // value before global // initializers are run? - public: // allocate space for exactly one operand void *operator new(size_t s) { @@ -67,7 +66,8 @@ class GlobalVariable : public GlobalObject, public ilist_node { bool isExternallyInitialized = false); ~GlobalVariable() override { - NumOperands = 1; // FIXME: needed by operator delete + // FIXME: needed by operator delete + setGlobalVariableNumOperands(1); } /// Provide fast operand accessors @@ -165,10 +165,6 @@ class GlobalVariable : public GlobalObject, public ilist_node { /// void eraseFromParent() override; - /// Override Constant's implementation of this method so we can - /// replace constant initializers. - void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) override; - // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Value *V) { return V->getValueID() == Value::GlobalVariableVal; diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index 9c4ba078995..d02f41b7e27 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -21,6 +21,7 @@ #include "llvm/IR/BasicBlock.h" #include "llvm/IR/ConstantFolder.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/Function.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" @@ -100,19 +101,8 @@ class IRBuilderBase { void SetInsertPoint(BasicBlock *TheBB, BasicBlock::iterator IP) { BB = TheBB; InsertPt = IP; - } - - /// \brief Find the nearest point that dominates this use, and specify that - /// created instructions should be inserted at this point. - void SetInsertPoint(Use &U) { - Instruction *UseInst = cast(U.getUser()); - if (PHINode *Phi = dyn_cast(UseInst)) { - BasicBlock *PredBB = Phi->getIncomingBlock(U); - assert(U != PredBB->getTerminator() && "critical edge not split"); - SetInsertPoint(PredBB, PredBB->getTerminator()); - return; - } - SetInsertPoint(UseInst); + if (IP != TheBB->end()) + SetCurrentDebugLocation(IP->getDebugLoc()); } /// \brief Set location information used by debugging information. @@ -244,7 +234,8 @@ class IRBuilderBase { /// filled in with the null terminated string value specified. The new global /// variable will be marked mergable with any others of the same contents. If /// Name is specified, it is the name of the global variable created. - GlobalVariable *CreateGlobalString(StringRef Str, const Twine &Name = ""); + GlobalVariable *CreateGlobalString(StringRef Str, const Twine &Name = "", + unsigned AddressSpace = 0); /// \brief Get a constant value representing either true or false. ConstantInt *getInt1(bool V) { @@ -321,6 +312,11 @@ class IRBuilderBase { return Type::getInt64Ty(Context); } + /// \brief Fetch the type representing a 128-bit integer. + IntegerType *getInt128Ty() { + return Type::getInt128Ty(Context); + } + /// \brief Fetch the type representing an N-bit integer. IntegerType *getIntNTy(unsigned N) { return Type::getIntNTy(Context, N); @@ -442,19 +438,40 @@ class IRBuilderBase { /// \brief Create a call to the experimental.gc.statepoint intrinsic to /// start a new statepoint sequence. - CallInst *CreateGCStatepoint(Value *ActualCallee, - ArrayRef CallArgs, - ArrayRef DeoptArgs, - ArrayRef GCArgs, - const Twine &Name = ""); + CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes, + Value *ActualCallee, + ArrayRef CallArgs, + ArrayRef DeoptArgs, + ArrayRef GCArgs, + const Twine &Name = ""); + + // \brief Conveninence function for the common case when CallArgs are filled + // in using makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be + // .get()'ed to get the Value pointer. + CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes, + Value *ActualCallee, ArrayRef CallArgs, + ArrayRef DeoptArgs, + ArrayRef GCArgs, + const Twine &Name = ""); + + /// brief Create an invoke to the experimental.gc.statepoint intrinsic to + /// start a new statepoint sequence. + InvokeInst * + CreateGCStatepointInvoke(uint64_t ID, uint32_t NumPatchBytes, + Value *ActualInvokee, BasicBlock *NormalDest, + BasicBlock *UnwindDest, ArrayRef InvokeArgs, + ArrayRef DeoptArgs, + ArrayRef GCArgs, const Twine &Name = ""); // Conveninence function for the common case when CallArgs are filled in using - // makeArrayRef(CS.arg_begin(), .arg_end()); Use needs to be .get()'ed to get - // the Value *. - CallInst *CreateGCStatepoint(Value *ActualCallee, ArrayRef CallArgs, - ArrayRef DeoptArgs, - ArrayRef GCArgs, - const Twine &Name = ""); + // makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be .get()'ed to + // get the Value *. + InvokeInst * + CreateGCStatepointInvoke(uint64_t ID, uint32_t NumPatchBytes, + Value *ActualInvokee, BasicBlock *NormalDest, + BasicBlock *UnwindDest, ArrayRef InvokeArgs, + ArrayRef DeoptArgs, + ArrayRef GCArgs, const Twine &Name = ""); /// \brief Create a call to the experimental.gc.result intrinsic to extract /// the result from a call wrapped in a statepoint. @@ -473,7 +490,7 @@ class IRBuilderBase { private: /// \brief Create a call to a masked intrinsic with given Id. /// Masked intrinsic has only one overloaded type - data type. - CallInst *CreateMaskedIntrinsic(unsigned Id, ArrayRef Ops, + CallInst *CreateMaskedIntrinsic(Intrinsic::ID Id, ArrayRef Ops, Type *DataTy, const Twine &Name = ""); Value *getCastedInt8PtrValue(Value *Ptr); @@ -522,13 +539,6 @@ class IRBuilder : public IRBuilderBase, public Inserter { explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = nullptr) : IRBuilderBase(IP->getContext(), FPMathTag), Folder() { SetInsertPoint(IP); - SetCurrentDebugLocation(IP->getDebugLoc()); - } - - explicit IRBuilder(Use &U, MDNode *FPMathTag = nullptr) - : IRBuilderBase(U->getContext(), FPMathTag), Folder() { - SetInsertPoint(U); - SetCurrentDebugLocation(cast(U.getUser())->getDebugLoc()); } IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F, @@ -662,6 +672,38 @@ class IRBuilder : public IRBuilderBase, public Inserter { return Insert(ResumeInst::Create(Exn)); } + CleanupReturnInst *CreateCleanupRet(BasicBlock *UnwindBB = nullptr, + Value *RetVal = nullptr) { + return Insert(CleanupReturnInst::Create(Context, RetVal, UnwindBB)); + } + + CatchPadInst *CreateCatchPad(Type *Ty, BasicBlock *NormalDest, + BasicBlock *UnwindDest, + ArrayRef Args, + const Twine &Name = "") { + return Insert(CatchPadInst::Create(Ty, NormalDest, UnwindDest, Args), + Name); + } + + CatchEndPadInst *CreateCatchEndPad(BasicBlock *UnwindBB = nullptr) { + return Insert(CatchEndPadInst::Create(Context, UnwindBB)); + } + + TerminatePadInst *CreateTerminatePad(BasicBlock *UnwindBB = nullptr, + ArrayRef Args = {}, + const Twine &Name = "") { + return Insert(TerminatePadInst::Create(Context, UnwindBB, Args), Name); + } + + CleanupPadInst *CreateCleanupPad(Type *Ty, ArrayRef Args, + const Twine &Name = "") { + return Insert(CleanupPadInst::Create(Ty, Args), Name); + } + + CatchReturnInst *CreateCatchRet(BasicBlock *BB) { + return Insert(CatchReturnInst::Create(BB)); + } + UnreachableInst *CreateUnreachable() { return Insert(new UnreachableInst(Context)); } @@ -966,6 +1008,9 @@ class IRBuilder : public IRBuilderBase, public Inserter { LoadInst *CreateLoad(Value *Ptr, const Twine &Name = "") { return Insert(new LoadInst(Ptr), Name); } + LoadInst *CreateLoad(Type *Ty, Value *Ptr, const Twine &Name = "") { + return Insert(new LoadInst(Ty, Ptr), Name); + } LoadInst *CreateLoad(Value *Ptr, bool isVolatile, const Twine &Name = "") { return Insert(new LoadInst(Ptr, nullptr, isVolatile), Name); } @@ -1161,8 +1206,9 @@ class IRBuilder : public IRBuilderBase, public Inserter { /// \brief Same as CreateGlobalString, but return a pointer with "i8*" type /// instead of a pointer to array of i8. - Value *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "") { - GlobalVariable *gv = CreateGlobalString(Str, Name); + Value *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "", + unsigned AddressSpace = 0) { + GlobalVariable *gv = CreateGlobalString(Str, Name, AddressSpace); Value *zero = ConstantInt::get(Type::getInt32Ty(Context), 0); Value *Args[] = { zero, zero }; return CreateInBoundsGEP(gv->getValueType(), gv, Args, Name); @@ -1368,47 +1414,61 @@ class IRBuilder : public IRBuilderBase, public Inserter { return CreateICmp(ICmpInst::ICMP_SLE, LHS, RHS, Name); } - Value *CreateFCmpOEQ(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_OEQ, LHS, RHS, Name); + Value *CreateFCmpOEQ(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_OEQ, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpOGT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_OGT, LHS, RHS, Name); + Value *CreateFCmpOGT(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_OGT, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpOGE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_OGE, LHS, RHS, Name); + Value *CreateFCmpOGE(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_OGE, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpOLT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_OLT, LHS, RHS, Name); + Value *CreateFCmpOLT(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_OLT, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpOLE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_OLE, LHS, RHS, Name); + Value *CreateFCmpOLE(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_OLE, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpONE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_ONE, LHS, RHS, Name); + Value *CreateFCmpONE(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_ONE, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpORD(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_ORD, LHS, RHS, Name); + Value *CreateFCmpORD(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_ORD, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpUNO(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_UNO, LHS, RHS, Name); + Value *CreateFCmpUNO(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_UNO, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpUEQ(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_UEQ, LHS, RHS, Name); + Value *CreateFCmpUEQ(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_UEQ, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpUGT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_UGT, LHS, RHS, Name); + Value *CreateFCmpUGT(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_UGT, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpUGE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_UGE, LHS, RHS, Name); + Value *CreateFCmpUGE(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_UGE, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpULT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_ULT, LHS, RHS, Name); + Value *CreateFCmpULT(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_ULT, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpULE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_ULE, LHS, RHS, Name); + Value *CreateFCmpULE(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_ULE, LHS, RHS, Name, FPMathTag); } - Value *CreateFCmpUNE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_UNE, LHS, RHS, Name); + Value *CreateFCmpUNE(Value *LHS, Value *RHS, const Twine &Name = "", + MDNode *FPMathTag = nullptr) { + return CreateFCmp(FCmpInst::FCMP_UNE, LHS, RHS, Name, FPMathTag); } Value *CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, @@ -1419,11 +1479,12 @@ class IRBuilder : public IRBuilderBase, public Inserter { return Insert(new ICmpInst(P, LHS, RHS), Name); } Value *CreateFCmp(CmpInst::Predicate P, Value *LHS, Value *RHS, - const Twine &Name = "") { + const Twine &Name = "", MDNode *FPMathTag = nullptr) { if (Constant *LC = dyn_cast(LHS)) if (Constant *RC = dyn_cast(RHS)) return Insert(Folder.CreateFCmp(P, LC, RC), Name); - return Insert(new FCmpInst(P, LHS, RHS), Name); + return Insert(AddFPMathAttributes(new FCmpInst(P, LHS, RHS), + FPMathTag, FMF), Name); } //===--------------------------------------------------------------------===// @@ -1435,36 +1496,19 @@ class IRBuilder : public IRBuilderBase, public Inserter { return Insert(PHINode::Create(Ty, NumReservedValues), Name); } - CallInst *CreateCall(Value *Callee, const Twine &Name = "") { - return Insert(CallInst::Create(Callee), Name); - } - CallInst *CreateCall(Value *Callee, Value *Arg, const Twine &Name = "") { - return Insert(CallInst::Create(Callee, Arg), Name); - } - CallInst *CreateCall2(Value *Callee, Value *Arg1, Value *Arg2, - const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2 }; - return Insert(CallInst::Create(Callee, Args), Name); - } - CallInst *CreateCall3(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, - const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2, Arg3 }; - return Insert(CallInst::Create(Callee, Args), Name); - } - CallInst *CreateCall4(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, - Value *Arg4, const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2, Arg3, Arg4 }; + CallInst *CreateCall(Value *Callee, ArrayRef Args = None, + const Twine &Name = "") { return Insert(CallInst::Create(Callee, Args), Name); } - CallInst *CreateCall5(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, - Value *Arg4, Value *Arg5, const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2, Arg3, Arg4, Arg5 }; - return Insert(CallInst::Create(Callee, Args), Name); + + CallInst *CreateCall(llvm::FunctionType *FTy, Value *Callee, + ArrayRef Args, const Twine &Name = "") { + return Insert(CallInst::Create(FTy, Callee, Args), Name); } - CallInst *CreateCall(Value *Callee, ArrayRef Args, + CallInst *CreateCall(Function *Callee, ArrayRef Args, const Twine &Name = "") { - return Insert(CallInst::Create(Callee, Args), Name); + return CreateCall(Callee->getFunctionType(), Callee, Args, Name); } Value *CreateSelect(Value *C, Value *True, Value *False, @@ -1488,6 +1532,11 @@ class IRBuilder : public IRBuilderBase, public Inserter { return Insert(ExtractElementInst::Create(Vec, Idx), Name); } + Value *CreateExtractElement(Value *Vec, uint64_t Idx, + const Twine &Name = "") { + return CreateExtractElement(Vec, getInt64(Idx), Name); + } + Value *CreateInsertElement(Value *Vec, Value *NewElt, Value *Idx, const Twine &Name = "") { if (Constant *VC = dyn_cast(Vec)) @@ -1497,6 +1546,11 @@ class IRBuilder : public IRBuilderBase, public Inserter { return Insert(InsertElementInst::Create(Vec, NewElt, Idx), Name); } + Value *CreateInsertElement(Value *Vec, Value *NewElt, uint64_t Idx, + const Twine &Name = "") { + return CreateInsertElement(Vec, NewElt, getInt64(Idx), Name); + } + Value *CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name = "") { if (Constant *V1C = dyn_cast(V1)) @@ -1533,9 +1587,9 @@ class IRBuilder : public IRBuilderBase, public Inserter { return Insert(InsertValueInst::Create(Agg, Val, Idxs), Name); } - LandingPadInst *CreateLandingPad(Type *Ty, Value *PersFn, unsigned NumClauses, + LandingPadInst *CreateLandingPad(Type *Ty, unsigned NumClauses, const Twine &Name = "") { - return Insert(LandingPadInst::Create(Ty, PersFn, NumClauses), Name); + return Insert(LandingPadInst::Create(Ty, NumClauses), Name); } //===--------------------------------------------------------------------===// diff --git a/include/llvm/IR/IRPrintingPasses.h b/include/llvm/IR/IRPrintingPasses.h index 5f1d56f7e83..88b18e826da 100644 --- a/include/llvm/IR/IRPrintingPasses.h +++ b/include/llvm/IR/IRPrintingPasses.h @@ -47,6 +47,12 @@ FunctionPass *createPrintFunctionPass(raw_ostream &OS, BasicBlockPass *createPrintBasicBlockPass(raw_ostream &OS, const std::string &Banner = ""); +/// Print out a name of an LLVM value without any prefixes. +/// +/// The name is surrounded with ""'s and escaped if it has any special or +/// non-printable characters in it. +void printLLVMNameWithoutPrefix(raw_ostream &OS, StringRef Name); + /// \brief Pass for printing a Module as LLVM's text IR assembly. /// /// Note: This pass is for use with the new pass manager. Use the create...Pass diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h index 6decc210586..aa0eccf666d 100644 --- a/include/llvm/IR/InlineAsm.h +++ b/include/llvm/IR/InlineAsm.h @@ -44,11 +44,12 @@ class InlineAsm : public Value { void operator=(const InlineAsm&) = delete; std::string AsmString, Constraints; + FunctionType *FTy; bool HasSideEffects; bool IsAlignStack; AsmDialect Dialect; - InlineAsm(PointerType *Ty, const std::string &AsmString, + InlineAsm(FunctionType *Ty, const std::string &AsmString, const std::string &Constraints, bool hasSideEffects, bool isAlignStack, AsmDialect asmDialect); ~InlineAsm() override; @@ -88,13 +89,6 @@ class InlineAsm : public Value { /// static bool Verify(FunctionType *Ty, StringRef Constraints); - // @LOCALMOD-START - /// isAsmMemory - Returns true if the Instruction corresponds to - /// ``asm("":::"memory")``, which is often used as a compiler barrier. - /// - bool isAsmMemory() const; - // @LOCALMOD-END - // Constraint String Parsing enum ConstraintPrefix { isInput, // 'x' @@ -255,6 +249,14 @@ class InlineAsm : public Value { Constraint_R, Constraint_S, Constraint_T, + Constraint_Um, + Constraint_Un, + Constraint_Uq, + Constraint_Us, + Constraint_Ut, + Constraint_Uv, + Constraint_Uy, + Constraint_X, Constraint_Z, Constraint_ZC, Constraint_Zy, diff --git a/include/llvm/IR/InstVisitor.h b/include/llvm/IR/InstVisitor.h index 1cdcd55448c..b6322044624 100644 --- a/include/llvm/IR/InstVisitor.h +++ b/include/llvm/IR/InstVisitor.h @@ -169,6 +169,11 @@ class InstVisitor { RetTy visitIndirectBrInst(IndirectBrInst &I) { DELEGATE(TerminatorInst);} RetTy visitResumeInst(ResumeInst &I) { DELEGATE(TerminatorInst);} RetTy visitUnreachableInst(UnreachableInst &I) { DELEGATE(TerminatorInst);} + RetTy visitCleanupReturnInst(CleanupReturnInst &I) { DELEGATE(TerminatorInst);} + RetTy visitCatchReturnInst(CatchReturnInst &I) { DELEGATE(TerminatorInst);} + RetTy visitCatchPadInst(CatchPadInst &I) { DELEGATE(TerminatorInst);} + RetTy visitCatchEndPadInst(CatchEndPadInst &I) { DELEGATE(TerminatorInst); } + RetTy visitTerminatePadInst(TerminatePadInst &I) { DELEGATE(TerminatorInst);} RetTy visitICmpInst(ICmpInst &I) { DELEGATE(CmpInst);} RetTy visitFCmpInst(FCmpInst &I) { DELEGATE(CmpInst);} RetTy visitAllocaInst(AllocaInst &I) { DELEGATE(UnaryInstruction);} @@ -200,6 +205,7 @@ class InstVisitor { RetTy visitExtractValueInst(ExtractValueInst &I){ DELEGATE(UnaryInstruction);} RetTy visitInsertValueInst(InsertValueInst &I) { DELEGATE(Instruction); } RetTy visitLandingPadInst(LandingPadInst &I) { DELEGATE(Instruction); } + RetTy visitCleanupPadInst(CleanupPadInst &I) { DELEGATE(Instruction); } // Handle the special instrinsic instruction classes. RetTy visitDbgDeclareInst(DbgDeclareInst &I) { DELEGATE(DbgInfoIntrinsic);} @@ -259,7 +265,7 @@ class InstVisitor { // Special helper function to delegate to CallInst subclass visitors. RetTy delegateCallInst(CallInst &I) { if (const Function *F = I.getCalledFunction()) { - switch ((Intrinsic::ID)F->getIntrinsicID()) { + switch (F->getIntrinsicID()) { default: DELEGATE(IntrinsicInst); case Intrinsic::dbg_declare: DELEGATE(DbgDeclareInst); case Intrinsic::dbg_value: DELEGATE(DbgValueInst); diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index d3cda6aca2a..ed12dd75b91 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -75,6 +75,22 @@ class TerminatorInst : public Instruction { static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); } + + // \brief Returns true if this terminator relates to exception handling. + bool isExceptional() const { + switch (getOpcode()) { + case Instruction::CatchPad: + case Instruction::CatchEndPad: + case Instruction::CatchRet: + case Instruction::CleanupRet: + case Instruction::Invoke: + case Instruction::Resume: + case Instruction::TerminatePad: + return true; + default: + return false; + } + } }; @@ -139,7 +155,11 @@ class BinaryOperator : public Instruction { const Twine &Name, Instruction *InsertBefore); BinaryOperator(BinaryOps iType, Value *S1, Value *S2, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd); - BinaryOperator *clone_impl() const override; + + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + BinaryOperator *cloneImpl() const; + public: // allocate space for exactly two operands void *operator new(size_t s) { @@ -655,13 +675,7 @@ class CastInst : public UnaryInstruction { /// Opcode op is valid or not. /// @returns true iff the proposed cast is valid. /// @brief Determine if a cast is valid without creating one. - // @LOCALMOD-BEGIN - static bool castIsValid(Instruction::CastOps op, Type *SrcTy, Type *DstTy); - - static bool castIsValid(Instruction::CastOps op, Value *S, Type *DstTy) { - return castIsValid(op, S->getType(), DstTy); - } - // @LOCALMOD-END + static bool castIsValid(Instruction::CastOps op, Value *S, Type *DstTy); /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { diff --git a/include/llvm/IR/Instruction.def b/include/llvm/IR/Instruction.def index d46314cc761..9af666204da 100644 --- a/include/llvm/IR/Instruction.def +++ b/include/llvm/IR/Instruction.def @@ -94,86 +94,92 @@ // instructions for it to be a well formed basic block. // FIRST_TERM_INST ( 1) -HANDLE_TERM_INST ( 1, Ret , ReturnInst) -HANDLE_TERM_INST ( 2, Br , BranchInst) -HANDLE_TERM_INST ( 3, Switch , SwitchInst) -HANDLE_TERM_INST ( 4, IndirectBr , IndirectBrInst) -HANDLE_TERM_INST ( 5, Invoke , InvokeInst) -HANDLE_TERM_INST ( 6, Resume , ResumeInst) -HANDLE_TERM_INST ( 7, Unreachable, UnreachableInst) - LAST_TERM_INST ( 7) +HANDLE_TERM_INST ( 1, Ret , ReturnInst) +HANDLE_TERM_INST ( 2, Br , BranchInst) +HANDLE_TERM_INST ( 3, Switch , SwitchInst) +HANDLE_TERM_INST ( 4, IndirectBr , IndirectBrInst) +HANDLE_TERM_INST ( 5, Invoke , InvokeInst) +HANDLE_TERM_INST ( 6, Resume , ResumeInst) +HANDLE_TERM_INST ( 7, Unreachable , UnreachableInst) +HANDLE_TERM_INST ( 8, CleanupRet , CleanupReturnInst) +HANDLE_TERM_INST ( 9, CatchRet , CatchReturnInst) +HANDLE_TERM_INST (10, CatchPad , CatchPadInst) +HANDLE_TERM_INST (11, TerminatePad, TerminatePadInst) +HANDLE_TERM_INST (12, CatchEndPad , CatchEndPadInst) + LAST_TERM_INST (12) // Standard binary operators... - FIRST_BINARY_INST( 8) -HANDLE_BINARY_INST( 8, Add , BinaryOperator) -HANDLE_BINARY_INST( 9, FAdd , BinaryOperator) -HANDLE_BINARY_INST(10, Sub , BinaryOperator) -HANDLE_BINARY_INST(11, FSub , BinaryOperator) -HANDLE_BINARY_INST(12, Mul , BinaryOperator) -HANDLE_BINARY_INST(13, FMul , BinaryOperator) -HANDLE_BINARY_INST(14, UDiv , BinaryOperator) -HANDLE_BINARY_INST(15, SDiv , BinaryOperator) -HANDLE_BINARY_INST(16, FDiv , BinaryOperator) -HANDLE_BINARY_INST(17, URem , BinaryOperator) -HANDLE_BINARY_INST(18, SRem , BinaryOperator) -HANDLE_BINARY_INST(19, FRem , BinaryOperator) + FIRST_BINARY_INST(13) +HANDLE_BINARY_INST(13, Add , BinaryOperator) +HANDLE_BINARY_INST(14, FAdd , BinaryOperator) +HANDLE_BINARY_INST(15, Sub , BinaryOperator) +HANDLE_BINARY_INST(16, FSub , BinaryOperator) +HANDLE_BINARY_INST(17, Mul , BinaryOperator) +HANDLE_BINARY_INST(18, FMul , BinaryOperator) +HANDLE_BINARY_INST(19, UDiv , BinaryOperator) +HANDLE_BINARY_INST(20, SDiv , BinaryOperator) +HANDLE_BINARY_INST(21, FDiv , BinaryOperator) +HANDLE_BINARY_INST(22, URem , BinaryOperator) +HANDLE_BINARY_INST(23, SRem , BinaryOperator) +HANDLE_BINARY_INST(24, FRem , BinaryOperator) // Logical operators (integer operands) -HANDLE_BINARY_INST(20, Shl , BinaryOperator) // Shift left (logical) -HANDLE_BINARY_INST(21, LShr , BinaryOperator) // Shift right (logical) -HANDLE_BINARY_INST(22, AShr , BinaryOperator) // Shift right (arithmetic) -HANDLE_BINARY_INST(23, And , BinaryOperator) -HANDLE_BINARY_INST(24, Or , BinaryOperator) -HANDLE_BINARY_INST(25, Xor , BinaryOperator) - LAST_BINARY_INST(25) +HANDLE_BINARY_INST(25, Shl , BinaryOperator) // Shift left (logical) +HANDLE_BINARY_INST(26, LShr , BinaryOperator) // Shift right (logical) +HANDLE_BINARY_INST(27, AShr , BinaryOperator) // Shift right (arithmetic) +HANDLE_BINARY_INST(28, And , BinaryOperator) +HANDLE_BINARY_INST(29, Or , BinaryOperator) +HANDLE_BINARY_INST(30, Xor , BinaryOperator) + LAST_BINARY_INST(30) // Memory operators... - FIRST_MEMORY_INST(26) -HANDLE_MEMORY_INST(26, Alloca, AllocaInst) // Stack management -HANDLE_MEMORY_INST(27, Load , LoadInst ) // Memory manipulation instrs -HANDLE_MEMORY_INST(28, Store , StoreInst ) -HANDLE_MEMORY_INST(29, GetElementPtr, GetElementPtrInst) -HANDLE_MEMORY_INST(30, Fence , FenceInst ) -HANDLE_MEMORY_INST(31, AtomicCmpXchg , AtomicCmpXchgInst ) -HANDLE_MEMORY_INST(32, AtomicRMW , AtomicRMWInst ) - LAST_MEMORY_INST(32) + FIRST_MEMORY_INST(31) +HANDLE_MEMORY_INST(31, Alloca, AllocaInst) // Stack management +HANDLE_MEMORY_INST(32, Load , LoadInst ) // Memory manipulation instrs +HANDLE_MEMORY_INST(33, Store , StoreInst ) +HANDLE_MEMORY_INST(34, GetElementPtr, GetElementPtrInst) +HANDLE_MEMORY_INST(35, Fence , FenceInst ) +HANDLE_MEMORY_INST(36, AtomicCmpXchg , AtomicCmpXchgInst ) +HANDLE_MEMORY_INST(37, AtomicRMW , AtomicRMWInst ) + LAST_MEMORY_INST(37) // Cast operators ... // NOTE: The order matters here because CastInst::isEliminableCastPair // NOTE: (see Instructions.cpp) encodes a table based on this ordering. - FIRST_CAST_INST(33) -HANDLE_CAST_INST(33, Trunc , TruncInst ) // Truncate integers -HANDLE_CAST_INST(34, ZExt , ZExtInst ) // Zero extend integers -HANDLE_CAST_INST(35, SExt , SExtInst ) // Sign extend integers -HANDLE_CAST_INST(36, FPToUI , FPToUIInst ) // floating point -> UInt -HANDLE_CAST_INST(37, FPToSI , FPToSIInst ) // floating point -> SInt -HANDLE_CAST_INST(38, UIToFP , UIToFPInst ) // UInt -> floating point -HANDLE_CAST_INST(39, SIToFP , SIToFPInst ) // SInt -> floating point -HANDLE_CAST_INST(40, FPTrunc , FPTruncInst ) // Truncate floating point -HANDLE_CAST_INST(41, FPExt , FPExtInst ) // Extend floating point -HANDLE_CAST_INST(42, PtrToInt, PtrToIntInst) // Pointer -> Integer -HANDLE_CAST_INST(43, IntToPtr, IntToPtrInst) // Integer -> Pointer -HANDLE_CAST_INST(44, BitCast , BitCastInst ) // Type cast -HANDLE_CAST_INST(45, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast - LAST_CAST_INST(45) + FIRST_CAST_INST(38) +HANDLE_CAST_INST(38, Trunc , TruncInst ) // Truncate integers +HANDLE_CAST_INST(39, ZExt , ZExtInst ) // Zero extend integers +HANDLE_CAST_INST(40, SExt , SExtInst ) // Sign extend integers +HANDLE_CAST_INST(41, FPToUI , FPToUIInst ) // floating point -> UInt +HANDLE_CAST_INST(42, FPToSI , FPToSIInst ) // floating point -> SInt +HANDLE_CAST_INST(43, UIToFP , UIToFPInst ) // UInt -> floating point +HANDLE_CAST_INST(44, SIToFP , SIToFPInst ) // SInt -> floating point +HANDLE_CAST_INST(45, FPTrunc , FPTruncInst ) // Truncate floating point +HANDLE_CAST_INST(46, FPExt , FPExtInst ) // Extend floating point +HANDLE_CAST_INST(47, PtrToInt, PtrToIntInst) // Pointer -> Integer +HANDLE_CAST_INST(48, IntToPtr, IntToPtrInst) // Integer -> Pointer +HANDLE_CAST_INST(49, BitCast , BitCastInst ) // Type cast +HANDLE_CAST_INST(50, AddrSpaceCast, AddrSpaceCastInst) // addrspace cast + LAST_CAST_INST(50) // Other operators... - FIRST_OTHER_INST(46) -HANDLE_OTHER_INST(46, ICmp , ICmpInst ) // Integer comparison instruction -HANDLE_OTHER_INST(47, FCmp , FCmpInst ) // Floating point comparison instr. -HANDLE_OTHER_INST(48, PHI , PHINode ) // PHI node instruction -HANDLE_OTHER_INST(49, Call , CallInst ) // Call a function -HANDLE_OTHER_INST(50, Select , SelectInst ) // select instruction -HANDLE_OTHER_INST(51, UserOp1, Instruction) // May be used internally in a pass -HANDLE_OTHER_INST(52, UserOp2, Instruction) // Internal to passes only -HANDLE_OTHER_INST(53, VAArg , VAArgInst ) // vaarg instruction -HANDLE_OTHER_INST(54, ExtractElement, ExtractElementInst)// extract from vector -HANDLE_OTHER_INST(55, InsertElement, InsertElementInst) // insert into vector -HANDLE_OTHER_INST(56, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. -HANDLE_OTHER_INST(57, ExtractValue, ExtractValueInst)// extract from aggregate -HANDLE_OTHER_INST(58, InsertValue, InsertValueInst) // insert into aggregate -HANDLE_OTHER_INST(59, LandingPad, LandingPadInst) // Landing pad instruction. - LAST_OTHER_INST(59) + FIRST_OTHER_INST(51) +HANDLE_OTHER_INST(51, ICmp , ICmpInst ) // Integer comparison instruction +HANDLE_OTHER_INST(52, FCmp , FCmpInst ) // Floating point comparison instr. +HANDLE_OTHER_INST(53, PHI , PHINode ) // PHI node instruction +HANDLE_OTHER_INST(54, Call , CallInst ) // Call a function +HANDLE_OTHER_INST(55, Select , SelectInst ) // select instruction +HANDLE_OTHER_INST(56, UserOp1, Instruction) // May be used internally in a pass +HANDLE_OTHER_INST(57, UserOp2, Instruction) // Internal to passes only +HANDLE_OTHER_INST(58, VAArg , VAArgInst ) // vaarg instruction +HANDLE_OTHER_INST(59, ExtractElement, ExtractElementInst)// extract from vector +HANDLE_OTHER_INST(60, InsertElement, InsertElementInst) // insert into vector +HANDLE_OTHER_INST(61, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. +HANDLE_OTHER_INST(62, ExtractValue, ExtractValueInst)// extract from aggregate +HANDLE_OTHER_INST(63, InsertValue, InsertValueInst) // insert into aggregate +HANDLE_OTHER_INST(64, LandingPad, LandingPadInst) // Landing pad instruction. +HANDLE_OTHER_INST(65, CleanupPad, CleanupPadInst) + LAST_OTHER_INST(65) #undef FIRST_TERM_INST #undef HANDLE_TERM_INST diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h index 9dd16fd5a60..3c48efb4561 100644 --- a/include/llvm/IR/Instruction.h +++ b/include/llvm/IR/Instruction.h @@ -78,6 +78,7 @@ class Instruction : public User, public ilist_node { /// Note: this is undefined behavior if the instruction does not have a /// parent, or the parent basic block does not have a parent function. const Module *getModule() const; + Module *getModule(); /// removeFromParent - This method unlinks 'this' from the containing basic /// block, but does not delete it. @@ -90,12 +91,12 @@ class Instruction : public User, public ilist_node { /// \returns an iterator pointing to the element after the erased one iplist::iterator eraseFromParent(); - /// insertBefore - Insert an unlinked instructions into a basic block - /// immediately before the specified instruction. + /// Insert an unlinked instruction into a basic block immediately before + /// the specified instruction. void insertBefore(Instruction *InsertPos); - /// insertAfter - Insert an unlinked instructions into a basic block - /// immediately after the specified instruction. + /// Insert an unlinked instruction into a basic block immediately after the + /// specified instruction. void insertAfter(Instruction *InsertPos); /// moveBefore - Unlink this instruction from its current basic block and @@ -381,12 +382,26 @@ class Instruction : public User, public ilist_node { /// /// Note that this does not consider malloc and alloca to have side /// effects because the newly allocated memory is completely invisible to - /// instructions which don't used the returned value. For cases where this + /// instructions which don't use the returned value. For cases where this /// matters, isSafeToSpeculativelyExecute may be more appropriate. bool mayHaveSideEffects() const { return mayWriteToMemory() || mayThrow() || !mayReturn(); } + /// \brief Return true if the instruction is a variety of EH-block. + bool isEHPad() const { + switch (getOpcode()) { + case Instruction::CatchPad: + case Instruction::CatchEndPad: + case Instruction::CleanupPad: + case Instruction::LandingPad: + case Instruction::TerminatePad: + return true; + default: + return false; + } + } + /// clone() - Create a copy of 'this' instruction that is identical in all /// ways except the following: /// * The instruction has no parent @@ -508,8 +523,10 @@ class Instruction : public User, public ilist_node { Instruction *InsertBefore = nullptr); Instruction(Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, BasicBlock *InsertAtEnd); - virtual Instruction *clone_impl() const = 0; +private: + /// Create a copy of this instruction. + Instruction *cloneImpl() const; }; inline Instruction *ilist_traits::createSentinel() const { diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index 1f2ca301d24..4330f2f87a7 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -22,6 +22,7 @@ #include "llvm/IR/Attributes.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" #include "llvm/IR/InstrTypes.h" #include "llvm/Support/ErrorHandling.h" #include @@ -73,8 +74,13 @@ return (Ord == Release || /// AllocaInst - an instruction to allocate memory on the stack /// class AllocaInst : public UnaryInstruction { + Type *AllocatedType; + protected: - AllocaInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + AllocaInst *cloneImpl() const; + public: explicit AllocaInst(Type *Ty, Value *ArraySize = nullptr, const Twine &Name = "", @@ -113,7 +119,10 @@ class AllocaInst : public UnaryInstruction { /// getAllocatedType - Return the type that is being allocated by the /// instruction. /// - Type *getAllocatedType() const; + Type *getAllocatedType() const { return AllocatedType; } + /// \brief for use only in special circumstances that need to generically + /// transform a whole instruction (eg: IR linking and vectorization). + void setAllocatedType(Type *Ty) { AllocatedType = Ty; } /// getAlignment - Return the alignment of the memory that is being allocated /// by the instruction. @@ -168,15 +177,26 @@ class AllocaInst : public UnaryInstruction { class LoadInst : public UnaryInstruction { void AssertOK(); protected: - LoadInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + LoadInst *cloneImpl() const; + public: LoadInst(Value *Ptr, const Twine &NameStr, Instruction *InsertBefore); LoadInst(Value *Ptr, const Twine &NameStr, BasicBlock *InsertAtEnd); - LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile = false, + LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, bool isVolatile = false, Instruction *InsertBefore = nullptr); + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile = false, + Instruction *InsertBefore = nullptr) + : LoadInst(cast(Ptr->getType())->getElementType(), Ptr, + NameStr, isVolatile, InsertBefore) {} LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, BasicBlock *InsertAtEnd); - LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, + Instruction *InsertBefore = nullptr) + : LoadInst(cast(Ptr->getType())->getElementType(), Ptr, + NameStr, isVolatile, Align, InsertBefore) {} + LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, Instruction *InsertBefore = nullptr); LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, BasicBlock *InsertAtEnd); @@ -196,9 +216,13 @@ class LoadInst : public UnaryInstruction { LoadInst(Value *Ptr, const char *NameStr, Instruction *InsertBefore); LoadInst(Value *Ptr, const char *NameStr, BasicBlock *InsertAtEnd); + LoadInst(Type *Ty, Value *Ptr, const char *NameStr = nullptr, + bool isVolatile = false, Instruction *InsertBefore = nullptr); explicit LoadInst(Value *Ptr, const char *NameStr = nullptr, bool isVolatile = false, - Instruction *InsertBefore = nullptr); + Instruction *InsertBefore = nullptr) + : LoadInst(cast(Ptr->getType())->getElementType(), Ptr, + NameStr, isVolatile, InsertBefore) {} LoadInst(Value *Ptr, const char *NameStr, bool isVolatile, BasicBlock *InsertAtEnd); @@ -293,7 +317,10 @@ class StoreInst : public Instruction { void *operator new(size_t, unsigned) = delete; void AssertOK(); protected: - StoreInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + StoreInst *cloneImpl() const; + public: // allocate space for exactly two operands void *operator new(size_t s) { @@ -419,7 +446,10 @@ class FenceInst : public Instruction { void *operator new(size_t, unsigned) = delete; void Init(AtomicOrdering Ordering, SynchronizationScope SynchScope); protected: - FenceInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + FenceInst *cloneImpl() const; + public: // allocate space for exactly zero operands void *operator new(size_t s) { @@ -488,7 +518,10 @@ class AtomicCmpXchgInst : public Instruction { AtomicOrdering SuccessOrdering, AtomicOrdering FailureOrdering, SynchronizationScope SynchScope); protected: - AtomicCmpXchgInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + AtomicCmpXchgInst *cloneImpl() const; + public: // allocate space for exactly three operands void *operator new(size_t s) { @@ -641,7 +674,10 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(AtomicCmpXchgInst, Value) class AtomicRMWInst : public Instruction { void *operator new(size_t, unsigned) = delete; protected: - AtomicRMWInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + AtomicRMWInst *cloneImpl() const; + public: /// This enumeration lists the possible modifications atomicrmw can make. In /// the descriptions, 'p' is the pointer to the instruction's memory location, @@ -792,6 +828,9 @@ inline Type *checkGEPType(Type *Ty) { /// access elements of arrays and structs /// class GetElementPtrInst : public Instruction { + Type *SourceElementType; + Type *ResultElementType; + GetElementPtrInst(const GetElementPtrInst &GEPI); void init(Value *Ptr, ArrayRef IdxList, const Twine &NameStr); @@ -807,13 +846,23 @@ class GetElementPtrInst : public Instruction { const Twine &NameStr, BasicBlock *InsertAtEnd); protected: - GetElementPtrInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + GetElementPtrInst *cloneImpl() const; + public: static GetElementPtrInst *Create(Type *PointeeType, Value *Ptr, ArrayRef IdxList, const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { unsigned Values = 1 + unsigned(IdxList.size()); + if (!PointeeType) + PointeeType = + cast(Ptr->getType()->getScalarType())->getElementType(); + else + assert( + PointeeType == + cast(Ptr->getType()->getScalarType())->getElementType()); return new (Values) GetElementPtrInst(PointeeType, Ptr, IdxList, Values, NameStr, InsertBefore); } @@ -822,6 +871,13 @@ class GetElementPtrInst : public Instruction { const Twine &NameStr, BasicBlock *InsertAtEnd) { unsigned Values = 1 + unsigned(IdxList.size()); + if (!PointeeType) + PointeeType = + cast(Ptr->getType()->getScalarType())->getElementType(); + else + assert( + PointeeType == + cast(Ptr->getType()->getScalarType())->getElementType()); return new (Values) GetElementPtrInst(PointeeType, Ptr, IdxList, Values, NameStr, InsertAtEnd); } @@ -867,12 +923,16 @@ class GetElementPtrInst : public Instruction { return cast(Instruction::getType()); } - Type *getSourceElementType() const { - return cast(getPointerOperandType()->getScalarType()) - ->getElementType(); - } + Type *getSourceElementType() const { return SourceElementType; } + + void setSourceElementType(Type *Ty) { SourceElementType = Ty; } + void setResultElementType(Type *Ty) { ResultElementType = Ty; } - Type *getResultElementType() const { return getType()->getElementType(); } + Type *getResultElementType() const { + assert(ResultElementType == + cast(getType()->getScalarType())->getElementType()); + return ResultElementType; + } /// \brief Returns the address space of this instruction's pointer type. unsigned getAddressSpace() const { @@ -920,18 +980,24 @@ class GetElementPtrInst : public Instruction { /// GetGEPReturnType - Returns the pointer type returned by the GEP /// instruction, which may be a vector of pointers. static Type *getGEPReturnType(Value *Ptr, ArrayRef IdxList) { - Type *PtrTy = - PointerType::get(checkGEPType(getIndexedType( - cast(Ptr->getType()->getScalarType()) - ->getElementType(), - IdxList)), - Ptr->getType()->getPointerAddressSpace()); + return getGEPReturnType( + cast(Ptr->getType()->getScalarType())->getElementType(), + Ptr, IdxList); + } + static Type *getGEPReturnType(Type *ElTy, Value *Ptr, + ArrayRef IdxList) { + Type *PtrTy = PointerType::get(checkGEPType(getIndexedType(ElTy, IdxList)), + Ptr->getType()->getPointerAddressSpace()); // Vector GEP if (Ptr->getType()->isVectorTy()) { - unsigned NumElem = cast(Ptr->getType())->getNumElements(); + unsigned NumElem = Ptr->getType()->getVectorNumElements(); return VectorType::get(PtrTy, NumElem); } - + for (Value *Index : IdxList) + if (Index->getType()->isVectorTy()) { + unsigned NumElem = Index->getType()->getVectorNumElements(); + return VectorType::get(PtrTy, NumElem); + } // Scalar GEP return PtrTy; } @@ -989,21 +1055,27 @@ GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr, ArrayRef IdxList, unsigned Values, const Twine &NameStr, Instruction *InsertBefore) - : Instruction(getGEPReturnType(Ptr, IdxList), GetElementPtr, + : Instruction(getGEPReturnType(PointeeType, Ptr, IdxList), GetElementPtr, OperandTraits::op_end(this) - Values, - Values, InsertBefore) { + Values, InsertBefore), + SourceElementType(PointeeType), + ResultElementType(getIndexedType(PointeeType, IdxList)) { + assert(ResultElementType == + cast(getType()->getScalarType())->getElementType()); init(Ptr, IdxList, NameStr); - assert(!PointeeType || PointeeType == getSourceElementType()); } GetElementPtrInst::GetElementPtrInst(Type *PointeeType, Value *Ptr, ArrayRef IdxList, unsigned Values, const Twine &NameStr, BasicBlock *InsertAtEnd) - : Instruction(getGEPReturnType(Ptr, IdxList), GetElementPtr, + : Instruction(getGEPReturnType(PointeeType, Ptr, IdxList), GetElementPtr, OperandTraits::op_end(this) - Values, - Values, InsertAtEnd) { + Values, InsertAtEnd), + SourceElementType(PointeeType), + ResultElementType(getIndexedType(PointeeType, IdxList)) { + assert(ResultElementType == + cast(getType()->getScalarType())->getElementType()); init(Ptr, IdxList, NameStr); - assert(!PointeeType || PointeeType == getSourceElementType()); } @@ -1032,8 +1104,11 @@ class ICmpInst: public CmpInst { } protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; /// \brief Clone an identical ICmpInst - ICmpInst *clone_impl() const override; + ICmpInst *cloneImpl() const; + public: /// \brief Constructor with insert-before-instruction semantics. ICmpInst( @@ -1164,8 +1239,11 @@ class ICmpInst: public CmpInst { /// \brief Represents a floating point comparison operator. class FCmpInst: public CmpInst { protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; /// \brief Clone an identical FCmpInst - FCmpInst *clone_impl() const override; + FCmpInst *cloneImpl() const; + public: /// \brief Constructor with insert-before-instruction semantics. FCmpInst( @@ -1274,14 +1352,26 @@ class FCmpInst: public CmpInst { /// class CallInst : public Instruction { AttributeSet AttributeList; ///< parameter attributes for call + FunctionType *FTy; CallInst(const CallInst &CI); - void init(Value *Func, ArrayRef Args, const Twine &NameStr); + void init(Value *Func, ArrayRef Args, const Twine &NameStr) { + init(cast( + cast(Func->getType())->getElementType()), + Func, Args, NameStr); + } + void init(FunctionType *FTy, Value *Func, ArrayRef Args, + const Twine &NameStr); void init(Value *Func, const Twine &NameStr); /// Construct a CallInst given a range of arguments. /// \brief Construct a CallInst from a range of arguments - inline CallInst(Value *Func, ArrayRef Args, + inline CallInst(FunctionType *Ty, Value *Func, ArrayRef Args, const Twine &NameStr, Instruction *InsertBefore); + inline CallInst(Value *Func, ArrayRef Args, const Twine &NameStr, + Instruction *InsertBefore) + : CallInst(cast( + cast(Func->getType())->getElementType()), + Func, Args, NameStr, InsertBefore) {} /// Construct a CallInst given a range of arguments. /// \brief Construct a CallInst from a range of arguments @@ -1292,14 +1382,24 @@ class CallInst : public Instruction { Instruction *InsertBefore); CallInst(Value *F, const Twine &NameStr, BasicBlock *InsertAtEnd); protected: - CallInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + CallInst *cloneImpl() const; + public: static CallInst *Create(Value *Func, ArrayRef Args, const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { - return new(unsigned(Args.size() + 1)) - CallInst(Func, Args, NameStr, InsertBefore); + return Create(cast( + cast(Func->getType())->getElementType()), + Func, Args, NameStr, InsertBefore); + } + static CallInst *Create(FunctionType *Ty, Value *Func, ArrayRef Args, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + return new (unsigned(Args.size() + 1)) + CallInst(Ty, Func, Args, NameStr, InsertBefore); } static CallInst *Create(Value *Func, ArrayRef Args, @@ -1337,8 +1437,11 @@ class CallInst : public Instruction { ~CallInst() override; - Type *getFunctionType() const { - return cast(getCalledValue()->getType())->getElementType(); + FunctionType *getFunctionType() const { return FTy; } + + void mutateFunctionType(FunctionType *FTy) { + mutateType(FTy->getReturnType()); + this->FTy = FTy; } // Note that 'musttail' implies 'tail'. @@ -1410,6 +1513,9 @@ class CallInst : public Instruction { /// addAttribute - adds the attribute to the list of attributes. void addAttribute(unsigned i, Attribute::AttrKind attr); + /// addAttribute - adds the attribute to the list of attributes. + void addAttribute(unsigned i, StringRef Kind, StringRef Value); + /// removeAttribute - removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attribute attr); @@ -1427,6 +1533,11 @@ class CallInst : public Instruction { return hasFnAttrImpl(A); } + /// \brief Determine whether this call has the given attribute. + bool hasFnAttr(StringRef A) const { + return hasFnAttrImpl(A); + } + /// \brief Determine whether the call or the callee has the given attributes. bool paramHasAttr(unsigned i, Attribute::AttrKind A) const; @@ -1441,6 +1552,12 @@ class CallInst : public Instruction { return AttributeList.getDereferenceableBytes(i); } + /// \brief Extract the number of dereferenceable_or_null bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableOrNullBytes(unsigned i) const { + return AttributeList.getDereferenceableOrNullBytes(i); + } + /// \brief Return true if the call should not be treated as a call to a /// builtin. bool isNoBuiltin() const { @@ -1478,6 +1595,15 @@ class CallInst : public Instruction { addAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly); } + /// @brief Determine if the call can access memmory only using pointers based + /// on its arguments. + bool onlyAccessesArgMemory() const { + return hasFnAttr(Attribute::ArgMemOnly); + } + void setOnlyAccessesArgMemory() { + addAttribute(AttributeSet::FunctionIndex, Attribute::ArgMemOnly); + } + /// \brief Determine if the call cannot return. bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); } void setDoesNotReturn() { @@ -1522,6 +1648,14 @@ class CallInst : public Instruction { /// setCalledFunction - Set the function called. void setCalledFunction(Value* Fn) { + setCalledFunction( + cast(cast(Fn->getType())->getElementType()), + Fn); + } + void setCalledFunction(FunctionType *FTy, Value *Fn) { + this->FTy = FTy; + assert(FTy == cast( + cast(Fn->getType())->getElementType())); Op<-1>() = Fn; } @@ -1539,7 +1673,14 @@ class CallInst : public Instruction { } private: - bool hasFnAttrImpl(Attribute::AttrKind A) const; + template + bool hasFnAttrImpl(AttrKind A) const { + if (AttributeList.hasAttribute(AttributeSet::FunctionIndex, A)) + return true; + if (const Function *F = getCalledFunction()) + return F->getAttributes().hasAttribute(AttributeSet::FunctionIndex, A); + return false; + } // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. @@ -1562,14 +1703,12 @@ CallInst::CallInst(Value *Func, ArrayRef Args, init(Func, Args, NameStr); } -CallInst::CallInst(Value *Func, ArrayRef Args, +CallInst::CallInst(FunctionType *Ty, Value *Func, ArrayRef Args, const Twine &NameStr, Instruction *InsertBefore) - : Instruction(cast(cast(Func->getType()) - ->getElementType())->getReturnType(), - Instruction::Call, - OperandTraits::op_end(this) - (Args.size() + 1), - unsigned(Args.size() + 1), InsertBefore) { - init(Func, Args, NameStr); + : Instruction(Ty->getReturnType(), Instruction::Call, + OperandTraits::op_end(this) - (Args.size() + 1), + unsigned(Args.size() + 1), InsertBefore) { + init(Ty, Func, Args, NameStr); } @@ -1607,7 +1746,10 @@ class SelectInst : public Instruction { setName(NameStr); } protected: - SelectInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + SelectInst *cloneImpl() const; + public: static SelectInst *Create(Value *C, Value *S1, Value *S2, const Twine &NameStr = "", @@ -1662,7 +1804,9 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SelectInst, Value) /// class VAArgInst : public UnaryInstruction { protected: - VAArgInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + VAArgInst *cloneImpl() const; public: VAArgInst(Value *List, Type *Ty, const Twine &NameStr = "", @@ -1702,7 +1846,9 @@ class ExtractElementInst : public Instruction { ExtractElementInst(Value *Vec, Value *Idx, const Twine &NameStr, BasicBlock *InsertAtEnd); protected: - ExtractElementInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + ExtractElementInst *cloneImpl() const; public: static ExtractElementInst *Create(Value *Vec, Value *Idx, @@ -1763,7 +1909,9 @@ class InsertElementInst : public Instruction { InsertElementInst(Value *Vec, Value *NewElt, Value *Idx, const Twine &NameStr, BasicBlock *InsertAtEnd); protected: - InsertElementInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + InsertElementInst *cloneImpl() const; public: static InsertElementInst *Create(Value *Vec, Value *NewElt, Value *Idx, @@ -1816,7 +1964,9 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementInst, Value) /// class ShuffleVectorInst : public Instruction { protected: - ShuffleVectorInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + ShuffleVectorInst *cloneImpl() const; public: // allocate space for exactly three operands @@ -1917,7 +2067,9 @@ class ExtractValueInst : public UnaryInstruction { return User::operator new(s, 1); } protected: - ExtractValueInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + ExtractValueInst *cloneImpl() const; public: static ExtractValueInst *Create(Value *Agg, @@ -2031,7 +2183,10 @@ class InsertValueInst : public Instruction { InsertValueInst(Value *Agg, Value *Val, unsigned Idx, const Twine &NameStr, BasicBlock *InsertAtEnd); protected: - InsertValueInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + InsertValueInst *cloneImpl() const; + public: // allocate space for exactly two operands void *operator new(size_t s) { @@ -2146,7 +2301,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 = "", @@ -2154,7 +2309,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, @@ -2162,15 +2317,20 @@ 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); + } + + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + PHINode *cloneImpl() const; - PHINode *clone_impl() const override; public: /// Constructors - NumReservedValues is a hint for the number of incoming /// edges that this phi node will have (use 0 if you really have no idea). @@ -2183,7 +2343,6 @@ class PHINode : public Instruction { const Twine &NameStr, BasicBlock *InsertAtEnd) { return new PHINode(Ty, NumReservedValues, NameStr, InsertAtEnd); } - ~PHINode() override; /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2216,6 +2375,8 @@ class PHINode : public Instruction { op_range incoming_values() { return operands(); } + const_op_range incoming_values() const { return operands(); } + /// getNumIncomingValues - Return the number of incoming edges /// unsigned getNumIncomingValues() const { return getNumOperands(); } @@ -2267,12 +2428,12 @@ class PHINode : public Instruction { 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 @@ -2351,38 +2512,33 @@ class LandingPadInst : public Instruction { 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); + void init(unsigned NumReservedValues, const Twine &NameStr); + + explicit LandingPadInst(Type *RetTy, unsigned NumReservedValues, + const Twine &NameStr, Instruction *InsertBefore); + explicit LandingPadInst(Type *RetTy, unsigned NumReservedValues, + const Twine &NameStr, BasicBlock *InsertAtEnd); - explicit LandingPadInst(Type *RetTy, Value *PersonalityFn, - unsigned NumReservedValues, const Twine &NameStr, - Instruction *InsertBefore); - explicit LandingPadInst(Type *RetTy, Value *PersonalityFn, - unsigned NumReservedValues, const Twine &NameStr, - BasicBlock *InsertAtEnd); protected: - LandingPadInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + LandingPadInst *cloneImpl() const; + public: /// Constructors - NumReservedClauses is a hint for the number of incoming /// clauses that this landingpad will have (use 0 if you really have no idea). - static LandingPadInst *Create(Type *RetTy, Value *PersonalityFn, - unsigned NumReservedClauses, + static LandingPadInst *Create(Type *RetTy, unsigned NumReservedClauses, const Twine &NameStr = "", Instruction *InsertBefore = nullptr); - static LandingPadInst *Create(Type *RetTy, Value *PersonalityFn, - unsigned NumReservedClauses, + static LandingPadInst *Create(Type *RetTy, unsigned NumReservedClauses, const Twine &NameStr, BasicBlock *InsertAtEnd); - ~LandingPadInst() override; /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - /// getPersonalityFn - Get the personality function associated with this - /// landing pad. - Value *getPersonalityFn() const { return getOperand(0); } - /// isCleanup - Return 'true' if this landingpad instruction is a /// cleanup. I.e., it should be run when unwinding even if its landing pad /// doesn't catch the exception. @@ -2400,21 +2556,21 @@ class LandingPadInst : public Instruction { /// 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(OperandList[Idx + 1]); + return cast(getOperandList()[Idx]); } /// isCatch - Return 'true' if the clause and index Idx is a catch clause. bool isCatch(unsigned Idx) const { - return !isa(OperandList[Idx + 1]->getType()); + return !isa(getOperandList()[Idx]->getType()); } /// isFilter - Return 'true' if the clause and index Idx is a filter clause. bool isFilter(unsigned Idx) const { - return isa(OperandList[Idx + 1]->getType()); + return isa(getOperandList()[Idx]->getType()); } /// getNumClauses - Get the number of clauses for this landing pad. - unsigned getNumClauses() const { return getNumOperands() - 1; } + unsigned getNumClauses() const { return getNumOperands(); } /// reserveClauses - Grow the size of the operand list to accommodate the new /// number of clauses. @@ -2430,7 +2586,7 @@ class LandingPadInst : public Instruction { }; template <> -struct OperandTraits : public HungoffOperandTraits<2> { +struct OperandTraits : public HungoffOperandTraits<1> { }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(LandingPadInst, Value) @@ -2463,7 +2619,10 @@ class ReturnInst : public TerminatorInst { ReturnInst(LLVMContext &C, Value *retVal, BasicBlock *InsertAtEnd); explicit ReturnInst(LLVMContext &C, BasicBlock *InsertAtEnd); protected: - ReturnInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + ReturnInst *cloneImpl() const; + public: static ReturnInst* Create(LLVMContext &C, Value *retVal = nullptr, Instruction *InsertBefore = nullptr) { @@ -2535,7 +2694,10 @@ class BranchInst : public TerminatorInst { BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, BasicBlock *InsertAtEnd); protected: - BranchInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + BranchInst *cloneImpl() const; + public: static BranchInst *Create(BasicBlock *IfTrue, Instruction *InsertBefore = nullptr) { @@ -2626,7 +2788,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 @@ -2642,7 +2804,10 @@ class SwitchInst : public TerminatorInst { SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, BasicBlock *InsertAtEnd); protected: - SwitchInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + SwitchInst *cloneImpl() const; + public: // -2 @@ -2773,8 +2938,6 @@ class SwitchInst : public TerminatorInst { return new SwitchInst(Value, Default, NumCases, InsertAtEnd); } - ~SwitchInst() override; - /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2935,7 +3098,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 @@ -2949,7 +3112,10 @@ class IndirectBrInst : public TerminatorInst { /// autoinserts at the end of the specified BasicBlock. IndirectBrInst(Value *Address, unsigned NumDests, BasicBlock *InsertAtEnd); protected: - IndirectBrInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + IndirectBrInst *cloneImpl() const; + public: static IndirectBrInst *Create(Value *Address, unsigned NumDests, Instruction *InsertBefore = nullptr) { @@ -2959,7 +3125,6 @@ class IndirectBrInst : public TerminatorInst { BasicBlock *InsertAtEnd) { return new IndirectBrInst(Address, NumDests, InsertAtEnd); } - ~IndirectBrInst() override; /// Provide fast operand accessors. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -3023,17 +3188,33 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(IndirectBrInst, Value) /// class InvokeInst : public TerminatorInst { AttributeSet AttributeList; + FunctionType *FTy; InvokeInst(const InvokeInst &BI); void init(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, - ArrayRef Args, const Twine &NameStr); + ArrayRef Args, const Twine &NameStr) { + init(cast( + cast(Func->getType())->getElementType()), + Func, IfNormal, IfException, Args, NameStr); + } + void init(FunctionType *FTy, Value *Func, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef Args, + const Twine &NameStr); /// Construct an InvokeInst given a range of arguments. /// /// \brief Construct an InvokeInst from a range of arguments inline InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef Args, unsigned Values, - const Twine &NameStr, Instruction *InsertBefore); - + const Twine &NameStr, Instruction *InsertBefore) + : InvokeInst(cast( + cast(Func->getType())->getElementType()), + Func, IfNormal, IfException, Args, Values, NameStr, + InsertBefore) {} + + inline InvokeInst(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef Args, + unsigned Values, const Twine &NameStr, + Instruction *InsertBefore); /// Construct an InvokeInst given a range of arguments. /// /// \brief Construct an InvokeInst from a range of arguments @@ -3041,15 +3222,26 @@ class InvokeInst : public TerminatorInst { ArrayRef Args, unsigned Values, const Twine &NameStr, BasicBlock *InsertAtEnd); protected: - InvokeInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + InvokeInst *cloneImpl() const; + public: static InvokeInst *Create(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, ArrayRef Args, const Twine &NameStr = "", Instruction *InsertBefore = nullptr) { + return Create(cast( + cast(Func->getType())->getElementType()), + Func, IfNormal, IfException, Args, NameStr, InsertBefore); + } + static InvokeInst *Create(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef Args, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { unsigned Values = unsigned(Args.size()) + 3; - return new(Values) InvokeInst(Func, IfNormal, IfException, Args, - Values, NameStr, InsertBefore); + return new (Values) InvokeInst(Ty, Func, IfNormal, IfException, Args, + Values, NameStr, InsertBefore); } static InvokeInst *Create(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, @@ -3063,6 +3255,13 @@ class InvokeInst : public TerminatorInst { /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + FunctionType *getFunctionType() const { return FTy; } + + void mutateFunctionType(FunctionType *FTy) { + mutateType(FTy->getReturnType()); + this->FTy = FTy; + } + /// getNumArgOperands - Return the number of invoke arguments. /// unsigned getNumArgOperands() const { return getNumOperands() - 3; } @@ -3136,6 +3335,12 @@ class InvokeInst : public TerminatorInst { uint64_t getDereferenceableBytes(unsigned i) const { return AttributeList.getDereferenceableBytes(i); } + + /// \brief Extract the number of dereferenceable_or_null bytes for a call or + /// parameter (0=unknown). + uint64_t getDereferenceableOrNullBytes(unsigned i) const { + return AttributeList.getDereferenceableOrNullBytes(i); + } /// \brief Return true if the call should not be treated as a call to a /// builtin. @@ -3168,6 +3373,15 @@ class InvokeInst : public TerminatorInst { addAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly); } + /// @brief Determine if the call access memmory only using it's pointer + /// arguments. + bool onlyAccessesArgMemory() const { + return hasFnAttr(Attribute::ArgMemOnly); + } + void setOnlyAccessesArgMemory() { + addAttribute(AttributeSet::FunctionIndex, Attribute::ArgMemOnly); + } + /// \brief Determine if the call cannot return. bool doesNotReturn() const { return hasFnAttr(Attribute::NoReturn); } void setDoesNotReturn() { @@ -3212,6 +3426,14 @@ class InvokeInst : public TerminatorInst { /// setCalledFunction - Set the function called. void setCalledFunction(Value* Fn) { + setCalledFunction( + cast(cast(Fn->getType())->getElementType()), + Fn); + } + void setCalledFunction(FunctionType *FTy, Value *Fn) { + this->FTy = FTy; + assert(FTy == cast( + cast(Fn->getType())->getElementType())); Op<-3>() = Fn; } @@ -3271,16 +3493,14 @@ template <> struct OperandTraits : public VariadicOperandTraits { }; -InvokeInst::InvokeInst(Value *Func, - BasicBlock *IfNormal, BasicBlock *IfException, - ArrayRef Args, unsigned Values, - const Twine &NameStr, Instruction *InsertBefore) - : TerminatorInst(cast(cast(Func->getType()) - ->getElementType())->getReturnType(), - Instruction::Invoke, - OperandTraits::op_end(this) - Values, - Values, InsertBefore) { - init(Func, IfNormal, IfException, Args, NameStr); +InvokeInst::InvokeInst(FunctionType *Ty, Value *Func, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef Args, + unsigned Values, const Twine &NameStr, + Instruction *InsertBefore) + : TerminatorInst(Ty->getReturnType(), Instruction::Invoke, + OperandTraits::op_end(this) - Values, Values, + InsertBefore) { + init(Ty, Func, IfNormal, IfException, Args, NameStr); } InvokeInst::InvokeInst(Value *Func, BasicBlock *IfNormal, BasicBlock *IfException, @@ -3309,7 +3529,10 @@ class ResumeInst : public TerminatorInst { explicit ResumeInst(Value *Exn, Instruction *InsertBefore=nullptr); ResumeInst(Value *Exn, BasicBlock *InsertAtEnd); protected: - ResumeInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + ResumeInst *cloneImpl() const; + public: static ResumeInst *Create(Value *Exn, Instruction *InsertBefore = nullptr) { return new(1) ResumeInst(Exn, InsertBefore); @@ -3346,6 +3569,528 @@ struct OperandTraits : DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value) +//===----------------------------------------------------------------------===// +// CleanupReturnInst Class +//===----------------------------------------------------------------------===// + +class CleanupReturnInst : public TerminatorInst { + CleanupReturnInst(const CleanupReturnInst &RI); + +private: + void init(Value *RetVal, BasicBlock *UnwindBB); + CleanupReturnInst(LLVMContext &C, Value *RetVal, BasicBlock *UnwindBB, + unsigned Values, Instruction *InsertBefore = nullptr); + CleanupReturnInst(LLVMContext &C, Value *RetVal, BasicBlock *UnwindBB, + unsigned Values, BasicBlock *InsertAtEnd); + + int getUnwindLabelOpIdx() const { + assert(hasUnwindDest()); + return 0; + } + + int getRetValOpIdx() const { + assert(hasReturnValue()); + if (hasUnwindDest()) + return 1; + return 0; + } + +protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + CleanupReturnInst *cloneImpl() const; + +public: + static CleanupReturnInst *Create(LLVMContext &C, + Value *RetVal = nullptr, + BasicBlock *UnwindBB = nullptr, + Instruction *InsertBefore = nullptr) { + unsigned Values = 0; + if (RetVal) + ++Values; + if (UnwindBB) + ++Values; + return new (Values) + CleanupReturnInst(C, RetVal, UnwindBB, Values, InsertBefore); + } + static CleanupReturnInst *Create(LLVMContext &C, Value *RetVal, + BasicBlock *UnwindBB, + BasicBlock *InsertAtEnd) { + unsigned Values = 0; + if (RetVal) + ++Values; + if (UnwindBB) + ++Values; + return new (Values) + CleanupReturnInst(C, RetVal, UnwindBB, Values, InsertAtEnd); + } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + bool hasUnwindDest() const { return getSubclassDataFromInstruction() & 1; } + bool unwindsToCaller() const { return !hasUnwindDest(); } + bool hasReturnValue() const { return getSubclassDataFromInstruction() & 2; } + + /// Convenience accessor. Returns null if there is no return value. + Value *getReturnValue() const { + if (!hasReturnValue()) + return nullptr; + return getOperand(getRetValOpIdx()); + } + void setReturnValue(Value *RetVal) { + assert(hasReturnValue()); + setOperand(getRetValOpIdx(), RetVal); + } + + unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; } + + BasicBlock *getUnwindDest() const; + void setUnwindDest(BasicBlock *NewDest); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::CleanupRet); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + +private: + BasicBlock *getSuccessorV(unsigned Idx) const override; + unsigned getNumSuccessorsV() const override; + void setSuccessorV(unsigned Idx, BasicBlock *B) override; + + // Shadow Instruction::setInstructionSubclassData with a private forwarding + // method so that subclasses cannot accidentally use it. + void setInstructionSubclassData(unsigned short D) { + Instruction::setInstructionSubclassData(D); + } +}; + +template <> +struct OperandTraits + : public VariadicOperandTraits {}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CleanupReturnInst, Value) + +//===----------------------------------------------------------------------===// +// CatchEndPadInst Class +//===----------------------------------------------------------------------===// + +class CatchEndPadInst : public TerminatorInst { + CatchEndPadInst(const CatchEndPadInst &RI); + +private: + void init(BasicBlock *UnwindBB); + CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB, unsigned Values, + Instruction *InsertBefore = nullptr); + CatchEndPadInst(LLVMContext &C, BasicBlock *UnwindBB, unsigned Values, + BasicBlock *InsertAtEnd); + +protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + CatchEndPadInst *cloneImpl() const; + +public: + static CatchEndPadInst *Create(LLVMContext &C, + BasicBlock *UnwindBB = nullptr, + Instruction *InsertBefore = nullptr) { + unsigned Values = UnwindBB ? 1 : 0; + return new (Values) CatchEndPadInst(C, UnwindBB, Values, InsertBefore); + } + static CatchEndPadInst *Create(LLVMContext &C, BasicBlock *UnwindBB, + BasicBlock *InsertAtEnd) { + unsigned Values = UnwindBB ? 1 : 0; + return new (Values) CatchEndPadInst(C, UnwindBB, Values, InsertAtEnd); + } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + bool hasUnwindDest() const { return getSubclassDataFromInstruction() & 1; } + bool unwindsToCaller() const { return !hasUnwindDest(); } + + /// Convenience accessor. Returns null if there is no return value. + unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; } + + BasicBlock *getUnwindDest() const { + return hasUnwindDest() ? cast(Op<-1>()) : nullptr; + } + void setUnwindDest(BasicBlock *NewDest) { + assert(NewDest); + Op<-1>() = NewDest; + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::CatchEndPad); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + +private: + BasicBlock *getSuccessorV(unsigned Idx) const override; + unsigned getNumSuccessorsV() const override; + void setSuccessorV(unsigned Idx, BasicBlock *B) override; + +private: + // Shadow Instruction::setInstructionSubclassData with a private forwarding + // method so that subclasses cannot accidentally use it. + void setInstructionSubclassData(unsigned short D) { + Instruction::setInstructionSubclassData(D); + } +}; + +template <> +struct OperandTraits + : public VariadicOperandTraits {}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchEndPadInst, Value) + +//===----------------------------------------------------------------------===// +// CatchPadInst Class +//===----------------------------------------------------------------------===// + +class CatchPadInst : public TerminatorInst { +private: + void init(BasicBlock *IfNormal, BasicBlock *IfException, + ArrayRef Args, const Twine &NameStr); + + CatchPadInst(const CatchPadInst &CPI); + + explicit CatchPadInst(Type *RetTy, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef Args, + unsigned Values, const Twine &NameStr, + Instruction *InsertBefore); + explicit CatchPadInst(Type *RetTy, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef Args, + unsigned Values, const Twine &NameStr, + BasicBlock *InsertAtEnd); + +protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + CatchPadInst *cloneImpl() const; + +public: + static CatchPadInst *Create(Type *RetTy, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef Args, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + unsigned Values = unsigned(Args.size()) + 2; + return new (Values) CatchPadInst(RetTy, IfNormal, IfException, Args, + Values, NameStr, InsertBefore); + } + static CatchPadInst *Create(Type *RetTy, BasicBlock *IfNormal, + BasicBlock *IfException, ArrayRef Args, + const Twine &NameStr, BasicBlock *InsertAtEnd) { + unsigned Values = unsigned(Args.size()) + 2; + return new (Values) CatchPadInst(RetTy, IfNormal, IfException, Args, + Values, NameStr, InsertAtEnd); + } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// getNumArgOperands - Return the number of catchpad arguments. + /// + unsigned getNumArgOperands() const { return getNumOperands() - 2; } + + /// getArgOperand/setArgOperand - Return/set the i-th catchpad argument. + /// + Value *getArgOperand(unsigned i) const { return getOperand(i); } + void setArgOperand(unsigned i, Value *v) { setOperand(i, v); } + + /// arg_operands - iteration adapter for range-for loops. + iterator_range arg_operands() { + return iterator_range(op_begin(), op_end() - 2); + } + + /// arg_operands - iteration adapter for range-for loops. + iterator_range arg_operands() const { + return iterator_range(op_begin(), op_end() - 2); + } + + /// \brief Wrappers for getting the \c Use of a catchpad argument. + const Use &getArgOperandUse(unsigned i) const { return getOperandUse(i); } + Use &getArgOperandUse(unsigned i) { return getOperandUse(i); } + + // get*Dest - Return the destination basic blocks... + BasicBlock *getNormalDest() const { return cast(Op<-2>()); } + BasicBlock *getUnwindDest() const { return cast(Op<-1>()); } + void setNormalDest(BasicBlock *B) { Op<-2>() = reinterpret_cast(B); } + void setUnwindDest(BasicBlock *B) { Op<-1>() = reinterpret_cast(B); } + + BasicBlock *getSuccessor(unsigned i) const { + assert(i < 2 && "Successor # out of range for catchpad!"); + return i == 0 ? getNormalDest() : getUnwindDest(); + } + + void setSuccessor(unsigned idx, BasicBlock *NewSucc) { + assert(idx < 2 && "Successor # out of range for catchpad!"); + *(&Op<-2>() + idx) = reinterpret_cast(NewSucc); + } + + unsigned getNumSuccessors() const { return 2; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::CatchPad; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + +private: + BasicBlock *getSuccessorV(unsigned idx) const override; + unsigned getNumSuccessorsV() const override; + void setSuccessorV(unsigned idx, BasicBlock *B) override; +}; + +template <> +struct OperandTraits + : public VariadicOperandTraits {}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchPadInst, Value) + +//===----------------------------------------------------------------------===// +// TerminatePadInst Class +//===----------------------------------------------------------------------===// + +class TerminatePadInst : public TerminatorInst { +private: + void init(BasicBlock *BB, ArrayRef Args, const Twine &NameStr); + + TerminatePadInst(const TerminatePadInst &TPI); + + explicit TerminatePadInst(LLVMContext &C, BasicBlock *BB, + ArrayRef Args, unsigned Values, + const Twine &NameStr, Instruction *InsertBefore); + explicit TerminatePadInst(LLVMContext &C, BasicBlock *BB, + ArrayRef Args, unsigned Values, + const Twine &NameStr, BasicBlock *InsertAtEnd); + +protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + TerminatePadInst *cloneImpl() const; + +public: + static TerminatePadInst *Create(LLVMContext &C, BasicBlock *BB = nullptr, + ArrayRef Args = None, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + unsigned Values = unsigned(Args.size()); + if (BB) + ++Values; + return new (Values) + TerminatePadInst(C, BB, Args, Values, NameStr, InsertBefore); + } + static TerminatePadInst *Create(LLVMContext &C, BasicBlock *BB, + ArrayRef Args, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + unsigned Values = unsigned(Args.size()); + if (BB) + ++Values; + return new (Values) + TerminatePadInst(C, BB, Args, Values, NameStr, InsertAtEnd); + } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + bool hasUnwindDest() const { return getSubclassDataFromInstruction() & 1; } + bool unwindsToCaller() const { return !hasUnwindDest(); } + + /// getNumArgOperands - Return the number of terminatepad arguments. + /// + unsigned getNumArgOperands() const { + unsigned NumOperands = getNumOperands(); + if (hasUnwindDest()) + return NumOperands - 1; + return NumOperands; + } + + /// getArgOperand/setArgOperand - Return/set the i-th terminatepad argument. + /// + Value *getArgOperand(unsigned i) const { return getOperand(i); } + void setArgOperand(unsigned i, Value *v) { setOperand(i, v); } + + const_op_iterator arg_end() const { + if (hasUnwindDest()) + return op_end() - 1; + return op_end(); + } + + op_iterator arg_end() { + if (hasUnwindDest()) + return op_end() - 1; + return op_end(); + } + + /// arg_operands - iteration adapter for range-for loops. + iterator_range arg_operands() { + return iterator_range(op_begin(), arg_end()); + } + + /// arg_operands - iteration adapter for range-for loops. + iterator_range arg_operands() const { + return iterator_range(op_begin(), arg_end()); + } + + /// \brief Wrappers for getting the \c Use of a terminatepad argument. + const Use &getArgOperandUse(unsigned i) const { return getOperandUse(i); } + Use &getArgOperandUse(unsigned i) { return getOperandUse(i); } + + // get*Dest - Return the destination basic blocks... + BasicBlock *getUnwindDest() const { + if (!hasUnwindDest()) + return nullptr; + return cast(Op<-1>()); + } + void setUnwindDest(BasicBlock *B) { + assert(B && hasUnwindDest()); + Op<-1>() = reinterpret_cast(B); + } + + unsigned getNumSuccessors() const { return hasUnwindDest() ? 1 : 0; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::TerminatePad; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + +private: + BasicBlock *getSuccessorV(unsigned idx) const override; + unsigned getNumSuccessorsV() const override; + void setSuccessorV(unsigned idx, BasicBlock *B) override; + + // Shadow Instruction::setInstructionSubclassData with a private forwarding + // method so that subclasses cannot accidentally use it. + void setInstructionSubclassData(unsigned short D) { + Instruction::setInstructionSubclassData(D); + } +}; + +template <> +struct OperandTraits + : public VariadicOperandTraits {}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(TerminatePadInst, Value) + +//===----------------------------------------------------------------------===// +// CleanupPadInst Class +//===----------------------------------------------------------------------===// + +class CleanupPadInst : public Instruction { +private: + void init(ArrayRef Args, const Twine &NameStr); + + CleanupPadInst(const CleanupPadInst &CPI); + + explicit CleanupPadInst(Type *RetTy, ArrayRef Args, + const Twine &NameStr, Instruction *InsertBefore); + explicit CleanupPadInst(Type *RetTy, ArrayRef Args, + const Twine &NameStr, BasicBlock *InsertAtEnd); + +protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + CleanupPadInst *cloneImpl() const; + +public: + static CleanupPadInst *Create(Type *RetTy, ArrayRef Args, + const Twine &NameStr = "", + Instruction *InsertBefore = nullptr) { + return new (Args.size()) + CleanupPadInst(RetTy, Args, NameStr, InsertBefore); + } + static CleanupPadInst *Create(Type *RetTy, ArrayRef Args, + const Twine &NameStr, + BasicBlock *InsertAtEnd) { + return new (Args.size()) + CleanupPadInst(RetTy, Args, NameStr, InsertAtEnd); + } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::CleanupPad; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +template <> +struct OperandTraits + : public VariadicOperandTraits {}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CleanupPadInst, Value) + +//===----------------------------------------------------------------------===// +// CatchReturnInst Class +//===----------------------------------------------------------------------===// + +class CatchReturnInst : public TerminatorInst { + CatchReturnInst(const CatchReturnInst &RI); + +private: + void init(Value *RetVal, BasicBlock *UnwindBB); + CatchReturnInst(BasicBlock *BB, Instruction *InsertBefore = nullptr); + CatchReturnInst(BasicBlock *BB, BasicBlock *InsertAtEnd); + +protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + CatchReturnInst *cloneImpl() const; + +public: + static CatchReturnInst *Create(BasicBlock *BB, + Instruction *InsertBefore = nullptr) { + return new (1) CatchReturnInst(BB, InsertBefore); + } + static CatchReturnInst *Create(BasicBlock *BB, BasicBlock *InsertAtEnd) { + return new (1) CatchReturnInst(BB, InsertAtEnd); + } + + /// Provide fast operand accessors + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + /// Convenience accessors. + BasicBlock *getSuccessor() const { return cast(Op<0>()); } + void setSuccessor(BasicBlock *NewSucc) { Op<0>() = (Value *)NewSucc; } + unsigned getNumSuccessors() const { return 1; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::CatchRet); + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + +private: + BasicBlock *getSuccessorV(unsigned Idx) const override; + unsigned getNumSuccessorsV() const override; + void setSuccessorV(unsigned Idx, BasicBlock *B) override; +}; + +template <> +struct OperandTraits + : public FixedNumOperandTraits {}; + +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CatchReturnInst, Value) + //===----------------------------------------------------------------------===// // UnreachableInst Class //===----------------------------------------------------------------------===// @@ -3358,7 +4103,9 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ResumeInst, Value) class UnreachableInst : public TerminatorInst { void *operator new(size_t, unsigned) = delete; protected: - UnreachableInst *clone_impl() const override; + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; + UnreachableInst *cloneImpl() const; public: // allocate space for exactly zero operands @@ -3390,8 +4137,10 @@ class UnreachableInst : public TerminatorInst { /// \brief This class represents a truncation of integer types. class TruncInst : public CastInst { protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; /// \brief Clone an identical TruncInst - TruncInst *clone_impl() const override; + TruncInst *cloneImpl() const; public: /// \brief Constructor with insert-before-instruction semantics @@ -3426,8 +4175,10 @@ class TruncInst : public CastInst { /// \brief This class represents zero extension of integer types. class ZExtInst : public CastInst { protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; /// \brief Clone an identical ZExtInst - ZExtInst *clone_impl() const override; + ZExtInst *cloneImpl() const; public: /// \brief Constructor with insert-before-instruction semantics @@ -3462,8 +4213,10 @@ class ZExtInst : public CastInst { /// \brief This class represents a sign extension of integer types. class SExtInst : public CastInst { protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; /// \brief Clone an identical SExtInst - SExtInst *clone_impl() const override; + SExtInst *cloneImpl() const; public: /// \brief Constructor with insert-before-instruction semantics @@ -3498,8 +4251,10 @@ class SExtInst : public CastInst { /// \brief This class represents a truncation of floating point types. class FPTruncInst : public CastInst { protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; /// \brief Clone an identical FPTruncInst - FPTruncInst *clone_impl() const override; + FPTruncInst *cloneImpl() const; public: /// \brief Constructor with insert-before-instruction semantics @@ -3534,8 +4289,10 @@ class FPTruncInst : public CastInst { /// \brief This class represents an extension of floating point types. class FPExtInst : public CastInst { protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; /// \brief Clone an identical FPExtInst - FPExtInst *clone_impl() const override; + FPExtInst *cloneImpl() const; public: /// \brief Constructor with insert-before-instruction semantics @@ -3570,8 +4327,10 @@ class FPExtInst : public CastInst { /// \brief This class represents a cast unsigned integer to floating point. class UIToFPInst : public CastInst { protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; /// \brief Clone an identical UIToFPInst - UIToFPInst *clone_impl() const override; + UIToFPInst *cloneImpl() const; public: /// \brief Constructor with insert-before-instruction semantics @@ -3606,8 +4365,10 @@ class UIToFPInst : public CastInst { /// \brief This class represents a cast from signed integer to floating point. class SIToFPInst : public CastInst { protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; /// \brief Clone an identical SIToFPInst - SIToFPInst *clone_impl() const override; + SIToFPInst *cloneImpl() const; public: /// \brief Constructor with insert-before-instruction semantics @@ -3642,8 +4403,10 @@ class SIToFPInst : public CastInst { /// \brief This class represents a cast from floating point to unsigned integer class FPToUIInst : public CastInst { protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; /// \brief Clone an identical FPToUIInst - FPToUIInst *clone_impl() const override; + FPToUIInst *cloneImpl() const; public: /// \brief Constructor with insert-before-instruction semantics @@ -3678,8 +4441,10 @@ class FPToUIInst : public CastInst { /// \brief This class represents a cast from floating point to signed integer. class FPToSIInst : public CastInst { protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; /// \brief Clone an identical FPToSIInst - FPToSIInst *clone_impl() const override; + FPToSIInst *cloneImpl() const; public: /// \brief Constructor with insert-before-instruction semantics @@ -3730,8 +4495,10 @@ class IntToPtrInst : public CastInst { BasicBlock *InsertAtEnd ///< The block to insert the instruction into ); + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; /// \brief Clone an identical IntToPtrInst - IntToPtrInst *clone_impl() const override; + IntToPtrInst *cloneImpl() const; /// \brief Returns the address space of this instruction's pointer type. unsigned getAddressSpace() const { @@ -3754,8 +4521,10 @@ class IntToPtrInst : public CastInst { /// \brief This class represents a cast from a pointer to an integer class PtrToIntInst : public CastInst { protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; /// \brief Clone an identical PtrToIntInst - PtrToIntInst *clone_impl() const override; + PtrToIntInst *cloneImpl() const; public: /// \brief Constructor with insert-before-instruction semantics @@ -3802,8 +4571,10 @@ class PtrToIntInst : public CastInst { /// \brief This class represents a no-op cast from one type to another. class BitCastInst : public CastInst { protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; /// \brief Clone an identical BitCastInst - BitCastInst *clone_impl() const override; + BitCastInst *cloneImpl() const; public: /// \brief Constructor with insert-before-instruction semantics @@ -3839,8 +4610,10 @@ class BitCastInst : public CastInst { /// one address space to another. class AddrSpaceCastInst : public CastInst { protected: + // Note: Instruction needs to be a friend here to call cloneImpl. + friend class Instruction; /// \brief Clone an identical AddrSpaceCastInst - AddrSpaceCastInst *clone_impl() const override; + AddrSpaceCastInst *cloneImpl() const; public: /// \brief Constructor with insert-before-instruction semantics diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h index bf0adc39347..2c8b6eb6f39 100644 --- a/include/llvm/IR/IntrinsicInst.h +++ b/include/llvm/IR/IntrinsicInst.h @@ -42,7 +42,7 @@ namespace llvm { /// getIntrinsicID - Return the intrinsic ID of this intrinsic. /// Intrinsic::ID getIntrinsicID() const { - return (Intrinsic::ID)getCalledFunction()->getIntrinsicID(); + return getCalledFunction()->getIntrinsicID(); } // Methods for support type inquiry through isa, cast, and dyn_cast: @@ -82,11 +82,11 @@ namespace llvm { class DbgDeclareInst : public DbgInfoIntrinsic { public: Value *getAddress() const; - MDLocalVariable *getVariable() const { - return cast(getRawVariable()); + DILocalVariable *getVariable() const { + return cast(getRawVariable()); } - MDExpression *getExpression() const { - return cast(getRawExpression()); + DIExpression *getExpression() const { + return cast(getRawExpression()); } Metadata *getRawVariable() const { @@ -115,11 +115,11 @@ namespace llvm { return cast( const_cast(getArgOperand(1)))->getZExtValue(); } - MDLocalVariable *getVariable() const { - return cast(getRawVariable()); + DILocalVariable *getVariable() const { + return cast(getRawVariable()); } - MDExpression *getExpression() const { - return cast(getRawExpression()); + DIExpression *getExpression() const { + return cast(getRawExpression()); } Metadata *getRawVariable() const { diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h index a66bd2cd7d9..43b8325107f 100644 --- a/include/llvm/IR/Intrinsics.h +++ b/include/llvm/IR/Intrinsics.h @@ -32,7 +32,7 @@ class AttributeSet; /// function known by LLVM. The enum values are returned by /// Function::getIntrinsicID(). namespace Intrinsic { - enum ID { + enum ID : unsigned { not_intrinsic = 0, // Must be zero // Get the intrinsic enums generated from Intrinsics.td @@ -52,6 +52,11 @@ namespace Intrinsic { /// Returns true if the intrinsic can be overloaded. bool isOverloaded(ID id); + /// Returns true if the intrinsic is a leaf, i.e. it does not make any calls + /// itself. Most intrinsics are leafs, the exceptions being the patchpoint + /// and statepoint intrinsics. These call (or invoke) their "target" argument. + bool isLeaf(ID id); + /// Return the attributes for an intrinsic. AttributeSet getAttributes(LLVMContext &C, ID id); diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index 9ff923da3dc..34774ccdbe4 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -73,6 +73,11 @@ def IntrNoReturn : IntrinsicProperty; // Parallels the noduplicate attribute on LLVM IR functions. def IntrNoDuplicate : IntrinsicProperty; +// IntrConvergent - Calls to this intrinsic are convergent and may only be +// moved to control equivalent blocks. +// Parallels the convergent attribute on LLVM IR functions. +def IntrConvergent : IntrinsicProperty; + //===----------------------------------------------------------------------===// // Types used by intrinsics. //===----------------------------------------------------------------------===// @@ -181,6 +186,8 @@ def llvm_v4i64_ty : LLVMType; // 4 x i64 def llvm_v8i64_ty : LLVMType; // 8 x i64 def llvm_v16i64_ty : LLVMType; // 16 x i64 +def llvm_v1i128_ty : LLVMType; // 1 x i128 + def llvm_v2f16_ty : LLVMType; // 2 x half (__fp16) def llvm_v4f16_ty : LLVMType; // 4 x half (__fp16) def llvm_v8f16_ty : LLVMType; // 8 x half (__fp16) @@ -261,15 +268,23 @@ def int_gcwrite : Intrinsic<[], // def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; -def int_frameescape : Intrinsic<[], [llvm_vararg_ty]>; -def int_framerecover : Intrinsic<[llvm_ptr_ty], - [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], - [IntrNoMem]>; def int_read_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty], - [IntrNoMem], "llvm.read_register">; + [IntrReadMem], "llvm.read_register">; def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty], [], "llvm.write_register">; +// Gets the address of the local variable area. This is typically a copy of the +// stack, frame, or base pointer depending on the type of prologue. +def int_localaddress : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; + +// Escapes local variables to allow access from other functions. +def int_localescape : Intrinsic<[], [llvm_vararg_ty]>; + +// Given a function and the localaddress of a parent frame, returns a pointer +// to an escaped allocation indicated by the index. +def int_localrecover : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty, llvm_ptr_ty, llvm_i32_ty], + [IntrNoMem]>; // Note: we treat stacksave/stackrestore as writemem because we don't otherwise // model their dependencies on allocas. def int_stacksave : Intrinsic<[llvm_ptr_ty]>, @@ -355,6 +370,8 @@ let Properties = [IntrNoMem] in { def int_rint : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_nearbyint : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_round : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_canonicalize : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], + [IntrNoMem]>; } // NOTE: these are internal interfaces. @@ -421,6 +438,8 @@ 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], [], [IntrReadMem]>; + // __builtin_unwind_init is an undocumented GCC intrinsic that causes all // callee-saved registers to be saved and restored (regardless of whether they // are used) in the calling function. It is used by libgcc_eh. @@ -436,6 +455,7 @@ let Properties = [IntrNoMem] in { def int_eh_sjlj_functioncontext : Intrinsic<[], [llvm_ptr_ty]>; def int_eh_sjlj_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; def int_eh_sjlj_longjmp : Intrinsic<[], [llvm_ptr_ty], [IntrNoReturn]>; +def int_eh_sjlj_setup_dispatch : Intrinsic<[], []>; //===---------------- Generic Variable Attribute Intrinsics----------------===// // @@ -525,8 +545,10 @@ def int_experimental_patchpoint_i64 : Intrinsic<[llvm_i64_ty], // These are documented in docs/Statepoint.rst def int_experimental_gc_statepoint : Intrinsic<[llvm_i32_ty], - [llvm_anyptr_ty, llvm_i32_ty, - llvm_i32_ty, llvm_vararg_ty]>; + [llvm_i64_ty, llvm_i32_ty, + llvm_anyptr_ty, llvm_i32_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], @@ -578,6 +600,7 @@ def int_convertus : Intrinsic<[llvm_anyint_ty], [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; def int_convertuu : Intrinsic<[llvm_anyint_ty], [llvm_anyint_ty, llvm_i32_ty, llvm_i32_ty]>; + // Clear cache intrinsic, default to ignore (ie. emit nothing) // maps to void __clear_cache() on supporting platforms def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], @@ -627,6 +650,11 @@ def int_nacl_atomic_is_lock_free : Intrinsic<[llvm_i1_ty], [llvm_i32_ty, llvm_ptr_ty], [IntrNoMem]>, GCCBuiltin<"__nacl_atomic_is_lock_free">; // @LOCALMOD-END +// Calculate the Absolute Differences of the two input vectors. +def int_sabsdiff : Intrinsic<[llvm_anyvector_ty], + [ LLVMMatchType<0>, LLVMMatchType<0> ], [IntrNoMem]>; +def int_uabsdiff : Intrinsic<[llvm_anyvector_ty], + [ LLVMMatchType<0>, LLVMMatchType<0> ], [IntrNoMem]>; //===-------------------------- Masked Intrinsics -------------------------===// // @@ -668,6 +696,7 @@ include "llvm/IR/IntrinsicsXCore.td" include "llvm/IR/IntrinsicsHexagon.td" include "llvm/IR/IntrinsicsNVVM.td" include "llvm/IR/IntrinsicsMips.td" -include "llvm/IR/IntrinsicsR600.td" +include "llvm/IR/IntrinsicsAMDGPU.td" include "llvm/IR/IntrinsicsBPF.td" include "llvm/IR/IntrinsicsSystemZ.td" +include "llvm/IR/IntrinsicsWebAssembly.td" diff --git a/include/llvm/IR/IntrinsicsAArch64.td b/include/llvm/IR/IntrinsicsAArch64.td index 7d69ed52171..578f259aae1 100644 --- a/include/llvm/IR/IntrinsicsAArch64.td +++ b/include/llvm/IR/IntrinsicsAArch64.td @@ -13,6 +13,9 @@ let TargetPrefix = "aarch64" in { +def int_aarch64_thread_pointer : GCCBuiltin<"__builtin_thread_pointer">, + Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; + def int_aarch64_ldxr : Intrinsic<[llvm_i64_ty], [llvm_anyptr_ty]>; def int_aarch64_ldaxr : Intrinsic<[llvm_i64_ty], [llvm_anyptr_ty]>; def int_aarch64_stxr : Intrinsic<[llvm_i32_ty], [llvm_i64_ty, llvm_anyptr_ty]>; diff --git a/include/llvm/IR/IntrinsicsAMDGPU.td b/include/llvm/IR/IntrinsicsAMDGPU.td new file mode 100644 index 00000000000..510e5ad2d9b --- /dev/null +++ b/include/llvm/IR/IntrinsicsAMDGPU.td @@ -0,0 +1,85 @@ +//===- IntrinsicsAMDGPU.td - Defines AMDGPU intrinsics -----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the R600-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "r600" in { + +class R600ReadPreloadRegisterIntrinsic + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin; + +multiclass R600ReadPreloadRegisterIntrinsic_xyz { + def _x : R600ReadPreloadRegisterIntrinsic; + def _y : R600ReadPreloadRegisterIntrinsic; + def _z : R600ReadPreloadRegisterIntrinsic; +} + +defm int_r600_read_global_size : R600ReadPreloadRegisterIntrinsic_xyz < + "__builtin_r600_read_global_size">; +defm int_r600_read_local_size : R600ReadPreloadRegisterIntrinsic_xyz < + "__builtin_r600_read_local_size">; +defm int_r600_read_ngroups : R600ReadPreloadRegisterIntrinsic_xyz < + "__builtin_r600_read_ngroups">; +defm int_r600_read_tgid : R600ReadPreloadRegisterIntrinsic_xyz < + "__builtin_r600_read_tgid">; +defm int_r600_read_tidig : R600ReadPreloadRegisterIntrinsic_xyz < + "__builtin_r600_read_tidig">; +} // End TargetPrefix = "r600" + +let TargetPrefix = "AMDGPU" in { + +class AMDGPUReadPreloadRegisterIntrinsic + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin; + +def int_AMDGPU_div_scale : GCCBuiltin<"__builtin_amdgpu_div_scale">, + // 1st parameter: Numerator + // 2nd parameter: Denominator + // 3rd parameter: Constant to select select between first and + // second. (0 = first, 1 = second). + Intrinsic<[llvm_anyfloat_ty, llvm_i1_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i1_ty], + [IntrNoMem]>; + +def int_AMDGPU_div_fmas : GCCBuiltin<"__builtin_amdgpu_div_fmas">, + Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, llvm_i1_ty], + [IntrNoMem]>; + +def int_AMDGPU_div_fixup : GCCBuiltin<"__builtin_amdgpu_div_fixup">, + Intrinsic<[llvm_anyfloat_ty], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem]>; + +def int_AMDGPU_trig_preop : GCCBuiltin<"__builtin_amdgpu_trig_preop">, + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty], + [IntrNoMem]>; + +def int_AMDGPU_rcp : GCCBuiltin<"__builtin_amdgpu_rcp">, + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; + +def int_AMDGPU_rsq : GCCBuiltin<"__builtin_amdgpu_rsq">, + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; + +def int_AMDGPU_rsq_clamped : GCCBuiltin<"__builtin_amdgpu_rsq_clamped">, + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; + +def int_AMDGPU_ldexp : GCCBuiltin<"__builtin_amdgpu_ldexp">, + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem]>; + +def int_AMDGPU_class : GCCBuiltin<"__builtin_amdgpu_class">, + Intrinsic<[llvm_i1_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_AMDGPU_read_workdim : AMDGPUReadPreloadRegisterIntrinsic < + "__builtin_amdgpu_read_workdim">; + +} // End TargetPrefix = "AMDGPU" diff --git a/include/llvm/IR/IntrinsicsARM.td b/include/llvm/IR/IntrinsicsARM.td index ce758e25731..1dff8087859 100644 --- a/include/llvm/IR/IntrinsicsARM.td +++ b/include/llvm/IR/IntrinsicsARM.td @@ -83,11 +83,9 @@ def int_arm_vcvtru : Intrinsic<[llvm_float_ty], [llvm_anyfloat_ty], // Move to coprocessor def int_arm_mcr : GCCBuiltin<"__builtin_arm_mcr">, - MSBuiltin<"_MoveToCoprocessor">, Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; def int_arm_mcr2 : GCCBuiltin<"__builtin_arm_mcr2">, - MSBuiltin<"_MoveToCoprocessor2">, Intrinsic<[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td index 74c017234f5..eb8f1e6cd07 100644 --- a/include/llvm/IR/IntrinsicsPowerPC.td +++ b/include/llvm/IR/IntrinsicsPowerPC.td @@ -24,7 +24,8 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". def int_ppc_dcbst : Intrinsic<[], [llvm_ptr_ty], []>; def int_ppc_dcbt : Intrinsic<[], [llvm_ptr_ty], [IntrReadWriteArgMem, NoCapture<0>]>; - def int_ppc_dcbtst: Intrinsic<[], [llvm_ptr_ty], []>; + def int_ppc_dcbtst: Intrinsic<[], [llvm_ptr_ty], + [IntrReadWriteArgMem, NoCapture<0>]>; def int_ppc_dcbz : Intrinsic<[], [llvm_ptr_ty], []>; def int_ppc_dcbzl : Intrinsic<[], [llvm_ptr_ty], []>; @@ -120,6 +121,13 @@ class PowerPC_Vec_DDD_Intrinsic [llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; +/// PowerPC_Vec_QQQ_Intrinsic - A PowerPC intrinsic that takes two v1i128 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_QQQ_Intrinsic + : PowerPC_Vec_Intrinsic; + //===----------------------------------------------------------------------===// // PowerPC VSX Intrinsic Class Definitions. // @@ -356,6 +364,7 @@ def int_ppc_altivec_vaddshs : PowerPC_Vec_HHH_Intrinsic<"vaddshs">; def int_ppc_altivec_vadduws : PowerPC_Vec_WWW_Intrinsic<"vadduws">; def int_ppc_altivec_vaddsws : PowerPC_Vec_WWW_Intrinsic<"vaddsws">; def int_ppc_altivec_vaddcuw : PowerPC_Vec_WWW_Intrinsic<"vaddcuw">; +def int_ppc_altivec_vaddcuq : PowerPC_Vec_QQQ_Intrinsic<"vaddcuq">; // Saturating subs. def int_ppc_altivec_vsububs : PowerPC_Vec_BBB_Intrinsic<"vsububs">; @@ -365,6 +374,7 @@ def int_ppc_altivec_vsubshs : PowerPC_Vec_HHH_Intrinsic<"vsubshs">; def int_ppc_altivec_vsubuws : PowerPC_Vec_WWW_Intrinsic<"vsubuws">; def int_ppc_altivec_vsubsws : PowerPC_Vec_WWW_Intrinsic<"vsubsws">; def int_ppc_altivec_vsubcuw : PowerPC_Vec_WWW_Intrinsic<"vsubcuw">; +def int_ppc_altivec_vsubcuq : PowerPC_Vec_QQQ_Intrinsic<"vsubcuq">; let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". // Saturating multiply-adds. @@ -479,6 +489,12 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". def int_ppc_altivec_vpkswus : GCCBuiltin<"__builtin_altivec_vpkswus">, Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vpksdss : GCCBuiltin<"__builtin_altivec_vpksdss">, + Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; + def int_ppc_altivec_vpksdus : GCCBuiltin<"__builtin_altivec_vpksdus">, + Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; // vpkuhum is lowered to a shuffle. def int_ppc_altivec_vpkuhus : GCCBuiltin<"__builtin_altivec_vpkuhus">, Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty], @@ -487,6 +503,10 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". def int_ppc_altivec_vpkuwus : GCCBuiltin<"__builtin_altivec_vpkuwus">, Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + // vpkudum is lowered to a shuffle. + def int_ppc_altivec_vpkudus : GCCBuiltin<"__builtin_altivec_vpkudus">, + Intrinsic<[llvm_v4i32_ty], [llvm_v2i64_ty, llvm_v2i64_ty], + [IntrNoMem]>; // Unpacks. def int_ppc_altivec_vupkhpx : GCCBuiltin<"__builtin_altivec_vupkhpx">, @@ -495,12 +515,16 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; def int_ppc_altivec_vupkhsh : GCCBuiltin<"__builtin_altivec_vupkhsh">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vupkhsw : GCCBuiltin<"__builtin_altivec_vupkhsw">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>; def int_ppc_altivec_vupklpx : GCCBuiltin<"__builtin_altivec_vupklpx">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; def int_ppc_altivec_vupklsb : GCCBuiltin<"__builtin_altivec_vupklsb">, Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty], [IntrNoMem]>; def int_ppc_altivec_vupklsh : GCCBuiltin<"__builtin_altivec_vupklsh">, Intrinsic<[llvm_v4i32_ty], [llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vupklsw : GCCBuiltin<"__builtin_altivec_vupklsw">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty], [IntrNoMem]>; // FP <-> integer conversion. @@ -525,6 +549,26 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; def int_ppc_altivec_vrfiz : GCCBuiltin<"__builtin_altivec_vrfiz">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; + + // Add Extended Quadword + def int_ppc_altivec_vaddeuqm : GCCBuiltin<"__builtin_altivec_vaddeuqm">, + Intrinsic<[llvm_v1i128_ty], + [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty], + [IntrNoMem]>; + def int_ppc_altivec_vaddecuq : GCCBuiltin<"__builtin_altivec_vaddecuq">, + Intrinsic<[llvm_v1i128_ty], + [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty], + [IntrNoMem]>; + + // Sub Extended Quadword + def int_ppc_altivec_vsubeuqm : GCCBuiltin<"__builtin_altivec_vsubeuqm">, + Intrinsic<[llvm_v1i128_ty], + [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty], + [IntrNoMem]>; + def int_ppc_altivec_vsubecuq : GCCBuiltin<"__builtin_altivec_vsubecuq">, + Intrinsic<[llvm_v1i128_ty], + [llvm_v1i128_ty, llvm_v1i128_ty, llvm_v1i128_ty], + [IntrNoMem]>; } def int_ppc_altivec_vsl : PowerPC_Vec_WWW_Intrinsic<"vsl">; @@ -564,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">; @@ -638,6 +687,47 @@ def int_ppc_vsx_xsmindp : PowerPC_VSX_Sca_DDD_Intrinsic<"xsmindp">; // Vector divide. def int_ppc_vsx_xvdivdp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvdivdp">; def int_ppc_vsx_xvdivsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvdivsp">; + +// Vector round-to-infinity (ceil) +def int_ppc_vsx_xvrspip : + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_ppc_vsx_xvrdpip : + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +// Vector reciprocal estimate +def int_ppc_vsx_xvresp : GCCBuiltin<"__builtin_vsx_xvresp">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_ppc_vsx_xvredp : GCCBuiltin<"__builtin_vsx_xvredp">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +// Vector rsqrte +def int_ppc_vsx_xvrsqrtesp : GCCBuiltin<"__builtin_vsx_xvrsqrtesp">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty], [IntrNoMem]>; +def int_ppc_vsx_xvrsqrtedp : GCCBuiltin<"__builtin_vsx_xvrsqrtedp">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty], [IntrNoMem]>; + +// Vector compare +def int_ppc_vsx_xvcmpeqdp : + PowerPC_VSX_Intrinsic<"xvcmpeqdp", [llvm_v2i64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; +def int_ppc_vsx_xvcmpeqsp : + PowerPC_VSX_Intrinsic<"xvcmpeqsp", [llvm_v4i32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_ppc_vsx_xvcmpgedp : + PowerPC_VSX_Intrinsic<"xvcmpgedp", [llvm_v2i64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; +def int_ppc_vsx_xvcmpgesp : + PowerPC_VSX_Intrinsic<"xvcmpgesp", [llvm_v4i32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_ppc_vsx_xvcmpgtdp : + PowerPC_VSX_Intrinsic<"xvcmpgtdp", [llvm_v2i64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; +def int_ppc_vsx_xvcmpgtsp : + PowerPC_VSX_Intrinsic<"xvcmpgtsp", [llvm_v4i32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +def int_ppc_vsx_xxleqv : + PowerPC_VSX_Intrinsic<"xxleqv", [llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; } //===----------------------------------------------------------------------===// diff --git a/include/llvm/IR/IntrinsicsR600.td b/include/llvm/IR/IntrinsicsR600.td deleted file mode 100644 index 50556673822..00000000000 --- a/include/llvm/IR/IntrinsicsR600.td +++ /dev/null @@ -1,85 +0,0 @@ -//===- IntrinsicsR600.td - Defines R600 intrinsics ---------*- tablegen -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines all of the R600-specific intrinsics. -// -//===----------------------------------------------------------------------===// - -let TargetPrefix = "r600" in { - -class R600ReadPreloadRegisterIntrinsic - : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, - GCCBuiltin; - -multiclass R600ReadPreloadRegisterIntrinsic_xyz { - def _x : R600ReadPreloadRegisterIntrinsic; - def _y : R600ReadPreloadRegisterIntrinsic; - def _z : R600ReadPreloadRegisterIntrinsic; -} - -defm int_r600_read_global_size : R600ReadPreloadRegisterIntrinsic_xyz < - "__builtin_r600_read_global_size">; -defm int_r600_read_local_size : R600ReadPreloadRegisterIntrinsic_xyz < - "__builtin_r600_read_local_size">; -defm int_r600_read_ngroups : R600ReadPreloadRegisterIntrinsic_xyz < - "__builtin_r600_read_ngroups">; -defm int_r600_read_tgid : R600ReadPreloadRegisterIntrinsic_xyz < - "__builtin_r600_read_tgid">; -defm int_r600_read_tidig : R600ReadPreloadRegisterIntrinsic_xyz < - "__builtin_r600_read_tidig">; -} // End TargetPrefix = "r600" - -let TargetPrefix = "AMDGPU" in { - -class AMDGPUReadPreloadRegisterIntrinsic - : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, - GCCBuiltin; - -def int_AMDGPU_div_scale : GCCBuiltin<"__builtin_amdgpu_div_scale">, - // 1st parameter: Numerator - // 2nd parameter: Denominator - // 3rd parameter: Constant to select select between first and - // second. (0 = first, 1 = second). - Intrinsic<[llvm_anyfloat_ty, llvm_i1_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i1_ty], - [IntrNoMem]>; - -def int_AMDGPU_div_fmas : GCCBuiltin<"__builtin_amdgpu_div_fmas">, - Intrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, llvm_i1_ty], - [IntrNoMem]>; - -def int_AMDGPU_div_fixup : GCCBuiltin<"__builtin_amdgpu_div_fixup">, - Intrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], - [IntrNoMem]>; - -def int_AMDGPU_trig_preop : GCCBuiltin<"__builtin_amdgpu_trig_preop">, - Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty], - [IntrNoMem]>; - -def int_AMDGPU_rcp : GCCBuiltin<"__builtin_amdgpu_rcp">, - Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; - -def int_AMDGPU_rsq : GCCBuiltin<"__builtin_amdgpu_rsq">, - Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; - -def int_AMDGPU_rsq_clamped : GCCBuiltin<"__builtin_amdgpu_rsq_clamped">, - Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; - -def int_AMDGPU_ldexp : GCCBuiltin<"__builtin_amdgpu_ldexp">, - Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem]>; - -def int_AMDGPU_class : GCCBuiltin<"__builtin_amdgpu_class">, - Intrinsic<[llvm_i1_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>; - -def int_AMDGPU_read_workdim : AMDGPUReadPreloadRegisterIntrinsic < - "__builtin_amdgpu_read_workdim">; - -} // End TargetPrefix = "AMDGPU" diff --git a/include/llvm/IR/IntrinsicsSystemZ.td b/include/llvm/IR/IntrinsicsSystemZ.td index 6883db3bf07..96e7ca52569 100644 --- a/include/llvm/IR/IntrinsicsSystemZ.td +++ b/include/llvm/IR/IntrinsicsSystemZ.td @@ -11,6 +11,185 @@ // //===----------------------------------------------------------------------===// +class SystemZUnaryConv + : GCCBuiltin<"__builtin_s390_" ## name>, + Intrinsic<[result], [arg], [IntrNoMem]>; + +class SystemZUnary + : SystemZUnaryConv; + +class SystemZUnaryConvCC + : Intrinsic<[result, llvm_i32_ty], [arg], [IntrNoMem]>; + +class SystemZUnaryCC + : SystemZUnaryConvCC; + +class SystemZBinaryConv + : GCCBuiltin<"__builtin_s390_" ## name>, + Intrinsic<[result], [arg, arg], [IntrNoMem]>; + +class SystemZBinary + : SystemZBinaryConv; + +class SystemZBinaryInt + : GCCBuiltin<"__builtin_s390_" ## name>, + Intrinsic<[type], [type, llvm_i32_ty], [IntrNoMem]>; + +class SystemZBinaryConvCC + : Intrinsic<[result, llvm_i32_ty], [arg, arg], [IntrNoMem]>; + +class SystemZBinaryConvIntCC + : Intrinsic<[result, llvm_i32_ty], [arg, llvm_i32_ty], [IntrNoMem]>; + +class SystemZBinaryCC + : SystemZBinaryConvCC; + +class SystemZTernaryConv + : GCCBuiltin<"__builtin_s390_" ## name>, + Intrinsic<[result], [arg, arg, result], [IntrNoMem]>; + +class SystemZTernary + : SystemZTernaryConv; + +class SystemZTernaryInt + : GCCBuiltin<"__builtin_s390_" ## name>, + Intrinsic<[type], [type, type, llvm_i32_ty], [IntrNoMem]>; + +class SystemZTernaryIntCC + : Intrinsic<[type, llvm_i32_ty], [type, type, llvm_i32_ty], [IntrNoMem]>; + +class SystemZQuaternaryInt + : GCCBuiltin<"__builtin_s390_" ## name>, + Intrinsic<[type], [type, type, type, llvm_i32_ty], [IntrNoMem]>; + +class SystemZQuaternaryIntCC + : Intrinsic<[type, llvm_i32_ty], [type, type, type, llvm_i32_ty], + [IntrNoMem]>; + +multiclass SystemZUnaryExtBHF { + def b : SystemZUnaryConv; + def h : SystemZUnaryConv; + def f : SystemZUnaryConv; +} + +multiclass SystemZUnaryExtBHWF { + def b : SystemZUnaryConv; + def hw : SystemZUnaryConv; + def f : SystemZUnaryConv; +} + +multiclass SystemZUnaryBHF { + def b : SystemZUnary; + def h : SystemZUnary; + def f : SystemZUnary; +} + +multiclass SystemZUnaryBHFG : SystemZUnaryBHF { + def g : SystemZUnary; +} + +multiclass SystemZUnaryCCBHF { + def bs : SystemZUnaryCC; + def hs : SystemZUnaryCC; + def fs : SystemZUnaryCC; +} + +multiclass SystemZBinaryTruncHFG { + def h : SystemZBinaryConv; + def f : SystemZBinaryConv; + def g : SystemZBinaryConv; +} + +multiclass SystemZBinaryTruncCCHFG { + def hs : SystemZBinaryConvCC; + def fs : SystemZBinaryConvCC; + def gs : SystemZBinaryConvCC; +} + +multiclass SystemZBinaryExtBHF { + def b : SystemZBinaryConv; + def h : SystemZBinaryConv; + def f : SystemZBinaryConv; +} + +multiclass SystemZBinaryExtBHFG : SystemZBinaryExtBHF { + def g : SystemZBinaryConv; +} + +multiclass SystemZBinaryBHF { + def b : SystemZBinary; + def h : SystemZBinary; + def f : SystemZBinary; +} + +multiclass SystemZBinaryBHFG : SystemZBinaryBHF { + def g : SystemZBinary; +} + +multiclass SystemZBinaryIntBHFG { + def b : SystemZBinaryInt; + def h : SystemZBinaryInt; + def f : SystemZBinaryInt; + def g : SystemZBinaryInt; +} + +multiclass SystemZBinaryCCBHF { + def bs : SystemZBinaryCC; + def hs : SystemZBinaryCC; + def fs : SystemZBinaryCC; +} + +multiclass SystemZCompareBHFG { + def bs : SystemZBinaryCC; + def hs : SystemZBinaryCC; + def fs : SystemZBinaryCC; + def gs : SystemZBinaryCC; +} + +multiclass SystemZTernaryExtBHF { + def b : SystemZTernaryConv; + def h : SystemZTernaryConv; + def f : SystemZTernaryConv; +} + +multiclass SystemZTernaryExtBHFG : SystemZTernaryExtBHF { + def g : SystemZTernaryConv; +} + +multiclass SystemZTernaryBHF { + def b : SystemZTernary; + def h : SystemZTernary; + def f : SystemZTernary; +} + +multiclass SystemZTernaryIntBHF { + def b : SystemZTernaryInt; + def h : SystemZTernaryInt; + def f : SystemZTernaryInt; +} + +multiclass SystemZTernaryIntCCBHF { + def bs : SystemZTernaryIntCC; + def hs : SystemZTernaryIntCC; + def fs : SystemZTernaryIntCC; +} + +multiclass SystemZQuaternaryIntBHF { + def b : SystemZQuaternaryInt; + def h : SystemZQuaternaryInt; + def f : SystemZQuaternaryInt; +} + +multiclass SystemZQuaternaryIntBHFG : SystemZQuaternaryIntBHF { + def g : SystemZQuaternaryInt; +} + +multiclass SystemZQuaternaryIntCCBHF { + def bs : SystemZQuaternaryIntCC; + def hs : SystemZQuaternaryIntCC; + def fs : SystemZQuaternaryIntCC; +} + //===----------------------------------------------------------------------===// // // Transactional-execution intrinsics @@ -44,3 +223,154 @@ let TargetPrefix = "s390" in { Intrinsic<[], [llvm_i32_ty]>; } +//===----------------------------------------------------------------------===// +// +// Vector intrinsics +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "s390" in { + def int_s390_lcbb : GCCBuiltin<"__builtin_s390_lcbb">, + Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_s390_vlbb : GCCBuiltin<"__builtin_s390_vlbb">, + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrReadArgMem]>; + + def int_s390_vll : GCCBuiltin<"__builtin_s390_vll">, + Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty, llvm_ptr_ty], + [IntrReadArgMem]>; + + def int_s390_vpdi : GCCBuiltin<"__builtin_s390_vpdi">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_s390_vperm : GCCBuiltin<"__builtin_s390_vperm">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + + defm int_s390_vpks : SystemZBinaryTruncHFG<"vpks">; + defm int_s390_vpks : SystemZBinaryTruncCCHFG; + + defm int_s390_vpkls : SystemZBinaryTruncHFG<"vpkls">; + defm int_s390_vpkls : SystemZBinaryTruncCCHFG; + + def int_s390_vstl : GCCBuiltin<"__builtin_s390_vstl">, + Intrinsic<[], [llvm_v16i8_ty, llvm_i32_ty, llvm_ptr_ty], + // In fact write-only but there's no property + // for that. + [IntrReadWriteArgMem]>; + + defm int_s390_vupl : SystemZUnaryExtBHWF<"vupl">; + defm int_s390_vupll : SystemZUnaryExtBHF<"vupll">; + + defm int_s390_vuph : SystemZUnaryExtBHF<"vuph">; + defm int_s390_vuplh : SystemZUnaryExtBHF<"vuplh">; + + defm int_s390_vacc : SystemZBinaryBHFG<"vacc">; + + def int_s390_vaq : SystemZBinary<"vaq", llvm_v16i8_ty>; + def int_s390_vacq : SystemZTernary<"vacq", llvm_v16i8_ty>; + def int_s390_vaccq : SystemZBinary<"vaccq", llvm_v16i8_ty>; + def int_s390_vacccq : SystemZTernary<"vacccq", llvm_v16i8_ty>; + + defm int_s390_vavg : SystemZBinaryBHFG<"vavg">; + defm int_s390_vavgl : SystemZBinaryBHFG<"vavgl">; + + def int_s390_vcksm : SystemZBinary<"vcksm", llvm_v4i32_ty>; + + defm int_s390_vgfm : SystemZBinaryExtBHFG<"vgfm">; + defm int_s390_vgfma : SystemZTernaryExtBHFG<"vgfma">; + + defm int_s390_vmah : SystemZTernaryBHF<"vmah">; + defm int_s390_vmalh : SystemZTernaryBHF<"vmalh">; + defm int_s390_vmae : SystemZTernaryExtBHF<"vmae">; + defm int_s390_vmale : SystemZTernaryExtBHF<"vmale">; + defm int_s390_vmao : SystemZTernaryExtBHF<"vmao">; + defm int_s390_vmalo : SystemZTernaryExtBHF<"vmalo">; + + defm int_s390_vmh : SystemZBinaryBHF<"vmh">; + defm int_s390_vmlh : SystemZBinaryBHF<"vmlh">; + defm int_s390_vme : SystemZBinaryExtBHF<"vme">; + defm int_s390_vmle : SystemZBinaryExtBHF<"vmle">; + defm int_s390_vmo : SystemZBinaryExtBHF<"vmo">; + defm int_s390_vmlo : SystemZBinaryExtBHF<"vmlo">; + + defm int_s390_verllv : SystemZBinaryBHFG<"verllv">; + defm int_s390_verll : SystemZBinaryIntBHFG<"verll">; + defm int_s390_verim : SystemZQuaternaryIntBHFG<"verim">; + + def int_s390_vsl : SystemZBinary<"vsl", llvm_v16i8_ty>; + def int_s390_vslb : SystemZBinary<"vslb", llvm_v16i8_ty>; + def int_s390_vsra : SystemZBinary<"vsra", llvm_v16i8_ty>; + def int_s390_vsrab : SystemZBinary<"vsrab", llvm_v16i8_ty>; + def int_s390_vsrl : SystemZBinary<"vsrl", llvm_v16i8_ty>; + def int_s390_vsrlb : SystemZBinary<"vsrlb", llvm_v16i8_ty>; + + def int_s390_vsldb : GCCBuiltin<"__builtin_s390_vsldb">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + defm int_s390_vscbi : SystemZBinaryBHFG<"vscbi">; + + def int_s390_vsq : SystemZBinary<"vsq", llvm_v16i8_ty>; + def int_s390_vsbiq : SystemZTernary<"vsbiq", llvm_v16i8_ty>; + def int_s390_vscbiq : SystemZBinary<"vscbiq", llvm_v16i8_ty>; + def int_s390_vsbcbiq : SystemZTernary<"vsbcbiq", llvm_v16i8_ty>; + + def int_s390_vsumb : SystemZBinaryConv<"vsumb", llvm_v4i32_ty, llvm_v16i8_ty>; + def int_s390_vsumh : SystemZBinaryConv<"vsumh", llvm_v4i32_ty, llvm_v8i16_ty>; + + def int_s390_vsumgh : SystemZBinaryConv<"vsumgh", llvm_v2i64_ty, + llvm_v8i16_ty>; + def int_s390_vsumgf : SystemZBinaryConv<"vsumgf", llvm_v2i64_ty, + llvm_v4i32_ty>; + + def int_s390_vsumqf : SystemZBinaryConv<"vsumqf", llvm_v16i8_ty, + llvm_v4i32_ty>; + def int_s390_vsumqg : SystemZBinaryConv<"vsumqg", llvm_v16i8_ty, + llvm_v2i64_ty>; + + def int_s390_vtm : SystemZBinaryConv<"vtm", llvm_i32_ty, llvm_v16i8_ty>; + + defm int_s390_vceq : SystemZCompareBHFG<"vceq">; + defm int_s390_vch : SystemZCompareBHFG<"vch">; + defm int_s390_vchl : SystemZCompareBHFG<"vchl">; + + defm int_s390_vfae : SystemZTernaryIntBHF<"vfae">; + defm int_s390_vfae : SystemZTernaryIntCCBHF; + defm int_s390_vfaez : SystemZTernaryIntBHF<"vfaez">; + defm int_s390_vfaez : SystemZTernaryIntCCBHF; + + defm int_s390_vfee : SystemZBinaryBHF<"vfee">; + defm int_s390_vfee : SystemZBinaryCCBHF; + defm int_s390_vfeez : SystemZBinaryBHF<"vfeez">; + defm int_s390_vfeez : SystemZBinaryCCBHF; + + defm int_s390_vfene : SystemZBinaryBHF<"vfene">; + defm int_s390_vfene : SystemZBinaryCCBHF; + defm int_s390_vfenez : SystemZBinaryBHF<"vfenez">; + defm int_s390_vfenez : SystemZBinaryCCBHF; + + defm int_s390_vistr : SystemZUnaryBHF<"vistr">; + defm int_s390_vistr : SystemZUnaryCCBHF; + + defm int_s390_vstrc : SystemZQuaternaryIntBHF<"vstrc">; + defm int_s390_vstrc : SystemZQuaternaryIntCCBHF; + defm int_s390_vstrcz : SystemZQuaternaryIntBHF<"vstrcz">; + defm int_s390_vstrcz : SystemZQuaternaryIntCCBHF; + + def int_s390_vfcedbs : SystemZBinaryConvCC; + def int_s390_vfchdbs : SystemZBinaryConvCC; + def int_s390_vfchedbs : SystemZBinaryConvCC; + + def int_s390_vftcidb : SystemZBinaryConvIntCC; + + def int_s390_vfidb : Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; +} diff --git a/include/llvm/IR/IntrinsicsWebAssembly.td b/include/llvm/IR/IntrinsicsWebAssembly.td new file mode 100644 index 00000000000..3ccde474238 --- /dev/null +++ b/include/llvm/IR/IntrinsicsWebAssembly.td @@ -0,0 +1,16 @@ +//===- IntrinsicsWebAssembly.td - Defines wasm intrinsics --*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file defines all of the WebAssembly-specific intrinsics. +/// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "wasm" in { // All intrinsics start with "llvm.wasm.". +} diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 49231d814f3..0d60aefed15 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -17,6 +17,23 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_int : Intrinsic<[], [llvm_i8_ty]>; } +//===----------------------------------------------------------------------===// +// SEH intrinsics for Windows +let TargetPrefix = "x86" in { + def int_x86_seh_lsda : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], [IntrNoMem]>; + + // Restores the frame, base, and stack pointers as necessary after recovering + // from an exception. Any block resuming control flow in the parent function + // should call this before accessing any stack memory. + def int_x86_seh_restoreframe : Intrinsic<[], [], []>; + + // Given a pointer to the end of an EH registration object, returns the true + // parent frame address that can be used with llvm.localrecover. + def int_x86_seh_recoverfp : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty, llvm_ptr_ty], + [IntrNoMem]>; +} + //===----------------------------------------------------------------------===// // Read Time Stamp Counter. let TargetPrefix = "x86" in { @@ -1123,28 +1140,292 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpermt_d_512: + def int_x86_avx512_mask_vpermi2var_d_128 : + GCCBuiltin<"__builtin_ia32_vpermi2vard128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermi2var_d_256 : + GCCBuiltin<"__builtin_ia32_vpermi2vard256_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermi2var_d_512 : + GCCBuiltin<"__builtin_ia32_vpermi2vard512_mask">, + Intrinsic<[llvm_v16i32_ty], + [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermi2var_hi_128 : + GCCBuiltin<"__builtin_ia32_vpermi2varhi128_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermi2var_hi_256 : + GCCBuiltin<"__builtin_ia32_vpermi2varhi256_mask">, + Intrinsic<[llvm_v16i16_ty], + [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermi2var_hi_512 : + GCCBuiltin<"__builtin_ia32_vpermi2varhi512_mask">, + Intrinsic<[llvm_v32i16_ty], + [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermi2var_pd_128 : + GCCBuiltin<"__builtin_ia32_vpermi2varpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2i64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermi2var_pd_256 : + GCCBuiltin<"__builtin_ia32_vpermi2varpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermi2var_pd_512 : + GCCBuiltin<"__builtin_ia32_vpermi2varpd512_mask">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8i64_ty, llvm_v8f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermi2var_ps_128 : + GCCBuiltin<"__builtin_ia32_vpermi2varps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4i32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermi2var_ps_256 : + GCCBuiltin<"__builtin_ia32_vpermi2varps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8i32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermi2var_ps_512 : + GCCBuiltin<"__builtin_ia32_vpermi2varps512_mask">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16i32_ty, llvm_v16f32_ty, llvm_i16_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermi2var_q_128 : + GCCBuiltin<"__builtin_ia32_vpermi2varq128_mask">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermi2var_q_256 : + GCCBuiltin<"__builtin_ia32_vpermi2varq256_mask">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermi2var_q_512 : + GCCBuiltin<"__builtin_ia32_vpermi2varq512_mask">, + Intrinsic<[llvm_v8i64_ty], + [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermt2var_d_512: GCCBuiltin<"__builtin_ia32_vpermt2vard512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpermt_q_512: + def int_x86_avx512_mask_vpermt2var_q_512: GCCBuiltin<"__builtin_ia32_vpermt2varq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpermt_ps_512: + def int_x86_avx512_mask_vpermt2var_ps_512: GCCBuiltin<"__builtin_ia32_vpermt2varps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16i32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vpermt_pd_512: + def int_x86_avx512_mask_vpermt2var_pd_512: GCCBuiltin<"__builtin_ia32_vpermt2varpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8i64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_vpermt2var_d_128 : + GCCBuiltin<"__builtin_ia32_vpermt2vard128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vpermt2var_d_128 : + GCCBuiltin<"__builtin_ia32_vpermt2vard128_maskz">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermt2var_d_256 : + GCCBuiltin<"__builtin_ia32_vpermt2vard256_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vpermt2var_d_256 : + GCCBuiltin<"__builtin_ia32_vpermt2vard256_maskz">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vpermt2var_d_512 : + GCCBuiltin<"__builtin_ia32_vpermt2vard512_maskz">, + Intrinsic<[llvm_v16i32_ty], + [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermt2var_hi_128 : + GCCBuiltin<"__builtin_ia32_vpermt2varhi128_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vpermt2var_hi_128 : + GCCBuiltin<"__builtin_ia32_vpermt2varhi128_maskz">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermt2var_hi_256 : + GCCBuiltin<"__builtin_ia32_vpermt2varhi256_mask">, + Intrinsic<[llvm_v16i16_ty], + [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vpermt2var_hi_256 : + GCCBuiltin<"__builtin_ia32_vpermt2varhi256_maskz">, + Intrinsic<[llvm_v16i16_ty], + [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermt2var_hi_512 : + GCCBuiltin<"__builtin_ia32_vpermt2varhi512_mask">, + Intrinsic<[llvm_v32i16_ty], + [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vpermt2var_hi_512 : + GCCBuiltin<"__builtin_ia32_vpermt2varhi512_maskz">, + Intrinsic<[llvm_v32i16_ty], + [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermt2var_pd_128 : + GCCBuiltin<"__builtin_ia32_vpermt2varpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2i64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vpermt2var_pd_128 : + GCCBuiltin<"__builtin_ia32_vpermt2varpd128_maskz">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2i64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermt2var_pd_256 : + GCCBuiltin<"__builtin_ia32_vpermt2varpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4i64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vpermt2var_pd_256 : + GCCBuiltin<"__builtin_ia32_vpermt2varpd256_maskz">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4i64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vpermt2var_pd_512 : + GCCBuiltin<"__builtin_ia32_vpermt2varpd512_maskz">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8i64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermt2var_ps_128 : + GCCBuiltin<"__builtin_ia32_vpermt2varps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4i32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vpermt2var_ps_128 : + GCCBuiltin<"__builtin_ia32_vpermt2varps128_maskz">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4i32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermt2var_ps_256 : + GCCBuiltin<"__builtin_ia32_vpermt2varps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8i32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vpermt2var_ps_256 : + GCCBuiltin<"__builtin_ia32_vpermt2varps256_maskz">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8i32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vpermt2var_ps_512 : + GCCBuiltin<"__builtin_ia32_vpermt2varps512_maskz">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16i32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermt2var_q_128 : + GCCBuiltin<"__builtin_ia32_vpermt2varq128_mask">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vpermt2var_q_128 : + GCCBuiltin<"__builtin_ia32_vpermt2varq128_maskz">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vpermt2var_q_256 : + GCCBuiltin<"__builtin_ia32_vpermt2varq256_mask">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vpermt2var_q_256 : + GCCBuiltin<"__builtin_ia32_vpermt2varq256_maskz">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vpermt2var_q_512 : + GCCBuiltin<"__builtin_ia32_vpermt2varq512_maskz">, + Intrinsic<[llvm_v8i64_ty], + [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_pshuf_b_128 : + GCCBuiltin<"__builtin_ia32_pshufb128_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_pshuf_b_256 : + GCCBuiltin<"__builtin_ia32_pshufb256_mask">, + Intrinsic<[llvm_v32i8_ty], + [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_pshuf_b_512 : + GCCBuiltin<"__builtin_ia32_pshufb512_mask">, + Intrinsic<[llvm_v64i8_ty], + [llvm_v64i8_ty, llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], + [IntrNoMem]>; } + // Vector blend let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx_blendv_pd_256 : GCCBuiltin<"__builtin_ia32_blendvpd256">, @@ -1448,30 +1729,150 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_pmins_d : GCCBuiltin<"__builtin_ia32_pminsd256">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem, Commutative]>; + def int_x86_avx512_mask_pmaxs_b_128 : GCCBuiltin<"__builtin_ia32_pmaxsb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxs_b_256 : GCCBuiltin<"__builtin_ia32_pmaxsb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxs_b_512 : GCCBuiltin<"__builtin_ia32_pmaxsb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxu_b_128 : GCCBuiltin<"__builtin_ia32_pmaxub128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxu_b_256 : GCCBuiltin<"__builtin_ia32_pmaxub256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxu_b_512 : GCCBuiltin<"__builtin_ia32_pmaxub512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxs_w_128 : GCCBuiltin<"__builtin_ia32_pmaxsw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxs_w_256 : GCCBuiltin<"__builtin_ia32_pmaxsw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxs_w_512 : GCCBuiltin<"__builtin_ia32_pmaxsw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty],[IntrNoMem]>; + def int_x86_avx512_mask_pmaxu_w_128 : GCCBuiltin<"__builtin_ia32_pmaxuw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxu_w_256 : GCCBuiltin<"__builtin_ia32_pmaxuw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxu_w_512 : GCCBuiltin<"__builtin_ia32_pmaxuw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty],[IntrNoMem]>; + def int_x86_avx512_mask_pmins_b_128 : GCCBuiltin<"__builtin_ia32_pminsb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty,llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmins_b_256 : GCCBuiltin<"__builtin_ia32_pminsb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmins_b_512 : GCCBuiltin<"__builtin_ia32_pminsb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pminu_b_128 : GCCBuiltin<"__builtin_ia32_pminub128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pminu_b_256 : GCCBuiltin<"__builtin_ia32_pminub256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pminu_b_512 : GCCBuiltin<"__builtin_ia32_pminub512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmins_w_128 : GCCBuiltin<"__builtin_ia32_pminsw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmins_w_256 : GCCBuiltin<"__builtin_ia32_pminsw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmins_w_512 : GCCBuiltin<"__builtin_ia32_pminsw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty],[IntrNoMem]>; + def int_x86_avx512_mask_pminu_w_128 : GCCBuiltin<"__builtin_ia32_pminuw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pminu_w_256 : GCCBuiltin<"__builtin_ia32_pminuw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pminu_w_512 : GCCBuiltin<"__builtin_ia32_pminuw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_pmaxu_d_512 : GCCBuiltin<"__builtin_ia32_pmaxud512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxu_d_256 : GCCBuiltin<"__builtin_ia32_pmaxud256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxu_d_128 : GCCBuiltin<"__builtin_ia32_pmaxud128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_pmaxs_d_512 : GCCBuiltin<"__builtin_ia32_pmaxsd512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxs_d_256 : GCCBuiltin<"__builtin_ia32_pmaxsd256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxs_d_128 : GCCBuiltin<"__builtin_ia32_pmaxsd128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_pmaxu_q_512 : GCCBuiltin<"__builtin_ia32_pmaxuq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxu_q_256 : GCCBuiltin<"__builtin_ia32_pmaxuq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxu_q_128 : GCCBuiltin<"__builtin_ia32_pmaxuq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_pmaxs_q_512 : GCCBuiltin<"__builtin_ia32_pmaxsq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxs_q_256 : GCCBuiltin<"__builtin_ia32_pmaxsq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaxs_q_128 : GCCBuiltin<"__builtin_ia32_pmaxsq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_pminu_d_512 : GCCBuiltin<"__builtin_ia32_pminud512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pminu_d_256 : GCCBuiltin<"__builtin_ia32_pminud256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pminu_d_128 : GCCBuiltin<"__builtin_ia32_pminud128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_pmins_d_512 : GCCBuiltin<"__builtin_ia32_pminsd512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmins_d_256 : GCCBuiltin<"__builtin_ia32_pminsd256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmins_d_128 : GCCBuiltin<"__builtin_ia32_pminsd128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_pminu_q_512 : GCCBuiltin<"__builtin_ia32_pminuq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pminu_q_256 : GCCBuiltin<"__builtin_ia32_pminuq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pminu_q_128 : GCCBuiltin<"__builtin_ia32_pminuq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_pmins_q_512 : GCCBuiltin<"__builtin_ia32_pminsq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmins_q_256 : GCCBuiltin<"__builtin_ia32_pminsq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmins_q_128 : GCCBuiltin<"__builtin_ia32_pminsq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; } // Integer shift ops. @@ -1589,12 +1990,78 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty], [IntrNoMem]>; def int_x86_avx2_pabs_d : GCCBuiltin<"__builtin_ia32_pabsd256">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pabs_d_512 : GCCBuiltin<"__builtin_ia32_pabsd512_mask">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_i16_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pabs_q_512 : GCCBuiltin<"__builtin_ia32_pabsq512_mask">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, - llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_pabs_b_128 : + GCCBuiltin<"__builtin_ia32_pabsb128_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_pabs_b_256 : + GCCBuiltin<"__builtin_ia32_pabsb256_mask">, + Intrinsic<[llvm_v32i8_ty], + [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_pabs_b_512 : + GCCBuiltin<"__builtin_ia32_pabsb512_mask">, + Intrinsic<[llvm_v64i8_ty], + [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_pabs_d_128 : + GCCBuiltin<"__builtin_ia32_pabsd128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_pabs_d_256 : + GCCBuiltin<"__builtin_ia32_pabsd256_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_pabs_d_512 : + GCCBuiltin<"__builtin_ia32_pabsd512_mask">, + Intrinsic<[llvm_v16i32_ty], + [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_pabs_q_128 : + GCCBuiltin<"__builtin_ia32_pabsq128_mask">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_pabs_q_256 : + GCCBuiltin<"__builtin_ia32_pabsq256_mask">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_pabs_q_512 : + GCCBuiltin<"__builtin_ia32_pabsq512_mask">, + Intrinsic<[llvm_v8i64_ty], + [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_pabs_w_128 : + GCCBuiltin<"__builtin_ia32_pabsw128_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_pabs_w_256 : + GCCBuiltin<"__builtin_ia32_pabsw256_mask">, + Intrinsic<[llvm_v16i16_ty], + [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_pabs_w_512 : + GCCBuiltin<"__builtin_ia32_pabsw512_mask">, + Intrinsic<[llvm_v32i16_ty], + [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], + [IntrNoMem]>; } // Horizontal arithmetic ops @@ -1640,6 +2107,15 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_pmul_hr_sw : GCCBuiltin<"__builtin_ia32_pmulhrsw256">, Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty], [IntrNoMem, Commutative]>; + def int_x86_avx512_mask_pmul_hr_sw_128 : GCCBuiltin<"__builtin_ia32_pmulhrsw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmul_hr_sw_256 : GCCBuiltin<"__builtin_ia32_pmulhrsw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmul_hr_sw_512 : GCCBuiltin<"__builtin_ia32_pmulhrsw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; } // Vector sign and zero extend @@ -1991,36 +2467,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_fma_mask_vfmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddps512_mask">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfmaddps256_mask">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, - llvm_i8_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfmadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfmaddps128_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddpd512_mask">, - Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmaddpd256_mask">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, - llvm_i8_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfmadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfmaddpd128_mask">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty], - [IntrNoMem]>; + def int_x86_fma_vfmsub_ss : GCCBuiltin<"__builtin_ia32_vfmsubss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -2045,36 +2492,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_fma_mask_vfmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubps512_mask">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfmsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfmsubps256_mask">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, - llvm_i8_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfmsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfmsubps128_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubpd512_mask">, - Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfmsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfmsubpd256_mask">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, - llvm_i8_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfmsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfmsubpd128_mask">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty], - [IntrNoMem]>; def int_x86_fma_vfnmadd_ss : GCCBuiltin<"__builtin_ia32_vfnmaddss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -2099,36 +2516,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_fma_mask_vfnmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmaddps512_mask">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfnmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfnmaddps256_mask">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, - llvm_i8_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfnmadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfnmaddps128_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfnmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmaddpd512_mask">, - Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfnmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfnmaddpd256_mask">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, - llvm_i8_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfnmadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfnmaddpd128_mask">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty], - [IntrNoMem]>; def int_x86_fma_vfnmsub_ss : GCCBuiltin<"__builtin_ia32_vfnmsubss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -2153,36 +2540,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_fma_mask_vfnmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmsubps512_mask">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfnmsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfnmsubps256_mask">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, - llvm_i8_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfnmsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfnmsubps128_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfnmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmsubpd512_mask">, - Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfnmsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfnmsubpd256_mask">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, - llvm_i8_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfnmsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfnmsubpd128_mask">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty], - [IntrNoMem]>; def int_x86_fma_vfmaddsub_ps : GCCBuiltin<"__builtin_ia32_vfmaddsubps">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -2201,36 +2558,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_fma_mask_vfmaddsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubps512_mask">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfmaddsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfmaddsubps256_mask">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, - llvm_i8_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfmaddsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfmaddsubps128_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfmaddsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd512_mask">, - Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfmaddsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd256_mask">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, - llvm_i8_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfmaddsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd128_mask">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty], - [IntrNoMem]>; def int_x86_fma_vfmsubadd_ps : GCCBuiltin<"__builtin_ia32_vfmsubaddps">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], @@ -2249,36 +2576,403 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_fma_mask_vfmsubadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddps512_mask">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfmsubadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfmsubaddps256_mask">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, - llvm_i8_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfmsubadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfmsubaddps128_mask">, - Intrinsic<[llvm_v4f32_ty], - [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, - llvm_i8_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfmsubadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd512_mask">, - Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, - llvm_i8_ty, llvm_i32_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfmsubadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd256_mask">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, - llvm_i8_ty], - [IntrNoMem]>; - def int_x86_fma_mask_vfmsubadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd128_mask">, - Intrinsic<[llvm_v2f64_ty], - [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, - llvm_i8_ty], - [IntrNoMem]>; + + def int_x86_avx512_mask_vfmadd_pd_128 : + GCCBuiltin<"__builtin_ia32_vfmaddpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmadd_pd_128 : + GCCBuiltin<"__builtin_ia32_vfmaddpd128_mask3">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vfmadd_pd_128 : + GCCBuiltin<"__builtin_ia32_vfmaddpd128_maskz">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vfmadd_pd_256 : + GCCBuiltin<"__builtin_ia32_vfmaddpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmadd_pd_256 : + GCCBuiltin<"__builtin_ia32_vfmaddpd256_mask3">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vfmadd_pd_256 : + GCCBuiltin<"__builtin_ia32_vfmaddpd256_maskz">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vfmadd_pd_512 : + GCCBuiltin<"__builtin_ia32_vfmaddpd512_mask">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmadd_pd_512 : + GCCBuiltin<"__builtin_ia32_vfmaddpd512_mask3">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_maskz_vfmadd_pd_512 : + GCCBuiltin<"__builtin_ia32_vfmaddpd512_maskz">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_vfmadd_ps_128 : + GCCBuiltin<"__builtin_ia32_vfmaddps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmadd_ps_128 : + GCCBuiltin<"__builtin_ia32_vfmaddps128_mask3">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vfmadd_ps_128 : + GCCBuiltin<"__builtin_ia32_vfmaddps128_maskz">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vfmadd_ps_256 : + GCCBuiltin<"__builtin_ia32_vfmaddps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmadd_ps_256 : + GCCBuiltin<"__builtin_ia32_vfmaddps256_mask3">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vfmadd_ps_256 : + GCCBuiltin<"__builtin_ia32_vfmaddps256_maskz">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vfmadd_ps_512 : + GCCBuiltin<"__builtin_ia32_vfmaddps512_mask">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmadd_ps_512 : + GCCBuiltin<"__builtin_ia32_vfmaddps512_mask3">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_maskz_vfmadd_ps_512 : + GCCBuiltin<"__builtin_ia32_vfmaddps512_maskz">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_vfmaddsub_pd_128 : + GCCBuiltin<"__builtin_ia32_vfmaddsubpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmaddsub_pd_128 : + GCCBuiltin<"__builtin_ia32_vfmaddsubpd128_mask3">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vfmaddsub_pd_128 : + GCCBuiltin<"__builtin_ia32_vfmaddsubpd128_maskz">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vfmaddsub_pd_256 : + GCCBuiltin<"__builtin_ia32_vfmaddsubpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmaddsub_pd_256 : + GCCBuiltin<"__builtin_ia32_vfmaddsubpd256_mask3">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vfmaddsub_pd_256 : + GCCBuiltin<"__builtin_ia32_vfmaddsubpd256_maskz">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vfmaddsub_pd_512 : + GCCBuiltin<"__builtin_ia32_vfmaddsubpd512_mask">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmaddsub_pd_512 : + GCCBuiltin<"__builtin_ia32_vfmaddsubpd512_mask3">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_maskz_vfmaddsub_pd_512 : + GCCBuiltin<"__builtin_ia32_vfmaddsubpd512_maskz">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_vfmaddsub_ps_128 : + GCCBuiltin<"__builtin_ia32_vfmaddsubps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmaddsub_ps_128 : + GCCBuiltin<"__builtin_ia32_vfmaddsubps128_mask3">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vfmaddsub_ps_128 : + GCCBuiltin<"__builtin_ia32_vfmaddsubps128_maskz">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vfmaddsub_ps_256 : + GCCBuiltin<"__builtin_ia32_vfmaddsubps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmaddsub_ps_256 : + GCCBuiltin<"__builtin_ia32_vfmaddsubps256_mask3">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_maskz_vfmaddsub_ps_256 : + GCCBuiltin<"__builtin_ia32_vfmaddsubps256_maskz">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vfmaddsub_ps_512 : + GCCBuiltin<"__builtin_ia32_vfmaddsubps512_mask">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmaddsub_ps_512 : + GCCBuiltin<"__builtin_ia32_vfmaddsubps512_mask3">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_maskz_vfmaddsub_ps_512 : + GCCBuiltin<"__builtin_ia32_vfmaddsubps512_maskz">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmsub_pd_128 : + GCCBuiltin<"__builtin_ia32_vfmsubpd128_mask3">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmsub_pd_256 : + GCCBuiltin<"__builtin_ia32_vfmsubpd256_mask3">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmsub_pd_512 : + GCCBuiltin<"__builtin_ia32_vfmsubpd512_mask3">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmsub_ps_128 : + GCCBuiltin<"__builtin_ia32_vfmsubps128_mask3">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmsub_ps_256 : + GCCBuiltin<"__builtin_ia32_vfmsubps256_mask3">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmsub_ps_512 : + GCCBuiltin<"__builtin_ia32_vfmsubps512_mask3">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmsubadd_pd_128 : + GCCBuiltin<"__builtin_ia32_vfmsubaddpd128_mask3">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmsubadd_pd_256 : + GCCBuiltin<"__builtin_ia32_vfmsubaddpd256_mask3">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmsubadd_pd_512 : + GCCBuiltin<"__builtin_ia32_vfmsubaddpd512_mask3">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmsubadd_ps_128 : + GCCBuiltin<"__builtin_ia32_vfmsubaddps128_mask3">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmsubadd_ps_256 : + GCCBuiltin<"__builtin_ia32_vfmsubaddps256_mask3">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask3_vfmsubadd_ps_512 : + GCCBuiltin<"__builtin_ia32_vfmsubaddps512_mask3">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_vfnmadd_pd_128 : + GCCBuiltin<"__builtin_ia32_vfnmaddpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vfnmadd_pd_256 : + GCCBuiltin<"__builtin_ia32_vfnmaddpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vfnmadd_pd_512 : + GCCBuiltin<"__builtin_ia32_vfnmaddpd512_mask">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_vfnmadd_ps_128 : + GCCBuiltin<"__builtin_ia32_vfnmaddps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vfnmadd_ps_256 : + GCCBuiltin<"__builtin_ia32_vfnmaddps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vfnmadd_ps_512 : + GCCBuiltin<"__builtin_ia32_vfnmaddps512_mask">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_vfnmsub_pd_128 : + GCCBuiltin<"__builtin_ia32_vfnmsubpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask3_vfnmsub_pd_128 : + GCCBuiltin<"__builtin_ia32_vfnmsubpd128_mask3">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vfnmsub_pd_256 : + GCCBuiltin<"__builtin_ia32_vfnmsubpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask3_vfnmsub_pd_256 : + GCCBuiltin<"__builtin_ia32_vfnmsubpd256_mask3">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vfnmsub_pd_512 : + GCCBuiltin<"__builtin_ia32_vfnmsubpd512_mask">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask3_vfnmsub_pd_512 : + GCCBuiltin<"__builtin_ia32_vfnmsubpd512_mask3">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_vfnmsub_ps_128 : + GCCBuiltin<"__builtin_ia32_vfnmsubps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask3_vfnmsub_ps_128 : + GCCBuiltin<"__builtin_ia32_vfnmsubps128_mask3">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vfnmsub_ps_256 : + GCCBuiltin<"__builtin_ia32_vfnmsubps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask3_vfnmsub_ps_256 : + GCCBuiltin<"__builtin_ia32_vfnmsubps256_mask3">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_vfnmsub_ps_512 : + GCCBuiltin<"__builtin_ia32_vfnmsubps512_mask">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask3_vfnmsub_ps_512 : + GCCBuiltin<"__builtin_ia32_vfnmsubps512_mask3">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, + llvm_i32_ty], [IntrNoMem]>; + } //===----------------------------------------------------------------------===// @@ -2837,6 +3531,19 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[], [llvm_i64_ty]>; } +//===----------------------------------------------------------------------===// +// FXSR +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_fxrstor : GCCBuiltin<"__builtin_ia32_fxrstor">, + Intrinsic<[], [llvm_ptr_ty], []>; + def int_x86_fxrstor64 : GCCBuiltin<"__builtin_ia32_fxrstor64">, + Intrinsic<[], [llvm_ptr_ty], []>; + def int_x86_fxsave : GCCBuiltin<"__builtin_ia32_fxsave">, + Intrinsic<[], [llvm_ptr_ty], []>; + def int_x86_fxsave64 : GCCBuiltin<"__builtin_ia32_fxsave64">, + Intrinsic<[], [llvm_ptr_ty], []>; +} + //===----------------------------------------------------------------------===// // Half float conversion @@ -2968,12 +3675,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_i32_ty], [llvm_v4f32_ty], [IntrNoMem]>; def int_x86_avx512_cvttss2usi64 : GCCBuiltin<"__builtin_ia32_cvttss2usi64">, Intrinsic<[llvm_i64_ty], [llvm_v4f32_ty], [IntrNoMem]>; - def int_x86_avx512_cvtusi2ss : GCCBuiltin<"__builtin_ia32_cvtusi2ss">, + def int_x86_avx512_cvtusi2ss : GCCBuiltin<"__builtin_ia32_cvtusi2ss32">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_cvtusi642ss : GCCBuiltin<"__builtin_ia32_cvtusi642ss">, + llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_cvtusi642ss : GCCBuiltin<"__builtin_ia32_cvtusi2ss64">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, - llvm_i64_ty], [IntrNoMem]>; + llvm_i64_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_cvtsd2usi : GCCBuiltin<"__builtin_ia32_cvtsd2usi">, Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; @@ -2983,61 +3690,810 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_i32_ty], [llvm_v2f64_ty], [IntrNoMem]>; def int_x86_avx512_cvttsd2usi64 : GCCBuiltin<"__builtin_ia32_cvttsd2usi64">, Intrinsic<[llvm_i64_ty], [llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_avx512_cvtusi2sd : GCCBuiltin<"__builtin_ia32_cvtusi2sd">, + def int_x86_avx512_cvtusi2sd : GCCBuiltin<"__builtin_ia32_cvtusi2sd32">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_cvtusi642sd : GCCBuiltin<"__builtin_ia32_cvtusi642sd">, + def int_x86_avx512_cvtusi642sd : GCCBuiltin<"__builtin_ia32_cvtusi2sd64">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, - llvm_i64_ty], [IntrNoMem]>; + llvm_i64_ty, llvm_i32_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. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_mask_packsswb_128 : GCCBuiltin<"__builtin_ia32_packsswb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packsswb_256 : GCCBuiltin<"__builtin_ia32_packsswb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty,llvm_v16i16_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packsswb_512 : GCCBuiltin<"__builtin_ia32_packsswb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v32i16_ty,llvm_v32i16_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packssdw_128 : GCCBuiltin<"__builtin_ia32_packssdw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packssdw_256 : GCCBuiltin<"__builtin_ia32_packssdw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packssdw_512 : GCCBuiltin<"__builtin_ia32_packssdw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packuswb_128 : GCCBuiltin<"__builtin_ia32_packuswb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packuswb_256 : GCCBuiltin<"__builtin_ia32_packuswb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v16i16_ty,llvm_v16i16_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packuswb_512 : GCCBuiltin<"__builtin_ia32_packuswb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v32i16_ty,llvm_v32i16_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packusdw_128 : GCCBuiltin<"__builtin_ia32_packusdw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packusdw_256 : GCCBuiltin<"__builtin_ia32_packusdw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_packusdw_512 : GCCBuiltin<"__builtin_ia32_packusdw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; +} + +// Unpack ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_mask_unpckh_pd_128 : + GCCBuiltin<"__builtin_ia32_unpckhpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_unpckh_pd_256 : + GCCBuiltin<"__builtin_ia32_unpckhpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_unpckh_pd_512 : + GCCBuiltin<"__builtin_ia32_unpckhpd512_mask">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_unpckh_ps_128 : + GCCBuiltin<"__builtin_ia32_unpckhps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_unpckh_ps_256 : + GCCBuiltin<"__builtin_ia32_unpckhps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_unpckh_ps_512 : + GCCBuiltin<"__builtin_ia32_unpckhps512_mask">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_unpckl_pd_128 : + GCCBuiltin<"__builtin_ia32_unpcklpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_unpckl_pd_256 : + GCCBuiltin<"__builtin_ia32_unpcklpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_unpckl_pd_512 : + GCCBuiltin<"__builtin_ia32_unpcklpd512_mask">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_unpckl_ps_128 : + GCCBuiltin<"__builtin_ia32_unpcklps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_unpckl_ps_256 : + GCCBuiltin<"__builtin_ia32_unpcklps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_unpckl_ps_512 : + GCCBuiltin<"__builtin_ia32_unpcklps512_mask">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpckhb_w_128 : + GCCBuiltin<"__builtin_ia32_punpckhbw128_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpckhb_w_256 : + GCCBuiltin<"__builtin_ia32_punpckhbw256_mask">, + Intrinsic<[llvm_v32i8_ty], + [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpckhb_w_512 : + GCCBuiltin<"__builtin_ia32_punpckhbw512_mask">, + Intrinsic<[llvm_v64i8_ty], + [llvm_v64i8_ty, llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpckhd_q_128 : + GCCBuiltin<"__builtin_ia32_punpckhdq128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpckhd_q_256 : + GCCBuiltin<"__builtin_ia32_punpckhdq256_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpckhd_q_512 : + GCCBuiltin<"__builtin_ia32_punpckhdq512_mask">, + Intrinsic<[llvm_v16i32_ty], + [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpckhqd_q_128 : + GCCBuiltin<"__builtin_ia32_punpckhqdq128_mask">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpckhqd_q_256 : + GCCBuiltin<"__builtin_ia32_punpckhqdq256_mask">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpckhqd_q_512 : + GCCBuiltin<"__builtin_ia32_punpckhqdq512_mask">, + Intrinsic<[llvm_v8i64_ty], + [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpckhw_d_128 : + GCCBuiltin<"__builtin_ia32_punpckhwd128_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpckhw_d_256 : + GCCBuiltin<"__builtin_ia32_punpckhwd256_mask">, + Intrinsic<[llvm_v16i16_ty], + [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpckhw_d_512 : + GCCBuiltin<"__builtin_ia32_punpckhwd512_mask">, + Intrinsic<[llvm_v32i16_ty], + [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpcklb_w_128 : + GCCBuiltin<"__builtin_ia32_punpcklbw128_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpcklb_w_256 : + GCCBuiltin<"__builtin_ia32_punpcklbw256_mask">, + Intrinsic<[llvm_v32i8_ty], + [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpcklb_w_512 : + GCCBuiltin<"__builtin_ia32_punpcklbw512_mask">, + Intrinsic<[llvm_v64i8_ty], + [llvm_v64i8_ty, llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpckld_q_128 : + GCCBuiltin<"__builtin_ia32_punpckldq128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpckld_q_256 : + GCCBuiltin<"__builtin_ia32_punpckldq256_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8i32_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpckld_q_512 : + GCCBuiltin<"__builtin_ia32_punpckldq512_mask">, + Intrinsic<[llvm_v16i32_ty], + [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpcklqd_q_128 : + GCCBuiltin<"__builtin_ia32_punpcklqdq128_mask">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpcklqd_q_256 : + GCCBuiltin<"__builtin_ia32_punpcklqdq256_mask">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4i64_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpcklqd_q_512 : + GCCBuiltin<"__builtin_ia32_punpcklqdq512_mask">, + Intrinsic<[llvm_v8i64_ty], + [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpcklw_d_128 : + GCCBuiltin<"__builtin_ia32_punpcklwd128_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpcklw_d_256 : + GCCBuiltin<"__builtin_ia32_punpcklwd256_mask">, + Intrinsic<[llvm_v16i16_ty], + [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_punpcklw_d_512 : + GCCBuiltin<"__builtin_ia32_punpcklwd512_mask">, + Intrinsic<[llvm_v32i16_ty], + [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], + [IntrNoMem]>; } // Vector convert let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_mask_cvttps2dq_512: GCCBuiltin<"__builtin_ia32_cvttps2dq512_mask">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16f32_ty, llvm_v16i32_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cvttps2udq_512: GCCBuiltin<"__builtin_ia32_cvttps2udq512_mask">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16f32_ty, llvm_v16i32_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cvttpd2dq_512: GCCBuiltin<"__builtin_ia32_cvttpd2dq512_mask">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8f64_ty, llvm_v8i32_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cvttpd2udq_512: GCCBuiltin<"__builtin_ia32_cvttpd2udq512_mask">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8f64_ty, llvm_v8i32_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_rndscale_ps_512: GCCBuiltin<"__builtin_ia32_rndscaleps_mask">, + def int_x86_avx512_mask_cvtdq2pd_128 : + GCCBuiltin<"__builtin_ia32_cvtdq2pd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v4i32_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtdq2pd_256 : + GCCBuiltin<"__builtin_ia32_cvtdq2pd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4i32_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtdq2pd_512 : + GCCBuiltin<"__builtin_ia32_cvtdq2pd512_mask">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8i32_ty, llvm_v8f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtdq2ps_128 : + GCCBuiltin<"__builtin_ia32_cvtdq2ps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4i32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtdq2ps_256 : + GCCBuiltin<"__builtin_ia32_cvtdq2ps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8i32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtdq2ps_512 : + GCCBuiltin<"__builtin_ia32_cvtdq2ps512_mask">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16i32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtpd2dq_128 : + GCCBuiltin<"__builtin_ia32_cvtpd2dq128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v2f64_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtpd2dq_256 : + GCCBuiltin<"__builtin_ia32_cvtpd2dq256_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4f64_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtpd2dq_512 : + GCCBuiltin<"__builtin_ia32_cvtpd2dq512_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8f64_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtpd2ps_256 : + GCCBuiltin<"__builtin_ia32_cvtpd2ps256_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f64_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtpd2ps_512 : + GCCBuiltin<"__builtin_ia32_cvtpd2ps512_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f64_ty, llvm_v8f32_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtpd2ps : + GCCBuiltin<"__builtin_ia32_cvtpd2ps_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v2f64_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtpd2qq_128 : + GCCBuiltin<"__builtin_ia32_cvtpd2qq128_mask">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2f64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtpd2qq_256 : + GCCBuiltin<"__builtin_ia32_cvtpd2qq256_mask">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4f64_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtpd2qq_512 : + GCCBuiltin<"__builtin_ia32_cvtpd2qq512_mask">, + Intrinsic<[llvm_v8i64_ty], + [llvm_v8f64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtpd2udq_128 : + GCCBuiltin<"__builtin_ia32_cvtpd2udq128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v2f64_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtpd2udq_256 : + GCCBuiltin<"__builtin_ia32_cvtpd2udq256_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4f64_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtpd2udq_512 : + GCCBuiltin<"__builtin_ia32_cvtpd2udq512_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8f64_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtpd2uqq_128 : + GCCBuiltin<"__builtin_ia32_cvtpd2uqq128_mask">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2f64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtpd2uqq_256 : + GCCBuiltin<"__builtin_ia32_cvtpd2uqq256_mask">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4f64_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtpd2uqq_512 : + GCCBuiltin<"__builtin_ia32_cvtpd2uqq512_mask">, + Intrinsic<[llvm_v8i64_ty], + [llvm_v8f64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtps2dq_128 : + GCCBuiltin<"__builtin_ia32_cvtps2dq128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4f32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtps2dq_256 : + GCCBuiltin<"__builtin_ia32_cvtps2dq256_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8f32_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtps2dq_512 : + GCCBuiltin<"__builtin_ia32_cvtps2dq512_mask">, + Intrinsic<[llvm_v16i32_ty], + [llvm_v16f32_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtps2pd_128 : + GCCBuiltin<"__builtin_ia32_cvtps2pd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v4f32_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtps2pd_256 : + GCCBuiltin<"__builtin_ia32_cvtps2pd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f32_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtps2pd_512 : + GCCBuiltin<"__builtin_ia32_cvtps2pd512_mask">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8f32_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtps2qq_128 : + GCCBuiltin<"__builtin_ia32_cvtps2qq128_mask">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v4f32_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtps2qq_256 : + GCCBuiltin<"__builtin_ia32_cvtps2qq256_mask">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4f32_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtps2qq_512 : + GCCBuiltin<"__builtin_ia32_cvtps2qq512_mask">, + Intrinsic<[llvm_v8i64_ty], + [llvm_v8f32_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtps2udq_128 : + GCCBuiltin<"__builtin_ia32_cvtps2udq128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4f32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtps2udq_256 : + GCCBuiltin<"__builtin_ia32_cvtps2udq256_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8f32_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtps2udq_512 : + GCCBuiltin<"__builtin_ia32_cvtps2udq512_mask">, + Intrinsic<[llvm_v16i32_ty], + [llvm_v16f32_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtps2uqq_128 : + GCCBuiltin<"__builtin_ia32_cvtps2uqq128_mask">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v4f32_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtps2uqq_256 : + GCCBuiltin<"__builtin_ia32_cvtps2uqq256_mask">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4f32_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtps2uqq_512 : + GCCBuiltin<"__builtin_ia32_cvtps2uqq512_mask">, + Intrinsic<[llvm_v8i64_ty], + [llvm_v8f32_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtqq2pd_128 : + GCCBuiltin<"__builtin_ia32_cvtqq2pd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2i64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtqq2pd_256 : + GCCBuiltin<"__builtin_ia32_cvtqq2pd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtqq2pd_512 : + GCCBuiltin<"__builtin_ia32_cvtqq2pd512_mask">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8i64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtqq2ps_128 : + GCCBuiltin<"__builtin_ia32_cvtqq2ps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v2i64_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtqq2ps_256 : + GCCBuiltin<"__builtin_ia32_cvtqq2ps256_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4i64_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtqq2ps_512 : + GCCBuiltin<"__builtin_ia32_cvtqq2ps512_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8i64_ty, llvm_v8f32_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttpd2dq_128 : + GCCBuiltin<"__builtin_ia32_cvttpd2dq128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v2f64_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttpd2dq_256 : + GCCBuiltin<"__builtin_ia32_cvttpd2dq256_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4f64_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttpd2dq_512 : + GCCBuiltin<"__builtin_ia32_cvttpd2dq512_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8f64_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttpd2qq_128 : + GCCBuiltin<"__builtin_ia32_cvttpd2qq128_mask">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2f64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttpd2qq_256 : + GCCBuiltin<"__builtin_ia32_cvttpd2qq256_mask">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4f64_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttpd2qq_512 : + GCCBuiltin<"__builtin_ia32_cvttpd2qq512_mask">, + Intrinsic<[llvm_v8i64_ty], + [llvm_v8f64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttpd2udq_128 : + GCCBuiltin<"__builtin_ia32_cvttpd2udq128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v2f64_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttpd2udq_256 : + GCCBuiltin<"__builtin_ia32_cvttpd2udq256_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4f64_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttpd2udq_512 : + GCCBuiltin<"__builtin_ia32_cvttpd2udq512_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8f64_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttpd2uqq_128 : + GCCBuiltin<"__builtin_ia32_cvttpd2uqq128_mask">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2f64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttpd2uqq_256 : + GCCBuiltin<"__builtin_ia32_cvttpd2uqq256_mask">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4f64_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttpd2uqq_512 : + GCCBuiltin<"__builtin_ia32_cvttpd2uqq512_mask">, + Intrinsic<[llvm_v8i64_ty], + [llvm_v8f64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttps2dq_128 : + GCCBuiltin<"__builtin_ia32_cvttps2dq128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4f32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttps2dq_256 : + GCCBuiltin<"__builtin_ia32_cvttps2dq256_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8f32_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttps2dq_512 : + GCCBuiltin<"__builtin_ia32_cvttps2dq512_mask">, + Intrinsic<[llvm_v16i32_ty], + [llvm_v16f32_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttps2qq_128 : + GCCBuiltin<"__builtin_ia32_cvttps2qq128_mask">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v4f32_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttps2qq_256 : + GCCBuiltin<"__builtin_ia32_cvttps2qq256_mask">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4f32_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttps2qq_512 : + GCCBuiltin<"__builtin_ia32_cvttps2qq512_mask">, + Intrinsic<[llvm_v8i64_ty], + [llvm_v8f32_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttps2udq_128 : + GCCBuiltin<"__builtin_ia32_cvttps2udq128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4f32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttps2udq_256 : + GCCBuiltin<"__builtin_ia32_cvttps2udq256_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8f32_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttps2udq_512 : + GCCBuiltin<"__builtin_ia32_cvttps2udq512_mask">, + Intrinsic<[llvm_v16i32_ty], + [llvm_v16f32_ty, llvm_v16i32_ty, llvm_i16_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttps2uqq_128 : + GCCBuiltin<"__builtin_ia32_cvttps2uqq128_mask">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v4f32_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttps2uqq_256 : + GCCBuiltin<"__builtin_ia32_cvttps2uqq256_mask">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4f32_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvttps2uqq_512 : + GCCBuiltin<"__builtin_ia32_cvttps2uqq512_mask">, + Intrinsic<[llvm_v8i64_ty], + [llvm_v8f32_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtudq2pd_128 : + GCCBuiltin<"__builtin_ia32_cvtudq2pd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v4i32_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtudq2pd_256 : + GCCBuiltin<"__builtin_ia32_cvtudq2pd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4i32_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtudq2pd_512 : + GCCBuiltin<"__builtin_ia32_cvtudq2pd512_mask">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8i32_ty, llvm_v8f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtudq2ps_128 : + GCCBuiltin<"__builtin_ia32_cvtudq2ps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4i32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtudq2ps_256 : + GCCBuiltin<"__builtin_ia32_cvtudq2ps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8i32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtudq2ps_512 : + GCCBuiltin<"__builtin_ia32_cvtudq2ps512_mask">, + Intrinsic<[llvm_v16f32_ty], + [llvm_v16i32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtuqq2pd_128 : + GCCBuiltin<"__builtin_ia32_cvtuqq2pd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2i64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtuqq2pd_256 : + GCCBuiltin<"__builtin_ia32_cvtuqq2pd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4i64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtuqq2pd_512 : + GCCBuiltin<"__builtin_ia32_cvtuqq2pd512_mask">, + Intrinsic<[llvm_v8f64_ty], + [llvm_v8i64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtuqq2ps_128 : + GCCBuiltin<"__builtin_ia32_cvtuqq2ps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v2i64_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtuqq2ps_256 : + GCCBuiltin<"__builtin_ia32_cvtuqq2ps256_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4i64_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cvtuqq2ps_512 : + GCCBuiltin<"__builtin_ia32_cvtuqq2ps512_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8i64_ty, llvm_v8f32_ty, llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_rndscale_pd_128 : GCCBuiltin<"__builtin_ia32_rndscalepd_128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_i32_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_rndscale_pd_256 : GCCBuiltin<"__builtin_ia32_rndscalepd_256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_i32_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_rndscale_pd_512 : GCCBuiltin<"__builtin_ia32_rndscalepd_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i32_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_rndscale_ps_128 : GCCBuiltin<"__builtin_ia32_rndscaleps_128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_i32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_rndscale_ps_256 : GCCBuiltin<"__builtin_ia32_rndscaleps_256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_i32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_rndscale_ps_512 : GCCBuiltin<"__builtin_ia32_rndscaleps_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_i32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_rndscale_pd_512: GCCBuiltin<"__builtin_ia32_rndscalepd_mask">, + def int_x86_avx512_mask_reduce_pd_128 : GCCBuiltin<"__builtin_ia32_reducepd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_i32_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_reduce_pd_256 : GCCBuiltin<"__builtin_ia32_reducepd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_i32_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_reduce_pd_512 : GCCBuiltin<"__builtin_ia32_reducepd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_i32_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cvtps2dq_512: GCCBuiltin<"__builtin_ia32_cvtps2dq512_mask">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16f32_ty, llvm_v16i32_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cvtpd2dq_512: GCCBuiltin<"__builtin_ia32_cvtpd2dq512_mask">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8f64_ty, llvm_v8i32_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cvtps2udq_512: GCCBuiltin<"__builtin_ia32_cvtps2udq512_mask">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16f32_ty, llvm_v16i32_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cvtpd2udq_512: GCCBuiltin<"__builtin_ia32_cvtpd2udq512_mask">, - Intrinsic<[llvm_v8i32_ty], [llvm_v8f64_ty, llvm_v8i32_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cvtdq2ps_512 : GCCBuiltin<"__builtin_ia32_cvtdq2ps512_mask">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16i32_ty, llvm_v16f32_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cvtdq2pd_512 : GCCBuiltin<"__builtin_ia32_cvtdq2pd512_mask">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8i32_ty, llvm_v8f64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cvtudq2ps_512 : GCCBuiltin<"__builtin_ia32_cvtudq2ps512_mask">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16i32_ty, llvm_v16f32_ty, + def int_x86_avx512_mask_reduce_ps_128 : GCCBuiltin<"__builtin_ia32_reduceps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_i32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_reduce_ps_256 : GCCBuiltin<"__builtin_ia32_reduceps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_i32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_reduce_ps_512 : GCCBuiltin<"__builtin_ia32_reduceps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_i32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cvtudq2pd_512 : GCCBuiltin<"__builtin_ia32_cvtudq2pd512_mask">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8i32_ty, llvm_v8f64_ty, - llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cvtpd2ps_512 : GCCBuiltin<"__builtin_ia32_cvtpd2ps512_mask">, - Intrinsic<[llvm_v8f32_ty], [llvm_v8f64_ty, llvm_v8f32_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_x86_avx512_mask_range_pd_128 : GCCBuiltin<"__builtin_ia32_rangepd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; +def int_x86_avx512_mask_range_pd_256 : GCCBuiltin<"__builtin_ia32_rangepd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_i32_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; +def int_x86_avx512_mask_range_pd_512 : GCCBuiltin<"__builtin_ia32_rangepd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; +def int_x86_avx512_mask_range_ps_128 : GCCBuiltin<"__builtin_ia32_rangeps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; +def int_x86_avx512_mask_range_ps_256 : GCCBuiltin<"__builtin_ia32_rangeps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, llvm_i32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; +def int_x86_avx512_mask_range_ps_512 : GCCBuiltin<"__builtin_ia32_rangeps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; } // Vector load with broadcast @@ -3089,21 +4545,75 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". } //Bitwise Ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_mask_pand_d_128 : GCCBuiltin<"__builtin_ia32_pandd128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pand_d_256 : GCCBuiltin<"__builtin_ia32_pandd256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_pand_d_512 : GCCBuiltin<"__builtin_ia32_pandd512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pand_q_128 : GCCBuiltin<"__builtin_ia32_pandq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pand_q_256 : GCCBuiltin<"__builtin_ia32_pandq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_pand_q_512 : GCCBuiltin<"__builtin_ia32_pandq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pandn_d_128 : GCCBuiltin<"__builtin_ia32_pandnd128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pandn_d_256 : GCCBuiltin<"__builtin_ia32_pandnd256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pandn_d_512 : GCCBuiltin<"__builtin_ia32_pandnd512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pandn_q_128 : GCCBuiltin<"__builtin_ia32_pandnq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pandn_q_256 : GCCBuiltin<"__builtin_ia32_pandnq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pandn_q_512 : GCCBuiltin<"__builtin_ia32_pandnq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_por_d_128 : GCCBuiltin<"__builtin_ia32_pord128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_por_d_256 : GCCBuiltin<"__builtin_ia32_pord256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_por_d_512 : GCCBuiltin<"__builtin_ia32_pord512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_por_q_128 : GCCBuiltin<"__builtin_ia32_porq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_por_q_256 : GCCBuiltin<"__builtin_ia32_porq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_por_q_512 : GCCBuiltin<"__builtin_ia32_porq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pxor_d_128 : GCCBuiltin<"__builtin_ia32_pxord128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pxor_d_256 : GCCBuiltin<"__builtin_ia32_pxord256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_pxor_d_512 : GCCBuiltin<"__builtin_ia32_pxord512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pxor_q_128 : GCCBuiltin<"__builtin_ia32_pxorq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pxor_q_256 : GCCBuiltin<"__builtin_ia32_pxorq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_pxor_q_512 : GCCBuiltin<"__builtin_ia32_pxorq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; @@ -3111,43 +4621,152 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Arithmetic ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_mask_add_ps_128 : GCCBuiltin<"__builtin_ia32_addps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_ps_256 : GCCBuiltin<"__builtin_ia32_addps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_add_ps_512 : GCCBuiltin<"__builtin_ia32_addps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_pd_128 : GCCBuiltin<"__builtin_ia32_addpd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_pd_256 : GCCBuiltin<"__builtin_ia32_addpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_add_pd_512 : GCCBuiltin<"__builtin_ia32_addpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_ps_128 : GCCBuiltin<"__builtin_ia32_subps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_ps_256 : GCCBuiltin<"__builtin_ia32_subps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_sub_ps_512 : GCCBuiltin<"__builtin_ia32_subps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_pd_128 : GCCBuiltin<"__builtin_ia32_subpd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_pd_256 : GCCBuiltin<"__builtin_ia32_subpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_sub_pd_512 : GCCBuiltin<"__builtin_ia32_subpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_ps_128 : GCCBuiltin<"__builtin_ia32_mulps_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_ps_256 : GCCBuiltin<"__builtin_ia32_mulps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_mul_ps_512 : GCCBuiltin<"__builtin_ia32_mulps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_pd_128 : GCCBuiltin<"__builtin_ia32_mulpd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_pd_256 : GCCBuiltin<"__builtin_ia32_mulpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_mul_pd_512 : GCCBuiltin<"__builtin_ia32_mulpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_ps_128 : GCCBuiltin<"__builtin_ia32_divps_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_ps_256 : GCCBuiltin<"__builtin_ia32_divps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_div_ps_512 : GCCBuiltin<"__builtin_ia32_divps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_pd_128 : GCCBuiltin<"__builtin_ia32_divpd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_pd_256 : GCCBuiltin<"__builtin_ia32_divpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_div_pd_512 : GCCBuiltin<"__builtin_ia32_divpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_max_ps_128 : GCCBuiltin<"__builtin_ia32_maxps_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_max_ps_256 : GCCBuiltin<"__builtin_ia32_maxps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_max_ps_512 : GCCBuiltin<"__builtin_ia32_maxps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_max_pd_128 : GCCBuiltin<"__builtin_ia32_maxpd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_max_pd_256 : GCCBuiltin<"__builtin_ia32_maxpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_max_pd_512 : GCCBuiltin<"__builtin_ia32_maxpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_min_ps_128 : GCCBuiltin<"__builtin_ia32_minps_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_min_ps_256 : GCCBuiltin<"__builtin_ia32_minps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_min_ps_512 : GCCBuiltin<"__builtin_ia32_minps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_min_pd_128 : GCCBuiltin<"__builtin_ia32_minpd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_min_pd_256 : GCCBuiltin<"__builtin_ia32_minpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_min_pd_512 : GCCBuiltin<"__builtin_ia32_minpd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_ss_round : GCCBuiltin<"__builtin_ia32_addss_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_ss_round : GCCBuiltin<"__builtin_ia32_divss_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_ss_round : GCCBuiltin<"__builtin_ia32_mulss_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_ss_round : GCCBuiltin<"__builtin_ia32_subss_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_max_ss_round : GCCBuiltin<"__builtin_ia32_maxss_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_min_ss_round : GCCBuiltin<"__builtin_ia32_minss_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_add_sd_round : GCCBuiltin<"__builtin_ia32_addsd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_div_sd_round : GCCBuiltin<"__builtin_ia32_divsd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_mul_sd_round : GCCBuiltin<"__builtin_ia32_mulsd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sub_sd_round : GCCBuiltin<"__builtin_ia32_subsd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_max_sd_round : GCCBuiltin<"__builtin_ia32_maxsd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_min_sd_round : GCCBuiltin<"__builtin_ia32_minsd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_rndscale_ss : GCCBuiltin<"__builtin_ia32_rndscaless_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], @@ -3156,6 +4775,47 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_range_ss : GCCBuiltin<"__builtin_ia32_rangess_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_range_sd : GCCBuiltin<"__builtin_ia32_rangesd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_reduce_ss : GCCBuiltin<"__builtin_ia32_reducess_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_reduce_sd : GCCBuiltin<"__builtin_ia32_reducesd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_scalef_sd : GCCBuiltin<"__builtin_ia32_scalefsd_round">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_scalef_ss : GCCBuiltin<"__builtin_ia32_scalefss_round">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_scalef_pd_128 : GCCBuiltin<"__builtin_ia32_scalefpd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_scalef_pd_256 : GCCBuiltin<"__builtin_ia32_scalefpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty],[IntrNoMem]>; + def int_x86_avx512_mask_scalef_pd_512 : GCCBuiltin<"__builtin_ia32_scalefpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_scalef_ps_128 : GCCBuiltin<"__builtin_ia32_scalefps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_scalef_ps_256 : GCCBuiltin<"__builtin_ia32_scalefps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_scalef_ps_512 : GCCBuiltin<"__builtin_ia32_scalefps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_sqrt_ss : GCCBuiltin<"__builtin_ia32_sqrtrndss">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; @@ -3163,13 +4823,50 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_avx512_sqrt_pd_512 : GCCBuiltin<"__builtin_ia32_sqrtpd512_mask">, + def int_x86_avx512_mask_sqrt_pd_128 : GCCBuiltin<"__builtin_ia32_sqrtpd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sqrt_pd_256 : GCCBuiltin<"__builtin_ia32_sqrtpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sqrt_pd_512 : GCCBuiltin<"__builtin_ia32_sqrtpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sqrt_ps_128 : GCCBuiltin<"__builtin_ia32_sqrtps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sqrt_ps_256 : GCCBuiltin<"__builtin_ia32_sqrtps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_sqrt_ps_512 : GCCBuiltin<"__builtin_ia32_sqrtps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_getexp_pd_128 : GCCBuiltin<"__builtin_ia32_getexppd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_getexp_pd_256 : GCCBuiltin<"__builtin_ia32_getexppd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_getexp_pd_512 : GCCBuiltin<"__builtin_ia32_getexppd512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_sqrt_ps_512 : GCCBuiltin<"__builtin_ia32_sqrtps512_mask">, + def int_x86_avx512_mask_getexp_ps_128 : GCCBuiltin<"__builtin_ia32_getexpps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_getexp_ps_256 : GCCBuiltin<"__builtin_ia32_getexpps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_getexp_ps_512 : GCCBuiltin<"__builtin_ia32_getexpps512_mask">, Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_getexp_ss : GCCBuiltin<"__builtin_ia32_getexpss_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_getexp_sd : GCCBuiltin<"__builtin_ia32_getexpsd_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_rsqrt14_ss : GCCBuiltin<"__builtin_ia32_rsqrt14ss_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; @@ -3235,28 +4932,341 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_v2f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; } - +// FP logical ops +let TargetPrefix = "x86" in { + def int_x86_avx512_mask_and_pd_128 : GCCBuiltin<"__builtin_ia32_andpd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_and_pd_256 : GCCBuiltin<"__builtin_ia32_andpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_and_pd_512 : GCCBuiltin<"__builtin_ia32_andpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_and_ps_128 : GCCBuiltin<"__builtin_ia32_andps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_and_ps_256 : GCCBuiltin<"__builtin_ia32_andps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_and_ps_512 : GCCBuiltin<"__builtin_ia32_andps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_andn_pd_128 : GCCBuiltin<"__builtin_ia32_andnpd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_andn_pd_256 : GCCBuiltin<"__builtin_ia32_andnpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_andn_pd_512 : GCCBuiltin<"__builtin_ia32_andnpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_andn_ps_128 : GCCBuiltin<"__builtin_ia32_andnps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_andn_ps_256 : GCCBuiltin<"__builtin_ia32_andnps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_andn_ps_512 : GCCBuiltin<"__builtin_ia32_andnps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_or_pd_128 : GCCBuiltin<"__builtin_ia32_orpd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_or_pd_256 : GCCBuiltin<"__builtin_ia32_orpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_or_pd_512 : GCCBuiltin<"__builtin_ia32_orpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_or_ps_128 : GCCBuiltin<"__builtin_ia32_orps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_or_ps_256 : GCCBuiltin<"__builtin_ia32_orps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_or_ps_512 : GCCBuiltin<"__builtin_ia32_orps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_xor_pd_128 : GCCBuiltin<"__builtin_ia32_xorpd128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_xor_pd_256 : GCCBuiltin<"__builtin_ia32_xorpd256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_xor_pd_512 : GCCBuiltin<"__builtin_ia32_xorpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_xor_ps_128 : GCCBuiltin<"__builtin_ia32_xorps128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_xor_ps_256 : GCCBuiltin<"__builtin_ia32_xorps256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_xor_ps_512 : GCCBuiltin<"__builtin_ia32_xorps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; +} // Integer arithmetic ops let TargetPrefix = "x86" in { + def int_x86_avx512_mask_padd_b_128 : GCCBuiltin<"__builtin_ia32_paddb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_b_256 : GCCBuiltin<"__builtin_ia32_paddb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_b_512 : GCCBuiltin<"__builtin_ia32_paddb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_w_128 : GCCBuiltin<"__builtin_ia32_paddw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_w_256 : GCCBuiltin<"__builtin_ia32_paddw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_w_512 : GCCBuiltin<"__builtin_ia32_paddw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padds_b_128 : GCCBuiltin<"__builtin_ia32_paddsb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padds_b_256 : GCCBuiltin<"__builtin_ia32_paddsb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padds_b_512 : GCCBuiltin<"__builtin_ia32_paddsb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padds_w_128 : GCCBuiltin<"__builtin_ia32_paddsw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padds_w_256 : GCCBuiltin<"__builtin_ia32_paddsw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padds_w_512 : GCCBuiltin<"__builtin_ia32_paddsw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_paddus_b_128 : GCCBuiltin<"__builtin_ia32_paddusb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_paddus_b_256 : GCCBuiltin<"__builtin_ia32_paddusb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_paddus_b_512 : GCCBuiltin<"__builtin_ia32_paddusb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_paddus_w_128 : GCCBuiltin<"__builtin_ia32_paddusw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_paddus_w_256 : GCCBuiltin<"__builtin_ia32_paddusw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_paddus_w_512 : GCCBuiltin<"__builtin_ia32_paddusw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_d_128 : GCCBuiltin<"__builtin_ia32_paddd128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_d_256 : GCCBuiltin<"__builtin_ia32_paddd256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_padd_d_512 : GCCBuiltin<"__builtin_ia32_paddd512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_q_128 : GCCBuiltin<"__builtin_ia32_paddq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_q_256 : GCCBuiltin<"__builtin_ia32_paddq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_padd_q_512 : GCCBuiltin<"__builtin_ia32_paddq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_b_128 : GCCBuiltin<"__builtin_ia32_psubb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_b_256 : GCCBuiltin<"__builtin_ia32_psubb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_b_512 : GCCBuiltin<"__builtin_ia32_psubb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_w_128 : GCCBuiltin<"__builtin_ia32_psubw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_w_256 : GCCBuiltin<"__builtin_ia32_psubw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_w_512 : GCCBuiltin<"__builtin_ia32_psubw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubs_b_128 : GCCBuiltin<"__builtin_ia32_psubsb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubs_b_256 : GCCBuiltin<"__builtin_ia32_psubsb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubs_b_512 : GCCBuiltin<"__builtin_ia32_psubsb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubs_w_128 : GCCBuiltin<"__builtin_ia32_psubsw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubs_w_256 : GCCBuiltin<"__builtin_ia32_psubsw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubs_w_512 : GCCBuiltin<"__builtin_ia32_psubsw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubus_b_128 : GCCBuiltin<"__builtin_ia32_psubusb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubus_b_256 : GCCBuiltin<"__builtin_ia32_psubusb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubus_b_512 : GCCBuiltin<"__builtin_ia32_psubusb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubus_w_128 : GCCBuiltin<"__builtin_ia32_psubusw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubus_w_256 : GCCBuiltin<"__builtin_ia32_psubusw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psubus_w_512 : GCCBuiltin<"__builtin_ia32_psubusw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_d_128 : GCCBuiltin<"__builtin_ia32_psubd128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_d_256 : GCCBuiltin<"__builtin_ia32_psubd256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_psub_d_512 : GCCBuiltin<"__builtin_ia32_psubd512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_q_128 : GCCBuiltin<"__builtin_ia32_psubq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_q_256 : GCCBuiltin<"__builtin_ia32_psubq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_psub_q_512 : GCCBuiltin<"__builtin_ia32_psubq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulu_dq_128 : GCCBuiltin<"__builtin_ia32_pmuludq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmul_dq_128 : GCCBuiltin<"__builtin_ia32_pmuldq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulu_dq_256 : GCCBuiltin<"__builtin_ia32_pmuludq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmul_dq_256 : GCCBuiltin<"__builtin_ia32_pmuldq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_pmulu_dq_512 : GCCBuiltin<"__builtin_ia32_pmuludq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_pmul_dq_512 : GCCBuiltin<"__builtin_ia32_pmuldq512_mask">, Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_w_128 : GCCBuiltin<"__builtin_ia32_pmullw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_w_256 : GCCBuiltin<"__builtin_ia32_pmullw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_w_512 : GCCBuiltin<"__builtin_ia32_pmullw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_d_128 : GCCBuiltin<"__builtin_ia32_pmulld128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_d_256 : GCCBuiltin<"__builtin_ia32_pmulld256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_d_512 : GCCBuiltin<"__builtin_ia32_pmulld512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_q_128 : GCCBuiltin<"__builtin_ia32_pmullq128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_q_256 : GCCBuiltin<"__builtin_ia32_pmullq256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmull_q_512 : GCCBuiltin<"__builtin_ia32_pmullq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulhu_w_512 : GCCBuiltin<"__builtin_ia32_pmulhuw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulh_w_512 : GCCBuiltin<"__builtin_ia32_pmulhw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulhu_w_128 : GCCBuiltin<"__builtin_ia32_pmulhuw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulhu_w_256 : GCCBuiltin<"__builtin_ia32_pmulhuw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulh_w_128 : GCCBuiltin<"__builtin_ia32_pmulhw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulh_w_256 : GCCBuiltin<"__builtin_ia32_pmulhw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pavg_b_512 : GCCBuiltin<"__builtin_ia32_pavgb512_mask">, + Intrinsic<[llvm_v64i8_ty], [llvm_v64i8_ty, llvm_v64i8_ty, + llvm_v64i8_ty, llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pavg_w_512 : GCCBuiltin<"__builtin_ia32_pavgw512_mask">, + Intrinsic<[llvm_v32i16_ty], [llvm_v32i16_ty, llvm_v32i16_ty, + llvm_v32i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pavg_b_128 : GCCBuiltin<"__builtin_ia32_pavgb128_mask">, + Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pavg_b_256 : GCCBuiltin<"__builtin_ia32_pavgb256_mask">, + Intrinsic<[llvm_v32i8_ty], [llvm_v32i8_ty, llvm_v32i8_ty, + llvm_v32i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pavg_w_128 : GCCBuiltin<"__builtin_ia32_pavgw128_mask">, + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pavg_w_256 : GCCBuiltin<"__builtin_ia32_pavgw256_mask">, + Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, + llvm_v16i16_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmaddw_d_128 : + GCCBuiltin<"__builtin_ia32_pmaddwd128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmaddw_d_256 : + GCCBuiltin<"__builtin_ia32_pmaddwd256_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v16i16_ty, llvm_v16i16_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmaddw_d_512 : + GCCBuiltin<"__builtin_ia32_pmaddwd512_mask">, + Intrinsic<[llvm_v16i32_ty], + [llvm_v32i16_ty, llvm_v32i16_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmaddubs_w_128 : + GCCBuiltin<"__builtin_ia32_pmaddubsw128_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmaddubs_w_256 : + GCCBuiltin<"__builtin_ia32_pmaddubsw256_mask">, + Intrinsic<[llvm_v16i16_ty], + [llvm_v32i8_ty, llvm_v32i8_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmaddubs_w_512 : + GCCBuiltin<"__builtin_ia32_pmaddubsw512_mask">, + Intrinsic<[llvm_v32i16_ty], + [llvm_v64i8_ty, llvm_v64i8_ty, llvm_v32i16_ty, llvm_i32_ty], + [IntrNoMem]>; } + // Gather and Scatter ops let TargetPrefix = "x86" in { def int_x86_avx512_gather_dpd_512 : GCCBuiltin<"__builtin_ia32_gathersiv8df">, @@ -3294,6 +5304,102 @@ let TargetPrefix = "x86" in { llvm_v8i64_ty, llvm_i8_ty, llvm_i32_ty], [IntrReadArgMem]>; + def int_x86_avx512_gather3div2_df : + GCCBuiltin<"__builtin_ia32_gather3div2df">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrReadArgMem]>; + + def int_x86_avx512_gather3div2_di : + GCCBuiltin<"__builtin_ia32_gather3div2di">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v2i64_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrReadArgMem]>; + + def int_x86_avx512_gather3div4_df : + GCCBuiltin<"__builtin_ia32_gather3div4df">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrReadArgMem]>; + + def int_x86_avx512_gather3div4_di : + GCCBuiltin<"__builtin_ia32_gather3div4di">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrReadArgMem]>; + + def int_x86_avx512_gather3div4_sf : + GCCBuiltin<"__builtin_ia32_gather3div4sf">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrReadArgMem]>; + + def int_x86_avx512_gather3div4_si : + GCCBuiltin<"__builtin_ia32_gather3div4si">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrReadArgMem]>; + + def int_x86_avx512_gather3div8_sf : + GCCBuiltin<"__builtin_ia32_gather3div8sf">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrReadArgMem]>; + + def int_x86_avx512_gather3div8_si : + GCCBuiltin<"__builtin_ia32_gather3div8si">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty, llvm_i32_ty], + [IntrReadArgMem]>; + + def int_x86_avx512_gather3siv2_df : + GCCBuiltin<"__builtin_ia32_gather3siv2df">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], + [IntrReadArgMem]>; + + def int_x86_avx512_gather3siv2_di : + GCCBuiltin<"__builtin_ia32_gather3siv2di">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v2i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], + [IntrReadArgMem]>; + + def int_x86_avx512_gather3siv4_df : + GCCBuiltin<"__builtin_ia32_gather3siv4df">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], + [IntrReadArgMem]>; + + def int_x86_avx512_gather3siv4_di : + GCCBuiltin<"__builtin_ia32_gather3siv4di">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v4i64_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], + [IntrReadArgMem]>; + + def int_x86_avx512_gather3siv4_sf : + GCCBuiltin<"__builtin_ia32_gather3siv4sf">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], + [IntrReadArgMem]>; + + def int_x86_avx512_gather3siv4_si : + GCCBuiltin<"__builtin_ia32_gather3siv4si">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty, llvm_i32_ty], + [IntrReadArgMem]>; + + def int_x86_avx512_gather3siv8_sf : + GCCBuiltin<"__builtin_ia32_gather3siv8sf">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], + [IntrReadArgMem]>; + + def int_x86_avx512_gather3siv8_si : + GCCBuiltin<"__builtin_ia32_gather3siv8si">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8i32_ty, llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty, llvm_i32_ty], + [IntrReadArgMem]>; + // scatter def int_x86_avx512_scatter_dpd_512 : GCCBuiltin<"__builtin_ia32_scattersiv8df">, Intrinsic<[], [llvm_ptr_ty, llvm_i8_ty, @@ -3330,6 +5436,102 @@ let TargetPrefix = "x86" in { llvm_i32_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_scatterdiv2_df : + GCCBuiltin<"__builtin_ia32_scatterdiv2df">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i8_ty, llvm_v2i64_ty, llvm_v2f64_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scatterdiv2_di : + GCCBuiltin<"__builtin_ia32_scatterdiv2di">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i8_ty, llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scatterdiv4_df : + GCCBuiltin<"__builtin_ia32_scatterdiv4df">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i8_ty, llvm_v4i64_ty, llvm_v4f64_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scatterdiv4_di : + GCCBuiltin<"__builtin_ia32_scatterdiv4di">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i8_ty, llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scatterdiv4_sf : + GCCBuiltin<"__builtin_ia32_scatterdiv4sf">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i8_ty, llvm_v2i64_ty, llvm_v4f32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scatterdiv4_si : + GCCBuiltin<"__builtin_ia32_scatterdiv4si">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i8_ty, llvm_v2i64_ty, llvm_v4i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scatterdiv8_sf : + GCCBuiltin<"__builtin_ia32_scatterdiv8sf">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i8_ty, llvm_v4i64_ty, llvm_v4f32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scatterdiv8_si : + GCCBuiltin<"__builtin_ia32_scatterdiv8si">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i8_ty, llvm_v4i64_ty, llvm_v4i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scattersiv2_df : + GCCBuiltin<"__builtin_ia32_scattersiv2df">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v2f64_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scattersiv2_di : + GCCBuiltin<"__builtin_ia32_scattersiv2di">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v2i64_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scattersiv4_df : + GCCBuiltin<"__builtin_ia32_scattersiv4df">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v4f64_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scattersiv4_di : + GCCBuiltin<"__builtin_ia32_scattersiv4di">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v4i64_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scattersiv4_sf : + GCCBuiltin<"__builtin_ia32_scattersiv4sf">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v4f32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scattersiv4_si : + GCCBuiltin<"__builtin_ia32_scattersiv4si">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i8_ty, llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scattersiv8_sf : + GCCBuiltin<"__builtin_ia32_scattersiv8sf">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i8_ty, llvm_v8i32_ty, llvm_v8f32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + + def int_x86_avx512_scattersiv8_si : + GCCBuiltin<"__builtin_ia32_scattersiv8si">, + Intrinsic<[], + [llvm_ptr_ty, llvm_i8_ty, llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + // gather prefetch def int_x86_avx512_gatherpf_dpd_512 : GCCBuiltin<"__builtin_ia32_gatherpfdpd">, Intrinsic<[], [llvm_i8_ty, llvm_v8i32_ty, llvm_ptr_ty, @@ -3504,29 +5706,29 @@ let TargetPrefix = "x86" in { [IntrNoMem]>; def int_x86_avx512_mask_cmp_b_512: GCCBuiltin<"__builtin_ia32_cmpb512_mask">, - Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i8_ty, + Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty, llvm_i64_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_w_512: GCCBuiltin<"__builtin_ia32_cmpw512_mask">, - Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i8_ty, + Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_d_512: GCCBuiltin<"__builtin_ia32_cmpd512_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i8_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty, llvm_i16_ty], [IntrNoMem ]>; def int_x86_avx512_mask_cmp_q_512: GCCBuiltin<"__builtin_ia32_cmpq512_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_b_512: GCCBuiltin<"__builtin_ia32_ucmpb512_mask">, - Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i8_ty, + Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty, llvm_i64_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_w_512: GCCBuiltin<"__builtin_ia32_ucmpw512_mask">, - Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i8_ty, + Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_d_512: GCCBuiltin<"__builtin_ia32_ucmpd512_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i8_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_q_512: GCCBuiltin<"__builtin_ia32_ucmpq512_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; // 256-bit @@ -3557,29 +5759,29 @@ let TargetPrefix = "x86" in { [IntrNoMem]>; def int_x86_avx512_mask_cmp_b_256: GCCBuiltin<"__builtin_ia32_cmpb256_mask">, - Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i8_ty, + Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_w_256: GCCBuiltin<"__builtin_ia32_cmpw256_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i8_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_d_256: GCCBuiltin<"__builtin_ia32_cmpd256_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_q_256: GCCBuiltin<"__builtin_ia32_cmpq256_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty, + Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_b_256: GCCBuiltin<"__builtin_ia32_ucmpb256_mask">, - Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i8_ty, + Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_w_256: GCCBuiltin<"__builtin_ia32_ucmpw256_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i8_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_d_256: GCCBuiltin<"__builtin_ia32_ucmpd256_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_q_256: GCCBuiltin<"__builtin_ia32_ucmpq256_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty, + Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; // 128-bit @@ -3610,29 +5812,29 @@ let TargetPrefix = "x86" in { [IntrNoMem]>; def int_x86_avx512_mask_cmp_b_128: GCCBuiltin<"__builtin_ia32_cmpb128_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_w_128: GCCBuiltin<"__builtin_ia32_cmpw128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_d_128: GCCBuiltin<"__builtin_ia32_cmpd128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty, + Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_cmp_q_128: GCCBuiltin<"__builtin_ia32_cmpq128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty, + Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_b_128: GCCBuiltin<"__builtin_ia32_ucmpb128_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty, + Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, llvm_i16_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_w_128: GCCBuiltin<"__builtin_ia32_ucmpw128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty, + Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_d_128: GCCBuiltin<"__builtin_ia32_ucmpd128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty, + Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx512_mask_ucmp_q_128: GCCBuiltin<"__builtin_ia32_ucmpq128_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty, + Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; } @@ -3840,15 +6042,579 @@ let TargetPrefix = "x86" in { llvm_i8_ty], [IntrReadArgMem]>; } + +// truncate +let TargetPrefix = "x86" in { + def int_x86_avx512_mask_pmov_qb_128 : + GCCBuiltin<"__builtin_ia32_pmovqb128_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v2i64_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmov_qb_mem_128 : + GCCBuiltin<"__builtin_ia32_pmovqb128mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovs_qb_128 : + GCCBuiltin<"__builtin_ia32_pmovsqb128_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v2i64_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovs_qb_mem_128 : + GCCBuiltin<"__builtin_ia32_pmovsqb128mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovus_qb_128 : + GCCBuiltin<"__builtin_ia32_pmovusqb128_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v2i64_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovus_qb_mem_128 : + GCCBuiltin<"__builtin_ia32_pmovusqb128mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmov_qb_256 : + GCCBuiltin<"__builtin_ia32_pmovqb256_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v4i64_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmov_qb_mem_256 : + GCCBuiltin<"__builtin_ia32_pmovqb256mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovs_qb_256 : + GCCBuiltin<"__builtin_ia32_pmovsqb256_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v4i64_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovs_qb_mem_256 : + GCCBuiltin<"__builtin_ia32_pmovsqb256mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovus_qb_256 : + GCCBuiltin<"__builtin_ia32_pmovusqb256_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v4i64_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovus_qb_mem_256 : + GCCBuiltin<"__builtin_ia32_pmovusqb256mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmov_qb_512 : + GCCBuiltin<"__builtin_ia32_pmovqb512_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v8i64_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmov_qb_mem_512 : + GCCBuiltin<"__builtin_ia32_pmovqb512mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovs_qb_512 : + GCCBuiltin<"__builtin_ia32_pmovsqb512_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v8i64_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovs_qb_mem_512 : + GCCBuiltin<"__builtin_ia32_pmovsqb512mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovus_qb_512 : + GCCBuiltin<"__builtin_ia32_pmovusqb512_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v8i64_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovus_qb_mem_512 : + GCCBuiltin<"__builtin_ia32_pmovusqb512mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmov_qw_128 : + GCCBuiltin<"__builtin_ia32_pmovqw128_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v2i64_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmov_qw_mem_128 : + GCCBuiltin<"__builtin_ia32_pmovqw128mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovs_qw_128 : + GCCBuiltin<"__builtin_ia32_pmovsqw128_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v2i64_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovs_qw_mem_128 : + GCCBuiltin<"__builtin_ia32_pmovsqw128mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovus_qw_128 : + GCCBuiltin<"__builtin_ia32_pmovusqw128_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v2i64_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovus_qw_mem_128 : + GCCBuiltin<"__builtin_ia32_pmovusqw128mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmov_qw_256 : + GCCBuiltin<"__builtin_ia32_pmovqw256_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v4i64_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmov_qw_mem_256 : + GCCBuiltin<"__builtin_ia32_pmovqw256mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovs_qw_256 : + GCCBuiltin<"__builtin_ia32_pmovsqw256_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v4i64_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovs_qw_mem_256 : + GCCBuiltin<"__builtin_ia32_pmovsqw256mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovus_qw_256 : + GCCBuiltin<"__builtin_ia32_pmovusqw256_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v4i64_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovus_qw_mem_256 : + GCCBuiltin<"__builtin_ia32_pmovusqw256mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmov_qw_512 : + GCCBuiltin<"__builtin_ia32_pmovqw512_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i64_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmov_qw_mem_512 : + GCCBuiltin<"__builtin_ia32_pmovqw512mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovs_qw_512 : + GCCBuiltin<"__builtin_ia32_pmovsqw512_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i64_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovs_qw_mem_512 : + GCCBuiltin<"__builtin_ia32_pmovsqw512mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovus_qw_512 : + GCCBuiltin<"__builtin_ia32_pmovusqw512_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i64_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovus_qw_mem_512 : + GCCBuiltin<"__builtin_ia32_pmovusqw512mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmov_qd_128 : + GCCBuiltin<"__builtin_ia32_pmovqd128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v2i64_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmov_qd_mem_128 : + GCCBuiltin<"__builtin_ia32_pmovqd128mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovs_qd_128 : + GCCBuiltin<"__builtin_ia32_pmovsqd128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v2i64_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovs_qd_mem_128 : + GCCBuiltin<"__builtin_ia32_pmovsqd128mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovus_qd_128 : + GCCBuiltin<"__builtin_ia32_pmovusqd128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v2i64_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovus_qd_mem_128 : + GCCBuiltin<"__builtin_ia32_pmovusqd128mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmov_qd_256 : + GCCBuiltin<"__builtin_ia32_pmovqd256_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i64_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmov_qd_mem_256 : + GCCBuiltin<"__builtin_ia32_pmovqd256mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovs_qd_256 : + GCCBuiltin<"__builtin_ia32_pmovsqd256_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i64_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovs_qd_mem_256 : + GCCBuiltin<"__builtin_ia32_pmovsqd256mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovus_qd_256 : + GCCBuiltin<"__builtin_ia32_pmovusqd256_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i64_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovus_qd_mem_256 : + GCCBuiltin<"__builtin_ia32_pmovusqd256mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmov_qd_512 : + GCCBuiltin<"__builtin_ia32_pmovqd512_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8i64_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmov_qd_mem_512 : + GCCBuiltin<"__builtin_ia32_pmovqd512mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovs_qd_512 : + GCCBuiltin<"__builtin_ia32_pmovsqd512_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8i64_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovs_qd_mem_512 : + GCCBuiltin<"__builtin_ia32_pmovsqd512mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovus_qd_512 : + GCCBuiltin<"__builtin_ia32_pmovusqd512_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8i64_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovus_qd_mem_512 : + GCCBuiltin<"__builtin_ia32_pmovusqd512mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmov_db_128 : + GCCBuiltin<"__builtin_ia32_pmovdb128_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v4i32_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmov_db_mem_128 : + GCCBuiltin<"__builtin_ia32_pmovdb128mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovs_db_128 : + GCCBuiltin<"__builtin_ia32_pmovsdb128_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v4i32_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovs_db_mem_128 : + GCCBuiltin<"__builtin_ia32_pmovsdb128mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovus_db_128 : + GCCBuiltin<"__builtin_ia32_pmovusdb128_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v4i32_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovus_db_mem_128 : + GCCBuiltin<"__builtin_ia32_pmovusdb128mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmov_db_256 : + GCCBuiltin<"__builtin_ia32_pmovdb256_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v8i32_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmov_db_mem_256 : + GCCBuiltin<"__builtin_ia32_pmovdb256mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovs_db_256 : + GCCBuiltin<"__builtin_ia32_pmovsdb256_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v8i32_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovs_db_mem_256 : + GCCBuiltin<"__builtin_ia32_pmovsdb256mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovus_db_256 : + GCCBuiltin<"__builtin_ia32_pmovusdb256_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v8i32_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovus_db_mem_256 : + GCCBuiltin<"__builtin_ia32_pmovusdb256mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmov_db_512 : + GCCBuiltin<"__builtin_ia32_pmovdb512_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i32_ty, llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmov_db_mem_512 : + GCCBuiltin<"__builtin_ia32_pmovdb512mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovs_db_512 : + GCCBuiltin<"__builtin_ia32_pmovsdb512_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i32_ty, llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovs_db_mem_512 : + GCCBuiltin<"__builtin_ia32_pmovsdb512mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovus_db_512 : + GCCBuiltin<"__builtin_ia32_pmovusdb512_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i32_ty, llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovus_db_mem_512 : + GCCBuiltin<"__builtin_ia32_pmovusdb512mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmov_dw_128 : + GCCBuiltin<"__builtin_ia32_pmovdw128_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v4i32_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmov_dw_mem_128 : + GCCBuiltin<"__builtin_ia32_pmovdw128mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovs_dw_128 : + GCCBuiltin<"__builtin_ia32_pmovsdw128_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v4i32_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovs_dw_mem_128 : + GCCBuiltin<"__builtin_ia32_pmovsdw128mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovus_dw_128 : + GCCBuiltin<"__builtin_ia32_pmovusdw128_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v4i32_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovus_dw_mem_128 : + GCCBuiltin<"__builtin_ia32_pmovusdw128mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmov_dw_256 : + GCCBuiltin<"__builtin_ia32_pmovdw256_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i32_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmov_dw_mem_256 : + GCCBuiltin<"__builtin_ia32_pmovdw256mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovs_dw_256 : + GCCBuiltin<"__builtin_ia32_pmovsdw256_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i32_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovs_dw_mem_256 : + GCCBuiltin<"__builtin_ia32_pmovsdw256mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovus_dw_256 : + GCCBuiltin<"__builtin_ia32_pmovusdw256_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i32_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovus_dw_mem_256 : + GCCBuiltin<"__builtin_ia32_pmovusdw256mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmov_dw_512 : + GCCBuiltin<"__builtin_ia32_pmovdw512_mask">, + Intrinsic<[llvm_v16i16_ty], + [llvm_v16i32_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmov_dw_mem_512 : + GCCBuiltin<"__builtin_ia32_pmovdw512mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovs_dw_512 : + GCCBuiltin<"__builtin_ia32_pmovsdw512_mask">, + Intrinsic<[llvm_v16i16_ty], + [llvm_v16i32_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovs_dw_mem_512 : + GCCBuiltin<"__builtin_ia32_pmovsdw512mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovus_dw_512 : + GCCBuiltin<"__builtin_ia32_pmovusdw512_mask">, + Intrinsic<[llvm_v16i16_ty], + [llvm_v16i32_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovus_dw_mem_512 : + GCCBuiltin<"__builtin_ia32_pmovusdw512mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmov_wb_128 : + GCCBuiltin<"__builtin_ia32_pmovwb128_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v8i16_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmov_wb_mem_128 : + GCCBuiltin<"__builtin_ia32_pmovwb128mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovs_wb_128 : + GCCBuiltin<"__builtin_ia32_pmovswb128_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v8i16_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovs_wb_mem_128 : + GCCBuiltin<"__builtin_ia32_pmovswb128mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovus_wb_128 : + GCCBuiltin<"__builtin_ia32_pmovuswb128_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v8i16_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovus_wb_mem_128 : + GCCBuiltin<"__builtin_ia32_pmovuswb128mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmov_wb_256 : + GCCBuiltin<"__builtin_ia32_pmovwb256_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i16_ty, llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmov_wb_mem_256 : + GCCBuiltin<"__builtin_ia32_pmovwb256mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovs_wb_256 : + GCCBuiltin<"__builtin_ia32_pmovswb256_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i16_ty, llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovs_wb_mem_256 : + GCCBuiltin<"__builtin_ia32_pmovswb256mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovus_wb_256 : + GCCBuiltin<"__builtin_ia32_pmovuswb256_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i16_ty, llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovus_wb_mem_256 : + GCCBuiltin<"__builtin_ia32_pmovuswb256mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmov_wb_512 : + GCCBuiltin<"__builtin_ia32_pmovwb512_mask">, + Intrinsic<[llvm_v32i8_ty], + [llvm_v32i16_ty, llvm_v32i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmov_wb_mem_512 : + GCCBuiltin<"__builtin_ia32_pmovwb512mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v32i16_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovs_wb_512 : + GCCBuiltin<"__builtin_ia32_pmovswb512_mask">, + Intrinsic<[llvm_v32i8_ty], + [llvm_v32i16_ty, llvm_v32i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovs_wb_mem_512 : + GCCBuiltin<"__builtin_ia32_pmovswb512mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v32i16_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_pmovus_wb_512 : + GCCBuiltin<"__builtin_ia32_pmovuswb512_mask">, + Intrinsic<[llvm_v32i8_ty], + [llvm_v32i16_ty, llvm_v32i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pmovus_wb_mem_512 : + GCCBuiltin<"__builtin_ia32_pmovuswb512mem_mask">, + Intrinsic<[], + [llvm_ptr_ty, llvm_v32i16_ty, llvm_i32_ty], + [IntrReadWriteArgMem]>; +} // Misc. let TargetPrefix = "x86" in { - def int_x86_avx512_mask_cmp_ps_512 : GCCBuiltin<"__builtin_ia32_cmpps512_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i8_ty, - llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_cmp_pd_512 : GCCBuiltin<"__builtin_ia32_cmppd512_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, - llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa512">, + def int_x86_avx512_mask_cmp_ps_512 : + GCCBuiltin<"__builtin_ia32_cmpps512_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i32_ty, llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_pd_512 : + GCCBuiltin<"__builtin_ia32_cmppd512_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_ps_256 : + GCCBuiltin<"__builtin_ia32_cmpps256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_pd_256 : + GCCBuiltin<"__builtin_ia32_cmppd256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_ps_128 : + GCCBuiltin<"__builtin_ia32_cmpps128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_pd_128 : + GCCBuiltin<"__builtin_ia32_cmppd128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i32_ty, llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_movntdqa : + GCCBuiltin<"__builtin_ia32_movntdqa512">, Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty], [IntrReadMem]>; } diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h index 8c04b08c4fa..e6c22090ab6 100644 --- a/include/llvm/IR/LLVMContext.h +++ b/include/llvm/IR/LLVMContext.h @@ -58,7 +58,9 @@ class LLVMContext { MD_noalias = 8, // "noalias", MD_nontemporal = 9, // "nontemporal" MD_mem_parallel_loop_access = 10, // "llvm.mem.parallel_loop_access" - MD_nonnull = 11 // "nonnull" + MD_nonnull = 11, // "nonnull" + MD_dereferenceable = 12, // "dereferenceable" + MD_dereferenceable_or_null = 13 // "dereferenceable_or_null" }; /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. diff --git a/include/llvm/IR/MDBuilder.h b/include/llvm/IR/MDBuilder.h index 51b8b02d8e6..ceb1c736e5c 100644 --- a/include/llvm/IR/MDBuilder.h +++ b/include/llvm/IR/MDBuilder.h @@ -60,6 +60,9 @@ class MDBuilder { /// \brief Return metadata containing a number of branch weights. MDNode *createBranchWeights(ArrayRef Weights); + /// Return metadata containing the entry count for a function. + MDNode *createFunctionEntryCount(uint64_t Count); + //===------------------------------------------------------------------===// // Range metadata. //===------------------------------------------------------------------===// @@ -150,7 +153,7 @@ class MDBuilder { /// \brief Return metadata for a TBAA tag node with the given /// base type, access type and offset relative to the base type. MDNode *createTBAAStructTagNode(MDNode *BaseType, MDNode *AccessType, - uint64_t Offset); + uint64_t Offset, bool IsConstant = false); }; } // end namespace llvm diff --git a/include/llvm/IR/Mangler.h b/include/llvm/IR/Mangler.h index 1e6b5b1dca0..b72b259097c 100644 --- a/include/llvm/IR/Mangler.h +++ b/include/llvm/IR/Mangler.h @@ -25,28 +25,15 @@ template class SmallVectorImpl; class Twine; class Mangler { -public: - enum ManglerPrefixTy { - Default, ///< Emit default string before each symbol. - Private, ///< Emit "private" prefix before each symbol. - LinkerPrivate ///< Emit "linker private" prefix before each symbol. - }; - -private: - const DataLayout *DL; - - /// AnonGlobalIDs - We need to give global values the same name every time - /// they are mangled. This keeps track of the number we give to anonymous - /// ones. - /// + /// We need to give global values the same name every time they are mangled. + /// This keeps track of the number we give to anonymous ones. mutable DenseMap AnonGlobalIDs; - /// NextAnonGlobalID - This simple counter is used to unique value names. - /// + /// This simple counter is used to unique value names. mutable unsigned NextAnonGlobalID; public: - Mangler(const DataLayout *DL) : DL(DL), NextAnonGlobalID(1) {} + Mangler() : NextAnonGlobalID(1) {} /// Print the appropriate prefix and the specified global variable's name. /// If the global variable doesn't have a name, this fills in a unique name @@ -58,10 +45,10 @@ class Mangler { /// Print the appropriate prefix and the specified name as the global variable /// name. GVName must not be empty. - void getNameWithPrefix(raw_ostream &OS, const Twine &GVName, - ManglerPrefixTy PrefixTy = Mangler::Default) const; - void getNameWithPrefix(SmallVectorImpl &OutName, const Twine &GVName, - ManglerPrefixTy PrefixTy = Mangler::Default) const; + static void getNameWithPrefix(raw_ostream &OS, const Twine &GVName, + const DataLayout &DL); + static void getNameWithPrefix(SmallVectorImpl &OutName, + const Twine &GVName, const DataLayout &DL); }; } // End llvm namespace diff --git a/include/llvm/IR/Metadata.def b/include/llvm/IR/Metadata.def index 0eb29bcad14..c88c87e4e48 100644 --- a/include/llvm/IR/Metadata.def +++ b/include/llvm/IR/Metadata.def @@ -60,36 +60,35 @@ HANDLE_METADATA_LEAF(ConstantAsMetadata) HANDLE_METADATA_LEAF(LocalAsMetadata) HANDLE_MDNODE_BRANCH(MDNode) HANDLE_MDNODE_LEAF(MDTuple) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDLocation) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDExpression) -HANDLE_SPECIALIZED_MDNODE_BRANCH(DebugNode) -HANDLE_SPECIALIZED_MDNODE_LEAF(GenericDebugNode) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDSubrange) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDEnumerator) -HANDLE_SPECIALIZED_MDNODE_BRANCH(MDScope) -HANDLE_SPECIALIZED_MDNODE_BRANCH(MDType) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDBasicType) -HANDLE_SPECIALIZED_MDNODE_BRANCH(MDDerivedTypeBase) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDDerivedType) -HANDLE_SPECIALIZED_MDNODE_BRANCH(MDCompositeTypeBase) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDCompositeType) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDSubroutineType) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDFile) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDCompileUnit) -HANDLE_SPECIALIZED_MDNODE_BRANCH(MDLocalScope) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDSubprogram) -HANDLE_SPECIALIZED_MDNODE_BRANCH(MDLexicalBlockBase) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDLexicalBlock) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDLexicalBlockFile) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDNamespace) -HANDLE_SPECIALIZED_MDNODE_BRANCH(MDTemplateParameter) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDTemplateTypeParameter) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDTemplateValueParameter) -HANDLE_SPECIALIZED_MDNODE_BRANCH(MDVariable) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDGlobalVariable) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDLocalVariable) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDObjCProperty) -HANDLE_SPECIALIZED_MDNODE_LEAF(MDImportedEntity) +HANDLE_SPECIALIZED_MDNODE_LEAF(DILocation) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIExpression) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DINode) +HANDLE_SPECIALIZED_MDNODE_LEAF(GenericDINode) +HANDLE_SPECIALIZED_MDNODE_LEAF(DISubrange) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIEnumerator) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DIScope) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DIType) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIBasicType) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIDerivedType) +HANDLE_SPECIALIZED_MDNODE_LEAF(DICompositeType) +HANDLE_SPECIALIZED_MDNODE_LEAF(DISubroutineType) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIFile) +HANDLE_SPECIALIZED_MDNODE_LEAF(DICompileUnit) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DILocalScope) +HANDLE_SPECIALIZED_MDNODE_LEAF(DISubprogram) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DILexicalBlockBase) +HANDLE_SPECIALIZED_MDNODE_LEAF(DILexicalBlock) +HANDLE_SPECIALIZED_MDNODE_LEAF(DILexicalBlockFile) +HANDLE_SPECIALIZED_MDNODE_LEAF(DINamespace) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIModule) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DITemplateParameter) +HANDLE_SPECIALIZED_MDNODE_LEAF(DITemplateTypeParameter) +HANDLE_SPECIALIZED_MDNODE_LEAF(DITemplateValueParameter) +HANDLE_SPECIALIZED_MDNODE_BRANCH(DIVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIGlobalVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF(DILocalVariable) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIObjCProperty) +HANDLE_SPECIALIZED_MDNODE_LEAF(DIImportedEntity) #undef HANDLE_METADATA #undef HANDLE_METADATA_LEAF diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index 03e70fe2671..c639625bf16 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -27,8 +27,11 @@ #include namespace llvm { + class LLVMContext; class Module; +class ModuleSlotTracker; + template class SymbolTableListTraits; @@ -59,27 +62,28 @@ class Metadata { public: enum MetadataKind { MDTupleKind, - MDLocationKind, - GenericDebugNodeKind, - MDSubrangeKind, - MDEnumeratorKind, - MDBasicTypeKind, - MDDerivedTypeKind, - MDCompositeTypeKind, - MDSubroutineTypeKind, - MDFileKind, - MDCompileUnitKind, - MDSubprogramKind, - MDLexicalBlockKind, - MDLexicalBlockFileKind, - MDNamespaceKind, - MDTemplateTypeParameterKind, - MDTemplateValueParameterKind, - MDGlobalVariableKind, - MDLocalVariableKind, - MDExpressionKind, - MDObjCPropertyKind, - MDImportedEntityKind, + DILocationKind, + GenericDINodeKind, + DISubrangeKind, + DIEnumeratorKind, + DIBasicTypeKind, + DIDerivedTypeKind, + DICompositeTypeKind, + DISubroutineTypeKind, + DIFileKind, + DICompileUnitKind, + DISubprogramKind, + DILexicalBlockKind, + DILexicalBlockFileKind, + DINamespaceKind, + DIModuleKind, + DITemplateTypeParameterKind, + DITemplateValueParameterKind, + DIGlobalVariableKind, + DILocalVariableKind, + DIExpressionKind, + DIObjCPropertyKind, + DIImportedEntityKind, ConstantAsMetadataKind, LocalAsMetadataKind, MDStringKind @@ -121,7 +125,11 @@ class Metadata { /// /// If \c M is provided, metadata nodes will be numbered canonically; /// otherwise, pointer addresses are substituted. + /// @{ void print(raw_ostream &OS, const Module *M = nullptr) const; + void print(raw_ostream &OS, ModuleSlotTracker &MST, + const Module *M = nullptr) const; + /// @} /// \brief Print as operand. /// @@ -129,7 +137,11 @@ class Metadata { /// /// If \c M is provided, metadata nodes will be numbered canonically; /// otherwise, pointer addresses are substituted. + /// @{ void printAsOperand(raw_ostream &OS, const Module *M = nullptr) const; + void printAsOperand(raw_ostream &OS, ModuleSlotTracker &MST, + const Module *M = nullptr) const; + /// @} }; #define HANDLE_METADATA(CLASS) class CLASS; diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index dbaf322263d..1668b95c8bd 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -249,7 +249,7 @@ class Module { /// Get the data layout string for the module's target platform. This is /// equivalent to getDataLayout()->getStringRepresentation(). - const std::string getDataLayoutStr() const { + const std::string &getDataLayoutStr() const { return DL.getStringRepresentation(); } @@ -492,7 +492,7 @@ class Module { /// If the GlobalValue is read in, and if the GVMaterializer supports it, /// release the memory for the function, and set it up to be materialized /// lazily. If !isDematerializable(), this method is a no-op. - void Dematerialize(GlobalValue *GV); + void dematerialize(GlobalValue *GV); /// Make sure all GlobalValues in this Module are fully read. std::error_code materializeAll(); @@ -512,28 +512,28 @@ class Module { const GlobalListType &getGlobalList() const { return GlobalList; } /// Get the Module's list of global variables. GlobalListType &getGlobalList() { return GlobalList; } - static iplist 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 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 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 Module::*getSublistAccess(NamedMDNode*) { + static NamedMDListType Module::*getSublistAccess(NamedMDNode*) { return &Module::NamedMDList; } /// Get the symbol table of global variable and function identifiers diff --git a/include/llvm/IR/ModuleSlotTracker.h b/include/llvm/IR/ModuleSlotTracker.h new file mode 100644 index 00000000000..49730a66bdf --- /dev/null +++ b/include/llvm/IR/ModuleSlotTracker.h @@ -0,0 +1,76 @@ +//===-- llvm/IR/ModuleSlotTracker.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_IR_MODULESLOTTRACKER_H +#define LLVM_IR_MODULESLOTTRACKER_H + +#include + +namespace llvm { + +class Module; +class Function; +class SlotTracker; +class Value; + +/// Manage lifetime of a slot tracker for printing IR. +/// +/// Wrapper around the \a SlotTracker used internally by \a AsmWriter. This +/// class allows callers to share the cost of incorporating the metadata in a +/// module or a function. +/// +/// If the IR changes from underneath \a ModuleSlotTracker, strings like +/// "" will be printed, or, worse, the wrong slots entirely. +class ModuleSlotTracker { + /// Storage for a slot tracker. + std::unique_ptr MachineStorage; + + const Module *M = nullptr; + const Function *F = nullptr; + SlotTracker *Machine = nullptr; + +public: + /// Wrap a preinitialized SlotTracker. + ModuleSlotTracker(SlotTracker &Machine, const Module *M, + const Function *F = nullptr); + + /// Construct a slot tracker from a module. + /// + /// If \a M is \c nullptr, uses a null slot tracker. Otherwise, initializes + /// a slot tracker, and initializes all metadata slots. \c + /// ShouldInitializeAllMetadata defaults to true because this is expected to + /// be shared between multiple callers, and otherwise MDNode references will + /// not match up. + explicit ModuleSlotTracker(const Module *M, + bool ShouldInitializeAllMetadata = true); + + /// Destructor to clean up storage. + ~ModuleSlotTracker(); + + SlotTracker *getMachine() const { return Machine; } + const Module *getModule() const { return M; } + const Function *getCurrentFunction() const { return F; } + + /// Incorporate the given function. + /// + /// Purge the currently incorporated function and incorporate \c F. If \c F + /// is currently incorporated, this is a no-op. + void incorporateFunction(const Function &F); + + /// Return the slot number of the specified local value. + /// + /// A function that defines this value should be incorporated prior to calling + /// this method. + /// Return -1 if the value is not in the function's SlotTracker. + int getLocalSlot(const Value *V); +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/IR/NaClAtomicIntrinsics.h b/include/llvm/IR/NaClAtomicIntrinsics.h index a0091b84557..e820b9df504 100644 --- a/include/llvm/IR/NaClAtomicIntrinsics.h +++ b/include/llvm/IR/NaClAtomicIntrinsics.h @@ -40,7 +40,7 @@ class AtomicIntrinsics { struct AtomicIntrinsic { Type *OverloadedType; - Intrinsic::ID ID : 16; + Intrinsic::ID ID; uint8_t Overloaded : 1; uint8_t NumParams : 7; uint8_t ParamType[MaxAtomicIntrinsicsParameters]; diff --git a/include/llvm/IR/OperandTraits.h b/include/llvm/IR/OperandTraits.h index 0e4b1950f27..e97a8009ccc 100644 --- a/include/llvm/IR/OperandTraits.h +++ b/include/llvm/IR/OperandTraits.h @@ -92,10 +92,10 @@ struct VariadicOperandTraits { template 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(); diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h index 8c3afdd86ae..372b254ab18 100644 --- a/include/llvm/IR/Operator.h +++ b/include/llvm/IR/Operator.h @@ -18,7 +18,6 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Type.h" @@ -306,7 +305,8 @@ class FPMathOperator : public Operator { float getFPAccuracy() const; static inline bool classof(const Instruction *I) { - return I->getType()->isFPOrFPVectorTy(); + return I->getType()->isFPOrFPVectorTy() || + I->getOpcode() == Instruction::FCmp; } static inline bool classof(const Value *V) { return isa(V) && classof(cast(V)); @@ -400,10 +400,7 @@ class GEPOperator return getPointerOperand()->getType(); } - Type *getSourceElementType() const { - return cast(getPointerOperandType()->getScalarType()) - ->getElementType(); - } + Type *getSourceElementType() const; /// Method to return the address space of the pointer operand. unsigned getPointerAddressSpace() const { @@ -450,36 +447,7 @@ class GEPOperator /// undefined (it is *not* preserved!). The APInt passed into this routine /// must be at exactly as wide as the IntPtr type for the address space of the /// base GEP pointer. - bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const { - assert(Offset.getBitWidth() == - DL.getPointerSizeInBits(getPointerAddressSpace()) && - "The offset must have exactly as many bits as our pointer."); - - for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this); - GTI != GTE; ++GTI) { - ConstantInt *OpC = dyn_cast(GTI.getOperand()); - if (!OpC) - return false; - if (OpC->isZero()) - continue; - - // Handle a struct index, which adds its field offset to the pointer. - if (StructType *STy = dyn_cast(*GTI)) { - unsigned ElementIdx = OpC->getZExtValue(); - const StructLayout *SL = DL.getStructLayout(STy); - Offset += APInt(Offset.getBitWidth(), - SL->getElementOffset(ElementIdx)); - continue; - } - - // For array or vector indices, scale the index by the size of the type. - APInt Index = OpC->getValue().sextOrTrunc(Offset.getBitWidth()); - Offset += Index * APInt(Offset.getBitWidth(), - DL.getTypeAllocSize(GTI.getIndexedType())); - } - return true; - } - + bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset) const; }; class PtrToIntOperator diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h index 3c24e7231a1..4166babd63e 100644 --- a/include/llvm/IR/PassManager.h +++ b/include/llvm/IR/PassManager.h @@ -509,7 +509,7 @@ class AnalysisManager PreservedAnalyses invalidateImpl(IRUnitT &IR, PreservedAnalyses PA) { // Short circuit for a common case of all analyses being preserved. if (PA.areAllPreserved()) - return std::move(PA); + return PA; if (DebugLogging) dbgs() << "Invalidating all non-preserved analyses for: " @@ -549,7 +549,7 @@ class AnalysisManager if (ResultsList.empty()) AnalysisResultLists.erase(&IR); - return std::move(PA); + return PA; } /// \brief List of function analysis pass IDs and associated concept pointers. @@ -827,7 +827,7 @@ template class ModuleToFunctionPassAdaptor { template ModuleToFunctionPassAdaptor createModuleToFunctionPassAdaptor(FunctionPassT Pass) { - return std::move(ModuleToFunctionPassAdaptor(std::move(Pass))); + return ModuleToFunctionPassAdaptor(std::move(Pass)); } /// \brief A template utility pass to force an analysis result to be available. diff --git a/include/llvm/IR/PredIteratorCache.h b/include/llvm/IR/PredIteratorCache.h index 5e1be37805f..118310aed1d 100644 --- a/include/llvm/IR/PredIteratorCache.h +++ b/include/llvm/IR/PredIteratorCache.h @@ -14,6 +14,7 @@ #ifndef LLVM_IR_PREDITERATORCACHE_H #define LLVM_IR_PREDITERATORCACHE_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/CFG.h" @@ -21,50 +22,58 @@ namespace llvm { - /// PredIteratorCache - This class is an extremely trivial cache for - /// predecessor iterator queries. This is useful for code that repeatedly - /// wants the predecessor list for the same blocks. - class PredIteratorCache { - /// BlockToPredsMap - Pointer to null-terminated list. - DenseMap BlockToPredsMap; - DenseMap BlockToPredCountMap; +/// PredIteratorCache - This class is an extremely trivial cache for +/// predecessor iterator queries. This is useful for code that repeatedly +/// wants the predecessor list for the same blocks. +class PredIteratorCache { + /// BlockToPredsMap - Pointer to null-terminated list. + DenseMap BlockToPredsMap; + DenseMap BlockToPredCountMap; - /// Memory - This is the space that holds cached preds. - BumpPtrAllocator Memory; - public: + /// Memory - This is the space that holds cached preds. + BumpPtrAllocator Memory; - /// GetPreds - Get a cached list for the null-terminated predecessor list of - /// the specified block. This can be used in a loop like this: - /// for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI) - /// use(*PI); - /// instead of: - /// for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) - BasicBlock **GetPreds(BasicBlock *BB) { - BasicBlock **&Entry = BlockToPredsMap[BB]; - if (Entry) return Entry; +private: + /// GetPreds - Get a cached list for the null-terminated predecessor list of + /// the specified block. This can be used in a loop like this: + /// for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI) + /// use(*PI); + /// instead of: + /// for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) + BasicBlock **GetPreds(BasicBlock *BB) { + BasicBlock **&Entry = BlockToPredsMap[BB]; + if (Entry) + return Entry; - SmallVector PredCache(pred_begin(BB), pred_end(BB)); - PredCache.push_back(nullptr); // null terminator. - - BlockToPredCountMap[BB] = PredCache.size()-1; + SmallVector PredCache(pred_begin(BB), pred_end(BB)); + PredCache.push_back(nullptr); // null terminator. - Entry = Memory.Allocate(PredCache.size()); - std::copy(PredCache.begin(), PredCache.end(), Entry); - return Entry; - } - - unsigned GetNumPreds(BasicBlock *BB) { - GetPreds(BB); - return BlockToPredCountMap[BB]; - } + BlockToPredCountMap[BB] = PredCache.size() - 1; + + Entry = Memory.Allocate(PredCache.size()); + std::copy(PredCache.begin(), PredCache.end(), Entry); + return Entry; + } + + unsigned GetNumPreds(BasicBlock *BB) { + GetPreds(BB); + return BlockToPredCountMap[BB]; + } + +public: + size_t size(BasicBlock *BB) { return GetNumPreds(BB); } + ArrayRef get(BasicBlock *BB) { + return makeArrayRef(GetPreds(BB), GetNumPreds(BB)); + } + + /// clear - Remove all information. + void clear() { + BlockToPredsMap.clear(); + BlockToPredCountMap.clear(); + Memory.Reset(); + } +}; - /// clear - Remove all information. - void clear() { - BlockToPredsMap.clear(); - BlockToPredCountMap.clear(); - Memory.Reset(); - } - }; } // end namespace llvm #endif diff --git a/include/llvm/IR/Statepoint.h b/include/llvm/IR/Statepoint.h index 38720edabad..4ab1f8497ad 100644 --- a/include/llvm/IR/Statepoint.h +++ b/include/llvm/IR/Statepoint.h @@ -13,29 +13,40 @@ // //===----------------------------------------------------------------------===// -#ifndef __LLVM_IR_STATEPOINT_H -#define __LLVM_IR_STATEPOINT_H +#ifndef LLVM_IR_STATEPOINT_H +#define LLVM_IR_STATEPOINT_H #include "llvm/ADT/iterator_range.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CallSite.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Support/Compiler.h" namespace llvm { +/// The statepoint intrinsic accepts a set of flags as its third argument. +/// Valid values come out of this set. +enum class StatepointFlags { + None = 0, + GCTransition = 1, ///< Indicates that this statepoint is a transition from + ///< GC-aware code to code that is not GC-aware. + + MaskAll = GCTransition ///< A bitmask that includes all valid flags. +}; class GCRelocateOperands; class ImmutableStatepoint; bool isStatepoint(const ImmutableCallSite &CS); -bool isStatepoint(const Value *inst); -bool isStatepoint(const Value &inst); +bool isStatepoint(const Value *V); +bool isStatepoint(const Value &V); -bool isGCRelocate(const Value *inst); +bool isGCRelocate(const Value *V); bool isGCRelocate(const ImmutableCallSite &CS); -bool isGCResult(const Value *inst); +bool isGCResult(const Value *V); bool isGCResult(const ImmutableCallSite &CS); /// Analogous to CallSiteBase, this provides most of the actual @@ -44,90 +55,188 @@ bool isGCResult(const ImmutableCallSite &CS); /// concrete subtypes. This is structured analogous to CallSite /// rather than the IntrinsicInst.h helpers since we want to support /// invokable statepoints in the near future. -/// TODO: This does not currently allow the if(Statepoint S = ...) -/// idiom used with CallSites. Consider refactoring to support. -template +template class StatepointBase { CallSiteTy StatepointCS; void *operator new(size_t, unsigned) = delete; void *operator new(size_t s) = delete; - protected: - explicit StatepointBase(InstructionTy *I) : StatepointCS(I) { - assert(isStatepoint(I)); +protected: + explicit StatepointBase(InstructionTy *I) { + if (isStatepoint(I)) { + StatepointCS = CallSiteTy(I); + assert(StatepointCS && "isStatepoint implies CallSite"); + } } - explicit StatepointBase(CallSiteTy CS) : StatepointCS(CS) { - assert(isStatepoint(CS)); + explicit StatepointBase(CallSiteTy CS) { + if (isStatepoint(CS)) + StatepointCS = CS; } - public: +public: typedef typename CallSiteTy::arg_iterator arg_iterator; + enum { + IDPos = 0, + NumPatchBytesPos = 1, + CalledFunctionPos = 2, + NumCallArgsPos = 3, + FlagsPos = 4, + CallArgsBeginPos = 5, + }; + + explicit operator bool() const { + // We do not assign non-statepoint CallSites to StatepointCS. + return (bool)StatepointCS; + } + /// Return the underlying CallSite. - CallSiteTy getCallSite() { + CallSiteTy getCallSite() const { + assert(*this && "check validity first!"); return StatepointCS; } + uint64_t getFlags() const { + return cast(getCallSite().getArgument(FlagsPos)) + ->getZExtValue(); + } + + /// Return the ID associated with this statepoint. + uint64_t getID() const { + const Value *IDVal = getCallSite().getArgument(IDPos); + return cast(IDVal)->getZExtValue(); + } + + /// Return the number of patchable bytes associated with this statepoint. + uint32_t getNumPatchBytes() const { + const Value *NumPatchBytesVal = getCallSite().getArgument(NumPatchBytesPos); + uint64_t NumPatchBytes = + cast(NumPatchBytesVal)->getZExtValue(); + assert(isInt<32>(NumPatchBytes) && "should fit in 32 bits!"); + return NumPatchBytes; + } + /// Return the value actually being called or invoked. - ValueTy *actualCallee() { - return StatepointCS.getArgument(0); + ValueTy *getCalledValue() const { + return getCallSite().getArgument(CalledFunctionPos); } - /// Number of arguments to be passed to the actual callee. - int numCallArgs() { - return cast(StatepointCS.getArgument(1))->getZExtValue(); + + InstructionTy *getInstruction() const { + return getCallSite().getInstruction(); } - /// Number of additional arguments excluding those intended - /// for garbage collection. - int numTotalVMSArgs() { - return cast(StatepointCS.getArgument(3 + numCallArgs()))->getZExtValue(); + + /// Return the function being called if this is a direct call, otherwise + /// return null (if it's an indirect call). + FunTy *getCalledFunction() const { + return dyn_cast(getCalledValue()); + } + + /// Return the caller function for this statepoint. + FunTy *getCaller() const { return getCallSite().getCaller(); } + + /// Determine if the statepoint cannot unwind. + bool doesNotThrow() const { + Function *F = getCalledFunction(); + return getCallSite().doesNotThrow() || (F ? F->doesNotThrow() : false); } - typename CallSiteTy::arg_iterator call_args_begin() { - // 3 = callTarget, #callArgs, flag - int Offset = 3; - assert(Offset <= (int)StatepointCS.arg_size()); - return StatepointCS.arg_begin() + Offset; + /// Return the type of the value returned by the call underlying the + /// statepoint. + Type *getActualReturnType() const { + auto *FTy = cast( + cast(getCalledValue()->getType())->getElementType()); + return FTy->getReturnType(); } - typename CallSiteTy::arg_iterator call_args_end() { - int Offset = 3 + numCallArgs(); - assert(Offset <= (int)StatepointCS.arg_size()); - return StatepointCS.arg_begin() + Offset; + + /// Number of arguments to be passed to the actual callee. + int getNumCallArgs() const { + const Value *NumCallArgsVal = getCallSite().getArgument(NumCallArgsPos); + return cast(NumCallArgsVal)->getZExtValue(); + } + + size_t arg_size() const { return getNumCallArgs(); } + typename CallSiteTy::arg_iterator arg_begin() const { + assert(CallArgsBeginPos <= (int)getCallSite().arg_size()); + return getCallSite().arg_begin() + CallArgsBeginPos; + } + typename CallSiteTy::arg_iterator arg_end() const { + auto I = arg_begin() + arg_size(); + assert((getCallSite().arg_end() - I) >= 0); + return I; + } + + ValueTy *getArgument(unsigned Index) { + assert(Index < arg_size() && "out of bounds!"); + return *(arg_begin() + Index); } /// range adapter for call arguments - iterator_range call_args() { - return iterator_range(call_args_begin(), call_args_end()); + iterator_range call_args() const { + return iterator_range(arg_begin(), arg_end()); } - typename CallSiteTy::arg_iterator vm_state_begin() { - return call_args_end(); + /// \brief Return true if the call or the callee has the given attribute. + bool paramHasAttr(unsigned i, Attribute::AttrKind A) const { + Function *F = getCalledFunction(); + return getCallSite().paramHasAttr(i + CallArgsBeginPos, A) || + (F ? F->getAttributes().hasAttribute(i, A) : false); } - typename CallSiteTy::arg_iterator vm_state_end() { - int Offset = 3 + numCallArgs() + 1 + numTotalVMSArgs(); - assert(Offset <= (int)StatepointCS.arg_size()); - return StatepointCS.arg_begin() + Offset; + + /// Number of GC transition args. + int getNumTotalGCTransitionArgs() const { + const Value *NumGCTransitionArgs = *arg_end(); + return cast(NumGCTransitionArgs)->getZExtValue(); + } + typename CallSiteTy::arg_iterator gc_transition_args_begin() const { + auto I = arg_end() + 1; + assert((getCallSite().arg_end() - I) >= 0); + return I; + } + typename CallSiteTy::arg_iterator gc_transition_args_end() const { + auto I = gc_transition_args_begin() + getNumTotalGCTransitionArgs(); + assert((getCallSite().arg_end() - I) >= 0); + return I; } - /// range adapter for vm state arguments - iterator_range vm_state_args() { - return iterator_range(vm_state_begin(), vm_state_end()); + /// range adapter for GC transition arguments + iterator_range gc_transition_args() const { + return iterator_range(gc_transition_args_begin(), + gc_transition_args_end()); + } + + /// Number of additional arguments excluding those intended + /// for garbage collection. + int getNumTotalVMSArgs() const { + const Value *NumVMSArgs = *gc_transition_args_end(); + return cast(NumVMSArgs)->getZExtValue(); } - typename CallSiteTy::arg_iterator first_vm_state_stack_begin() { - // 6 = numTotalVMSArgs, 1st_objectID, 1st_bci, - // 1st_#stack, 1st_#local, 1st_#monitor - return vm_state_begin() + 6; + typename CallSiteTy::arg_iterator vm_state_begin() const { + auto I = gc_transition_args_end() + 1; + assert((getCallSite().arg_end() - I) >= 0); + return I; + } + typename CallSiteTy::arg_iterator vm_state_end() const { + auto I = vm_state_begin() + getNumTotalVMSArgs(); + assert((getCallSite().arg_end() - I) >= 0); + return I; } - typename CallSiteTy::arg_iterator gc_args_begin() { + /// range adapter for vm state arguments + iterator_range vm_state_args() const { + return iterator_range(vm_state_begin(), vm_state_end()); + } + + typename CallSiteTy::arg_iterator gc_args_begin() const { return vm_state_end(); } - typename CallSiteTy::arg_iterator gc_args_end() { - return StatepointCS.arg_end(); + typename CallSiteTy::arg_iterator gc_args_end() const { + return getCallSite().arg_end(); } /// range adapter for gc arguments - iterator_range gc_args() { + iterator_range gc_args() const { return iterator_range(gc_args_begin(), gc_args_end()); } @@ -135,19 +244,32 @@ class StatepointBase { /// May contain several relocations for the same base/derived pair. /// For example this could happen due to relocations on unwinding /// path of invoke. - std::vector getRelocates(ImmutableStatepoint &IS); + std::vector getRelocates() const; + + /// Get the experimental_gc_result call tied to this statepoint. Can be + /// nullptr if there isn't a gc_result tied to this statepoint. Guaranteed to + /// be a CallInst if non-null. + InstructionTy *getGCResult() const { + for (auto *U : getInstruction()->users()) + if (isGCResult(U)) + return cast(U); + + return nullptr; + } #ifndef NDEBUG /// Asserts if this statepoint is malformed. Common cases for failure /// include incorrect length prefixes for variable length sections or /// illegal values for parameters. void verify() { - assert(numCallArgs() >= 0 && + assert(getNumCallArgs() >= 0 && "number of arguments to actually callee can't be negative"); // The internal asserts in the iterator accessors do the rest. - (void)call_args_begin(); - (void)call_args_end(); + (void)arg_begin(); + (void)arg_end(); + (void)gc_transition_args_begin(); + (void)gc_transition_args_end(); (void)vm_state_begin(); (void)vm_state_end(); (void)gc_args_begin(); @@ -159,10 +281,10 @@ class StatepointBase { /// A specialization of it's base class for read only access /// to a gc.statepoint. class ImmutableStatepoint - : public StatepointBase { - typedef StatepointBase - Base; + typedef StatepointBase Base; public: explicit ImmutableStatepoint(const Instruction *I) : Base(I) {} @@ -171,8 +293,9 @@ class ImmutableStatepoint /// A specialization of it's base class for read-write access /// to a gc.statepoint. -class Statepoint : public StatepointBase { - typedef StatepointBase Base; +class Statepoint + : public StatepointBase { + typedef StatepointBase Base; public: explicit Statepoint(Instruction *I) : Base(I) {} @@ -185,114 +308,107 @@ class Statepoint : public StatepointBase { class GCRelocateOperands { ImmutableCallSite RelocateCS; - public: - GCRelocateOperands(const User* U) : RelocateCS(U) { - assert(isGCRelocate(U)); - } +public: + GCRelocateOperands(const User *U) : RelocateCS(U) { assert(isGCRelocate(U)); } GCRelocateOperands(const Instruction *inst) : RelocateCS(inst) { assert(isGCRelocate(inst)); } - GCRelocateOperands(CallSite CS) : RelocateCS(CS) { - assert(isGCRelocate(CS)); - } + GCRelocateOperands(CallSite CS) : RelocateCS(CS) { assert(isGCRelocate(CS)); } /// Return true if this relocate is tied to the invoke statepoint. /// This includes relocates which are on the unwinding path. bool isTiedToInvoke() const { const Value *Token = RelocateCS.getArgument(0); - return isa(Token) || - isa(Token); + return isa(Token) || isa(Token); } /// Get enclosed relocate intrinsic - ImmutableCallSite getUnderlyingCallSite() { - return RelocateCS; - } + ImmutableCallSite getUnderlyingCallSite() { return RelocateCS; } /// The statepoint with which this gc.relocate is associated. - const Instruction *statepoint() { - const Value *token = RelocateCS.getArgument(0); + const Instruction *getStatepoint() { + const Value *Token = RelocateCS.getArgument(0); // This takes care both of relocates for call statepoints and relocates // on normal path of invoke statepoint. - if (!isa(token)) { - return cast(token); + if (!isa(Token)) { + return cast(Token); } // This relocate is on exceptional path of an invoke statepoint - const BasicBlock *invokeBB = - cast(token)->getParent()->getUniquePredecessor(); + const BasicBlock *InvokeBB = + cast(Token)->getParent()->getUniquePredecessor(); - assert(invokeBB && "safepoints should have unique landingpads"); - assert(invokeBB->getTerminator() && "safepoint block should be well formed"); - assert(isStatepoint(invokeBB->getTerminator())); + assert(InvokeBB && "safepoints should have unique landingpads"); + assert(InvokeBB->getTerminator() && + "safepoint block should be well formed"); + assert(isStatepoint(InvokeBB->getTerminator())); - return invokeBB->getTerminator(); + return InvokeBB->getTerminator(); } + /// The index into the associate statepoint's argument list /// which contains the base pointer of the pointer whose /// relocation this gc.relocate describes. - unsigned basePtrIndex() { + unsigned getBasePtrIndex() { return cast(RelocateCS.getArgument(1))->getZExtValue(); } + /// The index into the associate statepoint's argument list which /// contains the pointer whose relocation this gc.relocate describes. - unsigned derivedPtrIndex() { + unsigned getDerivedPtrIndex() { return cast(RelocateCS.getArgument(2))->getZExtValue(); } - Value *basePtr() { - ImmutableCallSite CS(statepoint()); - return *(CS.arg_begin() + basePtrIndex()); + + Value *getBasePtr() { + ImmutableCallSite CS(getStatepoint()); + return *(CS.arg_begin() + getBasePtrIndex()); } - Value *derivedPtr() { - ImmutableCallSite CS(statepoint()); - return *(CS.arg_begin() + derivedPtrIndex()); + + Value *getDerivedPtr() { + ImmutableCallSite CS(getStatepoint()); + return *(CS.arg_begin() + getDerivedPtrIndex()); } }; -template +template std::vector - StatepointBase:: - getRelocates(ImmutableStatepoint &IS) { +StatepointBase::getRelocates() + const { - std::vector res; + std::vector Result; - ImmutableCallSite StatepointCS = IS.getCallSite(); + CallSiteTy StatepointCS = getCallSite(); // Search for relocated pointers. Note that working backwards from the // gc_relocates ensures that we only get pairs which are actually relocated // and used after the statepoint. - for (const User *U : StatepointCS.getInstruction()->users()) { - if (isGCRelocate(U)) { - res.push_back(GCRelocateOperands(U)); - } - } + for (const User *U : getInstruction()->users()) + if (isGCRelocate(U)) + Result.push_back(GCRelocateOperands(U)); - if (!StatepointCS.isInvoke()) { - return res; - } + if (!StatepointCS.isInvoke()) + return Result; // We need to scan thorough exceptional relocations if it is invoke statepoint LandingPadInst *LandingPad = - cast(StatepointCS.getInstruction())->getLandingPadInst(); + cast(getInstruction())->getLandingPadInst(); // Search for extract value from landingpad instruction to which // gc relocates will be attached for (const User *LandingPadUser : LandingPad->users()) { - if (!isa(LandingPadUser)) { + if (!isa(LandingPadUser)) continue; - } // gc relocates should be attached to this extract value - for (const User *U : LandingPadUser->users()) { - if (isGCRelocate(U)) { - res.push_back(GCRelocateOperands(U)); - } - } + for (const User *U : LandingPadUser->users()) + if (isGCRelocate(U)) + Result.push_back(GCRelocateOperands(U)); } - return res; + return Result; } - } + #endif diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h index 09b6388bd26..6ab0bd0631a 100644 --- a/include/llvm/IR/Type.h +++ b/include/llvm/IR/Type.h @@ -395,7 +395,8 @@ class Type { static IntegerType *getInt16Ty(LLVMContext &C); static IntegerType *getInt32Ty(LLVMContext &C); static IntegerType *getInt64Ty(LLVMContext &C); - + static IntegerType *getInt128Ty(LLVMContext &C); + //===--------------------------------------------------------------------===// // Convenience methods for getting pointer types with one of the above builtin // types as pointee. diff --git a/include/llvm/IR/TypeBuilder.h b/include/llvm/IR/TypeBuilder.h index 5a29e1e1085..d2c6f00079d 100644 --- a/include/llvm/IR/TypeBuilder.h +++ b/include/llvm/IR/TypeBuilder.h @@ -34,6 +34,8 @@ namespace llvm { /// you'll need to specialize it. For example, say you want to call a /// function defined externally as: /// +/// \code{.cpp} +/// /// struct MyType { /// int32 a; /// int32 *b; @@ -41,12 +43,16 @@ namespace llvm { /// }; /// int8 AFunction(struct MyType *value); /// +/// \endcode +/// /// You'll want to use /// Function::Create(TypeBuilder(MyType*), true>::get(), ...) /// to declare the function, but when you first try this, your compiler will /// complain that TypeBuilder::get() doesn't exist. To fix this, /// write: /// +/// \code{.cpp} +/// /// namespace llvm { /// template class TypeBuilder { /// public: @@ -57,7 +63,7 @@ namespace llvm { /// TypeBuilder, xcompile>::get(Context), /// TypeBuilder*, xcompile>::get(Context), /// TypeBuilder*[], xcompile>::get(Context), -/// NULL); +/// nullptr); /// } /// /// // You may find this a convenient place to put some constants @@ -71,6 +77,8 @@ namespace llvm { /// } /// } // namespace llvm /// +/// \endcode +/// /// TypeBuilder cannot handle recursive types or types you only know at runtime. /// If you try to give it a recursive type, it will deadlock, infinitely /// recurse, or do something similarly undesirable. diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h index 455900566af..93614fab575 100644 --- a/include/llvm/IR/User.h +++ b/include/llvm/IR/User.h @@ -22,6 +22,7 @@ #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" #include "llvm/IR/Value.h" +#include "llvm/Support/AlignOf.h" #include "llvm/Support/ErrorHandling.h" namespace llvm { @@ -34,33 +35,45 @@ struct OperandTraits; class User : public Value { User(const User &) = delete; - void *operator new(size_t) = delete; template friend struct HungoffOperandTraits; virtual void anchor(); + protected: - /// \brief This is a pointer to the array of Uses for this User. + /// 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. /// - /// 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; + /// This is used for subclasses which have a fixed number of operands. + void *operator new(size_t Size, unsigned Us); - void *operator new(size_t s, 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 +96,81 @@ class User : public Value { template const Use &Op() const { return OpFrom(this); } +private: + Use *&getHungOffOperands() { return *(reinterpret_cast(this) - 1); } + + Use *getIntrusiveOperands() { + return reinterpret_cast(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(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((const Value*)this) || isa((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; + } + + /// Set the number of operands on a Function. + /// + /// Function 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 setFunctionNumOperands(unsigned NumOps) { + assert(NumOps <= 1 && "Function 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 +180,18 @@ class User : public Value { typedef iterator_range op_range; typedef iterator_range 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 +206,13 @@ class User : public Value { 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 operand_values() { + iterator_range operand_values() { return iterator_range(value_op_begin(), value_op_end()); } @@ -170,6 +240,11 @@ class User : public Value { return isa(V) || isa(V); } }; +// Either Use objects, or a Use pointer can be prepended to User. +static_assert(AlignOf::Alignment >= AlignOf::Alignment, + "Alignment is insufficient after objects prepended to User"); +static_assert(AlignOf::Alignment >= AlignOf::Alignment, + "Alignment is insufficient after objects prepended to User"); template<> struct simplify_type { typedef Value* SimpleType; diff --git a/include/llvm/IR/Value.def b/include/llvm/IR/Value.def new file mode 100644 index 00000000000..c2a0639603e --- /dev/null +++ b/include/llvm/IR/Value.def @@ -0,0 +1,90 @@ +//===-------- llvm/IR/Value.def - File that describes Values ---v-*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains descriptions of the various LLVM values. This is +// used as a central place for enumerating the different values. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +// Provide definitions of macros so that users of this file do not have to +// define everything to use it... +// +#if !(defined HANDLE_GLOBAL_VALUE || defined HANDLE_CONSTANT || \ + defined HANDLE_INSTRUCTION || defined HANDLE_INLINE_ASM_VALUE || \ + defined HANDLE_METADATA_VALUE || defined HANDLE_VALUE || \ + defined HANDLE_CONSTANT_MARKER) +#error "Missing macro definition of HANDLE_VALUE*" +#endif + +#ifndef HANDLE_GLOBAL_VALUE +#define HANDLE_GLOBAL_VALUE(ValueName) HANDLE_CONSTANT(ValueName) +#endif + +#ifndef HANDLE_CONSTANT +#define HANDLE_CONSTANT(ValueName) HANDLE_VALUE(ValueName) +#endif + +#ifndef HANDLE_INSTRUCTION +#define HANDLE_INSTRUCTION(ValueName) HANDLE_VALUE(ValueName) +#endif + +#ifndef HANDLE_INLINE_ASM_VALUE +#define HANDLE_INLINE_ASM_VALUE(ValueName) HANDLE_VALUE(ValueName) +#endif + +#ifndef HANDLE_METADATA_VALUE +#define HANDLE_METADATA_VALUE(ValueName) HANDLE_VALUE(ValueName) +#endif + +#ifndef HANDLE_VALUE +#define HANDLE_VALUE(ValueName) +#endif + +#ifndef HANDLE_CONSTANT_MARKER +#define HANDLE_CONSTANT_MARKER(MarkerName, ValueName) +#endif + +HANDLE_VALUE(Argument) +HANDLE_VALUE(BasicBlock) + +HANDLE_GLOBAL_VALUE(Function) +HANDLE_GLOBAL_VALUE(GlobalAlias) +HANDLE_GLOBAL_VALUE(GlobalVariable) +HANDLE_CONSTANT(UndefValue) +HANDLE_CONSTANT(BlockAddress) +HANDLE_CONSTANT(ConstantExpr) +HANDLE_CONSTANT(ConstantAggregateZero) +HANDLE_CONSTANT(ConstantDataArray) +HANDLE_CONSTANT(ConstantDataVector) +HANDLE_CONSTANT(ConstantInt) +HANDLE_CONSTANT(ConstantFP) +HANDLE_CONSTANT(ConstantArray) +HANDLE_CONSTANT(ConstantStruct) +HANDLE_CONSTANT(ConstantVector) +HANDLE_CONSTANT(ConstantPointerNull) + +HANDLE_METADATA_VALUE(MetadataAsValue) +HANDLE_INLINE_ASM_VALUE(InlineAsm) + +HANDLE_INSTRUCTION(Instruction) +// Enum values starting at InstructionVal are used for Instructions; +// don't add new values here! + +HANDLE_CONSTANT_MARKER(ConstantFirstVal, Function) +HANDLE_CONSTANT_MARKER(ConstantLastVal, ConstantPointerNull) + +#undef HANDLE_GLOBAL_VALUE +#undef HANDLE_CONSTANT +#undef HANDLE_INSTRUCTION +#undef HANDLE_METADATA_VALUE +#undef HANDLE_INLINE_ASM_VALUE +#undef HANDLE_VALUE +#undef HANDLE_CONSTANT_MARKER diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index fb79a8abb0a..9d83cef76f7 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -38,6 +38,7 @@ class InlineAsm; class Instruction; class LLVMContext; class Module; +class ModuleSlotTracker; class StringRef; class Twine; class Type; @@ -69,9 +70,8 @@ class Value { Type *VTy; Use *UseList; - friend class ValueAsMetadata; // Allow access to NameAndIsUsedByMD. + friend class ValueAsMetadata; // Allow access to IsUsedByMD. friend class ValueHandleBase; - PointerIntPair NameAndIsUsedByMD; const unsigned char SubclassID; // Subclass identifier (for isa/dyn_cast) unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this? @@ -101,7 +101,15 @@ class Value { /// 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; + /// + /// Note, this should *NOT* be used directly by any class other than User. + /// User uses this value to find the Use list. + enum : unsigned { NumUserOperandsBits = 29 }; + unsigned NumUserOperands : NumUserOperandsBits; + + bool IsUsedByMD : 1; + bool HasName : 1; + bool HasHungOffUses : 1; private: template // UseT == 'Use' or 'const Use' @@ -192,7 +200,10 @@ class Value { void dump() const; /// \brief Implement operator<< on Value. + /// @{ void print(raw_ostream &O) const; + void print(raw_ostream &O, ModuleSlotTracker &MST) const; + /// @} /// \brief Print the name of this Value out to the specified raw_ostream. /// @@ -200,8 +211,12 @@ class Value { /// instruction that generated it. If you specify a Module for context, then /// even constanst get pretty-printed; for example, the type of a null /// pointer is printed symbolically. + /// @{ void printAsOperand(raw_ostream &O, bool PrintType = true, const Module *M = nullptr) const; + void printAsOperand(raw_ostream &O, bool PrintType, + ModuleSlotTracker &MST) const; + /// @} /// \brief All values are typed, get the type of this value. Type *getType() const { return VTy; } @@ -210,12 +225,13 @@ class Value { LLVMContext &getContext() const; // \brief All values can potentially be named. - bool hasName() const { return getValueName() != nullptr; } - ValueName *getValueName() const { return NameAndIsUsedByMD.getPointer(); } - void setValueName(ValueName *VN) { NameAndIsUsedByMD.setPointer(VN); } + bool hasName() const { return HasName; } + ValueName *getValueName() const; + void setValueName(ValueName *VN); private: void destroyValueName(); + void setNameImpl(const Twine &Name); public: /// \brief Return a constant reference to the value's name. @@ -325,32 +341,12 @@ class Value { /// Value classes SubclassID field. They are used for concrete type /// identification. enum ValueTy { - ArgumentVal, // This is an instance of Argument - BasicBlockVal, // This is an instance of BasicBlock - FunctionVal, // This is an instance of Function - GlobalAliasVal, // This is an instance of GlobalAlias - GlobalVariableVal, // This is an instance of GlobalVariable - UndefValueVal, // This is an instance of UndefValue - BlockAddressVal, // This is an instance of BlockAddress - ConstantExprVal, // This is an instance of ConstantExpr - ConstantAggregateZeroVal, // This is an instance of ConstantAggregateZero - ConstantDataArrayVal, // This is an instance of ConstantDataArray - ConstantDataVectorVal, // This is an instance of ConstantDataVector - ConstantIntVal, // This is an instance of ConstantInt - ConstantFPVal, // This is an instance of ConstantFP - ConstantArrayVal, // This is an instance of ConstantArray - ConstantStructVal, // This is an instance of ConstantStruct - ConstantVectorVal, // This is an instance of ConstantVector - ConstantPointerNullVal, // This is an instance of ConstantPointerNull - MetadataAsValueVal, // This is an instance of MetadataAsValue - InlineAsmVal, // This is an instance of InlineAsm - InstructionVal, // This is an instance of Instruction - // Enum values starting at InstructionVal are used for Instructions; - // don't add new values here! +#define HANDLE_VALUE(Name) Name##Val, +#include "llvm/IR/Value.def" // Markers: - ConstantFirstVal = FunctionVal, - ConstantLastVal = ConstantPointerNullVal +#define HANDLE_CONSTANT_MARKER(Marker, Constant) Marker = Constant##Val, +#include "llvm/IR/Value.def" }; /// \brief Return an ID for the concrete type of this object. @@ -393,7 +389,7 @@ class Value { bool hasValueHandle() const { return HasValueHandle; } /// \brief Return true if there is metadata referencing this value. - bool isUsedByMetadata() const { return NameAndIsUsedByMD.getInt(); } + bool isUsedByMetadata() const { return IsUsedByMD; } /// \brief Strip off pointer casts, all-zero GEPs, and aliases. /// @@ -446,12 +442,6 @@ class Value { return const_cast(this)->stripInBoundsOffsets(); } - /// \brief Check if this is always a dereferenceable pointer. - /// - /// Test if this value is always a pointer to allocated and suitably aligned - /// memory for a simple load or store. - bool isDereferenceablePointer(const DataLayout &DL) const; - /// \brief Translate PHI node to its predecessor from the given basic block. /// /// If this value is a PHI node with CurBB as its parent, return the value in @@ -502,40 +492,38 @@ class Value { /// \note Completely ignores \a Use::Prev (doesn't read, doesn't update). template static Use *mergeUseLists(Use *L, Use *R, Compare Cmp) { - // XXX EMSCRIPTEN: Reimplemented to operate iteratively instead of recursively, - // since there exists use lists that have ~300k elems, which would - // blow up the stack. - if (!L && !R) return 0; - Use *Merged = 0; - Use *MergedLast = 0; - if (!L || (R && Cmp(*R, *L))) { - Merged = MergedLast = R; - R = R->Next; - } else { - Merged = MergedLast = L; - L = L->Next; - } + Use *Merged; + Use **Next = &Merged; - while (L && R) { + for (;;) { + if (!L) { + *Next = R; + break; + } + if (!R) { + *Next = L; + break; + } if (Cmp(*R, *L)) { - MergedLast->Next = R; - MergedLast = R; + *Next = R; + Next = &R->Next; R = R->Next; } else { - MergedLast->Next = L; - MergedLast = L; + *Next = L; + Next = &L->Next; L = L->Next; } } - if (L) { - MergedLast->Next = L; - } - if (R) { - MergedLast->Next = R; - } + return Merged; } + /// \brief Tail-recursive helper for \a mergeUseLists(). + /// + /// \param[out] Next the first element in the list. + template + static void mergeUseListsImpl(Use *L, Use *R, Use **Next, Compare Cmp); + protected: unsigned short getSubclassDataFromValue() const { return SubclassData; } void setValueSubclassData(unsigned short D) { SubclassData = D; } diff --git a/include/llvm/IR/ValueHandle.h b/include/llvm/IR/ValueHandle.h index 355748e0597..53fa80a626a 100644 --- a/include/llvm/IR/ValueHandle.h +++ b/include/llvm/IR/ValueHandle.h @@ -159,11 +159,13 @@ class WeakVH : public ValueHandleBase { // Specialize simplify_type to allow WeakVH to participate in // dyn_cast, isa, etc. -template<> struct simplify_type { - typedef Value* SimpleType; - static SimpleType getSimplifiedValue(WeakVH &WVH) { - return WVH; - } +template <> struct simplify_type { + typedef Value *SimpleType; + static SimpleType getSimplifiedValue(WeakVH &WVH) { return WVH; } +}; +template <> struct simplify_type { + typedef Value *SimpleType; + static SimpleType getSimplifiedValue(const WeakVH &WVH) { return WVH; } }; /// \brief Value handle that asserts if the Value is deleted. diff --git a/include/llvm/IRReader/IRReader.h b/include/llvm/IRReader/IRReader.h index 1816e0a2e36..2d9ace0b62a 100644 --- a/include/llvm/IRReader/IRReader.h +++ b/include/llvm/IRReader/IRReader.h @@ -43,42 +43,6 @@ std::unique_ptr parseIR(MemoryBufferRef Buffer, SMDiagnostic &Err, /// for it. std::unique_ptr parseIRFile(StringRef Filename, SMDiagnostic &Err, LLVMContext &Context); - -// @LOCALMOD-BEGIN -class raw_ostream; - -// \brief Define the expected format of the file. -enum NaClFileFormat { - // LLVM IR source or bitcode file (as appropriate). - LLVMFormat, - // PNaCl bitcode file. - PNaClFormat, - // Autodetect if PNaCl or LLVM format. - AutodetectFileFormat -}; - -// \brief If the given MemoryBuffer holds a bitcode image, return a -// Module for it. Otherwise, attempt to parse it as LLVM Assembly and -// return a Module for it. When Format=PNaClFormat and Verbose -// is non-null, more descriptive error messages are also written to -// Verbose. -std::unique_ptr NaClParseIR(MemoryBufferRef Buffer, - NaClFileFormat Format, - SMDiagnostic &Err, - raw_ostream *Verbose, - LLVMContext &Context); - -/// \brief If the given file holds a Bitcode image, read the file. -/// Otherwise, attempt to parse it as LLVM assembly and return a -/// Module for it. When Format=PNaClFormat and Verbose -// is non-null, more descriptive error messages are also written to -// Verbose. -std::unique_ptr NaClParseIRFile(StringRef Filename, - NaClFileFormat Format, - SMDiagnostic &Err, - raw_ostream *Verbose, - LLVMContext &Context); -// @LOCALMOD-END } #endif diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 49b2a04ffdb..8b784036fdb 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -79,10 +79,10 @@ void initializeBarrierNoopPass(PassRegistry&); void initializeBasicAliasAnalysisPass(PassRegistry&); void initializeCallGraphWrapperPassPass(PassRegistry &); void initializeBlockExtractorPassPass(PassRegistry&); -void initializeBlockFrequencyInfoPass(PassRegistry&); +void initializeBlockFrequencyInfoWrapperPassPass(PassRegistry&); void initializeBoundsCheckingPass(PassRegistry&); void initializeBranchFolderPassPass(PassRegistry&); -void initializeBranchProbabilityInfoPass(PassRegistry&); +void initializeBranchProbabilityInfoWrapperPassPass(PassRegistry&); void initializeBreakCriticalEdgesPass(PassRegistry&); void initializeCallGraphPrinterPass(PassRegistry&); void initializeCallGraphViewerPass(PassRegistry&); @@ -130,6 +130,7 @@ void initializeSanitizerCoverageModulePass(PassRegistry&); void initializeDataFlowSanitizerPass(PassRegistry&); void initializeScalarizerPass(PassRegistry&); void initializeEarlyCSELegacyPassPass(PassRegistry &); +void initializeEliminateAvailableExternallyPass(PassRegistry&); void initializeExpandISelPseudosPass(PassRegistry&); void initializeFunctionAttrsPass(PassRegistry&); void initializeGCMachineCodeAnalysisPass(PassRegistry&); @@ -187,6 +188,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,12 +243,14 @@ 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&); void initializeSROA_SSAUpPass(PassRegistry&); void initializeScalarEvolutionAliasAnalysisPass(PassRegistry&); void initializeScalarEvolutionPass(PassRegistry&); +void initializeShrinkWrapPass(PassRegistry &); void initializeSimpleInlinerPass(PassRegistry&); void initializeShadowStackGCLoweringPass(PassRegistry&); void initializeRegisterCoalescerPass(PassRegistry&); @@ -255,6 +259,7 @@ void initializeSinkingPass(PassRegistry&); void initializeSeparateConstOffsetFromGEPPass(PassRegistry &); void initializeSlotIndexesPass(PassRegistry&); void initializeSpillPlacementPass(PassRegistry&); +void initializeSpeculativeExecutionPass(PassRegistry&); void initializeStackProtectorPass(PassRegistry&); void initializeStackColoringPass(PassRegistry&); void initializeStackSlotColoringPass(PassRegistry&); @@ -267,7 +272,6 @@ void initializeStripSymbolsPass(PassRegistry&); void initializeTailCallElimPass(PassRegistry&); void initializeTailDuplicatePassPass(PassRegistry&); void initializeTargetPassConfigPass(PassRegistry&); -void initializeDataLayoutPassPass(PassRegistry &); void initializeTargetTransformInfoWrapperPassPass(PassRegistry &); void initializeTargetLibraryInfoWrapperPassPass(PassRegistry &); void initializeAssumptionCacheTrackerPass(PassRegistry &); @@ -288,6 +292,7 @@ void initializeLoopVectorizePass(PassRegistry&); void initializeSLPVectorizerPass(PassRegistry&); void initializeBBVectorizePass(PassRegistry&); void initializeMachineFunctionPrinterPassPass(PassRegistry&); +void initializeMIRPrintingPassPass(PassRegistry&); void initializeStackMapLivenessPass(PassRegistry&); void initializeMachineCombinerPass(PassRegistry &); void initializeLoadCombinePass(PassRegistry&); @@ -359,6 +364,8 @@ void initializeLowerEmSetjmpPass(PassRegistry&); void initializeNoExitRuntimePass(PassRegistry&); // Emscripten passes end. // @LOCALMOD-END +void initializeLoopDistributePass(PassRegistry&); +void initializeSjLjEHPreparePass(PassRegistry&); } #endif diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/LTOCodeGenerator.h index c19a41c3af6..0c46fc048a4 100644 --- a/include/llvm/LTO/LTOCodeGenerator.h +++ b/include/llvm/LTO/LTOCodeGenerator.h @@ -79,7 +79,10 @@ struct LTOCodeGenerator { void setAttr(const char *mAttr) { MAttr = mAttr; } void setOptLevel(unsigned optLevel) { OptLevel = optLevel; } - void addMustPreserveSymbol(const char *sym) { MustPreserveSymbols[sym] = 1; } + void setShouldInternalize(bool Value) { ShouldInternalize = Value; } + void setShouldEmbedUselists(bool Value) { ShouldEmbedUselists = Value; } + + void addMustPreserveSymbol(StringRef sym) { MustPreserveSymbols[sym] = 1; } // To pass options to the driver and optimization passes. These options are // not necessarily for debugging purpose (The function name is misleading). @@ -96,10 +99,6 @@ struct LTOCodeGenerator { // Return true on success. bool writeMergedModules(const char *path, std::string &errMsg); - // @LOCALMOD-BEGIN - void wrapSymbol(const char *sym); - // @LOCALMOD-END - // Compile the merged module into a *single* object file; the path to object // file is returned to the caller via argument "name". Return true on // success. @@ -118,11 +117,10 @@ struct LTOCodeGenerator { // (linker), it brings the object to a buffer, and return the buffer to the // caller. This function should delete intermediate object file once its content // is brought to memory. Return NULL if the compilation was not successful. - const void *compile(size_t *length, - bool disableInline, - bool disableGVNLoadPRE, - bool disableVectorization, - std::string &errMsg); + std::unique_ptr compile(bool disableInline, + bool disableGVNLoadPRE, + bool disableVectorization, + std::string &errMsg); // Optimizes the merged module. Returns true on success. bool optimize(bool disableInline, @@ -133,7 +131,7 @@ struct LTOCodeGenerator { // Compiles the merged optimized module into a single object file. It brings // the object to a buffer, and returns the buffer to the caller. Return NULL // if the compilation was not successful. - const void *compileOptimized(size_t *length, std::string &errMsg); + std::unique_ptr compileOptimized(std::string &errMsg); void setDiagnosticHandler(lto_diagnostic_handler_t, void *); @@ -157,27 +155,27 @@ struct LTOCodeGenerator { typedef StringMap StringSet; - void initialize(); void destroyMergedModule(); std::unique_ptr OwnedContext; LLVMContext &Context; Linker IRLinker; - TargetMachine *TargetMach; - bool EmitDwarfDebugInfo; - bool ScopeRestrictionsDone; - lto_codegen_model CodeModel; + TargetMachine *TargetMach = nullptr; + bool EmitDwarfDebugInfo = false; + bool ScopeRestrictionsDone = false; + lto_codegen_model CodeModel = LTO_CODEGEN_PIC_MODEL_DEFAULT; StringSet MustPreserveSymbols; StringSet AsmUndefinedRefs; - std::unique_ptr NativeObjectFile; std::vector CodegenOptions; std::string MCpu; std::string MAttr; std::string NativeObjectPath; TargetOptions Options; - unsigned OptLevel; - lto_diagnostic_handler_t DiagHandler; - void *DiagContext; - LTOModule *OwnedModule; + unsigned OptLevel = 2; + lto_diagnostic_handler_t DiagHandler = nullptr; + void *DiagContext = nullptr; + LTOModule *OwnedModule = nullptr; + bool ShouldInternalize = true; + bool ShouldEmbedUselists = false; }; } #endif diff --git a/include/llvm/LTO/LTOModule.h b/include/llvm/LTO/LTOModule.h index 53c2b8e521b..c4e2be62739 100644 --- a/include/llvm/LTO/LTOModule.h +++ b/include/llvm/LTO/LTOModule.h @@ -47,12 +47,11 @@ struct LTOModule { std::unique_ptr OwnedContext; + std::string LinkerOpts; + std::unique_ptr IRFile; std::unique_ptr _target; - StringSet<> _linkeropt_strings; - std::vector _deplibs; - std::vector _linkeropts; - std::vector _symbols; + std::vector _symbols; // _defines and _undefines only needed to disambiguate tentative definitions StringSet<> _defines; @@ -143,28 +142,14 @@ struct LTOModule { return nullptr; } - /// Get the number of dependent libraries - uint32_t getDependentLibraryCount() { - return _deplibs.size(); - } - - /// Get the dependent library at the specified index. - const char *getDependentLibrary(uint32_t index) { - if (index < _deplibs.size()) - return _deplibs[index]; + const GlobalValue *getSymbolGV(uint32_t index) { + if (index < _symbols.size()) + return _symbols[index].symbol; return nullptr; } - /// Get the number of linker options - uint32_t getLinkerOptCount() { - return _linkeropts.size(); - } - - /// Get the linker option at the specified index. - const char *getLinkerOpt(uint32_t index) { - if (index < _linkeropts.size()) - return _linkeropts[index]; - return nullptr; + const char *getLinkerOpts() { + return LinkerOpts.c_str(); } const std::vector &getAsmUndefinedRefs() { diff --git a/include/llvm/LibDriver/LibDriver.h b/include/llvm/LibDriver/LibDriver.h new file mode 100644 index 00000000000..aaaa7b7d21c --- /dev/null +++ b/include/llvm/LibDriver/LibDriver.h @@ -0,0 +1,26 @@ +//===- 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 + +#include "llvm/ADT/ArrayRef.h" + +namespace llvm { + +int libDriverMain(llvm::ArrayRef ARgs); + +} + +#endif diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index bee39b19366..cea5530db3b 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -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(); @@ -170,10 +171,12 @@ namespace { (void) llvm::createPartiallyInlineLibCallsPass(); (void) llvm::createScalarizerPass(); (void) llvm::createSeparateConstOffsetFromGEPPass(); + (void) llvm::createSpeculativeExecutionPass(); (void) llvm::createRewriteSymbolsPass(); (void) llvm::createStraightLineStrengthReducePass(); (void) llvm::createMemDerefPrinter(); (void) llvm::createFloat2IntPass(); + (void) llvm::createEliminateAvailableExternallyPass(); (void)new llvm::IntervalPartition(); (void)new llvm::ScalarEvolution(); diff --git a/include/llvm/Linker/Linker.h b/include/llvm/Linker/Linker.h index 5ca815c325a..c43b90e9cd2 100644 --- a/include/llvm/Linker/Linker.h +++ b/include/llvm/Linker/Linker.h @@ -68,8 +68,10 @@ class Linker { void deleteModule(); /// \brief Link \p Src into the composite. The source is destroyed. + /// Passing OverrideSymbols as true will have symbols from Src + /// shadow those in the Dest. /// Returns true on error. - bool linkInModule(Module *Src); + bool linkInModule(Module *Src, bool OverrideSymbols = false); /// \brief Set the composite to the passed-in module. void setModule(Module *Dst); diff --git a/include/llvm/MC/ConstantPools.h b/include/llvm/MC/ConstantPools.h index ee7022bf178..9aa4663ba0f 100644 --- a/include/llvm/MC/ConstantPools.h +++ b/include/llvm/MC/ConstantPools.h @@ -73,7 +73,7 @@ class AssemblerConstantPools { // sections in a stable order to ensure that we have print the // constant pools in a deterministic order when printing an assembly // file. - typedef MapVector ConstantPoolMapTy; + typedef MapVector ConstantPoolMapTy; ConstantPoolMapTy ConstantPools; public: @@ -83,8 +83,8 @@ class AssemblerConstantPools { unsigned Size); private: - ConstantPool *getConstantPool(const MCSection *Section); - ConstantPool &getOrCreateConstantPool(const MCSection *Section); + ConstantPool *getConstantPool(MCSection *Section); + ConstantPool &getOrCreateConstantPool(MCSection *Section); }; } // end namespace llvm diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h index d3dd9cb356f..2bfad2d355b 100644 --- a/include/llvm/MC/MCAsmBackend.h +++ b/include/llvm/MC/MCAsmBackend.h @@ -27,7 +27,6 @@ class MCInst; class MCRelaxableFragment; class MCObjectWriter; class MCSection; -class MCStreamer; class MCValue; class raw_ostream; @@ -62,7 +61,7 @@ class MCAsmBackend { /// region directives will be ignored. bool hasDataInCodeSupport() const { return HasDataInCodeSupport; } - /// @name Target Fixup Interfaces + /// \name Target Fixup Interfaces /// @{ /// Get the number of target specific fixup kinds. @@ -88,7 +87,7 @@ class MCAsmBackend { /// @} - /// @name Target Relaxation Interfaces + /// \name Target Relaxation Interfaces /// @{ /// Check whether the given instruction may need relaxation. @@ -98,6 +97,12 @@ class MCAsmBackend { /// Target specific predicate for whether a given fixup requires the /// associated instruction to be relaxed. + virtual bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, bool Resolved, + uint64_t Value, + const MCRelaxableFragment *DF, + const MCAsmLayout &Layout) const; + + /// Simple predicate for targets where !Resolved implies requiring relaxation virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const = 0; @@ -131,16 +136,6 @@ class MCAsmBackend { generateCompactUnwindEncoding(ArrayRef) const { return 0; } - - // @LOCALMOD-BEGIN - /// CustomExpandInst - - /// If the MCInst instruction has a custom expansion, write it to the - /// MCStreamer 'Out'. This can be used to perform "last minute" rewrites of - /// MCInst instructions for emission. - virtual bool CustomExpandInst(const MCInst &Inst, MCStreamer &Out) { - return false; - } - // @LOCALMOD-END }; } // End llvm namespace diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 658d77cbddf..9bb0fa63c52 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -18,7 +18,6 @@ #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCDwarf.h" -#include "llvm/MC/MachineLocation.h" #include #include @@ -37,6 +36,7 @@ enum class EncodingType { ARM, /// Windows NT (Windows on ARM) CE, /// Windows CE ARM, PowerPC, SH3, SH4 Itanium, /// Windows x64, Windows Itanium (IA-64) + X86, /// Windows x86, uses no CFI, just EH tables MIPS = Alpha, }; } @@ -155,6 +155,10 @@ class MCAsmInfo { /// 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. @@ -228,7 +232,7 @@ class MCAsmInfo { /// True if the expression /// .long f - g - /// uses an relocation but it can be supressed by writting + /// uses a relocation but it can be suppressed by writing /// a = f - g /// .long a bool SetDirectiveSuppressesReloc; @@ -256,7 +260,7 @@ class MCAsmInfo { /// argument and how it is interpreted. Defaults to NoAlignment. LCOMM::LCOMMType LCOMMDirectiveAlignmentType; - // True if the target allows .align directives on funtions. This is true for + // True if the target allows .align directives on functions. This is true for // most targets, so defaults to true. bool HasFunctionAlignment; @@ -339,7 +343,7 @@ class MCAsmInfo { std::vector InitialFrameState; - //===--- Integrated Assembler State ----------------------------------===// + //===--- Integrated Assembler Information ----------------------------===// /// Should we use the integrated assembler? /// The integrated assembler should be enabled by default (by the @@ -351,6 +355,10 @@ class MCAsmInfo { /// Compress DWARF debug sections. Defaults to false. bool CompressDebugSections; + /// True if the integrated assembler should interpret 'a >> b' constant + /// expressions as logical rather than arithmetic. + bool UseLogicalShr; + public: explicit MCAsmInfo(); virtual ~MCAsmInfo(); @@ -384,7 +392,7 @@ class MCAsmInfo { /// Targets can implement this method to specify a section to switch to if the /// translation unit doesn't have any trampolines that require an executable /// stack. - virtual const MCSection *getNonexecutableStackSection(MCContext &Ctx) const { + virtual MCSection *getNonexecutableStackSection(MCContext &Ctx) const { return nullptr; } @@ -402,6 +410,10 @@ class MCAsmInfo { 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; } @@ -452,6 +464,7 @@ class MCAsmInfo { 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; } @@ -502,12 +515,13 @@ class MCAsmInfo { /// frame information to unwind. bool usesCFIForEH() const { return (ExceptionsType == ExceptionHandling::DwarfCFI || - ExceptionsType == ExceptionHandling::ARM || - ExceptionsType == ExceptionHandling::WinEH); + ExceptionsType == ExceptionHandling::ARM || usesWindowsCFI()); } bool usesWindowsCFI() const { - return ExceptionsType == ExceptionHandling::WinEH; + return ExceptionsType == ExceptionHandling::WinEH && + (WinEHEncodingType != WinEH::EncodingType::Invalid && + WinEHEncodingType != WinEH::EncodingType::X86); } bool doesDwarfUseRelocationsAcrossSections() const { @@ -538,6 +552,8 @@ class MCAsmInfo { void setCompressDebugSections(bool CompressDebugSections) { this->CompressDebugSections = CompressDebugSections; } + + bool shouldUseLogicalShr() const { return UseLogicalShr; } }; } diff --git a/include/llvm/MC/MCAsmInfoELF.h b/include/llvm/MC/MCAsmInfoELF.h index afd49336646..7125f5c7ad7 100644 --- a/include/llvm/MC/MCAsmInfoELF.h +++ b/include/llvm/MC/MCAsmInfoELF.h @@ -15,7 +15,7 @@ namespace llvm { class MCAsmInfoELF : public MCAsmInfo { virtual void anchor(); - const MCSection *getNonexecutableStackSection(MCContext &Ctx) const final; + MCSection *getNonexecutableStackSection(MCContext &Ctx) const final; protected: MCAsmInfoELF(); diff --git a/include/llvm/MC/MCAsmLayout.h b/include/llvm/MC/MCAsmLayout.h index 8b012be46c9..1b20d5b804a 100644 --- a/include/llvm/MC/MCAsmLayout.h +++ b/include/llvm/MC/MCAsmLayout.h @@ -16,9 +16,8 @@ namespace llvm { class MCAssembler; class MCFragment; -class MCSectionData; +class MCSection; class MCSymbol; -class MCSymbolData; /// Encapsulates the layout of an assembly file at a particular point in time. /// @@ -28,20 +27,15 @@ class MCSymbolData; /// efficiently compute the exact address of any symbol in the assembly file, /// even during the relaxation process. class MCAsmLayout { -public: - typedef llvm::SmallVectorImpl::const_iterator const_iterator; - typedef llvm::SmallVectorImpl::iterator iterator; - -private: MCAssembler &Assembler; /// List of sections in layout order. - llvm::SmallVector SectionOrder; + llvm::SmallVector SectionOrder; /// The last fragment which was laid out, or 0 if nothing has been laid /// out. Fragments are always laid out in order, so all fragments with a /// lower ordinal will be valid. - mutable DenseMap LastValidFragment; + mutable DenseMap LastValidFragment; /// \brief Make sure that the layout for the given fragment is valid, lazily /// computing it if necessary. @@ -66,43 +60,41 @@ class MCAsmLayout { /// been initialized. void layoutFragment(MCFragment *Fragment); - /// @name Section Access (in layout order) + /// \name Section Access (in layout order) /// @{ - llvm::SmallVectorImpl &getSectionOrder() { - return SectionOrder; - } - const llvm::SmallVectorImpl &getSectionOrder() const { + llvm::SmallVectorImpl &getSectionOrder() { return SectionOrder; } + const llvm::SmallVectorImpl &getSectionOrder() const { return SectionOrder; } /// @} - /// @name Fragment Layout Data + /// \name Fragment Layout Data /// @{ /// \brief Get the offset of the given fragment inside its containing section. uint64_t getFragmentOffset(const MCFragment *F) const; /// @} - /// @name Utility Functions + /// \name Utility Functions /// @{ /// \brief Get the address space size of the given section, as it effects /// layout. This may differ from the size reported by \see getSectionSize() by /// not including section tail padding. - uint64_t getSectionAddressSize(const MCSectionData *SD) const; + uint64_t getSectionAddressSize(const MCSection *Sec) const; /// \brief Get the data size of the given section, as emitted to the object /// file. This may include additional padding, or be 0 for virtual sections. - uint64_t getSectionFileSize(const MCSectionData *SD) const; + uint64_t getSectionFileSize(const MCSection *Sec) const; /// \brief Get the offset of the given symbol, as computed in the current /// layout. - /// \result True on success. - bool getSymbolOffset(const MCSymbolData *SD, uint64_t &Val) const; + /// \return True on success. + bool getSymbolOffset(const MCSymbol &S, uint64_t &Val) const; /// \brief Variant that reports a fatal error if the offset is not computable. - uint64_t getSymbolOffset(const MCSymbolData *SD) const; + uint64_t getSymbolOffset(const MCSymbol &S) const; /// \brief If this symbol is equivalent to A + Constant, return A. const MCSymbol *getBaseSymbol(const MCSymbol &Symbol) const; diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index b8e9227d0f8..0642af837e7 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -12,15 +12,16 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/iterator.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCFixup.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCLinkerOptimizationHint.h" +#include "llvm/MC/MCSection.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" @@ -37,21 +38,18 @@ class MCExpr; class MCFragment; class MCObjectWriter; class MCSection; -class MCSectionData; class MCSubtargetInfo; -class MCSymbol; -class MCSymbolData; class MCValue; class MCAsmBackend; class MCFragment : public ilist_node { friend class MCAsmLayout; - MCFragment(const MCFragment&) = delete; - void operator=(const MCFragment&) = delete; + MCFragment(const MCFragment &) = delete; + void operator=(const MCFragment &) = delete; public: - enum FragmentType { + enum FragmentType : uint8_t { FT_Align, FT_Data, FT_CompactEncodedInst, @@ -60,20 +58,33 @@ class MCFragment : public ilist_node { FT_Org, FT_Dwarf, FT_DwarfFrame, - FT_LEB + FT_LEB, + FT_SafeSEH }; private: FragmentType Kind; - /// Parent - The data for the section this fragment is in. - MCSectionData *Parent; +protected: + bool HasInstructions; + +private: + /// \brief Should this fragment be aligned to the end of a bundle? + bool AlignToBundleEnd; + + uint8_t BundlePadding; + + /// LayoutOrder - The layout order of this fragment. + unsigned LayoutOrder; + + /// The data for the section this fragment is in. + MCSection *Parent; /// Atom - The atom this fragment is in, as represented by it's defining /// symbol. - MCSymbolData *Atom; + const MCSymbol *Atom; - /// @name Assembler Backend Data + /// \name Assembler Backend Data /// @{ // // FIXME: This could all be kept private to the assembler implementation. @@ -82,51 +93,55 @@ class MCFragment : public ilist_node { /// initialized. uint64_t Offset; - /// LayoutOrder - The layout order of this fragment. - unsigned LayoutOrder; - /// @} protected: - MCFragment(FragmentType Kind, MCSectionData *Parent = nullptr); + MCFragment(FragmentType Kind, bool HasInstructions, + uint8_t BundlePadding, MCSection *Parent = nullptr); -public: - // Only for sentinel. + ~MCFragment(); +private: + + // This is a friend so that the sentinal can be created. + friend struct ilist_sentinel_traits; MCFragment(); - virtual ~MCFragment(); + +public: + /// Destroys the current fragment. + /// + /// This must be used instead of delete as MCFragment is non-virtual. + /// This method will dispatch to the appropriate subclass. + void destroy(); FragmentType getKind() const { return Kind; } - MCSectionData *getParent() const { return Parent; } - void setParent(MCSectionData *Value) { Parent = Value; } + MCSection *getParent() const { return Parent; } + void setParent(MCSection *Value) { Parent = Value; } - MCSymbolData *getAtom() const { return Atom; } - void setAtom(MCSymbolData *Value) { Atom = Value; } + const MCSymbol *getAtom() const { return Atom; } + void setAtom(const MCSymbol *Value) { Atom = Value; } unsigned getLayoutOrder() const { return LayoutOrder; } void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } /// \brief Does this fragment have instructions emitted into it? By default /// this is false, but specific fragment types may set it to true. - virtual bool hasInstructions() const { return false; } + bool hasInstructions() const { return HasInstructions; } /// \brief Should this fragment be placed at the end of an aligned bundle? - virtual bool alignToBundleEnd() const { return false; } - virtual void setAlignToBundleEnd(bool V) { } + bool alignToBundleEnd() const { return AlignToBundleEnd; } + void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; } /// \brief Get the padding size that must be inserted before this fragment. /// Used for bundling. By default, no padding is inserted. /// Note that padding size is restricted to 8 bits. This is an optimization /// to reduce the amount of space used for each fragment. In practice, larger /// padding should never be required. - virtual uint8_t getBundlePadding() const { - return 0; - } + uint8_t getBundlePadding() const { return BundlePadding; } /// \brief Set the padding size for this fragment. By default it's a no-op, /// and only some fragments have a meaningful implementation. - virtual void setBundlePadding(uint8_t N) { - } + void setBundlePadding(uint8_t N) { BundlePadding = N; } void dump(); }; @@ -135,65 +150,72 @@ class MCFragment : public ilist_node { /// data. /// class MCEncodedFragment : public MCFragment { - virtual void anchor(); +protected: + MCEncodedFragment(MCFragment::FragmentType FType, bool HasInstructions, + MCSection *Sec) + : MCFragment(FType, HasInstructions, 0, Sec) {} - uint8_t BundlePadding; public: - MCEncodedFragment(MCFragment::FragmentType FType, MCSectionData *SD = nullptr) - : MCFragment(FType, SD), BundlePadding(0) - { - } - ~MCEncodedFragment() override; - - virtual SmallVectorImpl &getContents() = 0; - virtual const SmallVectorImpl &getContents() const = 0; - - uint8_t getBundlePadding() const override { - return BundlePadding; - } - - void setBundlePadding(uint8_t N) override { - BundlePadding = N; - } - static bool classof(const MCFragment *F) { MCFragment::FragmentType Kind = F->getKind(); switch (Kind) { - default: - return false; - case MCFragment::FT_Relaxable: - case MCFragment::FT_CompactEncodedInst: - case MCFragment::FT_Data: - return true; + default: + return false; + case MCFragment::FT_Relaxable: + case MCFragment::FT_CompactEncodedInst: + case MCFragment::FT_Data: + return true; } } }; /// Interface implemented by fragments that contain encoded instructions and/or -/// data and also have fixups registered. +/// data. /// -class MCEncodedFragmentWithFixups : public MCEncodedFragment { - void anchor() override; +template +class MCEncodedFragmentWithContents : public MCEncodedFragment { + SmallVector Contents; + +protected: + MCEncodedFragmentWithContents(MCFragment::FragmentType FType, + bool HasInstructions, + MCSection *Sec) + : MCEncodedFragment(FType, HasInstructions, Sec) {} public: - MCEncodedFragmentWithFixups(MCFragment::FragmentType FType, - MCSectionData *SD = nullptr) - : MCEncodedFragment(FType, SD) - { - } + SmallVectorImpl &getContents() { return Contents; } + const SmallVectorImpl &getContents() const { return Contents; } +}; + +/// Interface implemented by fragments that contain encoded instructions and/or +/// data and also have fixups registered. +/// +template +class MCEncodedFragmentWithFixups : + public MCEncodedFragmentWithContents { + + /// Fixups - The list of fixups in this fragment. + SmallVector Fixups; - ~MCEncodedFragmentWithFixups() override; +protected: + MCEncodedFragmentWithFixups(MCFragment::FragmentType FType, + bool HasInstructions, + MCSection *Sec) + : MCEncodedFragmentWithContents(FType, HasInstructions, + Sec) {} +public: typedef SmallVectorImpl::const_iterator const_fixup_iterator; typedef SmallVectorImpl::iterator fixup_iterator; - virtual SmallVectorImpl &getFixups() = 0; - virtual const SmallVectorImpl &getFixups() const = 0; + SmallVectorImpl &getFixups() { return Fixups; } + const SmallVectorImpl &getFixups() const { return Fixups; } + + fixup_iterator fixup_begin() { return Fixups.begin(); } + const_fixup_iterator fixup_begin() const { return Fixups.begin(); } - virtual fixup_iterator fixup_begin() = 0; - virtual const_fixup_iterator fixup_begin() const = 0; - virtual fixup_iterator fixup_end() = 0; - virtual const_fixup_iterator fixup_end() const = 0; + fixup_iterator fixup_end() { return Fixups.end(); } + const_fixup_iterator fixup_end() const { return Fixups.end(); } static bool classof(const MCFragment *F) { MCFragment::FragmentType Kind = F->getKind(); @@ -203,50 +225,12 @@ class MCEncodedFragmentWithFixups : public MCEncodedFragment { /// Fragment for data and encoded instructions. /// -class MCDataFragment : public MCEncodedFragmentWithFixups { - void anchor() override; - - /// \brief Does this fragment contain encoded instructions anywhere in it? - bool HasInstructions; - - /// \brief Should this fragment be aligned to the end of a bundle? - bool AlignToBundleEnd; - - SmallVector Contents; - - /// Fixups - The list of fixups in this fragment. - SmallVector Fixups; +class MCDataFragment : public MCEncodedFragmentWithFixups<32, 4> { public: - MCDataFragment(MCSectionData *SD = nullptr) - : MCEncodedFragmentWithFixups(FT_Data, SD), - HasInstructions(false), AlignToBundleEnd(false) - { - } + MCDataFragment(MCSection *Sec = nullptr) + : MCEncodedFragmentWithFixups<32, 4>(FT_Data, false, Sec) {} - SmallVectorImpl &getContents() override { return Contents; } - const SmallVectorImpl &getContents() const override { - return Contents; - } - - SmallVectorImpl &getFixups() override { - return Fixups; - } - - const SmallVectorImpl &getFixups() const override { - return Fixups; - } - - bool hasInstructions() const override { return HasInstructions; } - virtual void setHasInstructions(bool V) { HasInstructions = V; } - - bool alignToBundleEnd() const override { return AlignToBundleEnd; } - void setAlignToBundleEnd(bool V) override { AlignToBundleEnd = V; } - - fixup_iterator fixup_begin() override { return Fixups.begin(); } - const_fixup_iterator fixup_begin() const override { return Fixups.begin(); } - - fixup_iterator fixup_end() override {return Fixups.end();} - const_fixup_iterator fixup_end() const override {return Fixups.end();} + void setHasInstructions(bool V) { HasInstructions = V; } static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Data; @@ -258,29 +242,12 @@ class MCDataFragment : public MCEncodedFragmentWithFixups { /// it can be used instead of MCDataFragment and lead to lower memory /// consumption. /// -class MCCompactEncodedInstFragment : public MCEncodedFragment { - void anchor() override; - - /// \brief Should this fragment be aligned to the end of a bundle? - bool AlignToBundleEnd; - - SmallVector Contents; +class MCCompactEncodedInstFragment : public MCEncodedFragmentWithContents<4> { public: - MCCompactEncodedInstFragment(MCSectionData *SD = nullptr) - : MCEncodedFragment(FT_CompactEncodedInst, SD), AlignToBundleEnd(false) - { + MCCompactEncodedInstFragment(MCSection *Sec = nullptr) + : MCEncodedFragmentWithContents(FT_CompactEncodedInst, true, Sec) { } - bool hasInstructions() const override { - return true; - } - - SmallVectorImpl &getContents() override { return Contents; } - const SmallVectorImpl &getContents() const override { return Contents; } - - bool alignToBundleEnd() const override { return AlignToBundleEnd; } - void setAlignToBundleEnd(bool V) override { AlignToBundleEnd = V; } - static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_CompactEncodedInst; } @@ -289,8 +256,7 @@ class MCCompactEncodedInstFragment : public MCEncodedFragment { /// A relaxable fragment holds on to its MCInst, since it may need to be /// relaxed during the assembler layout and relaxation stage. /// -class MCRelaxableFragment : public MCEncodedFragmentWithFixups { - void anchor() override; +class MCRelaxableFragment : public MCEncodedFragmentWithFixups<8, 1> { /// Inst - The instruction this is a fragment for. MCInst Inst; @@ -300,52 +266,32 @@ class MCRelaxableFragment : public MCEncodedFragmentWithFixups { /// in the assembler are not seen here. const MCSubtargetInfo STI; - /// Contents - Binary data for the currently encoded instruction. - SmallVector Contents; - - /// Fixups - The list of fixups in this fragment. - SmallVector Fixups; - public: MCRelaxableFragment(const MCInst &Inst, const MCSubtargetInfo &STI, - MCSectionData *SD = nullptr) - : MCEncodedFragmentWithFixups(FT_Relaxable, SD), Inst(Inst), STI(STI) {} - - SmallVectorImpl &getContents() override { return Contents; } - const SmallVectorImpl &getContents() const override { return Contents; } + MCSection *Sec = nullptr) + : MCEncodedFragmentWithFixups(FT_Relaxable, true, Sec), + Inst(Inst), STI(STI) {} const MCInst &getInst() const { return Inst; } - void setInst(const MCInst& Value) { Inst = Value; } + void setInst(const MCInst &Value) { Inst = Value; } const MCSubtargetInfo &getSubtargetInfo() { return STI; } - SmallVectorImpl &getFixups() override { - return Fixups; - } - - const SmallVectorImpl &getFixups() const override { - return Fixups; - } - - bool hasInstructions() const override { return true; } - - fixup_iterator fixup_begin() override { return Fixups.begin(); } - const_fixup_iterator fixup_begin() const override { return Fixups.begin(); } - - fixup_iterator fixup_end() override {return Fixups.end();} - const_fixup_iterator fixup_end() const override {return Fixups.end();} - static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Relaxable; } }; class MCAlignFragment : public MCFragment { - virtual void anchor(); /// Alignment - The alignment to ensure, in bytes. unsigned Alignment; + /// EmitNops - Flag to indicate that (optimal) NOPs should be emitted instead + /// of using the provided value. The exact interpretation of this flag is + /// target dependent. + bool EmitNops : 1; + /// Value - Value to use for filling padding bytes. int64_t Value; @@ -356,18 +302,14 @@ class MCAlignFragment : public MCFragment { /// cannot be satisfied in this width then this fragment is ignored. unsigned MaxBytesToEmit; - /// EmitNops - Flag to indicate that (optimal) NOPs should be emitted instead - /// of using the provided value. The exact interpretation of this flag is - /// target dependent. - bool EmitNops : 1; - public: MCAlignFragment(unsigned Alignment, int64_t Value, unsigned ValueSize, - unsigned MaxBytesToEmit, MCSectionData *SD = nullptr) - : MCFragment(FT_Align, SD), Alignment(Alignment), Value(Value), - ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit), EmitNops(false) {} + unsigned MaxBytesToEmit, MCSection *Sec = nullptr) + : MCFragment(FT_Align, false, 0, Sec), Alignment(Alignment), + EmitNops(false), Value(Value), + ValueSize(ValueSize), MaxBytesToEmit(MaxBytesToEmit) {} - /// @name Accessors + /// \name Accessors /// @{ unsigned getAlignment() const { return Alignment; } @@ -389,7 +331,6 @@ class MCAlignFragment : public MCFragment { }; class MCFillFragment : public MCFragment { - virtual void anchor(); /// Value - Value to use for filling bytes. int64_t Value; @@ -403,14 +344,14 @@ class MCFillFragment : public MCFragment { public: MCFillFragment(int64_t Value, unsigned ValueSize, uint64_t Size, - MCSectionData *SD = nullptr) - : MCFragment(FT_Fill, SD), Value(Value), ValueSize(ValueSize), + MCSection *Sec = nullptr) + : MCFragment(FT_Fill, false, 0, Sec), Value(Value), ValueSize(ValueSize), Size(Size) { assert((!ValueSize || (Size % ValueSize) == 0) && "Fill size must be a multiple of the value size!"); } - /// @name Accessors + /// \name Accessors /// @{ int64_t getValue() const { return Value; } @@ -427,7 +368,6 @@ class MCFillFragment : public MCFragment { }; class MCOrgFragment : public MCFragment { - virtual void anchor(); /// Offset - The offset this fragment should start at. const MCExpr *Offset; @@ -436,10 +376,10 @@ class MCOrgFragment : public MCFragment { int8_t Value; public: - MCOrgFragment(const MCExpr &Offset, int8_t Value, MCSectionData *SD = nullptr) - : MCFragment(FT_Org, SD), Offset(&Offset), Value(Value) {} + MCOrgFragment(const MCExpr &Offset, int8_t Value, MCSection *Sec = nullptr) + : MCFragment(FT_Org, false, 0, Sec), Offset(&Offset), Value(Value) {} - /// @name Accessors + /// \name Accessors /// @{ const MCExpr &getOffset() const { return *Offset; } @@ -454,7 +394,6 @@ class MCOrgFragment : public MCFragment { }; class MCLEBFragment : public MCFragment { - virtual void anchor(); /// Value - The value this fragment should contain. const MCExpr *Value; @@ -463,13 +402,14 @@ class MCLEBFragment : public MCFragment { bool IsSigned; SmallString<8> Contents; + public: - MCLEBFragment(const MCExpr &Value_, bool IsSigned_, - MCSectionData *SD = nullptr) - : MCFragment(FT_LEB, SD), - Value(&Value_), IsSigned(IsSigned_) { Contents.push_back(0); } + MCLEBFragment(const MCExpr &Value_, bool IsSigned_, MCSection *Sec = nullptr) + : MCFragment(FT_LEB, false, 0, Sec), Value(&Value_), IsSigned(IsSigned_) { + Contents.push_back(0); + } - /// @name Accessors + /// \name Accessors /// @{ const MCExpr &getValue() const { return *Value; } @@ -487,7 +427,6 @@ class MCLEBFragment : public MCFragment { }; class MCDwarfLineAddrFragment : public MCFragment { - virtual void anchor(); /// LineDelta - the value of the difference between the two line numbers /// between two .loc dwarf directives. @@ -501,12 +440,13 @@ class MCDwarfLineAddrFragment : public MCFragment { public: MCDwarfLineAddrFragment(int64_t LineDelta, const MCExpr &AddrDelta, - MCSectionData *SD = nullptr) - : MCFragment(FT_Dwarf, SD), LineDelta(LineDelta), AddrDelta(&AddrDelta) { + MCSection *Sec = nullptr) + : MCFragment(FT_Dwarf, false, 0, Sec), LineDelta(LineDelta), + AddrDelta(&AddrDelta) { Contents.push_back(0); } - /// @name Accessors + /// \name Accessors /// @{ int64_t getLineDelta() const { return LineDelta; } @@ -524,7 +464,6 @@ class MCDwarfLineAddrFragment : public MCFragment { }; class MCDwarfCallFrameFragment : public MCFragment { - virtual void anchor(); /// AddrDelta - The expression for the difference of the two symbols that /// make up the address delta between two .cfi_* dwarf directives. @@ -533,12 +472,12 @@ class MCDwarfCallFrameFragment : public MCFragment { SmallString<8> Contents; public: - MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSectionData *SD = nullptr) - : MCFragment(FT_DwarfFrame, SD), AddrDelta(&AddrDelta) { + MCDwarfCallFrameFragment(const MCExpr &AddrDelta, MCSection *Sec = nullptr) + : MCFragment(FT_DwarfFrame, false, 0, Sec), AddrDelta(&AddrDelta) { Contents.push_back(0); } - /// @name Accessors + /// \name Accessors /// @{ const MCExpr &getAddrDelta() const { return *AddrDelta; } @@ -553,265 +492,30 @@ class MCDwarfCallFrameFragment : public MCFragment { } }; -// FIXME: Should this be a separate class, or just merged into MCSection? Since -// we anticipate the fast path being through an MCAssembler, the only reason to -// keep it out is for API abstraction. -class MCSectionData : public ilist_node { - friend class MCAsmLayout; - - MCSectionData(const MCSectionData&) = delete; - void operator=(const MCSectionData&) = delete; +class MCSafeSEHFragment : public MCFragment { + const MCSymbol *Sym; public: - typedef iplist FragmentListType; - - typedef FragmentListType::const_iterator const_iterator; - typedef FragmentListType::iterator iterator; - - typedef FragmentListType::const_reverse_iterator const_reverse_iterator; - typedef FragmentListType::reverse_iterator reverse_iterator; - - /// \brief Express the state of bundle locked groups while emitting code. - enum BundleLockStateType { - NotBundleLocked, - BundleLocked, - BundleLockedAlignToEnd - }; -private: - FragmentListType Fragments; - const MCSection *Section; - - /// Ordinal - The section index in the assemblers section list. - unsigned Ordinal; - - /// LayoutOrder - The index of this section in the layout order. - unsigned LayoutOrder; - - /// Alignment - The maximum alignment seen in this section. - unsigned Alignment; - - /// \brief Keeping track of bundle-locked state. - BundleLockStateType BundleLockState; + MCSafeSEHFragment(const MCSymbol *Sym, MCSection *Sec = nullptr) + : MCFragment(FT_SafeSEH, false, 0, Sec), Sym(Sym) {} - /// \brief Current nesting depth of bundle_lock directives. - unsigned BundleLockNestingDepth; - - /// \brief We've seen a bundle_lock directive but not its first instruction - /// yet. - bool BundleGroupBeforeFirstInst; - - /// @name Assembler Backend Data + /// \name Accessors /// @{ - // - // FIXME: This could all be kept private to the assembler implementation. - /// HasInstructions - Whether this section has had instructions emitted into - /// it. - unsigned HasInstructions : 1; - - /// Mapping from subsection number to insertion point for subsection numbers - /// below that number. - SmallVector, 1> SubsectionFragmentMap; + const MCSymbol *getSymbol() { return Sym; } + const MCSymbol *getSymbol() const { return Sym; } /// @} -public: - // Only for use as sentinel. - MCSectionData(); - MCSectionData(const MCSection &Section, MCAssembler *A = nullptr); - - const MCSection &getSection() const { return *Section; } - - unsigned getAlignment() const { return Alignment; } - void setAlignment(unsigned Value) { Alignment = Value; } - - bool hasInstructions() const { return HasInstructions; } - void setHasInstructions(bool Value) { HasInstructions = Value; } - - unsigned getOrdinal() const { return Ordinal; } - void setOrdinal(unsigned Value) { Ordinal = Value; } - - unsigned getLayoutOrder() const { return LayoutOrder; } - void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } - - /// @name Fragment Access - /// @{ - - const FragmentListType &getFragmentList() const { return Fragments; } - FragmentListType &getFragmentList() { return Fragments; } - - iterator begin() { return Fragments.begin(); } - const_iterator begin() const { return Fragments.begin(); } - - iterator end() { return Fragments.end(); } - const_iterator end() const { return Fragments.end(); } - - reverse_iterator rbegin() { return Fragments.rbegin(); } - const_reverse_iterator rbegin() const { return Fragments.rbegin(); } - - reverse_iterator rend() { return Fragments.rend(); } - const_reverse_iterator rend() const { return Fragments.rend(); } - - size_t size() const { return Fragments.size(); } - - bool empty() const { return Fragments.empty(); } - - iterator getSubsectionInsertionPoint(unsigned Subsection); - - bool isBundleLocked() const { - return BundleLockState != NotBundleLocked; - } - - BundleLockStateType getBundleLockState() const { - return BundleLockState; - } - - void setBundleLockState(BundleLockStateType NewState); - - bool isBundleGroupBeforeFirstInst() const { - return BundleGroupBeforeFirstInst; - } - - void setBundleGroupBeforeFirstInst(bool IsFirst) { - BundleGroupBeforeFirstInst = IsFirst; - } - - void dump(); - - /// @} -}; - -// FIXME: Same concerns as with SectionData. -class MCSymbolData : public ilist_node { - const MCSymbol *Symbol; - - /// Fragment - The fragment this symbol's value is relative to, if any. Also - /// stores if this symbol is visible outside this translation unit (bit 0) or - /// if it is private extern (bit 1). - PointerIntPair Fragment; - - union { - /// Offset - The offset to apply to the fragment address to form this - /// symbol's value. - uint64_t Offset; - - /// CommonSize - The size of the symbol, if it is 'common'. - uint64_t CommonSize; - }; - - /// SymbolSize - An expression describing how to calculate the size of - /// a symbol. If a symbol has no size this field will be NULL. - const MCExpr *SymbolSize; - - /// CommonAlign - The alignment of the symbol, if it is 'common', or -1. - // - // FIXME: Pack this in with other fields? - unsigned CommonAlign; - - /// Flags - The Flags field is used by object file implementations to store - /// additional per symbol information which is not easily classified. - uint32_t Flags; - - /// Index - Index field, for use by the object file implementation. - uint64_t Index; - -public: - // Only for use as sentinel. - MCSymbolData(); - MCSymbolData(const MCSymbol &Symbol, MCFragment *Fragment, uint64_t Offset, - MCAssembler *A = nullptr); - - /// @name Accessors - /// @{ - - const MCSymbol &getSymbol() const { return *Symbol; } - - MCFragment *getFragment() const { return Fragment.getPointer(); } - void setFragment(MCFragment *Value) { Fragment.setPointer(Value); } - - uint64_t getOffset() const { - assert(!isCommon()); - return Offset; - } - void setOffset(uint64_t Value) { - assert(!isCommon()); - Offset = Value; - } - - /// @} - /// @name Symbol Attributes - /// @{ - - bool isExternal() const { return Fragment.getInt() & 1; } - void setExternal(bool Value) { - Fragment.setInt((Fragment.getInt() & ~1) | unsigned(Value)); - } - - bool isPrivateExtern() const { return Fragment.getInt() & 2; } - void setPrivateExtern(bool Value) { - Fragment.setInt((Fragment.getInt() & ~2) | (unsigned(Value) << 1)); - } - - /// isCommon - Is this a 'common' symbol. - bool isCommon() const { return CommonAlign != -1U; } - - /// setCommon - Mark this symbol as being 'common'. - /// - /// \param Size - The size of the symbol. - /// \param Align - The alignment of the symbol. - void setCommon(uint64_t Size, unsigned Align) { - assert(getOffset() == 0); - CommonSize = Size; - CommonAlign = Align; - } - - /// getCommonSize - Return the size of a 'common' symbol. - uint64_t getCommonSize() const { - assert(isCommon() && "Not a 'common' symbol!"); - return CommonSize; - } - - void setSize(const MCExpr *SS) { - SymbolSize = SS; - } - - const MCExpr *getSize() const { - return SymbolSize; - } - - - /// getCommonAlignment - Return the alignment of a 'common' symbol. - unsigned getCommonAlignment() const { - assert(isCommon() && "Not a 'common' symbol!"); - return CommonAlign; - } - - /// getFlags - Get the (implementation defined) symbol flags. - uint32_t getFlags() const { return Flags; } - - /// setFlags - Set the (implementation defined) symbol flags. - void setFlags(uint32_t Value) { Flags = Value; } - - /// modifyFlags - Modify the flags via a mask - void modifyFlags(uint32_t Value, uint32_t Mask) { - Flags = (Flags & ~Mask) | Value; + static bool classof(const MCFragment *F) { + return F->getKind() == MCFragment::FT_SafeSEH; } - - /// getIndex - Get the (implementation defined) index. - uint64_t getIndex() const { return Index; } - - /// setIndex - Set the (implementation defined) index. - void setIndex(uint64_t Value) { Index = Value; } - - /// @} - - void dump() const; }; // FIXME: This really doesn't belong here. See comments below. struct IndirectSymbolData { MCSymbol *Symbol; - MCSectionData *SectionData; + MCSection *Section; }; // FIXME: Ditto this. Purely so the Streamer and the ObjectWriter can talk @@ -828,27 +532,25 @@ class MCAssembler { friend class MCAsmLayout; public: - typedef iplist SectionDataListType; - typedef iplist SymbolDataListType; + typedef std::vector SectionListType; + typedef std::vector SymbolDataListType; - typedef SectionDataListType::const_iterator const_iterator; - typedef SectionDataListType::iterator iterator; + typedef pointee_iterator const_iterator; + typedef pointee_iterator iterator; - typedef SymbolDataListType::const_iterator const_symbol_iterator; - typedef SymbolDataListType::iterator symbol_iterator; + typedef pointee_iterator + const_symbol_iterator; + typedef pointee_iterator symbol_iterator; typedef iterator_range symbol_range; typedef iterator_range const_symbol_range; - typedef std::vector FileNameVectorType; - typedef FileNameVectorType::const_iterator const_file_name_iterator; - typedef std::vector::const_iterator - const_indirect_symbol_iterator; + const_indirect_symbol_iterator; typedef std::vector::iterator indirect_symbol_iterator; typedef std::vector::const_iterator - const_data_region_iterator; + const_data_region_iterator; typedef std::vector::iterator data_region_iterator; /// MachO specific deployment target version info. @@ -860,9 +562,10 @@ class MCAssembler { unsigned Minor; unsigned Update; } VersionMinInfoType; + private: - MCAssembler(const MCAssembler&) = delete; - void operator=(const MCAssembler&) = delete; + MCAssembler(const MCAssembler &) = delete; + void operator=(const MCAssembler &) = delete; MCContext &Context; @@ -874,31 +577,19 @@ class MCAssembler { raw_ostream &OS; - iplist Sections; - - iplist Symbols; + SectionListType Sections; - DenseSet LocalsUsedInReloc; - - /// The map of sections to their associated assembler backend data. - // - // FIXME: Avoid this indirection? - DenseMap SectionMap; - - /// The map of symbols to their associated assembler backend data. - // - // FIXME: Avoid this indirection? - DenseMap SymbolMap; + SymbolDataListType Symbols; std::vector IndirectSymbols; std::vector DataRegions; /// The list of linker options to propagate into the object file. - std::vector > LinkerOptions; + std::vector> LinkerOptions; /// List of declared file names - FileNameVectorType FileNames; + std::vector FileNames; /// The set of function symbols for which a .thumb_func directive has /// been seen. @@ -907,7 +598,7 @@ class MCAssembler { // here. Maybe when the relocation stuff moves to target specific, // this can go with it? The streamer would need some target specific // refactoring too. - mutable SmallPtrSet ThumbFuncs; + mutable SmallPtrSet ThumbFuncs; /// \brief The bundle alignment size currently set in the assembler. /// @@ -929,6 +620,7 @@ class MCAssembler { MCLOHContainer LOHContainer; VersionMinInfoType VersionMinInfo; + private: /// Evaluate a fixup to a relocatable expression and the value which should be /// placed into the fixup. @@ -943,9 +635,9 @@ class MCAssembler { /// \return Whether the fixup value was fully resolved. This is true if the /// \p Value result is fixed, otherwise the value may change due to /// relocation. - bool evaluateFixup(const MCAsmLayout &Layout, - const MCFixup &Fixup, const MCFragment *DF, - MCValue &Target, uint64_t &Value) const; + bool evaluateFixup(const MCAsmLayout &Layout, const MCFixup &Fixup, + const MCFragment *DF, MCValue &Target, + uint64_t &Value) const; /// Check whether a fixup can be satisfied, or whether it needs to be relaxed /// (increased in size, in order to hold its value correctly). @@ -962,7 +654,7 @@ class MCAssembler { /// \brief Perform one layout iteration of the given section and return true /// if any offsets were adjusted. - bool layoutSectionOnce(MCAsmLayout &Layout, MCSectionData &SD); + bool layoutSectionOnce(MCAsmLayout &Layout, MCSection &Sec); bool relaxInstruction(MCAsmLayout &Layout, MCRelaxableFragment &IF); @@ -979,9 +671,6 @@ class MCAssembler { MCFragment &F, const MCFixup &Fixup); public: - void addLocalUsedInReloc(const MCSymbol &Sym); - bool isLocalUsedInReloc(const MCSymbol &Sym) const; - /// Compute the effective fragment size assuming it is laid out at the given /// \p SectionAddress and \p FragmentOffset. uint64_t computeFragmentSize(const MCAsmLayout &Layout, @@ -989,7 +678,7 @@ class MCAssembler { /// Find the symbol which defines the atom containing the given symbol, or /// null if there is no such symbol. - const MCSymbolData *getAtom(const MCSymbolData *Symbol) const; + const MCSymbol *getAtom(const MCSymbol &S) const; /// Check whether a particular symbol is visible to the linker and is required /// in the symbol table, or whether it can be discarded by the assembler. This @@ -998,7 +687,7 @@ class MCAssembler { bool isSymbolLinkerVisible(const MCSymbol &SD) const; /// Emit the section contents using the given object writer. - void writeSectionData(const MCSectionData *Section, + void writeSectionData(const MCSection *Section, const MCAsmLayout &Layout) const; /// Check whether a given symbol has been flagged with .thumb_func. @@ -1008,8 +697,8 @@ class MCAssembler { void setIsThumbFunc(const MCSymbol *Func) { ThumbFuncs.insert(Func); } /// ELF e_header flags - unsigned getELFHeaderEFlags() const {return ELFHeaderEFlags;} - void setELFHeaderEFlags(unsigned Flags) { ELFHeaderEFlags = Flags;} + unsigned getELFHeaderEFlags() const { return ELFHeaderEFlags; } + void setELFHeaderEFlags(unsigned Flags) { ELFHeaderEFlags = Flags; } /// MachO deployment target version information. const VersionMinInfoType &getVersionMinInfo() const { return VersionMinInfo; } @@ -1053,36 +742,25 @@ class MCAssembler { void Finish(); // FIXME: This does not belong here. - bool getSubsectionsViaSymbols() const { - return SubsectionsViaSymbols; - } - void setSubsectionsViaSymbols(bool Value) { - SubsectionsViaSymbols = Value; - } + bool getSubsectionsViaSymbols() const { return SubsectionsViaSymbols; } + void setSubsectionsViaSymbols(bool Value) { SubsectionsViaSymbols = Value; } bool getRelaxAll() const { return RelaxAll; } void setRelaxAll(bool Value) { RelaxAll = Value; } - bool isBundlingEnabled() const { - return BundleAlignSize != 0; - } + bool isBundlingEnabled() const { return BundleAlignSize != 0; } - unsigned getBundleAlignSize() const { - return BundleAlignSize; - } + unsigned getBundleAlignSize() const { return BundleAlignSize; } void setBundleAlignSize(unsigned Size) { - assert((Size == 0 || !(Size & (Size - 1))) && + assert((Size == 0 || !(Size & (Size - 1))) && "Expect a power-of-two bundle align size"); BundleAlignSize = Size; } - /// @name Section List Access + /// \name Section List Access /// @{ - const SectionDataListType &getSectionList() const { return Sections; } - SectionDataListType &getSectionList() { return Sections; } - iterator begin() { return Sections.begin(); } const_iterator begin() const { return Sections.begin(); } @@ -1092,12 +770,8 @@ class MCAssembler { size_t size() const { return Sections.size(); } /// @} - /// @name Symbol List Access + /// \name Symbol List Access /// @{ - - const SymbolDataListType &getSymbolList() const { return Symbols; } - SymbolDataListType &getSymbolList() { return Symbols; } - symbol_iterator symbol_begin() { return Symbols.begin(); } const_symbol_iterator symbol_begin() const { return Symbols.begin(); } @@ -1105,12 +779,14 @@ class MCAssembler { const_symbol_iterator symbol_end() const { return Symbols.end(); } symbol_range symbols() { return make_range(symbol_begin(), symbol_end()); } - const_symbol_range symbols() const { return make_range(symbol_begin(), symbol_end()); } + const_symbol_range symbols() const { + return make_range(symbol_begin(), symbol_end()); + } size_t symbol_size() const { return Symbols.size(); } /// @} - /// @name Indirect Symbol List Access + /// \name Indirect Symbol List Access /// @{ // FIXME: This is a total hack, this should not be here. Once things are @@ -1137,34 +813,28 @@ class MCAssembler { size_t indirect_symbol_size() const { return IndirectSymbols.size(); } /// @} - /// @name Linker Option List Access + /// \name Linker Option List Access /// @{ - std::vector > &getLinkerOptions() { + std::vector> &getLinkerOptions() { return LinkerOptions; } /// @} - /// @name Data Region List Access + /// \name Data Region List Access /// @{ // FIXME: This is a total hack, this should not be here. Once things are // factored so that the streamer has direct access to the .o writer, it can // disappear. - std::vector &getDataRegions() { - return DataRegions; - } + std::vector &getDataRegions() { return DataRegions; } - data_region_iterator data_region_begin() { - return DataRegions.begin(); - } + data_region_iterator data_region_begin() { return DataRegions.begin(); } const_data_region_iterator data_region_begin() const { return DataRegions.begin(); } - data_region_iterator data_region_end() { - return DataRegions.end(); - } + data_region_iterator data_region_end() { return DataRegions.end(); } const_data_region_iterator data_region_end() const { return DataRegions.end(); } @@ -1172,76 +842,35 @@ class MCAssembler { size_t data_region_size() const { return DataRegions.size(); } /// @} - /// @name Data Region List Access + /// \name Data Region List Access /// @{ // FIXME: This is a total hack, this should not be here. Once things are // factored so that the streamer has direct access to the .o writer, it can // disappear. - MCLOHContainer & getLOHContainer() { - return LOHContainer; - } - const MCLOHContainer & getLOHContainer() const { + MCLOHContainer &getLOHContainer() { return LOHContainer; } + const MCLOHContainer &getLOHContainer() const { return const_cast(this)->getLOHContainer(); } /// @} - /// @name Backend Data Access + /// \name Backend Data Access /// @{ - MCSectionData &getSectionData(const MCSection &Section) const { - MCSectionData *Entry = SectionMap.lookup(&Section); - assert(Entry && "Missing section data!"); - return *Entry; - } - - MCSectionData &getOrCreateSectionData(const MCSection &Section, - bool *Created = nullptr) { - MCSectionData *&Entry = SectionMap[&Section]; - - if (Created) *Created = !Entry; - if (!Entry) - Entry = new MCSectionData(Section, this); - - return *Entry; - } - - bool hasSymbolData(const MCSymbol &Symbol) const { - return SymbolMap.lookup(&Symbol) != nullptr; - } - - MCSymbolData &getSymbolData(const MCSymbol &Symbol) { - return const_cast( - static_cast(*this).getSymbolData(Symbol)); - } - - const MCSymbolData &getSymbolData(const MCSymbol &Symbol) const { - MCSymbolData *Entry = SymbolMap.lookup(&Symbol); - assert(Entry && "Missing symbol data!"); - return *Entry; - } - - MCSymbolData &getOrCreateSymbolData(const MCSymbol &Symbol, - bool *Created = nullptr) { - MCSymbolData *&Entry = SymbolMap[&Symbol]; - - if (Created) *Created = !Entry; - if (!Entry) - Entry = new MCSymbolData(Symbol, nullptr, 0, this); - - return *Entry; + bool registerSection(MCSection &Section) { + if (Section.isRegistered()) + return false; + Sections.push_back(&Section); + Section.setIsRegistered(true); + return true; } - const_file_name_iterator file_names_begin() const { - return FileNames.begin(); - } + void registerSymbol(const MCSymbol &Symbol, bool *Created = nullptr); - const_file_name_iterator file_names_end() const { - return FileNames.end(); - } + ArrayRef getFileNames() { return FileNames; } void addFileName(StringRef FileName) { - if (std::find(file_names_begin(), file_names_end(), FileName) == - file_names_end()) + if (std::find(FileNames.begin(), FileNames.end(), FileName) == + FileNames.end()) FileNames.push_back(FileName); } @@ -1258,8 +887,7 @@ class MCAssembler { /// \brief Compute the amount of padding required before the fragment \p F to /// obey bundling restrictions, where \p FOffset is the fragment's offset in /// its section and \p FSize is the fragment's size. -uint64_t computeBundlePadding(const MCAssembler &Assembler, - const MCFragment *F, +uint64_t computeBundlePadding(const MCAssembler &Assembler, const MCFragment *F, uint64_t FOffset, uint64_t FSize); } // end namespace llvm diff --git a/include/llvm/MC/MCCodeEmitter.h b/include/llvm/MC/MCCodeEmitter.h index ddf0f82e39e..b6c19150c12 100644 --- a/include/llvm/MC/MCCodeEmitter.h +++ b/include/llvm/MC/MCCodeEmitter.h @@ -24,6 +24,7 @@ class MCCodeEmitter { private: MCCodeEmitter(const MCCodeEmitter &) = delete; void operator=(const MCCodeEmitter &) = delete; + protected: // Can only create subclasses. MCCodeEmitter(); @@ -31,11 +32,11 @@ class MCCodeEmitter { virtual ~MCCodeEmitter(); /// Lifetime management - virtual void reset() { } + virtual void reset() {} /// EncodeInstruction - Encode the given \p Inst to bytes on the output /// stream \p OS. - virtual void EncodeInstruction(const MCInst &Inst, raw_ostream &OS, + virtual void encodeInstruction(const MCInst &Inst, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const = 0; }; diff --git a/include/llvm/MC/MCCodeGenInfo.h b/include/llvm/MC/MCCodeGenInfo.h index 84ce934d822..0a4744f1d0f 100644 --- a/include/llvm/MC/MCCodeGenInfo.h +++ b/include/llvm/MC/MCCodeGenInfo.h @@ -19,33 +19,33 @@ namespace llvm { - class MCCodeGenInfo { - /// RelocationModel - Relocation model: static, pic, etc. - /// - Reloc::Model RelocationModel; +class MCCodeGenInfo { + /// RelocationModel - Relocation model: static, pic, etc. + /// + Reloc::Model RelocationModel; - /// CMModel - Code model. - /// - CodeModel::Model CMModel; + /// CMModel - Code model. + /// + CodeModel::Model CMModel; - /// OptLevel - Optimization level. - /// - CodeGenOpt::Level OptLevel; + /// OptLevel - Optimization level. + /// + CodeGenOpt::Level OptLevel; - public: - void InitMCCodeGenInfo(Reloc::Model RM = Reloc::Default, - CodeModel::Model CM = CodeModel::Default, - CodeGenOpt::Level OL = CodeGenOpt::Default); +public: + void initMCCodeGenInfo(Reloc::Model RM = Reloc::Default, + CodeModel::Model CM = CodeModel::Default, + CodeGenOpt::Level OL = CodeGenOpt::Default); - Reloc::Model getRelocationModel() const { return RelocationModel; } + Reloc::Model getRelocationModel() const { return RelocationModel; } - CodeModel::Model getCodeModel() const { return CMModel; } + CodeModel::Model getCodeModel() const { return CMModel; } - CodeGenOpt::Level getOptLevel() const { return OptLevel; } + CodeGenOpt::Level getOptLevel() const { return OptLevel; } - // Allow overriding OptLevel on a per-function basis. - void setOptLevel(CodeGenOpt::Level Level) { OptLevel = Level; } - }; + // Allow overriding OptLevel on a per-function basis. + void setOptLevel(CodeGenOpt::Level Level) { OptLevel = Level; } +}; } // namespace llvm #endif diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index bf473ccc68e..41169e9a12a 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -30,6 +30,7 @@ namespace llvm { class MCExpr; class MCSection; class MCSymbol; + class MCSymbolELF; class MCLabel; struct MCDwarfFile; class MCDwarfLoc; @@ -45,10 +46,12 @@ namespace llvm { /// sections that it creates. /// class MCContext { - MCContext(const MCContext&) = delete; - MCContext &operator=(const MCContext&) = delete; + MCContext(const MCContext &) = delete; + MCContext &operator=(const MCContext &) = delete; + public: - typedef StringMap SymbolTable; + typedef StringMap SymbolTable; + private: /// The SourceMgr for this object, if any. const SourceMgr *SrcMgr; @@ -73,19 +76,19 @@ namespace llvm { /// ELF sections can have a corresponding symbol. This maps one to the /// other. - DenseMap SectionSymbols; + DenseMap SectionSymbols; - /// A maping from a local label number and an instance count to a symbol. + /// A mapping from a local label number and an instance count to a symbol. /// For example, in the assembly /// 1: /// 2: /// 1: /// We have three labels represented by the pairs (1, 0), (2, 0) and (1, 1) - DenseMap, MCSymbol*> LocalSymbols; + DenseMap, MCSymbol *> LocalSymbols; /// Keeps tracks of names that were used both for used declared and /// artificial symbols. - StringMap UsedNames; + StringMap UsedNames; /// The next ID to dole out to an unnamed assembler temporary symbol with /// a given prefix. @@ -134,10 +137,8 @@ namespace llvm { /// assembly source files. unsigned GenDwarfFileNumber; - /// Symbols created for the start and end of each section, used for - /// generating the .debug_ranges and .debug_aranges sections. - MapVector > - SectionStartEndSyms; + /// Sections for generating the .debug_ranges and .debug_aranges sections. + SetVector SectionsForRanges; /// The information gathered from labels that will have dwarf label /// entries when generating dwarf assembly source files. @@ -158,6 +159,7 @@ namespace llvm { /// differences between temporary and non-temporary labels (primarily on /// Darwin). bool AllowTemporaryLabels; + bool UseNamesOnTempLabels = true; /// The Compile Unit ID that we are currently processing. unsigned DwarfCompileUnitID; @@ -196,15 +198,18 @@ namespace llvm { } }; - StringMap MachOUniquingMap; - std::map ELFUniquingMap; - std::map COFFUniquingMap; + StringMap MachOUniquingMap; + std::map ELFUniquingMap; + std::map COFFUniquingMap; StringMap ELFRelSecNames; /// Do automatic reset in destructor bool AutoReset; - MCSymbol *CreateSymbol(StringRef Name, bool AlwaysAddSuffix); + MCSymbol *createSymbolImpl(const StringMapEntry *Name, + bool CanBeUnnamed); + MCSymbol *createSymbol(StringRef Name, bool AlwaysAddSuffix, + bool IsTemporary); MCSymbol *getOrCreateDirectionalLocalSymbol(unsigned LocalLabelVal, unsigned Instance); @@ -224,8 +229,9 @@ namespace llvm { const MCObjectFileInfo *getObjectFileInfo() const { return MOFI; } void setAllowTemporaryLabels(bool Value) { AllowTemporaryLabels = Value; } + void setUseNamesOnTempLabels(bool Value) { UseNamesOnTempLabels = Value; } - /// @name Module Lifetime Management + /// \name Module Lifetime Management /// @{ /// reset - return object to right after construction state to prepare @@ -234,149 +240,145 @@ namespace llvm { /// @} - /// @name Symbol Management + /// \name Symbol Management /// @{ /// Create and return a new linker temporary symbol with a unique but /// unspecified name. - MCSymbol *CreateLinkerPrivateTempSymbol(); + MCSymbol *createLinkerPrivateTempSymbol(); /// Create and return a new assembler temporary symbol with a unique but /// unspecified name. - MCSymbol *CreateTempSymbol(); + MCSymbol *createTempSymbol(bool CanBeUnnamed = true); - MCSymbol *createTempSymbol(const Twine &Name, bool AlwaysAddSuffix); + MCSymbol *createTempSymbol(const Twine &Name, bool AlwaysAddSuffix, + bool CanBeUnnamed = true); /// Create the definition of a directional local symbol for numbered label /// (used for "1:" definitions). - MCSymbol *CreateDirectionalLocalSymbol(unsigned LocalLabelVal); + MCSymbol *createDirectionalLocalSymbol(unsigned LocalLabelVal); /// Create and return a directional local symbol for numbered label (used /// for "1b" or 1f" references). - MCSymbol *GetDirectionalLocalSymbol(unsigned LocalLabelVal, bool Before); + MCSymbol *getDirectionalLocalSymbol(unsigned LocalLabelVal, bool Before); - /// Lookup the symbol inside with the specified @p Name. If it exists, + /// Lookup the symbol inside with the specified \p Name. If it exists, /// return it. If not, create a forward reference and return it. /// - /// @param Name - The symbol name, which must be unique across all symbols. - MCSymbol *GetOrCreateSymbol(const Twine &Name); + /// \param Name - The symbol name, which must be unique across all symbols. + MCSymbol *getOrCreateSymbol(const Twine &Name); - MCSymbol *getOrCreateSectionSymbol(const MCSectionELF &Section); + MCSymbolELF *getOrCreateSectionSymbol(const MCSectionELF &Section); /// Gets a symbol that will be defined to the final stack offset of a local /// variable after codegen. /// - /// @param Idx - The index of a local variable passed to @llvm.frameescape. + /// \param Idx - The index of a local variable passed to @llvm.localescape. MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName, unsigned Idx); MCSymbol *getOrCreateParentFrameOffsetSymbol(StringRef FuncName); + MCSymbol *getOrCreateLSDASymbol(StringRef FuncName); + /// Get the symbol for \p Name, or null. - MCSymbol *LookupSymbol(const Twine &Name) const; + MCSymbol *lookupSymbol(const Twine &Name) const; /// getSymbols - Get a reference for the symbol table for clients that /// want to, for example, iterate over all symbols. 'const' because we /// still want any modifications to the table itself to use the MCContext /// APIs. - const SymbolTable &getSymbols() const { - return Symbols; - } + const SymbolTable &getSymbols() const { return Symbols; } /// @} - /// @name Section Management + /// \name Section Management /// @{ /// Return the MCSection for the specified mach-o section. This requires /// the operands to be valid. - const MCSectionMachO *getMachOSection(StringRef Segment, StringRef Section, - unsigned TypeAndAttributes, - unsigned Reserved2, SectionKind K, - const char *BeginSymName = nullptr); - - const MCSectionMachO *getMachOSection(StringRef Segment, StringRef Section, - unsigned TypeAndAttributes, - SectionKind K, - const char *BeginSymName = nullptr) { + MCSectionMachO *getMachOSection(StringRef Segment, StringRef Section, + unsigned TypeAndAttributes, + unsigned Reserved2, SectionKind K, + const char *BeginSymName = nullptr); + + MCSectionMachO *getMachOSection(StringRef Segment, StringRef Section, + unsigned TypeAndAttributes, SectionKind K, + const char *BeginSymName = nullptr) { return getMachOSection(Segment, Section, TypeAndAttributes, 0, K, BeginSymName); } - const MCSectionELF *getELFSection(StringRef Section, unsigned Type, - unsigned Flags) { + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags) { return getELFSection(Section, Type, Flags, nullptr); } - const MCSectionELF *getELFSection(StringRef Section, unsigned Type, - unsigned Flags, - const char *BeginSymName) { + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, const char *BeginSymName) { return getELFSection(Section, Type, Flags, 0, "", BeginSymName); } - const MCSectionELF *getELFSection(StringRef Section, unsigned Type, - unsigned Flags, unsigned EntrySize, - StringRef Group) { + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + StringRef Group) { return getELFSection(Section, Type, Flags, EntrySize, Group, nullptr); } - const MCSectionELF *getELFSection(StringRef Section, unsigned Type, - unsigned Flags, unsigned EntrySize, - StringRef Group, - const char *BeginSymName) { + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + StringRef Group, const char *BeginSymName) { return getELFSection(Section, Type, Flags, EntrySize, Group, ~0, BeginSymName); } - const MCSectionELF *getELFSection(StringRef Section, unsigned Type, - unsigned Flags, unsigned EntrySize, - StringRef Group, unsigned UniqueID) { + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + StringRef Group, unsigned UniqueID) { return getELFSection(Section, Type, Flags, EntrySize, Group, UniqueID, nullptr); } - const MCSectionELF *getELFSection(StringRef Section, unsigned Type, - unsigned Flags, unsigned EntrySize, - StringRef Group, unsigned UniqueID, - const char *BeginSymName); + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + StringRef Group, unsigned UniqueID, + const char *BeginSymName); - const MCSectionELF *getELFSection(StringRef Section, unsigned Type, + MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + const MCSymbolELF *Group, unsigned UniqueID, + const char *BeginSymName, + const MCSectionELF *Associated); + + MCSectionELF *createELFRelSection(StringRef Name, unsigned Type, unsigned Flags, unsigned EntrySize, - const MCSymbol *Group, unsigned UniqueID, - const char *BeginSymName, + const MCSymbolELF *Group, const MCSectionELF *Associated); - const MCSectionELF *createELFRelSection(StringRef Name, unsigned Type, - unsigned Flags, unsigned EntrySize, - const MCSymbol *Group, - const MCSectionELF *Associated); - - void renameELFSection(const MCSectionELF *Section, StringRef Name); + void renameELFSection(MCSectionELF *Section, StringRef Name); - const MCSectionELF *CreateELFGroupSection(); + MCSectionELF *createELFGroupSection(const MCSymbolELF *Group); - const MCSectionCOFF *getCOFFSection(StringRef Section, - unsigned Characteristics, - SectionKind Kind, - StringRef COMDATSymName, int Selection, - const char *BeginSymName = nullptr); + MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics, + SectionKind Kind, StringRef COMDATSymName, + int Selection, + const char *BeginSymName = nullptr); - const MCSectionCOFF *getCOFFSection(StringRef Section, - unsigned Characteristics, - SectionKind Kind, - const char *BeginSymName = nullptr); + MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics, + SectionKind Kind, + const char *BeginSymName = nullptr); - const MCSectionCOFF *getCOFFSection(StringRef Section); + MCSectionCOFF *getCOFFSection(StringRef Section); /// Gets or creates a section equivalent to Sec that is associated with the /// section containing KeySym. For example, to create a debug info section /// associated with an inline function, pass the normal debug info section /// as Sec and the function symbol as KeySym. - const MCSectionCOFF *getAssociativeCOFFSection(const MCSectionCOFF *Sec, - const MCSymbol *KeySym); + MCSectionCOFF *getAssociativeCOFFSection(MCSectionCOFF *Sec, + const MCSymbol *KeySym); /// @} - /// @name Dwarf Management + /// \name Dwarf Management /// @{ /// \brief Get the compilation directory for DW_AT_comp_dir @@ -399,7 +401,7 @@ namespace llvm { void setMainFileName(StringRef S) { MainFileName = S; } /// Creates an entry in the dwarf file and directory tables. - unsigned GetDwarfFile(StringRef Directory, StringRef FileName, + unsigned getDwarfFile(StringRef Directory, StringRef FileName, unsigned FileNumber, unsigned CUID); bool isValidDwarfFileNumber(unsigned FileNumber, unsigned CUID = 0); @@ -431,9 +433,7 @@ namespace llvm { return true; return false; } - unsigned getDwarfCompileUnitID() { - return DwarfCompileUnitID; - } + unsigned getDwarfCompileUnitID() { return DwarfCompileUnitID; } void setDwarfCompileUnitID(unsigned CUIndex) { DwarfCompileUnitID = CUIndex; } @@ -456,7 +456,7 @@ namespace llvm { CurrentDwarfLoc.setDiscriminator(Discriminator); DwarfLocSeen = true; } - void ClearDwarfLocSeen() { DwarfLocSeen = false; } + void clearDwarfLocSeen() { DwarfLocSeen = false; } bool getDwarfLocSeen() { return DwarfLocSeen; } const MCDwarfLoc &getCurrentDwarfLoc() { return CurrentDwarfLoc; } @@ -467,17 +467,13 @@ namespace llvm { void setGenDwarfFileNumber(unsigned FileNumber) { GenDwarfFileNumber = FileNumber; } - MapVector > & - getGenDwarfSectionSyms() { - return SectionStartEndSyms; + const SetVector &getGenDwarfSectionSyms() { + return SectionsForRanges; } - std::pair >::iterator, - bool> - addGenDwarfSection(const MCSection *Sec) { - return SectionStartEndSyms.insert( - std::make_pair(Sec, std::make_pair(nullptr, nullptr))); + bool addGenDwarfSection(MCSection *Sec) { + return SectionsForRanges.insert(Sec); } + void finalizeDwarfSections(MCStreamer &MCOS); const std::vector &getMCGenDwarfLabelEntries() const { return MCGenDwarfLabelEntries; @@ -500,56 +496,52 @@ namespace llvm { char *getSecureLogFile() { return SecureLogFile; } raw_ostream *getSecureLog() { return SecureLog; } bool getSecureLogUsed() { return SecureLogUsed; } - void setSecureLog(raw_ostream *Value) { - SecureLog = Value; - } - void setSecureLogUsed(bool Value) { - SecureLogUsed = Value; - } + void setSecureLog(raw_ostream *Value) { SecureLog = Value; } + void setSecureLogUsed(bool Value) { SecureLogUsed = Value; } - void *Allocate(unsigned Size, unsigned Align = 8) { + void *allocate(unsigned Size, unsigned Align = 8) { return Allocator.Allocate(Size, Align); } - void Deallocate(void *Ptr) { - } + void deallocate(void *Ptr) {} // Unrecoverable error has occurred. Display the best diagnostic we can // and bail via exit(1). For now, most MC backend errors are unrecoverable. // FIXME: We should really do something about that. - LLVM_ATTRIBUTE_NORETURN void FatalError(SMLoc L, const Twine &Msg) const; + LLVM_ATTRIBUTE_NORETURN void reportFatalError(SMLoc L, + const Twine &Msg) const; }; } // end namespace llvm // operator new and delete aren't allowed inside namespaces. // The throw specifications are mandated by the standard. -/// @brief Placement new for using the MCContext's allocator. +/// \brief Placement new for using the MCContext's allocator. /// /// This placement form of operator new uses the MCContext's allocator for /// obtaining memory. It is a non-throwing new, which means that it returns /// null on error. (If that is what the allocator does. The current does, so if /// this ever changes, this operator will have to be changed, too.) /// Usage looks like this (assuming there's an MCContext 'Context' in scope): -/// @code -/// // Default alignment (16) +/// \code +/// // Default alignment (8) /// IntegerLiteral *Ex = new (Context) IntegerLiteral(arguments); /// // Specific alignment -/// IntegerLiteral *Ex2 = new (Context, 8) IntegerLiteral(arguments); -/// @endcode +/// IntegerLiteral *Ex2 = new (Context, 4) IntegerLiteral(arguments); +/// \endcode /// Please note that you cannot use delete on the pointer; it must be /// deallocated using an explicit destructor call followed by -/// @c Context.Deallocate(Ptr). +/// \c Context.Deallocate(Ptr). /// -/// @param Bytes The number of bytes to allocate. Calculated by the compiler. -/// @param C The MCContext that provides the allocator. -/// @param Alignment The alignment of the allocated memory (if the underlying +/// \param Bytes The number of bytes to allocate. Calculated by the compiler. +/// \param C The MCContext that provides the allocator. +/// \param Alignment The alignment of the allocated memory (if the underlying /// allocator supports it). -/// @return The allocated memory. Could be NULL. +/// \return The allocated memory. Could be NULL. inline void *operator new(size_t Bytes, llvm::MCContext &C, - size_t Alignment = 16) throw () { - return C.Allocate(Bytes, Alignment); + size_t Alignment = 8) throw() { + return C.allocate(Bytes, Alignment); } -/// @brief Placement delete companion to the new above. +/// \brief Placement delete companion to the new above. /// /// This operator is just a companion to the new above. There is no way of /// invoking it directly; see the new operator for more details. This operator @@ -557,41 +549,41 @@ inline void *operator new(size_t Bytes, llvm::MCContext &C, /// the MCContext throws in the object constructor. inline void operator delete(void *Ptr, llvm::MCContext &C, size_t) throw () { - C.Deallocate(Ptr); + C.deallocate(Ptr); } /// This placement form of operator new[] uses the MCContext's allocator for /// obtaining memory. It is a non-throwing new[], which means that it returns /// null on error. /// Usage looks like this (assuming there's an MCContext 'Context' in scope): -/// @code -/// // Default alignment (16) +/// \code +/// // Default alignment (8) /// char *data = new (Context) char[10]; /// // Specific alignment -/// char *data = new (Context, 8) char[10]; -/// @endcode +/// char *data = new (Context, 4) char[10]; +/// \endcode /// Please note that you cannot use delete on the pointer; it must be /// deallocated using an explicit destructor call followed by -/// @c Context.Deallocate(Ptr). +/// \c Context.Deallocate(Ptr). /// -/// @param Bytes The number of bytes to allocate. Calculated by the compiler. -/// @param C The MCContext that provides the allocator. -/// @param Alignment The alignment of the allocated memory (if the underlying +/// \param Bytes The number of bytes to allocate. Calculated by the compiler. +/// \param C The MCContext that provides the allocator. +/// \param Alignment The alignment of the allocated memory (if the underlying /// allocator supports it). -/// @return The allocated memory. Could be NULL. +/// \return The allocated memory. Could be NULL. inline void *operator new[](size_t Bytes, llvm::MCContext& C, - size_t Alignment = 16) throw () { - return C.Allocate(Bytes, Alignment); + size_t Alignment = 8) throw() { + return C.allocate(Bytes, Alignment); } -/// @brief Placement delete[] companion to the new[] above. +/// \brief Placement delete[] companion to the new[] above. /// /// This operator is just a companion to the new[] above. There is no way of /// invoking it directly; see the new[] operator for more details. This operator /// is called implicitly by the compiler if a placement new[] expression using /// the MCContext throws in the object constructor. inline void operator delete[](void *Ptr, llvm::MCContext &C) throw () { - C.Deallocate(Ptr); + C.deallocate(Ptr); } #endif diff --git a/include/llvm/MC/MCDisassembler.h b/include/llvm/MC/MCDisassembler.h index d6b0a305b1d..57c40d660f6 100644 --- a/include/llvm/MC/MCDisassembler.h +++ b/include/llvm/MC/MCDisassembler.h @@ -11,7 +11,6 @@ #include "llvm-c/Disassembler.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/MC/MCRelocationInfo.h" #include "llvm/MC/MCSymbolizer.h" #include "llvm/Support/DataTypes.h" @@ -61,16 +60,16 @@ class MCDisassembler { /// Returns the disassembly of a single instruction. /// - /// @param Instr - An MCInst to populate with the contents of the + /// \param Instr - An MCInst to populate with the contents of the /// instruction. - /// @param Size - A value to populate with the size of the instruction, or + /// \param Size - A value to populate with the size of the instruction, or /// the number of bytes consumed while attempting to decode /// an invalid instruction. - /// @param Address - The address, in the memory space of region, of the first + /// \param Address - The address, in the memory space of region, of the first /// byte of the instruction. - /// @param VStream - The stream to print warnings and diagnostic messages on. - /// @param CStream - The stream to print comments and annotations on. - /// @return - MCDisassembler::Success if the instruction is valid, + /// \param VStream - The stream to print warnings and diagnostic messages on. + /// \param CStream - The stream to print comments and annotations on. + /// \return - MCDisassembler::Success if the instruction is valid, /// MCDisassembler::SoftFail if the instruction was /// disassemblable but invalid, /// MCDisassembler::Fail if the instruction was invalid. diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index c266acf2f09..1e72dfee4ad 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -37,35 +37,30 @@ class MCSymbol; class SourceMgr; class SMLoc; -/// MCDwarfFile - Instances of this class represent the name of the dwarf +/// \brief Instances of this class represent the name of the dwarf /// .file directive and its associated dwarf file number in the MC file, -/// and MCDwarfFile's are created and unique'd by the MCContext class where +/// and MCDwarfFile's are created and uniqued by the MCContext class where /// the file number for each is its index into the vector of DwarfFiles (note /// index 0 is not used and not a valid dwarf file number). struct MCDwarfFile { - // Name - the base name of the file without its directory path. + // \brief The base name of the file without its directory path. // The StringRef references memory allocated in the MCContext. std::string Name; - // DirIndex - the index into the list of directory names for this file name. + // \brief The index into the list of directory names for this file name. unsigned DirIndex; }; -/// MCDwarfLoc - Instances of this class represent the information from a +/// \brief Instances of this class represent the information from a /// dwarf .loc directive. class MCDwarfLoc { - // FileNum - the file number. - unsigned FileNum; - // Line - the line number. - unsigned Line; - // Column - the column position. - unsigned Column; + uint32_t FileNum; + uint32_t Line; + uint16_t Column; // Flags (see #define's below) - unsigned Flags; - // Isa - unsigned Isa; - // Discriminator - unsigned Discriminator; + uint8_t Flags; + uint8_t Isa; + uint32_t Discriminator; // Flag that indicates the initial value of the is_stmt_start flag. #define DWARF2_LINE_DEFAULT_IS_STMT 1 @@ -87,46 +82,55 @@ class MCDwarfLoc { // for an MCDwarfLoc object. public: - /// getFileNum - Get the FileNum of this MCDwarfLoc. + /// \brief Get the FileNum of this MCDwarfLoc. unsigned getFileNum() const { return FileNum; } - /// getLine - Get the Line of this MCDwarfLoc. + /// \brief Get the Line of this MCDwarfLoc. unsigned getLine() const { return Line; } - /// getColumn - Get the Column of this MCDwarfLoc. + /// \brief Get the Column of this MCDwarfLoc. unsigned getColumn() const { return Column; } - /// getFlags - Get the Flags of this MCDwarfLoc. + /// \brief Get the Flags of this MCDwarfLoc. unsigned getFlags() const { return Flags; } - /// getIsa - Get the Isa of this MCDwarfLoc. + /// \brief Get the Isa of this MCDwarfLoc. unsigned getIsa() const { return Isa; } - /// getDiscriminator - Get the Discriminator of this MCDwarfLoc. + /// \brief Get the Discriminator of this MCDwarfLoc. unsigned getDiscriminator() const { return Discriminator; } - /// setFileNum - Set the FileNum of this MCDwarfLoc. + /// \brief Set the FileNum of this MCDwarfLoc. void setFileNum(unsigned fileNum) { FileNum = fileNum; } - /// setLine - Set the Line of this MCDwarfLoc. + /// \brief Set the Line of this MCDwarfLoc. void setLine(unsigned line) { Line = line; } - /// setColumn - Set the Column of this MCDwarfLoc. - void setColumn(unsigned column) { Column = column; } + /// \brief Set the Column of this MCDwarfLoc. + void setColumn(unsigned column) { + assert(column <= UINT16_MAX); + Column = column; + } - /// setFlags - Set the Flags of this MCDwarfLoc. - void setFlags(unsigned flags) { Flags = flags; } + /// \brief Set the Flags of this MCDwarfLoc. + void setFlags(unsigned flags) { + assert(flags <= UINT8_MAX); + Flags = flags; + } - /// setIsa - Set the Isa of this MCDwarfLoc. - void setIsa(unsigned isa) { Isa = isa; } + /// \brief Set the Isa of this MCDwarfLoc. + void setIsa(unsigned isa) { + assert(isa <= UINT8_MAX); + Isa = isa; + } - /// setDiscriminator - Set the Discriminator of this MCDwarfLoc. + /// \brief Set the Discriminator of this MCDwarfLoc. void setDiscriminator(unsigned discriminator) { Discriminator = discriminator; } }; -/// MCLineEntry - Instances of this class represent the line information for +/// \brief Instances of this class represent the line information for /// the dwarf line table entries. Which is created after a machine /// instruction is assembled and uses an address from a temporary label /// created at the current address in the current section and the info from @@ -148,24 +152,24 @@ class MCLineEntry : public MCDwarfLoc { // This is called when an instruction is assembled into the specified // section and if there is information from the last .loc directive that // has yet to have a line entry made for it is made. - static void Make(MCObjectStreamer *MCOS, const MCSection *Section); + static void Make(MCObjectStreamer *MCOS, MCSection *Section); }; -/// MCLineSection - Instances of this class represent the line information -/// for a compile unit where machine instructions have been assembled after seeing -/// .loc directives. This is the information used to build the dwarf line +/// \brief Instances of this class represent the line information for a compile +/// unit where machine instructions have been assembled after seeing .loc +/// directives. This is the information used to build the dwarf line /// table for a section. class MCLineSection { public: - // addLineEntry - adds an entry to this MCLineSection's line entries - void addLineEntry(const MCLineEntry &LineEntry, const MCSection *Sec) { + // \brief Add an entry to this MCLineSection's line entries. + void addLineEntry(const MCLineEntry &LineEntry, MCSection *Sec) { MCLineDivisions[Sec].push_back(LineEntry); } typedef std::vector MCLineEntryCollection; typedef MCLineEntryCollection::iterator iterator; typedef MCLineEntryCollection::const_iterator const_iterator; - typedef MapVector MCLineDivisionMap; + typedef MapVector MCLineDivisionMap; private: // A collection of MCLineEntry for each section. diff --git a/include/llvm/MC/MCELF.h b/include/llvm/MC/MCELF.h deleted file mode 100644 index 294a51bf7c7..00000000000 --- a/include/llvm/MC/MCELF.h +++ /dev/null @@ -1,37 +0,0 @@ -//===- lib/MC/MCELF.h - ELF MC --------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains some support functions used by the ELF Streamer and -// ObjectWriter. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_MCELF_H -#define LLVM_MC_MCELF_H - -#include "llvm/MC/MCExpr.h" - -namespace llvm { -class MCSymbolData; - -class MCELF { - public: - static void SetBinding(MCSymbolData &SD, unsigned Binding); - static unsigned GetBinding(const MCSymbolData &SD); - static void SetType(MCSymbolData &SD, unsigned Type); - static unsigned GetType(const MCSymbolData &SD); - static void SetVisibility(MCSymbolData &SD, unsigned Visibility); - static unsigned GetVisibility(const MCSymbolData &SD); - static void setOther(MCSymbolData &SD, unsigned Other); - static unsigned getOther(const MCSymbolData &SD); -}; - -} - -#endif diff --git a/include/llvm/MC/MCELFObjectWriter.h b/include/llvm/MC/MCELFObjectWriter.h index e9fef76c20f..01f694d3b75 100644 --- a/include/llvm/MC/MCELFObjectWriter.h +++ b/include/llvm/MC/MCELFObjectWriter.h @@ -20,19 +20,18 @@ class MCAssembler; class MCFixup; class MCFragment; class MCObjectWriter; -class MCSectionData; class MCSymbol; -class MCSymbolData; +class MCSymbolELF; class MCValue; class raw_pwrite_stream; struct ELFRelocationEntry { uint64_t Offset; // Where is the relocation. - const MCSymbol *Symbol; // The symbol to relocate with. + const MCSymbolELF *Symbol; // The symbol to relocate with. unsigned Type; // The type of the relocation. uint64_t Addend; // The addend to use. - ELFRelocationEntry(uint64_t Offset, const MCSymbol *Symbol, unsigned Type, + ELFRelocationEntry(uint64_t Offset, const MCSymbolELF *Symbol, unsigned Type, uint64_t Addend) : Offset(Offset), Symbol(Symbol), Type(Type), Addend(Addend) {} }; @@ -70,13 +69,13 @@ class MCELFObjectTargetWriter { virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const = 0; - virtual bool needsRelocateWithSymbol(const MCSymbolData &SD, + virtual bool needsRelocateWithSymbol(const MCSymbol &Sym, unsigned Type) const; virtual void sortRelocs(const MCAssembler &Asm, std::vector &Relocs); - /// @name Accessors + /// \name Accessors /// @{ uint8_t getOSABI() const { return OSABI; } uint16_t getEMachine() const { return EMachine; } diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h index ace4ee3e542..a5b257f5958 100644 --- a/include/llvm/MC/MCELFStreamer.h +++ b/include/llvm/MC/MCELFStreamer.h @@ -23,8 +23,6 @@ class MCAssembler; class MCCodeEmitter; class MCExpr; class MCInst; -class MCSymbol; -class MCSymbolData; class raw_ostream; class MCELFStreamer : public MCObjectStreamer { @@ -39,17 +37,15 @@ class MCELFStreamer : public MCObjectStreamer { void reset() override { SeenIdent = false; LocalCommons.clear(); - BindingExplicitlySet.clear(); BundleGroups.clear(); MCObjectStreamer::reset(); } - /// @name MCStreamer Interface + /// \name MCStreamer Interface /// @{ void InitSections(bool NoExecStack) override; - void ChangeSection(const MCSection *Section, - const MCExpr *Subsection) override; + void ChangeSection(MCSection *Section, const MCExpr *Subsection) override; void EmitLabel(MCSymbol *Symbol) override; void EmitAssemblerFlag(MCAssemblerFlag Flag) override; void EmitThumbFunc(MCSymbol *Func) override; @@ -63,15 +59,15 @@ class MCELFStreamer : public MCObjectStreamer { void EmitCOFFSymbolType(int Type) override; void EndCOFFSymbolDef() override; - void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) override; + void emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value) override; void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; - void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = nullptr, + void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, uint64_t Size = 0, unsigned ByteAlignment = 0) override; - void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment = 0) override; + void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment = 0) override; void EmitValueImpl(const MCExpr *Value, unsigned Size, const SMLoc &Loc = SMLoc()) override; @@ -90,26 +86,25 @@ class MCELFStreamer : public MCObjectStreamer { void EmitBundleUnlock() override; private: + bool isBundleLocked() const; void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &) override; void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override; void fixSymbolsInTLSFixups(const MCExpr *expr); /// \brief Merge the content of the fragment \p EF into the fragment \p DF. - void mergeFragment(MCDataFragment *, MCEncodedFragmentWithFixups *); + void mergeFragment(MCDataFragment *, MCDataFragment *); bool SeenIdent; struct LocalCommon { - MCSymbolData *SD; + const MCSymbol *Symbol; uint64_t Size; unsigned ByteAlignment; }; std::vector LocalCommons; - SmallPtrSet BindingExplicitlySet; - /// BundleGroups - The stack of fragments holding the bundle-locked /// instructions. llvm::SmallVector BundleGroups; diff --git a/include/llvm/MC/MCELFSymbolFlags.h b/include/llvm/MC/MCELFSymbolFlags.h deleted file mode 100644 index 297c44269a8..00000000000 --- a/include/llvm/MC/MCELFSymbolFlags.h +++ /dev/null @@ -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 MCSymbolData -// '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 diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index d5a68be3ec6..b3a607351a8 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -21,15 +21,14 @@ class MCAssembler; class MCContext; class MCFixup; class MCSection; -class MCSectionData; class MCStreamer; class MCSymbol; class MCValue; class raw_ostream; class StringRef; -typedef DenseMap SectionAddrMap; +typedef DenseMap SectionAddrMap; -/// MCExpr - Base class for the full range of assembler expressions which are +/// \brief Base class for the full range of assembler expressions which are /// needed for parsing. class MCExpr { public: @@ -47,7 +46,7 @@ class MCExpr { MCExpr(const MCExpr&) = delete; void operator=(const MCExpr&) = delete; - bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, + bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, const SectionAddrMap *Addrs) const; @@ -58,75 +57,75 @@ class MCExpr { protected: explicit MCExpr(ExprKind Kind) : Kind(Kind) {} - bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, + bool evaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, const MCFixup *Fixup, const SectionAddrMap *Addrs, bool InSet) const; public: - /// @name Accessors + /// \name Accessors /// @{ ExprKind getKind() const { return Kind; } /// @} - /// @name Utility Methods + /// \name Utility Methods /// @{ - void print(raw_ostream &OS) const; + void print(raw_ostream &OS, const MCAsmInfo *MAI) const; void dump() const; /// @} - /// @name Expression Evaluation + /// \name Expression Evaluation /// @{ - /// EvaluateAsAbsolute - Try to evaluate the expression to an absolute value. + /// \brief Try to evaluate the expression to an absolute value. /// - /// @param Res - The absolute value, if evaluation succeeds. - /// @param Layout - The assembler layout object to use for evaluating symbol + /// \param Res - The absolute value, if evaluation succeeds. + /// \param Layout - The assembler layout object to use for evaluating symbol /// values. If not given, then only non-symbolic expressions will be /// evaluated. - /// @result - True on success. - bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout, + /// \return - True on success. + bool evaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout, const SectionAddrMap &Addrs) const; - bool EvaluateAsAbsolute(int64_t &Res) const; - bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const; - bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const; + bool evaluateAsAbsolute(int64_t &Res) const; + bool evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const; + bool evaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const; bool evaluateKnownAbsolute(int64_t &Res, const MCAsmLayout &Layout) const; - /// EvaluateAsRelocatable - Try to evaluate the expression to a relocatable - /// value, i.e. an expression of the fixed form (a - b + constant). + /// \brief Try to evaluate the expression to a relocatable value, i.e. an + /// expression of the fixed form (a - b + constant). /// - /// @param Res - The relocatable value, if evaluation succeeds. - /// @param Layout - The assembler layout object to use for evaluating values. - /// @param Fixup - The Fixup object if available. - /// @result - True on success. - bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout, + /// \param Res - The relocatable value, if evaluation succeeds. + /// \param Layout - The assembler layout object to use for evaluating values. + /// \param Fixup - The Fixup object if available. + /// \return - True on success. + bool evaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const; /// \brief Try to evaluate the expression to the form (a - b + constant) where /// neither a nor b are variables. /// - /// This is a more aggressive variant of EvaluateAsRelocatable. The intended + /// This is a more aggressive variant of evaluateAsRelocatable. The intended /// use is for when relocations are not available, like the .size directive. bool evaluateAsValue(MCValue &Res, const MCAsmLayout &Layout) const; - /// FindAssociatedSection - Find the "associated section" for this expression, - /// which is currently defined as the absolute section for constants, or + /// \brief Find the "associated section" for this expression, which is + /// currently defined as the absolute section for constants, or /// otherwise the section associated with the first defined symbol in the /// expression. - const MCSection *FindAssociatedSection() const; + MCSection *findAssociatedSection() const; /// @} }; inline raw_ostream &operator<<(raw_ostream &OS, const MCExpr &E) { - E.print(OS); + E.print(OS, nullptr); return OS; } -//// MCConstantExpr - Represent a constant integer expression. +//// \brief Represent a constant integer expression. class MCConstantExpr : public MCExpr { int64_t Value; @@ -134,13 +133,13 @@ class MCConstantExpr : public MCExpr { : MCExpr(MCExpr::Constant), Value(Value) {} public: - /// @name Construction + /// \name Construction /// @{ - static const MCConstantExpr *Create(int64_t Value, MCContext &Ctx); + static const MCConstantExpr *create(int64_t Value, MCContext &Ctx); /// @} - /// @name Accessors + /// \name Accessors /// @{ int64_t getValue() const { return Value; } @@ -152,15 +151,14 @@ class MCConstantExpr : public MCExpr { } }; -/// MCSymbolRefExpr - Represent a reference to a symbol from inside an -/// expression. +/// \brief Represent a reference to a symbol from inside an expression. /// /// A symbol reference in an expression may be a use of a label, a use of an /// assembler variable (defined constant), or constitute an implicit definition /// of the symbol as external. class MCSymbolRefExpr : public MCExpr { public: - enum VariantKind { + enum VariantKind : uint16_t { VK_None, VK_Invalid, @@ -278,12 +276,25 @@ class MCSymbolRefExpr : public MCExpr { VK_Mips_PCREL_HI16, VK_Mips_PCREL_LO16, - VK_COFF_IMGREL32 // symbol@imgrel (image-relative) + VK_COFF_IMGREL32, // symbol@imgrel (image-relative) + + VK_Hexagon_PCREL, + VK_Hexagon_LO16, + VK_Hexagon_HI16, + VK_Hexagon_GPREL, + VK_Hexagon_GD_GOT, + VK_Hexagon_LD_GOT, + VK_Hexagon_GD_PLT, + VK_Hexagon_LD_PLT, + VK_Hexagon_IE, + VK_Hexagon_IE_GOT, + VK_TPREL, + VK_DTPREL }; private: /// The symbol reference modifier. - const unsigned Kind : 16; + const VariantKind Kind; /// Specifies how the variant kind should be printed. const unsigned UseParensForSymbolVariant : 1; @@ -298,32 +309,32 @@ class MCSymbolRefExpr : public MCExpr { const MCAsmInfo *MAI); public: - /// @name Construction + /// \name Construction /// @{ - static const MCSymbolRefExpr *Create(const MCSymbol *Symbol, MCContext &Ctx) { - return MCSymbolRefExpr::Create(Symbol, VK_None, Ctx); + static const MCSymbolRefExpr *create(const MCSymbol *Symbol, MCContext &Ctx) { + return MCSymbolRefExpr::create(Symbol, VK_None, Ctx); } - static const MCSymbolRefExpr *Create(const MCSymbol *Symbol, VariantKind Kind, + static const MCSymbolRefExpr *create(const MCSymbol *Symbol, VariantKind Kind, MCContext &Ctx); - static const MCSymbolRefExpr *Create(StringRef Name, VariantKind Kind, + static const MCSymbolRefExpr *create(StringRef Name, VariantKind Kind, MCContext &Ctx); /// @} - /// @name Accessors + /// \name Accessors /// @{ const MCSymbol &getSymbol() const { return *Symbol; } - VariantKind getKind() const { return static_cast(Kind); } + VariantKind getKind() const { return Kind; } void printVariantKind(raw_ostream &OS) const; bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; } /// @} - /// @name Static Utility Functions + /// \name Static Utility Functions /// @{ static StringRef getVariantKindName(VariantKind Kind); @@ -337,7 +348,7 @@ class MCSymbolRefExpr : public MCExpr { } }; -/// MCUnaryExpr - Unary assembler expressions. +/// \brief Unary assembler expressions. class MCUnaryExpr : public MCExpr { public: enum Opcode { @@ -355,32 +366,32 @@ class MCUnaryExpr : public MCExpr { : MCExpr(MCExpr::Unary), Op(Op), Expr(Expr) {} public: - /// @name Construction + /// \name Construction /// @{ - static const MCUnaryExpr *Create(Opcode Op, const MCExpr *Expr, + static const MCUnaryExpr *create(Opcode Op, const MCExpr *Expr, MCContext &Ctx); - static const MCUnaryExpr *CreateLNot(const MCExpr *Expr, MCContext &Ctx) { - return Create(LNot, Expr, Ctx); + static const MCUnaryExpr *createLNot(const MCExpr *Expr, MCContext &Ctx) { + return create(LNot, Expr, Ctx); } - static const MCUnaryExpr *CreateMinus(const MCExpr *Expr, MCContext &Ctx) { - return Create(Minus, Expr, Ctx); + static const MCUnaryExpr *createMinus(const MCExpr *Expr, MCContext &Ctx) { + return create(Minus, Expr, Ctx); } - static const MCUnaryExpr *CreateNot(const MCExpr *Expr, MCContext &Ctx) { - return Create(Not, Expr, Ctx); + static const MCUnaryExpr *createNot(const MCExpr *Expr, MCContext &Ctx) { + return create(Not, Expr, Ctx); } - static const MCUnaryExpr *CreatePlus(const MCExpr *Expr, MCContext &Ctx) { - return Create(Plus, Expr, Ctx); + static const MCUnaryExpr *createPlus(const MCExpr *Expr, MCContext &Ctx) { + return create(Plus, Expr, Ctx); } /// @} - /// @name Accessors + /// \name Accessors /// @{ - /// getOpcode - Get the kind of this unary expression. + /// \brief Get the kind of this unary expression. Opcode getOpcode() const { return Op; } - /// getSubExpr - Get the child of this unary expression. + /// \brief Get the child of this unary expression. const MCExpr *getSubExpr() const { return Expr; } /// @} @@ -390,7 +401,7 @@ class MCUnaryExpr : public MCExpr { } }; -/// MCBinaryExpr - Binary assembler expressions. +/// \brief Binary assembler expressions. class MCBinaryExpr : public MCExpr { public: enum Opcode { @@ -413,7 +424,8 @@ class MCBinaryExpr : public MCExpr { NE, ///< Inequality comparison. Or, ///< Bitwise or. Shl, ///< Shift left. - Shr, ///< Shift right (arithmetic or logical, depending on target) + AShr, ///< Arithmetic shift right. + LShr, ///< Logical shift right. Sub, ///< Subtraction. Xor ///< Bitwise exclusive or. }; @@ -426,95 +438,99 @@ class MCBinaryExpr : public MCExpr { : MCExpr(MCExpr::Binary), Op(Op), LHS(LHS), RHS(RHS) {} public: - /// @name Construction + /// \name Construction /// @{ - static const MCBinaryExpr *Create(Opcode Op, const MCExpr *LHS, + static const MCBinaryExpr *create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx); - static const MCBinaryExpr *CreateAdd(const MCExpr *LHS, const MCExpr *RHS, + static const MCBinaryExpr *createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { - return Create(Add, LHS, RHS, Ctx); + return create(Add, LHS, RHS, Ctx); } - static const MCBinaryExpr *CreateAnd(const MCExpr *LHS, const MCExpr *RHS, + static const MCBinaryExpr *createAnd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { - return Create(And, LHS, RHS, Ctx); + return create(And, LHS, RHS, Ctx); } - static const MCBinaryExpr *CreateDiv(const MCExpr *LHS, const MCExpr *RHS, + static const MCBinaryExpr *createDiv(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { - return Create(Div, LHS, RHS, Ctx); + return create(Div, LHS, RHS, Ctx); } - static const MCBinaryExpr *CreateEQ(const MCExpr *LHS, const MCExpr *RHS, + static const MCBinaryExpr *createEQ(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { - return Create(EQ, LHS, RHS, Ctx); + return create(EQ, LHS, RHS, Ctx); } - static const MCBinaryExpr *CreateGT(const MCExpr *LHS, const MCExpr *RHS, + static const MCBinaryExpr *createGT(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { - return Create(GT, LHS, RHS, Ctx); + return create(GT, LHS, RHS, Ctx); } - static const MCBinaryExpr *CreateGTE(const MCExpr *LHS, const MCExpr *RHS, + static const MCBinaryExpr *createGTE(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { - return Create(GTE, LHS, RHS, Ctx); + return create(GTE, LHS, RHS, Ctx); } - static const MCBinaryExpr *CreateLAnd(const MCExpr *LHS, const MCExpr *RHS, + static const MCBinaryExpr *createLAnd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { - return Create(LAnd, LHS, RHS, Ctx); + return create(LAnd, LHS, RHS, Ctx); } - static const MCBinaryExpr *CreateLOr(const MCExpr *LHS, const MCExpr *RHS, + static const MCBinaryExpr *createLOr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { - return Create(LOr, LHS, RHS, Ctx); + return create(LOr, LHS, RHS, Ctx); } - static const MCBinaryExpr *CreateLT(const MCExpr *LHS, const MCExpr *RHS, + static const MCBinaryExpr *createLT(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { - return Create(LT, LHS, RHS, Ctx); + return create(LT, LHS, RHS, Ctx); } - static const MCBinaryExpr *CreateLTE(const MCExpr *LHS, const MCExpr *RHS, + static const MCBinaryExpr *createLTE(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { - return Create(LTE, LHS, RHS, Ctx); + return create(LTE, LHS, RHS, Ctx); } - static const MCBinaryExpr *CreateMod(const MCExpr *LHS, const MCExpr *RHS, + static const MCBinaryExpr *createMod(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { - return Create(Mod, LHS, RHS, Ctx); + return create(Mod, LHS, RHS, Ctx); } - static const MCBinaryExpr *CreateMul(const MCExpr *LHS, const MCExpr *RHS, + static const MCBinaryExpr *createMul(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { - return Create(Mul, LHS, RHS, Ctx); + return create(Mul, LHS, RHS, Ctx); } - static const MCBinaryExpr *CreateNE(const MCExpr *LHS, const MCExpr *RHS, + static const MCBinaryExpr *createNE(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { - return Create(NE, LHS, RHS, Ctx); + return create(NE, LHS, RHS, Ctx); } - static const MCBinaryExpr *CreateOr(const MCExpr *LHS, const MCExpr *RHS, + static const MCBinaryExpr *createOr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { - return Create(Or, LHS, RHS, Ctx); + return create(Or, LHS, RHS, Ctx); + } + static const MCBinaryExpr *createShl(const MCExpr *LHS, const MCExpr *RHS, + MCContext &Ctx) { + return create(Shl, LHS, RHS, Ctx); } - static const MCBinaryExpr *CreateShl(const MCExpr *LHS, const MCExpr *RHS, + static const MCBinaryExpr *createAShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { - return Create(Shl, LHS, RHS, Ctx); + return create(AShr, LHS, RHS, Ctx); } - static const MCBinaryExpr *CreateShr(const MCExpr *LHS, const MCExpr *RHS, + static const MCBinaryExpr *createLShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { - return Create(Shr, LHS, RHS, Ctx); + return create(LShr, LHS, RHS, Ctx); } - static const MCBinaryExpr *CreateSub(const MCExpr *LHS, const MCExpr *RHS, + static const MCBinaryExpr *createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { - return Create(Sub, LHS, RHS, Ctx); + return create(Sub, LHS, RHS, Ctx); } - static const MCBinaryExpr *CreateXor(const MCExpr *LHS, const MCExpr *RHS, + static const MCBinaryExpr *createXor(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx) { - return Create(Xor, LHS, RHS, Ctx); + return create(Xor, LHS, RHS, Ctx); } /// @} - /// @name Accessors + /// \name Accessors /// @{ - /// getOpcode - Get the kind of this binary expression. + /// \brief Get the kind of this binary expression. Opcode getOpcode() const { return Op; } - /// getLHS - Get the left-hand side expression of the binary operator. + /// \brief Get the left-hand side expression of the binary operator. const MCExpr *getLHS() const { return LHS; } - /// getRHS - Get the right-hand side expression of the binary operator. + /// \brief Get the right-hand side expression of the binary operator. const MCExpr *getRHS() const { return RHS; } /// @} @@ -524,8 +540,8 @@ class MCBinaryExpr : public MCExpr { } }; -/// MCTargetExpr - This is an extension point for target-specific MCExpr -/// subclasses to implement. +/// \brief This is an extension point for target-specific MCExpr subclasses to +/// implement. /// /// NOTE: All subclasses are required to have trivial destructors because /// MCExprs are bump pointer allocated and not destructed. @@ -535,13 +551,12 @@ class MCTargetExpr : public MCExpr { MCTargetExpr() : MCExpr(Target) {} virtual ~MCTargetExpr() {} public: - - virtual void PrintImpl(raw_ostream &OS) const = 0; - virtual bool EvaluateAsRelocatableImpl(MCValue &Res, + virtual void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const = 0; + virtual bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const = 0; virtual void visitUsedExpr(MCStreamer& Streamer) const = 0; - virtual const MCSection *FindAssociatedSection() const = 0; + virtual MCSection *findAssociatedSection() const = 0; virtual void fixELFSymbolsInTLSFixups(MCAssembler &) const = 0; diff --git a/include/llvm/MC/MCFixedLenDisassembler.h b/include/llvm/MC/MCFixedLenDisassembler.h index ad99943df2c..ad34d9494bb 100644 --- a/include/llvm/MC/MCFixedLenDisassembler.h +++ b/include/llvm/MC/MCFixedLenDisassembler.h @@ -22,6 +22,8 @@ enum DecoderOps { // uleb128 Val, uint16_t NumToSkip) OPC_CheckPredicate, // OPC_CheckPredicate(uleb128 PIdx, uint16_t NumToSkip) OPC_Decode, // OPC_Decode(uleb128 Opcode, uleb128 DIdx) + OPC_TryDecode, // OPC_TryDecode(uleb128 Opcode, uleb128 DIdx, + // uint16_t NumToSkip) OPC_SoftFail, // OPC_SoftFail(uleb128 PMask, uleb128 NMask) OPC_Fail // OPC_Fail() }; diff --git a/include/llvm/MC/MCFixup.h b/include/llvm/MC/MCFixup.h index 98a1419a193..8ab477c401a 100644 --- a/include/llvm/MC/MCFixup.h +++ b/include/llvm/MC/MCFixup.h @@ -19,7 +19,7 @@ namespace llvm { class MCExpr; -/// MCFixupKind - Extensible enumeration to represent the type of a fixup. +/// \brief Extensible enumeration to represent the type of a fixup. enum MCFixupKind { FK_Data_1 = 0, ///< A one-byte fixup. FK_Data_2, ///< A two-byte fixup. @@ -45,7 +45,7 @@ enum MCFixupKind { MaxTargetFixupKind = (1 << 8) }; -/// MCFixup - Encode information on a single operation to perform on a byte +/// \brief Encode information on a single operation to perform on a byte /// sequence (e.g., an encoded instruction) which requires assemble- or run- /// time patching. /// @@ -75,7 +75,7 @@ class MCFixup { /// The source location which gave rise to the fixup, if any. SMLoc Loc; public: - static MCFixup Create(uint32_t Offset, const MCExpr *Value, + static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc = SMLoc()) { assert(unsigned(Kind) < MaxTargetFixupKind && "Kind out of range!"); MCFixup FI; @@ -93,8 +93,8 @@ class MCFixup { const MCExpr *getValue() const { return Value; } - /// getKindForSize - Return the generic fixup kind for a value with the given - /// size. It is an error to pass an unsupported size. + /// \brief Return the generic fixup kind for a value with the given size. It + /// is an error to pass an unsupported size. static MCFixupKind getKindForSize(unsigned Size, bool isPCRel) { switch (Size) { default: llvm_unreachable("Invalid generic fixup size!"); diff --git a/include/llvm/MC/MCFixupKindInfo.h b/include/llvm/MC/MCFixupKindInfo.h index 6979ad5807d..58183bd778e 100644 --- a/include/llvm/MC/MCFixupKindInfo.h +++ b/include/llvm/MC/MCFixupKindInfo.h @@ -12,7 +12,7 @@ namespace llvm { -/// MCFixupKindInfo - Target independent information on a fixup kind. +/// \brief Target independent information on a fixup kind. struct MCFixupKindInfo { enum FixupKindFlags { /// Is this fixup kind PCrelative? This is used by the assembler backend to diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h index 963b329cc07..4688b5f2b6e 100644 --- a/include/llvm/MC/MCInst.h +++ b/include/llvm/MC/MCInst.h @@ -28,16 +28,16 @@ class MCInstPrinter; class MCExpr; class MCInst; -/// MCOperand - Instances of this class represent operands of the MCInst class. +/// \brief Instances of this class represent operands of the MCInst class. /// This is a simple discriminated union. class MCOperand { enum MachineOperandType : unsigned char { - kInvalid, ///< Uninitialized. - kRegister, ///< Register operand. - kImmediate, ///< Immediate operand. - kFPImmediate, ///< Floating-point immediate operand. - kExpr, ///< Relocatable immediate operand. - kInst ///< Sub-instruction operand. + kInvalid, ///< Uninitialized. + kRegister, ///< Register operand. + kImmediate, ///< Immediate operand. + kFPImmediate, ///< Floating-point immediate operand. + kExpr, ///< Relocatable immediate operand. + kInst ///< Sub-instruction operand. }; MachineOperandType Kind; @@ -48,13 +48,9 @@ class MCOperand { const MCExpr *ExprVal; const MCInst *InstVal; }; -public: - // @LOCALMOD-START - // Initialize ImmVal instead of FPImmVal, thanks to - // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58416 - MCOperand() : Kind(kInvalid), ImmVal(0) {} - // @LOCALMOD-END +public: + MCOperand() : Kind(kInvalid), FPImmVal(0.0) {} bool isValid() const { return Kind != kInvalid; } bool isReg() const { return Kind == kRegister; } @@ -63,13 +59,13 @@ class MCOperand { bool isExpr() const { return Kind == kExpr; } bool isInst() const { return Kind == kInst; } - /// getReg - Returns the register number. + /// \brief Returns the register number. unsigned getReg() const { assert(isReg() && "This is not a register operand!"); return RegVal; } - /// setReg - Set the register number. + /// \brief Set the register number. void setReg(unsigned Reg) { assert(isReg() && "This is not a register operand!"); RegVal = Reg; @@ -112,31 +108,31 @@ class MCOperand { InstVal = Val; } - static MCOperand CreateReg(unsigned Reg) { + static MCOperand createReg(unsigned Reg) { MCOperand Op; Op.Kind = kRegister; Op.RegVal = Reg; return Op; } - static MCOperand CreateImm(int64_t Val) { + static MCOperand createImm(int64_t Val) { MCOperand Op; Op.Kind = kImmediate; Op.ImmVal = Val; return Op; } - static MCOperand CreateFPImm(double Val) { + static MCOperand createFPImm(double Val) { MCOperand Op; Op.Kind = kFPImmediate; Op.FPImmVal = Val; return Op; } - static MCOperand CreateExpr(const MCExpr *Val) { + static MCOperand createExpr(const MCExpr *Val) { MCOperand Op; Op.Kind = kExpr; Op.ExprVal = Val; return Op; } - static MCOperand CreateInst(const MCInst *Val) { + static MCOperand createInst(const MCInst *Val) { MCOperand Op; Op.Kind = kInst; Op.InstVal = Val; @@ -149,12 +145,13 @@ class MCOperand { template <> struct isPodLike { static const bool value = true; }; -/// MCInst - Instances of this class represent a single low-level machine +/// \brief Instances of this class represent a single low-level machine /// instruction. class MCInst { unsigned Opcode; SMLoc Loc; SmallVector Operands; + public: MCInst() : Opcode(0) {} @@ -168,18 +165,16 @@ class MCInst { MCOperand &getOperand(unsigned i) { return Operands[i]; } unsigned getNumOperands() const { return Operands.size(); } - void addOperand(const MCOperand &Op) { - Operands.push_back(Op); - } - - void clear() { Operands.clear(); } - size_t size() const { return Operands.size(); } + void addOperand(const MCOperand &Op) { Operands.push_back(Op); } typedef SmallVectorImpl::iterator iterator; typedef SmallVectorImpl::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(); } + iterator end() { return Operands.end(); } const_iterator end() const { return Operands.end(); } iterator insert(iterator I, const MCOperand &Op) { return Operands.insert(I, Op); diff --git a/include/llvm/MC/MCInstBuilder.h b/include/llvm/MC/MCInstBuilder.h index c5acb26eeca..30609bdb8b2 100644 --- a/include/llvm/MC/MCInstBuilder.h +++ b/include/llvm/MC/MCInstBuilder.h @@ -30,31 +30,37 @@ class MCInstBuilder { /// \brief Add a new register operand. MCInstBuilder &addReg(unsigned Reg) { - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return *this; } /// \brief Add a new integer immediate operand. MCInstBuilder &addImm(int64_t Val) { - Inst.addOperand(MCOperand::CreateImm(Val)); + Inst.addOperand(MCOperand::createImm(Val)); return *this; } /// \brief Add a new floating point immediate operand. MCInstBuilder &addFPImm(double Val) { - Inst.addOperand(MCOperand::CreateFPImm(Val)); + Inst.addOperand(MCOperand::createFPImm(Val)); return *this; } /// \brief Add a new MCExpr operand. MCInstBuilder &addExpr(const MCExpr *Val) { - Inst.addOperand(MCOperand::CreateExpr(Val)); + Inst.addOperand(MCOperand::createExpr(Val)); return *this; } /// \brief Add a new MCInst operand. MCInstBuilder &addInst(const MCInst *Val) { - Inst.addOperand(MCOperand::CreateInst(Val)); + Inst.addOperand(MCOperand::createInst(Val)); + return *this; + } + + /// \brief Add an operand. + MCInstBuilder &addOperand(const MCOperand &Op) { + Inst.addOperand(Op); return *this; } diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h index 4181d001add..0eafd02c51c 100644 --- a/include/llvm/MC/MCInstPrinter.h +++ b/include/llvm/MC/MCInstPrinter.h @@ -10,6 +10,7 @@ #ifndef LLVM_MC_MCINSTPRINTER_H #define LLVM_MC_MCINSTPRINTER_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/Format.h" @@ -22,20 +23,23 @@ class MCRegisterInfo; class MCSubtargetInfo; class StringRef; +/// Convert `Bytes' to a hex string and output to `OS' +void dumpBytes(ArrayRef Bytes, raw_ostream &OS); + namespace HexStyle { - enum Style { - C, ///< 0xff - Asm ///< 0ffh - }; +enum Style { + C, ///< 0xff + Asm ///< 0ffh +}; } -/// MCInstPrinter - This is an instance of a target assembly language printer -/// that converts an MCInst to valid target assembly syntax. +/// \brief This is an instance of a target assembly language printer that +/// converts an MCInst to valid target assembly syntax. class MCInstPrinter { protected: - /// CommentStream - a stream that comments can be emitted to if desired. - /// Each comment must end with a newline. This will be null if verbose - /// assembly emission is disable. + /// \brief A stream that comments can be emitted to if desired. Each comment + /// must end with a newline. This will be null if verbose assembly emission + /// is disable. raw_ostream *CommentStream; const MCAsmInfo &MAI; const MCInstrInfo &MII; @@ -52,28 +56,27 @@ class MCInstPrinter { /// Utility function for printing annotations. void printAnnotation(raw_ostream &OS, StringRef Annot); + public: MCInstPrinter(const MCAsmInfo &mai, const MCInstrInfo &mii, const MCRegisterInfo &mri) - : CommentStream(nullptr), MAI(mai), MII(mii), MRI(mri), - UseMarkup(0), PrintImmHex(0), - PrintHexStyle(HexStyle::C) {} + : CommentStream(nullptr), MAI(mai), MII(mii), MRI(mri), UseMarkup(0), + PrintImmHex(0), PrintHexStyle(HexStyle::C) {} virtual ~MCInstPrinter(); - /// setCommentStream - Specify a stream to emit comments to. + /// \brief Specify a stream to emit comments to. void setCommentStream(raw_ostream &OS) { CommentStream = &OS; } - /// printInst - Print the specified MCInst to the specified raw_ostream. - /// - virtual void printInst(const MCInst *MI, raw_ostream &OS, - StringRef Annot, const MCSubtargetInfo &STI) = 0; + /// \brief Print the specified MCInst to the specified raw_ostream. + virtual void printInst(const MCInst *MI, raw_ostream &OS, StringRef Annot, + const MCSubtargetInfo &STI) = 0; - /// getOpcodeName - Return the name of the specified opcode enum (e.g. - /// "MOV32ri") or empty if we can't resolve it. + /// \brief Return the name of the specified opcode enum (e.g. "MOV32ri") or + /// empty if we can't resolve it. StringRef getOpcodeName(unsigned Opcode) const; - /// printRegName - Print the assembler register name. + /// \brief Print the assembler register name. virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; bool getUseMarkup() const { return UseMarkup; } @@ -86,8 +89,8 @@ class MCInstPrinter { 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 formatImm(int64_t Value) const { diff --git a/include/llvm/MC/MCInstrAnalysis.h b/include/llvm/MC/MCInstrAnalysis.h index e921f768ac4..8f5159e9e1c 100644 --- a/include/llvm/MC/MCInstrAnalysis.h +++ b/include/llvm/MC/MCInstrAnalysis.h @@ -59,8 +59,8 @@ class MCInstrAnalysis { return Info->get(Inst.getOpcode()).isTerminator(); } - /// evaluateBranch - Given a branch instruction try to get the address the - /// branch targets. Return true on success, and the address in Target. + /// \brief Given a branch instruction try to get the address the branch + /// targets. Return true on success, and the address in Target. virtual bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, uint64_t &Target) const; diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h index 360989305d3..6a582e82d00 100644 --- a/include/llvm/MC/MCInstrDesc.h +++ b/include/llvm/MC/MCInstrDesc.h @@ -15,145 +15,147 @@ #ifndef LLVM_MC_MCINSTRDESC_H #define LLVM_MC_MCINSTRDESC_H -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/DataTypes.h" +#include namespace llvm { + class MCInst; + class MCRegisterInfo; + class MCSubtargetInfo; + class FeatureBitset; //===----------------------------------------------------------------------===// // Machine Operand Flags and Description //===----------------------------------------------------------------------===// namespace MCOI { - // Operand constraints - enum OperandConstraint { - TIED_TO = 0, // Must be allocated the same register as. - EARLY_CLOBBER // Operand is an early clobber register operand - }; - - /// OperandFlags - These are flags set on operands, but should be considered - /// private, all access should go through the MCOperandInfo accessors. - /// See the accessors for a description of what these are. - enum OperandFlags { - LookupPtrRegClass = 0, - Predicate, - OptionalDef - }; - - /// Operand Type - Operands are tagged with one of the values of this enum. - enum OperandType { - OPERAND_UNKNOWN = 0, - OPERAND_IMMEDIATE = 1, - OPERAND_REGISTER = 2, - OPERAND_MEMORY = 3, - OPERAND_PCREL = 4, - OPERAND_FIRST_TARGET = 5 - }; +// Operand constraints +enum OperandConstraint { + TIED_TO = 0, // Must be allocated the same register as. + EARLY_CLOBBER // Operand is an early clobber register operand +}; + +/// \brief These are flags set on operands, but should be considered +/// private, all access should go through the MCOperandInfo accessors. +/// See the accessors for a description of what these are. +enum OperandFlags { LookupPtrRegClass = 0, Predicate, OptionalDef }; + +/// \brief Operands are tagged with one of the values of this enum. +enum OperandType { + OPERAND_UNKNOWN = 0, + OPERAND_IMMEDIATE = 1, + OPERAND_REGISTER = 2, + OPERAND_MEMORY = 3, + OPERAND_PCREL = 4, + OPERAND_FIRST_TARGET = 5 +}; } -/// MCOperandInfo - This holds information about one operand of a machine -/// instruction, indicating the register class for register operands, etc. -/// +/// \brief This holds information about one operand of a machine instruction, +/// indicating the register class for register operands, etc. class MCOperandInfo { public: - /// RegClass - This specifies the register class enumeration of the operand + /// \brief This specifies the register class enumeration of the operand /// if the operand is a register. If isLookupPtrRegClass is set, then this is /// an index that is passed to TargetRegisterInfo::getPointerRegClass(x) to /// get a dynamic register class. int16_t RegClass; - /// Flags - These are flags from the MCOI::OperandFlags enum. + /// \brief These are flags from the MCOI::OperandFlags enum. uint8_t Flags; - /// OperandType - Information about the type of the operand. + /// \brief Information about the type of the operand. uint8_t OperandType; - - /// Lower 16 bits are used to specify which constraints are set. The higher 16 - /// bits are used to specify the value of constraints (4 bits each). + /// \brief The lower 16 bits are used to specify which constraints are set. + /// The higher 16 bits are used to specify the value of constraints (4 bits + /// each). uint32_t Constraints; - /// Currently no other information. - /// isLookupPtrRegClass - Set if this operand is a pointer value and it - /// requires a callback to look up its register class. - bool isLookupPtrRegClass() const {return Flags&(1 <isSubRegister(Reg, *ImpDefs))) - return true; - return false; - } - - /// \brief Return true if this instruction defines the specified physical - /// register, either explicitly or implicitly. - bool hasDefOfPhysReg(const MCInst &MI, unsigned Reg, - const MCRegisterInfo &RI) const { - for (int i = 0, e = NumDefs; i != e; ++i) - if (MI.getOperand(i).isReg() && - RI.isSubRegisterEq(Reg, MI.getOperand(i).getReg())) - return true; - return hasImplicitDefOfPhysReg(Reg, &RI); - } + const MCRegisterInfo *MRI = nullptr) const; /// \brief Return the scheduling class for this instruction. The /// scheduling class is an index into the InstrItineraryData table. This /// returns zero if there is no known scheduling information for the /// instruction. - unsigned getSchedClass() const { - return SchedClass; - } + unsigned getSchedClass() const { return SchedClass; } /// \brief Return the number of bytes in the encoding of this instruction, /// or zero if the encoding size cannot be known from the opcode. - unsigned getSize() const { - return Size; - } + unsigned getSize() const { return Size; } /// \brief Find the index of the first operand in the /// operand list that is used to represent the predicate. It returns -1 if @@ -639,6 +542,13 @@ class MCInstrDesc { } return -1; } + +private: + + /// \brief Return true if this instruction defines the specified physical + /// register, either explicitly or implicitly. + bool hasDefOfPhysReg(const MCInst &MI, unsigned Reg, + const MCRegisterInfo &RI) const; }; } // end namespace llvm diff --git a/include/llvm/MC/MCInstrInfo.h b/include/llvm/MC/MCInstrInfo.h index 1d3a36ca7c7..70c86587b08 100644 --- a/include/llvm/MC/MCInstrInfo.h +++ b/include/llvm/MC/MCInstrInfo.h @@ -20,9 +20,7 @@ namespace llvm { //--------------------------------------------------------------------------- -/// -/// MCInstrInfo - Interface to description of machine instruction set -/// +/// \brief Interface to description of machine instruction set. class MCInstrInfo { const MCInstrDesc *Desc; // Raw array to allow static init'n const unsigned *InstrNameIndices; // Array for name indices in InstrNameData @@ -30,8 +28,8 @@ class MCInstrInfo { unsigned NumOpcodes; // Number of entries in the desc array public: - /// InitMCInstrInfo - Initialize MCInstrInfo, called by TableGen - /// auto-generated routines. *DO NOT USE*. + /// \brief Initialize MCInstrInfo, called by TableGen auto-generated routines. + /// *DO NOT USE*. void InitMCInstrInfo(const MCInstrDesc *D, const unsigned *NI, const char *ND, unsigned NO) { Desc = D; @@ -42,15 +40,14 @@ class MCInstrInfo { unsigned getNumOpcodes() const { return NumOpcodes; } - /// get - Return the machine instruction descriptor that corresponds to the + /// \brief Return the machine instruction descriptor that corresponds to the /// specified instruction opcode. - /// const MCInstrDesc &get(unsigned Opcode) const { assert(Opcode < NumOpcodes && "Invalid opcode!"); return Desc[Opcode]; } - /// getName - Returns the name for the instructions with the given opcode. + /// \brief Returns the name for the instructions with the given opcode. const char *getName(unsigned Opcode) const { assert(Opcode < NumOpcodes && "Invalid opcode!"); return &InstrNameData[InstrNameIndices[Opcode]]; diff --git a/include/llvm/MC/MCInstrItineraries.h b/include/llvm/MC/MCInstrItineraries.h index 94d599f672a..161705de7c4 100644 --- a/include/llvm/MC/MCInstrItineraries.h +++ b/include/llvm/MC/MCInstrItineraries.h @@ -67,12 +67,12 @@ struct InstrStage { int NextCycles_; ///< Number of machine cycles to next stage ReservationKinds Kind_; ///< Kind of the FU reservation - /// Returns the number of cycles the stage is occupied. + /// \brief Returns the number of cycles the stage is occupied. unsigned getCycles() const { return Cycles_; } - /// Returns the choice of FUs. + /// \brief Returns the choice of FUs. unsigned getUnits() const { return Units_; } @@ -81,8 +81,8 @@ struct InstrStage { return Kind_; } - /// Returns the number of cycles from the start of - /// this stage to the start of the next stage in the itinerary + /// \brief Returns the number of cycles from the start of this stage to the + /// start of the next stage in the itinerary unsigned getNextCycles() const { return (NextCycles_ >= 0) ? (unsigned)NextCycles_ : Cycles_; } @@ -115,7 +115,6 @@ class InstrItineraryData { const InstrItinerary *Itineraries; ///< Array of itineraries selected /// Ctors. - /// InstrItineraryData() : SchedModel(MCSchedModel::GetDefaultSchedModel()), Stages(nullptr), OperandCycles(nullptr), Forwardings(nullptr), Itineraries(nullptr) {} @@ -125,30 +124,30 @@ class InstrItineraryData { : SchedModel(SM), Stages(S), OperandCycles(OS), Forwardings(F), Itineraries(SchedModel.InstrItineraries) {} - /// Returns true if there are no itineraries. + /// \brief Returns true if there are no itineraries. bool isEmpty() const { return Itineraries == nullptr; } - /// Returns true if the index is for the end marker itinerary. + /// \brief Returns true if the index is for the end marker itinerary. bool isEndMarker(unsigned ItinClassIndx) const { return ((Itineraries[ItinClassIndx].FirstStage == ~0U) && (Itineraries[ItinClassIndx].LastStage == ~0U)); } - /// Return the first stage of the itinerary. + /// \brief Return the first stage of the itinerary. const InstrStage *beginStage(unsigned ItinClassIndx) const { unsigned StageIdx = Itineraries[ItinClassIndx].FirstStage; return Stages + StageIdx; } - /// Return the last+1 stage of the itinerary. + /// \brief Return the last+1 stage of the itinerary. const InstrStage *endStage(unsigned ItinClassIndx) const { unsigned StageIdx = Itineraries[ItinClassIndx].LastStage; return Stages + StageIdx; } - /// Return the total stage latency of the given class. - /// The latency is the maximum completion time for any stage in the itinerary. - /// If no stages exist, it defaults to one cycle. + /// \brief Return the total stage latency of the given class. The latency is + /// the maximum completion time for any stage in the itinerary. If no stages + /// exist, it defaults to one cycle. unsigned getStageLatency(unsigned ItinClassIndx) const { // If the target doesn't provide itinerary information, use a simple // non-zero default value for all instructions. @@ -165,8 +164,8 @@ class InstrItineraryData { return Latency; } - /// Return the cycle for the given class and operand. - /// Return -1 if no cycle is specified for the operand. + /// \brief Return the cycle for the given class and operand. Return -1 if no + /// cycle is specified for the operand. int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const { if (isEmpty()) return -1; @@ -179,11 +178,11 @@ class InstrItineraryData { return (int)OperandCycles[FirstIdx + OperandIdx]; } - /// Return true if there is a pipeline forwarding - /// between instructions of itinerary classes DefClass and UseClasses so that - /// value produced by an instruction of itinerary class DefClass, operand - /// index DefIdx can be bypassed when it's read by an instruction of - /// itinerary class UseClass, operand index UseIdx. + /// \brief Return true if there is a pipeline forwarding between instructions + /// of itinerary classes DefClass and UseClasses so that value produced by an + /// instruction of itinerary class DefClass, operand index DefIdx can be + /// bypassed when it's read by an instruction of itinerary class UseClass, + /// operand index UseIdx. bool hasPipelineForwarding(unsigned DefClass, unsigned DefIdx, unsigned UseClass, unsigned UseIdx) const { unsigned FirstDefIdx = Itineraries[DefClass].FirstOperandCycle; @@ -202,9 +201,9 @@ class InstrItineraryData { Forwardings[FirstUseIdx + UseIdx]; } - /// Compute and return the use operand latency of a given - /// itinerary class and operand index if the value is produced by an - /// instruction of the specified itinerary class and def operand index. + /// \brief Compute and return the use operand latency of a given itinerary + /// class and operand index if the value is produced by an instruction of the + /// specified itinerary class and def operand index. int getOperandLatency(unsigned DefClass, unsigned DefIdx, unsigned UseClass, unsigned UseIdx) const { if (isEmpty()) @@ -226,7 +225,7 @@ class InstrItineraryData { return UseCycle; } - /// Return the number of micro-ops that the given class decodes to. + /// \brief Return the number of micro-ops that the given class decodes to. /// Return -1 for classes that require dynamic lookup via TargetInstrInfo. int getNumMicroOps(unsigned ItinClassIndx) const { if (isEmpty()) diff --git a/include/llvm/MC/MCLabel.h b/include/llvm/MC/MCLabel.h index a386deb554c..a12473fdad0 100644 --- a/include/llvm/MC/MCLabel.h +++ b/include/llvm/MC/MCLabel.h @@ -17,42 +17,41 @@ #include "llvm/Support/Compiler.h" namespace llvm { - class MCContext; - class raw_ostream; - - /// MCLabel - Instances of this class represent a label name in the MC file, - /// and MCLabel are created and unique'd by the MCContext class. MCLabel - /// should only be constructed for valid instances in the object file. - class MCLabel { - // Instance - the instance number of this Directional Local Label - unsigned Instance; - - private: // MCContext creates and uniques these. - friend class MCContext; - MCLabel(unsigned instance) - : Instance(instance) {} - - MCLabel(const MCLabel&) = delete; - void operator=(const MCLabel&) = delete; - public: - /// getInstance - Get the current instance of this Directional Local Label. - unsigned getInstance() const { return Instance; } - - /// incInstance - Increment the current instance of this Directional Local - /// Label. - unsigned incInstance() { return ++Instance; } - - /// 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 MCLabel &Label) { - Label.print(OS); - return OS; - } +class MCContext; +class raw_ostream; + +/// \brief Instances of this class represent a label name in the MC file, +/// and MCLabel are created and uniqued by the MCContext class. MCLabel +/// should only be constructed for valid instances in the object file. +class MCLabel { + // \brief The instance number of this Directional Local Label. + unsigned Instance; + +private: // MCContext creates and uniques these. + friend class MCContext; + MCLabel(unsigned instance) : Instance(instance) {} + + MCLabel(const MCLabel &) = delete; + void operator=(const MCLabel &) = delete; + +public: + /// \brief Get the current instance of this Directional Local Label. + unsigned getInstance() const { return Instance; } + + /// \brief Increment the current instance of this Directional Local Label. + unsigned incInstance() { return ++Instance; } + + /// \brief Print the value to the stream \p OS. + void print(raw_ostream &OS) const; + + /// \brief Print the value to stderr. + void dump() const; +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const MCLabel &Label) { + Label.print(OS); + return OS; +} } // end namespace llvm #endif diff --git a/include/llvm/MC/MCLinkerOptimizationHint.h b/include/llvm/MC/MCLinkerOptimizationHint.h index c96d5782bc4..a519c4b71b0 100644 --- a/include/llvm/MC/MCLinkerOptimizationHint.h +++ b/include/llvm/MC/MCLinkerOptimizationHint.h @@ -103,10 +103,10 @@ class MCLOHDirective { /// Arguments of this directive. Order matters. SmallVector Args; - /// Emit this directive in @p OutStream using the information available - /// in the given @p ObjWriter and @p Layout to get the address of the + /// Emit this directive in \p OutStream using the information available + /// in the given \p ObjWriter and \p Layout to get the address of the /// arguments within the object file. - void Emit_impl(raw_ostream &OutStream, const MachObjectWriter &ObjWriter, + void emit_impl(raw_ostream &OutStream, const MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const; public: @@ -123,13 +123,13 @@ class MCLOHDirective { /// Emit this directive as: /// - void Emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const { + void emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const { raw_ostream &OutStream = ObjWriter.getStream(); - Emit_impl(OutStream, ObjWriter, Layout); + emit_impl(OutStream, ObjWriter, Layout); } - /// Get the size in bytes of this directive if emitted in @p ObjWriter with - /// the given @p Layout. + /// Get the size in bytes of this directive if emitted in \p ObjWriter with + /// the given \p Layout. uint64_t getEmitSize(const MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const { class raw_counting_ostream : public raw_ostream { @@ -145,7 +145,7 @@ class MCLOHDirective { }; raw_counting_ostream OutStream; - Emit_impl(OutStream, ObjWriter, Layout); + emit_impl(OutStream, ObjWriter, Layout); return OutStream.tell(); } }; @@ -160,15 +160,15 @@ class MCLOHContainer { public: typedef SmallVectorImpl LOHDirectives; - MCLOHContainer() : EmitSize(0) {}; + MCLOHContainer() : EmitSize(0) {} /// Const accessor to the directives. const LOHDirectives &getDirectives() const { return Directives; } - /// Add the directive of the given kind @p Kind with the given arguments - /// @p Args to the container. + /// Add the directive of the given kind \p Kind with the given arguments + /// \p Args to the container. void addDirective(MCLOHType Kind, const MCLOHDirective::LOHArgs &Args) { Directives.push_back(MCLOHDirective(Kind, Args)); } @@ -184,10 +184,10 @@ class MCLOHContainer { } /// Emit all Linker Optimization Hint in one big table. - /// Each line of the table is emitted by LOHDirective::Emit. - void Emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const { + /// Each line of the table is emitted by LOHDirective::emit. + void emit(MachObjectWriter &ObjWriter, const MCAsmLayout &Layout) const { for (const MCLOHDirective &D : Directives) - D.Emit(ObjWriter, Layout); + D.emit(ObjWriter, Layout); } void reset() { diff --git a/include/llvm/MC/MCMachOSymbolFlags.h b/include/llvm/MC/MCMachOSymbolFlags.h deleted file mode 100644 index 71f01fab206..00000000000 --- a/include/llvm/MC/MCMachOSymbolFlags.h +++ /dev/null @@ -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 . - 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 diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index bfe5d3614c0..175d73e72c1 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -21,22 +21,17 @@ namespace llvm { -class MCSectionData; class MachObjectWriter; 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; @@ -45,18 +40,17 @@ class MCMachObjectTargetWriter { public: virtual ~MCMachObjectTargetWriter(); - /// @name Lifetime Management + /// \name Lifetime Management /// @{ - virtual void reset() {}; + virtual void reset() {} /// @} - /// @name Accessors + /// \name Accessors /// @{ 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 { @@ -65,10 +59,10 @@ class MCMachObjectTargetWriter { /// @} - /// @name API + /// \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, @@ -78,10 +72,9 @@ class MCMachObjectTargetWriter { }; 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 { - MCSymbolData *SymbolData; + const MCSymbol *Symbol; uint64_t StringIndex; uint8_t SectionIndex; @@ -92,21 +85,23 @@ class MachObjectWriter : public MCObjectWriter { /// The target specific Mach-O writer instance. std::unique_ptr TargetObjectWriter; - /// @name Relocation Data + /// \name Relocation Data /// @{ struct RelAndSymbol { - const MCSymbolData *Sym; + const MCSymbol *Sym; MachO::any_relocation_info MRE; - RelAndSymbol(const MCSymbolData *Sym, const MachO::any_relocation_info &MRE) + RelAndSymbol(const MCSymbol *Sym, const MachO::any_relocation_info &MRE) : Sym(Sym), MRE(MRE) {} }; - llvm::DenseMap> Relocations; - llvm::DenseMap IndirectSymBase; + llvm::DenseMap> Relocations; + llvm::DenseMap IndirectSymBase; + + SectionAddrMap SectionAddress; /// @} - /// @name Symbol Table Data + /// \name Symbol Table Data /// @{ StringTableBuilder StringTable; @@ -123,39 +118,37 @@ class MachObjectWriter : public MCObjectWriter { bool IsLittleEndian) : MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW) {} - /// @name Lifetime management Methods + const MCSymbol &findAliasedSymbol(const MCSymbol &Sym) const; + + /// \name Lifetime management Methods /// @{ void reset() override; /// @} - /// @name Utility Methods + /// \name Utility Methods /// @{ bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind); - SectionAddrMap SectionAddress; - SectionAddrMap &getSectionAddressMap() { return SectionAddress; } - uint64_t getSectionAddress(const MCSectionData* SD) const { - return SectionAddress.lookup(SD); + uint64_t getSectionAddress(const MCSection *Sec) const { + return SectionAddress.lookup(Sec); } - uint64_t getSymbolAddress(const MCSymbolData* SD, - const MCAsmLayout &Layout) const; + uint64_t getSymbolAddress(const MCSymbol &S, const MCAsmLayout &Layout) const; uint64_t getFragmentAddress(const MCFragment *Fragment, const MCAsmLayout &Layout) const; - uint64_t getPaddingSize(const MCSectionData *SD, - const MCAsmLayout &Layout) const; + uint64_t getPaddingSize(const MCSection *SD, const MCAsmLayout &Layout) const; - bool doesSymbolRequireExternRelocation(const MCSymbolData *SD); + bool doesSymbolRequireExternRelocation(const MCSymbol &S); /// @} - /// @name Target Writer Proxy Accessors + /// \name Target Writer Proxy Accessors /// @{ bool is64Bit() const { return TargetObjectWriter->is64Bit(); } @@ -166,41 +159,37 @@ class MachObjectWriter : public MCObjectWriter { /// @} - 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, - const MCSectionData &SD, uint64_t FileOffset, + 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 &Options); + void writeLinkerOptionsLoadCommand(const std::vector &Options); // FIXME: We really need to improve the relocation validation. Basically, we // want to implement a separate computation which evaluates the relocation @@ -221,35 +210,31 @@ class MachObjectWriter : public MCObjectWriter { // to a symbol it should be passed as \p RelSymbol so that it can be updated // afterwards. If the relocation doesn't refer to a symbol, nullptr should be // used. - void addRelocation(const MCSymbolData *RelSymbol, const MCSectionData *SD, + void addRelocation(const MCSymbol *RelSymbol, const MCSection *Sec, MachO::any_relocation_info &MRE) { RelAndSymbol P(RelSymbol, MRE); - Relocations[SD].push_back(P); + 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 &LocalSymbolData, std::vector &ExternalSymbolData, std::vector &UndefinedSymbolData); @@ -257,21 +242,18 @@ class MachObjectWriter : public MCObjectWriter { 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, - const MCSymbolData &DataA, - const MCSymbolData *DataB, - const MCFragment &FB, - bool InSet, + 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. /// diff --git a/include/llvm/MC/MCNaCl.h b/include/llvm/MC/MCNaCl.h deleted file mode 100644 index d7617da6ca1..00000000000 --- a/include/llvm/MC/MCNaCl.h +++ /dev/null @@ -1,22 +0,0 @@ -//===- MCNaCl.h - NaCl-specific code for MC --------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/CommandLine.h" - -namespace llvm { - -class MCContext; -class MCStreamer; -class Triple; -/// Initialize target-specific bundle alignment and emit target-specific NaCl -/// ELF note sections. -void initializeNaClMCStreamer(MCStreamer &Streamer, MCContext &Ctx, - const Triple &TheTriple); - -} diff --git a/include/llvm/MC/MCNaClExpander.h b/include/llvm/MC/MCNaClExpander.h deleted file mode 100644 index 80d3d2f76ea..00000000000 --- a/include/llvm/MC/MCNaClExpander.h +++ /dev/null @@ -1,59 +0,0 @@ -//===- MCNaClExpander.h -----------------------------------------*- 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 MCNaClExpander class. This is an abstract -// class that encapsulates the expansion logic for MCInsts, and holds -// state such as available scratch registers. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_MCNACLEXPANDER_H -#define LLVM_MC_MCNACLEXPANDER_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCRegisterInfo.h" - -namespace llvm { -class MCInst; -class MCSubtargetInfo; -class MCStreamer; -class SourceMgr; - -class MCNaClExpander { -private: - SmallVector ScratchRegs; - const SourceMgr *SrcMgr; - -protected: - std::unique_ptr InstInfo; - std::unique_ptr RegInfo; - -public: - MCNaClExpander(const MCContext &Ctx, std::unique_ptr &&RI, - std::unique_ptr &&II) - : InstInfo(std::move(II)), RegInfo(std::move(RI)) { - SrcMgr = Ctx.getSourceManager(); - } - - void Error(const MCInst &Inst, const char msg[]); - - void pushScratchReg(unsigned Reg); - unsigned popScratchReg(); - unsigned getScratchReg(int index); - unsigned numScratchRegs(); - - virtual ~MCNaClExpander() = default; - virtual bool expandInst(const MCInst &Inst, MCStreamer &Out, - const MCSubtargetInfo &STI) = 0; -}; - -} -#endif diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h index 025a76a27af..b9cea06161d 100644 --- a/include/llvm/MC/MCObjectFileInfo.h +++ b/include/llvm/MC/MCObjectFileInfo.h @@ -18,28 +18,24 @@ #include "llvm/Support/CodeGen.h" namespace llvm { - class MCContext; - class MCSection; - class StringRef; +class MCContext; +class MCSection; 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,151 +45,154 @@ class MCObjectFileInfo { 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; - /// TextSection - Section directive for standard text. - /// - const MCSection *TextSection; + /// Section directive for standard text. + MCSection *TextSection; - /// DataSection - Section directive for standard data. - /// - const MCSection *DataSection; + /// Section directive for standard data. + MCSection *DataSection; - /// BSSSection - Section that is default initialized to zero. - const MCSection *BSSSection; + /// Section that is default initialized to zero. + MCSection *BSSSection; - /// ReadOnlySection - Section that is readonly and can contain arbitrary - /// initialized data. Targets are not required to have a readonly section. - /// If they don't, various bits of code will fall back to using the data - /// section for constants. - const MCSection *ReadOnlySection; + /// Section that is readonly and can contain arbitrary initialized data. + /// Targets are not required to have a readonly section. If they don't, + /// various bits of code will fall back to using the data section for + /// constants. + MCSection *ReadOnlySection; - /// StaticCtorSection - This section contains the static constructor pointer - /// list. - const MCSection *StaticCtorSection; + /// This section contains the static constructor pointer list. + MCSection *StaticCtorSection; - /// StaticDtorSection - This section contains the static destructor pointer - /// list. - const MCSection *StaticDtorSection; + /// This section contains the static destructor pointer list. + MCSection *StaticDtorSection; - /// LSDASection - If exception handling is supported by the target, this is - /// the section the Language Specific Data Area information is emitted to. - const MCSection *LSDASection; + /// If exception handling is supported by the target, this is the section the + /// Language Specific Data Area information is emitted to. + MCSection *LSDASection; - /// CompactUnwindSection - If exception handling is supported by the target - /// and the target can support a compact representation of the CIE and FDE, - /// this is the section to emit them into. - const MCSection *CompactUnwindSection; + /// If exception handling is supported by the target and the target can + /// support a compact representation of the CIE and FDE, this is the section + /// to emit them into. + MCSection *CompactUnwindSection; // Dwarf sections for debug info. If a target supports debug info, these must // be set. - const MCSection *DwarfAbbrevSection; - const MCSection *DwarfInfoSection; - const MCSection *DwarfLineSection; - const MCSection *DwarfFrameSection; - const MCSection *DwarfPubTypesSection; + MCSection *DwarfAbbrevSection; + MCSection *DwarfInfoSection; + MCSection *DwarfLineSection; + MCSection *DwarfFrameSection; + MCSection *DwarfPubTypesSection; const MCSection *DwarfDebugInlineSection; - const MCSection *DwarfStrSection; - const MCSection *DwarfLocSection; - const MCSection *DwarfARangesSection; - const MCSection *DwarfRangesSection; + MCSection *DwarfStrSection; + MCSection *DwarfLocSection; + MCSection *DwarfARangesSection; + MCSection *DwarfRangesSection; // The pubnames section is no longer generated by default. The generation // can be enabled by a compiler flag. - const MCSection *DwarfPubNamesSection; + 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 /// sections. - const MCSection *DwarfAccelNamesSection; - const MCSection *DwarfAccelObjCSection; - const MCSection *DwarfAccelNamespaceSection; - const MCSection *DwarfAccelTypesSection; - - /// These are used for the Fission separate debug information files. - const MCSection *DwarfInfoDWOSection; - const MCSection *DwarfTypesDWOSection; - const MCSection *DwarfAbbrevDWOSection; - const MCSection *DwarfStrDWOSection; - const MCSection *DwarfLineDWOSection; - const MCSection *DwarfLocDWOSection; - const MCSection *DwarfStrOffDWOSection; - const MCSection *DwarfAddrSection; - - /// Sections for newer gnu pubnames and pubtypes. - const MCSection *DwarfGnuPubNamesSection; - const MCSection *DwarfGnuPubTypesSection; - - const MCSection *COFFDebugSymbolsSection; - - // Extra TLS Variable Data section. If the target needs to put additional - // information for a TLS variable, it'll go here. - const MCSection *TLSExtraDataSection; - - /// TLSDataSection - Section directive for Thread Local data. - /// ELF, MachO and COFF. - const MCSection *TLSDataSection; // Defaults to ".tdata". - - /// TLSBSSSection - Section directive for Thread Local uninitialized data. - /// Null if this target doesn't support a BSS section. - /// ELF and MachO only. - const MCSection *TLSBSSSection; // Defaults to ".tbss". + MCSection *DwarfAccelNamesSection; + MCSection *DwarfAccelObjCSection; + MCSection *DwarfAccelNamespaceSection; + MCSection *DwarfAccelTypesSection; + + // These are used for the Fission separate debug information files. + MCSection *DwarfInfoDWOSection; + MCSection *DwarfTypesDWOSection; + MCSection *DwarfAbbrevDWOSection; + MCSection *DwarfStrDWOSection; + MCSection *DwarfLineDWOSection; + MCSection *DwarfLocDWOSection; + MCSection *DwarfStrOffDWOSection; + MCSection *DwarfAddrSection; + + /// 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. + 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. + MCSection *TLSBSSSection; // Defaults to ".tbss". /// StackMap section. - const MCSection *StackMapSection; + MCSection *StackMapSection; - /// EHFrameSection - EH frame section. It is initialized on demand so it - /// can be overwritten (with uniquing). - const MCSection *EHFrameSection; + /// FaultMap section. + MCSection *FaultMapSection; - /// ELF specific sections. + /// EH frame section. /// - const MCSection *DataRelSection; + /// It is initialized on demand so it can be overwritten (with uniquing). + MCSection *EHFrameSection; + + // ELF specific sections. + MCSection *DataRelSection; const MCSection *DataRelLocalSection; - const MCSection *DataRelROSection; - const MCSection *DataRelROLocalSection; - const MCSection *MergeableConst4Section; - const MCSection *MergeableConst8Section; - const MCSection *MergeableConst16Section; + MCSection *DataRelROSection; + MCSection *DataRelROLocalSection; + MCSection *MergeableConst4Section; + MCSection *MergeableConst8Section; + MCSection *MergeableConst16Section; - /// MachO specific sections. - /// + // MachO specific sections. - /// TLSTLVSection - 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). - const MCSection *TLSTLVSection; // Defaults to ".tlv". - - /// TLSThreadInitSection - Section for thread local data initialization - /// functions. - const MCSection *TLSThreadInitSection; // Defaults to ".thread_init_func". - - const MCSection *CStringSection; - const MCSection *UStringSection; - const MCSection *TextCoalSection; - const MCSection *ConstTextCoalSection; - const MCSection *ConstDataSection; - const MCSection *DataCoalSection; - const MCSection *DataCommonSection; - const MCSection *DataBSSSection; - const MCSection *FourByteConstantSection; - const MCSection *EightByteConstantSection; - const MCSection *SixteenByteConstantSection; - const MCSection *LazySymbolPointerSection; - const MCSection *NonLazySymbolPointerSection; + /// 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". + + /// Section for thread local data initialization functions. + const MCSection *TLSThreadInitSection; // Defaults to ".thread_init_func". + + MCSection *CStringSection; + MCSection *UStringSection; + MCSection *TextCoalSection; + MCSection *ConstTextCoalSection; + MCSection *ConstDataSection; + MCSection *DataCoalSection; + MCSection *DataCommonSection; + MCSection *DataBSSSection; + MCSection *FourByteConstantSection; + MCSection *EightByteConstantSection; + MCSection *SixteenByteConstantSection; + MCSection *LazySymbolPointerSection; + MCSection *NonLazySymbolPointerSection; /// COFF specific sections. - /// - const MCSection *DrectveSection; - const MCSection *PDataSection; - const MCSection *XDataSection; + MCSection *DrectveSection; + MCSection *PDataSection; + MCSection *XDataSection; + MCSection *SXDataSection; public: - void InitMCObjectFileInfo(StringRef TT, Reloc::Model RM, CodeModel::Model CM, - MCContext &ctx); + void InitMCObjectFileInfo(const Triple &TT, Reloc::Model RM, + CodeModel::Model CM, MCContext &ctx); + LLVM_ATTRIBUTE_DEPRECATED( + void InitMCObjectFileInfo(StringRef TT, Reloc::Model RM, + CodeModel::Model CM, MCContext &ctx), + "StringRef GNU Triple argument replaced by a llvm::Triple object"); bool getSupportsWeakOmittedEHFrame() const { return SupportsWeakOmittedEHFrame; @@ -214,94 +213,71 @@ class MCObjectFileInfo { return CompactUnwindDwarfEHFrameOnly; } - const MCSection *getTextSection() const { return TextSection; } - const MCSection *getDataSection() const { return DataSection; } - const MCSection *getBSSSection() const { return BSSSection; } - const MCSection *getLSDASection() const { return LSDASection; } - const MCSection *getCompactUnwindSection() const{ - return CompactUnwindSection; - } - const MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; } - const MCSection *getDwarfInfoSection() const { return DwarfInfoSection; } - const MCSection *getDwarfLineSection() const { return DwarfLineSection; } - const MCSection *getDwarfFrameSection() const { return DwarfFrameSection; } - const MCSection *getDwarfPubNamesSection() const{return DwarfPubNamesSection;} - const MCSection *getDwarfPubTypesSection() const{return DwarfPubTypesSection;} - const MCSection *getDwarfGnuPubNamesSection() const { + MCSection *getTextSection() const { return TextSection; } + MCSection *getDataSection() const { return DataSection; } + MCSection *getBSSSection() const { return BSSSection; } + MCSection *getReadOnlySection() const { return ReadOnlySection; } + MCSection *getLSDASection() const { return LSDASection; } + MCSection *getCompactUnwindSection() const { return CompactUnwindSection; } + MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; } + MCSection *getDwarfInfoSection() const { return DwarfInfoSection; } + MCSection *getDwarfLineSection() const { return DwarfLineSection; } + MCSection *getDwarfFrameSection() const { return DwarfFrameSection; } + MCSection *getDwarfPubNamesSection() const { return DwarfPubNamesSection; } + MCSection *getDwarfPubTypesSection() const { return DwarfPubTypesSection; } + MCSection *getDwarfGnuPubNamesSection() const { return DwarfGnuPubNamesSection; } - const MCSection *getDwarfGnuPubTypesSection() const { + MCSection *getDwarfGnuPubTypesSection() const { return DwarfGnuPubTypesSection; } const MCSection *getDwarfDebugInlineSection() const { return DwarfDebugInlineSection; } - const MCSection *getDwarfStrSection() const { return DwarfStrSection; } - const MCSection *getDwarfLocSection() const { return DwarfLocSection; } - const MCSection *getDwarfARangesSection() const { return DwarfARangesSection;} - const MCSection *getDwarfRangesSection() const { return DwarfRangesSection; } + MCSection *getDwarfStrSection() const { return DwarfStrSection; } + MCSection *getDwarfLocSection() const { return DwarfLocSection; } + MCSection *getDwarfARangesSection() const { return DwarfARangesSection; } + MCSection *getDwarfRangesSection() const { return DwarfRangesSection; } // DWARF5 Experimental Debug Info Sections - const MCSection *getDwarfAccelNamesSection() const { + MCSection *getDwarfAccelNamesSection() const { return DwarfAccelNamesSection; } - const MCSection *getDwarfAccelObjCSection() const { - return DwarfAccelObjCSection; - } - const MCSection *getDwarfAccelNamespaceSection() const { + MCSection *getDwarfAccelObjCSection() const { return DwarfAccelObjCSection; } + MCSection *getDwarfAccelNamespaceSection() const { return DwarfAccelNamespaceSection; } - const MCSection *getDwarfAccelTypesSection() const { + MCSection *getDwarfAccelTypesSection() const { return DwarfAccelTypesSection; } - const MCSection *getDwarfInfoDWOSection() const { - return DwarfInfoDWOSection; - } - const MCSection *getDwarfTypesSection(uint64_t Hash) const; - const MCSection *getDwarfTypesDWOSection() const { - return DwarfTypesDWOSection; - } - const MCSection *getDwarfAbbrevDWOSection() const { - return DwarfAbbrevDWOSection; - } - const MCSection *getDwarfStrDWOSection() const { - return DwarfStrDWOSection; - } - const MCSection *getDwarfLineDWOSection() const { - return DwarfLineDWOSection; - } - const MCSection *getDwarfLocDWOSection() const { - return DwarfLocDWOSection; - } - const MCSection *getDwarfStrOffDWOSection() const { - return DwarfStrOffDWOSection; - } - const MCSection *getDwarfAddrSection() const { - return DwarfAddrSection; - } - - const MCSection *getCOFFDebugSymbolsSection() const { + MCSection *getDwarfInfoDWOSection() const { return DwarfInfoDWOSection; } + MCSection *getDwarfTypesSection(uint64_t Hash) const; + MCSection *getDwarfTypesDWOSection() const { return DwarfTypesDWOSection; } + MCSection *getDwarfAbbrevDWOSection() const { return DwarfAbbrevDWOSection; } + MCSection *getDwarfStrDWOSection() const { return DwarfStrDWOSection; } + MCSection *getDwarfLineDWOSection() const { return DwarfLineDWOSection; } + MCSection *getDwarfLocDWOSection() const { return DwarfLocDWOSection; } + MCSection *getDwarfStrOffDWOSection() const { return DwarfStrOffDWOSection; } + MCSection *getDwarfAddrSection() const { return DwarfAddrSection; } + + MCSection *getCOFFDebugSymbolsSection() const { return COFFDebugSymbolsSection; } - const MCSection *getTLSExtraDataSection() const { - return TLSExtraDataSection; - } + MCSection *getTLSExtraDataSection() const { return TLSExtraDataSection; } const MCSection *getTLSDataSection() const { return TLSDataSection; } - const MCSection *getTLSBSSSection() const { return TLSBSSSection; } + MCSection *getTLSBSSSection() const { return TLSBSSSection; } - const MCSection *getStackMapSection() const { return StackMapSection; } + MCSection *getStackMapSection() const { return StackMapSection; } + MCSection *getFaultMapSection() const { return FaultMapSection; } - /// ELF specific sections. - /// - const MCSection *getDataRelSection() const { return DataRelSection; } + // ELF specific sections. + MCSection *getDataRelSection() const { return DataRelSection; } const MCSection *getDataRelLocalSection() const { return DataRelLocalSection; } - const MCSection *getDataRelROSection() const { return DataRelROSection; } - const MCSection *getDataRelROLocalSection() const { - return DataRelROLocalSection; - } + MCSection *getDataRelROSection() const { return DataRelROSection; } + MCSection *getDataRelROLocalSection() const { return DataRelROLocalSection; } const MCSection *getMergeableConst4Section() const { return MergeableConst4Section; } @@ -312,22 +288,21 @@ class MCObjectFileInfo { return MergeableConst16Section; } - /// MachO specific sections. - /// + // MachO specific sections. const MCSection *getTLSTLVSection() const { return TLSTLVSection; } const MCSection *getTLSThreadInitSection() const { return TLSThreadInitSection; } const MCSection *getCStringSection() const { return CStringSection; } const MCSection *getUStringSection() const { return UStringSection; } - const MCSection *getTextCoalSection() const { return TextCoalSection; } + MCSection *getTextCoalSection() const { return TextCoalSection; } const MCSection *getConstTextCoalSection() const { return ConstTextCoalSection; } const MCSection *getConstDataSection() const { return ConstDataSection; } const MCSection *getDataCoalSection() const { return DataCoalSection; } const MCSection *getDataCommonSection() const { return DataCommonSection; } - const MCSection *getDataBSSSection() const { return DataBSSSection; } + MCSection *getDataBSSSection() const { return DataBSSSection; } const MCSection *getFourByteConstantSection() const { return FourByteConstantSection; } @@ -337,33 +312,29 @@ class MCObjectFileInfo { const MCSection *getSixteenByteConstantSection() const { return SixteenByteConstantSection; } - const MCSection *getLazySymbolPointerSection() const { + MCSection *getLazySymbolPointerSection() const { return LazySymbolPointerSection; } - const MCSection *getNonLazySymbolPointerSection() const { + MCSection *getNonLazySymbolPointerSection() const { return NonLazySymbolPointerSection; } - /// COFF specific sections. - /// - const MCSection *getDrectveSection() const { return DrectveSection; } - const MCSection *getPDataSection() const { return PDataSection; } - const MCSection *getXDataSection() const { return XDataSection; } + // COFF specific sections. + MCSection *getDrectveSection() const { return DrectveSection; } + MCSection *getPDataSection() const { return PDataSection; } + MCSection *getXDataSection() const { return XDataSection; } + MCSection *getSXDataSection() const { return SXDataSection; } - const MCSection *getEHFrameSection() { + MCSection *getEHFrameSection() { if (!EHFrameSection) InitEHFrameSection(); return EHFrameSection; } 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; @@ -372,12 +343,11 @@ class MCObjectFileInfo { 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: diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index 6666a503ea8..ce1fc80f2cf 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -12,12 +12,12 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" namespace llvm { class MCAssembler; class MCCodeEmitter; -class MCSectionData; class MCSubtargetInfo; class MCExpr; class MCFragment; @@ -35,11 +35,10 @@ class raw_pwrite_stream; /// implementation. class MCObjectStreamer : public MCStreamer { MCAssembler *Assembler; - MCSectionData *CurSectionData; - MCSectionData::iterator CurInsertionPoint; + MCSection::iterator CurInsertionPoint; bool EmitEHFrame; bool EmitDebugFrame; - SmallVector PendingLabels; + SmallVector PendingLabels; virtual void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo&) = 0; void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; @@ -57,30 +56,24 @@ class MCObjectStreamer : public MCStreamer { /// Object streamers require the integrated assembler. bool isIntegratedAssemblerRequired() const override { return true; } - MCSymbolData &getOrCreateSymbolData(const MCSymbol *Symbol) { - return getAssembler().getOrCreateSymbolData(*Symbol); - } void EmitFrames(MCAsmBackend *MAB); void EmitCFISections(bool EH, bool Debug) override; protected: - MCSectionData *getCurrentSectionData() const { - return CurSectionData; - } - MCFragment *getCurrentFragment() const; void insert(MCFragment *F) { flushPendingLabels(F); - CurSectionData->getFragmentList().insert(CurInsertionPoint, F); - F->setParent(CurSectionData); + MCSection *CurSection = getCurrentSectionOnly(); + CurSection->getFragmentList().insert(CurInsertionPoint, F); + F->setParent(CurSection); } /// Get a data fragment to write into, creating a new one if the current /// fragment is not a data fragment. MCDataFragment *getOrCreateDataFragment(); - bool changeSectionImpl(const MCSection *Section, const MCExpr *Subsection); + bool changeSectionImpl(MCSection *Section, const MCExpr *Subsection); /// If any labels have been emitted but not assigned fragments, ensure that /// they get assigned, either to F if possible or to a new data fragment. @@ -93,7 +86,7 @@ class MCObjectStreamer : public MCStreamer { MCAssembler &getAssembler() { return *Assembler; } - /// @name MCStreamer Interface + /// \name MCStreamer Interface /// @{ void EmitLabel(MCSymbol *Symbol) override; @@ -103,8 +96,7 @@ class MCObjectStreamer : public MCStreamer { void EmitULEB128Value(const MCExpr *Value) override; void EmitSLEB128Value(const MCExpr *Value) override; void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; - void ChangeSection(const MCSection *Section, - const MCExpr *Subsection) override; + void ChangeSection(MCSection *Section, const MCExpr *Subsection) override; void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo& STI) override; /// \brief Emit an instruction to a special fragment, because this instruction @@ -136,9 +128,17 @@ class MCObjectStreamer : public MCStreamer { void EmitZeros(uint64_t NumBytes) override; void FinishImpl() override; - bool mayHaveInstructions() const override { - return getCurrentSectionData()->hasInstructions(); - } + /// Emit the absolute difference between two symbols if possible. + /// + /// Emit the absolute difference between \c Hi and \c Lo, as long as we can + /// compute it. Currently, that requires that both symbols are in the same + /// data fragment. Otherwise, do nothing and return \c false. + /// + /// \pre Offset of \c Hi is greater than the offset \c Lo. + void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, + unsigned Size) override; + + bool mayHaveInstructions(MCSection &Sec) const override; }; } // end namespace llvm diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h index f8e2821c4dc..2211673efc3 100644 --- a/include/llvm/MC/MCObjectWriter.h +++ b/include/llvm/MC/MCObjectWriter.h @@ -22,18 +22,17 @@ class MCAsmLayout; class MCAssembler; class MCFixup; class MCFragment; -class MCSymbolData; 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. @@ -54,119 +53,115 @@ class MCObjectWriter { virtual ~MCObjectWriter(); /// lifetime management - virtual void reset() { } + virtual void reset() {} bool isLittleEndian() const { return IsLittleEndian; } raw_ostream &getStream() { return OS; } - /// @name High-Level API + /// \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, - const MCSymbolData &DataA, - const MCSymbolData *DataB, + 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 MCSymbolData &SD) const; + 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 + /// \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(OS).write(Value); } - void WriteLE32(uint32_t Value) { + void writeLE32(uint32_t Value) { support::endian::Writer(OS).write(Value); } - void WriteLE64(uint64_t Value) { + void writeLE64(uint64_t Value) { support::endian::Writer(OS).write(Value); } - void WriteBE16(uint16_t Value) { + void writeBE16(uint16_t Value) { support::endian::Writer(OS).write(Value); } - void WriteBE32(uint32_t Value) { + void writeBE32(uint32_t Value) { support::endian::Writer(OS).write(Value); } - void WriteBE64(uint64_t Value) { + void writeBE64(uint64_t Value) { support::endian::Writer(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); @@ -174,22 +169,23 @@ class MCObjectWriter { OS << StringRef(Zeros, N % 16); } - void WriteBytes(const SmallVectorImpl &ByteVec, unsigned ZeroFillSize = 0) { - WriteBytes(StringRef(ByteVec.data(), ByteVec.size()), ZeroFillSize); + void writeBytes(const SmallVectorImpl &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 - 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 diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index 83ffbb5044d..ac8706d9950 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -45,7 +45,7 @@ class InlineAsmIdentifierInfo { } }; -/// Generic Sema callback for assembly parser. +/// \brief Generic Sema callback for assembly parser. class MCAsmParserSemaCallback { public: virtual ~MCAsmParserSemaCallback(); @@ -59,8 +59,8 @@ class MCAsmParserSemaCallback { unsigned &Offset) = 0; }; -/// Generic assembler parser interface, for use by target specific assembly -/// parsers. +/// \brief Generic assembler parser interface, for use by target specific +/// assembly parsers. class MCAsmParser { public: typedef bool (*DirectiveHandler)(MCAsmParserExtension*, StringRef, SMLoc); @@ -84,6 +84,8 @@ class MCAsmParser { virtual void addDirectiveHandler(StringRef Directive, ExtensionDirectiveHandler Handler) = 0; + virtual void addAliasForDirective(StringRef Directive, StringRef Alias) = 0; + virtual SourceMgr &getSourceManager() = 0; virtual MCAsmLexer &getLexer() = 0; @@ -93,7 +95,7 @@ class MCAsmParser { virtual MCContext &getContext() = 0; - /// Return the output streamer for the assembler. + /// \brief Return the output streamer for the assembler. virtual MCStreamer &getStreamer() = 0; MCTargetAsmParser &getTargetParser() const { return *TargetParser; } @@ -105,13 +107,13 @@ class MCAsmParser { bool getShowParsedOperands() const { return ShowParsedOperands; } void setShowParsedOperands(bool Value) { ShowParsedOperands = Value; } - /// Run the parser on the input source buffer. + /// \brief Run the parser on the input source buffer. virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false) = 0; virtual void setParsingInlineAsm(bool V) = 0; virtual bool isParsingInlineAsm() = 0; - /// Parse ms-style inline assembly. + /// \brief Parse MS-style inline assembly. virtual bool parseMSInlineAsm( void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, SmallVectorImpl> &OpDecls, @@ -119,35 +121,35 @@ class MCAsmParser { SmallVectorImpl &Clobbers, const MCInstrInfo *MII, const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) = 0; - /// Emit a note at the location \p L, with the message \p Msg. + /// \brief Emit a note at the location \p L, with the message \p Msg. virtual void Note(SMLoc L, const Twine &Msg, ArrayRef Ranges = None) = 0; - /// Emit a warning at the location \p L, with the message \p Msg. + /// \brief Emit a warning at the location \p L, with the message \p Msg. /// /// \return The return value is true, if warnings are fatal. virtual bool Warning(SMLoc L, const Twine &Msg, ArrayRef Ranges = None) = 0; - /// Emit an error at the location \p L, with the message \p Msg. + /// \brief Emit an error at the location \p L, with the message \p Msg. /// /// \return The return value is always true, as an idiomatic convenience to /// clients. virtual bool Error(SMLoc L, const Twine &Msg, ArrayRef Ranges = None) = 0; - /// Get the next AsmToken in the stream, possibly handling file inclusion - /// first. + /// \brief Get the next AsmToken in the stream, possibly handling file + /// inclusion first. virtual const AsmToken &Lex() = 0; - /// Get the current AsmToken from the stream. + /// \brief Get the current AsmToken from the stream. const AsmToken &getTok() const; /// \brief Report an error at the current lexer location. bool TokError(const Twine &Msg, ArrayRef Ranges = None); - /// Parse an identifier or string (as a quoted identifier) and set \p Res to - /// the identifier contents. + /// \brief Parse an identifier or string (as a quoted identifier) and set \p + /// Res to the identifier contents. virtual bool parseIdentifier(StringRef &Res) = 0; /// \brief Parse up to the end of statement and return the contents from the @@ -155,51 +157,62 @@ class MCAsmParser { /// will be either the EndOfStatement or EOF. virtual StringRef parseStringToEndOfStatement() = 0; - /// Parse the current token as a string which may include escaped characters - /// and return the string contents. + /// \brief Parse the current token as a string which may include escaped + /// characters and return the string contents. virtual bool parseEscapedString(std::string &Data) = 0; - /// Skip to the end of the current statement, for error recovery. + /// \brief Skip to the end of the current statement, for error recovery. virtual void eatToEndOfStatement() = 0; - /// Parse an arbitrary expression. + /// \brief Parse an arbitrary expression. /// - /// @param Res - The value of the expression. The result is undefined + /// \param Res - The value of the expression. The result is undefined /// on error. - /// @result - False on success. + /// \return - False on success. virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; bool parseExpression(const MCExpr *&Res); - /// Parse a primary expression. + /// \brief Parse a primary expression. /// - /// @param Res - The value of the expression. The result is undefined + /// \param Res - The value of the expression. The result is undefined /// on error. - /// @result - False on success. + /// \return - False on success. virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) = 0; - /// Parse an arbitrary expression, assuming that an initial '(' has already - /// been consumed. + /// \brief Parse an arbitrary expression, assuming that an initial '(' has + /// already been consumed. /// - /// @param Res - The value of the expression. The result is undefined + /// \param Res - The value of the expression. The result is undefined /// on error. - /// @result - False on success. + /// \return - False on success. virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; - /// Parse an expression which must evaluate to an absolute value. + /// \brief Parse an expression which must evaluate to an absolute value. /// - /// @param Res - The value of the absolute expression. The result is undefined + /// \param Res - The value of the absolute expression. The result is undefined /// on error. - /// @result - False on success. + /// \return - False on success. virtual bool parseAbsoluteExpression(int64_t &Res) = 0; - /// Ensure that we have a valid section set in the streamer. Otherwise, report - /// an error and switch to .text. + /// \brief Ensure that we have a valid section set in the streamer. Otherwise, + /// report an error and switch to .text. virtual void checkForValidSection() = 0; + + /// \brief Parse an arbitrary expression of a specified parenthesis depth, + /// assuming that the initial '(' characters have already been consumed. + /// + /// \param ParenDepth - Specifies how many trailing expressions outside the + /// current parentheses we have to parse. + /// \param Res - The value of the expression. The result is undefined + /// on error. + /// \return - False on success. + virtual bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res, + SMLoc &EndLoc) = 0; }; /// \brief Create an MCAsmParser instance. -MCAsmParser *createMCAsmParser(SourceMgr &, MCContext &, - MCStreamer &, const MCAsmInfo &); +MCAsmParser *createMCAsmParser(SourceMgr &, MCContext &, MCStreamer &, + const MCAsmInfo &); } // End llvm namespace diff --git a/include/llvm/MC/MCParser/MCAsmParserExtension.h b/include/llvm/MC/MCParser/MCAsmParserExtension.h index 53515d78d3c..077fd21e073 100644 --- a/include/llvm/MC/MCParser/MCAsmParserExtension.h +++ b/include/llvm/MC/MCParser/MCAsmParserExtension.h @@ -48,7 +48,7 @@ class MCAsmParserExtension { /// parsing routines. virtual void Initialize(MCAsmParser &Parser); - /// @name MCAsmParser Proxy Interfaces + /// \name MCAsmParser Proxy Interfaces /// @{ MCContext &getContext() { return getParser().getContext(); } diff --git a/include/llvm/MC/MCParser/MCAsmParserUtils.h b/include/llvm/MC/MCParser/MCAsmParserUtils.h new file mode 100644 index 00000000000..9834fe96307 --- /dev/null +++ b/include/llvm/MC/MCParser/MCAsmParserUtils.h @@ -0,0 +1,33 @@ +//===------ llvm/MC/MCAsmParserUtils.h - Asm Parser Utilities ---*- 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_MCPARSER_MCASMPARSERUTILS_H +#define LLVM_MC_MCPARSER_MCASMPARSERUTILS_H + +namespace llvm { + +class MCAsmParser; +class MCExpr; +class MCSymbol; +class StringRef; + +namespace MCParserUtils { + +/// Parse a value expression and return whether it can be assigned to a symbol +/// with the given name. +/// +/// On success, returns false and sets the Symbol and Value output parameters. +bool parseAssignmentExpression(StringRef Name, bool allow_redef, + MCAsmParser &Parser, MCSymbol *&Symbol, + const MCExpr *&Value); + +} // namespace MCParserUtils +} // namespace llvm + +#endif diff --git a/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/include/llvm/MC/MCParser/MCParsedAsmOperand.h index e8740aa10aa..a25108a0eff 100644 --- a/include/llvm/MC/MCParser/MCParsedAsmOperand.h +++ b/include/llvm/MC/MCParser/MCParsedAsmOperand.h @@ -10,8 +10,11 @@ #ifndef LLVM_MC_MCPARSER_MCPARSEDASMOPERAND_H #define LLVM_MC_MCPARSER_MCPARSEDASMOPERAND_H +#include +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/SMLoc.h" + namespace llvm { -class SMLoc; class raw_ostream; /// MCParsedAsmOperand - This abstract class represents a source-level assembly diff --git a/include/llvm/MC/MCSchedule.h b/include/llvm/MC/MCSchedule.h index 1adfedd2638..a8b20570103 100644 --- a/include/llvm/MC/MCSchedule.h +++ b/include/llvm/MC/MCSchedule.h @@ -206,6 +206,9 @@ struct MCSchedModel { /// scheduling class (itinerary class or SchedRW list). bool isComplete() const { return CompleteModel; } + /// Return true if machine supports out of order execution. + bool isOutOfOrder() const { return MicroOpBufferSize > 1; } + unsigned getNumProcResourceKinds() const { return NumProcResourceKinds; } @@ -224,25 +227,9 @@ struct MCSchedModel { return &SchedClassTable[SchedClassIdx]; } - // /\brief Returns a default initialized model. Used for unknown processors. - static MCSchedModel GetDefaultSchedModel() { - MCSchedModel Ret = { DefaultIssueWidth, - DefaultMicroOpBufferSize, - DefaultLoopMicroOpBufferSize, - DefaultLoadLatency, - DefaultHighLatency, - DefaultMispredictPenalty, - false, - true, - 0, - nullptr, - nullptr, - 0, - 0, - nullptr - }; - return Ret; - } + /// Returns the default initialized model. + static const MCSchedModel &GetDefaultSchedModel() { return Default; } + static const MCSchedModel Default; }; } // End llvm namespace diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h index ab8968ef2ba..2d0d4dfc591 100644 --- a/include/llvm/MC/MCSection.h +++ b/include/llvm/MC/MCSection.h @@ -14,33 +14,92 @@ #ifndef LLVM_MC_MCSECTION_H #define LLVM_MC_MCSECTION_H +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/ilist.h" +#include "llvm/ADT/ilist_node.h" #include "llvm/MC/SectionKind.h" #include "llvm/Support/Compiler.h" namespace llvm { +class MCAssembler; class MCAsmInfo; class MCContext; class MCExpr; +class MCFragment; +class MCSection; class MCSymbol; class raw_ostream; +template<> +struct ilist_node_traits { + MCFragment *createNode(const MCFragment &V); + static void deleteNode(MCFragment *V); + + void addNodeToList(MCFragment *) {} + void removeNodeFromList(MCFragment *) {} + void transferNodesFromList(ilist_node_traits & /*SrcTraits*/, + ilist_iterator /*first*/, + ilist_iterator /*last*/) {} +}; + /// Instances of this class represent a uniqued identifier for a section in the /// current translation unit. The MCContext class uniques and creates these. class MCSection { public: enum SectionVariant { SV_COFF = 0, SV_ELF, SV_MachO }; + /// \brief Express the state of bundle locked groups while emitting code. + enum BundleLockStateType { + NotBundleLocked, + BundleLocked, + BundleLockedAlignToEnd + }; + + typedef iplist FragmentListType; + + typedef FragmentListType::const_iterator const_iterator; + typedef FragmentListType::iterator iterator; + + typedef FragmentListType::const_reverse_iterator const_reverse_iterator; + typedef FragmentListType::reverse_iterator reverse_iterator; + private: MCSection(const MCSection &) = delete; void operator=(const MCSection &) = delete; MCSymbol *Begin; - mutable MCSymbol *End; + MCSymbol *End = nullptr; + /// The alignment requirement of this section. + unsigned Alignment = 1; + /// The section index in the assemblers section list. + unsigned Ordinal = 0; + /// The index of this section in the layout order. + unsigned LayoutOrder; + + /// \brief Keeping track of bundle-locked state. + BundleLockStateType BundleLockState = NotBundleLocked; + + /// \brief Current nesting depth of bundle_lock directives. + unsigned BundleLockNestingDepth = 0; + + /// \brief We've seen a bundle_lock directive but not its first instruction + /// yet. + unsigned BundleGroupBeforeFirstInst : 1; + + /// Whether this section has had instructions emitted into it. + unsigned HasInstructions : 1; + + unsigned IsRegistered : 1; + + FragmentListType Fragments; + + /// Mapping from subsection number to insertion point for subsection numbers + /// below that number. + SmallVector, 1> SubsectionFragmentMap; protected: - MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin) - : Begin(Begin), End(nullptr), Variant(V), Kind(K) {} + MCSection(SectionVariant V, SectionKind K, MCSymbol *Begin); SectionVariant Variant; SectionKind Kind; @@ -51,10 +110,72 @@ class MCSection { SectionVariant getVariant() const { return Variant; } - MCSymbol *getBeginSymbol() const { return Begin; } - MCSymbol *getEndSymbol(MCContext &Ctx) const; + MCSymbol *getBeginSymbol() { return Begin; } + const MCSymbol *getBeginSymbol() const { + return const_cast(this)->getBeginSymbol(); + } + void setBeginSymbol(MCSymbol *Sym) { + assert(!Begin); + Begin = Sym; + } + MCSymbol *getEndSymbol(MCContext &Ctx); bool hasEnded() const; + unsigned getAlignment() const { return Alignment; } + void setAlignment(unsigned Value) { Alignment = Value; } + + unsigned getOrdinal() const { return Ordinal; } + void setOrdinal(unsigned Value) { Ordinal = Value; } + + unsigned getLayoutOrder() const { return LayoutOrder; } + void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } + + BundleLockStateType getBundleLockState() const { return BundleLockState; } + void setBundleLockState(BundleLockStateType NewState); + bool isBundleLocked() const { return BundleLockState != NotBundleLocked; } + + bool isBundleGroupBeforeFirstInst() const { + return BundleGroupBeforeFirstInst; + } + void setBundleGroupBeforeFirstInst(bool IsFirst) { + BundleGroupBeforeFirstInst = IsFirst; + } + + bool hasInstructions() const { return HasInstructions; } + void setHasInstructions(bool Value) { HasInstructions = Value; } + + bool isRegistered() const { return IsRegistered; } + void setIsRegistered(bool Value) { IsRegistered = Value; } + + MCSection::FragmentListType &getFragmentList() { return Fragments; } + const MCSection::FragmentListType &getFragmentList() const { + return const_cast(this)->getFragmentList(); + } + + MCSection::iterator begin(); + MCSection::const_iterator begin() const { + return const_cast(this)->begin(); + } + + MCSection::iterator end(); + MCSection::const_iterator end() const { + return const_cast(this)->end(); + } + + MCSection::reverse_iterator rbegin(); + MCSection::const_reverse_iterator rbegin() const { + return const_cast(this)->rbegin(); + } + + MCSection::reverse_iterator rend(); + MCSection::const_reverse_iterator rend() const { + return const_cast(this)->rend(); + } + + MCSection::iterator getSubsectionInsertionPoint(unsigned Subsection); + + void dump(); + virtual void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS, const MCExpr *Subsection) const = 0; diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h index 9efe1022f29..f6730371fe1 100644 --- a/include/llvm/MC/MCSectionELF.h +++ b/include/llvm/MC/MCSectionELF.h @@ -16,7 +16,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCSymbolELF.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" #include "llvm/Support/raw_ostream.h" @@ -46,7 +46,7 @@ class MCSectionELF : public MCSection { /// section does not contain fixed-sized entries 'EntrySize' will be 0. unsigned EntrySize; - const MCSymbol *Group; + const MCSymbolELF *Group; /// Depending on the type of the section this is sh_link or sh_info. const MCSectionELF *Associated; @@ -54,11 +54,14 @@ class MCSectionELF : public MCSection { private: friend class MCContext; MCSectionELF(StringRef Section, unsigned type, unsigned flags, SectionKind K, - unsigned entrySize, const MCSymbol *group, unsigned UniqueID, + unsigned entrySize, const MCSymbolELF *group, unsigned UniqueID, 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; } @@ -73,7 +76,7 @@ class MCSectionELF : public MCSection { unsigned getType() const { return Type; } unsigned getFlags() const { return Flags; } unsigned getEntrySize() const { return EntrySize; } - const MCSymbol *getGroup() const { return Group; } + const MCSymbolELF *getGroup() const { return Group; } void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS, const MCExpr *Subsection) const override; diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 12cee2a6bfb..63e30bc3d54 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -16,13 +16,12 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCLinkerOptimizationHint.h" #include "llvm/MC/MCWinEH.h" -#include "llvm/MC/MCNaClExpander.h" // @LOCALMOD #include "llvm/Support/DataTypes.h" +#include "llvm/Support/SMLoc.h" #include namespace llvm { @@ -35,6 +34,7 @@ class MCInstPrinter; class MCSection; class MCStreamer; class MCSymbol; +class MCSymbolELF; class MCSymbolRefExpr; class MCSubtargetInfo; class StringRef; @@ -43,7 +43,7 @@ class raw_ostream; class formatted_raw_ostream; class AssemblerConstantPools; -typedef std::pair MCSectionSubPair; +typedef std::pair MCSectionSubPair; /// Target specific streamer interface. This is used so that targets can /// implement support for target specific assembly directives. @@ -78,37 +78,17 @@ class MCTargetStreamer { MCTargetStreamer(MCStreamer &S); virtual ~MCTargetStreamer(); - const MCStreamer &getStreamer() { return Streamer; } + MCStreamer &getStreamer() { return Streamer; } // Allow a target to add behavior to the EmitLabel of MCStreamer. virtual void emitLabel(MCSymbol *Symbol); // Allow a target to add behavior to the emitAssignment of MCStreamer. virtual void emitAssignment(MCSymbol *Symbol, const MCExpr *Value); - virtual void finish(); -}; - -class AArch64TargetStreamer : public MCTargetStreamer { -public: - AArch64TargetStreamer(MCStreamer &S); - ~AArch64TargetStreamer() override; - - void finish() override; - - /// Callback used to implement the ldr= pseudo. - /// Add a new entry to the constant pool for the current section and return an - /// MCExpr that can be used to refer to the constant pool location. - const MCExpr *addConstantPoolEntry(const MCExpr *, unsigned Size); - - /// Callback used to implemnt the .ltorg directive. - /// Emit contents of constant pool for the current section. - void emitCurrentConstantPool(); - - /// Callback used to implement the .inst directive. - virtual void emitInst(uint32_t Inst); + virtual void prettyPrintAsm(MCInstPrinter &InstPrinter, raw_ostream &OS, + const MCInst &Inst, const MCSubtargetInfo &STI); -private: - std::unique_ptr ConstantPools; + virtual void finish(); }; // FIXME: declared here because it is used from @@ -164,11 +144,12 @@ class ARMTargetStreamer : public MCTargetStreamer { std::unique_ptr ConstantPools; }; -/// MCStreamer - Streaming machine code generation interface. This interface -/// is intended to provide a programatic interface that is very similar to the -/// level that an assembler .s file provides. It has callbacks to emit bytes, -/// handle directives, etc. The implementation of this interface retains -/// state to know what the current section is etc. +/// \brief Streaming machine code generation interface. +/// +/// This interface is intended to provide a programatic interface that is very +/// similar to the level that an assembler .s file provides. It has callbacks +/// to emit bytes, handle directives, etc. The implementation of this interface +/// retains state to know what the current section is etc. /// /// There are multiple implementations of this interface: one for writing out /// a .s file, and implementations that write out .o files of various formats. @@ -190,12 +171,12 @@ class MCStreamer { WinEH::FrameInfo *CurrentWinFrameInfo; void EnsureValidWinFrameInfo(); - // SymbolOrdering - Tracks an index to represent the order - // a symbol was emitted in. Zero means we did not emit that symbol. + /// \brief Tracks an index to represent the order a symbol was emitted in. + /// Zero means we did not emit that symbol. DenseMap SymbolOrdering; - /// SectionStack - This is stack of current and previous section - /// values saved by PushSection. + /// \brief This is stack of current and previous section values saved by + /// PushSection. SmallVector, 4> SectionStack; protected: @@ -211,7 +192,6 @@ class MCStreamer { virtual void EmitWindowsUnwindTables(); virtual void EmitRawTextImpl(StringRef String); - std::unique_ptr NaClExpander; //@LOCALMOD public: virtual ~MCStreamer(); @@ -223,11 +203,6 @@ class MCStreamer { TargetStreamer.reset(TS); } - // @LOCALMOD-START - void setNaClExpander(MCNaClExpander *Exp) { NaClExpander.reset(Exp); } - - MCNaClExpander *getNaClExpander() { return NaClExpander.get(); } - // @LOCALMOD-END /// State management /// virtual void reset(); @@ -250,22 +225,24 @@ class MCStreamer { void generateCompactUnwindEncodings(MCAsmBackend *MAB); - /// @name Assembly File Formatting. + /// \name Assembly File Formatting. /// @{ - /// isVerboseAsm - Return true if this streamer supports verbose assembly - /// and if it is enabled. + /// \brief Return true if this streamer supports verbose assembly and if it is + /// enabled. virtual bool isVerboseAsm() const { return false; } - /// hasRawTextSupport - Return true if this asm streamer supports emitting - /// unformatted text to the .s file with EmitRawText. + /// \brief Return true if this asm streamer supports emitting unformatted text + /// to the .s file with EmitRawText. virtual bool hasRawTextSupport() const { return false; } - /// Is the integrated assembler required for this streamer to function + /// \brief Is the integrated assembler required for this streamer to function /// correctly? virtual bool isIntegratedAssemblerRequired() const { return false; } - /// AddComment - Add a comment that can be emitted to the generated .s + /// \brief Add a textual command. + /// + /// Typically for comments that can be emitted to the generated .s /// file if applicable as a QoI issue to make the output of the compiler /// more readable. This only affects the MCAsmStreamer, and only when /// verbose assembly output is enabled. @@ -274,14 +251,14 @@ class MCStreamer { /// prefix as appropriate. The added comment should not end with a \n. virtual void AddComment(const Twine &T) {} - /// GetCommentOS - Return a raw_ostream that comments can be written to. - /// Unlike AddComment, you are required to terminate comments with \n if you - /// use this method. + /// \brief Return a raw_ostream that comments can be written to. Unlike + /// AddComment, you are required to terminate comments with \n if you use this + /// method. virtual raw_ostream &GetCommentOS(); - /// Print T and prefix it with the comment string (normally #) and optionally - /// a tab. This prints the comment immediately, not at the end of the - /// current line. It is basically a safe version of EmitRawText: since it + /// \brief Print T and prefix it with the comment string (normally #) and + /// optionally a tab. This prints the comment immediately, not at the end of + /// the current line. It is basically a safe version of EmitRawText: since it /// only prints comments, the object streamer ignores it instead of asserting. virtual void emitRawComment(const Twine &T, bool TabPrefix = true); @@ -290,56 +267,58 @@ class MCStreamer { /// @} - /// @name Symbol & Section Management + /// \name Symbol & Section Management /// @{ - /// getCurrentSection - Return the current section that the streamer is - /// emitting code to. + /// \brief Return the current section that the streamer is emitting code to. MCSectionSubPair getCurrentSection() const { if (!SectionStack.empty()) return SectionStack.back().first; return MCSectionSubPair(); } + MCSection *getCurrentSectionOnly() const { return getCurrentSection().first; } - /// getPreviousSection - Return the previous section that the streamer is - /// emitting code to. + /// \brief Return the previous section that the streamer is emitting code to. MCSectionSubPair getPreviousSection() const { if (!SectionStack.empty()) return SectionStack.back().second; return MCSectionSubPair(); } - /// GetSymbolOrder - Returns an index to represent the order - /// a symbol was emitted in. (zero if we did not emit that symbol) + /// \brief Returns an index to represent the order a symbol was emitted in. + /// (zero if we did not emit that symbol) unsigned GetSymbolOrder(const MCSymbol *Sym) const { return SymbolOrdering.lookup(Sym); } - /// ChangeSection - Update streamer for a new active section. + /// \brief Update streamer for a new active section. /// /// This is called by PopSection and SwitchSection, if the current /// section changes. - virtual void ChangeSection(const MCSection *, const MCExpr *); + virtual void ChangeSection(MCSection *, const MCExpr *); - /// pushSection - Save the current and previous section on the - /// section stack. + /// \brief Save the current and previous section on the section stack. void PushSection() { SectionStack.push_back( std::make_pair(getCurrentSection(), getPreviousSection())); } - /// popSection - Restore the current and previous section from - /// the section stack. Calls ChangeSection as needed. + /// \brief Restore the current and previous section from the section stack. + /// Calls ChangeSection as needed. /// /// Returns false if the stack was empty. bool PopSection() { if (SectionStack.size() <= 1) return false; - MCSectionSubPair oldSection = SectionStack.pop_back_val().first; - MCSectionSubPair curSection = SectionStack.back().first; - - if (oldSection != curSection) - ChangeSection(curSection.first, curSection.second); + auto I = SectionStack.end(); + --I; + MCSectionSubPair OldSection = I->first; + --I; + MCSectionSubPair NewSection = I->first; + + if (OldSection != NewSection) + ChangeSection(NewSection.first, NewSection.second); + SectionStack.pop_back(); return true; } @@ -351,17 +330,17 @@ class MCStreamer { return true; } - /// Set the current section where code is being emitted to @p Section. This + /// Set the current section where code is being emitted to \p Section. This /// is required to update CurSection. /// /// This corresponds to assembler directives like .section, .text, etc. - virtual void SwitchSection(const MCSection *Section, + virtual void SwitchSection(MCSection *Section, const MCExpr *Subsection = nullptr); - /// SwitchSectionNoChange - Set the current section where code is being - /// emitted to @p Section. This is required to update CurSection. This - /// version does not call ChangeSection. - void SwitchSectionNoChange(const MCSection *Section, + /// \brief Set the current section where code is being emitted to \p Section. + /// This is required to update CurSection. This version does not call + /// ChangeSection. + void SwitchSectionNoChange(MCSection *Section, const MCExpr *Subsection = nullptr) { assert(Section && "Cannot switch to a null section!"); MCSectionSubPair curSection = SectionStack.back().first; @@ -370,23 +349,23 @@ class MCStreamer { SectionStack.back().first = MCSectionSubPair(Section, Subsection); } - /// Create the default sections and set the initial one. + /// \brief Create the default sections and set the initial one. virtual void InitSections(bool NoExecStack); - MCSymbol *endSection(const MCSection *Section); + MCSymbol *endSection(MCSection *Section); - /// AssignSection - Sets the symbol's section. + /// \brief Sets the symbol's section. /// /// Each emitted symbol will be tracked in the ordering table, /// so we can sort on them later. - void AssignSection(MCSymbol *Symbol, const MCSection *Section); + void AssignSection(MCSymbol *Symbol, MCSection *Section); - /// EmitLabel - Emit a label for @p Symbol into the current section. + /// \brief Emit a label for \p Symbol into the current section. /// /// This corresponds to an assembler statement such as: /// foo: /// - /// @param Symbol - The symbol to emit. A given symbol should only be + /// \param Symbol - The symbol to emit. A given symbol should only be /// emitted as a label once, and symbols emitted as a label should never be /// used in an assignment. // FIXME: These emission are non-const because we mutate the symbol to @@ -395,25 +374,25 @@ class MCStreamer { virtual void EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol); - /// EmitAssemblerFlag - Note in the output the specified @p Flag. + /// \brief Note in the output the specified \p Flag. virtual void EmitAssemblerFlag(MCAssemblerFlag Flag); - /// EmitLinkerOptions - Emit the given list @p Options of strings as linker + /// \brief Emit the given list \p Options of strings as linker /// options into the output. virtual void EmitLinkerOptions(ArrayRef Kind) {} - /// EmitDataRegion - Note in the output the specified region @p Kind. + /// \brief Note in the output the specified region \p Kind. virtual void EmitDataRegion(MCDataRegionType Kind) {} - /// EmitVersionMin - Specify the MachO minimum deployment target version. + /// \brief Specify the MachO minimum deployment target version. virtual void EmitVersionMin(MCVersionMinType, unsigned Major, unsigned Minor, unsigned Update) {} - /// EmitThumbFunc - Note in the output that the specified @p Func is - /// a Thumb mode function (ARM target only). + /// \brief Note in the output that the specified \p Func is a Thumb mode + /// function (ARM target only). virtual void EmitThumbFunc(MCSymbol *Func); - /// EmitAssignment - Emit an assignment of @p Value to @p Symbol. + /// \brief Emit an assignment of \p Value to \p Symbol. /// /// This corresponds to an assembler statement such as: /// symbol = value @@ -422,133 +401,133 @@ class MCStreamer { /// value in the current context. For the assembly streamer, this prints the /// binding into the .s file. /// - /// @param Symbol - The symbol being assigned to. - /// @param Value - The value for the symbol. + /// \param Symbol - The symbol being assigned to. + /// \param Value - The value for the symbol. virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); - /// EmitWeakReference - Emit an weak reference from @p Alias to @p Symbol. + /// \brief Emit an weak reference from \p Alias to \p Symbol. /// /// This corresponds to an assembler statement such as: /// .weakref alias, symbol /// - /// @param Alias - The alias that is being created. - /// @param Symbol - The symbol being aliased. + /// \param Alias - The alias that is being created. + /// \param Symbol - The symbol being aliased. virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); - /// EmitSymbolAttribute - Add the given @p Attribute to @p Symbol. + /// \brief Add the given \p Attribute to \p Symbol. virtual bool EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) = 0; - /// EmitSymbolDesc - Set the @p DescValue for the @p Symbol. + /// \brief Set the \p DescValue for the \p Symbol. /// - /// @param Symbol - The symbol to have its n_desc field set. - /// @param DescValue - The value to set into the n_desc field. + /// \param Symbol - The symbol to have its n_desc field set. + /// \param DescValue - The value to set into the n_desc field. virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue); - /// BeginCOFFSymbolDef - Start emitting COFF symbol definition + /// \brief Start emitting COFF symbol definition /// - /// @param Symbol - The symbol to have its External & Type fields set. + /// \param Symbol - The symbol to have its External & Type fields set. virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol); - /// EmitCOFFSymbolStorageClass - Emit the storage class of the symbol. + /// \brief Emit the storage class of the symbol. /// - /// @param StorageClass - The storage class the symbol should have. + /// \param StorageClass - The storage class the symbol should have. virtual void EmitCOFFSymbolStorageClass(int StorageClass); - /// EmitCOFFSymbolType - Emit the type of the symbol. + /// \brief Emit the type of the symbol. /// - /// @param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h) + /// \param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h) virtual void EmitCOFFSymbolType(int Type); - /// EndCOFFSymbolDef - Marks the end of the symbol definition. + /// \brief Marks the end of the symbol definition. virtual void EndCOFFSymbolDef(); - /// EmitCOFFSectionIndex - Emits a COFF section index. + virtual void EmitCOFFSafeSEH(MCSymbol const *Symbol); + + /// \brief Emits a COFF section index. /// - /// @param Symbol - Symbol the section number relocation should point to. + /// \param Symbol - Symbol the section number relocation should point to. virtual void EmitCOFFSectionIndex(MCSymbol const *Symbol); - /// EmitCOFFSecRel32 - Emits a COFF section relative relocation. + /// \brief Emits a COFF section relative relocation. /// - /// @param Symbol - Symbol the section relative relocation should point to. + /// \param Symbol - Symbol the section relative relocation should point to. virtual void EmitCOFFSecRel32(MCSymbol const *Symbol); - /// EmitELFSize - Emit an ELF .size directive. + /// \brief Emit an ELF .size directive. /// /// This corresponds to an assembler statement such as: /// .size symbol, expression - /// - virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); + virtual void emitELFSize(MCSymbolELF *Symbol, const MCExpr *Value); /// \brief Emit a Linker Optimization Hint (LOH) directive. /// \param Args - Arguments of the LOH. virtual void EmitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) {} - /// EmitCommonSymbol - Emit a common symbol. + /// \brief Emit a common symbol. /// - /// @param Symbol - The common symbol to emit. - /// @param Size - The size of the common symbol. - /// @param ByteAlignment - The alignment of the symbol if + /// \param Symbol - The common symbol to emit. + /// \param Size - The size of the common symbol. + /// \param ByteAlignment - The alignment of the symbol if /// non-zero. This must be a power of 2. virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) = 0; - /// EmitLocalCommonSymbol - Emit a local common (.lcomm) symbol. + /// \brief Emit a local common (.lcomm) symbol. /// - /// @param Symbol - The common symbol to emit. - /// @param Size - The size of the common symbol. - /// @param ByteAlignment - The alignment of the common symbol in bytes. + /// \param Symbol - The common symbol to emit. + /// \param Size - The size of the common symbol. + /// \param ByteAlignment - The alignment of the common symbol in bytes. virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment); - /// EmitZerofill - Emit the zerofill section and an optional symbol. + /// \brief Emit the zerofill section and an optional symbol. /// - /// @param Section - The zerofill section to create and or to put the symbol - /// @param Symbol - The zerofill symbol to emit, if non-NULL. - /// @param Size - The size of the zerofill symbol. - /// @param ByteAlignment - The alignment of the zerofill symbol if + /// \param Section - The zerofill section to create and or to put the symbol + /// \param Symbol - The zerofill symbol to emit, if non-NULL. + /// \param Size - The size of the zerofill symbol. + /// \param ByteAlignment - The alignment of the zerofill symbol if /// non-zero. This must be a power of 2 on some targets. - virtual void EmitZerofill(const MCSection *Section, - MCSymbol *Symbol = nullptr, uint64_t Size = 0, - unsigned ByteAlignment = 0) = 0; + virtual void EmitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, + uint64_t Size = 0, unsigned ByteAlignment = 0) = 0; - /// EmitTBSSSymbol - Emit a thread local bss (.tbss) symbol. + /// \brief Emit a thread local bss (.tbss) symbol. /// - /// @param Section - The thread local common section. - /// @param Symbol - The thread local common symbol to emit. - /// @param Size - The size of the symbol. - /// @param ByteAlignment - The alignment of the thread local common symbol + /// \param Section - The thread local common section. + /// \param Symbol - The thread local common symbol to emit. + /// \param Size - The size of the symbol. + /// \param ByteAlignment - The alignment of the thread local common symbol /// if non-zero. This must be a power of 2 on some targets. - virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + virtual void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment = 0); /// @} - /// @name Generating Data + /// \name Generating Data /// @{ - /// EmitBytes - Emit the bytes in \p Data into the output. + /// \brief Emit the bytes in \p Data into the output. /// /// This is used to implement assembler directives such as .byte, .ascii, /// etc. virtual void EmitBytes(StringRef Data); - /// EmitValue - Emit the expression @p Value into the output as a native - /// integer of the given @p Size bytes. + /// \brief Emit the expression \p Value into the output as a native + /// integer of the given \p Size bytes. /// /// This is used to implement assembler directives such as .word, .quad, /// etc. /// - /// @param Value - The value to emit. - /// @param Size - The size of the integer (in bytes) to emit. This must + /// \param Value - The value to emit. + /// \param Size - The size of the integer (in bytes) to emit. This must /// match a native machine width. - /// @param Loc - The location of the expression for error reporting. + /// \param Loc - The location of the expression for error reporting. virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, const SMLoc &Loc = SMLoc()); void EmitValue(const MCExpr *Value, unsigned Size, const SMLoc &Loc = SMLoc()); - /// EmitIntValue - Special case of EmitValue that avoids the client having + /// \brief Special case of EmitValue that avoids the client having /// to pass in a MCExpr for constant integers. virtual void EmitIntValue(uint64_t Value, unsigned Size); @@ -556,112 +535,116 @@ class MCStreamer { virtual void EmitSLEB128Value(const MCExpr *Value); - /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the - /// client having to pass in a MCExpr for constant integers. + /// \brief Special case of EmitULEB128Value that avoids the client having to + /// pass in a MCExpr for constant integers. void EmitULEB128IntValue(uint64_t Value, unsigned Padding = 0); - /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the - /// client having to pass in a MCExpr for constant integers. + /// \brief Special case of EmitSLEB128Value that avoids the client having to + /// pass in a MCExpr for constant integers. void EmitSLEB128IntValue(int64_t Value); - /// EmitSymbolValue - Special case of EmitValue that avoids the client - /// having to pass in a MCExpr for MCSymbols. + /// \brief Special case of EmitValue that avoids the client having to pass in + /// a MCExpr for MCSymbols. void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, bool IsSectionRelative = false); - /// EmitGPRel64Value - Emit the expression @p Value into the output as a - /// gprel64 (64-bit GP relative) value. + /// \brief Emit the expression \p Value into the output as a gprel64 (64-bit + /// GP relative) value. /// /// This is used to implement assembler directives such as .gpdword on /// targets that support them. virtual void EmitGPRel64Value(const MCExpr *Value); - /// EmitGPRel32Value - Emit the expression @p Value into the output as a - /// gprel32 (32-bit GP relative) value. + /// \brief Emit the expression \p Value into the output as a gprel32 (32-bit + /// GP relative) value. /// /// This is used to implement assembler directives such as .gprel32 on /// targets that support them. virtual void EmitGPRel32Value(const MCExpr *Value); - /// EmitFill - Emit NumBytes bytes worth of the value specified by - /// FillValue. This implements directives such as '.space'. + /// \brief Emit NumBytes bytes worth of the value specified by FillValue. + /// This implements directives such as '.space'. virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue); /// \brief Emit NumBytes worth of zeros. /// This function properly handles data in virtual sections. virtual void EmitZeros(uint64_t NumBytes); - /// EmitValueToAlignment - Emit some number of copies of @p Value until - /// the byte alignment @p ByteAlignment is reached. + /// \brief Emit some number of copies of \p Value until the byte alignment \p + /// ByteAlignment is reached. /// /// If the number of bytes need to emit for the alignment is not a multiple - /// of @p ValueSize, then the contents of the emitted fill bytes is + /// of \p ValueSize, then the contents of the emitted fill bytes is /// undefined. /// /// This used to implement the .align assembler directive. /// - /// @param ByteAlignment - The alignment to reach. This must be a power of + /// \param ByteAlignment - The alignment to reach. This must be a power of /// two on some targets. - /// @param Value - The value to use when filling bytes. - /// @param ValueSize - The size of the integer (in bytes) to emit for - /// @p Value. This must match a native machine width. - /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If + /// \param Value - The value to use when filling bytes. + /// \param ValueSize - The size of the integer (in bytes) to emit for + /// \p Value. This must match a native machine width. + /// \param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If /// the alignment cannot be reached in this many bytes, no bytes are /// emitted. virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, unsigned ValueSize = 1, unsigned MaxBytesToEmit = 0); - /// EmitCodeAlignment - Emit nops until the byte alignment @p ByteAlignment - /// is reached. + /// \brief Emit nops until the byte alignment \p ByteAlignment is reached. /// /// This used to align code where the alignment bytes may be executed. This /// can emit different bytes for different sizes to optimize execution. /// - /// @param ByteAlignment - The alignment to reach. This must be a power of + /// \param ByteAlignment - The alignment to reach. This must be a power of /// two on some targets. - /// @param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If + /// \param MaxBytesToEmit - The maximum numbers of bytes to emit, or 0. If /// the alignment cannot be reached in this many bytes, no bytes are /// emitted. virtual void EmitCodeAlignment(unsigned ByteAlignment, unsigned MaxBytesToEmit = 0); - /// EmitValueToOffset - Emit some number of copies of @p Value until the - /// byte offset @p Offset is reached. + /// \brief Emit some number of copies of \p Value until the byte offset \p + /// Offset is reached. /// /// This is used to implement assembler directives such as .org. /// - /// @param Offset - The offset to reach. This may be an expression, but the + /// \param Offset - The offset to reach. This may be an expression, but the /// expression must be associated with the current section. - /// @param Value - The value to use when filling bytes. - /// @return false on success, true if the offset was invalid. + /// \param Value - The value to use when filling bytes. + /// \return false on success, true if the offset was invalid. virtual bool EmitValueToOffset(const MCExpr *Offset, unsigned char Value = 0); /// @} - /// EmitFileDirective - Switch to a new logical file. This is used to - /// implement the '.file "foo.c"' assembler directive. + /// \brief Switch to a new logical file. This is used to implement the '.file + /// "foo.c"' assembler directive. virtual void EmitFileDirective(StringRef Filename); - /// Emit the "identifiers" directive. This implements the + /// \brief Emit the "identifiers" directive. This implements the /// '.ident "version foo"' assembler directive. virtual void EmitIdent(StringRef IdentString) {} - /// EmitDwarfFileDirective - Associate a filename with a specified logical - /// file number. This implements the DWARF2 '.file 4 "foo.c"' assembler - /// directive. + /// \brief Associate a filename with a specified logical file number. This + /// implements the DWARF2 '.file 4 "foo.c"' assembler directive. virtual unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, StringRef Filename, unsigned CUID = 0); - /// EmitDwarfLocDirective - This implements the DWARF2 - // '.loc fileno lineno ...' assembler directive. + /// \brief This implements the DWARF2 '.loc fileno lineno ...' assembler + /// directive. virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column, unsigned Flags, unsigned Isa, unsigned Discriminator, StringRef FileName); + /// Emit the absolute difference between two symbols. + /// + /// \pre Offset of \c Hi is greater than the offset \c Lo. + virtual void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, + unsigned Size); + virtual MCSymbol *getDwarfLineTableSymbol(unsigned CUID); virtual void EmitCFISections(bool EH, bool Debug); void EmitCFIStartProc(bool IsSimple); @@ -699,8 +682,9 @@ class MCStreamer { virtual void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except); virtual void EmitWinEHHandlerData(); - /// EmitInstruction - Emit the given @p Instruction into the current - /// section. + virtual void EmitSyntaxDirective(); + + /// \brief Emit the given \p Instruction into the current section. virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI); /// \brief Set the bundle alignment mode from now on in the section. @@ -717,20 +701,20 @@ class MCStreamer { /// \brief Ends a bundle-locked group. virtual void EmitBundleUnlock(); - /// EmitRawText - If this file is backed by a assembly streamer, this dumps - /// the specified string in the output .s file. This capability is - /// indicated by the hasRawTextSupport() predicate. By default this aborts. + /// \brief If this file is backed by a assembly streamer, this dumps the + /// specified string in the output .s file. This capability is indicated by + /// the hasRawTextSupport() predicate. By default this aborts. void EmitRawText(const Twine &String); - /// Flush - Causes any cached state to be written out. + /// \brief Causes any cached state to be written out. virtual void Flush() {} - /// FinishImpl - Streamer specific finalization. + /// \brief Streamer specific finalization. virtual void FinishImpl(); - /// Finish - Finish emission of machine code. + /// \brief Finish emission of machine code. void Finish(); - virtual bool mayHaveInstructions() const { return true; } + virtual bool mayHaveInstructions(MCSection &Sec) const { return true; } }; /// Create a dummy machine code streamer, which does nothing. This is useful for diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h index 3984a1fb21b..d5ad4eebf9e 100644 --- a/include/llvm/MC/MCSubtargetInfo.h +++ b/include/llvm/MC/MCSubtargetInfo.h @@ -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 ProcFeatures; // Processor feature list ArrayRef ProcDesc; // Processor descriptions @@ -37,28 +37,29 @@ class MCSubtargetInfo { const MCWriteProcResEntry *WriteProcResTable; const MCWriteLatencyEntry *WriteLatencyTable; const MCReadAdvanceEntry *ReadAdvanceTable; - MCSchedModel CPUSchedModel; + const MCSchedModel *CPUSchedModel; const InstrStage *Stages; // Instruction itinerary stages const unsigned *OperandCycles; // Itinerary operand cycles const unsigned *ForwardingPaths; // Forwarding paths - uint64_t FeatureBits; // Feature bits for current CPU + FS + FeatureBitset FeatureBits; // Feature bits for current CPU + FS + + MCSubtargetInfo() = delete; + MCSubtargetInfo &operator=(MCSubtargetInfo &&) = delete; + MCSubtargetInfo &operator=(const MCSubtargetInfo &) = delete; public: - void InitMCSubtargetInfo(StringRef TT, StringRef CPU, StringRef FS, - ArrayRef PF, - ArrayRef PD, - const SubtargetInfoKV *ProcSched, - const MCWriteProcResEntry *WPR, - const MCWriteLatencyEntry *WL, - const MCReadAdvanceEntry *RA, - const InstrStage *IS, - const unsigned *OC, const unsigned *FP); + MCSubtargetInfo(const MCSubtargetInfo &) = default; + MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS, + ArrayRef PF, + ArrayRef PD, + const SubtargetInfoKV *ProcSched, + const MCWriteProcResEntry *WPR, const MCWriteLatencyEntry *WL, + 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 { @@ -67,36 +68,49 @@ class MCSubtargetInfo { /// getFeatureBits - Return the feature bits. /// - uint64_t getFeatureBits() const { + const FeatureBitset& getFeatureBits() const { return FeatureBits; } /// setFeatureBits - Set the feature bits. /// - void setFeatureBits(uint64_t 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. +protected: + /// Initialize the scheduling model and feature bits. + /// + /// FIXME: Find a way to stick this in the constructor, since it should only + /// be called during initialization. void InitMCProcessorInfo(StringRef CPU, StringRef FS); - /// InitCPUSchedModel - Recompute scheduling model based on CPU. - void InitCPUSchedModel(StringRef CPU); +public: + /// Set the features to the default for the given CPU. + void setDefaultFeatures(StringRef CPU); /// ToggleFeature - Toggle a feature and returns the re-computed feature /// bits. This version does not change the implied bits. - uint64_t ToggleFeature(uint64_t FB); + FeatureBitset ToggleFeature(uint64_t FB); /// ToggleFeature - Toggle a feature and returns the re-computed feature - /// bits. This version will also change all implied bits. - uint64_t ToggleFeature(StringRef FS); + /// bits. This version does not change the implied bits. + FeatureBitset ToggleFeature(const FeatureBitset& FB); + + /// ToggleFeature - Toggle a set of features and returns the re-computed + /// 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; + const MCSchedModel &getSchedModelForCPU(StringRef CPU) const; - /// getSchedModel - Get the machine model for this subtarget's CPU. - /// - const MCSchedModel &getSchedModel() const { return CPUSchedModel; } + /// Get the machine model for this subtarget's CPU. + const MCSchedModel &getSchedModel() const { return *CPUSchedModel; } /// Return an iterator at the first process resource consumed by the given /// scheduling class. @@ -144,7 +158,7 @@ class MCSubtargetInfo { void initInstrItins(InstrItineraryData &InstrItins) const; /// Check whether the CPU string is valid. - bool isCPUStringValid(StringRef CPU) { + bool isCPUStringValid(StringRef CPU) const { auto Found = std::find_if(ProcDesc.begin(), ProcDesc.end(), [=](const SubtargetFeatureKV &KV) { return CPU == KV.Key; diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h index e4bdfda55d6..b2910dfccd6 100644 --- a/include/llvm/MC/MCSymbol.h +++ b/include/llvm/MC/MCSymbol.h @@ -14,176 +14,411 @@ #ifndef LLVM_MC_MCSYMBOL_H #define LLVM_MC_MCSYMBOL_H -#include "llvm/ADT/StringRef.h" -#include "llvm/MC/MCExpr.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/MC/MCAssembler.h" #include "llvm/Support/Compiler.h" namespace llvm { - class MCExpr; - class MCSection; - class MCContext; - class raw_ostream; - - /// MCSymbol - Instances of this class represent a symbol name in the MC file, - /// and MCSymbols are created and unique'd by the MCContext class. MCSymbols - /// should only be constructed with valid names for the object file. +class MCAsmInfo; +class MCExpr; +class MCSymbol; +class MCFragment; +class MCSection; +class MCContext; +class raw_ostream; + +/// MCSymbol - Instances of this class represent a symbol name in the MC file, +/// and MCSymbols are created and uniqued by the MCContext class. MCSymbols +/// should only be constructed with valid names for the object file. +/// +/// If the symbol is defined/emitted into the current translation unit, the +/// 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, + }; + + /// A symbol can contain an Offset, or Value, or be Common, but never more + /// than one of these. + enum Contents : uint8_t { + SymContentsUnset, + SymContentsOffset, + SymContentsVariable, + SymContentsCommon, + }; + + // Special sentinal value for the absolute pseudo section. + // + // FIXME: Use a PointerInt wrapper for this? + static MCSection *AbsolutePseudoSection; + + /// 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. + /// 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. + /// + /// For the 'HasName' integer, this is 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. + mutable PointerIntPair, 1> + SectionOrFragmentAndHasName; + + /// IsTemporary - True if this is an assembler temporary label, which + /// typically does not survive in the .o file's symbol table. Usually + /// "Lfoo" or ".foo". + unsigned IsTemporary : 1; + + /// \brief True if this symbol can be redefined. + unsigned IsRedefinable : 1; + + /// IsUsed - True if this symbol has been used. + mutable unsigned IsUsed : 1; + + mutable bool IsRegistered : 1; + + /// This symbol is visible outside this translation unit. + mutable unsigned IsExternal : 1; + + /// This symbol is private extern. + mutable unsigned IsPrivateExtern : 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; + + /// True if we have created a relocation that uses this symbol. + mutable unsigned IsUsedInReloc : 1; + + /// This is actually a Contents enumerator, but is unsigned to avoid sign + /// extension and achieve better bitpacking with MSVC. + unsigned SymbolContents : 2; + + /// The alignment of the symbol, if it is 'common', or -1. /// - /// If the symbol is defined/emitted into the current translation unit, the - /// 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 { - // Special sentinal value for the absolute pseudo section. - // - // FIXME: Use a PointerInt wrapper for this? - static const MCSection *AbsolutePseudoSection; - - /// Name - The name of the symbol. The referred-to string data is actually - /// held by the StringMap that lives in MCContext. - StringRef Name; - - /// Section - 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 const MCSection *Section; - - /// Value - If non-null, the value for a variable symbol. + /// The alignment is stored as log2(align) + 1. This allows all values from + /// 0 to 2^31 to be stored which is every power of 2 representable by an + /// unsigned. + enum : unsigned { NumCommonAlignmentBits = 5 }; + unsigned CommonAlignLog2 : NumCommonAlignmentBits; + + /// The Flags field is used by object file implementations to store + /// additional per symbol information which is not easily classified. + enum : unsigned { NumFlagsBits = 16 }; + mutable uint32_t Flags : NumFlagsBits; + + /// Index field, for use by the object file implementation. + mutable uint32_t Index = 0; + + union { + /// The offset to apply to the fragment address to form this symbol's value. + uint64_t Offset; + + /// The size of the symbol, if it is 'common'. + uint64_t CommonSize; + + /// If non-null, the value for a variable symbol. const MCExpr *Value; + }; - /// IsTemporary - True if this is an assembler temporary label, which - /// typically does not survive in the .o file's symbol table. Usually - /// "Lfoo" or ".foo". - unsigned IsTemporary : 1; - - /// \brief True if this symbol can be redefined. - unsigned IsRedefinable : 1; - - /// IsUsed - True if this symbol has been used. - mutable unsigned IsUsed : 1; - - private: // MCContext creates and uniques these. - friend class MCExpr; - friend class MCContext; - MCSymbol(StringRef name, bool isTemporary) - : Name(name), Section(nullptr), Value(nullptr), - IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false) {} - - MCSymbol(const MCSymbol&) = delete; - void operator=(const MCSymbol&) = delete; - const MCSection *getSectionPtr() const { - if (Section || !Value) - return Section; - return Section = Value->FindAssociatedSection(); - } +protected: // MCContext creates and uniques these. + friend class MCExpr; + friend class MCContext; + + /// \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 *NameEntry; + uint64_t AlignmentPadding; + } NameEntryStorageTy; + + MCSymbol(SymbolKind Kind, const StringMapEntry *Name, bool isTemporary) + : IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false), + IsRegistered(false), IsExternal(false), IsPrivateExtern(false), + Kind(Kind), IsUsedInReloc(false), SymbolContents(SymContentsUnset), + CommonAlignLog2(0), Flags(0) { + Offset = 0; + SectionOrFragmentAndHasName.setInt(!!Name); + 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 *Name, + MCContext &Ctx); - public: - /// getName - Get the symbol name. - StringRef getName() const { return Name; } +private: - /// @name Accessors - /// @{ + 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?"); + } - /// isTemporary - Check if this is an assembler temporary symbol. - bool isTemporary() const { return IsTemporary; } + MCSymbol(const MCSymbol &) = delete; + void operator=(const MCSymbol &) = delete; + MCSection *getSectionPtr() const { + if (MCFragment *F = getFragment()) + return F->getParent(); + const auto &SectionOrFragment = SectionOrFragmentAndHasName.getPointer(); + assert(!SectionOrFragment.is() && "Section or null expected"); + MCSection *Section = SectionOrFragment.dyn_cast(); + if (Section || !isVariable()) + return Section; + return Section = getVariableValue()->findAssociatedSection(); + } - /// isUsed - Check if this is used. - bool isUsed() const { return IsUsed; } - void setUsed(bool Value) const { IsUsed = Value; } + /// \brief Get a reference to the name field. Requires that we have a name + const StringMapEntry *&getNameEntryPtr() { + assert(SectionOrFragmentAndHasName.getInt() && "Name is required"); + NameEntryStorageTy *Name = reinterpret_cast(this); + return (*(Name - 1)).NameEntry; + } + const StringMapEntry *&getNameEntryPtr() const { + return const_cast(this)->getNameEntryPtr(); + } + +public: + /// getName - Get the symbol name. + StringRef getName() const { + if (!SectionOrFragmentAndHasName.getInt()) + return StringRef(); + + return getNameEntryPtr()->first(); + } - /// \brief Check if this symbol is redefinable. - bool isRedefinable() const { return IsRedefinable; } - /// \brief Mark this symbol as redefinable. - void setRedefinable(bool Value) { IsRedefinable = Value; } - /// \brief Prepare this symbol to be redefined. - void redefineIfPossible() { - if (IsRedefinable) { + bool isRegistered() const { return IsRegistered; } + void setIsRegistered(bool Value) const { IsRegistered = Value; } + + void setUsedInReloc() const { IsUsedInReloc = true; } + bool isUsedInReloc() const { return IsUsedInReloc; } + + /// \name Accessors + /// @{ + + /// isTemporary - Check if this is an assembler temporary symbol. + bool isTemporary() const { return IsTemporary; } + + /// isUsed - Check if this is used. + bool isUsed() const { return IsUsed; } + void setUsed(bool Value) const { IsUsed = Value; } + + /// \brief Check if this symbol is redefinable. + bool isRedefinable() const { return IsRedefinable; } + /// \brief Mark this symbol as redefinable. + void setRedefinable(bool Value) { IsRedefinable = Value; } + /// \brief Prepare this symbol to be redefined. + void redefineIfPossible() { + if (IsRedefinable) { + if (SymbolContents == SymContentsVariable) { Value = nullptr; - Section = nullptr; - IsRedefinable = false; + SymbolContents = SymContentsUnset; } + setUndefined(); + IsRedefinable = false; } + } - /// @} - /// @name Associated Sections - /// @{ + /// @} + /// \name Associated Sections + /// @{ - /// isDefined - Check if this symbol is defined (i.e., it has an address). - /// - /// Defined symbols are either absolute or in some section. - bool isDefined() const { - return getSectionPtr() != nullptr; - } + /// isDefined - Check if this symbol is defined (i.e., it has an address). + /// + /// Defined symbols are either absolute or in some section. + bool isDefined() const { return getSectionPtr() != nullptr; } - /// isInSection - Check if this symbol is defined in some section (i.e., it - /// is defined but not absolute). - bool isInSection() const { - return isDefined() && !isAbsolute(); - } + /// isInSection - Check if this symbol is defined in some section (i.e., it + /// is defined but not absolute). + bool isInSection() const { return isDefined() && !isAbsolute(); } - /// isUndefined - Check if this symbol undefined (i.e., implicitly defined). - bool isUndefined() const { - return !isDefined(); - } + /// isUndefined - Check if this symbol undefined (i.e., implicitly defined). + bool isUndefined() const { return !isDefined(); } - /// isAbsolute - Check if this is an absolute symbol. - bool isAbsolute() const { - return getSectionPtr() == AbsolutePseudoSection; - } + /// isAbsolute - Check if this is an absolute symbol. + bool isAbsolute() const { return getSectionPtr() == AbsolutePseudoSection; } - /// getSection - Get the section associated with a defined, non-absolute - /// symbol. - const MCSection &getSection() const { - assert(isInSection() && "Invalid accessor!"); - return *getSectionPtr(); - } + /// Get the section associated with a defined, non-absolute symbol. + MCSection &getSection() const { + assert(isInSection() && "Invalid accessor!"); + return *getSectionPtr(); + } - /// setSection - Mark the symbol as defined in the section \p S. - void setSection(const MCSection &S) { - assert(!isVariable() && "Cannot set section of variable"); - Section = &S; - } + /// Mark the symbol as defined in the section \p S. + void setSection(MCSection &S) { + assert(!isVariable() && "Cannot set section of variable"); + assert(!SectionOrFragmentAndHasName.getPointer().is() && + "Section or null expected"); + SectionOrFragmentAndHasName.setPointer(&S); + } - /// setUndefined - Mark the symbol as undefined. - void setUndefined() { - Section = nullptr; - } + /// Mark the symbol as undefined. + void setUndefined() { + SectionOrFragmentAndHasName.setPointer( + PointerUnion()); + } - /// @} - /// @name Variable Symbols - /// @{ + bool isELF() const { return Kind == SymbolKindELF; } - /// isVariable - Check if this is a variable symbol. - bool isVariable() const { - return Value != nullptr; - } + bool isCOFF() const { return Kind == SymbolKindCOFF; } - /// getVariableValue() - Get the value for variable symbols. - const MCExpr *getVariableValue() const { - assert(isVariable() && "Invalid accessor!"); - IsUsed = true; - return Value; - } + bool isMachO() const { return Kind == SymbolKindMachO; } - // AliasedSymbol() - If this is an alias (a = b), return the symbol - // we ultimately point to. For a non-alias, this just returns the symbol - // itself. - const MCSymbol &AliasedSymbol() const; + /// @} + /// \name Variable Symbols + /// @{ - void setVariableValue(const MCExpr *Value); + /// isVariable - Check if this is a variable symbol. + bool isVariable() const { + return SymbolContents == SymContentsVariable; + } - /// @} + /// getVariableValue() - Get the value for variable symbols. + const MCExpr *getVariableValue() const { + assert(isVariable() && "Invalid accessor!"); + IsUsed = true; + return Value; + } - /// print - Print the value to the stream \p OS. - void print(raw_ostream &OS) const; + void setVariableValue(const MCExpr *Value); - /// dump - Print the value to stderr. - void dump() const; - }; + /// @} + + /// Get the (implementation defined) index. + uint32_t getIndex() const { + return Index; + } + + /// Set the (implementation defined) index. + void setIndex(uint32_t Value) const { + Index = Value; + } + + uint64_t getOffset() const { + assert((SymbolContents == SymContentsUnset || + SymbolContents == SymContentsOffset) && + "Cannot get offset for a common/variable symbol"); + return Offset; + } + void setOffset(uint64_t Value) { + assert((SymbolContents == SymContentsUnset || + SymbolContents == SymContentsOffset) && + "Cannot set offset for a common/variable symbol"); + Offset = Value; + SymbolContents = SymContentsOffset; + } + + /// Return the size of a 'common' symbol. + uint64_t getCommonSize() const { + assert(isCommon() && "Not a 'common' symbol!"); + return CommonSize; + } - inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) { - Sym.print(OS); - return OS; + /// Mark this symbol as being 'common'. + /// + /// \param Size - The size of the symbol. + /// \param Align - The alignment of the symbol. + void setCommon(uint64_t Size, unsigned Align) { + assert(getOffset() == 0); + CommonSize = Size; + SymbolContents = SymContentsCommon; + + assert((!Align || isPowerOf2_32(Align)) && + "Alignment must be a power of 2"); + unsigned Log2Align = Log2_32(Align) + 1; + assert(Log2Align < (1U << NumCommonAlignmentBits) && + "Out of range alignment"); + CommonAlignLog2 = Log2Align; + } + + /// Return the alignment of a 'common' symbol. + unsigned getCommonAlignment() const { + assert(isCommon() && "Not a 'common' symbol!"); + return CommonAlignLog2 ? (1U << (CommonAlignLog2 - 1)) : 0; + } + + /// 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 || getCommonAlignment() != Align) + return true; + } else + setCommon(Size, Align); + return false; + } + + /// Is this a 'common' symbol. + bool isCommon() const { + return SymbolContents == SymContentsCommon; + } + + MCFragment *getFragment() const { + return SectionOrFragmentAndHasName.getPointer().dyn_cast(); + } + void setFragment(MCFragment *Value) const { + SectionOrFragmentAndHasName.setPointer(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; } + + /// Set the (implementation defined) symbol flags. + void setFlags(uint32_t Value) const { + assert(Value < (1U << NumFlagsBits) && "Out of range flags"); + Flags = Value; + } + + /// Modify the flags via a mask + void modifyFlags(uint32_t Value, uint32_t Mask) const { + assert(Value < (1U << NumFlagsBits) && "Out of range flags"); + Flags = (Flags & ~Mask) | Value; + } +}; + +inline raw_ostream &operator<<(raw_ostream &OS, const MCSymbol &Sym) { + Sym.print(OS, nullptr); + return OS; +} } // end namespace llvm #endif diff --git a/include/llvm/MC/MCSymbolCOFF.h b/include/llvm/MC/MCSymbolCOFF.h new file mode 100644 index 00000000000..2172c67981c --- /dev/null +++ b/include/llvm/MC/MCSymbolCOFF.h @@ -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 *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 diff --git a/include/llvm/MC/MCSymbolELF.h b/include/llvm/MC/MCSymbolELF.h new file mode 100644 index 00000000000..bbcd22e8e7d --- /dev/null +++ b/include/llvm/MC/MCSymbolELF.h @@ -0,0 +1,54 @@ +//===- MCSymbolELF.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_MCSYMBOLELF_H +#define LLVM_MC_MCSYMBOLELF_H + +#include "llvm/MC/MCSymbol.h" + +namespace llvm { +class MCSymbolELF : public MCSymbol { + /// An expression describing how to calculate the size of a symbol. If a + /// symbol has no size this field will be NULL. + const MCExpr *SymbolSize = nullptr; + +public: + MCSymbolELF(const StringMapEntry *Name, bool isTemporary) + : MCSymbol(SymbolKindELF, Name, isTemporary) {} + void setSize(const MCExpr *SS) { SymbolSize = SS; } + + const MCExpr *getSize() const { return SymbolSize; } + + void setVisibility(unsigned Visibility); + unsigned getVisibility() const; + + void setOther(unsigned Other); + unsigned getOther() const; + + void setType(unsigned Type) const; + unsigned getType() const; + + void setBinding(unsigned Binding) const; + unsigned getBinding() const; + + bool isBindingSet() 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; +}; +} + +#endif diff --git a/include/llvm/MC/MCSymbolMachO.h b/include/llvm/MC/MCSymbolMachO.h new file mode 100644 index 00000000000..5b0321fe9f7 --- /dev/null +++ b/include/llvm/MC/MCSymbolMachO.h @@ -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 LLVM_MC_MCSYMBOLMACHO_H + +#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 . + 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 *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 diff --git a/include/llvm/MC/MCSymbolizer.h b/include/llvm/MC/MCSymbolizer.h index 20e7b81e733..2ef17673f09 100644 --- a/include/llvm/MC/MCSymbolizer.h +++ b/include/llvm/MC/MCSymbolizer.h @@ -59,14 +59,14 @@ class MCSymbolizer { /// represent this immediate in a more understandable way, for instance as a /// symbol or an offset from a symbol. Relocations can also be used to enrich /// the symbolic expression. - /// @param Inst - The MCInst where to insert the symbolic operand. - /// @param cStream - Stream to print comments and annotations on. - /// @param Value - Operand value, pc-adjusted by the caller if necessary. - /// @param Address - Load address of the instruction. - /// @param IsBranch - Is the instruction a branch? - /// @param Offset - Byte offset of the operand inside the inst. - /// @param InstSize - Size of the instruction in bytes. - /// @return Whether a symbolic operand was added. + /// \param Inst - The MCInst where to insert the symbolic operand. + /// \param cStream - Stream to print comments and annotations on. + /// \param Value - Operand value, pc-adjusted by the caller if necessary. + /// \param Address - Load address of the instruction. + /// \param IsBranch - Is the instruction a branch? + /// \param Offset - Byte offset of the operand inside the inst. + /// \param InstSize - Size of the instruction in bytes. + /// \return Whether a symbolic operand was added. virtual bool tryAddingSymbolicOperand(MCInst &Inst, raw_ostream &cStream, int64_t Value, uint64_t Address, bool IsBranch, uint64_t Offset, diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h index 36db3914f01..2b857ca4b2d 100644 --- a/include/llvm/MC/MCTargetAsmParser.h +++ b/include/llvm/MC/MCTargetAsmParser.h @@ -92,7 +92,7 @@ class MCTargetAsmParser : public MCAsmParserExtension { MCTargetAsmParser(const MCTargetAsmParser &) = delete; void operator=(const MCTargetAsmParser &) = delete; protected: // Can only create subclasses. - MCTargetAsmParser(); + MCTargetAsmParser(MCTargetOptions const &); /// AvailableFeatures - The current set of available features. uint64_t AvailableFeatures; @@ -198,7 +198,7 @@ class MCTargetAsmParser : public MCAsmParserExtension { return nullptr; } - virtual void onLabelParsed(MCSymbol *Symbol) { }; + virtual void onLabelParsed(MCSymbol *Symbol) { } }; } // End llvm namespace diff --git a/include/llvm/MC/MCTargetOptions.h b/include/llvm/MC/MCTargetOptions.h index ce28a196e97..00a74de9d06 100644 --- a/include/llvm/MC/MCTargetOptions.h +++ b/include/llvm/MC/MCTargetOptions.h @@ -29,6 +29,7 @@ class MCTargetOptions { bool MCRelaxAll : 1; bool MCNoExecStack : 1; bool MCFatalWarnings : 1; + bool MCNoWarn : 1; bool MCSaveTempLabels : 1; bool MCUseDwarfDirectory : 1; bool ShowMCEncoding : 1; @@ -49,13 +50,14 @@ inline bool operator==(const MCTargetOptions &LHS, const MCTargetOptions &RHS) { ARE_EQUAL(MCRelaxAll) && ARE_EQUAL(MCNoExecStack) && ARE_EQUAL(MCFatalWarnings) && + ARE_EQUAL(MCNoWarn) && ARE_EQUAL(MCSaveTempLabels) && ARE_EQUAL(MCUseDwarfDirectory) && ARE_EQUAL(ShowMCEncoding) && ARE_EQUAL(ShowMCInst) && ARE_EQUAL(AsmVerbose) && ARE_EQUAL(DwarfVersion) && - ARE_EQUAL(ABIName)); + ARE_EQUAL(ABIName)); #undef ARE_EQUAL } diff --git a/include/llvm/MC/MCTargetOptionsCommandFlags.h b/include/llvm/MC/MCTargetOptionsCommandFlags.h index af23a92e6e9..1240e135ea0 100644 --- a/include/llvm/MC/MCTargetOptionsCommandFlags.h +++ b/include/llvm/MC/MCTargetOptionsCommandFlags.h @@ -40,6 +40,12 @@ cl::opt ShowMCInst("asm-show-inst", cl::desc("Emit internal instruction representation to " "assembly file")); +cl::opt FatalWarnings("fatal-warnings", + cl::desc("Treat warnings as errors")); + +cl::opt NoWarn("no-warn", cl::desc("Suppress all warnings")); +cl::alias NoWarnW("W", cl::desc("Alias for --no-warn"), cl::aliasopt(NoWarn)); + cl::opt ABIName("target-abi", cl::Hidden, cl::desc("The name of the ABI to be targeted from the backend."), @@ -53,6 +59,8 @@ static inline MCTargetOptions InitMCTargetOptionsFromFlags() { Options.DwarfVersion = DwarfVersion; Options.ShowMCInst = ShowMCInst; Options.ABIName = ABIName; + Options.MCFatalWarnings = FatalWarnings; + Options.MCNoWarn = NoWarn; return Options; } diff --git a/include/llvm/MC/MCValue.h b/include/llvm/MC/MCValue.h index 175fed090b3..6bdf43685f2 100644 --- a/include/llvm/MC/MCValue.h +++ b/include/llvm/MC/MCValue.h @@ -23,10 +23,11 @@ namespace llvm { class MCAsmInfo; class raw_ostream; -/// MCValue - This represents an "assembler immediate". In its most -/// general form, this can hold ":Kind:(SymbolA - SymbolB + imm64)". -/// Not all targets supports relocations of this general form, but we -/// need to represent this anyway. +/// \brief This represents an "assembler immediate". +/// +/// In its most general form, this can hold ":Kind:(SymbolA - SymbolB + +/// imm64)". Not all targets supports relocations of this general form, but we +/// need to represent this anyway. /// /// In general both SymbolA and SymbolB will also have a modifier /// analogous to the top-level Kind. Current targets are not expected @@ -51,13 +52,13 @@ class MCValue { const MCSymbolRefExpr *getSymB() const { return SymB; } uint32_t getRefKind() const { return RefKind; } - /// isAbsolute - Is this an absolute (as opposed to relocatable) value. + /// \brief Is this an absolute (as opposed to relocatable) value. bool isAbsolute() const { return !SymA && !SymB; } - /// print - Print the value to the stream \p OS. + /// \brief Print the value to the stream \p OS. void print(raw_ostream &OS) const; - /// dump - Print the value to stderr. + /// \brief Print the value to stderr. void dump() const; MCSymbolRefExpr::VariantKind getAccessVariant() const; diff --git a/include/llvm/MC/MCWinCOFFStreamer.h b/include/llvm/MC/MCWinCOFFStreamer.h index b3fee810b6b..6fbc754f112 100644 --- a/include/llvm/MC/MCWinCOFFStreamer.h +++ b/include/llvm/MC/MCWinCOFFStreamer.h @@ -50,16 +50,16 @@ class MCWinCOFFStreamer : public MCObjectStreamer { void EmitCOFFSymbolStorageClass(int StorageClass) override; void EmitCOFFSymbolType(int Type) override; void EndCOFFSymbolDef() override; + void EmitCOFFSafeSEH(MCSymbol const *Symbol) override; void EmitCOFFSectionIndex(MCSymbol const *Symbol) override; void EmitCOFFSecRel32(MCSymbol const *Symbol) override; - void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) override; void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; - void EmitZerofill(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, + void EmitZerofill(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; - void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, + void EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override; void EmitFileDirective(StringRef Filename) override; void EmitIdent(StringRef IdentString) override; diff --git a/include/llvm/MC/MCWinEH.h b/include/llvm/MC/MCWinEH.h index 05b58c753b6..723d7a397c4 100644 --- a/include/llvm/MC/MCWinEH.h +++ b/include/llvm/MC/MCWinEH.h @@ -65,10 +65,10 @@ struct FrameInfo { class UnwindEmitter { public: - static const MCSection *getPDataSection(const MCSymbol *Function, - MCContext &Context); - static const MCSection *getXDataSection(const MCSymbol *Function, - MCContext &Context); + static MCSection *getPDataSection(const MCSymbol *Function, + MCContext &Context); + static MCSection *getXDataSection(const MCSymbol *Function, + MCContext &Context); virtual ~UnwindEmitter() { } diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h index 6f195d7be99..8edd798f153 100644 --- a/include/llvm/MC/SubtargetFeature.h +++ b/include/llvm/MC/SubtargetFeature.h @@ -21,11 +21,29 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/DataTypes.h" +#include namespace llvm { class raw_ostream; class StringRef; +// A container class for subtarget features. +// This is convenient because std::bitset does not have a constructor +// with an initializer list of set bits. +const unsigned MAX_SUBTARGET_FEATURES = 96; +class FeatureBitset : public std::bitset { +public: + // Cannot inherit constructors because it's not supported by VC++.. + FeatureBitset() : bitset() {} + + FeatureBitset(const bitset& B) : bitset(B) {} + + FeatureBitset(std::initializer_list Init) : bitset() { + for (auto I = Init.begin() , E = Init.end(); I != E; ++I) + set(*I); + } +}; + //===----------------------------------------------------------------------===// /// /// SubtargetFeatureKV - Used to provide key value pairs for feature and @@ -34,8 +52,8 @@ namespace llvm { struct SubtargetFeatureKV { const char *Key; // K-V key string const char *Desc; // Help descriptor - uint64_t Value; // K-V integer value - uint64_t Implies; // K-V bit mask + FeatureBitset Value; // K-V integer value + FeatureBitset Implies; // K-V bit mask // Compare routine for std::lower_bound bool operator<(StringRef S) const { @@ -82,11 +100,15 @@ class SubtargetFeatures { /// ToggleFeature - Toggle a feature and returns the newly updated feature /// bits. - uint64_t ToggleFeature(uint64_t Bits, StringRef String, + FeatureBitset ToggleFeature(FeatureBitset Bits, StringRef String, ArrayRef FeatureTable); + /// Apply the feature flag and return the newly updated feature bits. + FeatureBitset ApplyFeatureFlag(FeatureBitset Bits, StringRef Feature, + ArrayRef FeatureTable); + /// Get feature bits of a CPU. - uint64_t getFeatureBits(StringRef CPU, + FeatureBitset getFeatureBits(StringRef CPU, ArrayRef CPUTable, ArrayRef FeatureTable); diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index d40dc9db9f5..d7f46551827 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -62,6 +62,8 @@ class Archive : public Binary { return reinterpret_cast(Data.data()); } + bool isThinMember() const; + public: Child(const Archive *Parent, const char *Start); @@ -74,6 +76,7 @@ class Archive : public Binary { return Data.begin() < other.Data.begin(); } + const Archive *getParent() const { return Parent; } Child getNext() const; ErrorOr getName() const; @@ -94,9 +97,7 @@ class Archive : public Binary { /// \return the size in the archive header for this member. uint64_t getRawSize() const; - StringRef getBuffer() const { - return StringRef(Data.data() + StartOfFile, getSize()); - } + ErrorOr getBuffer() const; uint64_t getChildOffset() const; ErrorOr getMemoryBufferRef() const; @@ -183,6 +184,7 @@ class Archive : public Binary { }; Kind kind() const { return (Kind)Format; } + bool isThin() const { return IsThin; } child_iterator child_begin(bool SkipInternal = true) const; child_iterator child_end() const; @@ -207,6 +209,12 @@ class Archive : public Binary { bool hasSymbolTable() const; child_iterator getSymbolTableChild() const { return SymbolTable; } + StringRef getSymbolTable() const { + // We know that the symbol table is not an external file, + // so we just assert there is no error. + return *SymbolTable->getBuffer(); + } + uint32_t getNumberOfSymbols() const; private: child_iterator SymbolTable; @@ -214,6 +222,7 @@ class Archive : public Binary { child_iterator FirstRegular; unsigned Format : 2; unsigned IsThin : 1; + mutable std::vector> ThinBuffers; }; } diff --git a/include/llvm/Object/ArchiveWriter.h b/include/llvm/Object/ArchiveWriter.h new file mode 100644 index 00000000000..fc4669de1ba --- /dev/null +++ b/include/llvm/Object/ArchiveWriter.h @@ -0,0 +1,48 @@ +//===- 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; + +public: + NewArchiveIterator(object::Archive::child_iterator I, StringRef Name); + NewArchiveIterator(StringRef FileName); + bool isNewMember() const; + StringRef getName() const; + + object::Archive::child_iterator getOld() const; + + StringRef getNew() const; + llvm::ErrorOr getFD(sys::fs::file_status &NewStatus) const; + const sys::fs::file_status &getStatus() const; +}; + +std::pair +writeArchive(StringRef ArcName, std::vector &NewMembers, + bool WriteSymtab, object::Archive::Kind Kind, bool Deterministic, + bool Thin); +} + +#endif diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index 522bf68c6cb..025a9dbc6bc 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -249,6 +249,15 @@ struct coff_symbol { typedef coff_symbol coff_symbol16; typedef coff_symbol coff_symbol32; +// Contains only common parts of coff_symbol16 and coff_symbol32. +struct coff_symbol_generic { + union { + char ShortName[COFF::NameSize]; + StringTableOffset Offset; + } Name; + support::ulittle32_t Value; +}; + class COFFSymbolRef { public: COFFSymbolRef(const coff_symbol16 *CS) : CS16(CS), CS32(nullptr) {} @@ -259,6 +268,12 @@ class COFFSymbolRef { return CS16 ? static_cast(CS16) : CS32; } + const coff_symbol_generic *getGeneric() const { + if (CS16) + return reinterpret_cast(CS16); + return reinterpret_cast(CS32); + } + friend bool operator<(COFFSymbolRef A, COFFSymbolRef B) { return A.getRawPtr() < B.getRawPtr(); } @@ -314,6 +329,10 @@ class COFFSymbolRef { return (getType() & 0xF0) >> COFF::SCT_COMPLEX_TYPE_SHIFT; } + bool isAbsolute() const { + return getSectionNumber() == -1; + } + bool isExternal() const { return getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL; } @@ -350,6 +369,10 @@ class COFFSymbolRef { return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE; } + bool isSection() const { + return getStorageClass() == COFF::IMAGE_SYM_CLASS_SECTION; + } + bool isSectionDefinition() const { // C++/CLI creates external ABS symbols for non-const appdomain globals. // These are also followed by an auxiliary section definition. @@ -441,6 +464,27 @@ struct coff_aux_clr_token { support::ulittle32_t SymbolTableIndex; }; +struct coff_import_header { + support::ulittle16_t Sig1; + support::ulittle16_t Sig2; + support::ulittle16_t Version; + support::ulittle16_t Machine; + support::ulittle32_t TimeDateStamp; + support::ulittle32_t SizeOfData; + support::ulittle16_t OrdinalHint; + support::ulittle16_t TypeInfo; + int getType() const { return TypeInfo & 0x3; } + int getNameType() const { return (TypeInfo >> 2) & 0x7; } +}; + +struct coff_import_directory_table_entry { + support::ulittle32_t ImportLookupTableRVA; + support::ulittle32_t TimeDateStamp; + support::ulittle32_t ForwarderChain; + support::ulittle32_t NameRVA; + support::ulittle32_t ImportAddressTableRVA; +}; + struct coff_load_configuration32 { support::ulittle32_t Characteristics; support::ulittle32_t TimeDateStamp; @@ -464,6 +508,29 @@ struct coff_load_configuration32 { support::ulittle32_t SEHandlerCount; }; +struct coff_load_configuration64 { + support::ulittle32_t Characteristics; + support::ulittle32_t TimeDateStamp; + support::ulittle16_t MajorVersion; + support::ulittle16_t MinorVersion; + support::ulittle32_t GlobalFlagsClear; + support::ulittle32_t GlobalFlagsSet; + support::ulittle32_t CriticalSectionDefaultTimeout; + support::ulittle32_t DeCommitFreeBlockThreshold; + support::ulittle32_t DeCommitTotalFreeThreshold; + support::ulittle32_t LockPrefixTable; + support::ulittle32_t MaximumAllocationSize; + support::ulittle32_t VirtualMemoryThreshold; + support::ulittle32_t ProcessAffinityMask; + support::ulittle32_t ProcessHeapFlags; + support::ulittle16_t CSDVersion; + support::ulittle16_t Reserved; + support::ulittle32_t EditList; + support::ulittle64_t SecurityCookie; + support::ulittle64_t SEHandlerTable; + support::ulittle64_t SEHandlerCount; +}; + struct coff_runtime_function_x64 { support::ulittle32_t BeginAddress; support::ulittle32_t EndAddress; @@ -580,14 +647,12 @@ class COFFObjectFile : public ObjectFile { } protected: void moveSymbolNext(DataRefImpl &Symb) const override; - std::error_code getSymbolName(DataRefImpl Symb, - StringRef &Res) const override; - std::error_code getSymbolAddress(DataRefImpl Symb, - uint64_t &Res) const override; - std::error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; + ErrorOr getSymbolName(DataRefImpl Symb) const override; + ErrorOr getSymbolAddress(DataRefImpl Symb) const override; + uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; + uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; - std::error_code getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const override; + SymbolRef::Type getSymbolType(DataRefImpl Symb) const override; std::error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const override; void moveSectionNext(DataRefImpl &Sec) const override; @@ -602,24 +667,15 @@ class COFFObjectFile : public ObjectFile { bool isSectionData(DataRefImpl Sec) const override; bool isSectionBSS(DataRefImpl Sec) const override; bool isSectionVirtual(DataRefImpl Sec) const override; - bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; void moveRelocationNext(DataRefImpl &Rel) const override; - std::error_code getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const override; - std::error_code getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const override; + uint64_t getRelocationOffset(DataRefImpl Rel) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; - std::error_code getRelocationType(DataRefImpl Rel, - uint64_t &Res) const override; - std::error_code - getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl &Result) const override; - std::error_code - getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const override; + uint64_t getRelocationType(DataRefImpl Rel) const override; + void getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl &Result) const override; public: COFFObjectFile(MemoryBufferRef Object, std::error_code &EC); @@ -632,6 +688,8 @@ class COFFObjectFile : public ObjectFile { COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const; COFFSymbolRef getCOFFSymbol(const SymbolRef &Symbol) const; const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const; + unsigned getSectionID(SectionRef Sec) const; + unsigned getSymbolSectionID(SymbolRef Sym) const; uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; @@ -669,7 +727,7 @@ class COFFObjectFile : public ObjectFile { return object_error::parse_failed; Res = reinterpret_cast(getSymbolTable()) + Index; - return object_error::success; + return std::error_code(); } ErrorOr getSymbol(uint32_t index) const { if (SymbolTable16) { @@ -692,9 +750,11 @@ class COFFObjectFile : public ObjectFile { if (std::error_code EC = s.getError()) return EC; Res = reinterpret_cast(s->getRawPtr()); - return object_error::success; + return std::error_code(); } std::error_code getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const; + std::error_code getSymbolName(const coff_symbol_generic *Symbol, + StringRef &Res) const; ArrayRef getSymbolAuxData(COFFSymbolRef Symbol) const; @@ -706,6 +766,9 @@ class COFFObjectFile : public ObjectFile { llvm_unreachable("null symbol table pointer!"); } + iterator_range + getRelocations(const coff_section *Sec) const; + std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const; uint64_t getSectionSize(const coff_section *Sec) const; std::error_code getSectionContents(const coff_section *Sec, diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index ddabf59f309..4518ffae661 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -55,78 +55,6 @@ class ELFFile { typedef typename std::conditional::type uintX_t; - /// \brief Iterate over constant sized entities. - template - class ELFEntityIterator { - public: - typedef ptrdiff_t difference_type; - typedef EntT value_type; - typedef std::forward_iterator_tag iterator_category; - typedef value_type &reference; - typedef value_type *pointer; - - /// \brief Default construct iterator. - ELFEntityIterator() : EntitySize(0), Current(nullptr) {} - ELFEntityIterator(uintX_t EntSize, const char *Start) - : EntitySize(EntSize), Current(Start) {} - - reference operator *() { - assert(Current && "Attempted to dereference an invalid iterator!"); - return *reinterpret_cast(Current); - } - - pointer operator ->() { - assert(Current && "Attempted to dereference an invalid iterator!"); - return reinterpret_cast(Current); - } - - bool operator ==(const ELFEntityIterator &Other) { - return Current == Other.Current; - } - - bool operator !=(const ELFEntityIterator &Other) { - return !(*this == Other); - } - - ELFEntityIterator &operator ++() { - assert(Current && "Attempted to increment an invalid iterator!"); - Current += EntitySize; - return *this; - } - - ELFEntityIterator &operator+(difference_type n) { - assert(Current && "Attempted to increment an invalid iterator!"); - Current += (n * EntitySize); - return *this; - } - - ELFEntityIterator &operator-(difference_type n) { - assert(Current && "Attempted to subtract an invalid iterator!"); - Current -= (n * EntitySize); - return *this; - } - - ELFEntityIterator operator ++(int) { - ELFEntityIterator Tmp = *this; - ++*this; - return Tmp; - } - - difference_type operator -(const ELFEntityIterator &Other) const { - assert(EntitySize == Other.EntitySize && - "Subtracting iterators of different EntitySize!"); - return (Current - Other.Current) / EntitySize; - } - - const char *get() const { return Current; } - - uintX_t getEntSize() const { return EntitySize; } - - private: - uintX_t EntitySize; - const char *Current; - }; - typedef Elf_Ehdr_Impl Elf_Ehdr; typedef Elf_Shdr_Impl Elf_Shdr; typedef Elf_Sym_Impl Elf_Sym; @@ -139,12 +67,9 @@ class ELFFile { typedef Elf_Verneed_Impl Elf_Verneed; typedef Elf_Vernaux_Impl Elf_Vernaux; typedef Elf_Versym_Impl Elf_Versym; - typedef ELFEntityIterator Elf_Dyn_Iter; - typedef iterator_range Elf_Dyn_Range; - typedef ELFEntityIterator Elf_Rela_Iter; - typedef ELFEntityIterator Elf_Rel_Iter; - typedef ELFEntityIterator Elf_Shdr_Iter; - typedef iterator_range Elf_Shdr_Range; + typedef Elf_Hash_Impl Elf_Hash; + typedef iterator_range Elf_Dyn_Range; + typedef iterator_range Elf_Shdr_Range; /// \brief Archive files are 2 byte aligned, so we need this for /// PointerIntPair to work. @@ -158,74 +83,11 @@ class ELFFile { enum { NumLowBitsAvailable = 1 }; }; - class Elf_Sym_Iter { - public: - typedef ptrdiff_t difference_type; - typedef const Elf_Sym value_type; - typedef std::random_access_iterator_tag iterator_category; - typedef value_type &reference; - typedef value_type *pointer; - - /// \brief Default construct iterator. - Elf_Sym_Iter() : EntitySize(0), Current(0, false) {} - Elf_Sym_Iter(uintX_t EntSize, const char *Start, bool IsDynamic) - : EntitySize(EntSize), Current(Start, IsDynamic) {} - - reference operator*() { - assert(Current.getPointer() && - "Attempted to dereference an invalid iterator!"); - return *reinterpret_cast(Current.getPointer()); - } - - pointer operator->() { - assert(Current.getPointer() && - "Attempted to dereference an invalid iterator!"); - return reinterpret_cast(Current.getPointer()); - } - - bool operator==(const Elf_Sym_Iter &Other) { - return Current == Other.Current; - } - - bool operator!=(const Elf_Sym_Iter &Other) { return !(*this == Other); } - - Elf_Sym_Iter &operator++() { - assert(Current.getPointer() && - "Attempted to increment an invalid iterator!"); - Current.setPointer(Current.getPointer() + EntitySize); - return *this; - } - - Elf_Sym_Iter operator++(int) { - Elf_Sym_Iter Tmp = *this; - ++*this; - return Tmp; - } - - Elf_Sym_Iter operator+(difference_type Dist) { - assert(Current.getPointer() && - "Attempted to increment an invalid iterator!"); - Current.setPointer(Current.getPointer() + EntitySize * Dist); - return *this; - } - - difference_type operator-(const Elf_Sym_Iter &Other) const { - assert(EntitySize == Other.EntitySize && - "Subtracting iterators of different EntitySize!"); - return (Current.getPointer() - Other.Current.getPointer()) / EntitySize; - } - - const char *get() const { return Current.getPointer(); } - - bool isDynamic() const { return Current.getInt(); } + typedef iterator_range Elf_Sym_Range; - uintX_t getEntSize() const { return EntitySize; } - - private: - uintX_t EntitySize; - PointerIntPair > Current; - }; + const uint8_t *base() const { + return reinterpret_cast(Buf.data()); + } private: typedef SmallVector Sections_t; @@ -233,42 +95,19 @@ class ELFFile { StringRef Buf; - const uint8_t *base() const { - return reinterpret_cast(Buf.data()); - } - const Elf_Ehdr *Header; - const Elf_Shdr *SectionHeaderTable; - const Elf_Shdr *dot_shstrtab_sec; // Section header string table. - const Elf_Shdr *dot_strtab_sec; // Symbol header string table. - const Elf_Shdr *dot_symtab_sec; // Symbol table section. + const Elf_Shdr *SectionHeaderTable = nullptr; + StringRef DotShstrtab; // Section header string table. + StringRef DotStrtab; // Symbol header string table. + const Elf_Shdr *dot_symtab_sec = nullptr; // Symbol table section. + const Elf_Shdr *DotDynSymSec = nullptr; // Dynamic symbol table section. - const Elf_Shdr *SymbolTableSectionHeaderIndex; + const Elf_Shdr *SymbolTableSectionHeaderIndex = nullptr; DenseMap ExtendedSymbolTable; - const Elf_Shdr *dot_gnu_version_sec; // .gnu.version - const Elf_Shdr *dot_gnu_version_r_sec; // .gnu.version_r - const Elf_Shdr *dot_gnu_version_d_sec; // .gnu.version_d - - /// \brief Represents a region described by entries in the .dynamic table. - struct DynRegionInfo { - DynRegionInfo() : Addr(nullptr), Size(0), EntSize(0) {} - /// \brief Address in current address space. - const void *Addr; - /// \brief Size in bytes of the region. - uintX_t Size; - /// \brief Size of each entity in the region. - uintX_t EntSize; - }; - - DynRegionInfo DynamicRegion; - DynRegionInfo DynHashRegion; - DynRegionInfo DynStrRegion; - DynRegionInfo DynSymRegion; - - // Pointer to SONAME entry in dynamic string table - // This is set the first time getLoadName is called. - mutable const char *dt_soname; + const Elf_Shdr *dot_gnu_version_sec = nullptr; // .gnu.version + const Elf_Shdr *dot_gnu_version_r_sec = nullptr; // .gnu.version_r + const Elf_Shdr *dot_gnu_version_d_sec = nullptr; // .gnu.version_d // Records for each version index the corresponding Verdef or Vernaux entry. // This is filled the first time LoadVersionMap() is called. @@ -301,11 +140,14 @@ class ELFFile { const T *getEntry(uint32_t Section, uint32_t Entry) const; template const T *getEntry(const Elf_Shdr *Section, uint32_t Entry) const; - const char *getString(uint32_t section, uint32_t offset) const; - const char *getString(const Elf_Shdr *section, uint32_t offset) const; - const char *getDynamicString(uintX_t Offset) const; - ErrorOr getSymbolVersion(const Elf_Shdr *section, - const Elf_Sym *Symb, + + const Elf_Shdr *getDotSymtabSec() const { return dot_symtab_sec; } + const Elf_Shdr *getDotDynSymSec() const { return DotDynSymSec; } + + ErrorOr getStringTable(const Elf_Shdr *Section) const; + ErrorOr getStringTableForSymtab(const Elf_Shdr &Section) const; + + ErrorOr getSymbolVersion(StringRef StrTab, const Elf_Sym *Symb, bool &IsDefault) const; void VerifyStrTab(const Elf_Shdr *sh) const; @@ -318,7 +160,7 @@ class ELFFile { std::pair getRelocationSymbol(const Elf_Shdr *RelSec, const RelT *Rel) const; - ELFFile(StringRef Object, std::error_code &ec); + ELFFile(StringRef Object, std::error_code &EC); bool isMipsELF64() const { return Header->e_machine == ELF::EM_MIPS && @@ -331,104 +173,114 @@ class ELFFile { Header->getDataEncoding() == ELF::ELFDATA2LSB; } - Elf_Shdr_Iter begin_sections() const; - Elf_Shdr_Iter end_sections() const; + const Elf_Shdr *section_begin() const; + const Elf_Shdr *section_end() const; Elf_Shdr_Range sections() const { - return make_range(begin_sections(), end_sections()); + return make_range(section_begin(), section_end()); + } + + const Elf_Sym *symbol_begin(const Elf_Shdr *Sec) const { + if (!Sec) + return nullptr; + if (Sec->sh_entsize != sizeof(Elf_Sym)) + report_fatal_error("Invalid symbol size"); + return reinterpret_cast(base() + Sec->sh_offset); + } + const Elf_Sym *symbol_end(const Elf_Shdr *Sec) const { + if (!Sec) + return nullptr; + uint64_t Size = Sec->sh_size; + if (Size % sizeof(Elf_Sym)) + report_fatal_error("Invalid symbol table size"); + return symbol_begin(Sec) + Size / sizeof(Elf_Sym); + } + Elf_Sym_Range symbols(const Elf_Shdr *Sec) const { + return make_range(symbol_begin(Sec), symbol_end(Sec)); } - Elf_Sym_Iter begin_symbols() const; - Elf_Sym_Iter end_symbols() const; + const Elf_Sym *symbol_begin() const { return symbol_begin(dot_symtab_sec); } + const Elf_Sym *symbol_end() const { return symbol_end(dot_symtab_sec); } + Elf_Sym_Range symbols() const { return symbols(dot_symtab_sec); } - Elf_Dyn_Iter begin_dynamic_table() const; - /// \param NULLEnd use one past the first DT_NULL entry as the end instead of - /// the section size. - Elf_Dyn_Iter end_dynamic_table(bool NULLEnd = false) const; - Elf_Dyn_Range dynamic_table(bool NULLEnd = false) const { - return make_range(begin_dynamic_table(), end_dynamic_table(NULLEnd)); + const Elf_Sym *dynamic_symbol_begin() const { + return symbol_begin(DotDynSymSec); } + const Elf_Sym *dynamic_symbol_end() const { return symbol_end(DotDynSymSec); } + Elf_Sym_Range dynamic_symbols() const { return symbols(DotDynSymSec); } + + typedef iterator_range Elf_Rela_Range; - Elf_Sym_Iter begin_dynamic_symbols() const { - if (DynSymRegion.Addr) - return Elf_Sym_Iter(DynSymRegion.EntSize, (const char *)DynSymRegion.Addr, - true); - return Elf_Sym_Iter(0, nullptr, true); + const Elf_Rela *rela_begin(const Elf_Shdr *sec) const { + if (sec->sh_entsize != sizeof(Elf_Rela)) + report_fatal_error("Invalid relocation entry size"); + return reinterpret_cast(base() + sec->sh_offset); } - Elf_Sym_Iter end_dynamic_symbols() const { - if (DynSymRegion.Addr) - return Elf_Sym_Iter(DynSymRegion.EntSize, - (const char *)DynSymRegion.Addr + DynSymRegion.Size, - true); - return Elf_Sym_Iter(0, nullptr, true); + const Elf_Rela *rela_end(const Elf_Shdr *sec) const { + uint64_t Size = sec->sh_size; + if (Size % sizeof(Elf_Rela)) + report_fatal_error("Invalid relocation table size"); + return rela_begin(sec) + Size / sizeof(Elf_Rela); } - Elf_Rela_Iter begin_rela(const Elf_Shdr *sec) const { - return Elf_Rela_Iter(sec->sh_entsize, - (const char *)(base() + sec->sh_offset)); + Elf_Rela_Range relas(const Elf_Shdr *Sec) const { + return make_range(rela_begin(Sec), rela_end(Sec)); } - Elf_Rela_Iter end_rela(const Elf_Shdr *sec) const { - return Elf_Rela_Iter( - sec->sh_entsize, - (const char *)(base() + sec->sh_offset + sec->sh_size)); + const Elf_Rel *rel_begin(const Elf_Shdr *sec) const { + if (sec->sh_entsize != sizeof(Elf_Rel)) + report_fatal_error("Invalid relocation entry size"); + return reinterpret_cast(base() + sec->sh_offset); } - Elf_Rel_Iter begin_rel(const Elf_Shdr *sec) const { - return Elf_Rel_Iter(sec->sh_entsize, - (const char *)(base() + sec->sh_offset)); + const Elf_Rel *rel_end(const Elf_Shdr *sec) const { + uint64_t Size = sec->sh_size; + if (Size % sizeof(Elf_Rel)) + report_fatal_error("Invalid relocation table size"); + return rel_begin(sec) + Size / sizeof(Elf_Rel); } - Elf_Rel_Iter end_rel(const Elf_Shdr *sec) const { - return Elf_Rel_Iter(sec->sh_entsize, - (const char *)(base() + sec->sh_offset + sec->sh_size)); + typedef iterator_range Elf_Rel_Range; + Elf_Rel_Range rels(const Elf_Shdr *Sec) const { + return make_range(rel_begin(Sec), rel_end(Sec)); } /// \brief Iterate over program header table. - typedef ELFEntityIterator Elf_Phdr_Iter; + const Elf_Phdr *program_header_begin() const { + if (Header->e_phnum && Header->e_phentsize != sizeof(Elf_Phdr)) + report_fatal_error("Invalid program header size"); + return reinterpret_cast(base() + Header->e_phoff); + } - Elf_Phdr_Iter begin_program_headers() const { - return Elf_Phdr_Iter(Header->e_phentsize, - (const char*)base() + Header->e_phoff); + const Elf_Phdr *program_header_end() const { + return program_header_begin() + Header->e_phnum; } - Elf_Phdr_Iter end_program_headers() const { - return Elf_Phdr_Iter(Header->e_phentsize, - (const char*)base() + - Header->e_phoff + - (Header->e_phnum * Header->e_phentsize)); + typedef iterator_range Elf_Phdr_Range; + + const Elf_Phdr_Range program_headers() const { + return make_range(program_header_begin(), program_header_end()); } uint64_t getNumSections() const; uintX_t getStringTableIndex() const; - ELF::Elf64_Word getSymbolTableIndex(const Elf_Sym *symb) const; + ELF::Elf64_Word getExtendedSymbolTableIndex(const Elf_Sym *symb) const; const Elf_Ehdr *getHeader() const { return Header; } - const Elf_Shdr *getSection(const Elf_Sym *symb) const; - const Elf_Shdr *getSection(uint32_t Index) const; - const Elf_Sym *getSymbol(uint32_t index) const; - - ErrorOr getSymbolName(Elf_Sym_Iter Sym) const; - - /// \brief Get the name of \p Symb. - /// \param SymTab The symbol table section \p Symb is contained in. - /// \param Symb The symbol to get the name of. - /// - /// \p SymTab is used to lookup the string table to use to get the symbol's - /// name. - ErrorOr getSymbolName(const Elf_Shdr *SymTab, - const Elf_Sym *Symb) const; + ErrorOr getSection(const Elf_Sym *symb) const; + ErrorOr getSection(uint32_t Index) const; + + const Elf_Sym *getSymbol(const Elf_Shdr *Sec, uint32_t Index) const { + return &*(symbol_begin(Sec) + Index); + } + ErrorOr getSectionName(const Elf_Shdr *Section) const; - uint64_t getSymbolIndex(const Elf_Sym *sym) const; ErrorOr > getSectionContents(const Elf_Shdr *Sec) const; - StringRef getLoadName() const; }; -// Use an alignment of 2 for the typedefs since that is the worst case for -// ELF files in archives. -typedef ELFFile > ELF32LEFile; -typedef ELFFile > ELF64LEFile; -typedef ELFFile > ELF32BEFile; -typedef ELFFile > ELF64BEFile; +typedef ELFFile> ELF32LEFile; +typedef ELFFile> ELF64LEFile; +typedef ELFFile> ELF32BEFile; +typedef ELFFile> ELF64BEFile; // Iterate through the version definitions, and place each Elf_Verdef // in the VersionMap according to its index. @@ -492,7 +344,7 @@ void ELFFile::LoadVersionNeeds(const Elf_Shdr *sec) const { template void ELFFile::LoadVersionMap() const { // If there is no dynamic symtab or version table, there is nothing to do. - if (!DynSymRegion.Addr || !dot_gnu_version_sec) + if (!DotDynSymSec || !dot_gnu_version_sec) return; // Has the VersionMap already been loaded? @@ -512,28 +364,23 @@ void ELFFile::LoadVersionMap() const { } template -ELF::Elf64_Word ELFFile::getSymbolTableIndex(const Elf_Sym *symb) const { - if (symb->st_shndx == ELF::SHN_XINDEX) - return ExtendedSymbolTable.lookup(symb); - return symb->st_shndx; +ELF::Elf64_Word +ELFFile::getExtendedSymbolTableIndex(const Elf_Sym *symb) const { + assert(symb->st_shndx == ELF::SHN_XINDEX); + return ExtendedSymbolTable.lookup(symb); } template -const typename ELFFile::Elf_Shdr * +ErrorOr::Elf_Shdr *> ELFFile::getSection(const Elf_Sym *symb) const { - if (symb->st_shndx == ELF::SHN_XINDEX) + uint32_t Index = symb->st_shndx; + if (Index == ELF::SHN_XINDEX) return getSection(ExtendedSymbolTable.lookup(symb)); - if (symb->st_shndx >= ELF::SHN_LORESERVE) + if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE) return nullptr; return getSection(symb->st_shndx); } -template -const typename ELFFile::Elf_Sym * -ELFFile::getSymbol(uint32_t Index) const { - return &*(begin_symbols() + Index); -} - template ErrorOr > ELFFile::getSectionContents(const Elf_Shdr *Sec) const { @@ -586,20 +433,14 @@ std::pair::Elf_Shdr *, ELFFile::getRelocationSymbol(const Elf_Shdr *Sec, const RelT *Rel) const { if (!Sec->sh_link) return std::make_pair(nullptr, nullptr); - const Elf_Shdr *SymTable = getSection(Sec->sh_link); + ErrorOr SymTableOrErr = getSection(Sec->sh_link); + if (std::error_code EC = SymTableOrErr.getError()) + report_fatal_error(EC.message()); + const Elf_Shdr *SymTable = *SymTableOrErr; return std::make_pair( SymTable, getEntry(SymTable, Rel->getSymbol(isMips64EL()))); } -// Verify that the last byte in the string table in a null. -template -void ELFFile::VerifyStrTab(const Elf_Shdr *sh) const { - const char *strtab = (const char *)base() + sh->sh_offset; - if (strtab[sh->sh_size - 1] != 0) - // FIXME: Proper error handling. - report_fatal_error("String table must end with a null terminator!"); -} - template uint64_t ELFFile::getNumSections() const { assert(Header && "Header not initialized!"); @@ -622,17 +463,15 @@ typename ELFFile::uintX_t ELFFile::getStringTableIndex() const { } template -ELFFile::ELFFile(StringRef Object, std::error_code &ec) - : Buf(Object), SectionHeaderTable(nullptr), dot_shstrtab_sec(nullptr), - dot_strtab_sec(nullptr), dot_symtab_sec(nullptr), - SymbolTableSectionHeaderIndex(nullptr), dot_gnu_version_sec(nullptr), - dot_gnu_version_r_sec(nullptr), dot_gnu_version_d_sec(nullptr), - dt_soname(nullptr) { +ELFFile::ELFFile(StringRef Object, std::error_code &EC) + : Buf(Object) { const uint64_t FileSize = Buf.size(); - if (sizeof(Elf_Ehdr) > FileSize) - // FIXME: Proper error handling. - report_fatal_error("File too short!"); + if (sizeof(Elf_Ehdr) > FileSize) { + // File too short! + EC = object_error::parse_failed; + return; + } Header = reinterpret_cast(base()); @@ -641,203 +480,136 @@ ELFFile::ELFFile(StringRef Object, std::error_code &ec) const uint64_t SectionTableOffset = Header->e_shoff; - if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize) - // FIXME: Proper error handling. - report_fatal_error("Section header table goes past end of file!"); + if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize) { + // Section header table goes past end of file! + EC = object_error::parse_failed; + return; + } // The getNumSections() call below depends on SectionHeaderTable being set. SectionHeaderTable = reinterpret_cast(base() + SectionTableOffset); const uint64_t SectionTableSize = getNumSections() * Header->e_shentsize; - if (SectionTableOffset + SectionTableSize > FileSize) - // FIXME: Proper error handling. - report_fatal_error("Section table goes past end of file!"); + if (SectionTableOffset + SectionTableSize > FileSize) { + // Section table goes past end of file! + EC = object_error::parse_failed; + return; + } // Scan sections for special sections. for (const Elf_Shdr &Sec : sections()) { switch (Sec.sh_type) { case ELF::SHT_SYMTAB_SHNDX: - if (SymbolTableSectionHeaderIndex) - // FIXME: Proper error handling. - report_fatal_error("More than one .symtab_shndx!"); + if (SymbolTableSectionHeaderIndex) { + // More than one .symtab_shndx! + EC = object_error::parse_failed; + return; + } SymbolTableSectionHeaderIndex = &Sec; break; - case ELF::SHT_SYMTAB: - if (dot_symtab_sec) - // FIXME: Proper error handling. - report_fatal_error("More than one .symtab!"); + case ELF::SHT_SYMTAB: { + if (dot_symtab_sec) { + // More than one .symtab! + EC = object_error::parse_failed; + return; + } dot_symtab_sec = &Sec; - dot_strtab_sec = getSection(Sec.sh_link); - break; + ErrorOr SymtabOrErr = getStringTableForSymtab(Sec); + if ((EC = SymtabOrErr.getError())) + return; + DotStrtab = *SymtabOrErr; + } break; case ELF::SHT_DYNSYM: { - if (DynSymRegion.Addr) - // FIXME: Proper error handling. - report_fatal_error("More than one .dynsym!"); - DynSymRegion.Addr = base() + Sec.sh_offset; - DynSymRegion.Size = Sec.sh_size; - DynSymRegion.EntSize = Sec.sh_entsize; - const Elf_Shdr *DynStr = getSection(Sec.sh_link); - DynStrRegion.Addr = base() + DynStr->sh_offset; - DynStrRegion.Size = DynStr->sh_size; - DynStrRegion.EntSize = DynStr->sh_entsize; + if (DotDynSymSec) { + // More than one .dynsym! + EC = object_error::parse_failed; + return; + } + DotDynSymSec = &Sec; break; } - case ELF::SHT_DYNAMIC: - if (DynamicRegion.Addr) - // FIXME: Proper error handling. - report_fatal_error("More than one .dynamic!"); - DynamicRegion.Addr = base() + Sec.sh_offset; - DynamicRegion.Size = Sec.sh_size; - DynamicRegion.EntSize = Sec.sh_entsize; - break; case ELF::SHT_GNU_versym: - if (dot_gnu_version_sec != nullptr) - // FIXME: Proper error handling. - report_fatal_error("More than one .gnu.version section!"); + if (dot_gnu_version_sec != nullptr) { + // More than one .gnu.version section! + EC = object_error::parse_failed; + return; + } dot_gnu_version_sec = &Sec; break; case ELF::SHT_GNU_verdef: - if (dot_gnu_version_d_sec != nullptr) - // FIXME: Proper error handling. - report_fatal_error("More than one .gnu.version_d section!"); + if (dot_gnu_version_d_sec != nullptr) { + // More than one .gnu.version_d section! + EC = object_error::parse_failed; + return; + } dot_gnu_version_d_sec = &Sec; break; case ELF::SHT_GNU_verneed: - if (dot_gnu_version_r_sec != nullptr) - // FIXME: Proper error handling. - report_fatal_error("More than one .gnu.version_r section!"); + if (dot_gnu_version_r_sec != nullptr) { + // More than one .gnu.version_r section! + EC = object_error::parse_failed; + return; + } dot_gnu_version_r_sec = &Sec; break; } } // Get string table sections. - dot_shstrtab_sec = getSection(getStringTableIndex()); - if (dot_shstrtab_sec) { - // Verify that the last byte in the string table in a null. - VerifyStrTab(dot_shstrtab_sec); + uintX_t StringTableIndex = getStringTableIndex(); + if (StringTableIndex) { + ErrorOr StrTabSecOrErr = + getSection(getStringTableIndex()); + if ((EC = StrTabSecOrErr.getError())) + return; + + ErrorOr SymtabOrErr = getStringTable(*StrTabSecOrErr); + if ((EC = SymtabOrErr.getError())) + return; + DotShstrtab = *SymtabOrErr; } // Build symbol name side-mapping if there is one. if (SymbolTableSectionHeaderIndex) { const Elf_Word *ShndxTable = reinterpret_cast(base() + SymbolTableSectionHeaderIndex->sh_offset); - for (Elf_Sym_Iter SI = begin_symbols(), SE = end_symbols(); SI != SE; - ++SI) { + for (const Elf_Sym &S : symbols()) { if (*ShndxTable != ELF::SHN_UNDEF) - ExtendedSymbolTable[&*SI] = *ShndxTable; + ExtendedSymbolTable[&S] = *ShndxTable; ++ShndxTable; } } - // Scan program headers. - for (Elf_Phdr_Iter PhdrI = begin_program_headers(), - PhdrE = end_program_headers(); - PhdrI != PhdrE; ++PhdrI) { - if (PhdrI->p_type == ELF::PT_DYNAMIC) { - DynamicRegion.Addr = base() + PhdrI->p_offset; - DynamicRegion.Size = PhdrI->p_filesz; - DynamicRegion.EntSize = sizeof(Elf_Dyn); - break; - } - } - - ec = std::error_code(); -} - -// Get the symbol table index in the symtab section given a symbol -template -uint64_t ELFFile::getSymbolIndex(const Elf_Sym *Sym) const { - uintptr_t SymLoc = uintptr_t(Sym); - uintptr_t SymTabLoc = uintptr_t(base() + dot_symtab_sec->sh_offset); - assert(SymLoc > SymTabLoc && "Symbol not in symbol table!"); - uint64_t SymOffset = SymLoc - SymTabLoc; - assert(SymOffset % dot_symtab_sec->sh_entsize == 0 && - "Symbol not multiple of symbol size!"); - return SymOffset / dot_symtab_sec->sh_entsize; -} - -template -typename ELFFile::Elf_Shdr_Iter ELFFile::begin_sections() const { - return Elf_Shdr_Iter(Header->e_shentsize, - (const char *)base() + Header->e_shoff); + EC = std::error_code(); } template -typename ELFFile::Elf_Shdr_Iter ELFFile::end_sections() const { - return Elf_Shdr_Iter(Header->e_shentsize, - (const char *)base() + Header->e_shoff + - (getNumSections() * Header->e_shentsize)); +static bool compareAddr(uint64_t VAddr, const Elf_Phdr_Impl *Phdr) { + return VAddr < Phdr->p_vaddr; } template -typename ELFFile::Elf_Sym_Iter ELFFile::begin_symbols() const { - if (!dot_symtab_sec) - return Elf_Sym_Iter(0, nullptr, false); - return Elf_Sym_Iter(dot_symtab_sec->sh_entsize, - (const char *)base() + dot_symtab_sec->sh_offset, false); +const typename ELFFile::Elf_Shdr *ELFFile::section_begin() const { + if (Header->e_shentsize != sizeof(Elf_Shdr)) + report_fatal_error( + "Invalid section header entry size (e_shentsize) in ELF header"); + return reinterpret_cast(base() + Header->e_shoff); } template -typename ELFFile::Elf_Sym_Iter ELFFile::end_symbols() const { - if (!dot_symtab_sec) - return Elf_Sym_Iter(0, nullptr, false); - return Elf_Sym_Iter(dot_symtab_sec->sh_entsize, - (const char *)base() + dot_symtab_sec->sh_offset + - dot_symtab_sec->sh_size, - false); -} - -template -typename ELFFile::Elf_Dyn_Iter -ELFFile::begin_dynamic_table() const { - if (DynamicRegion.Addr) - return Elf_Dyn_Iter(DynamicRegion.EntSize, - (const char *)DynamicRegion.Addr); - return Elf_Dyn_Iter(0, nullptr); -} - -template -typename ELFFile::Elf_Dyn_Iter -ELFFile::end_dynamic_table(bool NULLEnd) const { - if (!DynamicRegion.Addr) - return Elf_Dyn_Iter(0, nullptr); - Elf_Dyn_Iter Ret(DynamicRegion.EntSize, - (const char *)DynamicRegion.Addr + DynamicRegion.Size); - - if (NULLEnd) { - Elf_Dyn_Iter Start = begin_dynamic_table(); - while (Start != Ret && Start->getTag() != ELF::DT_NULL) - ++Start; - - // Include the DT_NULL. - if (Start != Ret) - ++Start; - Ret = Start; - } - return Ret; -} - -template -StringRef ELFFile::getLoadName() const { - if (!dt_soname) { - dt_soname = ""; - // Find the DT_SONAME entry - for (const auto &Entry : dynamic_table()) - if (Entry.getTag() == ELF::DT_SONAME) { - dt_soname = getDynamicString(Entry.getVal()); - break; - } - } - return dt_soname; +const typename ELFFile::Elf_Shdr *ELFFile::section_end() const { + return section_begin() + getNumSections(); } template template const T *ELFFile::getEntry(uint32_t Section, uint32_t Entry) const { - return getEntry(getSection(Section), Entry); + ErrorOr Sec = getSection(Section); + if (std::error_code EC = Sec.getError()) + report_fatal_error(EC.message()); + return getEntry(*Sec, Entry); } template @@ -849,103 +621,58 @@ const T *ELFFile::getEntry(const Elf_Shdr *Section, } template -const typename ELFFile::Elf_Shdr * -ELFFile::getSection(uint32_t index) const { - if (index == 0) - return nullptr; - if (!SectionHeaderTable || index >= getNumSections()) - // FIXME: Proper error handling. - report_fatal_error("Invalid section index!"); +ErrorOr::Elf_Shdr *> +ELFFile::getSection(uint32_t Index) const { + assert(SectionHeaderTable && "SectionHeaderTable not initialized!"); + if (Index >= getNumSections()) + return object_error::invalid_section_index; return reinterpret_cast( - reinterpret_cast(SectionHeaderTable) - + (index * Header->e_shentsize)); -} - -template -const char *ELFFile::getString(uint32_t section, - ELF::Elf32_Word offset) const { - return getString(getSection(section), offset); + reinterpret_cast(SectionHeaderTable) + + (Index * Header->e_shentsize)); } template -const char *ELFFile::getString(const Elf_Shdr *section, - ELF::Elf32_Word offset) const { - assert(section && section->sh_type == ELF::SHT_STRTAB && "Invalid section!"); - if (offset >= section->sh_size) - // FIXME: Proper error handling. - report_fatal_error("Symbol name offset outside of string table!"); - return (const char *)base() + section->sh_offset + offset; -} - -template -const char *ELFFile::getDynamicString(uintX_t Offset) const { - if (!DynStrRegion.Addr || Offset >= DynStrRegion.Size) - return nullptr; - return (const char *)DynStrRegion.Addr + Offset; -} - -template -ErrorOr ELFFile::getSymbolName(Elf_Sym_Iter Sym) const { - if (!Sym.isDynamic()) - return getSymbolName(dot_symtab_sec, &*Sym); - - if (!DynStrRegion.Addr || Sym->st_name >= DynStrRegion.Size) +ErrorOr +ELFFile::getStringTable(const Elf_Shdr *Section) const { + if (Section->sh_type != ELF::SHT_STRTAB) + return object_error::parse_failed; + uint64_t Offset = Section->sh_offset; + uint64_t Size = Section->sh_size; + if (Offset + Size > Buf.size()) return object_error::parse_failed; - return StringRef(getDynamicString(Sym->st_name)); + StringRef Data((const char *)base() + Section->sh_offset, Size); + if (Data[Size - 1] != '\0') + return object_error::string_table_non_null_end; + return Data; } template -ErrorOr ELFFile::getSymbolName(const Elf_Shdr *Section, - const Elf_Sym *Symb) const { - if (Symb->st_name == 0) { - const Elf_Shdr *ContainingSec = getSection(Symb); - if (ContainingSec) - return getSectionName(ContainingSec); - } - - const Elf_Shdr *StrTab = getSection(Section->sh_link); - if (Symb->st_name >= StrTab->sh_size) +ErrorOr +ELFFile::getStringTableForSymtab(const Elf_Shdr &Sec) const { + if (Sec.sh_type != ELF::SHT_SYMTAB && Sec.sh_type != ELF::SHT_DYNSYM) return object_error::parse_failed; - return StringRef(getString(StrTab, Symb->st_name)); + ErrorOr SectionOrErr = getSection(Sec.sh_link); + if (std::error_code EC = SectionOrErr.getError()) + return EC; + return getStringTable(*SectionOrErr); } template ErrorOr ELFFile::getSectionName(const Elf_Shdr *Section) const { - if (Section->sh_name >= dot_shstrtab_sec->sh_size) + uint32_t Offset = Section->sh_name; + if (Offset == 0) + return StringRef(); + if (Offset >= DotShstrtab.size()) return object_error::parse_failed; - return StringRef(getString(dot_shstrtab_sec, Section->sh_name)); + return StringRef(DotShstrtab.data() + Offset); } template -ErrorOr ELFFile::getSymbolVersion(const Elf_Shdr *section, +ErrorOr ELFFile::getSymbolVersion(StringRef StrTab, const Elf_Sym *symb, bool &IsDefault) const { - // Handle non-dynamic symbols. - if (section != DynSymRegion.Addr && section != nullptr) { - // Non-dynamic symbols can have versions in their names - // A name of the form 'foo@V1' indicates version 'V1', non-default. - // A name of the form 'foo@@V2' indicates version 'V2', default version. - ErrorOr SymName = getSymbolName(section, symb); - if (!SymName) - return SymName; - StringRef Name = *SymName; - size_t atpos = Name.find('@'); - if (atpos == StringRef::npos) { - IsDefault = false; - return StringRef(""); - } - ++atpos; - if (atpos < Name.size() && Name[atpos] == '@') { - IsDefault = true; - ++atpos; - } else { - IsDefault = false; - } - return Name.substr(atpos); - } - // This is a dynamic symbol. Look in the GNU symbol version table. if (!dot_gnu_version_sec) { // No version table. @@ -954,8 +681,10 @@ ErrorOr ELFFile::getSymbolVersion(const Elf_Shdr *section, } // Determine the position in the symbol table of this entry. - size_t entry_index = ((const char *)symb - (const char *)DynSymRegion.Addr) / - DynSymRegion.EntSize; + size_t entry_index = + (reinterpret_cast(symb) - DotDynSymSec->sh_offset - + reinterpret_cast(base())) / + sizeof(Elf_Sym); // Get the corresponding version index entry const Elf_Versym *vs = getEntry(dot_gnu_version_sec, entry_index); @@ -990,9 +719,9 @@ ErrorOr ELFFile::getSymbolVersion(const Elf_Shdr *section, IsDefault = false; } - if (name_offset >= DynStrRegion.Size) + if (name_offset >= StrTab.size()) return object_error::parse_failed; - return StringRef(getDynamicString(name_offset)); + return StringRef(StrTab.data() + name_offset); } /// This function returns the hash value for a symbol in the .dynsym section diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index e7eba976fd4..2a870bdbca9 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -35,26 +35,148 @@ namespace llvm { namespace object { +class elf_symbol_iterator; +class ELFSymbolRef; +class ELFRelocationRef; + class ELFObjectFileBase : public ObjectFile { + friend class ELFSymbolRef; + friend class ELFSectionRef; + friend class ELFRelocationRef; + protected: ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source); + virtual uint64_t getSymbolSize(DataRefImpl Symb) const = 0; + virtual uint8_t getSymbolOther(DataRefImpl Symb) const = 0; + virtual uint8_t getSymbolELFType(DataRefImpl Symb) const = 0; + + virtual uint32_t getSectionType(DataRefImpl Sec) const = 0; + virtual uint64_t getSectionFlags(DataRefImpl Sec) const = 0; + + virtual ErrorOr getRelocationAddend(DataRefImpl Rel) const = 0; public: - virtual std::error_code getRelocationAddend(DataRefImpl Rel, - int64_t &Res) const = 0; - virtual std::pair - getELFDynamicSymbolIterators() const = 0; - virtual std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, - bool &IsDefault) const = 0; + typedef iterator_range elf_symbol_iterator_range; + virtual elf_symbol_iterator_range getDynamicSymbolIterators() const = 0; - virtual uint64_t getSectionFlags(SectionRef Sec) const = 0; - virtual uint32_t getSectionType(SectionRef Sec) const = 0; + elf_symbol_iterator_range symbols() const; static inline bool classof(const Binary *v) { return v->isELF(); } }; +class ELFSectionRef : public SectionRef { +public: + ELFSectionRef(const SectionRef &B) : SectionRef(B) { + assert(isa(SectionRef::getObject())); + } + + const ELFObjectFileBase *getObject() const { + return cast(SectionRef::getObject()); + } + + uint32_t getType() const { + return getObject()->getSectionType(getRawDataRefImpl()); + } + + uint64_t getFlags() const { + return getObject()->getSectionFlags(getRawDataRefImpl()); + } +}; + +class elf_section_iterator : public section_iterator { +public: + elf_section_iterator(const section_iterator &B) : section_iterator(B) { + assert(isa(B->getObject())); + } + + const ELFSectionRef *operator->() const { + return static_cast(section_iterator::operator->()); + } + + const ELFSectionRef &operator*() const { + return static_cast(section_iterator::operator*()); + } +}; + +class ELFSymbolRef : public SymbolRef { +public: + ELFSymbolRef(const SymbolRef &B) : SymbolRef(B) { + assert(isa(SymbolRef::getObject())); + } + + const ELFObjectFileBase *getObject() const { + return cast(BasicSymbolRef::getObject()); + } + + uint64_t getSize() const { + return getObject()->getSymbolSize(getRawDataRefImpl()); + } + + uint8_t getOther() const { + return getObject()->getSymbolOther(getRawDataRefImpl()); + } + + uint8_t getELFType() const { + return getObject()->getSymbolELFType(getRawDataRefImpl()); + } +}; + +class elf_symbol_iterator : public symbol_iterator { +public: + elf_symbol_iterator(const basic_symbol_iterator &B) + : symbol_iterator(SymbolRef(B->getRawDataRefImpl(), + cast(B->getObject()))) {} + + const ELFSymbolRef *operator->() const { + return static_cast(symbol_iterator::operator->()); + } + + const ELFSymbolRef &operator*() const { + return static_cast(symbol_iterator::operator*()); + } +}; + +class ELFRelocationRef : public RelocationRef { +public: + ELFRelocationRef(const RelocationRef &B) : RelocationRef(B) { + assert(isa(RelocationRef::getObject())); + } + + const ELFObjectFileBase *getObject() const { + return cast(RelocationRef::getObject()); + } + + ErrorOr getAddend() const { + return getObject()->getRelocationAddend(getRawDataRefImpl()); + } +}; + +class elf_relocation_iterator : public relocation_iterator { +public: + elf_relocation_iterator(const relocation_iterator &B) + : relocation_iterator(RelocationRef( + B->getRawDataRefImpl(), cast(B->getObject()))) {} + + const ELFRelocationRef *operator->() const { + return static_cast( + relocation_iterator::operator->()); + } + + const ELFRelocationRef &operator*() const { + return static_cast( + relocation_iterator::operator*()); + } +}; + +inline ELFObjectFileBase::elf_symbol_iterator_range +ELFObjectFileBase::symbols() const { + return elf_symbol_iterator_range(symbol_begin(), symbol_end()); +} + template class ELFObjectFile : public ELFObjectFileBase { + uint64_t getSymbolSize(DataRefImpl Sym) const override; + public: LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) @@ -67,25 +189,20 @@ template class ELFObjectFile : public ELFObjectFileBase { typedef typename ELFFile::Elf_Rela Elf_Rela; typedef typename ELFFile::Elf_Dyn Elf_Dyn; - typedef typename ELFFile::Elf_Sym_Iter Elf_Sym_Iter; - typedef typename ELFFile::Elf_Shdr_Iter Elf_Shdr_Iter; - typedef typename ELFFile::Elf_Dyn_Iter Elf_Dyn_Iter; - protected: ELFFile EF; void moveSymbolNext(DataRefImpl &Symb) const override; - std::error_code getSymbolName(DataRefImpl Symb, - StringRef &Res) const override; - std::error_code getSymbolAddress(DataRefImpl Symb, - uint64_t &Res) const override; - std::error_code getSymbolAlignment(DataRefImpl Symb, - uint32_t &Res) const override; - std::error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; + ErrorOr getSymbolName(DataRefImpl Symb) const override; + ErrorOr getSymbolAddress(DataRefImpl Symb) const override; + uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; + uint32_t getSymbolAlignment(DataRefImpl Symb) const override; + uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; - std::error_code getSymbolOther(DataRefImpl Symb, uint8_t &Res) const override; - std::error_code getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const override; + uint8_t getSymbolOther(DataRefImpl Symb) const override; + uint8_t getSymbolELFType(DataRefImpl Symb) const override; + SymbolRef::Type getSymbolType(DataRefImpl Symb) const override; + section_iterator getSymbolSection(const Elf_Sym *Symb) const; std::error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const override; @@ -101,79 +218,62 @@ template class ELFObjectFile : public ELFObjectFileBase { bool isSectionData(DataRefImpl Sec) const override; bool isSectionBSS(DataRefImpl Sec) const override; bool isSectionVirtual(DataRefImpl Sec) const override; - bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; section_iterator getRelocatedSection(DataRefImpl Sec) const override; void moveRelocationNext(DataRefImpl &Rel) const override; - std::error_code getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const override; - std::error_code getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const override; + uint64_t getRelocationOffset(DataRefImpl Rel) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; - std::error_code getRelocationType(DataRefImpl Rel, - uint64_t &Res) const override; - std::error_code - getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl &Result) const override; - std::error_code - getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const override; - - uint64_t getROffset(DataRefImpl Rel) const; + uint64_t getRelocationType(DataRefImpl Rel) const override; + void getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl &Result) const override; + + uint32_t getSectionType(DataRefImpl Sec) const override; + uint64_t getSectionFlags(DataRefImpl Sec) const override; StringRef getRelocationTypeName(uint32_t Type) const; /// \brief Get the relocation section that contains \a Rel. const Elf_Shdr *getRelSection(DataRefImpl Rel) const { - return EF.getSection(Rel.d.a); + return *EF.getSection(Rel.d.a); } - const Elf_Rel *getRel(DataRefImpl Rel) const; - const Elf_Rela *getRela(DataRefImpl Rela) const; - - Elf_Sym_Iter toELFSymIter(DataRefImpl Symb) const { - bool IsDynamic = Symb.p & 1; - if (IsDynamic) - return Elf_Sym_Iter( - EF.begin_dynamic_symbols().getEntSize(), - reinterpret_cast(Symb.p & ~uintptr_t(1)), IsDynamic); - return Elf_Sym_Iter(EF.begin_symbols().getEntSize(), - reinterpret_cast(Symb.p), IsDynamic); + const Elf_Sym *toELFSymIter(DataRefImpl Sym) const { + return EF.template getEntry(Sym.d.a, Sym.d.b); } - DataRefImpl toDRI(Elf_Sym_Iter Symb) const { + DataRefImpl toDRI(const Elf_Shdr *SymTable, unsigned SymbolNum) const { DataRefImpl DRI; - DRI.p = reinterpret_cast(Symb.get()) | - static_cast(Symb.isDynamic()); - return DRI; - } + if (!SymTable) { + DRI.d.a = 0; + DRI.d.b = 0; + return DRI; + } + assert(SymTable->sh_type == ELF::SHT_SYMTAB || + SymTable->sh_type == ELF::SHT_DYNSYM); - Elf_Shdr_Iter toELFShdrIter(DataRefImpl Sec) const { - return Elf_Shdr_Iter(EF.getHeader()->e_shentsize, - reinterpret_cast(Sec.p)); - } + uintptr_t SHT = reinterpret_cast(EF.section_begin()); + unsigned SymTableIndex = + (reinterpret_cast(SymTable) - SHT) / sizeof(Elf_Shdr); - DataRefImpl toDRI(Elf_Shdr_Iter Sec) const { - DataRefImpl DRI; - DRI.p = reinterpret_cast(Sec.get()); + DRI.d.a = SymTableIndex; + DRI.d.b = SymbolNum; return DRI; } + const Elf_Shdr *toELFShdrIter(DataRefImpl Sec) const { + return reinterpret_cast(Sec.p); + } + DataRefImpl toDRI(const Elf_Shdr *Sec) const { DataRefImpl DRI; DRI.p = reinterpret_cast(Sec); return DRI; } - Elf_Dyn_Iter toELFDynIter(DataRefImpl Dyn) const { - return Elf_Dyn_Iter(EF.begin_dynamic_table().getEntSize(), - reinterpret_cast(Dyn.p)); - } - - DataRefImpl toDRI(Elf_Dyn_Iter Dyn) const { + DataRefImpl toDRI(const Elf_Dyn *Dyn) const { DataRefImpl DRI; - DRI.p = reinterpret_cast(Dyn.get()); + DRI.p = reinterpret_cast(Dyn); return DRI; } @@ -199,33 +299,29 @@ template class ELFObjectFile : public ELFObjectFileBase { public: ELFObjectFile(MemoryBufferRef Object, std::error_code &EC); + const Elf_Rel *getRel(DataRefImpl Rel) const; + const Elf_Rela *getRela(DataRefImpl Rela) const; + const Elf_Sym *getSymbol(DataRefImpl Symb) const; basic_symbol_iterator symbol_begin_impl() const override; basic_symbol_iterator symbol_end_impl() const override; - symbol_iterator dynamic_symbol_begin() const; - symbol_iterator dynamic_symbol_end() const; + elf_symbol_iterator dynamic_symbol_begin() const; + elf_symbol_iterator dynamic_symbol_end() const; section_iterator section_begin() const override; section_iterator section_end() const override; - std::error_code getRelocationAddend(DataRefImpl Rel, - int64_t &Res) const override; - std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, - bool &IsDefault) const override; - - uint64_t getSectionFlags(SectionRef Sec) const override; - uint32_t getSectionType(SectionRef Sec) const override; + ErrorOr getRelocationAddend(DataRefImpl Rel) const override; uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; unsigned getArch() const override; - StringRef getLoadName() const; std::error_code getPlatformFlags(unsigned &Result) const override { Result = EF.getHeader()->e_flags; - return object_error::success; + return std::error_code(); } const ELFFile *getELFFile() const { return &EF; } @@ -236,153 +332,135 @@ template class ELFObjectFile : public ELFObjectFileBase { ELFT::Is64Bits); } - std::pair - getELFDynamicSymbolIterators() const override; + elf_symbol_iterator_range getDynamicSymbolIterators() const override; bool isRelocatableObject() const override; }; -// Use an alignment of 2 for the typedefs since that is the worst case for -// ELF files in archives. -typedef ELFObjectFile > ELF32LEObjectFile; -typedef ELFObjectFile > ELF64LEObjectFile; -typedef ELFObjectFile > ELF32BEObjectFile; -typedef ELFObjectFile > ELF64BEObjectFile; +typedef ELFObjectFile> ELF32LEObjectFile; +typedef ELFObjectFile> ELF64LEObjectFile; +typedef ELFObjectFile> ELF32BEObjectFile; +typedef ELFObjectFile> ELF64BEObjectFile; template -void ELFObjectFile::moveSymbolNext(DataRefImpl &Symb) const { - Symb = toDRI(++toELFSymIter(Symb)); +void ELFObjectFile::moveSymbolNext(DataRefImpl &Sym) const { + ++Sym.d.b; } template -std::error_code ELFObjectFile::getSymbolName(DataRefImpl Symb, - StringRef &Result) const { - ErrorOr Name = EF.getSymbolName(toELFSymIter(Symb)); - if (!Name) - return Name.getError(); - Result = *Name; - return object_error::success; +ErrorOr ELFObjectFile::getSymbolName(DataRefImpl Sym) const { + const Elf_Sym *ESym = toELFSymIter(Sym); + const Elf_Shdr *SymTableSec = *EF.getSection(Sym.d.a); + const Elf_Shdr *StringTableSec = *EF.getSection(SymTableSec->sh_link); + StringRef SymTable = *EF.getStringTable(StringTableSec); + return ESym->getName(SymTable); } template -std::error_code ELFObjectFile::getSymbolVersion(SymbolRef SymRef, - StringRef &Version, - bool &IsDefault) const { - DataRefImpl Symb = SymRef.getRawDataRefImpl(); - const Elf_Sym *symb = getSymbol(Symb); - ErrorOr Ver = - EF.getSymbolVersion(EF.getSection(Symb.d.b), symb, IsDefault); - if (!Ver) - return Ver.getError(); - Version = *Ver; - return object_error::success; +uint64_t ELFObjectFile::getSectionFlags(DataRefImpl Sec) const { + return toELFShdrIter(Sec)->sh_flags; } template -uint64_t ELFObjectFile::getSectionFlags(SectionRef Sec) const { - DataRefImpl DRI = Sec.getRawDataRefImpl(); - return toELFShdrIter(DRI)->sh_flags; +uint32_t ELFObjectFile::getSectionType(DataRefImpl Sec) const { + return toELFShdrIter(Sec)->sh_type; } template -uint32_t ELFObjectFile::getSectionType(SectionRef Sec) const { - DataRefImpl DRI = Sec.getRawDataRefImpl(); - return toELFShdrIter(DRI)->sh_type; +uint64_t ELFObjectFile::getSymbolValueImpl(DataRefImpl Symb) const { + const Elf_Sym *ESym = getSymbol(Symb); + uint64_t Ret = ESym->st_value; + if (ESym->st_shndx == ELF::SHN_ABS) + return Ret; + + const Elf_Ehdr *Header = EF.getHeader(); + // Clear the ARM/Thumb or microMIPS indicator flag. + if ((Header->e_machine == ELF::EM_ARM || Header->e_machine == ELF::EM_MIPS) && + ESym->getType() == ELF::STT_FUNC) + Ret &= ~1; + + return Ret; } template -std::error_code ELFObjectFile::getSymbolAddress(DataRefImpl Symb, - uint64_t &Result) const { +ErrorOr +ELFObjectFile::getSymbolAddress(DataRefImpl Symb) const { + uint64_t Result = getSymbolValue(Symb); const Elf_Sym *ESym = getSymbol(Symb); - switch (EF.getSymbolTableIndex(ESym)) { + switch (ESym->st_shndx) { case ELF::SHN_COMMON: case ELF::SHN_UNDEF: - Result = UnknownAddressOrSize; - return object_error::success; case ELF::SHN_ABS: - Result = ESym->st_value; - return object_error::success; - default: - break; + return Result; } const Elf_Ehdr *Header = EF.getHeader(); - Result = ESym->st_value; - - // Clear the ARM/Thumb or microMIPS indicator flag. - if ((Header->e_machine == ELF::EM_ARM || Header->e_machine == ELF::EM_MIPS) && - ESym->getType() == ELF::STT_FUNC) - Result &= ~1; if (Header->e_type == ELF::ET_REL) { - const typename ELFFile::Elf_Shdr * Section = EF.getSection(ESym); - if (Section != nullptr) + ErrorOr SectionOrErr = EF.getSection(ESym); + if (std::error_code EC = SectionOrErr.getError()) + return EC; + const Elf_Shdr *Section = *SectionOrErr; + if (Section) Result += Section->sh_addr; } - return object_error::success; + return Result; } template -std::error_code ELFObjectFile::getSymbolAlignment(DataRefImpl Symb, - uint32_t &Res) const { - Elf_Sym_Iter Sym = toELFSymIter(Symb); +uint32_t ELFObjectFile::getSymbolAlignment(DataRefImpl Symb) const { + const Elf_Sym *Sym = toELFSymIter(Symb); if (Sym->st_shndx == ELF::SHN_COMMON) - Res = Sym->st_value; - else - Res = 0; - return object_error::success; + return Sym->st_value; + return 0; } template -std::error_code ELFObjectFile::getSymbolSize(DataRefImpl Symb, - uint64_t &Result) const { - Result = toELFSymIter(Symb)->st_size; - return object_error::success; +uint64_t ELFObjectFile::getSymbolSize(DataRefImpl Sym) const { + return toELFSymIter(Sym)->st_size; } template -std::error_code ELFObjectFile::getSymbolOther(DataRefImpl Symb, - uint8_t &Result) const { - Result = toELFSymIter(Symb)->st_other; - return object_error::success; +uint64_t ELFObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const { + return toELFSymIter(Symb)->st_size; } template -std::error_code -ELFObjectFile::getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Result) const { +uint8_t ELFObjectFile::getSymbolOther(DataRefImpl Symb) const { + return toELFSymIter(Symb)->st_other; +} + +template +uint8_t ELFObjectFile::getSymbolELFType(DataRefImpl Symb) const { + return toELFSymIter(Symb)->getType(); +} + +template +SymbolRef::Type ELFObjectFile::getSymbolType(DataRefImpl Symb) const { const Elf_Sym *ESym = getSymbol(Symb); switch (ESym->getType()) { case ELF::STT_NOTYPE: - Result = SymbolRef::ST_Unknown; - break; + return SymbolRef::ST_Unknown; case ELF::STT_SECTION: - Result = SymbolRef::ST_Debug; - break; + return SymbolRef::ST_Debug; case ELF::STT_FILE: - Result = SymbolRef::ST_File; - break; + return SymbolRef::ST_File; case ELF::STT_FUNC: - Result = SymbolRef::ST_Function; - break; + return SymbolRef::ST_Function; case ELF::STT_OBJECT: case ELF::STT_COMMON: case ELF::STT_TLS: - Result = SymbolRef::ST_Data; - break; + return SymbolRef::ST_Data; default: - Result = SymbolRef::ST_Other; - break; + return SymbolRef::ST_Other; } - return object_error::success; } template -uint32_t ELFObjectFile::getSymbolFlags(DataRefImpl Symb) const { - Elf_Sym_Iter EIter = toELFSymIter(Symb); - const Elf_Sym *ESym = &*EIter; +uint32_t ELFObjectFile::getSymbolFlags(DataRefImpl Sym) const { + const Elf_Sym *ESym = toELFSymIter(Sym); uint32_t Result = SymbolRef::SF_None; @@ -396,41 +474,61 @@ uint32_t ELFObjectFile::getSymbolFlags(DataRefImpl Symb) const { Result |= SymbolRef::SF_Absolute; if (ESym->getType() == ELF::STT_FILE || ESym->getType() == ELF::STT_SECTION || - EIter == EF.begin_symbols() || EIter == EF.begin_dynamic_symbols()) + ESym == EF.symbol_begin() || ESym == EF.dynamic_symbol_begin()) Result |= SymbolRef::SF_FormatSpecific; - if (EF.getSymbolTableIndex(ESym) == ELF::SHN_UNDEF) + if (EF.getHeader()->e_machine == ELF::EM_ARM) { + if (ErrorOr NameOrErr = getSymbolName(Sym)) { + StringRef Name = *NameOrErr; + if (Name.startswith("$d") || Name.startswith("$t") || + Name.startswith("$a")) + Result |= SymbolRef::SF_FormatSpecific; + } + } + + if (ESym->st_shndx == ELF::SHN_UNDEF) Result |= SymbolRef::SF_Undefined; - if (ESym->getType() == ELF::STT_COMMON || - EF.getSymbolTableIndex(ESym) == ELF::SHN_COMMON) + if (ESym->getType() == ELF::STT_COMMON || ESym->st_shndx == ELF::SHN_COMMON) Result |= SymbolRef::SF_Common; if (isExportedToOtherDSO(ESym)) Result |= SymbolRef::SF_Exported; + if (ESym->getVisibility() == ELF::STV_HIDDEN) + Result |= SymbolRef::SF_Hidden; + return Result; } +template +section_iterator +ELFObjectFile::getSymbolSection(const Elf_Sym *ESym) const { + ErrorOr ESecOrErr = EF.getSection(ESym); + if (std::error_code EC = ESecOrErr.getError()) + report_fatal_error(EC.message()); + + const Elf_Shdr *ESec = *ESecOrErr; + if (!ESec) + return section_end(); + + DataRefImpl Sec; + Sec.p = reinterpret_cast(ESec); + return section_iterator(SectionRef(Sec, this)); +} + template std::error_code ELFObjectFile::getSymbolSection(DataRefImpl Symb, section_iterator &Res) const { - const Elf_Sym *ESym = getSymbol(Symb); - const Elf_Shdr *ESec = EF.getSection(ESym); - if (!ESec) - Res = section_end(); - else { - DataRefImpl Sec; - Sec.p = reinterpret_cast(ESec); - Res = section_iterator(SectionRef(Sec, this)); - } - return object_error::success; + Res = getSymbolSection(getSymbol(Symb)); + return std::error_code(); } template void ELFObjectFile::moveSectionNext(DataRefImpl &Sec) const { - Sec = toDRI(++toELFShdrIter(Sec)); + const Elf_Shdr *ESec = toELFShdrIter(Sec); + Sec = toDRI(++ESec); } template @@ -440,7 +538,7 @@ std::error_code ELFObjectFile::getSectionName(DataRefImpl Sec, if (!Name) return Name.getError(); Result = *Name; - return object_error::success; + return std::error_code(); } template @@ -457,9 +555,9 @@ template std::error_code ELFObjectFile::getSectionContents(DataRefImpl Sec, StringRef &Result) const { - Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + const Elf_Shdr *EShdr = toELFShdrIter(Sec); Result = StringRef((const char *)base() + EShdr->sh_offset, EShdr->sh_size); - return object_error::success; + return std::error_code(); } template @@ -474,14 +572,14 @@ bool ELFObjectFile::isSectionText(DataRefImpl Sec) const { template bool ELFObjectFile::isSectionData(DataRefImpl Sec) const { - Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + const Elf_Shdr *EShdr = toELFShdrIter(Sec); return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && EShdr->sh_type == ELF::SHT_PROGBITS; } template bool ELFObjectFile::isSectionBSS(DataRefImpl Sec) const { - Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + const Elf_Shdr *EShdr = toELFShdrIter(Sec); return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && EShdr->sh_type == ELF::SHT_NOBITS; } @@ -491,39 +589,41 @@ bool ELFObjectFile::isSectionVirtual(DataRefImpl Sec) const { return toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; } -template -bool ELFObjectFile::sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb) const { - Elf_Sym_Iter ESym = toELFSymIter(Symb); - - uintX_t Index = ESym->st_shndx; - bool Reserved = Index >= ELF::SHN_LORESERVE && Index <= ELF::SHN_HIRESERVE; - - return !Reserved && (&*toELFShdrIter(Sec) == EF.getSection(ESym->st_shndx)); -} - template relocation_iterator ELFObjectFile::section_rel_begin(DataRefImpl Sec) const { DataRefImpl RelData; - uintptr_t SHT = reinterpret_cast(EF.begin_sections().get()); + uintptr_t SHT = reinterpret_cast(EF.section_begin()); RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize; RelData.d.b = 0; + + const Elf_Shdr *S = reinterpret_cast(Sec.p); + if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL) + return relocation_iterator(RelocationRef(RelData, this)); + + const Elf_Shdr *RelSec = getRelSection(RelData); + ErrorOr SymSecOrErr = EF.getSection(RelSec->sh_link); + if (std::error_code EC = SymSecOrErr.getError()) + report_fatal_error(EC.message()); + const Elf_Shdr *SymSec = *SymSecOrErr; + uint32_t SymSecType = SymSec->sh_type; + if (SymSecType != ELF::SHT_SYMTAB && SymSecType != ELF::SHT_DYNSYM) + report_fatal_error("Invalid symbol table section type!"); + if (SymSecType == ELF::SHT_DYNSYM) + RelData.d.b = 1; + return relocation_iterator(RelocationRef(RelData, this)); } template relocation_iterator ELFObjectFile::section_rel_end(DataRefImpl Sec) const { - DataRefImpl RelData; - uintptr_t SHT = reinterpret_cast(EF.begin_sections().get()); const Elf_Shdr *S = reinterpret_cast(Sec.p); - RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize; + relocation_iterator Begin = section_rel_begin(Sec); if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL) - RelData.d.b = 0; - else - RelData.d.b = S->sh_size / S->sh_entsize; - + return Begin; + DataRefImpl RelData = Begin->getRawDataRefImpl(); + RelData.d.b += (S->sh_size / S->sh_entsize) << 1; return relocation_iterator(RelocationRef(RelData, this)); } @@ -533,19 +633,21 @@ ELFObjectFile::getRelocatedSection(DataRefImpl Sec) const { if (EF.getHeader()->e_type != ELF::ET_REL) return section_end(); - Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); + const Elf_Shdr *EShdr = toELFShdrIter(Sec); uintX_t Type = EShdr->sh_type; if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA) return section_end(); - const Elf_Shdr *R = EF.getSection(EShdr->sh_info); - return section_iterator(SectionRef(toDRI(R), this)); + ErrorOr R = EF.getSection(EShdr->sh_info); + if (std::error_code EC = R.getError()) + report_fatal_error(EC.message()); + return section_iterator(SectionRef(toDRI(*R), this)); } // Relocations template void ELFObjectFile::moveRelocationNext(DataRefImpl &Rel) const { - ++Rel.d.b; + Rel.d.b += 2; } template @@ -553,96 +655,40 @@ symbol_iterator ELFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { uint32_t symbolIdx; const Elf_Shdr *sec = getRelSection(Rel); - switch (sec->sh_type) { - default: - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL: { + if (sec->sh_type == ELF::SHT_REL) symbolIdx = getRel(Rel)->getSymbol(EF.isMips64EL()); - break; - } - case ELF::SHT_RELA: { + else symbolIdx = getRela(Rel)->getSymbol(EF.isMips64EL()); - break; - } - } if (!symbolIdx) return symbol_end(); - const Elf_Shdr *SymSec = EF.getSection(sec->sh_link); - + bool IsDyn = Rel.d.b & 1; DataRefImpl SymbolData; - switch (SymSec->sh_type) { - default: - report_fatal_error("Invalid symbol table section type!"); - case ELF::SHT_SYMTAB: - SymbolData = toDRI(EF.begin_symbols() + symbolIdx); - break; - case ELF::SHT_DYNSYM: - SymbolData = toDRI(EF.begin_dynamic_symbols() + symbolIdx); - break; - } - + if (IsDyn) + SymbolData = toDRI(EF.getDotDynSymSec(), symbolIdx); + else + SymbolData = toDRI(EF.getDotSymtabSec(), symbolIdx); return symbol_iterator(SymbolRef(SymbolData, this)); } template -std::error_code -ELFObjectFile::getRelocationAddress(DataRefImpl Rel, - uint64_t &Result) const { - uint64_t ROffset = getROffset(Rel); - const Elf_Ehdr *Header = EF.getHeader(); - - if (Header->e_type == ELF::ET_REL) { - const Elf_Shdr *RelocationSec = getRelSection(Rel); - const Elf_Shdr *RelocatedSec = EF.getSection(RelocationSec->sh_info); - Result = ROffset + RelocatedSec->sh_addr; - } else { - Result = ROffset; - } - - return object_error::success; -} - -template -std::error_code -ELFObjectFile::getRelocationOffset(DataRefImpl Rel, - uint64_t &Result) const { +uint64_t ELFObjectFile::getRelocationOffset(DataRefImpl Rel) const { assert(EF.getHeader()->e_type == ELF::ET_REL && "Only relocatable object files have relocation offsets"); - Result = getROffset(Rel); - return object_error::success; -} - -template -uint64_t ELFObjectFile::getROffset(DataRefImpl Rel) const { const Elf_Shdr *sec = getRelSection(Rel); - switch (sec->sh_type) { - default: - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL: + if (sec->sh_type == ELF::SHT_REL) return getRel(Rel)->r_offset; - case ELF::SHT_RELA: - return getRela(Rel)->r_offset; - } + + return getRela(Rel)->r_offset; } template -std::error_code ELFObjectFile::getRelocationType(DataRefImpl Rel, - uint64_t &Result) const { +uint64_t ELFObjectFile::getRelocationType(DataRefImpl Rel) const { const Elf_Shdr *sec = getRelSection(Rel); - switch (sec->sh_type) { - default: - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL: { - Result = getRel(Rel)->getType(EF.isMips64EL()); - break; - } - case ELF::SHT_RELA: { - Result = getRela(Rel)->getType(EF.isMips64EL()); - break; - } - } - return object_error::success; + if (sec->sh_type == ELF::SHT_REL) + return getRel(Rel)->getType(EF.isMips64EL()); + else + return getRela(Rel)->getType(EF.isMips64EL()); } template @@ -651,125 +697,18 @@ StringRef ELFObjectFile::getRelocationTypeName(uint32_t Type) const { } template -std::error_code ELFObjectFile::getRelocationTypeName( +void ELFObjectFile::getRelocationTypeName( DataRefImpl Rel, SmallVectorImpl &Result) const { - const Elf_Shdr *sec = getRelSection(Rel); - uint32_t type; - switch (sec->sh_type) { - default: - return object_error::parse_failed; - case ELF::SHT_REL: { - type = getRel(Rel)->getType(EF.isMips64EL()); - break; - } - case ELF::SHT_RELA: { - type = getRela(Rel)->getType(EF.isMips64EL()); - break; - } - } - + uint32_t type = getRelocationType(Rel); EF.getRelocationTypeName(type, Result); - return object_error::success; -} - -template -std::error_code -ELFObjectFile::getRelocationAddend(DataRefImpl Rel, - int64_t &Result) const { - const Elf_Shdr *sec = getRelSection(Rel); - switch (sec->sh_type) { - default: - report_fatal_error("Invalid section type in Rel!"); - case ELF::SHT_REL: { - Result = 0; - return object_error::success; - } - case ELF::SHT_RELA: { - Result = getRela(Rel)->r_addend; - return object_error::success; - } - } } template -std::error_code ELFObjectFile::getRelocationValueString( - DataRefImpl Rel, SmallVectorImpl &Result) const { - const Elf_Shdr *sec = getRelSection(Rel); - uint8_t type; - StringRef res; - int64_t addend = 0; - uint16_t symbol_index = 0; - switch (sec->sh_type) { - default: +ErrorOr +ELFObjectFile::getRelocationAddend(DataRefImpl Rel) const { + if (getRelSection(Rel)->sh_type != ELF::SHT_RELA) return object_error::parse_failed; - case ELF::SHT_REL: { - type = getRel(Rel)->getType(EF.isMips64EL()); - symbol_index = getRel(Rel)->getSymbol(EF.isMips64EL()); - // TODO: Read implicit addend from section data. - break; - } - case ELF::SHT_RELA: { - type = getRela(Rel)->getType(EF.isMips64EL()); - symbol_index = getRela(Rel)->getSymbol(EF.isMips64EL()); - addend = getRela(Rel)->r_addend; - break; - } - } - const Elf_Sym *symb = - EF.template getEntry(sec->sh_link, symbol_index); - ErrorOr SymName = - EF.getSymbolName(EF.getSection(sec->sh_link), symb); - if (!SymName) - return SymName.getError(); - switch (EF.getHeader()->e_machine) { - case ELF::EM_X86_64: - switch (type) { - case ELF::R_X86_64_PC8: - case ELF::R_X86_64_PC16: - case ELF::R_X86_64_PC32: { - std::string fmtbuf; - raw_string_ostream fmt(fmtbuf); - fmt << *SymName << (addend < 0 ? "" : "+") << addend << "-P"; - fmt.flush(); - Result.append(fmtbuf.begin(), fmtbuf.end()); - } break; - case ELF::R_X86_64_8: - case ELF::R_X86_64_16: - case ELF::R_X86_64_32: - case ELF::R_X86_64_32S: - case ELF::R_X86_64_64: { - std::string fmtbuf; - raw_string_ostream fmt(fmtbuf); - fmt << *SymName << (addend < 0 ? "" : "+") << addend; - fmt.flush(); - Result.append(fmtbuf.begin(), fmtbuf.end()); - } break; - default: - res = "Unknown"; - } - break; - case ELF::EM_AARCH64: { - std::string fmtbuf; - raw_string_ostream fmt(fmtbuf); - fmt << *SymName; - if (addend != 0) - fmt << (addend < 0 ? "" : "+") << addend; - fmt.flush(); - Result.append(fmtbuf.begin(), fmtbuf.end()); - break; - } - case ELF::EM_386: - case ELF::EM_ARM: - case ELF::EM_HEXAGON: - case ELF::EM_MIPS: - res = *SymName; - break; - default: - res = "Unknown"; - } - if (Result.empty()) - Result.append(res.begin(), res.end()); - return object_error::success; + return (int64_t)getRela(Rel)->r_addend; } template @@ -781,13 +720,15 @@ ELFObjectFile::getSymbol(DataRefImpl Symb) const { template const typename ELFObjectFile::Elf_Rel * ELFObjectFile::getRel(DataRefImpl Rel) const { - return EF.template getEntry(Rel.d.a, Rel.d.b); + assert(getRelSection(Rel)->sh_type == ELF::SHT_REL); + return EF.template getEntry(Rel.d.a, Rel.d.b >> 1); } template const typename ELFObjectFile::Elf_Rela * ELFObjectFile::getRela(DataRefImpl Rela) const { - return EF.template getEntry(Rela.d.a, Rela.d.b); + assert(getRelSection(Rela)->sh_type == ELF::SHT_RELA); + return EF.template getEntry(Rela.d.a, Rela.d.b >> 1); } template @@ -801,45 +742,40 @@ ELFObjectFile::ELFObjectFile(MemoryBufferRef Object, std::error_code &EC) template basic_symbol_iterator ELFObjectFile::symbol_begin_impl() const { - return basic_symbol_iterator(SymbolRef(toDRI(EF.begin_symbols()), this)); + DataRefImpl Sym = toDRI(EF.getDotSymtabSec(), 0); + return basic_symbol_iterator(SymbolRef(Sym, this)); } template basic_symbol_iterator ELFObjectFile::symbol_end_impl() const { - return basic_symbol_iterator(SymbolRef(toDRI(EF.end_symbols()), this)); + const Elf_Shdr *SymTab = EF.getDotSymtabSec(); + if (!SymTab) + return symbol_begin_impl(); + DataRefImpl Sym = toDRI(SymTab, SymTab->sh_size / sizeof(Elf_Sym)); + return basic_symbol_iterator(SymbolRef(Sym, this)); } template -symbol_iterator ELFObjectFile::dynamic_symbol_begin() const { - return symbol_iterator(SymbolRef(toDRI(EF.begin_dynamic_symbols()), this)); +elf_symbol_iterator ELFObjectFile::dynamic_symbol_begin() const { + DataRefImpl Sym = toDRI(EF.getDotDynSymSec(), 0); + return symbol_iterator(SymbolRef(Sym, this)); } template -symbol_iterator ELFObjectFile::dynamic_symbol_end() const { - return symbol_iterator(SymbolRef(toDRI(EF.end_dynamic_symbols()), this)); +elf_symbol_iterator ELFObjectFile::dynamic_symbol_end() const { + const Elf_Shdr *SymTab = EF.getDotDynSymSec(); + DataRefImpl Sym = toDRI(SymTab, SymTab->sh_size / sizeof(Elf_Sym)); + return basic_symbol_iterator(SymbolRef(Sym, this)); } template section_iterator ELFObjectFile::section_begin() const { - return section_iterator(SectionRef(toDRI(EF.begin_sections()), this)); + return section_iterator(SectionRef(toDRI(EF.section_begin()), this)); } template section_iterator ELFObjectFile::section_end() const { - return section_iterator(SectionRef(toDRI(EF.end_sections()), this)); -} - -template -StringRef ELFObjectFile::getLoadName() const { - Elf_Dyn_Iter DI = EF.begin_dynamic_table(); - Elf_Dyn_Iter DE = EF.end_dynamic_table(); - - while (DI != DE && DI->getTag() != ELF::DT_SONAME) - ++DI; - - if (DI != DE) - return EF.getDynamicString(DI->getVal()); - return ""; + return section_iterator(SectionRef(toDRI(EF.section_end()), this)); } template @@ -928,7 +864,7 @@ unsigned ELFObjectFile::getArch() const { case ELF::EM_SPARC: case ELF::EM_SPARC32PLUS: - return Triple::sparc; + return IsLittleEndian ? Triple::sparcel : Triple::sparc; case ELF::EM_SPARCV9: return Triple::sparcv9; @@ -938,34 +874,15 @@ unsigned ELFObjectFile::getArch() const { } template -std::pair -ELFObjectFile::getELFDynamicSymbolIterators() const { - return std::make_pair(dynamic_symbol_begin(), dynamic_symbol_end()); +ELFObjectFileBase::elf_symbol_iterator_range +ELFObjectFile::getDynamicSymbolIterators() const { + return make_range(dynamic_symbol_begin(), dynamic_symbol_end()); } template bool ELFObjectFile::isRelocatableObject() const { return EF.getHeader()->e_type == ELF::ET_REL; } -inline std::error_code getELFRelocationAddend(const RelocationRef R, - int64_t &Addend) { - const ObjectFile *Obj = R.getObjectFile(); - DataRefImpl DRI = R.getRawDataRefImpl(); - return cast(Obj)->getRelocationAddend(DRI, Addend); -} - -inline std::pair -getELFDynamicSymbolIterators(const SymbolicFile *Obj) { - return cast(Obj)->getELFDynamicSymbolIterators(); -} - -inline std::error_code GetELFSymbolVersion(const ObjectFile *Obj, - const SymbolRef &Sym, - StringRef &Version, - bool &IsDefault) { - return cast(Obj) - ->getSymbolVersion(Sym, Version, IsDefault); -} } } diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h index 5a4e03e7bbe..27e987ba285 100644 --- a/include/llvm/Object/ELFTypes.h +++ b/include/llvm/Object/ELFTypes.h @@ -10,105 +10,91 @@ #ifndef LLVM_OBJECT_ELFTYPES_H #define LLVM_OBJECT_ELFTYPES_H -#include "llvm/Support/AlignOf.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Object/Error.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorOr.h" namespace llvm { namespace object { using support::endianness; -template -struct ELFType { +template struct ELFType { static const endianness TargetEndianness = target_endianness; - static const std::size_t MaxAlignment = max_alignment; static const bool Is64Bits = is64Bits; }; -template struct MaximumAlignment { - enum { value = AlignOf::Alignment > max_align ? max_align - : AlignOf::Alignment - }; -}; +typedef ELFType ELF32LE; +typedef ELFType ELF32BE; +typedef ELFType ELF64LE; +typedef ELFType ELF64BE; + +// Use an alignment of 2 for the typedefs since that is the worst case for +// ELF files in archives. // Templates to choose Elf_Addr and Elf_Off depending on is64Bits. -template -struct ELFDataTypeTypedefHelperCommon { +template struct ELFDataTypeTypedefHelperCommon { typedef support::detail::packed_endian_specific_integral< - uint16_t, target_endianness, - MaximumAlignment::value> Elf_Half; + uint16_t, target_endianness, 2> Elf_Half; typedef support::detail::packed_endian_specific_integral< - uint32_t, target_endianness, - MaximumAlignment::value> Elf_Word; + uint32_t, target_endianness, 2> Elf_Word; typedef support::detail::packed_endian_specific_integral< - int32_t, target_endianness, - MaximumAlignment::value> Elf_Sword; + int32_t, target_endianness, 2> Elf_Sword; typedef support::detail::packed_endian_specific_integral< - uint64_t, target_endianness, - MaximumAlignment::value> Elf_Xword; + uint64_t, target_endianness, 2> Elf_Xword; typedef support::detail::packed_endian_specific_integral< - int64_t, target_endianness, - MaximumAlignment::value> Elf_Sxword; + int64_t, target_endianness, 2> Elf_Sxword; }; template struct ELFDataTypeTypedefHelper; /// ELF 32bit types. -template -struct ELFDataTypeTypedefHelper > - : ELFDataTypeTypedefHelperCommon { +template +struct ELFDataTypeTypedefHelper> + : ELFDataTypeTypedefHelperCommon { typedef uint32_t value_type; typedef support::detail::packed_endian_specific_integral< - value_type, TargetEndianness, - MaximumAlignment::value> Elf_Addr; + value_type, TargetEndianness, 2> Elf_Addr; typedef support::detail::packed_endian_specific_integral< - value_type, TargetEndianness, - MaximumAlignment::value> Elf_Off; + value_type, TargetEndianness, 2> Elf_Off; }; /// ELF 64bit types. -template -struct ELFDataTypeTypedefHelper > - : ELFDataTypeTypedefHelperCommon { +template +struct ELFDataTypeTypedefHelper> + : ELFDataTypeTypedefHelperCommon { typedef uint64_t value_type; typedef support::detail::packed_endian_specific_integral< - value_type, TargetEndianness, - MaximumAlignment::value> Elf_Addr; + value_type, TargetEndianness, 2> Elf_Addr; typedef support::detail::packed_endian_specific_integral< - value_type, TargetEndianness, - MaximumAlignment::value> Elf_Off; + value_type, TargetEndianness, 2> Elf_Off; }; // I really don't like doing this, but the alternative is copypasta. -#define LLVM_ELF_IMPORT_TYPES(E, M, W) \ -typedef typename ELFDataTypeTypedefHelper >::Elf_Addr \ - Elf_Addr; \ -typedef typename ELFDataTypeTypedefHelper >::Elf_Off \ - Elf_Off; \ -typedef typename ELFDataTypeTypedefHelper >::Elf_Half \ - Elf_Half; \ -typedef typename ELFDataTypeTypedefHelper >::Elf_Word \ - Elf_Word; \ -typedef typename ELFDataTypeTypedefHelper >::Elf_Sword \ - Elf_Sword; \ -typedef typename ELFDataTypeTypedefHelper >::Elf_Xword \ - Elf_Xword; \ -typedef typename ELFDataTypeTypedefHelper >::Elf_Sxword \ - Elf_Sxword; +#define LLVM_ELF_IMPORT_TYPES(E, W) \ + typedef typename ELFDataTypeTypedefHelper>::Elf_Addr Elf_Addr; \ + typedef typename ELFDataTypeTypedefHelper>::Elf_Off Elf_Off; \ + typedef typename ELFDataTypeTypedefHelper>::Elf_Half Elf_Half; \ + typedef typename ELFDataTypeTypedefHelper>::Elf_Word Elf_Word; \ + typedef \ + typename ELFDataTypeTypedefHelper>::Elf_Sword Elf_Sword; \ + typedef \ + typename ELFDataTypeTypedefHelper>::Elf_Xword Elf_Xword; \ + typedef \ + typename ELFDataTypeTypedefHelper>::Elf_Sxword Elf_Sxword; #define LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) \ - LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::MaxAlignment, \ - ELFT::Is64Bits) + LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::Is64Bits) // Section header. template struct Elf_Shdr_Base; -template -struct Elf_Shdr_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) +template +struct Elf_Shdr_Base> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_type; // Section type (SHT_*) Elf_Word sh_flags; // Section flags (SHF_*) @@ -121,9 +107,9 @@ struct Elf_Shdr_Base > { Elf_Word sh_entsize; // Size of records contained within the section }; -template -struct Elf_Shdr_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) +template +struct Elf_Shdr_Base> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) Elf_Word sh_name; // Section name (index into string table) Elf_Word sh_type; // Section type (SHT_*) Elf_Xword sh_flags; // Section flags (SHF_*) @@ -151,9 +137,9 @@ struct Elf_Shdr_Impl : Elf_Shdr_Base { template struct Elf_Sym_Base; -template -struct Elf_Sym_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) +template +struct Elf_Sym_Base> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) Elf_Word st_name; // Symbol name (index into string table) Elf_Addr st_value; // Value or address associated with the symbol Elf_Word st_size; // Size of the symbol @@ -162,9 +148,9 @@ struct Elf_Sym_Base > { Elf_Half st_shndx; // Which section (header table index) it's defined in }; -template -struct Elf_Sym_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) +template +struct Elf_Sym_Base> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) Elf_Word st_name; // Symbol name (index into string table) unsigned char st_info; // Symbol's type and binding attributes unsigned char st_other; // Must be zero; reserved @@ -176,12 +162,15 @@ struct Elf_Sym_Base > { template struct Elf_Sym_Impl : Elf_Sym_Base { using Elf_Sym_Base::st_info; + using Elf_Sym_Base::st_shndx; using Elf_Sym_Base::st_other; + using Elf_Sym_Base::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) { @@ -198,8 +187,39 @@ struct Elf_Sym_Impl : Elf_Sym_Base { 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; } + bool isExternal() const { + return getBinding() != ELF::STB_LOCAL; + } + + ErrorOr getName(StringRef StrTab) const; }; +template +ErrorOr Elf_Sym_Impl::getName(StringRef StrTab) const { + uint32_t Offset = this->st_name; + if (Offset >= StrTab.size()) + return object_error::parse_failed; + return StringRef(StrTab.data() + Offset); +} + /// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section /// (.gnu.version). This structure is identical for ELF32 and ELF64. template @@ -267,9 +287,9 @@ struct Elf_Vernaux_Impl { /// table section (.dynamic) look like. template struct Elf_Dyn_Base; -template -struct Elf_Dyn_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) +template +struct Elf_Dyn_Base> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) Elf_Sword d_tag; union { Elf_Word d_val; @@ -277,9 +297,9 @@ struct Elf_Dyn_Base > { } d_un; }; -template -struct Elf_Dyn_Base > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) +template +struct Elf_Dyn_Base> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) Elf_Sxword d_tag; union { Elf_Xword d_val; @@ -294,15 +314,15 @@ struct Elf_Dyn_Impl : Elf_Dyn_Base { using Elf_Dyn_Base::d_un; int64_t getTag() const { return d_tag; } uint64_t getVal() const { return d_un.d_val; } - uint64_t getPtr() const { return d_un.ptr; } + uint64_t getPtr() const { return d_un.d_ptr; } }; // Elf_Rel: Elf Relocation -template struct Elf_Rel_Base; +template struct Elf_Rel_Impl; -template -struct Elf_Rel_Base, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) +template +struct Elf_Rel_Impl, false> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf_Word r_info; // Symbol table index and type of relocation to apply @@ -314,64 +334,46 @@ struct Elf_Rel_Base, false> { assert(!IsMips64EL); r_info = R; } -}; -template -struct Elf_Rel_Base, false> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Xword r_info; // Symbol table index and type of relocation to apply - - uint64_t getRInfo(bool isMips64EL) const { - uint64_t t = r_info; - if (!isMips64EL) - return t; - // Mips64 little endian has a "special" encoding of r_info. Instead of one - // 64 bit little endian number, it is a little endian 32 bit number followed - // by a 32 bit big endian number. - return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | - ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); + // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, + // and ELF32_R_INFO macros defined in the ELF specification: + uint32_t getSymbol(bool isMips64EL) const { + return this->getRInfo(isMips64EL) >> 8; } - void setRInfo(uint64_t R, bool IsMips64EL) { - if (IsMips64EL) - r_info = (R >> 32) | ((R & 0xff000000) << 8) | ((R & 0x00ff0000) << 24) | - ((R & 0x0000ff00) << 40) | ((R & 0x000000ff) << 56); - else - r_info = R; + unsigned char getType(bool isMips64EL) const { + return (unsigned char)(this->getRInfo(isMips64EL) & 0x0ff); + } + void setSymbol(uint32_t s, bool IsMips64EL) { + setSymbolAndType(s, getType(), IsMips64EL); + } + void setType(unsigned char t, bool IsMips64EL) { + setSymbolAndType(getSymbol(), t, IsMips64EL); + } + void setSymbolAndType(uint32_t s, unsigned char t, bool IsMips64EL) { + this->setRInfo((s << 8) + t, IsMips64EL); } }; -template -struct Elf_Rel_Base, true> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Word r_info; // Symbol table index and type of relocation to apply +template +struct Elf_Rel_Impl, true> + : public Elf_Rel_Impl, false> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) Elf_Sword r_addend; // Compute value for relocatable field by adding this - - uint32_t getRInfo(bool isMips64EL) const { - assert(!isMips64EL); - return r_info; - } - void setRInfo(uint32_t R, bool IsMips64EL) { - assert(!IsMips64EL); - r_info = R; - } }; -template -struct Elf_Rel_Base, true> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) - Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) - Elf_Xword r_info; // Symbol table index and type of relocation to apply - Elf_Sxword r_addend; // Compute value for relocatable field by adding this. +template +struct Elf_Rel_Impl, false> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) + Elf_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf_Xword r_info; // Symbol table index and type of relocation to apply uint64_t getRInfo(bool isMips64EL) const { - // Mips64 little endian has a "special" encoding of r_info. Instead of one - // 64 bit little endian number, it is a little endian 32 bit number followed - // by a 32 bit big endian number. uint64_t t = r_info; if (!isMips64EL) return t; + // Mips64 little endian has a "special" encoding of r_info. Instead of one + // 64 bit little endian number, it is a little endian 32 bit number followed + // by a 32 bit big endian number. return (t << 32) | ((t >> 8) & 0xff000000) | ((t >> 24) & 0x00ff0000) | ((t >> 40) & 0x0000ff00) | ((t >> 56) & 0x000000ff); } @@ -382,15 +384,6 @@ struct Elf_Rel_Base, true> { else r_info = R; } -}; - -template struct Elf_Rel_Impl; - -template -struct Elf_Rel_Impl, - isRela> : Elf_Rel_Base< - ELFType, isRela> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, // and ELF64_R_INFO macros defined in the ELF specification: @@ -411,29 +404,11 @@ struct Elf_Rel_Impl, } }; -template -struct Elf_Rel_Impl, - isRela> : Elf_Rel_Base< - ELFType, isRela> { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) - - // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, - // and ELF32_R_INFO macros defined in the ELF specification: - uint32_t getSymbol(bool isMips64EL) const { - return this->getRInfo(isMips64EL) >> 8; - } - unsigned char getType(bool isMips64EL) const { - return (unsigned char)(this->getRInfo(isMips64EL) & 0x0ff); - } - void setSymbol(uint32_t s, bool IsMips64EL) { - setSymbolAndType(s, getType(), IsMips64EL); - } - void setType(unsigned char t, bool IsMips64EL) { - setSymbolAndType(getSymbol(), t, IsMips64EL); - } - void setSymbolAndType(uint32_t s, unsigned char t, bool IsMips64EL) { - this->setRInfo((s << 8) + t, IsMips64EL); - } +template +struct Elf_Rel_Impl, true> + : public Elf_Rel_Impl, false> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) + Elf_Sxword r_addend; // Compute value for relocatable field by adding this. }; template @@ -463,9 +438,9 @@ struct Elf_Ehdr_Impl { template struct Elf_Phdr_Impl; -template -struct Elf_Phdr_Impl > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false) +template +struct Elf_Phdr_Impl> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) Elf_Word p_type; // Type of segment Elf_Off p_offset; // FileOffset where segment is located, in bytes Elf_Addr p_vaddr; // Virtual Address of beginning of segment @@ -476,9 +451,9 @@ struct Elf_Phdr_Impl > { Elf_Word p_align; // Segment alignment constraint }; -template -struct Elf_Phdr_Impl > { - LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true) +template +struct Elf_Phdr_Impl> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) Elf_Word p_type; // Type of segment Elf_Word p_flags; // Segment flags Elf_Off p_offset; // FileOffset where segment is located, in bytes @@ -489,6 +464,76 @@ struct Elf_Phdr_Impl > { Elf_Xword p_align; // Segment alignment constraint }; +// ELFT needed for endianess. +template +struct Elf_Hash_Impl { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Word nbucket; + Elf_Word nchain; + + ArrayRef buckets() const { + return ArrayRef(&nbucket + 2, &nbucket + 2 + nbucket); + } + + ArrayRef chains() const { + return ArrayRef(&nbucket + 2 + nbucket, + &nbucket + 2 + nbucket + nchain); + } +}; + +// MIPS .reginfo section +template +struct Elf_Mips_RegInfo; + +template +struct Elf_Mips_RegInfo> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, false) + Elf_Word ri_gprmask; // bit-mask of used general registers + Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers + Elf_Addr ri_gp_value; // gp register value +}; + +template +struct Elf_Mips_RegInfo> { + LLVM_ELF_IMPORT_TYPES(TargetEndianness, true) + Elf_Word ri_gprmask; // bit-mask of used general registers + Elf_Word ri_pad; // unused padding field + Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers + Elf_Addr ri_gp_value; // gp register value +}; + +// .MIPS.options section +template struct Elf_Mips_Options { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + uint8_t kind; // Determines interpretation of variable part of descriptor + uint8_t size; // Byte size of descriptor, including this header + Elf_Half section; // Section header index of section affected, + // or 0 for global options + Elf_Word info; // Kind-specific information + + const Elf_Mips_RegInfo &getRegInfo() const { + assert(kind == llvm::ELF::ODK_REGINFO); + return *reinterpret_cast *>( + (const uint8_t *)this + sizeof(Elf_Mips_Options)); + } +}; + +// .MIPS.abiflags section content +template struct Elf_Mips_ABIFlags { + LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) + Elf_Half version; // Version of the structure + uint8_t isa_level; // ISA level: 1-5, 32, and 64 + uint8_t isa_rev; // ISA revision (0 for MIPS I - MIPS V) + uint8_t gpr_size; // General purpose registers size + uint8_t cpr1_size; // Co-processor 1 registers size + uint8_t cpr2_size; // Co-processor 2 registers size + uint8_t fp_abi; // Floating-point ABI flag + Elf_Word isa_ext; // Processor-specific extension + Elf_Word ases; // ASEs flags + Elf_Word flags1; // General flags + Elf_Word flags2; // General flags +}; + } // end namespace object. } // end namespace llvm. diff --git a/include/llvm/Object/ELFYAML.h b/include/llvm/Object/ELFYAML.h index 45cbdbd2da3..df0aa500c8a 100644 --- a/include/llvm/Object/ELFYAML.h +++ b/include/llvm/Object/ELFYAML.h @@ -48,6 +48,13 @@ LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STV) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STO) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_AFL_REG) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_ABI_FP) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_EXT) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_ASE) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_FLAGS1) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_ISA) + // For now, hardcode 64 bits everywhere that 32 or 64 would be needed // since 64-bit can hold 32-bit values too. struct FileHeader { @@ -78,7 +85,13 @@ struct SectionOrType { }; struct Section { - enum class SectionKind { Group, RawContent, Relocation }; + enum class SectionKind { + Group, + RawContent, + Relocation, + NoBits, + MipsABIFlags + }; SectionKind Kind; StringRef Name; ELF_SHT Type; @@ -99,6 +112,14 @@ struct RawContentSection : Section { } }; +struct NoBitsSection : Section { + llvm::yaml::Hex64 Size; + NoBitsSection() : Section(SectionKind::NoBits) {} + static bool classof(const Section *S) { + return S->Kind == SectionKind::NoBits; + } +}; + struct Group : Section { // Members of a group contain a flag and a list of section indices // that are part of the group. @@ -122,6 +143,26 @@ struct RelocationSection : Section { return S->Kind == SectionKind::Relocation; } }; + +// Represents .MIPS.abiflags section +struct MipsABIFlags : Section { + llvm::yaml::Hex16 Version; + MIPS_ISA ISALevel; + llvm::yaml::Hex8 ISARevision; + MIPS_AFL_REG GPRSize; + MIPS_AFL_REG CPR1Size; + MIPS_AFL_REG CPR2Size; + MIPS_ABI_FP FpABI; + MIPS_AFL_EXT ISAExtension; + MIPS_AFL_ASE ASEs; + MIPS_AFL_FLAGS1 Flags1; + llvm::yaml::Hex32 Flags2; + MipsABIFlags() : Section(SectionKind::MipsABIFlags) {} + static bool classof(const Section *S) { + return S->Kind == SectionKind::MipsABIFlags; + } +}; + struct Object { FileHeader Header; std::vector> Sections; @@ -208,6 +249,36 @@ struct ScalarEnumerationTraits { static void enumeration(IO &IO, ELFYAML::ELF_RSS &Value); }; +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::MIPS_AFL_REG &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::MIPS_ABI_FP &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::MIPS_AFL_EXT &Value); +}; + +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, ELFYAML::MIPS_ISA &Value); +}; + +template <> +struct ScalarBitSetTraits { + static void bitset(IO &IO, ELFYAML::MIPS_AFL_ASE &Value); +}; + +template <> +struct ScalarBitSetTraits { + static void bitset(IO &IO, ELFYAML::MIPS_AFL_FLAGS1 &Value); +}; + template <> struct MappingTraits { static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr); diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h index 90c2bd74b43..aa320bb51a4 100644 --- a/include/llvm/Object/Error.h +++ b/include/llvm/Object/Error.h @@ -22,12 +22,17 @@ 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, + string_table_non_null_end, + invalid_section_index, 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) { diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index a552aca91d7..489ecef5c99 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -190,28 +190,30 @@ class MachOObjectFile : public ObjectFile { const char *Ptr; // Where in memory the load command is. MachO::load_command C; // The command itself. }; + typedef SmallVector LoadCommandList; + typedef LoadCommandList::const_iterator load_command_iterator; MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits, std::error_code &EC); void moveSymbolNext(DataRefImpl &Symb) const override; - std::error_code getSymbolName(DataRefImpl Symb, - StringRef &Res) const override; + + uint64_t getNValue(DataRefImpl Sym) const; + ErrorOr getSymbolName(DataRefImpl Symb) const override; // MachO specific. std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const; unsigned getSectionType(SectionRef Sec) const; - std::error_code getSymbolAddress(DataRefImpl Symb, - uint64_t &Res) const override; - std::error_code getSymbolAlignment(DataRefImpl Symb, - uint32_t &Res) const override; - std::error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const override; - std::error_code getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const override; + ErrorOr getSymbolAddress(DataRefImpl Symb) const override; + uint32_t getSymbolAlignment(DataRefImpl Symb) const override; + uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; + SymbolRef::Type getSymbolType(DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; std::error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const override; + unsigned getSymbolSectionID(SymbolRef Symb) const; + unsigned getSectionID(SectionRef Sec) const; void moveSectionNext(DataRefImpl &Sec) const override; std::error_code getSectionName(DataRefImpl Sec, @@ -225,30 +227,23 @@ class MachOObjectFile : public ObjectFile { bool isSectionData(DataRefImpl Sec) const override; bool isSectionBSS(DataRefImpl Sec) const override; bool isSectionVirtual(DataRefImpl Sec) const override; - bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; void moveRelocationNext(DataRefImpl &Rel) const override; - std::error_code getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const override; - std::error_code getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const override; + uint64_t getRelocationOffset(DataRefImpl Rel) const override; symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override; - std::error_code getRelocationType(DataRefImpl Rel, - uint64_t &Res) const override; - std::error_code - getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl &Result) const override; - std::error_code - getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const override; - std::error_code getRelocationHidden(DataRefImpl Rel, - bool &Result) const override; + section_iterator getRelocationSection(DataRefImpl Rel) const; + uint64_t getRelocationType(DataRefImpl Rel) const override; + void getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl &Result) const override; + uint8_t getRelocationLength(DataRefImpl Rel) const; // MachO specific. std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const; + section_iterator getRelocationRelocatedSection(relocation_iterator Rel) const; + // TODO: Would be useful to have an iterator based version // of the load command interface too. @@ -272,10 +267,14 @@ class MachOObjectFile : public ObjectFile { 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_commands() const; + /// For use iterating over all exported symbols. iterator_range exports() const; - + /// For use examining a trie not in a MachOObjectFile. static iterator_range exports(ArrayRef Trie); @@ -326,11 +325,7 @@ class MachOObjectFile : public ObjectFile { unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const; unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const; unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const; - SectionRef getRelocationSection(const MachO::any_relocation_info &RE) const; - - // Walk load commands. - LoadCommandInfo getFirstLoadCommandInfo() const; - LoadCommandInfo getNextLoadCommandInfo(const LoadCommandInfo &L) const; + SectionRef getAnyRelocationSection(const MachO::any_relocation_info &RE) const; // MachO specific structures. MachO::section getSection(DataRefImpl DRI) const; @@ -385,8 +380,8 @@ class MachOObjectFile : public ObjectFile { 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; @@ -429,10 +424,17 @@ class MachOObjectFile : public ObjectFile { } private: + uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; + + union { + MachO::mach_header_64 Header64; + MachO::mach_header Header; + }; typedef SmallVector SectionList; SectionList Sections; typedef SmallVector LibraryList; LibraryList Libraries; + LoadCommandList LoadCommands; typedef SmallVector LibraryShortName; mutable LibraryShortName LibrariesShortNames; const char *SymtabLoadCmd; @@ -471,7 +473,7 @@ inline std::error_code DiceRef::getOffset(uint32_t &Result) const { static_cast(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 { @@ -479,7 +481,7 @@ inline std::error_code DiceRef::getLength(uint16_t &Result) const { static_cast(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 { @@ -487,7 +489,7 @@ inline std::error_code DiceRef::getKind(uint16_t &Result) const { static_cast(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 { diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h index 05119b29331..a11d381a700 100644 --- a/include/llvm/Object/MachOUniversal.h +++ b/include/llvm/Object/MachOUniversal.h @@ -109,7 +109,7 @@ class MachOUniversalBinary : public Binary { } ErrorOr> - getObjectForArch(Triple::ArchType Arch) const; + getObjectForArch(StringRef ArchName) const; }; } diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index b7e19b941c8..8dd52562621 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -32,9 +32,11 @@ class MachOObjectFile; class SymbolRef; class symbol_iterator; +class SectionRef; +typedef content_iterator section_iterator; -/// RelocationRef - This is a value type class that represents a single -/// relocation in the list of relocations in the object file. +/// This is a value type class that represents a single relocation in the list +/// of relocations in the object file. class RelocationRef { DataRefImpl RelocationPimpl; const ObjectFile *OwningObject; @@ -48,36 +50,22 @@ class RelocationRef { void moveNext(); - std::error_code getAddress(uint64_t &Result) const; - std::error_code getOffset(uint64_t &Result) const; + uint64_t getOffset() const; symbol_iterator getSymbol() const; - std::error_code getType(uint64_t &Result) const; - - /// @brief Indicates whether this relocation should hidden when listing - /// relocations, usually because it is the trailing part of a multipart - /// relocation that will be printed as part of the leading relocation. - std::error_code getHidden(bool &Result) const; + uint64_t getType() const; /// @brief Get a string that represents the type of this relocation. /// /// This is for display purposes only. - std::error_code getTypeName(SmallVectorImpl &Result) const; - - /// @brief Get a string that represents the calculation of the value of this - /// relocation. - /// - /// This is for display purposes only. - std::error_code getValueString(SmallVectorImpl &Result) const; + void getTypeName(SmallVectorImpl &Result) const; DataRefImpl getRawDataRefImpl() const; - const ObjectFile *getObjectFile() const; + const ObjectFile *getObject() const; }; typedef content_iterator relocation_iterator; -/// SectionRef - This is a value type class that represents a single section in -/// the list of sections in the object file. -class SectionRef; -typedef content_iterator section_iterator; +/// This is a value type class that represents a single section in the list of +/// sections in the object file. class SectionRef { friend class SymbolRef; DataRefImpl SectionPimpl; @@ -121,8 +109,8 @@ class SectionRef { const ObjectFile *getObject() const; }; -/// SymbolRef - This is a value type class that represents a single symbol in -/// the list of symbols in the object file. +/// This is a value type class that represents a single symbol in the list of +/// symbols in the object file. class SymbolRef : public BasicSymbolRef { friend class SectionRef; @@ -139,16 +127,23 @@ class SymbolRef : public BasicSymbolRef { }; SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner); + SymbolRef(const BasicSymbolRef &B) : BasicSymbolRef(B) { + assert(isa(BasicSymbolRef::getObject())); + } - std::error_code getName(StringRef &Result) const; + ErrorOr getName() const; /// Returns the symbol virtual address (i.e. address at which it will be /// mapped). - std::error_code getAddress(uint64_t &Result) const; + ErrorOr getAddress() const; + + /// Return the value of the symbol depending on the object this can be an + /// offset or a virtual address. + uint64_t getValue() const; + /// @brief Get the alignment of this symbol as the actual value (not log 2). - std::error_code getAlignment(uint32_t &Result) const; - std::error_code getSize(uint64_t &Result) const; - std::error_code getType(SymbolRef::Type &Result) const; - std::error_code getOther(uint8_t &Result) const; + uint32_t getAlignment() const; + uint64_t getCommonSize() const; + SymbolRef::Type getType() const; /// @brief Get section this symbol is defined in reference to. Result is /// end_sections() if it is undefined or is an absolute symbol. @@ -175,9 +170,9 @@ class symbol_iterator : public basic_symbol_iterator { } }; -/// ObjectFile - This class is the base class for all object file types. -/// Concrete instances of this object are created by createObjectFile, which -/// figures out which type to create. +/// This class is the base class for all object file types. Concrete instances +/// of this object are created by createObjectFile, which figures out which type +/// to create. class ObjectFile : public SymbolicFile { virtual void anchor(); ObjectFile() = delete; @@ -199,24 +194,16 @@ class ObjectFile : public SymbolicFile { // Implementations assume that the DataRefImpl is valid and has not been // modified externally. It's UB otherwise. friend class SymbolRef; - virtual std::error_code getSymbolName(DataRefImpl Symb, - StringRef &Res) const = 0; + virtual ErrorOr getSymbolName(DataRefImpl Symb) const = 0; std::error_code printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; - virtual std::error_code getSymbolAddress(DataRefImpl Symb, - uint64_t &Res) const = 0; - virtual std::error_code getSymbolAlignment(DataRefImpl Symb, - uint32_t &Res) const; - virtual std::error_code getSymbolSize(DataRefImpl Symb, - uint64_t &Res) const = 0; - virtual std::error_code getSymbolType(DataRefImpl Symb, - SymbolRef::Type &Res) const = 0; + virtual ErrorOr getSymbolAddress(DataRefImpl Symb) const = 0; + virtual uint64_t getSymbolValueImpl(DataRefImpl Symb) const = 0; + virtual uint32_t getSymbolAlignment(DataRefImpl Symb) const; + virtual uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const = 0; + virtual SymbolRef::Type getSymbolType(DataRefImpl Symb) const = 0; virtual std::error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const = 0; - virtual std::error_code getSymbolOther(DataRefImpl Symb, - uint8_t &Res) const { - return object_error::invalid_file_type; - } // Same as above for SectionRef. friend class SectionRef; @@ -233,8 +220,6 @@ class ObjectFile : public SymbolicFile { virtual bool isSectionBSS(DataRefImpl Sec) const = 0; // A section is 'virtual' if its contents aren't present in the object image. virtual bool isSectionVirtual(DataRefImpl Sec) const = 0; - virtual bool sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb) const = 0; virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0; virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0; virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; @@ -242,26 +227,20 @@ class ObjectFile : public SymbolicFile { // Same as above for RelocationRef. friend class RelocationRef; virtual void moveRelocationNext(DataRefImpl &Rel) const = 0; - virtual std::error_code getRelocationAddress(DataRefImpl Rel, - uint64_t &Res) const = 0; - virtual std::error_code getRelocationOffset(DataRefImpl Rel, - uint64_t &Res) const = 0; + virtual uint64_t getRelocationOffset(DataRefImpl Rel) const = 0; virtual symbol_iterator getRelocationSymbol(DataRefImpl Rel) const = 0; - virtual std::error_code getRelocationType(DataRefImpl Rel, - uint64_t &Res) const = 0; - virtual std::error_code - getRelocationTypeName(DataRefImpl Rel, - SmallVectorImpl &Result) const = 0; - virtual std::error_code - getRelocationValueString(DataRefImpl Rel, - SmallVectorImpl &Result) const = 0; - virtual std::error_code getRelocationHidden(DataRefImpl Rel, - bool &Result) const { - Result = false; - return object_error::success; - } + virtual uint64_t getRelocationType(DataRefImpl Rel) const = 0; + virtual void getRelocationTypeName(DataRefImpl Rel, + SmallVectorImpl &Result) const = 0; + + uint64_t getSymbolValue(DataRefImpl Symb) const; public: + uint64_t getCommonSymbolSize(DataRefImpl Symb) const { + assert(getSymbolFlags(Symb) & SymbolRef::SF_Common); + return getCommonSymbolSizeImpl(Symb); + } + typedef iterator_range symbol_iterator_range; symbol_iterator_range symbols() const { return symbol_iterator_range(symbol_begin(), symbol_end()); @@ -324,32 +303,32 @@ class ObjectFile : public SymbolicFile { inline SymbolRef::SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner) : BasicSymbolRef(SymbolP, Owner) {} -inline std::error_code SymbolRef::getName(StringRef &Result) const { - return getObject()->getSymbolName(getRawDataRefImpl(), Result); +inline ErrorOr SymbolRef::getName() const { + return getObject()->getSymbolName(getRawDataRefImpl()); } -inline std::error_code SymbolRef::getAddress(uint64_t &Result) const { - return getObject()->getSymbolAddress(getRawDataRefImpl(), Result); +inline ErrorOr SymbolRef::getAddress() const { + return getObject()->getSymbolAddress(getRawDataRefImpl()); } -inline std::error_code SymbolRef::getAlignment(uint32_t &Result) const { - return getObject()->getSymbolAlignment(getRawDataRefImpl(), Result); +inline uint64_t SymbolRef::getValue() const { + return getObject()->getSymbolValue(getRawDataRefImpl()); } -inline std::error_code SymbolRef::getSize(uint64_t &Result) const { - return getObject()->getSymbolSize(getRawDataRefImpl(), Result); +inline uint32_t SymbolRef::getAlignment() const { + return getObject()->getSymbolAlignment(getRawDataRefImpl()); } -inline std::error_code SymbolRef::getSection(section_iterator &Result) const { - return getObject()->getSymbolSection(getRawDataRefImpl(), Result); +inline uint64_t SymbolRef::getCommonSize() const { + return getObject()->getCommonSymbolSize(getRawDataRefImpl()); } -inline std::error_code SymbolRef::getType(SymbolRef::Type &Result) const { - return getObject()->getSymbolType(getRawDataRefImpl(), Result); +inline std::error_code SymbolRef::getSection(section_iterator &Result) const { + return getObject()->getSymbolSection(getRawDataRefImpl(), Result); } -inline std::error_code SymbolRef::getOther(uint8_t &Result) const { - return getObject()->getSymbolOther(getRawDataRefImpl(), Result); +inline SymbolRef::Type SymbolRef::getType() const { + return getObject()->getSymbolType(getRawDataRefImpl()); } inline const ObjectFile *SymbolRef::getObject() const { @@ -416,11 +395,6 @@ inline bool SectionRef::isVirtual() const { return OwningObject->isSectionVirtual(SectionPimpl); } -inline bool SectionRef::containsSymbol(SymbolRef S) const { - return OwningObject->sectionContainsSymbol(SectionPimpl, - S.getRawDataRefImpl()); -} - inline relocation_iterator SectionRef::relocation_begin() const { return OwningObject->section_rel_begin(SectionPimpl); } @@ -455,41 +429,27 @@ inline void RelocationRef::moveNext() { return OwningObject->moveRelocationNext(RelocationPimpl); } -inline std::error_code RelocationRef::getAddress(uint64_t &Result) const { - return OwningObject->getRelocationAddress(RelocationPimpl, Result); -} - -inline std::error_code RelocationRef::getOffset(uint64_t &Result) const { - return OwningObject->getRelocationOffset(RelocationPimpl, Result); +inline uint64_t RelocationRef::getOffset() const { + return OwningObject->getRelocationOffset(RelocationPimpl); } inline symbol_iterator RelocationRef::getSymbol() const { return OwningObject->getRelocationSymbol(RelocationPimpl); } -inline std::error_code RelocationRef::getType(uint64_t &Result) const { - return OwningObject->getRelocationType(RelocationPimpl, Result); +inline uint64_t RelocationRef::getType() const { + return OwningObject->getRelocationType(RelocationPimpl); } -inline std::error_code -RelocationRef::getTypeName(SmallVectorImpl &Result) const { +inline void RelocationRef::getTypeName(SmallVectorImpl &Result) const { return OwningObject->getRelocationTypeName(RelocationPimpl, Result); } -inline std::error_code -RelocationRef::getValueString(SmallVectorImpl &Result) const { - return OwningObject->getRelocationValueString(RelocationPimpl, Result); -} - -inline std::error_code RelocationRef::getHidden(bool &Result) const { - return OwningObject->getRelocationHidden(RelocationPimpl, Result); -} - inline DataRefImpl RelocationRef::getRawDataRefImpl() const { return RelocationPimpl; } -inline const ObjectFile *RelocationRef::getObjectFile() const { +inline const ObjectFile *RelocationRef::getObject() const { return OwningObject; } diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index 91eafd55ad7..d5e4258cb0a 100644 --- a/include/llvm/Object/RelocVisitor.h +++ b/include/llvm/Object/RelocVisitor.h @@ -19,9 +19,11 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Object/COFF.h" #include "llvm/Object/ELFObjectFile.h" +#include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" +#include "llvm/Support/MachO.h" #include "llvm/Support/raw_ostream.h" namespace llvm { @@ -52,6 +54,8 @@ class RelocVisitor { return visitELF(RelocType, R, Value); if (isa(ObjToVisit)) return visitCOFF(RelocType, R, Value); + if (isa(ObjToVisit)) + return visitMachO(RelocType, R, Value); HasError = true; return RelocToApply(); @@ -96,9 +100,9 @@ class RelocVisitor { case Triple::mips64: switch (RelocType) { case llvm::ELF::R_MIPS_32: - return visitELF_MIPS_32(R, Value); + return visitELF_MIPS64_32(R, Value); case llvm::ELF::R_MIPS_64: - return visitELF_MIPS_64(R, Value); + return visitELF_MIPS64_64(R, Value); default: HasError = true; return RelocToApply(); @@ -221,37 +225,32 @@ class RelocVisitor { return RelocToApply(); } - int64_t getELFAddend32LE(RelocationRef R) { - const ELF32LEObjectFile *Obj = cast(R.getObjectFile()); - DataRefImpl DRI = R.getRawDataRefImpl(); - int64_t Addend; - Obj->getRelocationAddend(DRI, Addend); - return Addend; + RelocToApply visitMachO(uint32_t RelocType, RelocationRef R, uint64_t Value) { + switch (ObjToVisit.getArch()) { + default: break; + case Triple::x86_64: + switch (RelocType) { + default: break; + case MachO::X86_64_RELOC_UNSIGNED: + return visitMACHO_X86_64_UNSIGNED(R, Value); + } + } + HasError = true; + return RelocToApply(); } - int64_t getELFAddend64LE(RelocationRef R) { - const ELF64LEObjectFile *Obj = cast(R.getObjectFile()); - DataRefImpl DRI = R.getRawDataRefImpl(); - int64_t Addend; - Obj->getRelocationAddend(DRI, Addend); - return Addend; + int64_t getELFAddend(RelocationRef R) { + ErrorOr AddendOrErr = ELFRelocationRef(R).getAddend(); + if (std::error_code EC = AddendOrErr.getError()) + report_fatal_error(EC.message()); + return *AddendOrErr; } - int64_t getELFAddend32BE(RelocationRef R) { - const ELF32BEObjectFile *Obj = cast(R.getObjectFile()); - DataRefImpl DRI = R.getRawDataRefImpl(); - int64_t Addend; - Obj->getRelocationAddend(DRI, Addend); - return Addend; + uint8_t getLengthMachO64(RelocationRef R) { + const MachOObjectFile *Obj = cast(R.getObject()); + return Obj->getRelocationLength(R.getRawDataRefImpl()); } - int64_t getELFAddend64BE(RelocationRef R) { - const ELF64BEObjectFile *Obj = cast(R.getObjectFile()); - DataRefImpl DRI = R.getRawDataRefImpl(); - int64_t Addend; - Obj->getRelocationAddend(DRI, Addend); - return Addend; - } /// Operations /// 386-ELF @@ -262,15 +261,12 @@ class RelocVisitor { // Ideally the Addend here will be the addend in the data for // the relocation. It's not actually the case for Rel relocations. RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) { - int64_t Addend = getELFAddend32LE(R); - return RelocToApply(Value + Addend, 4); + return RelocToApply(Value, 4); } RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value) { - int64_t Addend = getELFAddend32LE(R); - uint64_t Address; - R.getOffset(Address); - return RelocToApply(Value + Addend - Address, 4); + uint64_t Address = R.getOffset(); + return RelocToApply(Value - Address, 4); } /// X86-64 ELF @@ -278,65 +274,65 @@ class RelocVisitor { return RelocToApply(0, 0); } RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) { - int64_t Addend = getELFAddend64LE(R); + int64_t Addend = getELFAddend(R); return RelocToApply(Value + Addend, 8); } RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value) { - int64_t Addend = getELFAddend64LE(R); - uint64_t Address; - R.getOffset(Address); + int64_t Addend = getELFAddend(R); + uint64_t Address = R.getOffset(); return RelocToApply(Value + Addend - Address, 4); } RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) { - int64_t Addend = getELFAddend64LE(R); + int64_t Addend = getELFAddend(R); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) { - int64_t Addend = getELFAddend64LE(R); + int64_t Addend = getELFAddend(R); int32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } /// PPC64 ELF RelocToApply visitELF_PPC64_ADDR32(RelocationRef R, uint64_t Value) { - int64_t Addend; - getELFRelocationAddend(R, Addend); + int64_t Addend = getELFAddend(R); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } RelocToApply visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) { - int64_t Addend; - getELFRelocationAddend(R, Addend); + int64_t Addend = getELFAddend(R); return RelocToApply(Value + Addend, 8); } /// PPC32 ELF RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) { - int64_t Addend = getELFAddend32BE(R); + int64_t Addend = getELFAddend(R); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } /// MIPS ELF RelocToApply visitELF_MIPS_32(RelocationRef R, uint64_t Value) { - int64_t Addend; - getELFRelocationAddend(R, Addend); + uint32_t Res = Value & 0xFFFFFFFF; + return RelocToApply(Res, 4); + } + + /// MIPS64 ELF + RelocToApply visitELF_MIPS64_32(RelocationRef R, uint64_t Value) { + int64_t Addend = getELFAddend(R); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } - RelocToApply visitELF_MIPS_64(RelocationRef R, uint64_t Value) { - int64_t Addend; - getELFRelocationAddend(R, Addend); + RelocToApply visitELF_MIPS64_64(RelocationRef R, uint64_t Value) { + int64_t Addend = getELFAddend(R); uint64_t Res = (Value + Addend); return RelocToApply(Res, 8); } // AArch64 ELF RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) { - int64_t Addend; - getELFRelocationAddend(R, Addend); + int64_t Addend = getELFAddend(R); int64_t Res = Value + Addend; // Overflow check allows for both signed and unsigned interpretation. @@ -347,14 +343,13 @@ class RelocVisitor { } RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) { - int64_t Addend; - getELFRelocationAddend(R, Addend); + int64_t Addend = getELFAddend(R); return RelocToApply(Value + Addend, 8); } // SystemZ ELF RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) { - int64_t Addend = getELFAddend64BE(R); + int64_t Addend = getELFAddend(R); int64_t Res = Value + Addend; // Overflow check allows for both signed and unsigned interpretation. @@ -365,29 +360,27 @@ class RelocVisitor { } RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) { - int64_t Addend = getELFAddend64BE(R); + int64_t Addend = getELFAddend(R); return RelocToApply(Value + Addend, 8); } RelocToApply visitELF_SPARC_32(RelocationRef R, uint32_t Value) { - int32_t Addend = getELFAddend32BE(R); + int32_t Addend = getELFAddend(R); return RelocToApply(Value + Addend, 4); } RelocToApply visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) { - int32_t Addend = getELFAddend64BE(R); + int32_t Addend = getELFAddend(R); return RelocToApply(Value + Addend, 4); } RelocToApply visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) { - int64_t Addend = getELFAddend64BE(R); + int64_t Addend = getELFAddend(R); return RelocToApply(Value + Addend, 8); } RelocToApply visitELF_ARM_ABS32(RelocationRef R, uint64_t Value) { - int64_t Addend; - getELFRelocationAddend(R, Addend); - int64_t Res = Value + Addend; + int64_t Res = Value; // Overflow check allows for both signed and unsigned interpretation. if (Res < INT32_MIN || Res > UINT32_MAX) @@ -413,6 +406,13 @@ class RelocVisitor { RelocToApply visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) { return RelocToApply(Value, /*Width=*/8); } + + // X86_64 MachO + RelocToApply visitMACHO_X86_64_UNSIGNED(RelocationRef R, uint64_t Value) { + uint8_t Length = getLengthMachO64(R); + Length = 1< +#include + +namespace llvm { + +template +class StackMapV1Parser { +public: + + template + class AccessorIterator { + public: + + AccessorIterator(AccessorT A) : A(A) {} + AccessorIterator& operator++() { A = A.next(); return *this; } + AccessorIterator operator++(int) { + auto tmp = *this; + ++*this; + return tmp; + } + + bool operator==(const AccessorIterator &Other) { + return A.P == Other.A.P; + } + + bool operator!=(const AccessorIterator &Other) { return !(*this == Other); } + + AccessorT& operator*() { return A; } + AccessorT* operator->() { return &A; } + + private: + AccessorT A; + }; + + /// Accessor for function records. + class FunctionAccessor { + friend class StackMapV1Parser; + public: + + /// Get the function address. + uint64_t getFunctionAddress() const { + return read(P); + } + + /// Get the function's stack size. + uint32_t getStackSize() const { + return read(P + sizeof(uint64_t)); + } + + private: + FunctionAccessor(const uint8_t *P) : P(P) {} + + const static int FunctionAccessorSize = 2 * sizeof(uint64_t); + + FunctionAccessor next() const { + return FunctionAccessor(P + FunctionAccessorSize); + } + + const uint8_t *P; + }; + + /// Accessor for constants. + class ConstantAccessor { + friend class StackMapV1Parser; + public: + + /// Return the value of this constant. + uint64_t getValue() const { return read(P); } + + private: + + ConstantAccessor(const uint8_t *P) : P(P) {} + + const static int ConstantAccessorSize = sizeof(uint64_t); + + ConstantAccessor next() const { + return ConstantAccessor(P + ConstantAccessorSize); + } + + const uint8_t *P; + }; + + // Forward-declare RecordAccessor so we can friend it below. + class RecordAccessor; + + enum class LocationKind : uint8_t { + Register = 1, Direct = 2, Indirect = 3, Constant = 4, ConstantIndex = 5 + }; + + + /// Accessor for location records. + class LocationAccessor { + friend class StackMapV1Parser; + friend class RecordAccessor; + public: + + /// Get the Kind for this location. + LocationKind getKind() const { + return LocationKind(P[KindOffset]); + } + + /// Get the Dwarf register number for this location. + uint16_t getDwarfRegNum() const { + return read(P + DwarfRegNumOffset); + } + + /// Get the small-constant for this location. (Kind must be Constant). + uint32_t getSmallConstant() const { + assert(getKind() == LocationKind::Constant && "Not a small constant."); + return read(P + SmallConstantOffset); + } + + /// Get the constant-index for this location. (Kind must be ConstantIndex). + uint32_t getConstantIndex() const { + assert(getKind() == LocationKind::ConstantIndex && + "Not a constant-index."); + return read(P + SmallConstantOffset); + } + + /// Get the offset for this location. (Kind must be Direct or Indirect). + int32_t getOffset() const { + assert((getKind() == LocationKind::Direct || + getKind() == LocationKind::Indirect) && + "Not direct or indirect."); + return read(P + SmallConstantOffset); + } + + private: + + LocationAccessor(const uint8_t *P) : P(P) {} + + LocationAccessor next() const { + return LocationAccessor(P + LocationAccessorSize); + } + + static const int KindOffset = 0; + static const int DwarfRegNumOffset = KindOffset + sizeof(uint16_t); + static const int SmallConstantOffset = DwarfRegNumOffset + sizeof(uint16_t); + static const int LocationAccessorSize = sizeof(uint64_t); + + const uint8_t *P; + }; + + /// Accessor for stackmap live-out fields. + class LiveOutAccessor { + friend class StackMapV1Parser; + friend class RecordAccessor; + public: + + /// Get the Dwarf register number for this live-out. + uint16_t getDwarfRegNum() const { + return read(P + DwarfRegNumOffset); + } + + /// Get the size in bytes of live [sub]register. + unsigned getSizeInBytes() const { + return read(P + SizeOffset); + } + + private: + + LiveOutAccessor(const uint8_t *P) : P(P) {} + + LiveOutAccessor next() const { + return LiveOutAccessor(P + LiveOutAccessorSize); + } + + static const int DwarfRegNumOffset = 0; + static const int SizeOffset = + DwarfRegNumOffset + sizeof(uint16_t) + sizeof(uint8_t); + static const int LiveOutAccessorSize = sizeof(uint32_t); + + const uint8_t *P; + }; + + /// Accessor for stackmap records. + class RecordAccessor { + friend class StackMapV1Parser; + public: + + typedef AccessorIterator location_iterator; + typedef AccessorIterator liveout_iterator; + + /// Get the patchpoint/stackmap ID for this record. + uint64_t getID() const { + return read(P + PatchpointIDOffset); + } + + /// Get the instruction offset (from the start of the containing function) + /// for this record. + uint32_t getInstructionOffset() const { + return read(P + InstructionOffsetOffset); + } + + /// Get the number of locations contained in this record. + uint16_t getNumLocations() const { + return read(P + NumLocationsOffset); + } + + /// Get the location with the given index. + LocationAccessor getLocation(unsigned LocationIndex) const { + unsigned LocationOffset = + LocationListOffset + LocationIndex * LocationSize; + return LocationAccessor(P + LocationOffset); + } + + /// Begin iterator for locations. + location_iterator location_begin() const { + return location_iterator(getLocation(0)); + } + + /// End iterator for locations. + location_iterator location_end() const { + return location_iterator(getLocation(getNumLocations())); + } + + /// Iterator range for locations. + iterator_range locations() const { + return make_range(location_begin(), location_end()); + } + + /// Get the number of liveouts contained in this record. + uint16_t getNumLiveOuts() const { + return read(P + getNumLiveOutsOffset()); + } + + /// Get the live-out with the given index. + LiveOutAccessor getLiveOut(unsigned LiveOutIndex) const { + unsigned LiveOutOffset = + getNumLiveOutsOffset() + sizeof(uint16_t) + LiveOutIndex * LiveOutSize; + return LiveOutAccessor(P + LiveOutOffset); + } + + /// Begin iterator for live-outs. + liveout_iterator liveouts_begin() const { + return liveout_iterator(getLiveOut(0)); + } + + + /// End iterator for live-outs. + liveout_iterator liveouts_end() const { + return liveout_iterator(getLiveOut(getNumLiveOuts())); + } + + /// Iterator range for live-outs. + iterator_range liveouts() const { + return make_range(liveouts_begin(), liveouts_end()); + } + + private: + + RecordAccessor(const uint8_t *P) : P(P) {} + + unsigned getNumLiveOutsOffset() const { + return LocationListOffset + LocationSize * getNumLocations() + + sizeof(uint16_t); + } + + unsigned getSizeInBytes() const { + unsigned RecordSize = + getNumLiveOutsOffset() + sizeof(uint16_t) + getNumLiveOuts() * LiveOutSize; + return (RecordSize + 7) & ~0x7; + } + + RecordAccessor next() const { + return RecordAccessor(P + getSizeInBytes()); + } + + static const unsigned PatchpointIDOffset = 0; + static const unsigned InstructionOffsetOffset = + PatchpointIDOffset + sizeof(uint64_t); + static const unsigned NumLocationsOffset = + InstructionOffsetOffset + sizeof(uint32_t) + sizeof(uint16_t); + static const unsigned LocationListOffset = + NumLocationsOffset + sizeof(uint16_t); + static const unsigned LocationSize = sizeof(uint64_t); + static const unsigned LiveOutSize = sizeof(uint32_t); + + const uint8_t *P; + }; + + /// Construct a parser for a version-1 stackmap. StackMap data will be read + /// from the given array. + StackMapV1Parser(ArrayRef StackMapSection) + : StackMapSection(StackMapSection) { + ConstantsListOffset = FunctionListOffset + getNumFunctions() * FunctionSize; + + assert(StackMapSection[0] == 1 && + "StackMapV1Parser can only parse version 1 stackmaps"); + + unsigned CurrentRecordOffset = + ConstantsListOffset + getNumConstants() * ConstantSize; + + for (unsigned I = 0, E = getNumRecords(); I != E; ++I) { + StackMapRecordOffsets.push_back(CurrentRecordOffset); + CurrentRecordOffset += + RecordAccessor(&StackMapSection[CurrentRecordOffset]).getSizeInBytes(); + } + } + + typedef AccessorIterator function_iterator; + typedef AccessorIterator constant_iterator; + typedef AccessorIterator record_iterator; + + /// Get the version number of this stackmap. (Always returns 1). + unsigned getVersion() const { return 1; } + + /// Get the number of functions in the stack map. + uint32_t getNumFunctions() const { + return read(&StackMapSection[NumFunctionsOffset]); + } + + /// Get the number of large constants in the stack map. + uint32_t getNumConstants() const { + return read(&StackMapSection[NumConstantsOffset]); + } + + /// Get the number of stackmap records in the stackmap. + uint32_t getNumRecords() const { + return read(&StackMapSection[NumRecordsOffset]); + } + + /// Return an FunctionAccessor for the given function index. + FunctionAccessor getFunction(unsigned FunctionIndex) const { + return FunctionAccessor(StackMapSection.data() + + getFunctionOffset(FunctionIndex)); + } + + /// Begin iterator for functions. + function_iterator functions_begin() const { + return function_iterator(getFunction(0)); + } + + /// End iterator for functions. + function_iterator functions_end() const { + return function_iterator( + FunctionAccessor(StackMapSection.data() + + getFunctionOffset(getNumFunctions()))); + } + + /// Iterator range for functions. + iterator_range functions() const { + return make_range(functions_begin(), functions_end()); + } + + /// Return the large constant at the given index. + ConstantAccessor getConstant(unsigned ConstantIndex) const { + return ConstantAccessor(StackMapSection.data() + + getConstantOffset(ConstantIndex)); + } + + /// Begin iterator for constants. + constant_iterator constants_begin() const { + return constant_iterator(getConstant(0)); + } + + /// End iterator for constants. + constant_iterator constants_end() const { + return constant_iterator( + ConstantAccessor(StackMapSection.data() + + getConstantOffset(getNumConstants()))); + } + + /// Iterator range for constants. + iterator_range constants() const { + return make_range(constants_begin(), constants_end()); + } + + /// Return a RecordAccessor for the given record index. + RecordAccessor getRecord(unsigned RecordIndex) const { + std::size_t RecordOffset = StackMapRecordOffsets[RecordIndex]; + return RecordAccessor(StackMapSection.data() + RecordOffset); + } + + /// Begin iterator for records. + record_iterator records_begin() const { + if (getNumRecords() == 0) + return record_iterator(RecordAccessor(nullptr)); + return record_iterator(getRecord(0)); + } + + /// End iterator for records. + record_iterator records_end() const { + // Records need to be handled specially, since we cache the start addresses + // for them: We can't just compute the 1-past-the-end address, we have to + // look at the last record and use the 'next' method. + if (getNumRecords() == 0) + return record_iterator(RecordAccessor(nullptr)); + return record_iterator(getRecord(getNumRecords() - 1).next()); + } + + /// Iterator range for records. + iterator_range records() const { + return make_range(records_begin(), records_end()); + } + +private: + + template + static T read(const uint8_t *P) { + return support::endian::read(P); + } + + static const unsigned HeaderOffset = 0; + static const unsigned NumFunctionsOffset = HeaderOffset + sizeof(uint32_t); + static const unsigned NumConstantsOffset = NumFunctionsOffset + sizeof(uint32_t); + static const unsigned NumRecordsOffset = NumConstantsOffset + sizeof(uint32_t); + static const unsigned FunctionListOffset = NumRecordsOffset + sizeof(uint32_t); + + static const unsigned FunctionSize = 2 * sizeof(uint64_t); + static const unsigned ConstantSize = sizeof(uint64_t); + + std::size_t getFunctionOffset(unsigned FunctionIndex) const { + return FunctionListOffset + FunctionIndex * FunctionSize; + } + + std::size_t getConstantOffset(unsigned ConstantIndex) const { + return ConstantsListOffset + ConstantIndex * ConstantSize; + } + + ArrayRef StackMapSection; + unsigned ConstantsListOffset; + std::vector StackMapRecordOffsets; +}; + +} + +#endif diff --git a/include/llvm/Object/SymbolSize.h b/include/llvm/Object/SymbolSize.h new file mode 100644 index 00000000000..f2ce70f4208 --- /dev/null +++ b/include/llvm/Object/SymbolSize.h @@ -0,0 +1,23 @@ +//===- SymbolSize.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_OBJECT_SYMBOLSIZE_H +#define LLVM_OBJECT_SYMBOLSIZE_H + +#include "llvm/Object/ObjectFile.h" + +namespace llvm { +namespace object { +std::vector> +computeSymbolSizes(const ObjectFile &O); +} +} // namespace llvm + +#endif diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h index 114b229b822..6b10ceb263a 100644 --- a/include/llvm/Object/SymbolicFile.h +++ b/include/llvm/Object/SymbolicFile.h @@ -15,6 +15,7 @@ #define LLVM_OBJECT_SYMBOLICFILE_H #include "llvm/Object/Binary.h" +#include "llvm/Support/Format.h" namespace llvm { namespace object { @@ -29,6 +30,12 @@ union DataRefImpl { DataRefImpl() { std::memset(this, 0, sizeof(DataRefImpl)); } }; +template +OStream& operator<<(OStream &OS, const DataRefImpl &D) { + OS << "(" << format("0x%x8", D.p) << " (" << format("0x%x8", D.d.a) << ", " << format("0x%x8", D.d.b) << "))"; + return OS; +} + inline bool operator==(const DataRefImpl &a, const DataRefImpl &b) { // Check bitwise identical. This is the only legal way to compare a union w/o // knowing which member is in use. @@ -93,6 +100,7 @@ class BasicSymbolRef { SF_FormatSpecific = 1U << 7, // Specific to the object file format // (e.g. section symbols) SF_Thumb = 1U << 8, // Thumb symbol in a 32-bit ARM binary + SF_Hidden = 1U << 9, // Symbol has hidden visibility }; BasicSymbolRef() : OwningObject(nullptr) { } @@ -114,8 +122,6 @@ class BasicSymbolRef { typedef content_iterator basic_symbol_iterator; -const uint64_t UnknownAddressOrSize = ~0ULL; - class SymbolicFile : public Binary { public: ~SymbolicFile() override; diff --git a/include/llvm/Option/Arg.h b/include/llvm/Option/Arg.h index 5f6941a53d0..e1b72b6267c 100644 --- a/include/llvm/Option/Arg.h +++ b/include/llvm/Option/Arg.h @@ -93,9 +93,8 @@ class Arg { return Values[N]; } - SmallVectorImpl &getValues() { - return Values; - } + SmallVectorImpl &getValues() { return Values; } + const SmallVectorImpl &getValues() const { return Values; } bool containsValue(StringRef Value) const { for (unsigned i = 0, e = getNumValues(); i != e; ++i) diff --git a/include/llvm/Option/ArgList.h b/include/llvm/Option/ArgList.h index 23b04513178..0a78e935afa 100644 --- a/include/llvm/Option/ArgList.h +++ b/include/llvm/Option/ArgList.h @@ -14,6 +14,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/Option/Arg.h" #include "llvm/Option/OptSpecifier.h" #include "llvm/Option/Option.h" #include @@ -23,7 +24,6 @@ namespace llvm { namespace opt { -class Arg; class ArgList; class Option; @@ -92,10 +92,6 @@ class arg_iterator { /// check for the presence of Arg instances for a particular Option /// and to iterate over groups of arguments. class ArgList { -private: - ArgList(const ArgList &) = delete; - void operator=(const ArgList &) = delete; - public: typedef SmallVector arglist_type; typedef arglist_type::iterator iterator; @@ -108,12 +104,23 @@ class ArgList { arglist_type Args; protected: - // Default ctor provided explicitly as it is not provided implicitly due to - // the presence of the (deleted) copy ctor above. - ArgList() { } - // Virtual to provide a vtable anchor and because -Wnon-virtua-dtor warns, not - // because this type is ever actually destroyed polymorphically. - virtual ~ArgList(); + // Make the default special members protected so they won't be used to slice + // derived objects, but can still be used by derived objects to implement + // their own special members. + ArgList() = default; + // Explicit move operations to ensure the container is cleared post-move + // otherwise it could lead to a double-delete in the case of moving of an + // InputArgList which deletes the contents of the container. If we could fix + // up the ownership here (delegate storage/ownership to the derived class so + // it can be a container of unique_ptr) this would be simpler. + ArgList(ArgList &&RHS) : Args(std::move(RHS.Args)) { RHS.Args.clear(); } + ArgList &operator=(ArgList &&RHS) { + Args = std::move(RHS.Args); + RHS.Args.clear(); + return *this; + } + // Protect the dtor to ensure this type is never destroyed polymorphically. + ~ArgList() = default; public: @@ -252,6 +259,9 @@ class ArgList { void AddLastArg(ArgStringList &Output, OptSpecifier Id0, OptSpecifier Id1) const; + /// AddAllArgs - Render all arguments matching any of the given ids. + void AddAllArgs(ArgStringList &Output, ArrayRef Ids) const; + /// AddAllArgs - Render all arguments matching the given ids. void AddAllArgs(ArgStringList &Output, OptSpecifier Id0, OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const; @@ -299,7 +309,7 @@ class ArgList { /// @} }; -class InputArgList : public ArgList { +class InputArgList final : public ArgList { private: /// List of argument strings used by the contained Args. /// @@ -318,9 +328,24 @@ class InputArgList : public ArgList { /// The number of original input argument strings. unsigned NumInputArgStrings; + /// Release allocated arguments. + void releaseMemory(); + public: InputArgList(const char* const *ArgBegin, const char* const *ArgEnd); - ~InputArgList() override; + InputArgList(InputArgList &&RHS) + : ArgList(std::move(RHS)), ArgStrings(std::move(RHS.ArgStrings)), + SynthesizedStrings(std::move(RHS.SynthesizedStrings)), + NumInputArgStrings(RHS.NumInputArgStrings) {} + InputArgList &operator=(InputArgList &&RHS) { + releaseMemory(); + ArgList::operator=(std::move(RHS)); + ArgStrings = std::move(RHS.ArgStrings); + SynthesizedStrings = std::move(RHS.SynthesizedStrings); + NumInputArgStrings = RHS.NumInputArgStrings; + return *this; + } + ~InputArgList() { releaseMemory(); } const char *getArgString(unsigned Index) const override { return ArgStrings[Index]; @@ -346,7 +371,7 @@ class InputArgList : public ArgList { /// DerivedArgList - An ordered collection of driver arguments, /// whose storage may be in another argument list. -class DerivedArgList : public ArgList { +class DerivedArgList final : public ArgList { const InputArgList &BaseArgs; /// The list of arguments we synthesized. @@ -355,7 +380,6 @@ class DerivedArgList : public ArgList { public: /// Construct a new derived arg list from \p BaseArgs. DerivedArgList(const InputArgList &BaseArgs); - ~DerivedArgList() override; const char *getArgString(unsigned Index) const override { return BaseArgs.getArgString(Index); diff --git a/include/llvm/Option/OptTable.h b/include/llvm/Option/OptTable.h index a7ff46919cd..96f51cf3317 100644 --- a/include/llvm/Option/OptTable.h +++ b/include/llvm/Option/OptTable.h @@ -10,6 +10,7 @@ #ifndef LLVM_OPTION_OPTTABLE_H #define LLVM_OPTION_OPTTABLE_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/Option/OptSpecifier.h" @@ -141,8 +142,6 @@ class OptTable { /// The only error that can occur in this routine is if an argument is /// missing values; in this case \p MissingArgCount will be non-zero. /// - /// \param ArgBegin - The beginning of the argument vector. - /// \param ArgEnd - The end of the argument vector. /// \param MissingArgIndex - On error, the index of the option which could /// not be parsed. /// \param MissingArgCount - On error, the number of missing options. @@ -152,12 +151,9 @@ class OptTable { /// is the default and means exclude nothing. /// \return An InputArgList; on error this will contain all the options /// which could be parsed. - InputArgList *ParseArgs(const char* const *ArgBegin, - const char* const *ArgEnd, - unsigned &MissingArgIndex, - unsigned &MissingArgCount, - unsigned FlagsToInclude = 0, - unsigned FlagsToExclude = 0) const; + InputArgList ParseArgs(ArrayRef Args, unsigned &MissingArgIndex, + unsigned &MissingArgCount, unsigned FlagsToInclude = 0, + unsigned FlagsToExclude = 0) const; /// \brief Render the help text for an option table. /// diff --git a/include/llvm/PassAnalysisSupport.h b/include/llvm/PassAnalysisSupport.h index 38adb2dbb69..0b318fc8fb0 100644 --- a/include/llvm/PassAnalysisSupport.h +++ b/include/llvm/PassAnalysisSupport.h @@ -27,28 +27,27 @@ namespace llvm { //===----------------------------------------------------------------------===// -// AnalysisUsage - Represent the analysis usage information of a pass. This -// tracks analyses that the pass REQUIRES (must be available when the pass -// runs), REQUIRES TRANSITIVE (must be available throughout the lifetime of the -// pass), and analyses that the pass PRESERVES (the pass does not invalidate the -// results of these analyses). This information is provided by a pass to the -// Pass infrastructure through the getAnalysisUsage virtual function. -// +/// Represent the analysis usage information of a pass. This tracks analyses +/// that the pass REQUIRES (must be available when the pass runs), REQUIRES +/// TRANSITIVE (must be available throughout the lifetime of the pass), and +/// analyses that the pass PRESERVES (the pass does not invalidate the results +/// of these analyses). This information is provided by a pass to the Pass +/// infrastructure through the getAnalysisUsage virtual function. +/// class AnalysisUsage { public: typedef SmallVector VectorType; private: - // Sets of analyses required and preserved by a pass + /// Sets of analyses required and preserved by a pass VectorType Required, RequiredTransitive, Preserved; bool PreservesAll; public: AnalysisUsage() : PreservesAll(false) {} - // addRequired - Add the specified ID to the required set of the usage info - // for a pass. - // + ///@{ + /// Add the specified ID to the required set of the usage info for a pass. AnalysisUsage &addRequiredID(const void *ID); AnalysisUsage &addRequiredID(char &ID); template @@ -61,10 +60,10 @@ class AnalysisUsage { AnalysisUsage &addRequiredTransitive() { return addRequiredTransitiveID(PassClass::ID); } + ///@} - // addPreserved - Add the specified ID to the set of analyses preserved by - // this pass - // + ///@{ + /// Add the specified ID to the set of analyses preserved by this pass. AnalysisUsage &addPreservedID(const void *ID) { Preserved.push_back(ID); return *this; @@ -73,29 +72,28 @@ class AnalysisUsage { Preserved.push_back(&ID); return *this; } + ///@} - // addPreserved - Add the specified Pass class to the set of analyses - // preserved by this pass. - // + /// Add the specified Pass class to the set of analyses preserved by this pass. template AnalysisUsage &addPreserved() { Preserved.push_back(&PassClass::ID); return *this; } - // addPreserved - Add the Pass with the specified argument string to the set - // of analyses preserved by this pass. If no such Pass exists, do nothing. - // This can be useful when a pass is trivially preserved, but may not be - // linked in. Be careful about spelling! - // + /// Add the Pass with the specified argument string to the set of analyses + /// preserved by this pass. If no such Pass exists, do nothing. This can be + /// useful when a pass is trivially preserved, but may not be linked in. Be + /// careful about spelling! AnalysisUsage &addPreserved(StringRef Arg); - // setPreservesAll - Set by analyses that do not transform their input at all + /// Set by analyses that do not transform their input at all void setPreservesAll() { PreservesAll = true; } + + /// Determine whether a pass said it does not transform its input at all bool getPreservesAll() const { return PreservesAll; } - /// setPreservesCFG - This function should be called by the pass, iff they do - /// not: + /// This function should be called by the pass, iff they do not: /// /// 1. Add or remove basic blocks from the function /// 2. Modify terminator instructions in any way. @@ -113,10 +111,10 @@ class AnalysisUsage { }; //===----------------------------------------------------------------------===// -// AnalysisResolver - Simple interface used by Pass objects to pull all -// analysis information out of pass manager that is responsible to manage -// the pass. -// +/// AnalysisResolver - Simple interface used by Pass objects to pull all +/// analysis information out of pass manager that is responsible to manage +/// the pass. +/// class PMDataManager; class AnalysisResolver { private: @@ -124,10 +122,10 @@ class AnalysisResolver { public: explicit AnalysisResolver(PMDataManager &P) : PM(P) { } - + inline PMDataManager &getPMDataManager() { return PM; } - // Find pass that is implementing PI. + /// Find pass that is implementing PI. Pass *findImplPass(AnalysisID PI) { Pass *ResultPass = nullptr; for (unsigned i = 0; i < AnalysisImpls.size() ; ++i) { @@ -139,7 +137,7 @@ class AnalysisResolver { return ResultPass; } - // Find pass that is implementing PI. Initialize pass for Function F. + /// Find pass that is implementing PI. Initialize pass for Function F. Pass *findImplPass(Pass *P, AnalysisID PI, Function &F); void addAnalysisImplsPair(AnalysisID PI, Pass *P) { @@ -149,21 +147,20 @@ class AnalysisResolver { AnalysisImpls.push_back(pir); } - /// clearAnalysisImpls - Clear cache that is used to connect a pass to the - /// the analysis (PassInfo). + /// Clear cache that is used to connect a pass to the the analysis (PassInfo). void clearAnalysisImpls() { AnalysisImpls.clear(); } - // getAnalysisIfAvailable - Return analysis result or null if it doesn't exist + /// Return analysis result or null if it doesn't exist. Pass *getAnalysisIfAvailable(AnalysisID ID, bool Direction) const; private: - // AnalysisImpls - This keeps track of which passes implements the interfaces - // that are required by the current pass (to implement getAnalysis()). + /// This keeps track of which passes implements the interfaces that are + /// required by the current pass (to implement getAnalysis()). std::vector > AnalysisImpls; - // PassManager that is used to resolve analysis info + /// PassManager that is used to resolve analysis info PMDataManager &PM; }; @@ -240,7 +237,7 @@ AnalysisType &Pass::getAnalysisID(AnalysisID PI, Function &F) { // vector. Pass *ResultPass = Resolver->findImplPass(this, PI, F); assert(ResultPass && "Unable to find requested analysis info"); - + // Because the AnalysisType may not be a subclass of pass (for // AnalysisGroups), we use getAdjustedAnalysisPointer here to potentially // adjust the return pointer (because the class may multiply inherit, once diff --git a/include/llvm/ProfileData/CoverageMapping.h b/include/llvm/ProfileData/CoverageMapping.h index e9d6ea5a492..3488e793d84 100644 --- a/include/llvm/ProfileData/CoverageMapping.h +++ b/include/llvm/ProfileData/CoverageMapping.h @@ -410,7 +410,7 @@ class CoverageMapping { /// \brief Load the coverage mapping from the given files. static ErrorOr> load(StringRef ObjectFilename, StringRef ProfileFilename, - Triple::ArchType Arch = Triple::ArchType::UnknownArch); + StringRef Arch = StringRef()); /// \brief The number of functions that couldn't have their profiles mapped. /// @@ -484,7 +484,26 @@ template<> struct DenseMapInfo { } }; +const std::error_category &coveragemap_category(); + +enum class coveragemap_error { + success = 0, + eof, + no_data_found, + unsupported_version, + truncated, + malformed +}; + +inline std::error_code make_error_code(coveragemap_error E) { + return std::error_code(static_cast(E), coveragemap_category()); +} } // end namespace llvm +namespace std { +template <> +struct is_error_code_enum : std::true_type {}; +} + #endif // LLVM_PROFILEDATA_COVERAGEMAPPING_H_ diff --git a/include/llvm/ProfileData/CoverageMappingReader.h b/include/llvm/ProfileData/CoverageMappingReader.h index bc68f0b47a2..38fb4680476 100644 --- a/include/llvm/ProfileData/CoverageMappingReader.h +++ b/include/llvm/ProfileData/CoverageMappingReader.h @@ -80,12 +80,6 @@ class RawCoverageReader { protected: StringRef Data; - /// \brief Return the error code. - std::error_code error(std::error_code EC) { return EC; } - - /// \brief Clear the current error code and return a successful one. - std::error_code success() { return error(instrprof_error::success); } - RawCoverageReader(StringRef Data) : Data(Data) {} std::error_code readULEB128(uint64_t &Result); @@ -177,7 +171,7 @@ class BinaryCoverageReader : public CoverageMappingReader { public: static ErrorOr> create(std::unique_ptr &ObjectBuffer, - Triple::ArchType Arch = Triple::ArchType::UnknownArch); + StringRef Arch); std::error_code readNextRecord(CoverageMappingRecord &Record) override; }; diff --git a/include/llvm/ProfileData/InstrProf.h b/include/llvm/ProfileData/InstrProf.h index eafb76886c8..77055ba8726 100644 --- a/include/llvm/ProfileData/InstrProf.h +++ b/include/llvm/ProfileData/InstrProf.h @@ -16,7 +16,10 @@ #ifndef LLVM_PROFILEDATA_INSTRPROF_H_ #define LLVM_PROFILEDATA_INSTRPROF_H_ +#include "llvm/ADT/StringRef.h" +#include #include +#include namespace llvm { const std::error_category &instrprof_category(); @@ -41,6 +44,16 @@ inline std::error_code make_error_code(instrprof_error E) { return std::error_code(static_cast(E), instrprof_category()); } +/// Profiling information for a single function. +struct InstrProfRecord { + InstrProfRecord() {} + InstrProfRecord(StringRef Name, uint64_t Hash, std::vector Counts) + : Name(Name), Hash(Hash), Counts(std::move(Counts)) {} + StringRef Name; + uint64_t Hash; + std::vector Counts; +}; + } // end namespace llvm namespace std { diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h index 63a6ac671f2..f937e7d08d5 100644 --- a/include/llvm/ProfileData/InstrProfReader.h +++ b/include/llvm/ProfileData/InstrProfReader.h @@ -29,16 +29,6 @@ namespace llvm { class InstrProfReader; -/// Profiling information for a single function. -struct InstrProfRecord { - InstrProfRecord() {} - InstrProfRecord(StringRef Name, uint64_t Hash, ArrayRef Counts) - : Name(Name), Hash(Hash), Counts(Counts) {} - StringRef Name; - uint64_t Hash; - ArrayRef Counts; -}; - /// A file format agnostic iterator over profiling data. class InstrProfIterator : public std::iterator { @@ -114,8 +104,6 @@ class TextInstrProfReader : public InstrProfReader { std::unique_ptr DataBuffer; /// Iterator over the profile data. line_iterator Line; - /// The current set of counter values. - std::vector Counts; TextInstrProfReader(const TextInstrProfReader &) = delete; TextInstrProfReader &operator=(const TextInstrProfReader &) = delete; @@ -141,8 +129,6 @@ class RawInstrProfReader : public InstrProfReader { private: /// The profile data file contents. std::unique_ptr DataBuffer; - /// The current set of counter values. - std::vector Counts; struct ProfileData { const uint32_t NameSize; const uint32_t NumCounters; @@ -206,17 +192,16 @@ enum class HashT : uint32_t; /// Trait for lookups into the on-disk hash table for the binary instrprof /// format. class InstrProfLookupTrait { - std::vector DataBuffer; + std::vector DataBuffer; IndexedInstrProf::HashT HashType; + unsigned FormatVersion; + public: - InstrProfLookupTrait(IndexedInstrProf::HashT HashType) : HashType(HashType) {} + InstrProfLookupTrait(IndexedInstrProf::HashT HashType, unsigned FormatVersion) + : HashType(HashType), FormatVersion(FormatVersion) {} + + typedef ArrayRef data_type; - struct data_type { - data_type(StringRef Name, ArrayRef Data) - : Name(Name), Data(Data) {} - StringRef Name; - ArrayRef Data; - }; typedef StringRef internal_key_type; typedef StringRef external_key_type; typedef uint64_t hash_value_type; @@ -239,22 +224,9 @@ class InstrProfLookupTrait { return StringRef((const char *)D, N); } - data_type ReadData(StringRef K, const unsigned char *D, offset_type N) { - DataBuffer.clear(); - if (N % sizeof(uint64_t)) - // The data is corrupt, don't try to read it. - return data_type("", DataBuffer); - - using namespace support; - // We just treat the data as opaque here. It's simpler to handle in - // IndexedInstrProfReader. - unsigned NumEntries = N / sizeof(uint64_t); - DataBuffer.reserve(NumEntries); - for (unsigned I = 0; I < NumEntries; ++I) - DataBuffer.push_back(endian::readNext(D)); - return data_type(K, DataBuffer); - } + data_type ReadData(StringRef K, const unsigned char *D, offset_type N); }; + typedef OnDiskIterableChainedHashTable InstrProfReaderIndex; @@ -267,8 +239,6 @@ class IndexedInstrProfReader : public InstrProfReader { std::unique_ptr Index; /// Iterator over the profile data. InstrProfReaderIndex::data_iterator RecordIterator; - /// Offset into our current data set. - size_t CurrentOffset; /// The file format version of the profile data. uint64_t FormatVersion; /// The maximal execution count among all functions. @@ -278,7 +248,7 @@ class IndexedInstrProfReader : public InstrProfReader { IndexedInstrProfReader &operator=(const IndexedInstrProfReader &) = delete; public: IndexedInstrProfReader(std::unique_ptr DataBuffer) - : DataBuffer(std::move(DataBuffer)), Index(nullptr), CurrentOffset(0) {} + : DataBuffer(std::move(DataBuffer)), Index(nullptr) {} /// Return true if the given buffer is in an indexed instrprof format. static bool hasFormat(const MemoryBuffer &DataBuffer); diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h index df0a055c2a7..1b82e55aa77 100644 --- a/include/llvm/ProfileData/SampleProf.h +++ b/include/llvm/ProfileData/SampleProf.h @@ -59,7 +59,7 @@ static inline uint64_t SPMagic() { static inline uint64_t SPVersion() { return 100; } -/// \brief Represents the relative location of an instruction. +/// Represents the relative location of an instruction. /// /// Instruction locations are specified by the line offset from the /// beginning of the function (marked by the line where the function @@ -100,7 +100,7 @@ template <> struct DenseMapInfo { namespace sampleprof { -/// \brief Representation of a single sample record. +/// Representation of a single sample record. /// /// A sample record is represented by a positive integer value, which /// indicates how frequently was the associated line location executed. @@ -116,7 +116,7 @@ class SampleRecord { SampleRecord() : NumSamples(0), CallTargets() {} - /// \brief Increment the number of samples for this record by \p S. + /// Increment the number of samples for this record by \p S. /// /// Sample counts accumulate using saturating arithmetic, to avoid wrapping /// around unsigned integers. @@ -127,7 +127,7 @@ class SampleRecord { NumSamples = std::numeric_limits::max(); } - /// \brief Add called function \p F with samples \p S. + /// Add called function \p F with samples \p S. /// /// Sample counts accumulate using saturating arithmetic, to avoid wrapping /// around unsigned integers. @@ -139,13 +139,13 @@ class SampleRecord { TargetSamples = std::numeric_limits::max(); } - /// \brief Return true if this sample record contains function calls. + /// Return true if this sample record contains function calls. bool hasCalls() const { return CallTargets.size() > 0; } unsigned getSamples() const { return NumSamples; } const CallTargetMap &getCallTargets() const { return CallTargets; } - /// \brief Merge the samples in \p Other into this record. + /// Merge the samples in \p Other into this record. void merge(const SampleRecord &Other) { addSamples(Other.getSamples()); for (const auto &I : Other.getCallTargets()) @@ -159,7 +159,7 @@ class SampleRecord { typedef DenseMap BodySampleMap; -/// \brief Representation of the samples collected for a function. +/// Representation of the samples collected for a function. /// /// This data structure contains all the collected samples for the body /// of a function. Each sample corresponds to a LineLocation instance @@ -187,13 +187,13 @@ class FunctionSamples { Num); } - /// \brief Return the sample record at the given location. + /// Return the sample record at the given location. /// Each location is specified by \p LineOffset and \p Discriminator. SampleRecord &sampleRecordAt(const LineLocation &Loc) { return BodySamples[Loc]; } - /// \brief Return the number of samples collected at the given location. + /// Return the number of samples collected at the given location. /// Each location is specified by \p LineOffset and \p Discriminator. unsigned samplesAt(int LineOffset, unsigned Discriminator) { return sampleRecordAt(LineLocation(LineOffset, Discriminator)).getSamples(); @@ -201,17 +201,17 @@ class FunctionSamples { bool empty() const { return BodySamples.empty(); } - /// \brief Return the total number of samples collected inside the function. + /// Return the total number of samples collected inside the function. unsigned getTotalSamples() const { return TotalSamples; } - /// \brief Return the total number of samples collected at the head of the + /// Return the total number of samples collected at the head of the /// function. unsigned getHeadSamples() const { return TotalHeadSamples; } - /// \brief Return all the samples collected in the body of the function. + /// Return all the samples collected in the body of the function. const BodySampleMap &getBodySamples() const { return BodySamples; } - /// \brief Merge the samples in \p Other into this one. + /// Merge the samples in \p Other into this one. void merge(const FunctionSamples &Other) { addTotalSamples(Other.getTotalSamples()); addHeadSamples(Other.getHeadSamples()); @@ -223,16 +223,18 @@ class FunctionSamples { } private: - /// \brief Total number of samples collected inside this function. + /// Total number of samples collected inside this function. /// /// Samples are cumulative, they include all the samples collected /// inside this function and all its inlined callees. unsigned TotalSamples; - /// \brief Total number of samples collected at the head of the function. + /// Total number of samples collected at the head of the function. + /// This is an approximation of the number of calls made to this function + /// at runtime. unsigned TotalHeadSamples; - /// \brief Map instruction locations to collected samples. + /// Map instruction locations to collected samples. /// /// Each entry in this map contains the number of samples /// collected at the corresponding line offset. All line locations diff --git a/include/llvm/Support/AlignOf.h b/include/llvm/Support/AlignOf.h index 061d5acf232..07da02d063c 100644 --- a/include/llvm/Support/AlignOf.h +++ b/include/llvm/Support/AlignOf.h @@ -22,6 +22,14 @@ namespace llvm { template struct AlignmentCalcImpl { char x; +#if defined(_MSC_VER) +// Disables "structure was padded due to __declspec(align())" warnings that are +// generated by any class using AlignOf with a manually specified alignment. +// Although the warning is disabled in the LLVM project we need this pragma +// as AlignOf.h is a published support header that's available for use +// out-of-tree, and we would like that to compile cleanly at /W4. +#pragma warning(suppress : 4324) +#endif T t; private: AlignmentCalcImpl() {} // Never instantiate. @@ -36,9 +44,18 @@ struct AlignmentCalcImpl { /// compile-time constant (e.g., for template instantiation). template struct AlignOf { +#ifndef _MSC_VER + // Avoid warnings from GCC like: + // comparison between 'enum llvm::AlignOf::' and 'enum + // llvm::AlignOf::' [-Wenum-compare] + // by using constexpr instead of enum. + // (except on MSVC, since it doesn't support constexpr yet). + static constexpr unsigned Alignment = + static_cast(sizeof(AlignmentCalcImpl) - sizeof(T)); +#else enum { Alignment = static_cast(sizeof(AlignmentCalcImpl) - sizeof(T)) }; - +#endif enum { Alignment_GreaterEqual_2Bytes = Alignment >= 2 ? 1 : 0 }; enum { Alignment_GreaterEqual_4Bytes = Alignment >= 4 ? 1 : 0 }; enum { Alignment_GreaterEqual_8Bytes = Alignment >= 8 ? 1 : 0 }; @@ -50,6 +67,10 @@ struct AlignOf { enum { Alignment_LessEqual_16Bytes = Alignment <= 16 ? 1 : 0 }; }; +#ifndef _MSC_VER +template constexpr unsigned AlignOf::Alignment; +#endif + /// alignOf - A templated function that returns the minimum alignment of /// of a type. This provides no extra functionality beyond the AlignOf /// class besides some cosmetic cleanliness. Example usage: @@ -190,12 +211,12 @@ union SizerImpl { } // end namespace detail /// \brief This union template exposes a suitably aligned and sized character -/// array member which can hold elements of any of up to four types. +/// array member which can hold elements of any of up to ten types. /// /// These types may be arrays, structs, or any other types. The goal is to /// expose a char array buffer member which can be used as suitable storage for -/// a placement new of any of these types. Support for more than seven types can -/// be added at the cost of more boiler plate. +/// a placement new of any of these types. Support for more than ten types can +/// be added at the cost of more boilerplate. template (Allocator)) {} - // Manually implement a move constructor as we must clear the old allocators + // Manually implement a move constructor as we must clear the old allocator's // slabs as a matter of correctness. BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old) : CurPtr(Old.CurPtr), End(Old.End), Slabs(std::move(Old.Slabs)), @@ -187,6 +187,9 @@ class BumpPtrAllocatorImpl /// \brief Deallocate all but the current slab and reset the current pointer /// to the beginning of it, freeing all memory allocated so far. void Reset() { + DeallocateCustomSizedSlabs(); + CustomSizedSlabs.clear(); + if (Slabs.empty()) return; @@ -195,11 +198,9 @@ class BumpPtrAllocatorImpl CurPtr = (char *)Slabs.front(); End = CurPtr + SlabSize; - // Deallocate all but the first slab, and all custome sized slabs. + // Deallocate all but the first slab, and deallocate all custom-sized slabs. DeallocateSlabs(std::next(Slabs.begin()), Slabs.end()); Slabs.erase(std::next(Slabs.begin()), Slabs.end()); - DeallocateCustomSizedSlabs(); - CustomSizedSlabs.clear(); } /// \brief Allocate space at the specified alignment. @@ -320,14 +321,6 @@ class BumpPtrAllocatorImpl for (; I != E; ++I) { size_t AllocatedSlabSize = computeSlabSize(std::distance(Slabs.begin(), I)); -#ifndef NDEBUG - // Poison the memory so stale pointers crash sooner. Note we must - // preserve the Size and NextPtr fields at the beginning. - if (AllocatedSlabSize != 0) { - sys::Memory::setRangeWritable(*I, AllocatedSlabSize); - memset(*I, 0xCD, AllocatedSlabSize); - } -#endif Allocator.Deallocate(*I, AllocatedSlabSize); } } @@ -337,12 +330,6 @@ class BumpPtrAllocatorImpl for (auto &PtrAndSize : CustomSizedSlabs) { void *Ptr = PtrAndSize.first; size_t Size = PtrAndSize.second; -#ifndef NDEBUG - // Poison the memory so stale pointers crash sooner. Note we must - // preserve the Size and NextPtr fields at the beginning. - sys::Memory::setRangeWritable(Ptr, Size); - memset(Ptr, 0xCD, Size); -#endif Allocator.Deallocate(Ptr, Size); } } diff --git a/include/llvm/Support/BranchProbability.h b/include/llvm/Support/BranchProbability.h index 9aab6ace6e3..a6429dd22a3 100644 --- a/include/llvm/Support/BranchProbability.h +++ b/include/llvm/Support/BranchProbability.h @@ -31,7 +31,7 @@ class BranchProbability { public: BranchProbability(uint32_t n, uint32_t d) : N(n), D(d) { - assert(d > 0 && "Denomiator cannot be 0!"); + assert(d > 0 && "Denominator cannot be 0!"); assert(n <= d && "Probability cannot be bigger than 1!"); } diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index 7f54822d503..0162175efe3 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -88,6 +88,7 @@ namespace COFF { IMAGE_FILE_MACHINE_AMD64 = 0x8664, IMAGE_FILE_MACHINE_ARM = 0x1C0, IMAGE_FILE_MACHINE_ARMNT = 0x1C4, + IMAGE_FILE_MACHINE_ARM64 = 0xAA64, IMAGE_FILE_MACHINE_EBC = 0xEBC, IMAGE_FILE_MACHINE_I386 = 0x14C, IMAGE_FILE_MACHINE_IA64 = 0x200, @@ -155,16 +156,6 @@ namespace COFF { uint8_t NumberOfAuxSymbols; }; - enum SymbolFlags { - SF_TypeMask = 0x0000FFFF, - SF_TypeShift = 0, - - SF_ClassMask = 0x00FF0000, - SF_ClassShift = 16, - - SF_WeakExternal = 0x01000000 - }; - enum SymbolSectionNumber : int32_t { IMAGE_SYM_DEBUG = -2, IMAGE_SYM_ABSOLUTE = -1, @@ -257,6 +248,7 @@ namespace COFF { enum SectionCharacteristics : uint32_t { SC_Invalid = 0xffffffff, + IMAGE_SCN_TYPE_NOLOAD = 0x00000002, IMAGE_SCN_TYPE_NO_PAD = 0x00000008, IMAGE_SCN_CNT_CODE = 0x00000020, IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040, @@ -665,6 +657,7 @@ namespace COFF { }; enum CodeViewIdentifiers { + DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS = 0x1, DEBUG_SECTION_MAGIC = 0x4, DEBUG_SYMBOL_SUBSECTION = 0xF1, DEBUG_LINE_TABLE_SUBSECTION = 0xF2, diff --git a/include/llvm/Support/COM.h b/include/llvm/Support/COM.h new file mode 100644 index 00000000000..a2d5a7a68ba --- /dev/null +++ b/include/llvm/Support/COM.h @@ -0,0 +1,36 @@ +//===- llvm/Support/COM.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// Provides a library for accessing COM functionality of the Host OS. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_COM_H +#define LLVM_SUPPORT_COM_H + +namespace llvm { +namespace sys { + +enum class COMThreadingMode { SingleThreaded, MultiThreaded }; + +class InitializeCOMRAII { +public: + explicit InitializeCOMRAII(COMThreadingMode Threading, + bool SpeedOverMemory = false); + ~InitializeCOMRAII(); + +private: + InitializeCOMRAII(const InitializeCOMRAII &) = delete; + void operator=(const InitializeCOMRAII &) = delete; +}; +} +} + +#endif diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index bd1d1cb6dc9..379d06a6574 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -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. @@ -787,7 +790,7 @@ template <> class parser final : public basic_parser { void anchor() override; }; -EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); +extern template class basic_parser; //-------------------------------------------------- // parser @@ -813,7 +816,7 @@ class parser final : public basic_parser { void anchor() override; }; -EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); +extern template class basic_parser; //-------------------------------------------------- // parser @@ -835,7 +838,7 @@ template <> class parser final : public basic_parser { void anchor() override; }; -EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); +extern template class basic_parser; //-------------------------------------------------- // parser @@ -857,7 +860,7 @@ template <> class parser final : public basic_parser { void anchor() override; }; -EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); +extern template class basic_parser; //-------------------------------------------------- // parser @@ -882,7 +885,7 @@ class parser final void anchor() override; }; -EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); +extern template class basic_parser; //-------------------------------------------------- // parser @@ -904,7 +907,7 @@ template <> class parser final : public basic_parser { void anchor() override; }; -EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); +extern template class basic_parser; //-------------------------------------------------- // parser @@ -926,7 +929,7 @@ template <> class parser final : public basic_parser { void anchor() override; }; -EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); +extern template class basic_parser; //-------------------------------------------------- // parser @@ -951,7 +954,7 @@ template <> class parser final : public basic_parser { void anchor() override; }; -EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); +extern template class basic_parser; //-------------------------------------------------- // parser @@ -976,7 +979,7 @@ template <> class parser final : public basic_parser { void anchor() override; }; -EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); +extern template class basic_parser; //-------------------------------------------------- // PrintOptionDiff @@ -1251,11 +1254,11 @@ class opt : public Option, } }; -EXTERN_TEMPLATE_INSTANTIATION(class opt); -EXTERN_TEMPLATE_INSTANTIATION(class opt); -EXTERN_TEMPLATE_INSTANTIATION(class opt); -EXTERN_TEMPLATE_INSTANTIATION(class opt); -EXTERN_TEMPLATE_INSTANTIATION(class opt); +extern template class opt; +extern template class opt; +extern template class opt; +extern template class opt; +extern template class opt; //===----------------------------------------------------------------------===// // list_storage class @@ -1284,24 +1287,81 @@ template class list_storage { } }; -// Define how to hold a class type object, such as a string. Since we can -// inherit from a class, we do so. This makes us exactly compatible with the -// object in all cases that it is used. +// Define how to hold a class type object, such as a string. +// Originally this code inherited from std::vector. In transitioning to a new +// API for command line options we should change this. The new implementation +// of this list_storage specialization implements the minimum subset of the +// std::vector API required for all the current clients. // -template -class list_storage : public std::vector { +// FIXME: Reduce this API to a more narrow subset of std::vector +// +template class list_storage { + std::vector Storage; + public: - template void addValue(const T &V) { - std::vector::push_back(V); + typedef typename std::vector::iterator iterator; + + iterator begin() { return Storage.begin(); } + iterator end() { return Storage.end(); } + + typedef typename std::vector::const_iterator const_iterator; + const_iterator begin() const { return Storage.begin(); } + const_iterator end() const { return Storage.end(); } + + typedef typename std::vector::size_type size_type; + size_type size() const { return Storage.size(); } + + bool empty() const { return Storage.empty(); } + + void push_back(const DataType &value) { Storage.push_back(value); } + void push_back(DataType &&value) { Storage.push_back(value); } + + typedef typename std::vector::reference reference; + typedef typename std::vector::const_reference const_reference; + reference operator[](size_type pos) { return Storage[pos]; } + const_reference operator[](size_type pos) const { return Storage[pos]; } + + iterator erase(const_iterator pos) { return Storage.erase(pos); } + iterator erase(const_iterator first, const_iterator last) { + return Storage.erase(first, last); + } + + iterator erase(iterator pos) { return Storage.erase(pos); } + iterator erase(iterator first, iterator last) { + return Storage.erase(first, last); + } + + iterator insert(const_iterator pos, const DataType &value) { + return Storage.insert(pos, value); + } + iterator insert(const_iterator pos, DataType &&value) { + return Storage.insert(pos, value); } + + iterator insert(iterator pos, const DataType &value) { + return Storage.insert(pos, value); + } + iterator insert(iterator pos, DataType &&value) { + return Storage.insert(pos, value); + } + + reference front() { return Storage.front(); } + const_reference front() const { return Storage.front(); } + + operator std::vector&() { return Storage; } + operator ArrayRef() { return Storage; } + std::vector *operator&() { return &Storage; } + const std::vector *operator&() const { return &Storage; } + + template void addValue(const T &V) { Storage.push_back(V); } }; //===----------------------------------------------------------------------===// // list - A list of command line options. // -template > -class list : public Option, public list_storage { +class list : public Option, public list_storage { std::vector Positions; ParserClass Parser; @@ -1319,7 +1379,7 @@ class list : public Option, public list_storage { typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) return true; // Parse Error! - list_storage::addValue(Val); + list_storage::addValue(Val); setPosition(pos); Positions.push_back(pos); return false; @@ -1619,16 +1679,6 @@ StringMap