Vendor import of llvm trunk r321017:
https://llvm.org/svn/llvm-project/llvm/trunk@321017
This commit is contained in:
parent
eb70dddbd7
commit
044eb2f6af
12
.gitattributes
vendored
Normal file
12
.gitattributes
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# binary files
|
||||
test/Object/Inputs/*.a-* binary
|
||||
test/tools/dsymutil/Inputs/* binary
|
||||
test/tools/llvm-ar/Inputs/*.lib binary
|
||||
test/tools/llvm-objdump/Inputs/*.a binary
|
||||
test/tools/llvm-rc/Inputs/* binary
|
||||
test/tools/llvm-strings/Inputs/numbers binary
|
||||
test/MC/AsmParser/incbin_abcd binary
|
||||
test/YAMLParser/spec-09-02.test binary
|
||||
|
||||
# Windows line ending test
|
||||
test/MC/AsmParser/preserve-comments-crlf.s text eol=crlf
|
129
CMakeLists.txt
129
CMakeLists.txt
@ -2,41 +2,32 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.4.3)
|
||||
|
||||
if(POLICY CMP0022)
|
||||
cmake_policy(SET CMP0022 NEW) # automatic when 2.8.12 is required
|
||||
endif()
|
||||
cmake_policy(SET CMP0022 NEW)
|
||||
|
||||
if (POLICY CMP0051)
|
||||
# CMake 3.1 and higher include generator expressions of the form
|
||||
# $<TARGETLIB:obj> in the SOURCES property. These need to be
|
||||
# stripped everywhere that access the SOURCES property, so we just
|
||||
# defer to the OLD behavior of not including generator expressions
|
||||
# in the output for now.
|
||||
cmake_policy(SET CMP0051 OLD)
|
||||
endif()
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
|
||||
if(POLICY CMP0057)
|
||||
cmake_policy(SET CMP0057 NEW)
|
||||
endif()
|
||||
# CMake 3.1 and higher include generator expressions of the form
|
||||
# $<TARGETLIB:obj> in the SOURCES property. These need to be
|
||||
# stripped everywhere that access the SOURCES property, so we just
|
||||
# defer to the OLD behavior of not including generator expressions
|
||||
# in the output for now.
|
||||
cmake_policy(SET CMP0051 OLD)
|
||||
|
||||
cmake_policy(SET CMP0056 NEW)
|
||||
|
||||
cmake_policy(SET CMP0057 NEW)
|
||||
|
||||
if(NOT DEFINED LLVM_VERSION_MAJOR)
|
||||
set(LLVM_VERSION_MAJOR 5)
|
||||
set(LLVM_VERSION_MAJOR 6)
|
||||
endif()
|
||||
if(NOT DEFINED LLVM_VERSION_MINOR)
|
||||
set(LLVM_VERSION_MINOR 0)
|
||||
endif()
|
||||
if(NOT DEFINED LLVM_VERSION_PATCH)
|
||||
set(LLVM_VERSION_PATCH 1)
|
||||
set(LLVM_VERSION_PATCH 0)
|
||||
endif()
|
||||
if(NOT DEFINED LLVM_VERSION_SUFFIX)
|
||||
set(LLVM_VERSION_SUFFIX "")
|
||||
endif()
|
||||
|
||||
if (POLICY CMP0048)
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
set(cmake_3_0_PROJ_VERSION
|
||||
VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH})
|
||||
set(cmake_3_0_LANGUAGES LANGUAGES)
|
||||
set(LLVM_VERSION_SUFFIX svn)
|
||||
endif()
|
||||
|
||||
if (NOT PACKAGE_VERSION)
|
||||
@ -52,9 +43,8 @@ if ((CMAKE_GENERATOR MATCHES "Visual Studio") AND (CMAKE_GENERATOR_TOOLSET STREQ
|
||||
endif()
|
||||
|
||||
project(LLVM
|
||||
${cmake_3_0_PROJ_VERSION}
|
||||
${cmake_3_0_LANGUAGES}
|
||||
C CXX ASM)
|
||||
VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}
|
||||
LANGUAGES C CXX ASM)
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS "No build type selected, default to Debug")
|
||||
@ -120,7 +110,7 @@ endif()
|
||||
# LLVM_EXTERNAL_${project}_SOURCE_DIR using LLVM_ALL_PROJECTS
|
||||
# This allows an easy way of setting up a build directory for llvm and another
|
||||
# one for llvm+clang+... using the same sources.
|
||||
set(LLVM_ALL_PROJECTS "clang;libcxx;libcxxabi;lldb;compiler-rt;lld;polly")
|
||||
set(LLVM_ALL_PROJECTS "clang;libcxx;libcxxabi;lldb;compiler-rt;lld;polly;debuginfo-tests")
|
||||
set(LLVM_ENABLE_PROJECTS "" CACHE STRING
|
||||
"Semicolon-separated list of projects to build (${LLVM_ALL_PROJECTS}), or \"all\".")
|
||||
if( LLVM_ENABLE_PROJECTS STREQUAL "all" )
|
||||
@ -176,12 +166,11 @@ if(LLVM_DEPENDENCY_DEBUGGING)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(LLVM_BUILD_GLOBAL_ISEL "Experimental: Build GlobalISel" ON)
|
||||
if(LLVM_BUILD_GLOBAL_ISEL)
|
||||
add_definitions(-DLLVM_BUILD_GLOBAL_ISEL)
|
||||
endif()
|
||||
|
||||
option(LLVM_ENABLE_DAGISEL_COV "Debug: Prints tablegen patterns that were used for selecting" OFF)
|
||||
option(LLVM_ENABLE_GISEL_COV "Enable collection of GlobalISel rule coverage" OFF)
|
||||
if(LLVM_ENABLE_GISEL_COV)
|
||||
set(LLVM_GISEL_COV_PREFIX "${CMAKE_BINARY_DIR}/gisel-coverage-" CACHE STRING "Provide a filename prefix to collect the GlobalISel rule coverage")
|
||||
endif()
|
||||
|
||||
# Add path for custom modules
|
||||
set(CMAKE_MODULE_PATH
|
||||
@ -194,6 +183,9 @@ set(CMAKE_MODULE_PATH
|
||||
# for use by clang_complete, YouCompleteMe, etc.
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
|
||||
|
||||
option(LLVM_INSTALL_BINUTILS_SYMLINKS
|
||||
"Install symlinks from the binutils tool names to the corresponding LLVM tools." OFF)
|
||||
|
||||
option(LLVM_INSTALL_UTILS "Include utility binaries in the 'install' target." OFF)
|
||||
|
||||
option(LLVM_INSTALL_TOOLCHAIN_ONLY "Only include toolchain files in the 'install' target." OFF)
|
||||
@ -242,11 +234,11 @@ endif()
|
||||
include(CPack)
|
||||
|
||||
# Sanity check our source directory to make sure that we are not trying to
|
||||
# generate an in-tree build (unless on MSVC_IDE, where it is ok), and to make
|
||||
# generate an in-source build (unless on MSVC_IDE, where it is ok), and to make
|
||||
# sure that we don't have any stray generated files lying around in the tree
|
||||
# (which would end up getting picked up by header search, instead of the correct
|
||||
# versions).
|
||||
if( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND NOT MSVC_IDE )
|
||||
if( CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR AND NOT MSVC_IDE )
|
||||
message(FATAL_ERROR "In-source builds are not allowed.
|
||||
CMake would overwrite the makefiles distributed with LLVM.
|
||||
Please create a directory and run cmake from there, passing the path
|
||||
@ -359,6 +351,8 @@ set(LLVM_TARGET_ARCH "host"
|
||||
|
||||
option(LLVM_ENABLE_TERMINFO "Use terminfo database if available." ON)
|
||||
|
||||
set(LLVM_ENABLE_LIBXML2 "ON" CACHE STRING "Use libxml2 if available. Can be ON, OFF, or FORCE_ON")
|
||||
|
||||
option(LLVM_ENABLE_LIBEDIT "Use libedit if available." ON)
|
||||
|
||||
option(LLVM_ENABLE_THREADS "Use threads if available." ON)
|
||||
@ -391,6 +385,8 @@ option(LLVM_ENABLE_LLD "Use lld as C and C++ linker." OFF)
|
||||
option(LLVM_ENABLE_PEDANTIC "Compile with pedantic enabled." ON)
|
||||
option(LLVM_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF)
|
||||
|
||||
option(LLVM_ENABLE_DUMP "Enable dump functions even when assertions are disabled" OFF)
|
||||
|
||||
if( NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG" )
|
||||
option(LLVM_ENABLE_ASSERTIONS "Enable assertions" OFF)
|
||||
else()
|
||||
@ -432,6 +428,8 @@ endif( LLVM_USE_OPROFILE )
|
||||
|
||||
set(LLVM_USE_SANITIZER "" CACHE STRING
|
||||
"Define the sanitizer used to build binaries and tests.")
|
||||
set(LLVM_LIB_FUZZING_ENGINE "" CACHE PATH
|
||||
"Path to fuzzing library for linking with fuzz targets")
|
||||
|
||||
option(LLVM_USE_SPLIT_DWARF
|
||||
"Use -gsplit-dwarf when compiling llvm." OFF)
|
||||
@ -551,7 +549,8 @@ else()
|
||||
set(LLVM_ADD_NATIVE_VISUALIZERS_TO_SOLUTION FALSE CACHE INTERNAL "For Visual Studio 2013, manually copy natvis files to Documents\\Visual Studio 2013\\Visualizers" FORCE)
|
||||
endif()
|
||||
|
||||
if (LLVM_BUILD_INSTRUMENTED OR LLVM_BUILD_INSTRUMENTED_COVERAGE)
|
||||
if (LLVM_BUILD_INSTRUMENTED OR LLVM_BUILD_INSTRUMENTED_COVERAGE OR
|
||||
LLVM_ENABLE_IR_PGO)
|
||||
if(NOT LLVM_PROFILE_MERGE_POOL_SIZE)
|
||||
# A pool size of 1-2 is probably sufficient on a SSD. 3-4 should be fine
|
||||
# for spining disks. Anything higher may only help on slower mediums.
|
||||
@ -559,10 +558,9 @@ if (LLVM_BUILD_INSTRUMENTED OR LLVM_BUILD_INSTRUMENTED_COVERAGE)
|
||||
endif()
|
||||
if(NOT LLVM_PROFILE_FILE_PATTERN)
|
||||
if(NOT LLVM_PROFILE_DATA_DIR)
|
||||
file(TO_NATIVE_PATH "${LLVM_BINARY_DIR}/profiles/%${LLVM_PROFILE_MERGE_POOL_SIZE}m.profraw" LLVM_PROFILE_FILE_PATTERN)
|
||||
else()
|
||||
file(TO_NATIVE_PATH "${LLVM_PROFILE_DATA_DIR}/%${LLVM_PROFILE_MERGE_POOL_SIZE}m.profraw" LLVM_PROFILE_FILE_PATTERN)
|
||||
file(TO_NATIVE_PATH "${LLVM_BINARY_DIR}/profiles" LLVM_PROFILE_DATA_DIR)
|
||||
endif()
|
||||
file(TO_NATIVE_PATH "${LLVM_PROFILE_DATA_DIR}/%${LLVM_PROFILE_MERGE_POOL_SIZE}m.profraw" LLVM_PROFILE_FILE_PATTERN)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -680,9 +678,13 @@ foreach(t ${LLVM_TARGETS_TO_BUILD})
|
||||
|
||||
list(FIND LLVM_ALL_TARGETS ${t} idx)
|
||||
list(FIND LLVM_EXPERIMENTAL_TARGETS_TO_BUILD ${t} idy)
|
||||
# At this point, LLVMBUILDTOOL already checked all the targets passed in
|
||||
# LLVM_TARGETS_TO_BUILD and LLVM_EXPERIMENTAL_TARGETS_TO_BUILD, so
|
||||
# this test just makes sure that any experimental targets were passed via
|
||||
# LLVM_EXPERIMENTAL_TARGETS_TO_BUILD, not LLVM_TARGETS_TO_BUILD.
|
||||
if( idx LESS 0 AND idy LESS 0 )
|
||||
message(FATAL_ERROR "The target `${t}' does not exist.
|
||||
It should be one of\n${LLVM_ALL_TARGETS}")
|
||||
message(FATAL_ERROR "The target `${t}' is experimental and must be passed "
|
||||
"via LLVM_EXPERIMENTAL_TARGETS_TO_BUILD.")
|
||||
else()
|
||||
set(LLVM_ENUM_TARGETS "${LLVM_ENUM_TARGETS}LLVM_TARGET(${t})\n")
|
||||
endif()
|
||||
@ -757,6 +759,7 @@ configure_file(
|
||||
add_custom_target(srpm
|
||||
COMMAND cpack -G TGZ --config CPackSourceConfig.cmake -B ${LLVM_SRPM_DIR}/SOURCES
|
||||
COMMAND rpmbuild -bs --define '_topdir ${LLVM_SRPM_DIR}' ${LLVM_SRPM_BINARY_SPECFILE})
|
||||
set_target_properties(srpm PROPERTIES FOLDER "Misc")
|
||||
|
||||
|
||||
# They are not referenced. See set_output_directory().
|
||||
@ -792,14 +795,14 @@ if(LLVM_USE_HOST_TOOLS)
|
||||
include(CrossCompile)
|
||||
endif(LLVM_USE_HOST_TOOLS)
|
||||
if(LLVM_TARGET_IS_CROSSCOMPILE_HOST)
|
||||
# Dummy use to avoid CMake Wraning: Manually-specified variables were not used
|
||||
# Dummy use to avoid CMake Warning: Manually-specified variables were not used
|
||||
# (this is a variable that CrossCompile sets on recursive invocations)
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "(FreeBSD|DragonFly)")
|
||||
# On FreeBSD, /usr/local/* is not used by default. In order to build LLVM
|
||||
# with libxml2, iconv.h, etc., we must add /usr/local paths.
|
||||
include_directories("/usr/local/include")
|
||||
include_directories(SYSTEM "/usr/local/include")
|
||||
link_directories("/usr/local/lib")
|
||||
endif(${CMAKE_SYSTEM_NAME} MATCHES "(FreeBSD|DragonFly)")
|
||||
|
||||
@ -839,15 +842,6 @@ add_subdirectory(lib/TableGen)
|
||||
|
||||
add_subdirectory(utils/TableGen)
|
||||
|
||||
# Force target to be built as soon as possible. Clang modules builds depend
|
||||
# header-wise on it as they ship all headers from the umbrella folders. Building
|
||||
# an entire module might include header, which depends on intrinsics_gen. This
|
||||
# should be right after LLVMSupport and LLVMTableGen otherwise we introduce a
|
||||
# circular dependence.
|
||||
if (LLVM_ENABLE_MODULES)
|
||||
list(APPEND LLVM_COMMON_DEPENDS intrinsics_gen)
|
||||
endif(LLVM_ENABLE_MODULES)
|
||||
|
||||
add_subdirectory(include/llvm)
|
||||
|
||||
add_subdirectory(lib)
|
||||
@ -857,7 +851,6 @@ if( LLVM_INCLUDE_UTILS )
|
||||
add_subdirectory(utils/PerfectShuffle)
|
||||
add_subdirectory(utils/count)
|
||||
add_subdirectory(utils/not)
|
||||
add_subdirectory(utils/llvm-lit)
|
||||
add_subdirectory(utils/yaml-bench)
|
||||
else()
|
||||
if ( LLVM_INCLUDE_TESTS )
|
||||
@ -900,6 +893,7 @@ if( LLVM_INCLUDE_TESTS )
|
||||
NO_INSTALL
|
||||
ALWAYS_CLEAN)
|
||||
endif()
|
||||
add_subdirectory(utils/lit)
|
||||
add_subdirectory(test)
|
||||
add_subdirectory(unittests)
|
||||
if( LLVM_INCLUDE_UTILS )
|
||||
@ -943,6 +937,11 @@ endif()
|
||||
|
||||
add_subdirectory(cmake/modules)
|
||||
|
||||
# Do this last so that all lit targets have already been created.
|
||||
if (LLVM_INCLUDE_UTILS)
|
||||
add_subdirectory(utils/llvm-lit)
|
||||
endif()
|
||||
|
||||
if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
|
||||
install(DIRECTORY include/llvm include/llvm-c
|
||||
DESTINATION include
|
||||
@ -973,13 +972,11 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
|
||||
# Installing the headers needs to depend on generating any public
|
||||
# tablegen'd headers.
|
||||
add_custom_target(llvm-headers DEPENDS intrinsics_gen)
|
||||
set_target_properties(llvm-headers PROPERTIES FOLDER "Misc")
|
||||
|
||||
if (NOT CMAKE_CONFIGURATION_TYPES)
|
||||
add_custom_target(install-llvm-headers
|
||||
DEPENDS llvm-headers
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
-DCMAKE_INSTALL_COMPONENT=llvm-headers
|
||||
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
|
||||
add_llvm_install_targets(install-llvm-headers
|
||||
COMPONENT llvm-headers)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -992,22 +989,32 @@ if(LLVM_DISTRIBUTION_COMPONENTS)
|
||||
|
||||
add_custom_target(distribution)
|
||||
add_custom_target(install-distribution)
|
||||
add_custom_target(install-distribution-stripped)
|
||||
foreach(target ${LLVM_DISTRIBUTION_COMPONENTS})
|
||||
if(TARGET ${target})
|
||||
add_dependencies(distribution ${target})
|
||||
else()
|
||||
message(FATAL_ERROR "Specified distribution component '${target}' doesn't have a target")
|
||||
message(SEND_ERROR "Specified distribution component '${target}' doesn't have a target")
|
||||
endif()
|
||||
|
||||
if(TARGET install-${target})
|
||||
add_dependencies(install-distribution install-${target})
|
||||
else()
|
||||
message(FATAL_ERROR "Specified distribution component '${target}' doesn't have an install target")
|
||||
message(SEND_ERROR "Specified distribution component '${target}' doesn't have an install target")
|
||||
endif()
|
||||
|
||||
if(TARGET install-${target}-stripped)
|
||||
add_dependencies(install-distribution-stripped install-${target}-stripped)
|
||||
else()
|
||||
message(SEND_ERROR "Specified distribution component '${target}' doesn't have an install-stripped target."
|
||||
" Its installation target creation should be changed to use add_llvm_install_targets,"
|
||||
" or you should manually create the 'install-${target}-stripped' target.")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# This allows us to deploy the Universal CRT DLLs by passing -DCMAKE_INSTALL_UCRT_LIBRARIES=ON to CMake
|
||||
if (MSVC)
|
||||
if (MSVC AND CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
||||
include(InstallRequiredSystemLibraries)
|
||||
endif()
|
||||
|
||||
|
@ -41,9 +41,13 @@ E: andrey.churbanov@intel.com
|
||||
D: OpenMP runtime library
|
||||
|
||||
N: Greg Clayton
|
||||
E: gclayton@apple.com
|
||||
E: clayborg@gmail.com
|
||||
D: LLDB
|
||||
|
||||
N: Pete Couperus
|
||||
E: petecoup@synopsys.com
|
||||
D: ARC backend (lib/Target/ARC/*)
|
||||
|
||||
N: Sanjoy Das
|
||||
E: sanjoy@playingwithpointers.com
|
||||
D: IndVar Simplify, Scalar Evolution
|
||||
@ -61,7 +65,7 @@ E: qcolombet@apple.com
|
||||
D: Loop Strength Reduction, Register allocators
|
||||
|
||||
N: Simon Dardis
|
||||
E: simon.dardis@imgtec.com
|
||||
E: simon.dardis@mips.com
|
||||
D: MIPS Backend (lib/Target/Mips/*)
|
||||
|
||||
N: Duncan P. N. Exon Smith
|
||||
|
@ -43,6 +43,10 @@ N: Neil Booth
|
||||
E: neil@daikokuya.co.uk
|
||||
D: APFloat implementation.
|
||||
|
||||
N: Alex Bradbury
|
||||
E: asb@lowrisc.org
|
||||
D: RISC-V backend
|
||||
|
||||
N: Misha Brukman
|
||||
E: brukman+llvm@uiuc.edu
|
||||
W: http://misha.brukman.net
|
||||
|
@ -16,3 +16,4 @@ documentation setup.
|
||||
If you are writing a package for LLVM, see docs/Packaging.rst for our
|
||||
suggestions.
|
||||
|
||||
|
||||
|
@ -47,6 +47,6 @@ T: ARM, AArch64
|
||||
O: Linux
|
||||
|
||||
N: Simon Dardis
|
||||
E: simon.dardis@imgtec.com
|
||||
E: simon.dardis@mips.com
|
||||
T: MIPS
|
||||
O: Linux
|
||||
|
@ -29,25 +29,6 @@ void LLVMDIBuilderDestroy(LLVMDIBuilderRef dref) {
|
||||
delete d;
|
||||
}
|
||||
|
||||
void LLVMDIBuilderFinalize(LLVMDIBuilderRef dref) { unwrap(dref)->finalize(); }
|
||||
|
||||
LLVMMetadataRef LLVMDIBuilderCreateCompileUnit(LLVMDIBuilderRef Dref,
|
||||
unsigned Lang, const char *File,
|
||||
const char *Dir,
|
||||
const char *Producer,
|
||||
int Optimized, const char *Flags,
|
||||
unsigned RuntimeVersion) {
|
||||
DIBuilder *D = unwrap(Dref);
|
||||
return wrap(D->createCompileUnit(Lang, D->createFile(File, Dir), Producer,
|
||||
Optimized, Flags, RuntimeVersion));
|
||||
}
|
||||
|
||||
LLVMMetadataRef LLVMDIBuilderCreateFile(LLVMDIBuilderRef Dref, const char *File,
|
||||
const char *Dir) {
|
||||
DIBuilder *D = unwrap(Dref);
|
||||
return wrap(D->createFile(File, Dir));
|
||||
}
|
||||
|
||||
LLVMMetadataRef LLVMDIBuilderCreateLexicalBlock(LLVMDIBuilderRef Dref,
|
||||
LLVMMetadataRef Scope,
|
||||
LLVMMetadataRef File,
|
||||
@ -237,7 +218,7 @@ LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef Dref,
|
||||
}
|
||||
|
||||
LLVMValueRef LLVMDIBuilderInsertValueAtEnd(LLVMDIBuilderRef Dref,
|
||||
LLVMValueRef Val, uint64_t Offset,
|
||||
LLVMValueRef Val,
|
||||
LLVMMetadataRef VarInfo,
|
||||
LLVMMetadataRef Expr,
|
||||
LLVMBasicBlockRef Block) {
|
||||
@ -247,7 +228,7 @@ LLVMValueRef LLVMDIBuilderInsertValueAtEnd(LLVMDIBuilderRef Dref,
|
||||
|
||||
DIBuilder *D = unwrap(Dref);
|
||||
Instruction *Instr = D->insertDbgValueIntrinsic(
|
||||
unwrap(Val), Offset, unwrap<DILocalVariable>(VarInfo),
|
||||
unwrap<DIExpression>(Expr), /* DebugLoc */ nullptr, unwrap(Block));
|
||||
unwrap(Val), unwrap<DILocalVariable>(VarInfo), unwrap<DIExpression>(Expr),
|
||||
/* DebugLoc */ nullptr, unwrap(Block));
|
||||
return wrap(Instr);
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "IRBindings.h"
|
||||
#include "llvm-c/Core.h"
|
||||
#include "llvm-c/DebugInfo.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -30,16 +31,6 @@ typedef struct LLVMOpaqueDIBuilder *LLVMDIBuilderRef;
|
||||
LLVMDIBuilderRef LLVMNewDIBuilder(LLVMModuleRef m);
|
||||
|
||||
void LLVMDIBuilderDestroy(LLVMDIBuilderRef d);
|
||||
void LLVMDIBuilderFinalize(LLVMDIBuilderRef d);
|
||||
|
||||
LLVMMetadataRef
|
||||
LLVMDIBuilderCreateCompileUnit(LLVMDIBuilderRef D, unsigned Language,
|
||||
const char *File, const char *Dir,
|
||||
const char *Producer, int Optimized,
|
||||
const char *Flags, unsigned RuntimeVersion);
|
||||
|
||||
LLVMMetadataRef LLVMDIBuilderCreateFile(LLVMDIBuilderRef D, const char *File,
|
||||
const char *Dir);
|
||||
|
||||
LLVMMetadataRef LLVMDIBuilderCreateLexicalBlock(LLVMDIBuilderRef D,
|
||||
LLVMMetadataRef Scope,
|
||||
@ -132,7 +123,6 @@ LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef D,
|
||||
LLVMBasicBlockRef Block);
|
||||
|
||||
LLVMValueRef LLVMDIBuilderInsertValueAtEnd(LLVMDIBuilderRef D, LLVMValueRef Val,
|
||||
uint64_t Offset,
|
||||
LLVMMetadataRef VarInfo,
|
||||
LLVMMetadataRef Expr,
|
||||
LLVMBasicBlockRef Block);
|
||||
|
@ -132,12 +132,17 @@ func (d *DIBuilder) CreateCompileUnit(cu DICompileUnit) Metadata {
|
||||
defer C.free(unsafe.Pointer(flags))
|
||||
result := C.LLVMDIBuilderCreateCompileUnit(
|
||||
d.ref,
|
||||
C.unsigned(cu.Language),
|
||||
file, dir,
|
||||
producer,
|
||||
boolToCInt(cu.Optimized),
|
||||
flags,
|
||||
C.LLVMDWARFSourceLanguage(cu.Language),
|
||||
C.LLVMDIBuilderCreateFile(d.ref, file, C.size_t(len(cu.File)), dir, C.size_t(len(cu.Dir))),
|
||||
producer, C.size_t(len(cu.Producer)),
|
||||
C.LLVMBool(boolToCInt(cu.Optimized)),
|
||||
flags, C.size_t(len(cu.Flags)),
|
||||
C.unsigned(cu.RuntimeVersion),
|
||||
/*SplitName=*/ nil, 0,
|
||||
C.LLVMDWARFEmissionFull,
|
||||
/*DWOId=*/ 0,
|
||||
/*SplitDebugInlining*/ C.LLVMBool(boolToCInt(true)),
|
||||
/*DebugInfoForProfiling*/ C.LLVMBool(boolToCInt(false)),
|
||||
)
|
||||
return Metadata{C: result}
|
||||
}
|
||||
@ -148,7 +153,9 @@ func (d *DIBuilder) CreateFile(filename, dir string) Metadata {
|
||||
defer C.free(unsafe.Pointer(cfilename))
|
||||
cdir := C.CString(dir)
|
||||
defer C.free(unsafe.Pointer(cdir))
|
||||
result := C.LLVMDIBuilderCreateFile(d.ref, cfilename, cdir)
|
||||
result := C.LLVMDIBuilderCreateFile(d.ref,
|
||||
cfilename, C.size_t(len(filename)),
|
||||
cdir, C.size_t(len(dir)))
|
||||
return Metadata{C: result}
|
||||
}
|
||||
|
||||
@ -533,8 +540,8 @@ func (d *DIBuilder) InsertDeclareAtEnd(v Value, diVarInfo, expr Metadata, bb Bas
|
||||
|
||||
// InsertValueAtEnd inserts a call to llvm.dbg.value at the end of the
|
||||
// specified basic block for the given value and associated debug metadata.
|
||||
func (d *DIBuilder) InsertValueAtEnd(v Value, diVarInfo, expr Metadata, offset uint64, bb BasicBlock) Value {
|
||||
result := C.LLVMDIBuilderInsertValueAtEnd(d.ref, v.C, C.uint64_t(offset), diVarInfo.C, expr.C, bb.C)
|
||||
func (d *DIBuilder) InsertValueAtEnd(v Value, diVarInfo, expr Metadata, bb BasicBlock) Value {
|
||||
result := C.LLVMDIBuilderInsertValueAtEnd(d.ref, v.C, diVarInfo.C, expr.C, bb.C)
|
||||
return Value{C: result}
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ include(CheckIncludeFileCXX)
|
||||
include(CheckLibraryExists)
|
||||
include(CheckSymbolExists)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckCCompilerFlag)
|
||||
include(CheckCXXSourceCompiles)
|
||||
include(TestBigEndian)
|
||||
|
||||
@ -126,35 +127,61 @@ if(HAVE_LIBPTHREAD)
|
||||
set(LLVM_PTHREAD_LIB ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
|
||||
# Don't look for these libraries on Windows. Also don't look for them if we're
|
||||
# using MSan, since uninstrumented third party code may call MSan interceptors
|
||||
# like strlen, leading to false positives.
|
||||
if( NOT PURE_WINDOWS AND NOT LLVM_USE_SANITIZER MATCHES "Memory.*")
|
||||
if (LLVM_ENABLE_ZLIB)
|
||||
check_library_exists(z compress2 "" HAVE_LIBZ)
|
||||
else()
|
||||
set(HAVE_LIBZ 0)
|
||||
endif()
|
||||
# Skip libedit if using ASan as it contains memory leaks.
|
||||
if (LLVM_ENABLE_LIBEDIT AND HAVE_HISTEDIT_H AND NOT LLVM_USE_SANITIZER MATCHES ".*Address.*")
|
||||
check_library_exists(edit el_init "" HAVE_LIBEDIT)
|
||||
else()
|
||||
set(HAVE_LIBEDIT 0)
|
||||
endif()
|
||||
if(LLVM_ENABLE_TERMINFO)
|
||||
set(HAVE_TERMINFO 0)
|
||||
foreach(library tinfo terminfo curses ncurses ncursesw)
|
||||
# Don't look for these libraries if we're using MSan, since uninstrumented third
|
||||
# party code may call MSan interceptors like strlen, leading to false positives.
|
||||
if(NOT LLVM_USE_SANITIZER MATCHES "Memory.*")
|
||||
set(HAVE_LIBZ 0)
|
||||
if(LLVM_ENABLE_ZLIB)
|
||||
foreach(library z zlib_static zlib)
|
||||
string(TOUPPER ${library} library_suffix)
|
||||
check_library_exists(${library} setupterm "" HAVE_TERMINFO_${library_suffix})
|
||||
if(HAVE_TERMINFO_${library_suffix})
|
||||
set(HAVE_TERMINFO 1)
|
||||
set(TERMINFO_LIBS "${library}")
|
||||
check_library_exists(${library} compress2 "" HAVE_LIBZ_${library_suffix})
|
||||
if(HAVE_LIBZ_${library_suffix})
|
||||
set(HAVE_LIBZ 1)
|
||||
set(ZLIB_LIBRARIES "${library}")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
else()
|
||||
set(HAVE_TERMINFO 0)
|
||||
endif()
|
||||
|
||||
# Don't look for these libraries on Windows.
|
||||
if (NOT PURE_WINDOWS)
|
||||
# Skip libedit if using ASan as it contains memory leaks.
|
||||
if (LLVM_ENABLE_LIBEDIT AND HAVE_HISTEDIT_H AND NOT LLVM_USE_SANITIZER MATCHES ".*Address.*")
|
||||
check_library_exists(edit el_init "" HAVE_LIBEDIT)
|
||||
else()
|
||||
set(HAVE_LIBEDIT 0)
|
||||
endif()
|
||||
if(LLVM_ENABLE_TERMINFO)
|
||||
set(HAVE_TERMINFO 0)
|
||||
foreach(library tinfo terminfo curses ncurses ncursesw)
|
||||
string(TOUPPER ${library} library_suffix)
|
||||
check_library_exists(${library} setupterm "" HAVE_TERMINFO_${library_suffix})
|
||||
if(HAVE_TERMINFO_${library_suffix})
|
||||
set(HAVE_TERMINFO 1)
|
||||
set(TERMINFO_LIBS "${library}")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
else()
|
||||
set(HAVE_TERMINFO 0)
|
||||
endif()
|
||||
|
||||
find_library(ICONV_LIBRARY_PATH NAMES iconv libiconv libiconv-2 c)
|
||||
set(LLVM_LIBXML2_ENABLED 0)
|
||||
set(LIBXML2_FOUND 0)
|
||||
if((LLVM_ENABLE_LIBXML2) AND ((CMAKE_SYSTEM_NAME MATCHES "Linux") AND (ICONV_LIBRARY_PATH) OR APPLE))
|
||||
find_package(LibXml2)
|
||||
if (LIBXML2_FOUND)
|
||||
set(LLVM_LIBXML2_ENABLED 1)
|
||||
include_directories(${LIBXML2_INCLUDE_DIR})
|
||||
set(LIBXML2_LIBS "xml2")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (LLVM_ENABLE_LIBXML2 STREQUAL "FORCE_ON" AND NOT LLVM_LIBXML2_ENABLED)
|
||||
message(FATAL_ERROR "Failed to congifure libxml2")
|
||||
endif()
|
||||
|
||||
check_library_exists(xar xar_open "" HAVE_LIBXAR)
|
||||
@ -167,6 +194,14 @@ check_symbol_exists(arc4random "stdlib.h" HAVE_DECL_ARC4RANDOM)
|
||||
find_package(Backtrace)
|
||||
set(HAVE_BACKTRACE ${Backtrace_FOUND})
|
||||
set(BACKTRACE_HEADER ${Backtrace_HEADER})
|
||||
|
||||
# Prevent check_symbol_exists from using API that is not supported for a given
|
||||
# deployment target.
|
||||
check_c_compiler_flag("-Werror=unguarded-availability-new" "C_SUPPORTS_WERROR_UNGUARDED_AVAILABILITY_NEW")
|
||||
if(C_SUPPORTS_WERROR_UNGUARDED_AVAILABILITY_NEW)
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror=unguarded-availability-new")
|
||||
endif()
|
||||
|
||||
check_symbol_exists(_Unwind_Backtrace "unwind.h" HAVE__UNWIND_BACKTRACE)
|
||||
check_symbol_exists(getpagesize unistd.h HAVE_GETPAGESIZE)
|
||||
check_symbol_exists(sysconf unistd.h HAVE_SYSCONF)
|
||||
@ -246,8 +281,11 @@ endif()
|
||||
check_symbol_exists(__GLIBC__ stdio.h LLVM_USING_GLIBC)
|
||||
if( LLVM_USING_GLIBC )
|
||||
add_definitions( -D_GNU_SOURCE )
|
||||
list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_GNU_SOURCE")
|
||||
endif()
|
||||
# This check requires _GNU_SOURCE
|
||||
check_symbol_exists(sched_getaffinity sched.h HAVE_SCHED_GETAFFINITY)
|
||||
check_symbol_exists(CPU_COUNT sched.h HAVE_CPU_COUNT)
|
||||
if(HAVE_LIBPTHREAD)
|
||||
check_library_exists(pthread pthread_getname_np "" HAVE_PTHREAD_GETNAME_NP)
|
||||
check_library_exists(pthread pthread_setname_np "" HAVE_PTHREAD_SETNAME_NP)
|
||||
@ -600,3 +638,34 @@ else()
|
||||
endif()
|
||||
|
||||
string(REPLACE " " ";" LLVM_BINDINGS_LIST "${LLVM_BINDINGS}")
|
||||
|
||||
function(find_python_module module)
|
||||
string(TOUPPER ${module} module_upper)
|
||||
set(FOUND_VAR PY_${module_upper}_FOUND)
|
||||
|
||||
execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c" "import ${module}"
|
||||
RESULT_VARIABLE status
|
||||
ERROR_QUIET)
|
||||
|
||||
if(status)
|
||||
set(${FOUND_VAR} 0 PARENT_SCOPE)
|
||||
message(STATUS "Could NOT find Python module ${module}")
|
||||
else()
|
||||
set(${FOUND_VAR} 1 PARENT_SCOPE)
|
||||
message(STATUS "Found Python module ${module}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
set (PYTHON_MODULES
|
||||
pygments
|
||||
yaml
|
||||
)
|
||||
foreach(module ${PYTHON_MODULES})
|
||||
find_python_module(${module})
|
||||
endforeach()
|
||||
|
||||
if(PY_PYGMENTS_FOUND AND PY_YAML_FOUND)
|
||||
set (LLVM_HAVE_OPT_VIEWER_MODULES 1)
|
||||
else()
|
||||
set (LLVM_HAVE_OPT_VIEWER_MODULES 0)
|
||||
endif()
|
||||
|
4
cmake/config.guess
vendored
4
cmake/config.guess
vendored
@ -206,10 +206,6 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
|
||||
echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
|
||||
exit ;;
|
||||
*:Bitrig:*:*)
|
||||
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
|
||||
echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
|
||||
exit ;;
|
||||
*:ekkoBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
|
||||
exit ;;
|
||||
|
@ -149,8 +149,13 @@ endfunction(add_llvm_symbol_exports)
|
||||
|
||||
if(NOT WIN32 AND NOT APPLE)
|
||||
# Detect what linker we have here
|
||||
if( LLVM_USE_LINKER )
|
||||
set(command ${CMAKE_C_COMPILER} -fuse-ld=${LLVM_USE_LINKER} -Wl,--version)
|
||||
else()
|
||||
set(command ${CMAKE_C_COMPILER} -Wl,--version)
|
||||
endif()
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_C_COMPILER} -Wl,--version
|
||||
COMMAND ${command}
|
||||
OUTPUT_VARIABLE stdout
|
||||
ERROR_VARIABLE stderr
|
||||
)
|
||||
@ -164,7 +169,8 @@ if(NOT WIN32 AND NOT APPLE)
|
||||
elseif("${stdout}" MATCHES "GNU ld")
|
||||
set(LLVM_LINKER_IS_GNULD ON)
|
||||
message(STATUS "Linker detection: GNU ld")
|
||||
elseif("${stderr}" MATCHES "Solaris Link Editors")
|
||||
elseif("${stderr}" MATCHES "Solaris Link Editors" OR
|
||||
"${stdout}" MATCHES "Solaris Link Editors")
|
||||
set(LLVM_LINKER_IS_SOLARISLD ON)
|
||||
message(STATUS "Linker detection: Solaris ld")
|
||||
else()
|
||||
@ -263,14 +269,14 @@ endfunction()
|
||||
#
|
||||
function(add_windows_version_resource_file OUT_VAR)
|
||||
set(sources ${ARGN})
|
||||
if (MSVC)
|
||||
if (MSVC AND CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
||||
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)
|
||||
endif(MSVC AND CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
|
||||
|
||||
set(${OUT_VAR} ${sources} PARENT_SCOPE)
|
||||
endfunction(add_windows_version_resource_file)
|
||||
@ -563,6 +569,32 @@ function(llvm_add_library name)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(add_llvm_install_targets target)
|
||||
cmake_parse_arguments(ARG "" "COMPONENT;PREFIX" "DEPENDS" ${ARGN})
|
||||
if(ARG_COMPONENT)
|
||||
set(component_option -DCMAKE_INSTALL_COMPONENT="${ARG_COMPONENT}")
|
||||
endif()
|
||||
if(ARG_PREFIX)
|
||||
set(prefix_option -DCMAKE_INSTALL_PREFIX="${ARG_PREFIX}")
|
||||
endif()
|
||||
|
||||
add_custom_target(${target}
|
||||
DEPENDS ${ARG_DEPENDS}
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
${component_option}
|
||||
${prefix_option}
|
||||
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake"
|
||||
USES_TERMINAL)
|
||||
add_custom_target(${target}-stripped
|
||||
DEPENDS ${ARG_DEPENDS}
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
${component_option}
|
||||
${prefix_option}
|
||||
-DCMAKE_INSTALL_DO_STRIP=1
|
||||
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake"
|
||||
USES_TERMINAL)
|
||||
endfunction()
|
||||
|
||||
macro(add_llvm_library name)
|
||||
cmake_parse_arguments(ARG
|
||||
"SHARED;BUILDTREE_ONLY"
|
||||
@ -613,11 +645,9 @@ macro(add_llvm_library name)
|
||||
COMPONENT ${name})
|
||||
|
||||
if (NOT CMAKE_CONFIGURATION_TYPES)
|
||||
add_custom_target(install-${name}
|
||||
DEPENDS ${name}
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
-DCMAKE_INSTALL_COMPONENT=${name}
|
||||
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
|
||||
add_llvm_install_targets(install-${name}
|
||||
DEPENDS ${name}
|
||||
COMPONENT ${name})
|
||||
endif()
|
||||
endif()
|
||||
set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS ${name})
|
||||
@ -687,7 +717,7 @@ macro(add_llvm_executable name)
|
||||
# it forces Xcode to properly link the static library.
|
||||
list(APPEND ALL_FILES "${LLVM_MAIN_SRC_DIR}/cmake/dummy.cpp")
|
||||
endif()
|
||||
|
||||
|
||||
if( EXCLUDE_FROM_ALL )
|
||||
add_executable(${name} EXCLUDE_FROM_ALL ${ALL_FILES})
|
||||
else()
|
||||
@ -738,7 +768,7 @@ macro(add_llvm_executable name)
|
||||
# libpthreads overrides some standard library symbols, so main
|
||||
# executable must be linked with it in order to provide consistent
|
||||
# API for all shared libaries loaded by this executable.
|
||||
target_link_libraries(${name} ${LLVM_PTHREAD_LIB})
|
||||
target_link_libraries(${name} PRIVATE ${LLVM_PTHREAD_LIB})
|
||||
endif()
|
||||
endmacro(add_llvm_executable name)
|
||||
|
||||
@ -843,11 +873,9 @@ macro(add_llvm_tool name)
|
||||
COMPONENT ${name})
|
||||
|
||||
if (NOT CMAKE_CONFIGURATION_TYPES)
|
||||
add_custom_target(install-${name}
|
||||
DEPENDS ${name}
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
-DCMAKE_INSTALL_COMPONENT=${name}
|
||||
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
|
||||
add_llvm_install_targets(install-${name}
|
||||
DEPENDS ${name}
|
||||
COMPONENT ${name})
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
@ -883,15 +911,30 @@ macro(add_llvm_utility name)
|
||||
RUNTIME DESTINATION ${LLVM_UTILS_INSTALL_DIR}
|
||||
COMPONENT ${name})
|
||||
if (NOT CMAKE_CONFIGURATION_TYPES)
|
||||
add_custom_target(install-${name}
|
||||
DEPENDS ${name}
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
-DCMAKE_INSTALL_COMPONENT=${name}
|
||||
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
|
||||
add_llvm_install_targets(install-${name}
|
||||
DEPENDS ${name}
|
||||
COMPONENT ${name})
|
||||
endif()
|
||||
endif()
|
||||
endmacro(add_llvm_utility name)
|
||||
|
||||
macro(add_llvm_fuzzer name)
|
||||
cmake_parse_arguments(ARG "" "DUMMY_MAIN" "" ${ARGN})
|
||||
if( LLVM_LIB_FUZZING_ENGINE )
|
||||
set(LLVM_OPTIONAL_SOURCES ${ARG_DUMMY_MAIN})
|
||||
add_llvm_executable(${name} ${ARG_UNPARSED_ARGUMENTS})
|
||||
target_link_libraries(${name} PRIVATE ${LLVM_LIB_FUZZING_ENGINE})
|
||||
set_target_properties(${name} PROPERTIES FOLDER "Fuzzers")
|
||||
elseif( LLVM_USE_SANITIZE_COVERAGE )
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=fuzzer")
|
||||
set(LLVM_OPTIONAL_SOURCES ${ARG_DUMMY_MAIN})
|
||||
add_llvm_executable(${name} ${ARG_UNPARSED_ARGUMENTS})
|
||||
set_target_properties(${name} PROPERTIES FOLDER "Fuzzers")
|
||||
elseif( ARG_DUMMY_MAIN )
|
||||
add_llvm_executable(${name} ${ARG_DUMMY_MAIN} ${ARG_UNPARSED_ARGUMENTS})
|
||||
set_target_properties(${name} PROPERTIES FOLDER "Fuzzers")
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(add_llvm_target target_name)
|
||||
include_directories(BEFORE
|
||||
@ -1020,6 +1063,13 @@ function(add_unittest test_suite test_name)
|
||||
set(EXCLUDE_FROM_ALL ON)
|
||||
endif()
|
||||
|
||||
# Our current version of gtest does not properly recognize C++11 support
|
||||
# with MSVC, so it falls back to tr1 / experimental classes. Since LLVM
|
||||
# itself requires C++11, we can safely force it on unconditionally so that
|
||||
# we don't have to fight with the buggy gtest check.
|
||||
add_definitions(-DGTEST_LANG_CXX11=1)
|
||||
add_definitions(-DGTEST_HAS_TR1_TUPLE=0)
|
||||
|
||||
include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest/include)
|
||||
include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googlemock/include)
|
||||
if (NOT LLVM_ENABLE_THREADS)
|
||||
@ -1043,7 +1093,7 @@ function(add_unittest test_suite test_name)
|
||||
# libpthreads overrides some standard library symbols, so main
|
||||
# executable must be linked with it in order to provide consistent
|
||||
# API for all shared libaries loaded by this executable.
|
||||
target_link_libraries(${test_name} gtest_main gtest ${LLVM_PTHREAD_LIB})
|
||||
target_link_libraries(${test_name} PRIVATE gtest_main gtest ${LLVM_PTHREAD_LIB})
|
||||
|
||||
add_dependencies(${test_suite} ${test_name})
|
||||
get_target_property(test_suite_folder ${test_suite} FOLDER)
|
||||
@ -1095,12 +1145,31 @@ function(llvm_canonicalize_cmake_booleans)
|
||||
endforeach()
|
||||
endfunction(llvm_canonicalize_cmake_booleans)
|
||||
|
||||
macro(set_llvm_build_mode)
|
||||
# Configuration-time: See Unit/lit.site.cfg.in
|
||||
if (CMAKE_CFG_INTDIR STREQUAL ".")
|
||||
set(LLVM_BUILD_MODE ".")
|
||||
else ()
|
||||
set(LLVM_BUILD_MODE "%(build_mode)s")
|
||||
endif ()
|
||||
endmacro()
|
||||
|
||||
# This function provides an automatic way to 'configure'-like generate a file
|
||||
# based on a set of common and custom variables, specifically targeting the
|
||||
# variables needed for the 'lit.site.cfg' files. This function bundles the
|
||||
# common variables that any Lit instance is likely to need, and custom
|
||||
# variables can be passed in.
|
||||
function(configure_lit_site_cfg input output)
|
||||
function(configure_lit_site_cfg site_in site_out)
|
||||
cmake_parse_arguments(ARG "" "" "MAIN_CONFIG;OUTPUT_MAPPING" ${ARGN})
|
||||
|
||||
if ("${ARG_MAIN_CONFIG}" STREQUAL "")
|
||||
get_filename_component(INPUT_DIR ${site_in} DIRECTORY)
|
||||
set(ARG_MAIN_CONFIG "${INPUT_DIR}/lit.cfg")
|
||||
endif()
|
||||
if ("${ARG_OUTPUT_MAPPING}" STREQUAL "")
|
||||
set(ARG_OUTPUT_MAPPING "${site_out}")
|
||||
endif()
|
||||
|
||||
foreach(c ${LLVM_TARGETS_TO_BUILD})
|
||||
set(TARGETS_BUILT "${TARGETS_BUILT} ${c}")
|
||||
endforeach(c)
|
||||
@ -1108,21 +1177,16 @@ function(configure_lit_site_cfg input output)
|
||||
|
||||
set(SHLIBEXT "${LTDL_SHLIB_EXT}")
|
||||
|
||||
# Configuration-time: See Unit/lit.site.cfg.in
|
||||
if (CMAKE_CFG_INTDIR STREQUAL ".")
|
||||
set(LLVM_BUILD_MODE ".")
|
||||
else ()
|
||||
set(LLVM_BUILD_MODE "%(build_mode)s")
|
||||
endif ()
|
||||
set_llvm_build_mode()
|
||||
|
||||
# They below might not be the build tree but provided binary tree.
|
||||
set(LLVM_SOURCE_DIR ${LLVM_MAIN_SRC_DIR})
|
||||
set(LLVM_BINARY_DIR ${LLVM_BINARY_DIR})
|
||||
string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} LLVM_TOOLS_DIR ${LLVM_TOOLS_BINARY_DIR})
|
||||
string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} LLVM_LIBS_DIR ${LLVM_LIBRARY_DIR})
|
||||
string(REPLACE "${CMAKE_CFG_INTDIR}" "${LLVM_BUILD_MODE}" LLVM_TOOLS_DIR "${LLVM_TOOLS_BINARY_DIR}")
|
||||
string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} LLVM_LIBS_DIR "${LLVM_LIBRARY_DIR}")
|
||||
|
||||
# SHLIBDIR points the build tree.
|
||||
string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} SHLIBDIR "${LLVM_SHLIB_OUTPUT_INTDIR}")
|
||||
string(REPLACE "${CMAKE_CFG_INTDIR}" "${LLVM_BUILD_MODE}" SHLIBDIR "${LLVM_SHLIB_OUTPUT_INTDIR}")
|
||||
|
||||
set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE})
|
||||
# FIXME: "ENABLE_SHARED" doesn't make sense, since it is used just for
|
||||
@ -1146,7 +1210,7 @@ function(configure_lit_site_cfg input output)
|
||||
set(HOST_CXX "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}")
|
||||
set(HOST_LDFLAGS "${CMAKE_EXE_LINKER_FLAGS}")
|
||||
|
||||
set(LIT_SITE_CFG_IN_HEADER "## Autogenerated from ${input}\n## Do not edit!")
|
||||
set(LIT_SITE_CFG_IN_HEADER "## Autogenerated from ${site_in}\n## Do not edit!")
|
||||
|
||||
# Override config_target_triple (and the env)
|
||||
if(LLVM_TARGET_TRIPLE_ENV)
|
||||
@ -1161,7 +1225,74 @@ function(configure_lit_site_cfg input output)
|
||||
set(TARGET_TRIPLE "\"+config.target_triple+\"")
|
||||
endif()
|
||||
|
||||
configure_file(${input} ${output} @ONLY)
|
||||
string(CONCAT LIT_SITE_CFG_IN_FOOTER
|
||||
"import lit.llvm\n"
|
||||
"lit.llvm.initialize(lit_config, config)\n")
|
||||
|
||||
configure_file(${site_in} ${site_out} @ONLY)
|
||||
if (EXISTS "${ARG_MAIN_CONFIG}")
|
||||
set(PYTHON_STATEMENT "map_config('${ARG_MAIN_CONFIG}', '${site_out}')")
|
||||
get_property(LLVM_LIT_CONFIG_MAP GLOBAL PROPERTY LLVM_LIT_CONFIG_MAP)
|
||||
set(LLVM_LIT_CONFIG_MAP "${LLVM_LIT_CONFIG_MAP}\n${PYTHON_STATEMENT}")
|
||||
set_property(GLOBAL PROPERTY LLVM_LIT_CONFIG_MAP ${LLVM_LIT_CONFIG_MAP})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(dump_all_cmake_variables)
|
||||
get_cmake_property(_variableNames VARIABLES)
|
||||
foreach (_variableName ${_variableNames})
|
||||
message(STATUS "${_variableName}=${${_variableName}}")
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(get_llvm_lit_path base_dir file_name)
|
||||
cmake_parse_arguments(ARG "ALLOW_EXTERNAL" "" "" ${ARGN})
|
||||
|
||||
if (ARG_ALLOW_EXTERNAL)
|
||||
set(LLVM_DEFAULT_EXTERNAL_LIT "${LLVM_EXTERNAL_LIT}")
|
||||
set (LLVM_EXTERNAL_LIT "" CACHE STRING "Command used to spawn lit")
|
||||
if ("${LLVM_EXTERNAL_LIT}" STREQUAL "")
|
||||
set(LLVM_EXTERNAL_LIT "${LLVM_DEFAULT_EXTERNAL_LIT}")
|
||||
endif()
|
||||
|
||||
if (NOT "${LLVM_EXTERNAL_LIT}" STREQUAL "")
|
||||
if (EXISTS ${LLVM_EXTERNAL_LIT})
|
||||
get_filename_component(LIT_FILE_NAME ${LLVM_EXTERNAL_LIT} NAME)
|
||||
get_filename_component(LIT_BASE_DIR ${LLVM_EXTERNAL_LIT} DIRECTORY)
|
||||
set(${file_name} ${LIT_FILE_NAME} PARENT_SCOPE)
|
||||
set(${base_dir} ${LIT_BASE_DIR} PARENT_SCOPE)
|
||||
return()
|
||||
else()
|
||||
message(WARN "LLVM_EXTERNAL_LIT set to ${LLVM_EXTERNAL_LIT}, but the path does not exist.")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(lit_file_name "llvm-lit")
|
||||
if (WIN32 AND NOT CYGWIN)
|
||||
# llvm-lit needs suffix.py for multiprocess to find a main module.
|
||||
set(lit_file_name "${lit_file_name}.py")
|
||||
endif ()
|
||||
set(${file_name} ${lit_file_name} PARENT_SCOPE)
|
||||
|
||||
get_property(LLVM_LIT_BASE_DIR GLOBAL PROPERTY LLVM_LIT_BASE_DIR)
|
||||
if (NOT "${LLVM_LIT_BASE_DIR}" STREQUAL "")
|
||||
set(${base_dir} ${LLVM_LIT_BASE_DIR} PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
# Allow individual projects to provide an override
|
||||
if (NOT "${LLVM_LIT_OUTPUT_DIR}" STREQUAL "")
|
||||
set(LLVM_LIT_BASE_DIR ${LLVM_LIT_OUTPUT_DIR})
|
||||
elseif(NOT "${LLVM_RUNTIME_OUTPUT_INTDIR}" STREQUAL "")
|
||||
set(LLVM_LIT_BASE_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR})
|
||||
else()
|
||||
set(LLVM_LIT_BASE_DIR "")
|
||||
endif()
|
||||
|
||||
# Cache this so we don't have to do it again and have subsequent calls
|
||||
# potentially disagree on the value.
|
||||
set_property(GLOBAL PROPERTY LLVM_LIT_BASE_DIR ${LLVM_LIT_BASE_DIR})
|
||||
set(${base_dir} ${LLVM_LIT_BASE_DIR} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# A raw function to create a lit target. This is used to implement the testuite
|
||||
@ -1173,12 +1304,16 @@ function(add_lit_target target comment)
|
||||
if (NOT CMAKE_CFG_INTDIR STREQUAL ".")
|
||||
list(APPEND LIT_ARGS --param build_mode=${CMAKE_CFG_INTDIR})
|
||||
endif ()
|
||||
if (EXISTS ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py)
|
||||
set (LIT_COMMAND "${PYTHON_EXECUTABLE};${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py"
|
||||
CACHE STRING "Command used to spawn llvm-lit")
|
||||
else()
|
||||
find_program(LIT_COMMAND NAMES llvm-lit lit.py lit)
|
||||
endif ()
|
||||
|
||||
# Get the path to the lit to *run* tests with. This can be overriden by
|
||||
# the user by specifying -DLLVM_EXTERNAL_LIT=<path-to-lit.py>
|
||||
get_llvm_lit_path(
|
||||
lit_base_dir
|
||||
lit_file_name
|
||||
ALLOW_EXTERNAL
|
||||
)
|
||||
|
||||
set(LIT_COMMAND "${PYTHON_EXECUTABLE};${lit_base_dir}/${lit_file_name}")
|
||||
list(APPEND LIT_COMMAND ${LIT_ARGS})
|
||||
foreach(param ${ARG_PARAMS})
|
||||
list(APPEND LIT_COMMAND --param ${param})
|
||||
@ -1285,11 +1420,9 @@ function(llvm_install_library_symlink name dest type)
|
||||
COMPONENT ${component})
|
||||
|
||||
if (NOT CMAKE_CONFIGURATION_TYPES AND NOT ARG_ALWAYS_GENERATE)
|
||||
add_custom_target(install-${name}
|
||||
DEPENDS ${name} ${dest} install-${dest}
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
-DCMAKE_INSTALL_COMPONENT=${name}
|
||||
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
|
||||
add_llvm_install_targets(install-${name}
|
||||
DEPENDS ${name} ${dest} install-${dest}
|
||||
COMPONENT ${name})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
@ -1320,11 +1453,9 @@ function(llvm_install_symlink name dest)
|
||||
COMPONENT ${component})
|
||||
|
||||
if (NOT CMAKE_CONFIGURATION_TYPES AND NOT ARG_ALWAYS_GENERATE)
|
||||
add_custom_target(install-${name}
|
||||
DEPENDS ${name} ${dest} install-${dest}
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
-DCMAKE_INSTALL_COMPONENT=${name}
|
||||
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
|
||||
add_llvm_install_targets(install-${name}
|
||||
DEPENDS ${name} ${dest} install-${dest}
|
||||
COMPONENT ${name})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
@ -1338,7 +1469,7 @@ function(add_llvm_tool_symlink link_name target)
|
||||
# magic. First we grab one of the types, and a type-specific path. Then from
|
||||
# the type-specific path we find the last occurrence of the type in the path,
|
||||
# and replace it with CMAKE_CFG_INTDIR. This allows the build step to be type
|
||||
# agnostic again.
|
||||
# agnostic again.
|
||||
if(NOT ARG_OUTPUT_DIR)
|
||||
# If you're not overriding the OUTPUT_DIR, we can make the link relative in
|
||||
# the same directory.
|
||||
@ -1488,3 +1619,36 @@ function(setup_dependency_debugging name)
|
||||
set(sandbox_command "sandbox-exec -p '(version 1) (allow default) ${deny_attributes_gen} ${deny_intrinsics_gen}'")
|
||||
set_target_properties(${name} PROPERTIES RULE_LAUNCH_COMPILE ${sandbox_command})
|
||||
endfunction()
|
||||
|
||||
# Figure out if we can track VC revisions.
|
||||
function(find_first_existing_file out_var)
|
||||
foreach(file ${ARGN})
|
||||
if(EXISTS "${file}")
|
||||
set(${out_var} "${file}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
macro(find_first_existing_vc_file out_var path)
|
||||
find_program(git_executable NAMES git git.exe git.cmd)
|
||||
# Run from a subdirectory to force git to print an absolute path.
|
||||
execute_process(COMMAND ${git_executable} rev-parse --git-dir
|
||||
WORKING_DIRECTORY ${path}/cmake
|
||||
RESULT_VARIABLE git_result
|
||||
OUTPUT_VARIABLE git_dir
|
||||
ERROR_QUIET)
|
||||
if(git_result EQUAL 0)
|
||||
string(STRIP "${git_dir}" git_dir)
|
||||
set(${out_var} "${git_dir}/logs/HEAD")
|
||||
# some branchless cases (e.g. 'repo') may not yet have .git/logs/HEAD
|
||||
if (NOT EXISTS "${git_dir}/logs/HEAD")
|
||||
file(WRITE "${git_dir}/logs/HEAD" "")
|
||||
endif()
|
||||
else()
|
||||
find_first_existing_file(${out_var}
|
||||
"${path}/.svn/wc.db" # SVN 1.7
|
||||
"${path}/.svn/entries" # SVN 1.6
|
||||
)
|
||||
endif()
|
||||
endmacro()
|
||||
|
@ -221,3 +221,4 @@ add_custom_target(ocaml_make_directory
|
||||
COMMAND "${CMAKE_COMMAND}" "-E" "make_directory" "${LLVM_LIBRARY_DIR}/ocaml/llvm")
|
||||
add_custom_target("ocaml_all")
|
||||
set_target_properties(ocaml_all PROPERTIES FOLDER "Misc")
|
||||
set_target_properties(ocaml_make_directory PROPERTIES FOLDER "Misc")
|
||||
|
@ -19,7 +19,7 @@ endif()
|
||||
# ``project`` should be the project name
|
||||
function (add_sphinx_target builder project)
|
||||
set(SPHINX_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/${builder}")
|
||||
set(SPHINX_DOC_TREE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_doctrees-${builder}")
|
||||
set(SPHINX_DOC_TREE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_doctrees-${project}-${builder}")
|
||||
set(SPHINX_TARGET_NAME docs-${project}-${builder})
|
||||
|
||||
if (SPHINX_WARNINGS_AS_ERRORS)
|
||||
|
@ -129,9 +129,7 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
|
||||
if (NOT CMAKE_CONFIGURATION_TYPES)
|
||||
# Add a dummy target so this can be used with LLVM_DISTRIBUTION_COMPONENTS
|
||||
add_custom_target(cmake-exports)
|
||||
add_custom_target(install-cmake-exports
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
-DCMAKE_INSTALL_COMPONENT=cmake-exports
|
||||
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
|
||||
add_llvm_install_targets(install-cmake-exports
|
||||
COMPONENT cmake-exports)
|
||||
endif()
|
||||
endif()
|
||||
|
@ -1,6 +1,7 @@
|
||||
# atomic builtins are required for threading support.
|
||||
|
||||
INCLUDE(CheckCXXSourceCompiles)
|
||||
INCLUDE(CheckLibraryExists)
|
||||
|
||||
# Sometimes linking against libatomic is required for atomic ops, if
|
||||
# the platform doesn't support lock-free atomics.
|
||||
@ -80,7 +81,6 @@ endif()
|
||||
## assumes C++11 <atomic> works.
|
||||
CHECK_CXX_SOURCE_COMPILES("
|
||||
#ifdef _MSC_VER
|
||||
#include <Intrin.h> /* Workaround for PR19898. */
|
||||
#include <windows.h>
|
||||
#endif
|
||||
int main() {
|
||||
|
@ -1,8 +1,6 @@
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
function(check_linker_flag flag out_var)
|
||||
set(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${flag}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${flag}")
|
||||
check_cxx_compiler_flag("" ${out_var})
|
||||
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
|
||||
endfunction()
|
||||
|
@ -7,52 +7,56 @@ function(llvm_create_cross_target_internal target_name toolchain buildtype)
|
||||
endif(NOT DEFINED LLVM_${target_name}_BUILD)
|
||||
|
||||
if (EXISTS ${LLVM_MAIN_SRC_DIR}/cmake/platforms/${toolchain}.cmake)
|
||||
set(CROSS_TOOLCHAIN_FLAGS_${target_name}
|
||||
-DCMAKE_TOOLCHAIN_FILE=\"${LLVM_MAIN_SRC_DIR}/cmake/platforms/${toolchain}.cmake\"
|
||||
CACHE STRING "Toolchain file for ${target_name}")
|
||||
set(CROSS_TOOLCHAIN_FLAGS_INIT
|
||||
-DCMAKE_TOOLCHAIN_FILE=\"${LLVM_MAIN_SRC_DIR}/cmake/platforms/${toolchain}.cmake\")
|
||||
else()
|
||||
set(CROSS_TOOLCHAIN_FLAGS_INIT
|
||||
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
|
||||
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
|
||||
)
|
||||
endif()
|
||||
set(CROSS_TOOLCHAIN_FLAGS_${target_name} ${CROSS_TOOLCHAIN_FLAGS_INIT}
|
||||
CACHE STRING "Toolchain configuration for ${target_name}")
|
||||
|
||||
if (buildtype)
|
||||
set(build_type_flags "-DCMAKE_BUILD_TYPE=${buildtype}")
|
||||
endif()
|
||||
if (LLVM_USE_LINKER AND NOT CMAKE_CROSSCOMPILING)
|
||||
set(linker_flag "-DLLVM_USE_LINKER=${LLVM_USE_LINKER}")
|
||||
endif()
|
||||
if (LLVM_EXTERNAL_CLANG_SOURCE_DIR)
|
||||
# Propagate LLVM_EXTERNAL_CLANG_SOURCE_DIR so that clang-tblgen can be built
|
||||
set(external_clang_dir "-DLLVM_EXTERNAL_CLANG_SOURCE_DIR=${LLVM_EXTERNAL_CLANG_SOURCE_DIR}")
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT ${LLVM_${target_name}_BUILD}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${LLVM_${target_name}_BUILD}
|
||||
COMMENT "Creating ${LLVM_${target_name}_BUILD}...")
|
||||
|
||||
add_custom_target(CREATE_LLVM_${target_name}
|
||||
DEPENDS ${LLVM_${target_name}_BUILD})
|
||||
|
||||
# Escape semicolons in the targets list so that cmake doesn't expand
|
||||
# them to spaces.
|
||||
string(REPLACE ";" "$<SEMICOLON>" targets_to_build_arg
|
||||
"${LLVM_TARGETS_TO_BUILD}")
|
||||
string(REPLACE ";" "$<SEMICOLON>" experimental_targets_to_build_arg
|
||||
"${LLVM_EXPERIMENTAL_TARGETS_TO_BUILD}")
|
||||
|
||||
add_custom_command(OUTPUT ${LLVM_${target_name}_BUILD}/CMakeCache.txt
|
||||
COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}"
|
||||
${CROSS_TOOLCHAIN_FLAGS_${target_name}} ${CMAKE_SOURCE_DIR}
|
||||
-DLLVM_TARGET_IS_CROSSCOMPILE_HOST=TRUE
|
||||
-DLLVM_TARGETS_TO_BUILD="${targets_to_build_arg}"
|
||||
-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="${experimental_targets_to_build_arg}"
|
||||
${build_type_flags} ${linker_flag} ${external_clang_dir}
|
||||
WORKING_DIRECTORY ${LLVM_${target_name}_BUILD}
|
||||
DEPENDS ${LLVM_${target_name}_BUILD}
|
||||
DEPENDS CREATE_LLVM_${target_name}
|
||||
COMMENT "Configuring ${target_name} LLVM...")
|
||||
|
||||
add_custom_target(CONFIGURE_LLVM_${target_name}
|
||||
DEPENDS ${LLVM_${target_name}_BUILD}/CMakeCache.txt)
|
||||
|
||||
set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES
|
||||
${LLVM_${target_name}_BUILD})
|
||||
|
||||
if(NOT IS_DIRECTORY ${LLVM_${target_name}_BUILD})
|
||||
|
||||
|
||||
message(STATUS "Configuring ${target_name} build...")
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory
|
||||
${LLVM_${target_name}_BUILD} )
|
||||
|
||||
message(STATUS "Configuring ${target_name} targets...")
|
||||
if (buildtype)
|
||||
set(build_type_flags "-DCMAKE_BUILD_TYPE=${buildtype}")
|
||||
endif()
|
||||
if (LLVM_EXTERNAL_CLANG_SOURCE_DIR)
|
||||
# Propagate LLVM_EXTERNAL_CLANG_SOURCE_DIR so that clang-tblgen can be built
|
||||
set(external_clang_dir "-DLLVM_EXTERNAL_CLANG_SOURCE_DIR=${LLVM_EXTERNAL_CLANG_SOURCE_DIR}")
|
||||
endif()
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} ${build_type_flags}
|
||||
-G "${CMAKE_GENERATOR}" -DLLVM_TARGETS_TO_BUILD=${LLVM_TARGETS_TO_BUILD}
|
||||
${CROSS_TOOLCHAIN_FLAGS_${target_name}} ${CMAKE_SOURCE_DIR}
|
||||
-DLLVM_TARGET_IS_CROSSCOMPILE_HOST=TRUE
|
||||
${external_clang_dir}
|
||||
WORKING_DIRECTORY ${LLVM_${target_name}_BUILD} )
|
||||
endif(NOT IS_DIRECTORY ${LLVM_${target_name}_BUILD})
|
||||
|
||||
endfunction()
|
||||
|
||||
function(llvm_create_cross_target target_name sysroot)
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
function( get_host_triple var )
|
||||
if( MSVC )
|
||||
if( CMAKE_CL_64 )
|
||||
if( CMAKE_SIZEOF_VOID_P EQUAL 8 )
|
||||
set( value "x86_64-pc-win32" )
|
||||
else()
|
||||
set( value "i686-pc-win32" )
|
||||
|
@ -1,17 +1,15 @@
|
||||
# CMake project that writes Subversion revision information to a header.
|
||||
#
|
||||
# Input variables:
|
||||
# FIRST_SOURCE_DIR - First source directory
|
||||
# FIRST_NAME - The macro prefix for the first repository's info
|
||||
# SECOND_SOURCE_DIR - Second source directory (opt)
|
||||
# SECOND_NAME - The macro prefix for the second repository's info (opt)
|
||||
# HEADER_FILE - The header file to write
|
||||
# SOURCE_DIRS - A list of source directories.
|
||||
# NAMES - A list of macro prefixes for each of the source directories.
|
||||
# HEADER_FILE - The header file to write
|
||||
#
|
||||
# The output header will contain macros FIRST_REPOSITORY and FIRST_REVISION,
|
||||
# and SECOND_REPOSITORY and SECOND_REVISION if requested, where "FIRST" and
|
||||
# "SECOND" are substituted with the names specified in the input variables.
|
||||
# The output header will contain macros <NAME>_REPOSITORY and <NAME>_REVISION,
|
||||
# where "<NAME>" and is substituted with the names specified in the input
|
||||
# variables, for each of the SOURCE_DIRS given.
|
||||
|
||||
# Chop off cmake/modules/GetSVN.cmake
|
||||
# Chop off cmake/modules/GetSVN.cmake
|
||||
get_filename_component(LLVM_DIR "${CMAKE_SCRIPT_MODE_FILE}" PATH)
|
||||
get_filename_component(LLVM_DIR "${LLVM_DIR}" PATH)
|
||||
get_filename_component(LLVM_DIR "${LLVM_DIR}" PATH)
|
||||
@ -86,7 +84,7 @@ endmacro()
|
||||
function(get_source_info path revision repository)
|
||||
if (EXISTS "${path}/.svn")
|
||||
get_source_info_svn("${path}" revision repository)
|
||||
elseif (EXISTS "${path}/.git/svn")
|
||||
elseif (EXISTS "${path}/.git/svn/refs")
|
||||
get_source_info_git_svn("${path}" revision repository)
|
||||
elseif (EXISTS "${path}/.git")
|
||||
get_source_info_git("${path}" revision repository)
|
||||
@ -103,9 +101,37 @@ function(append_info name path)
|
||||
"#define ${name}_REPOSITORY \"${repository}\"\n")
|
||||
endfunction()
|
||||
|
||||
append_info(${FIRST_NAME} "${FIRST_SOURCE_DIR}")
|
||||
if(DEFINED SECOND_SOURCE_DIR)
|
||||
append_info(${SECOND_NAME} "${SECOND_SOURCE_DIR}")
|
||||
function(validate_inputs source_dirs names)
|
||||
list(LENGTH source_dirs source_dirs_length)
|
||||
list(LENGTH names names_length)
|
||||
if (NOT source_dirs_length EQUAL names_length)
|
||||
message(FATAL_ERROR
|
||||
"GetSVN.cmake takes two arguments: a list of source directories, "
|
||||
"and a list of names. Expected two lists must be of equal length, "
|
||||
"but got ${source_dirs_length} source directories and "
|
||||
"${names_length} names.")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
if (DEFINED SOURCE_DIRS AND DEFINED NAMES)
|
||||
validate_inputs("${SOURCE_DIRS}" "${NAMES}")
|
||||
|
||||
list(LENGTH SOURCE_DIRS source_dirs_length)
|
||||
math(EXPR source_dirs_max_index ${source_dirs_length}-1)
|
||||
foreach(index RANGE ${source_dirs_max_index})
|
||||
list(GET SOURCE_DIRS ${index} source_dir)
|
||||
list(GET NAMES ${index} name)
|
||||
append_info(${name} ${source_dir})
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Allow -DFIRST_SOURCE_DIR arguments until Clang migrates to the new
|
||||
# -DSOURCE_DIRS argument.
|
||||
if(DEFINED FIRST_SOURCE_DIR)
|
||||
append_info(${FIRST_NAME} "${FIRST_SOURCE_DIR}")
|
||||
if(DEFINED SECOND_SOURCE_DIR)
|
||||
append_info(${SECOND_NAME} "${SECOND_SOURCE_DIR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Copy the file only if it has changed.
|
||||
|
@ -151,6 +151,14 @@ if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR WIN32 OR CYGWIN OR
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,defs")
|
||||
endif()
|
||||
|
||||
# Pass -Wl,-z,nodelete. This makes sure our shared libraries are not unloaded
|
||||
# by dlclose(). We need that since the CLI API relies on cross-references
|
||||
# between global objects which became horribly broken when one of the libraries
|
||||
# is unloaded.
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,nodelete")
|
||||
endif()
|
||||
|
||||
|
||||
function(append value)
|
||||
foreach(variable ${ARGN})
|
||||
@ -194,10 +202,13 @@ if( LLVM_ENABLE_LLD )
|
||||
endif()
|
||||
|
||||
if( LLVM_USE_LINKER )
|
||||
check_cxx_compiler_flag("-fuse-ld=${LLVM_USE_LINKER}" CXX_SUPPORTS_CUSTOM_LINKER)
|
||||
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fuse-ld=${LLVM_USE_LINKER}")
|
||||
check_cxx_source_compiles("int main() { return 0; }" CXX_SUPPORTS_CUSTOM_LINKER)
|
||||
if ( NOT CXX_SUPPORTS_CUSTOM_LINKER )
|
||||
message(FATAL_ERROR "Host compiler does not support '-fuse-ld=${LLVM_USE_LINKER}'")
|
||||
endif()
|
||||
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
|
||||
append("-fuse-ld=${LLVM_USE_LINKER}"
|
||||
CMAKE_EXE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS)
|
||||
endif()
|
||||
@ -229,12 +240,21 @@ if( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32 )
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -m32")
|
||||
|
||||
# FIXME: CMAKE_SIZEOF_VOID_P is still 8
|
||||
add_definitions(-D_LARGEFILE_SOURCE)
|
||||
add_definitions(-D_FILE_OFFSET_BITS=64)
|
||||
endif( LLVM_BUILD_32_BITS )
|
||||
endif( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32 )
|
||||
|
||||
# If building on a GNU specific 32-bit system, make sure off_t is 64 bits
|
||||
# so that off_t can stored offset > 2GB
|
||||
if( CMAKE_SIZEOF_VOID_P EQUAL 4 )
|
||||
# so that off_t can stored offset > 2GB.
|
||||
# Android until version N (API 24) doesn't support it.
|
||||
if (ANDROID AND (ANDROID_NATIVE_API_LEVEL LESS 24))
|
||||
set(LLVM_FORCE_SMALLFILE_FOR_ANDROID TRUE)
|
||||
endif()
|
||||
if( CMAKE_SIZEOF_VOID_P EQUAL 4 AND NOT LLVM_FORCE_SMALLFILE_FOR_ANDROID)
|
||||
# FIXME: It isn't handled in LLVM_BUILD_32_BITS.
|
||||
add_definitions( -D_LARGEFILE_SOURCE )
|
||||
add_definitions( -D_FILE_OFFSET_BITS=64 )
|
||||
endif()
|
||||
@ -303,13 +323,13 @@ if( MSVC )
|
||||
# especially so std::equal(nullptr, nullptr, nullptr) will not assert.
|
||||
add_definitions("-D_DEBUG_POINTER_IMPL=")
|
||||
endif()
|
||||
|
||||
|
||||
include(ChooseMSVCCRT)
|
||||
|
||||
if( MSVC11 )
|
||||
add_definitions(-D_VARIADIC_MAX=10)
|
||||
endif()
|
||||
|
||||
|
||||
# Add definitions that make MSVC much less annoying.
|
||||
add_definitions(
|
||||
# For some reason MS wants to deprecate a bunch of standard functions...
|
||||
@ -370,7 +390,7 @@ if( MSVC )
|
||||
|
||||
string(FIND "${upper_exe_flags} ${upper_module_flags} ${upper_shared_flags}"
|
||||
"/INCREMENTAL" linker_flag_idx)
|
||||
|
||||
|
||||
if (${linker_flag_idx} GREATER -1)
|
||||
message(WARNING "/Brepro not compatible with /INCREMENTAL linking - builds will be non-deterministic")
|
||||
else()
|
||||
@ -381,7 +401,9 @@ if( MSVC )
|
||||
|
||||
elseif( LLVM_COMPILER_IS_GCC_COMPATIBLE )
|
||||
append_if(LLVM_ENABLE_WERROR "-Werror" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
append_if(LLVM_ENABLE_WERROR "-Wno-error" CMAKE_REQUIRED_FLAGS)
|
||||
add_flag_if_supported("-Werror=date-time" WERROR_DATE_TIME)
|
||||
add_flag_if_supported("-Werror=unguarded-availability-new" WERROR_UNGUARDED_AVAILABILITY_NEW)
|
||||
if (LLVM_ENABLE_CXX1Y)
|
||||
check_cxx_compiler_flag("-std=c++1y" CXX_SUPPORTS_CXX1Y)
|
||||
append_if(CXX_SUPPORTS_CXX1Y "-std=c++1y" CMAKE_CXX_FLAGS)
|
||||
@ -436,64 +458,66 @@ elseif( LLVM_COMPILER_IS_GCC_COMPATIBLE )
|
||||
endif(LLVM_ENABLE_MODULES)
|
||||
endif( MSVC )
|
||||
|
||||
if (MSVC AND NOT CLANG_CL)
|
||||
set(msvc_warning_flags
|
||||
# Disabled warnings.
|
||||
-wd4141 # Suppress ''modifier' : used more than once' (because of __forceinline combined with inline)
|
||||
-wd4146 # Suppress 'unary minus operator applied to unsigned type, result still unsigned'
|
||||
-wd4180 # Suppress 'qualifier applied to function type has no meaning; ignored'
|
||||
-wd4244 # Suppress ''argument' : conversion from 'type1' to 'type2', possible loss of data'
|
||||
-wd4258 # Suppress ''var' : definition from the for loop is ignored; the definition from the enclosing scope is used'
|
||||
-wd4267 # Suppress ''var' : conversion from 'size_t' to 'type', possible loss of data'
|
||||
-wd4291 # Suppress ''declaration' : no matching operator delete found; memory will not be freed if initialization throws an exception'
|
||||
-wd4345 # Suppress 'behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized'
|
||||
-wd4351 # Suppress 'new behavior: elements of array 'array' will be default initialized'
|
||||
-wd4355 # Suppress ''this' : used in base member initializer list'
|
||||
-wd4456 # Suppress 'declaration of 'var' hides local variable'
|
||||
-wd4457 # Suppress 'declaration of 'var' hides function parameter'
|
||||
-wd4458 # Suppress 'declaration of 'var' hides class member'
|
||||
-wd4459 # Suppress 'declaration of 'var' hides global declaration'
|
||||
-wd4503 # Suppress ''identifier' : decorated name length exceeded, name was truncated'
|
||||
-wd4624 # Suppress ''derived class' : destructor could not be generated because a base class destructor is inaccessible'
|
||||
-wd4722 # Suppress 'function' : destructor never returns, potential memory leak
|
||||
-wd4800 # Suppress ''type' : forcing value to bool 'true' or 'false' (performance warning)'
|
||||
-wd4100 # Suppress 'unreferenced formal parameter'
|
||||
-wd4127 # Suppress 'conditional expression is constant'
|
||||
-wd4512 # Suppress 'assignment operator could not be generated'
|
||||
-wd4505 # Suppress 'unreferenced local function has been removed'
|
||||
-wd4610 # Suppress '<class> can never be instantiated'
|
||||
-wd4510 # Suppress 'default constructor could not be generated'
|
||||
-wd4702 # Suppress 'unreachable code'
|
||||
-wd4245 # Suppress 'signed/unsigned mismatch'
|
||||
-wd4706 # Suppress 'assignment within conditional expression'
|
||||
-wd4310 # Suppress 'cast truncates constant value'
|
||||
-wd4701 # Suppress 'potentially uninitialized local variable'
|
||||
-wd4703 # Suppress 'potentially uninitialized local pointer variable'
|
||||
-wd4389 # Suppress 'signed/unsigned mismatch'
|
||||
-wd4611 # Suppress 'interaction between '_setjmp' and C++ object destruction is non-portable'
|
||||
-wd4805 # Suppress 'unsafe mix of type <type> and type <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'
|
||||
# C4592 is disabled because of false positives in Visual Studio 2015
|
||||
# Update 1. Re-evaluate the usefulness of this diagnostic with Update 2.
|
||||
-wd4592 # Suppress ''var': symbol will be dynamically initialized (implementation limitation)
|
||||
-wd4319 # Suppress ''operator' : zero extending 'type' to 'type' of greater size'
|
||||
if (MSVC)
|
||||
if (NOT CLANG_CL)
|
||||
set(msvc_warning_flags
|
||||
# Disabled warnings.
|
||||
-wd4141 # Suppress ''modifier' : used more than once' (because of __forceinline combined with inline)
|
||||
-wd4146 # Suppress 'unary minus operator applied to unsigned type, result still unsigned'
|
||||
-wd4180 # Suppress 'qualifier applied to function type has no meaning; ignored'
|
||||
-wd4244 # Suppress ''argument' : conversion from 'type1' to 'type2', possible loss of data'
|
||||
-wd4258 # Suppress ''var' : definition from the for loop is ignored; the definition from the enclosing scope is used'
|
||||
-wd4267 # Suppress ''var' : conversion from 'size_t' to 'type', possible loss of data'
|
||||
-wd4291 # Suppress ''declaration' : no matching operator delete found; memory will not be freed if initialization throws an exception'
|
||||
-wd4345 # Suppress 'behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized'
|
||||
-wd4351 # Suppress 'new behavior: elements of array 'array' will be default initialized'
|
||||
-wd4355 # Suppress ''this' : used in base member initializer list'
|
||||
-wd4456 # Suppress 'declaration of 'var' hides local variable'
|
||||
-wd4457 # Suppress 'declaration of 'var' hides function parameter'
|
||||
-wd4458 # Suppress 'declaration of 'var' hides class member'
|
||||
-wd4459 # Suppress 'declaration of 'var' hides global declaration'
|
||||
-wd4503 # Suppress ''identifier' : decorated name length exceeded, name was truncated'
|
||||
-wd4624 # Suppress ''derived class' : destructor could not be generated because a base class destructor is inaccessible'
|
||||
-wd4722 # Suppress 'function' : destructor never returns, potential memory leak
|
||||
-wd4800 # Suppress ''type' : forcing value to bool 'true' or 'false' (performance warning)'
|
||||
-wd4100 # Suppress 'unreferenced formal parameter'
|
||||
-wd4127 # Suppress 'conditional expression is constant'
|
||||
-wd4512 # Suppress 'assignment operator could not be generated'
|
||||
-wd4505 # Suppress 'unreferenced local function has been removed'
|
||||
-wd4610 # Suppress '<class> can never be instantiated'
|
||||
-wd4510 # Suppress 'default constructor could not be generated'
|
||||
-wd4702 # Suppress 'unreachable code'
|
||||
-wd4245 # Suppress 'signed/unsigned mismatch'
|
||||
-wd4706 # Suppress 'assignment within conditional expression'
|
||||
-wd4310 # Suppress 'cast truncates constant value'
|
||||
-wd4701 # Suppress 'potentially uninitialized local variable'
|
||||
-wd4703 # Suppress 'potentially uninitialized local pointer variable'
|
||||
-wd4389 # Suppress 'signed/unsigned mismatch'
|
||||
-wd4611 # Suppress 'interaction between '_setjmp' and C++ object destruction is non-portable'
|
||||
-wd4805 # Suppress 'unsafe mix of type <type> and type <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'
|
||||
# C4592 is disabled because of false positives in Visual Studio 2015
|
||||
# Update 1. Re-evaluate the usefulness of this diagnostic with Update 2.
|
||||
-wd4592 # Suppress ''var': symbol will be dynamically initialized (implementation limitation)
|
||||
-wd4319 # Suppress ''operator' : zero extending 'type' to 'type' of greater size'
|
||||
|
||||
# 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())'
|
||||
# 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.
|
||||
# Promoted warnings.
|
||||
-w14062 # Promote 'enumerator in switch of enum is not handled' to level 1 warning.
|
||||
|
||||
# Promoted warnings to errors.
|
||||
-we4238 # Promote 'nonstandard extension used : class rvalue used as lvalue' to error.
|
||||
)
|
||||
# Promoted warnings to errors.
|
||||
-we4238 # Promote 'nonstandard extension used : class rvalue used as lvalue' to error.
|
||||
)
|
||||
endif(NOT CLANG_CL)
|
||||
|
||||
# Enable warnings
|
||||
if (LLVM_ENABLE_WARNINGS)
|
||||
@ -516,10 +540,17 @@ if (MSVC AND NOT CLANG_CL)
|
||||
foreach(flag ${msvc_warning_flags})
|
||||
append("${flag}" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
endforeach(flag)
|
||||
endif (MSVC AND NOT CLANG_CL)
|
||||
endif (MSVC)
|
||||
|
||||
if (LLVM_ENABLE_WARNINGS AND (LLVM_COMPILER_IS_GCC_COMPATIBLE OR CLANG_CL))
|
||||
append("-Wall -W -Wno-unused-parameter -Wwrite-strings" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
|
||||
# Don't add -Wall for clang-cl, because it maps -Wall to -Weverything for
|
||||
# MSVC compatibility. /W4 is added above instead.
|
||||
if (NOT CLANG_CL)
|
||||
append("-Wall" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
endif()
|
||||
|
||||
append("-W -Wno-unused-parameter -Wwrite-strings" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
append("-Wcast-qual" CMAKE_CXX_FLAGS)
|
||||
|
||||
# Turn off missing field initializer warnings for gcc to avoid noise from
|
||||
@ -663,7 +694,7 @@ if(LLVM_USE_SANITIZER)
|
||||
FSANITIZE_USE_AFTER_SCOPE_FLAG)
|
||||
endif()
|
||||
if (LLVM_USE_SANITIZE_COVERAGE)
|
||||
append("-fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
append("-fsanitize=fuzzer-no-link" CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -724,15 +755,30 @@ if(LLVM_ENABLE_EH AND NOT LLVM_ENABLE_RTTI)
|
||||
message(FATAL_ERROR "Exception handling requires RTTI. You must set LLVM_ENABLE_RTTI to ON")
|
||||
endif()
|
||||
|
||||
option(LLVM_BUILD_INSTRUMENTED "Build LLVM and tools with PGO instrumentation (experimental)" Off)
|
||||
mark_as_advanced(LLVM_BUILD_INSTRUMENTED)
|
||||
append_if(LLVM_BUILD_INSTRUMENTED "-fprofile-instr-generate='${LLVM_PROFILE_FILE_PATTERN}'"
|
||||
CMAKE_CXX_FLAGS
|
||||
CMAKE_C_FLAGS
|
||||
CMAKE_EXE_LINKER_FLAGS
|
||||
CMAKE_SHARED_LINKER_FLAGS)
|
||||
option(LLVM_ENABLE_IR_PGO "Build LLVM and tools with IR PGO instrumentation (deprecated)" Off)
|
||||
mark_as_advanced(LLVM_ENABLE_IR_PGO)
|
||||
|
||||
option(LLVM_BUILD_INSTRUMENTED_COVERAGE "Build LLVM and tools with Code Coverage instrumentation (experimental)" Off)
|
||||
set(LLVM_BUILD_INSTRUMENTED OFF CACHE STRING "Build LLVM and tools with PGO instrumentation. May be specified as IR or Frontend")
|
||||
mark_as_advanced(LLVM_BUILD_INSTRUMENTED)
|
||||
string(TOUPPER "${LLVM_BUILD_INSTRUMENTED}" uppercase_LLVM_BUILD_INSTRUMENTED)
|
||||
|
||||
if (LLVM_BUILD_INSTRUMENTED)
|
||||
if (LLVM_ENABLE_IR_PGO OR uppercase_LLVM_BUILD_INSTRUMENTED STREQUAL "IR")
|
||||
append("-fprofile-generate='${LLVM_PROFILE_DATA_DIR}'"
|
||||
CMAKE_CXX_FLAGS
|
||||
CMAKE_C_FLAGS
|
||||
CMAKE_EXE_LINKER_FLAGS
|
||||
CMAKE_SHARED_LINKER_FLAGS)
|
||||
else()
|
||||
append("-fprofile-instr-generate='${LLVM_PROFILE_FILE_PATTERN}'"
|
||||
CMAKE_CXX_FLAGS
|
||||
CMAKE_C_FLAGS
|
||||
CMAKE_EXE_LINKER_FLAGS
|
||||
CMAKE_SHARED_LINKER_FLAGS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(LLVM_BUILD_INSTRUMENTED_COVERAGE "Build LLVM and tools with Code Coverage instrumentation" Off)
|
||||
mark_as_advanced(LLVM_BUILD_INSTRUMENTED_COVERAGE)
|
||||
append_if(LLVM_BUILD_INSTRUMENTED_COVERAGE "-fprofile-instr-generate='${LLVM_PROFILE_FILE_PATTERN}' -fcoverage-mapping"
|
||||
CMAKE_CXX_FLAGS
|
||||
@ -740,6 +786,10 @@ append_if(LLVM_BUILD_INSTRUMENTED_COVERAGE "-fprofile-instr-generate='${LLVM_PRO
|
||||
CMAKE_EXE_LINKER_FLAGS
|
||||
CMAKE_SHARED_LINKER_FLAGS)
|
||||
|
||||
if (LLVM_BUILD_INSTRUMENTED AND LLVM_BUILD_INSTRUMENTED_COVERAGE)
|
||||
message(FATAL_ERROR "LLVM_BUILD_INSTRUMENTED and LLVM_BUILD_INSTRUMENTED_COVERAGE cannot both be specified")
|
||||
endif()
|
||||
|
||||
if(LLVM_ENABLE_LTO AND LLVM_ON_WIN32 AND NOT LINKER_IS_LLD_LINK)
|
||||
message(FATAL_ERROR "When compiling for Windows, LLVM_ENABLE_LTO requires using lld as the linker (point CMAKE_LINKER at lld-link.exe)")
|
||||
endif()
|
||||
@ -790,7 +840,7 @@ endif()
|
||||
# Plugin support
|
||||
# FIXME: Make this configurable.
|
||||
if(WIN32 OR CYGWIN)
|
||||
if(BUILD_SHARED_LIBS)
|
||||
if(BUILD_SHARED_LIBS OR LLVM_BUILD_LLVM_DYLIB)
|
||||
set(LLVM_ENABLE_PLUGINS ON)
|
||||
else()
|
||||
set(LLVM_ENABLE_PLUGINS OFF)
|
||||
|
@ -87,7 +87,7 @@ macro(llvm_config executable)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_link_libraries(${executable} LLVM)
|
||||
target_link_libraries(${executable} PRIVATE LLVM)
|
||||
endif()
|
||||
|
||||
explicit_llvm_config(${executable} ${link_components})
|
||||
@ -99,9 +99,9 @@ function(explicit_llvm_config executable)
|
||||
|
||||
llvm_map_components_to_libnames(LIBRARIES ${link_components})
|
||||
get_target_property(t ${executable} TYPE)
|
||||
if("x${t}" STREQUAL "xSTATIC_LIBRARY")
|
||||
if(t STREQUAL "STATIC_LIBRARY")
|
||||
target_link_libraries(${executable} INTERFACE ${LIBRARIES})
|
||||
elseif("x${t}" STREQUAL "xSHARED_LIBRARY" OR "x${t}" STREQUAL "xMODULE_LIBRARY")
|
||||
elseif(t STREQUAL "EXECUTABLE" OR t STREQUAL "SHARED_LIBRARY" OR t STREQUAL "MODULE_LIBRARY")
|
||||
target_link_libraries(${executable} PRIVATE ${LIBRARIES})
|
||||
else()
|
||||
# Use plain form for legacy user.
|
||||
@ -175,18 +175,15 @@ function(llvm_map_components_to_libnames out_libs)
|
||||
message(FATAL_ERROR "Target ${c} is not in the set of libraries.")
|
||||
endif()
|
||||
endif()
|
||||
if( TARGET LLVM${c}AsmPrinter )
|
||||
list(APPEND expanded_components "LLVM${c}AsmPrinter")
|
||||
endif()
|
||||
if( TARGET LLVM${c}AsmParser )
|
||||
list(APPEND expanded_components "LLVM${c}AsmParser")
|
||||
endif()
|
||||
if( TARGET LLVM${c}AsmPrinter )
|
||||
list(APPEND expanded_components "LLVM${c}AsmPrinter")
|
||||
endif()
|
||||
if( TARGET LLVM${c}Desc )
|
||||
list(APPEND expanded_components "LLVM${c}Desc")
|
||||
endif()
|
||||
if( TARGET LLVM${c}Info )
|
||||
list(APPEND expanded_components "LLVM${c}Info")
|
||||
endif()
|
||||
if( TARGET LLVM${c}Disassembler )
|
||||
list(APPEND expanded_components "LLVM${c}Disassembler")
|
||||
endif()
|
||||
|
@ -72,6 +72,7 @@ set(LLVM_CMAKE_DIR "@LLVM_CONFIG_CMAKE_DIR@")
|
||||
set(LLVM_BINARY_DIR "@LLVM_CONFIG_BINARY_DIR@")
|
||||
set(LLVM_TOOLS_BINARY_DIR "@LLVM_CONFIG_TOOLS_BINARY_DIR@")
|
||||
set(LLVM_TOOLS_INSTALL_DIR "@LLVM_TOOLS_INSTALL_DIR@")
|
||||
set(LLVM_HAVE_OPT_VIEWER_MODULES @LLVM_HAVE_OPT_VIEWER_MODULES@)
|
||||
|
||||
if(NOT TARGET LLVMSupport)
|
||||
set(LLVM_EXPORTED_TARGETS "@LLVM_CONFIG_EXPORTS@")
|
||||
@ -79,5 +80,12 @@ if(NOT TARGET LLVMSupport)
|
||||
@llvm_config_include_buildtree_only_exports@
|
||||
endif()
|
||||
|
||||
# By creating intrinsics_gen here, subprojects that depend on LLVM's
|
||||
# tablegen-generated headers can always depend on this target whether building
|
||||
# in-tree with LLVM or not.
|
||||
if(NOT TARGET intrinsics_gen)
|
||||
add_custom_target(intrinsics_gen)
|
||||
endif()
|
||||
|
||||
set_property(GLOBAL PROPERTY LLVM_TARGETS_CONFIGURED On)
|
||||
include(${LLVM_CMAKE_DIR}/LLVM-Config.cmake)
|
||||
|
@ -95,7 +95,7 @@ function(llvm_ExternalProject_Add name source_dir)
|
||||
foreach(prefix ${ARG_PASSTHROUGH_PREFIXES})
|
||||
foreach(variableName ${variableNames})
|
||||
if(variableName MATCHES "^${prefix}")
|
||||
string(REPLACE ";" "\;" value "${${variableName}}")
|
||||
string(REPLACE ";" "|" value "${${variableName}}")
|
||||
list(APPEND PASSTHROUGH_VARIABLES
|
||||
-D${variableName}=${value})
|
||||
endif()
|
||||
@ -132,6 +132,10 @@ function(llvm_ExternalProject_Add name source_dir)
|
||||
set(exclude EXCLUDE_FROM_ALL 1)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSROOT)
|
||||
set(sysroot_arg -DCMAKE_SYSROOT=${CMAKE_SYSROOT})
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(${name}
|
||||
DEPENDS ${ARG_DEPENDS} llvm-config
|
||||
${name}-clobber
|
||||
@ -143,12 +147,16 @@ function(llvm_ExternalProject_Add name source_dir)
|
||||
CMAKE_ARGS ${${nameCanon}_CMAKE_ARGS}
|
||||
${compiler_args}
|
||||
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
|
||||
${sysroot_arg}
|
||||
-DLLVM_BINARY_DIR=${PROJECT_BINARY_DIR}
|
||||
-DLLVM_CONFIG_PATH=$<TARGET_FILE:llvm-config>
|
||||
-DLLVM_ENABLE_WERROR=${LLVM_ENABLE_WERROR}
|
||||
-DLLVM_HOST_TRIPLE=${LLVM_HOST_TRIPLE}
|
||||
-DLLVM_HAVE_LINK_VERSION_SCRIPT=${LLVM_HAVE_LINK_VERSION_SCRIPT}
|
||||
-DPACKAGE_VERSION=${PACKAGE_VERSION}
|
||||
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
|
||||
-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}
|
||||
-DCMAKE_EXPORT_COMPILE_COMMANDS=1
|
||||
${ARG_CMAKE_ARGS}
|
||||
${PASSTHROUGH_VARIABLES}
|
||||
INSTALL_COMMAND ""
|
||||
@ -157,6 +165,7 @@ function(llvm_ExternalProject_Add name source_dir)
|
||||
USES_TERMINAL_CONFIGURE 1
|
||||
USES_TERMINAL_BUILD 1
|
||||
USES_TERMINAL_INSTALL 1
|
||||
LIST_SEPARATOR |
|
||||
)
|
||||
|
||||
if(ARG_USE_TOOLCHAIN)
|
||||
@ -185,12 +194,9 @@ function(llvm_ExternalProject_Add name source_dir)
|
||||
install(CODE "execute_process\(COMMAND \${CMAKE_COMMAND} -DCMAKE_INSTALL_PREFIX=\${CMAKE_INSTALL_PREFIX} -P ${BINARY_DIR}/cmake_install.cmake \)"
|
||||
COMPONENT ${name})
|
||||
|
||||
add_custom_target(install-${name}
|
||||
DEPENDS ${name}
|
||||
COMMAND "${CMAKE_COMMAND}"
|
||||
-DCMAKE_INSTALL_COMPONENT=${name}
|
||||
-P "${CMAKE_BINARY_DIR}/cmake_install.cmake"
|
||||
USES_TERMINAL)
|
||||
add_llvm_install_targets(install-${name}
|
||||
DEPENDS ${name}
|
||||
COMPONENT ${name})
|
||||
endif()
|
||||
|
||||
# Add top-level targets
|
||||
|
@ -68,17 +68,29 @@ endfunction(llvm_process_sources)
|
||||
|
||||
|
||||
function(llvm_check_source_file_list)
|
||||
set(listed ${ARGN})
|
||||
file(GLOB globbed *.c *.cpp)
|
||||
cmake_parse_arguments(ARG "" "SOURCE_DIR" "" ${ARGN})
|
||||
set(listed ${ARG_UNPARSED_ARGUMENTS})
|
||||
if(ARG_SOURCE_DIR)
|
||||
file(GLOB globbed
|
||||
RELATIVE "${CMAKE_CURRENT_LIST_DIR}"
|
||||
"${ARG_SOURCE_DIR}/*.c" "${ARG_SOURCE_DIR}/*.cpp")
|
||||
else()
|
||||
file(GLOB globbed *.c *.cpp)
|
||||
endif()
|
||||
foreach(g ${globbed})
|
||||
get_filename_component(fn ${g} NAME)
|
||||
if(ARG_SOURCE_DIR)
|
||||
set(entry "${g}")
|
||||
else()
|
||||
set(entry "${fn}")
|
||||
endif()
|
||||
|
||||
# Don't reject hidden files. Some editors create backups in the
|
||||
# same directory as the file.
|
||||
if (NOT "${fn}" MATCHES "^\\.")
|
||||
list(FIND LLVM_OPTIONAL_SOURCES ${fn} idx)
|
||||
list(FIND LLVM_OPTIONAL_SOURCES ${entry} idx)
|
||||
if( idx LESS 0 )
|
||||
list(FIND listed ${fn} idx)
|
||||
list(FIND listed ${entry} idx)
|
||||
if( idx LESS 0 )
|
||||
message(SEND_ERROR "Found unknown source file ${g}
|
||||
Please update ${CMAKE_CURRENT_LIST_FILE}\n")
|
||||
|
@ -52,6 +52,13 @@ function(tablegen project ofn)
|
||||
list(APPEND LLVM_TABLEGEN_FLAGS "-instrument-coverage")
|
||||
endif()
|
||||
endif()
|
||||
if (LLVM_ENABLE_GISEL_COV)
|
||||
list(FIND ARGN "-gen-global-isel" idx)
|
||||
if( NOT idx EQUAL -1 )
|
||||
list(APPEND LLVM_TABLEGEN_FLAGS "-instrument-gisel-coverage")
|
||||
list(APPEND LLVM_TABLEGEN_FLAGS "-gisel-coverage-file=${LLVM_GISEL_COV_PREFIX}all")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# We need both _TABLEGEN_TARGET and _TABLEGEN_EXE in the DEPENDS list
|
||||
# (both the target and the file) to have .inc files rebuilt on
|
||||
@ -110,19 +117,6 @@ function(add_public_tablegen_target target)
|
||||
set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} ${target} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
if(LLVM_USE_HOST_TOOLS)
|
||||
llvm_ExternalProject_BuildCmd(tblgen_build_cmd LLVMSupport
|
||||
${LLVM_NATIVE_BUILD}
|
||||
CONFIGURATION Release)
|
||||
add_custom_command(OUTPUT LIB_LLVMTABLEGEN
|
||||
COMMAND ${tblgen_build_cmd}
|
||||
DEPENDS CONFIGURE_LLVM_NATIVE
|
||||
WORKING_DIRECTORY ${LLVM_NATIVE_BUILD}
|
||||
COMMENT "Building libLLVMTableGen for native TableGen..."
|
||||
USES_TERMINAL)
|
||||
add_custom_target(NATIVE_LIB_LLVMTABLEGEN DEPENDS LIB_LLVMTABLEGEN)
|
||||
endif(LLVM_USE_HOST_TOOLS)
|
||||
|
||||
macro(add_tablegen target project)
|
||||
set(${target}_OLD_LLVM_LINK_COMPONENTS ${LLVM_LINK_COMPONENTS})
|
||||
set(LLVM_LINK_COMPONENTS ${LLVM_LINK_COMPONENTS} TableGen)
|
||||
@ -166,7 +160,7 @@ macro(add_tablegen target project)
|
||||
CONFIGURATION Release)
|
||||
add_custom_command(OUTPUT ${${project}_TABLEGEN_EXE}
|
||||
COMMAND ${tblgen_build_cmd}
|
||||
DEPENDS ${target} NATIVE_LIB_LLVMTABLEGEN
|
||||
DEPENDS CONFIGURE_LLVM_NATIVE ${target}
|
||||
WORKING_DIRECTORY ${LLVM_NATIVE_BUILD}
|
||||
COMMENT "Building native TableGen..."
|
||||
USES_TERMINAL)
|
||||
|
9
cmake/platforms/ClangClCMakeCompileRules.cmake
Normal file
9
cmake/platforms/ClangClCMakeCompileRules.cmake
Normal file
@ -0,0 +1,9 @@
|
||||
# macOS paths usually start with /Users/*. Unfortunately, clang-cl interprets
|
||||
# paths starting with /U as macro undefines, so we need to put a -- before the
|
||||
# input file path to force it to be treated as a path. CMake's compilation rules
|
||||
# should be tweaked accordingly, but until that's done, and to support older
|
||||
# CMake versions, overriding compilation rules works well enough. This file will
|
||||
# be included by cmake after the default compilation rules have already been set
|
||||
# up, so we can just modify them instead of duplicating them entirely.
|
||||
string(REPLACE "-c <SOURCE>" "-c -- <SOURCE>" CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT}")
|
||||
string(REPLACE "-c <SOURCE>" "-c -- <SOURCE>" CMAKE_CXX_COMPILE_OBJECT "${CMAKE_CXX_COMPILE_OBJECT}")
|
304
cmake/platforms/WinMsvc.cmake
Normal file
304
cmake/platforms/WinMsvc.cmake
Normal file
@ -0,0 +1,304 @@
|
||||
# Cross toolchain configuration for using clang-cl on non-Windows hosts to
|
||||
# target MSVC.
|
||||
#
|
||||
# Usage:
|
||||
# cmake -G Ninja
|
||||
# -DCMAKE_TOOLCHAIN_FILE=/path/to/this/file
|
||||
# -DHOST_ARCH=[aarch64|arm64|armv7|arm|i686|x86|x86_64|x64]
|
||||
# -DLLVM_NATIVE_TOOLCHAIN=/path/to/llvm/installation
|
||||
# -DMSVC_BASE=/path/to/MSVC/system/libraries/and/includes
|
||||
# -DWINSDK_BASE=/path/to/windows-sdk
|
||||
# -DWINSDK_VER=windows sdk version folder name
|
||||
#
|
||||
# HOST_ARCH:
|
||||
# The architecture to build for.
|
||||
#
|
||||
# LLVM_NATIVE_TOOLCHAIN:
|
||||
# *Absolute path* to a folder containing the toolchain which will be used to
|
||||
# build. At a minimum, this folder should have a bin directory with a
|
||||
# copy of clang-cl, clang, clang++, and lld-link, as well as a lib directory
|
||||
# containing clang's system resource directory.
|
||||
#
|
||||
# MSVC_BASE:
|
||||
# *Absolute path* to the folder containing MSVC headers and system libraries.
|
||||
# The layout of the folder matches that which is intalled by MSVC 2017 on
|
||||
# Windows, and should look like this:
|
||||
#
|
||||
# ${MSVC_BASE}
|
||||
# include
|
||||
# vector
|
||||
# stdint.h
|
||||
# etc...
|
||||
# lib
|
||||
# x64
|
||||
# libcmt.lib
|
||||
# msvcrt.lib
|
||||
# etc...
|
||||
# x86
|
||||
# libcmt.lib
|
||||
# msvcrt.lib
|
||||
# etc...
|
||||
#
|
||||
# For versions of MSVC < 2017, or where you have a hermetic toolchain in a
|
||||
# custom format, you must use symlinks or restructure it to look like the above.
|
||||
#
|
||||
# WINSDK_BASE:
|
||||
# Together with WINSDK_VER, determines the location of Windows SDK headers
|
||||
# and libraries.
|
||||
#
|
||||
# WINSDK_VER:
|
||||
# Together with WINSDK_BASE, determines the locations of Windows SDK headers
|
||||
# and libraries.
|
||||
#
|
||||
# WINSDK_BASE and WINSDK_VER work together to define a folder layout that matches
|
||||
# that of the Windows SDK installation on a standard Windows machine. It should
|
||||
# match the layout described below.
|
||||
#
|
||||
# Note that if you install Windows SDK to a windows machine and simply copy the
|
||||
# files, it will already be in the correct layout.
|
||||
#
|
||||
# ${WINSDK_BASE}
|
||||
# Include
|
||||
# ${WINSDK_VER}
|
||||
# shared
|
||||
# ucrt
|
||||
# um
|
||||
# windows.h
|
||||
# etc...
|
||||
# Lib
|
||||
# ${WINSDK_VER}
|
||||
# ucrt
|
||||
# x64
|
||||
# x86
|
||||
# ucrt.lib
|
||||
# etc...
|
||||
# um
|
||||
# x64
|
||||
# x86
|
||||
# kernel32.lib
|
||||
# etc
|
||||
#
|
||||
# IMPORTANT: In order for this to work, you will need a valid copy of the Windows
|
||||
# SDK and C++ STL headers and libraries on your host. Additionally, since the
|
||||
# Windows libraries and headers are not case-correct, this toolchain file sets
|
||||
# up a VFS overlay for the SDK headers and case-correcting symlinks for the
|
||||
# libraries when running on a case-sensitive filesystem.
|
||||
|
||||
|
||||
# When configuring CMake with a toolchain file against a top-level CMakeLists.txt,
|
||||
# it will actually run CMake many times, once for each small test program used to
|
||||
# determine what features a compiler supports. Unfortunately, none of these
|
||||
# invocations share a CMakeCache.txt with the top-level invocation, meaning they
|
||||
# won't see the value of any arguments the user passed via -D. Since these are
|
||||
# necessary to properly configure MSVC in both the top-level configuration as well as
|
||||
# all feature-test invocations, we set environment variables with the values so that
|
||||
# these environments get inherited by child invocations.
|
||||
function(init_user_prop prop)
|
||||
if(${prop})
|
||||
set(ENV{_${prop}} "${${prop}}")
|
||||
else()
|
||||
set(${prop} "$ENV{_${prop}}" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(generate_winsdk_vfs_overlay winsdk_include_dir output_path)
|
||||
set(include_dirs)
|
||||
file(GLOB_RECURSE entries LIST_DIRECTORIES true "${winsdk_include_dir}/*")
|
||||
foreach(entry ${entries})
|
||||
if(IS_DIRECTORY "${entry}")
|
||||
list(APPEND include_dirs "${entry}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
file(WRITE "${output_path}" "version: 0\n")
|
||||
file(APPEND "${output_path}" "case-sensitive: false\n")
|
||||
file(APPEND "${output_path}" "roots:\n")
|
||||
|
||||
foreach(dir ${include_dirs})
|
||||
file(GLOB headers RELATIVE "${dir}" "${dir}/*.h")
|
||||
if(NOT headers)
|
||||
continue()
|
||||
endif()
|
||||
|
||||
file(APPEND "${output_path}" " - name: \"${dir}\"\n")
|
||||
file(APPEND "${output_path}" " type: directory\n")
|
||||
file(APPEND "${output_path}" " contents:\n")
|
||||
|
||||
foreach(header ${headers})
|
||||
file(APPEND "${output_path}" " - name: \"${header}\"\n")
|
||||
file(APPEND "${output_path}" " type: file\n")
|
||||
file(APPEND "${output_path}" " external-contents: \"${dir}/${header}\"\n")
|
||||
endforeach()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(generate_winsdk_lib_symlinks winsdk_um_lib_dir output_dir)
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}" -E make_directory "${output_dir}")
|
||||
file(GLOB libraries RELATIVE "${winsdk_um_lib_dir}" "${winsdk_um_lib_dir}/*")
|
||||
foreach(library ${libraries})
|
||||
string(TOLOWER "${library}" symlink_name)
|
||||
execute_process(COMMAND "${CMAKE_COMMAND}"
|
||||
-E create_symlink
|
||||
"${winsdk_um_lib_dir}/${library}"
|
||||
"${output_dir}/${symlink_name}")
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
set(CMAKE_SYSTEM_NAME Windows)
|
||||
set(CMAKE_SYSTEM_VERSION 10.0)
|
||||
set(CMAKE_SYSTEM_PROCESSOR AMD64)
|
||||
|
||||
init_user_prop(HOST_ARCH)
|
||||
init_user_prop(LLVM_NATIVE_TOOLCHAIN)
|
||||
init_user_prop(MSVC_BASE)
|
||||
init_user_prop(WINSDK_BASE)
|
||||
init_user_prop(WINSDK_VER)
|
||||
|
||||
if(NOT HOST_ARCH)
|
||||
set(HOST_ARCH x86_64)
|
||||
endif()
|
||||
if(HOST_ARCH STREQUAL "aarch64" OR HOST_ARCH STREQUAL "arm64")
|
||||
set(TRIPLE_ARCH "aarch64")
|
||||
set(WINSDK_ARCH "arm64")
|
||||
elseif(HOST_ARCH STREQUAL "armv7" OR HOST_ARCH STREQUAL "arm")
|
||||
set(TRIPLE_ARCH "armv7")
|
||||
set(WINSDK_ARCH "arm")
|
||||
elseif(HOST_ARCH STREQUAL "i686" OR HOST_ARCH STREQUAL "x86")
|
||||
set(TRIPLE_ARCH "i686")
|
||||
set(WINSDK_ARCH "x86")
|
||||
elseif(HOST_ARCH STREQUAL "x86_64" OR HOST_ARCH STREQUAL "x64")
|
||||
set(TRIPLE_ARCH "x86_64")
|
||||
set(WINSDK_ARCH "x64")
|
||||
else()
|
||||
message(SEND_ERROR "Unknown host architecture ${HOST_ARCH}. Must be aarch64 (or arm64), armv7 (or arm), i686 (or x86), or x86_64 (or x64).")
|
||||
endif()
|
||||
|
||||
set(MSVC_INCLUDE "${MSVC_BASE}/include")
|
||||
set(MSVC_LIB "${MSVC_BASE}/lib")
|
||||
set(WINSDK_INCLUDE "${WINSDK_BASE}/Include/${WINSDK_VER}")
|
||||
set(WINSDK_LIB "${WINSDK_BASE}/Lib/${WINSDK_VER}")
|
||||
|
||||
# Do some sanity checking to make sure we can find a native toolchain and
|
||||
# that the Windows SDK / MSVC STL directories look kosher.
|
||||
if(NOT EXISTS "${LLVM_NATIVE_TOOLCHAIN}/bin/clang-cl" OR
|
||||
NOT EXISTS "${LLVM_NATIVE_TOOLCHAIN}/bin/lld-link")
|
||||
message(SEND_ERROR
|
||||
"LLVM_NATIVE_TOOLCHAIN folder '${LLVM_NATIVE_TOOLCHAIN}' does not "
|
||||
"point to a valid directory containing bin/clang-cl and bin/lld-link "
|
||||
"binaries")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${MSVC_BASE}" OR
|
||||
NOT EXISTS "${MSVC_INCLUDE}" OR
|
||||
NOT EXISTS "${MSVC_LIB}")
|
||||
message(SEND_ERROR
|
||||
"CMake variable MSVC_BASE must point to a folder containing MSVC "
|
||||
"system headers and libraries")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${WINSDK_BASE}" OR
|
||||
NOT EXISTS "${WINSDK_INCLUDE}" OR
|
||||
NOT EXISTS "${WINSDK_LIB}")
|
||||
message(SEND_ERROR
|
||||
"CMake variable WINSDK_BASE and WINSDK_VER must resolve to a valid "
|
||||
"Windows SDK installation")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${WINSDK_INCLUDE}/um/Windows.h")
|
||||
message(SEND_ERROR "Cannot find Windows.h")
|
||||
endif()
|
||||
if(NOT EXISTS "${WINSDK_INCLUDE}/um/WINDOWS.H")
|
||||
set(case_sensitive_filesystem TRUE)
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_COMPILER "${LLVM_NATIVE_TOOLCHAIN}/bin/clang-cl" CACHE FILEPATH "")
|
||||
set(CMAKE_CXX_COMPILER "${LLVM_NATIVE_TOOLCHAIN}/bin/clang-cl" CACHE FILEPATH "")
|
||||
set(CMAKE_LINKER "${LLVM_NATIVE_TOOLCHAIN}/bin/lld-link" CACHE FILEPATH "")
|
||||
|
||||
# Even though we're cross-compiling, we need some native tools (e.g. llvm-tblgen), and those
|
||||
# native tools have to be built before we can start doing the cross-build. LLVM supports
|
||||
# a CROSS_TOOLCHAIN_FLAGS_NATIVE argument which consists of a list of flags to pass to CMake
|
||||
# when configuring the NATIVE portion of the cross-build. By default we construct this so
|
||||
# that it points to the tools in the same location as the native clang-cl that we're using.
|
||||
list(APPEND _CTF_NATIVE_DEFAULT "-DCMAKE_ASM_COMPILER=${LLVM_NATIVE_TOOLCHAIN}/bin/clang")
|
||||
list(APPEND _CTF_NATIVE_DEFAULT "-DCMAKE_C_COMPILER=${LLVM_NATIVE_TOOLCHAIN}/bin/clang")
|
||||
list(APPEND _CTF_NATIVE_DEFAULT "-DCMAKE_CXX_COMPILER=${LLVM_NATIVE_TOOLCHAIN}/bin/clang++")
|
||||
|
||||
set(CROSS_TOOLCHAIN_FLAGS_NATIVE "${_CTF_NATIVE_DEFAULT}" CACHE STRING "")
|
||||
|
||||
set(COMPILE_FLAGS
|
||||
-D_CRT_SECURE_NO_WARNINGS
|
||||
--target=${TRIPLE_ARCH}-windows-msvc
|
||||
-fms-compatibility-version=19.11
|
||||
-imsvc "${MSVC_INCLUDE}"
|
||||
-imsvc "${WINSDK_INCLUDE}/ucrt"
|
||||
-imsvc "${WINSDK_INCLUDE}/shared"
|
||||
-imsvc "${WINSDK_INCLUDE}/um"
|
||||
-imsvc "${WINSDK_INCLUDE}/winrt")
|
||||
|
||||
if(case_sensitive_filesystem)
|
||||
# Ensure all sub-configures use the top-level VFS overlay instead of generating their own.
|
||||
init_user_prop(winsdk_vfs_overlay_path)
|
||||
if(NOT winsdk_vfs_overlay_path)
|
||||
set(winsdk_vfs_overlay_path "${CMAKE_BINARY_DIR}/winsdk_vfs_overlay.yaml")
|
||||
generate_winsdk_vfs_overlay("${WINSDK_BASE}/Include/${WINSDK_VER}" "${winsdk_vfs_overlay_path}")
|
||||
init_user_prop(winsdk_vfs_overlay_path)
|
||||
endif()
|
||||
list(APPEND COMPILE_FLAGS
|
||||
-Xclang -ivfsoverlay -Xclang "${winsdk_vfs_overlay_path}")
|
||||
endif()
|
||||
|
||||
string(REPLACE ";" " " COMPILE_FLAGS "${COMPILE_FLAGS}")
|
||||
|
||||
# We need to preserve any flags that were passed in by the user. However, we
|
||||
# can't append to CMAKE_C_FLAGS and friends directly, because toolchain files
|
||||
# will be re-invoked on each reconfigure and therefore need to be idempotent.
|
||||
# The assignments to the _INITIAL cache variables don't use FORCE, so they'll
|
||||
# only be populated on the initial configure, and their values won't change
|
||||
# afterward.
|
||||
set(_CMAKE_C_FLAGS_INITIAL "${CMAKE_C_FLAGS}" CACHE STRING "")
|
||||
set(CMAKE_C_FLAGS "${_CMAKE_C_FLAGS_INITIAL} ${COMPILE_FLAGS}" CACHE STRING "" FORCE)
|
||||
|
||||
set(_CMAKE_CXX_FLAGS_INITIAL "${CMAKE_CXX_FLAGS}" CACHE STRING "")
|
||||
set(CMAKE_CXX_FLAGS "${_CMAKE_CXX_FLAGS_INITIAL} ${COMPILE_FLAGS}" CACHE STRING "" FORCE)
|
||||
|
||||
set(LINK_FLAGS
|
||||
# Prevent CMake from attempting to invoke mt.exe. It only recognizes the slashed form and not the dashed form.
|
||||
/manifest:no
|
||||
|
||||
-libpath:"${MSVC_LIB}/${WINSDK_ARCH}"
|
||||
-libpath:"${WINSDK_LIB}/ucrt/${WINSDK_ARCH}"
|
||||
-libpath:"${WINSDK_LIB}/um/${WINSDK_ARCH}")
|
||||
|
||||
if(case_sensitive_filesystem)
|
||||
# Ensure all sub-configures use the top-level symlinks dir instead of generating their own.
|
||||
init_user_prop(winsdk_lib_symlinks_dir)
|
||||
if(NOT winsdk_lib_symlinks_dir)
|
||||
set(winsdk_lib_symlinks_dir "${CMAKE_BINARY_DIR}/winsdk_lib_symlinks")
|
||||
generate_winsdk_lib_symlinks("${WINSDK_BASE}/Lib/${WINSDK_VER}/um/${WINSDK_ARCH}" "${winsdk_lib_symlinks_dir}")
|
||||
init_user_prop(winsdk_lib_symlinks_dir)
|
||||
endif()
|
||||
list(APPEND LINK_FLAGS
|
||||
-libpath:"${winsdk_lib_symlinks_dir}")
|
||||
endif()
|
||||
|
||||
string(REPLACE ";" " " LINK_FLAGS "${LINK_FLAGS}")
|
||||
|
||||
# See explanation for compiler flags above for the _INITIAL variables.
|
||||
set(_CMAKE_EXE_LINKER_FLAGS_INITIAL "${CMAKE_EXE_LINKER_FLAGS}" CACHE STRING "")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${_CMAKE_EXE_LINKER_FLAGS_INITIAL} ${LINK_FLAGS}" CACHE STRING "" FORCE)
|
||||
|
||||
set(_CMAKE_MODULE_LINKER_FLAGS_INITIAL "${CMAKE_MODULE_LINKER_FLAGS}" CACHE STRING "")
|
||||
set(CMAKE_MODULE_LINKER_FLAGS "${_CMAKE_MODULE_LINKER_FLAGS_INITIAL} ${LINK_FLAGS}" CACHE STRING "" FORCE)
|
||||
|
||||
set(_CMAKE_SHARED_LINKER_FLAGS_INITIAL "${CMAKE_SHARED_LINKER_FLAGS}" CACHE STRING "")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${_CMAKE_SHARED_LINKER_FLAGS_INITIAL} ${LINK_FLAGS}" CACHE STRING "" FORCE)
|
||||
|
||||
# CMake populates these with a bunch of unnecessary libraries, which requires
|
||||
# extra case-correcting symlinks and what not. Instead, let projects explicitly
|
||||
# control which libraries they require.
|
||||
set(CMAKE_C_STANDARD_LIBRARIES "" CACHE STRING "" FORCE)
|
||||
set(CMAKE_CXX_STANDARD_LIBRARIES "" CACHE STRING "" FORCE)
|
||||
|
||||
# Allow clang-cl to work with macOS paths.
|
||||
set(CMAKE_USER_MAKE_RULES_OVERRIDE "${CMAKE_CURRENT_LIST_DIR}/ClangClCMakeCompileRules.cmake")
|
2002
docs/AMDGPUUsage.rst
2002
docs/AMDGPUUsage.rst
File diff suppressed because it is too large
Load Diff
@ -681,7 +681,7 @@ for each library name referenced.
|
||||
MODULE_CODE_GLOBALVAR Record
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
``[GLOBALVAR, strtab offset, strtab size, pointer type, isconst, initid, linkage, alignment, section, visibility, threadlocal, unnamed_addr, externally_initialized, dllstorageclass, comdat]``
|
||||
``[GLOBALVAR, strtab offset, strtab size, pointer type, isconst, initid, linkage, alignment, section, visibility, threadlocal, unnamed_addr, externally_initialized, dllstorageclass, comdat, attributes, preemptionspecifier]``
|
||||
|
||||
The ``GLOBALVAR`` record (code 7) marks the declaration or definition of a
|
||||
global variable. The operand fields are:
|
||||
@ -761,12 +761,21 @@ global variable. The operand fields are:
|
||||
|
||||
* *comdat*: An encoding of the COMDAT of this function
|
||||
|
||||
* *attributes*: If nonzero, the 1-based index into the table of AttributeLists.
|
||||
|
||||
.. _bcpreemptionspecifier:
|
||||
|
||||
* *preemptionspecifier*: If present, an encoding of the runtime preemption specifier of this variable:
|
||||
|
||||
* ``dso_preemptable``: code 0
|
||||
* ``dso_local``: code 1
|
||||
|
||||
.. _FUNCTION:
|
||||
|
||||
MODULE_CODE_FUNCTION Record
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
``[FUNCTION, strtab offset, strtab size, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prologuedata, dllstorageclass, comdat, prefixdata, personalityfn]``
|
||||
``[FUNCTION, strtab offset, strtab size, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prologuedata, dllstorageclass, comdat, prefixdata, personalityfn, preemptionspecifier]``
|
||||
|
||||
The ``FUNCTION`` record (code 8) marks the declaration or definition of a
|
||||
function. The operand fields are:
|
||||
@ -828,10 +837,12 @@ function. The operand fields are:
|
||||
* *personalityfn*: If non-zero, the value index of the personality function for this function,
|
||||
plus 1.
|
||||
|
||||
* *preemptionspecifier*: If present, an encoding of the :ref:`runtime preemption specifier<bcpreemptionspecifier>` of this function.
|
||||
|
||||
MODULE_CODE_ALIAS Record
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
``[ALIAS, strtab offset, strtab size, alias type, aliasee val#, linkage, visibility, dllstorageclass, threadlocal, unnamed_addr]``
|
||||
``[ALIAS, strtab offset, strtab size, alias type, aliasee val#, linkage, visibility, dllstorageclass, threadlocal, unnamed_addr, preemptionspecifier]``
|
||||
|
||||
The ``ALIAS`` record (code 9) marks the definition of an alias. The operand
|
||||
fields are
|
||||
@ -856,6 +867,8 @@ fields are
|
||||
* *unnamed_addr*: If present, an encoding of the
|
||||
:ref:`unnamed_addr<bcunnamedaddr>` attribute of this alias
|
||||
|
||||
* *preemptionspecifier*: If present, an encoding of the :ref:`runtime preemption specifier<bcpreemptionspecifier>` of this alias.
|
||||
|
||||
.. _MODULE_CODE_GCNAME:
|
||||
|
||||
MODULE_CODE_GCNAME Record
|
||||
@ -1039,6 +1052,9 @@ The integer codes are mapped to well-known attributes as follows.
|
||||
* code 50: ``inaccessiblememonly_or_argmemonly``
|
||||
* code 51: ``allocsize(<EltSizeParam>[, <NumEltsParam>])``
|
||||
* code 52: ``writeonly``
|
||||
* code 53: ``speculatable``
|
||||
* code 54: ``strictfp``
|
||||
* code 55: ``sanitize_hwaddress``
|
||||
|
||||
.. note::
|
||||
The ``allocsize`` attribute has a special encoding for its arguments. Its two
|
||||
|
@ -151,6 +151,11 @@ non-obvious ways. Here are some hints and tips:
|
||||
optimizations to be randomized and applied to the program. This process will
|
||||
repeat until a bug is found or the user kills ``bugpoint``.
|
||||
|
||||
* ``bugpoint`` can produce IR which contains long names. Run ``opt
|
||||
-metarenamer`` over the IR to rename everything using easy-to-read,
|
||||
metasyntactic names. Alternatively, run ``opt -strip -instnamer`` to rename
|
||||
everything with very short (often purely numeric) names.
|
||||
|
||||
What to do when bugpoint isn't enough
|
||||
=====================================
|
||||
|
||||
|
91
docs/CFIVerify.rst
Normal file
91
docs/CFIVerify.rst
Normal file
@ -0,0 +1,91 @@
|
||||
==============================================
|
||||
Control Flow Verification Tool Design Document
|
||||
==============================================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Objective
|
||||
=========
|
||||
|
||||
This document provides an overview of an external tool to verify the protection
|
||||
mechanisms implemented by Clang's *Control Flow Integrity* (CFI) schemes
|
||||
(``-fsanitize=cfi``). This tool, provided a binary or DSO, should infer whether
|
||||
indirect control flow operations are protected by CFI, and should output these
|
||||
results in a human-readable form.
|
||||
|
||||
This tool should also be added as part of Clang's continuous integration testing
|
||||
framework, where modifications to the compiler ensure that CFI protection
|
||||
schemes are still present in the final binary.
|
||||
|
||||
Location
|
||||
========
|
||||
|
||||
This tool will be present as a part of the LLVM toolchain, and will reside in
|
||||
the "/llvm/tools/llvm-cfi-verify" directory, relative to the LLVM trunk. It will
|
||||
be tested in two methods:
|
||||
|
||||
- Unit tests to validate code sections, present in "/llvm/unittests/llvm-cfi-
|
||||
verify".
|
||||
- Integration tests, present in "/llvm/tools/clang/test/LLVMCFIVerify". These
|
||||
integration tests are part of clang as part of a continuous integration
|
||||
framework, ensuring updates to the compiler that reduce CFI coverage on
|
||||
indirect control flow instructions are identified.
|
||||
|
||||
Background
|
||||
==========
|
||||
|
||||
This tool will continuously validate that CFI directives are properly
|
||||
implemented around all indirect control flows by analysing the output machine
|
||||
code. The analysis of machine code is important as it ensures that any bugs
|
||||
present in linker or compiler do not subvert CFI protections in the final
|
||||
shipped binary.
|
||||
|
||||
Unprotected indirect control flow instructions will be flagged for manual
|
||||
review. These unexpected control flows may simply have not been accounted for in
|
||||
the compiler implementation of CFI (e.g. indirect jumps to facilitate switch
|
||||
statements may not be fully protected).
|
||||
|
||||
It may be possible in the future to extend this tool to flag unnecessary CFI
|
||||
directives (e.g. CFI directives around a static call to a non-polymorphic base
|
||||
type). This type of directive has no security implications, but may present
|
||||
performance impacts.
|
||||
|
||||
Design Ideas
|
||||
============
|
||||
|
||||
This tool will disassemble binaries and DSO's from their machine code format and
|
||||
analyse the disassembled machine code. The tool will inspect virtual calls and
|
||||
indirect function calls. This tool will also inspect indirect jumps, as inlined
|
||||
functions and jump tables should also be subject to CFI protections. Non-virtual
|
||||
calls (``-fsanitize=cfi-nvcall``) and cast checks (``-fsanitize=cfi-*cast*``)
|
||||
are not implemented due to a lack of information provided by the bytecode.
|
||||
|
||||
The tool would operate by searching for indirect control flow instructions in
|
||||
the disassembly. A control flow graph would be generated from a small buffer of
|
||||
the instructions surrounding the 'target' control flow instruction. If the
|
||||
target instruction is branched-to, the fallthrough of the branch should be the
|
||||
CFI trap (on x86, this is a ``ud2`` instruction). If the target instruction is
|
||||
the fallthrough (i.e. immediately succeeds) of a conditional jump, the
|
||||
conditional jump target should be the CFI trap. If an indirect control flow
|
||||
instruction does not conform to one of these formats, the target will be noted
|
||||
as being CFI-unprotected.
|
||||
|
||||
Note that in the second case outlined above (where the target instruction is the
|
||||
fallthrough of a conditional jump), if the target represents a vcall that takes
|
||||
arguments, these arguments may be pushed to the stack after the branch but
|
||||
before the target instruction. In these cases, a secondary 'spill graph' in
|
||||
constructed, to ensure the register argument used by the indirect jump/call is
|
||||
not spilled from the stack at any point in the interim period. If there are no
|
||||
spills that affect the target register, the target is marked as CFI-protected.
|
||||
|
||||
Other Design Notes
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Only machine code sections that are marked as executable will be subject to this
|
||||
analysis. Non-executable sections do not require analysis as any execution
|
||||
present in these sections has already violated the control flow integrity.
|
||||
|
||||
Suitable extensions may be made at a later date to include anaylsis for indirect
|
||||
control flow operations across DSO boundaries. Currently, these CFI features are
|
||||
only experimental with an unstable ABI, making them unsuitable for analysis.
|
@ -224,6 +224,10 @@ LLVM-specific variables
|
||||
Generate build targets for the LLVM tools. Defaults to ON. You can use this
|
||||
option to disable the generation of build targets for the LLVM tools.
|
||||
|
||||
**LLVM_INSTALL_BINUTILS_SYMLINKS**:BOOL
|
||||
Install symlinks from the binutils tool names to the corresponding LLVM tools.
|
||||
For example, ar will be symlinked to llvm-ar.
|
||||
|
||||
**LLVM_BUILD_EXAMPLES**:BOOL
|
||||
Build LLVM examples. Defaults to OFF. Targets for building each example are
|
||||
generated in any case. See documentation for *LLVM_BUILD_TOOLS* above for more
|
||||
@ -542,6 +546,11 @@ LLVM-specific variables
|
||||
reverse order. This is useful for uncovering non-determinism caused by
|
||||
iteration of unordered containers.
|
||||
|
||||
**LLVM_BUILD_INSTRUMENTED_COVERAGE**:BOOL
|
||||
If enabled, `source-based code coverage
|
||||
<http://clang.llvm.org/docs/SourceBasedCodeCoverage.html>`_ instrumentation
|
||||
is enabled while building llvm.
|
||||
|
||||
CMake Caches
|
||||
============
|
||||
|
||||
|
@ -3,7 +3,7 @@ if (DOXYGEN_FOUND)
|
||||
if (LLVM_ENABLE_DOXYGEN)
|
||||
set(abs_top_srcdir ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(abs_top_builddir ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
|
||||
if (HAVE_DOT)
|
||||
set(DOT ${LLVM_PATH_DOT})
|
||||
endif()
|
||||
@ -21,20 +21,20 @@ if (LLVM_ENABLE_DOXYGEN)
|
||||
set(enable_external_search "NO")
|
||||
set(extra_search_mappings "")
|
||||
endif()
|
||||
|
||||
|
||||
# If asked, configure doxygen for the creation of a Qt Compressed Help file.
|
||||
option(LLVM_ENABLE_DOXYGEN_QT_HELP
|
||||
"Generate a Qt Compressed Help file." OFF)
|
||||
if (LLVM_ENABLE_DOXYGEN_QT_HELP)
|
||||
set(LLVM_DOXYGEN_QCH_FILENAME "org.llvm.qch" CACHE STRING
|
||||
"Filename of the Qt Compressed help file")
|
||||
set(LLVM_DOXYGEN_QHP_NAMESPACE "org.llvm" CACHE STRING
|
||||
set(LLVM_DOXYGEN_QHP_NAMESPACE "org.llvm" CACHE STRING
|
||||
"Namespace under which the intermediate Qt Help Project file lives")
|
||||
set(LLVM_DOXYGEN_QHP_CUST_FILTER_NAME "${PACKAGE_STRING}" CACHE STRING
|
||||
"See http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-filters")
|
||||
set(LLVM_DOXYGEN_QHP_CUST_FILTER_ATTRS "${PACKAGE_NAME},${PACKAGE_VERSION}" CACHE STRING
|
||||
"See http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes")
|
||||
find_program(LLVM_DOXYGEN_QHELPGENERATOR_PATH qhelpgenerator
|
||||
find_program(LLVM_DOXYGEN_QHELPGENERATOR_PATH qhelpgenerator
|
||||
DOC "Path to the qhelpgenerator binary")
|
||||
if (NOT LLVM_DOXYGEN_QHELPGENERATOR_PATH)
|
||||
message(FATAL_ERROR "Failed to find qhelpgenerator binary")
|
||||
@ -55,7 +55,7 @@ if (LLVM_ENABLE_DOXYGEN)
|
||||
set(llvm_doxygen_qhp_cust_filter_name "")
|
||||
set(llvm_doxygen_qhp_cust_filter_attrs "")
|
||||
endif()
|
||||
|
||||
|
||||
option(LLVM_DOXYGEN_SVG
|
||||
"Use svg instead of png files for doxygen graphs." OFF)
|
||||
if (LLVM_DOXYGEN_SVG)
|
||||
@ -112,6 +112,8 @@ if (LLVM_ENABLE_SPHINX)
|
||||
|
||||
if (${SPHINX_OUTPUT_MAN})
|
||||
add_sphinx_target(man llvm)
|
||||
add_sphinx_target(man llvm-dwarfdump)
|
||||
add_sphinx_target(man dsymutil)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
@ -167,10 +167,9 @@ Other Types
|
||||
|
||||
Variables that are cached or specified on the command line can have types
|
||||
associated with them. The variable's type is used by CMake's UI tool to display
|
||||
the right input field. The variable's type generally doesn't impact evaluation.
|
||||
One of the few examples is PATH variables, which CMake does have some special
|
||||
handling for. You can read more about the special handling in `CMake's set
|
||||
documentation
|
||||
the right input field. A variable's type generally doesn't impact evaluation,
|
||||
however CMake does have special handling for some variables such as PATH.
|
||||
You can read more about the special handling in `CMake's set documentation
|
||||
<https://cmake.org/cmake/help/v3.5/command/set.html#set-cache-entry>`_.
|
||||
|
||||
Scope
|
||||
@ -203,7 +202,7 @@ Control Flow
|
||||
============
|
||||
|
||||
CMake features the same basic control flow constructs you would expect in any
|
||||
scripting language, but there are a few quarks because, as with everything in
|
||||
scripting language, but there are a few quirks because, as with everything in
|
||||
CMake, control flow constructs are commands.
|
||||
|
||||
If, ElseIf, Else
|
||||
@ -334,21 +333,23 @@ When defining a CMake command handling arguments is very useful. The examples
|
||||
in this section will all use the CMake ``function`` block, but this all applies
|
||||
to the ``macro`` block as well.
|
||||
|
||||
CMake commands can have named arguments, but all commands are implicitly
|
||||
variable argument. If the command has named arguments they are required and must
|
||||
be specified at every call site. Below is a trivial example of providing a
|
||||
wrapper function for CMake's built in function ``add_dependencies``.
|
||||
CMake commands can have named arguments that are requried at every call site. In
|
||||
addition, all commands will implicitly accept a variable number of extra
|
||||
arguments (In C parlance, all commands are varargs functions). When a command is
|
||||
invoked with extra arguments (beyond the named ones) CMake will store the full
|
||||
list of arguments (both named and unnamed) in a list named ``ARGV``, and the
|
||||
sublist of unnamed arguments in ``ARGN``. Below is a trivial example of
|
||||
providing a wrapper function for CMake's built in function ``add_dependencies``.
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
function(add_deps target)
|
||||
add_dependencies(${target} ${ARGV})
|
||||
add_dependencies(${target} ${ARGN})
|
||||
endfunction()
|
||||
|
||||
This example defines a new macro named ``add_deps`` which takes a required first
|
||||
argument, and just calls another function passing through the first argument and
|
||||
all trailing arguments. When variable arguments are present CMake defines them
|
||||
in a list named ``ARGV``, and the count of the arguments is defined in ``ARGN``.
|
||||
all trailing arguments.
|
||||
|
||||
CMake provides a module ``CMakeParseArguments`` which provides an implementation
|
||||
of advanced argument parsing. We use this all over LLVM, and it is recommended
|
||||
|
@ -1578,6 +1578,17 @@ which lowers MCInst's into machine code bytes and relocations. This is
|
||||
important if you want to support direct .o file emission, or would like to
|
||||
implement an assembler for your target.
|
||||
|
||||
Emitting function stack size information
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A section containing metadata on function stack sizes will be emitted when
|
||||
``TargetLoweringObjectFile::StackSizesSection`` is not null, and
|
||||
``TargetOptions::EmitStackSizeSection`` is set (-stack-size-section). The
|
||||
section will contain an array of pairs of function symbol references (8 byte)
|
||||
and stack sizes (unsigned LEB128). The stack size values only include the space
|
||||
allocated in the function prologue. Functions with dynamic stack allocations are
|
||||
not included.
|
||||
|
||||
VLIW Packetizer
|
||||
---------------
|
||||
|
||||
|
@ -203,7 +203,7 @@ this means are `Effective Go`_ and `Go Code Review Comments`_.
|
||||
https://golang.org/doc/effective_go.html
|
||||
|
||||
.. _Go Code Review Comments:
|
||||
https://code.google.com/p/go-wiki/wiki/CodeReviewComments
|
||||
https://github.com/golang/go/wiki/CodeReviewComments
|
||||
|
||||
Mechanical Source Issues
|
||||
========================
|
||||
@ -811,6 +811,21 @@ As a rule of thumb, use ``auto &`` unless you need to copy the result, and use
|
||||
for (const auto *Ptr : Container) { observe(*Ptr); }
|
||||
for (auto *Ptr : Container) { Ptr->change(); }
|
||||
|
||||
Beware of non-determinism due to ordering of pointers
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In general, there is no relative ordering among pointers. As a result,
|
||||
when unordered containers like sets and maps are used with pointer keys
|
||||
the iteration order is undefined. Hence, iterating such containers may
|
||||
result in non-deterministic code generation. While the generated code
|
||||
might not necessarily be "wrong code", this non-determinism might result
|
||||
in unexpected runtime crashes or simply hard to reproduce bugs on the
|
||||
customer side making it harder to debug and fix.
|
||||
|
||||
As a rule of thumb, in case an ordered result is expected, remember to
|
||||
sort an unordered container before iteration. Or use ordered containers
|
||||
like vector/MapVector/SetVector if you want to iterate pointer keys.
|
||||
|
||||
Style Issues
|
||||
============
|
||||
|
||||
@ -941,8 +956,8 @@ loops. A silly example is something like this:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ++II) {
|
||||
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(II)) {
|
||||
for (Instruction &I : BB) {
|
||||
if (auto *BO = dyn_cast<BinaryOperator>(&I)) {
|
||||
Value *LHS = BO->getOperand(0);
|
||||
Value *RHS = BO->getOperand(1);
|
||||
if (LHS != RHS) {
|
||||
@ -961,8 +976,8 @@ It is strongly preferred to structure the loop like this:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ++II) {
|
||||
BinaryOperator *BO = dyn_cast<BinaryOperator>(II);
|
||||
for (Instruction &I : BB) {
|
||||
auto *BO = dyn_cast<BinaryOperator>(&I);
|
||||
if (!BO) continue;
|
||||
|
||||
Value *LHS = BO->getOperand(0);
|
||||
@ -1232,6 +1247,12 @@ builds), ``llvm_unreachable`` becomes a hint to compilers to skip generating
|
||||
code for this branch. If the compiler does not support this, it will fall back
|
||||
to the "abort" implementation.
|
||||
|
||||
Neither assertions or ``llvm_unreachable`` will abort the program on a release
|
||||
build. If the error condition can be triggered by user input then the
|
||||
recoverable error mechanism described in :doc:`ProgrammersManual` should be
|
||||
used instead. In cases where this is not practical, ``report_fatal_error`` may
|
||||
be used.
|
||||
|
||||
Another issue is that values used only by assertions will produce an "unused
|
||||
value" warning when assertions are disabled. For example, this code will warn:
|
||||
|
||||
@ -1316,19 +1337,31 @@ that the enum expression may take any representable value, not just those of
|
||||
individual enumerators. To suppress this warning, use ``llvm_unreachable`` after
|
||||
the switch.
|
||||
|
||||
Don't evaluate ``end()`` every time through a loop
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Use range-based ``for`` loops wherever possible
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Because C++ doesn't have a standard "``foreach``" loop (though it can be
|
||||
emulated with macros and may be coming in C++'0x) we end up writing a lot of
|
||||
loops that manually iterate from begin to end on a variety of containers or
|
||||
through other data structures. One common mistake is to write a loop in this
|
||||
style:
|
||||
The introduction of range-based ``for`` loops in C++11 means that explicit
|
||||
manipulation of iterators is rarely necessary. We use range-based ``for``
|
||||
loops wherever possible for all newly added code. For example:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
BasicBlock *BB = ...
|
||||
for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I)
|
||||
for (Instruction &I : *BB)
|
||||
... use I ...
|
||||
|
||||
Don't evaluate ``end()`` every time through a loop
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In cases where range-based ``for`` loops can't be used and it is necessary
|
||||
to write an explicit iterator-based loop, pay close attention to whether
|
||||
``end()`` is re-evaluted on each loop iteration. One common mistake is to
|
||||
write a loop in this style:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
BasicBlock *BB = ...
|
||||
for (auto I = BB->begin(); I != BB->end(); ++I)
|
||||
... use I ...
|
||||
|
||||
The problem with this construct is that it evaluates "``BB->end()``" every time
|
||||
@ -1339,7 +1372,7 @@ convenient way to do this is like so:
|
||||
.. code-block:: c++
|
||||
|
||||
BasicBlock *BB = ...
|
||||
for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
|
||||
for (auto I = BB->begin(), E = BB->end(); I != E; ++I)
|
||||
... use I ...
|
||||
|
||||
The observant may quickly point out that these two loops may have different
|
||||
|
@ -86,6 +86,11 @@ OPTIONS
|
||||
|
||||
All other variables get undefined after each encountered ``CHECK-LABEL``.
|
||||
|
||||
.. option:: -D<VAR=VALUE>
|
||||
|
||||
Sets a filecheck variable ``VAR`` with value ``VALUE`` that can be used in
|
||||
``CHECK:`` lines.
|
||||
|
||||
.. option:: -version
|
||||
|
||||
Show the version number of this program.
|
||||
@ -397,10 +402,11 @@ All FileCheck directives take a pattern to match.
|
||||
For most uses of FileCheck, fixed string matching is perfectly sufficient. For
|
||||
some things, a more flexible form of matching is desired. To support this,
|
||||
FileCheck allows you to specify regular expressions in matching strings,
|
||||
surrounded by double braces: ``{{yourregex}}``. Because we want to use fixed
|
||||
string matching for a majority of what we do, FileCheck has been designed to
|
||||
support mixing and matching fixed string matching with regular expressions.
|
||||
This allows you to write things like this:
|
||||
surrounded by double braces: ``{{yourregex}}``. FileCheck implements a POSIX
|
||||
regular expression matcher; it supports Extended POSIX regular expressions
|
||||
(ERE). Because we want to use fixed string matching for a majority of what we
|
||||
do, FileCheck has been designed to support mixing and matching fixed string
|
||||
matching with regular expressions. This allows you to write things like this:
|
||||
|
||||
.. code-block:: llvm
|
||||
|
||||
@ -434,7 +440,7 @@ The first check line matches a regex ``%[a-z]+`` and captures it into the
|
||||
variable ``REGISTER``. The second line verifies that whatever is in
|
||||
``REGISTER`` occurs later in the file after an "``andw``". :program:`FileCheck`
|
||||
variable references are always contained in ``[[ ]]`` pairs, and their names can
|
||||
be formed with the regex ``[a-zA-Z][a-zA-Z0-9]*``. If a colon follows the name,
|
||||
be formed with the regex ``[a-zA-Z_][a-zA-Z0-9_]*``. If a colon follows the name,
|
||||
then it is a definition of the variable; otherwise, it is a use.
|
||||
|
||||
:program:`FileCheck` variables can be defined multiple times, and uses always
|
||||
|
89
docs/CommandGuide/dsymutil.rst
Normal file
89
docs/CommandGuide/dsymutil.rst
Normal file
@ -0,0 +1,89 @@
|
||||
dsymutil - manipulate archived DWARF debug symbol files
|
||||
=======================================================
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
|
||||
| :program:`dsymutil` [*options*] *executable*
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
:program:`dsymutil` links the DWARF debug information found in the object files
|
||||
for an executable *executable* by using debug symbols information contained in
|
||||
its symbol table. By default, the linked debug information is placed in a
|
||||
``.dSYM`` bundle with the same name as the executable.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
.. option:: --arch=<arch>
|
||||
|
||||
Link DWARF debug information only for specified CPU architecture types.
|
||||
Architectures may be specified by name. When using this option, an error will
|
||||
be returned if any architectures can not be properly linked. This option can
|
||||
be specified multiple times, once for each desired architecture. All CPU
|
||||
architectures will be linked by default and any architectures that can't be
|
||||
properly linked will cause :program:`dsymutil` to return an error.
|
||||
|
||||
.. option:: --dump-debug-map
|
||||
|
||||
Dump the *executable*'s debug-map (the list of the object files containing the
|
||||
debug information) in YAML format and exit. Not DWARF link will take place.
|
||||
|
||||
.. option:: -f, --flat
|
||||
|
||||
Produce a flat dSYM file. A ``.dwarf`` extension will be appended to the
|
||||
executable name unless the output file is specified using the -o option.
|
||||
|
||||
.. option:: --no-odr
|
||||
|
||||
Do not use ODR (One Definition Rule) for uniquing C++ types.
|
||||
|
||||
.. option:: --no-output
|
||||
|
||||
Do the link in memory, but do not emit the result file.
|
||||
|
||||
.. option:: --no-swiftmodule-timestamp
|
||||
|
||||
Don't check the timestamp for swiftmodule files.
|
||||
|
||||
.. option:: -j <n>, --num-threads=<n>
|
||||
|
||||
Specifies the maximum number (``n``) of simultaneous threads to use when
|
||||
linking multiple architectures.
|
||||
|
||||
.. option:: -o <filename>
|
||||
|
||||
Specifies an alternate ``path`` to place the dSYM bundle. The default dSYM
|
||||
bundle path is created by appending ``.dSYM`` to the executable name.
|
||||
|
||||
.. option:: --oso-prepend-path=<path>
|
||||
|
||||
Specifies a ``path`` to prepend to all debug symbol object file paths.
|
||||
|
||||
.. option:: -s, --symtab
|
||||
|
||||
Dumps the symbol table found in *executable* or object file(s) and exits.
|
||||
|
||||
.. option:: -v, --verbose
|
||||
|
||||
Display verbose information when linking.
|
||||
|
||||
.. option:: --version
|
||||
|
||||
Display the version of the tool.
|
||||
|
||||
.. option:: -y
|
||||
|
||||
Treat *executable* as a YAML debug-map rather than an executable.
|
||||
|
||||
EXIT STATUS
|
||||
-----------
|
||||
|
||||
:program:`dsymutil` returns 0 if the DWARF debug information was linked
|
||||
successfully. Otherwise, it returns 1.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
||||
:manpage:`llvm-dwarfdump(1)`
|
@ -30,6 +30,7 @@ Basic Commands
|
||||
llvm-stress
|
||||
llvm-symbolizer
|
||||
llvm-dwarfdump
|
||||
dsymutil
|
||||
|
||||
Debugging Tools
|
||||
~~~~~~~~~~~~~~~
|
||||
@ -51,4 +52,5 @@ Developer Tools
|
||||
tblgen
|
||||
lit
|
||||
llvm-build
|
||||
llvm-pdbutil
|
||||
llvm-readobj
|
||||
|
@ -132,6 +132,14 @@ End-user Options
|
||||
Specify which EABI version should conform to. Valid EABI versions are *gnu*,
|
||||
*4* and *5*. Default value (*default*) depends on the triple.
|
||||
|
||||
.. option:: -stack-size-section
|
||||
|
||||
Emit the .stack_sizes section which contains stack size metadata. The section
|
||||
contains an array of pairs of function symbol references (8 byte) and stack
|
||||
sizes (unsigned LEB128). The stack size values only include the space allocated
|
||||
in the function prologue. Functions with dynamic stack allocations are not
|
||||
included.
|
||||
|
||||
|
||||
Tuning/Configuration Options
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -122,7 +122,7 @@ CODE GENERATION OPTIONS
|
||||
|
||||
Choose the code model from:
|
||||
|
||||
.. code-block:: perl
|
||||
.. code-block:: text
|
||||
|
||||
default: Target default code model
|
||||
small: Small code model
|
||||
@ -154,7 +154,7 @@ CODE GENERATION OPTIONS
|
||||
|
||||
Instruction schedulers available (before register allocation):
|
||||
|
||||
.. code-block:: perl
|
||||
.. code-block:: text
|
||||
|
||||
=default: Best scheduler for the target
|
||||
=none: No scheduling: breadth first sequencing
|
||||
@ -168,7 +168,7 @@ CODE GENERATION OPTIONS
|
||||
|
||||
Register allocator to use (default=linearscan)
|
||||
|
||||
.. code-block:: perl
|
||||
.. code-block:: text
|
||||
|
||||
=bigblock: Big-block register allocator
|
||||
=linearscan: linear scan register allocator =local - local register allocator
|
||||
@ -178,7 +178,7 @@ CODE GENERATION OPTIONS
|
||||
|
||||
Choose relocation model from:
|
||||
|
||||
.. code-block:: perl
|
||||
.. code-block:: text
|
||||
|
||||
=default: Target default relocation model
|
||||
=static: Non-relocatable code =pic - Fully relocatable, position independent code
|
||||
@ -188,7 +188,7 @@ CODE GENERATION OPTIONS
|
||||
|
||||
Spiller to use (default=local)
|
||||
|
||||
.. code-block:: perl
|
||||
.. code-block:: text
|
||||
|
||||
=simple: simple spiller
|
||||
=local: local spiller
|
||||
@ -197,7 +197,7 @@ CODE GENERATION OPTIONS
|
||||
|
||||
Choose style of code to emit from X86 backend:
|
||||
|
||||
.. code-block:: perl
|
||||
.. code-block:: text
|
||||
|
||||
=att: Emit AT&T-style assembly
|
||||
=intel: Emit Intel-style assembly
|
||||
|
@ -195,44 +195,53 @@ OPTIONS
|
||||
|
||||
.. option:: -show-line-counts
|
||||
|
||||
Show the execution counts for each line. This is enabled by default, unless
|
||||
another ``-show`` option is used.
|
||||
Show the execution counts for each line. Defaults to true, unless another
|
||||
``-show`` option is used.
|
||||
|
||||
.. option:: -show-expansions
|
||||
|
||||
Expand inclusions, such as preprocessor macros or textual inclusions, inline
|
||||
in the display of the source file.
|
||||
in the display of the source file. Defaults to false.
|
||||
|
||||
.. option:: -show-instantiations
|
||||
|
||||
For source regions that are instantiated multiple times, such as templates in
|
||||
``C++``, show each instantiation separately as well as the combined summary.
|
||||
Defaults to true.
|
||||
|
||||
.. option:: -show-regions
|
||||
|
||||
Show the execution counts for each region by displaying a caret that points to
|
||||
the character where the region starts.
|
||||
the character where the region starts. Defaults to false.
|
||||
|
||||
.. option:: -show-line-counts-or-regions
|
||||
|
||||
Show the execution counts for each line if there is only one region on the
|
||||
line, but show the individual regions if there are multiple on the line.
|
||||
Defaults to false.
|
||||
|
||||
.. option:: -use-color[=VALUE]
|
||||
.. option:: -use-color
|
||||
|
||||
Enable or disable color output. By default this is autodetected.
|
||||
|
||||
.. option:: -arch=<name>
|
||||
.. option:: -arch=[*NAMES*]
|
||||
|
||||
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.
|
||||
Specify a list of architectures such that the Nth entry in the list
|
||||
corresponds to the Nth specified binary. If the covered object is a universal
|
||||
binary, this specifies 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=<NAME>
|
||||
|
||||
Show code coverage only for functions with the given name.
|
||||
|
||||
.. option:: -name-whitelist=<FILE>
|
||||
|
||||
Show code coverage only for functions listed in the given file. Each line in
|
||||
the file should start with `whitelist_fun:`, immediately followed by the name
|
||||
of the function to accept. This name can be a wildcard expression.
|
||||
|
||||
.. option:: -name-regex=<PATTERN>
|
||||
|
||||
Show code coverage only for functions that match the given regular expression.
|
||||
@ -288,6 +297,12 @@ OPTIONS
|
||||
Show code coverage only for functions with region coverage less than the given
|
||||
threshold.
|
||||
|
||||
.. option:: -path-equivalence=<from>,<to>
|
||||
|
||||
Map the paths in the coverage data to local source file paths. This allows you
|
||||
to generate the coverage data on one machine, and then use llvm-cov on a
|
||||
different machine where you have the same files on a different path.
|
||||
|
||||
.. program:: llvm-cov report
|
||||
|
||||
.. _llvm-cov-report:
|
||||
@ -330,7 +345,11 @@ OPTIONS
|
||||
|
||||
.. option:: -show-functions
|
||||
|
||||
Show coverage summaries for each function.
|
||||
Show coverage summaries for each function. Defaults to false.
|
||||
|
||||
.. option:: -show-instantiation-summary
|
||||
|
||||
Show statistics for all function instantiations. Defaults to false.
|
||||
|
||||
.. program:: llvm-cov export
|
||||
|
||||
@ -363,3 +382,10 @@ OPTIONS
|
||||
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:: -summary-only
|
||||
|
||||
Export only summary information for each file in the coverage data. This mode
|
||||
will not export coverage information for smaller units such as individual
|
||||
functions or regions. The result will be the same as produced by :program:
|
||||
`llvm-cov report` command, but presented in JSON format rather than text.
|
||||
|
@ -1,30 +1,142 @@
|
||||
llvm-dwarfdump - print contents of DWARF sections
|
||||
=================================================
|
||||
llvm-dwarfdump - dump and verify DWARF debug information
|
||||
========================================================
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
|
||||
:program:`llvm-dwarfdump` [*options*] [*filenames...*]
|
||||
:program:`llvm-dwarfdump` [*options*] [*filename ...*]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
:program:`llvm-dwarfdump` parses DWARF sections in the object files
|
||||
and prints their contents in human-readable form.
|
||||
:program:`llvm-dwarfdump` parses DWARF sections in object files,
|
||||
archives, and `.dSYM` bundles and prints their contents in
|
||||
human-readable form. Only the .debug_info section is printed unless one of
|
||||
the section-specific options or :option:`--all` is specified.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
|
||||
.. option:: -debug-dump=section
|
||||
.. option:: -a, --all
|
||||
|
||||
Specify the DWARF section to dump.
|
||||
For example, use ``abbrev`` to dump the contents of ``.debug_abbrev`` section,
|
||||
``loc.dwo`` to dump the contents of ``.debug_loc.dwo`` etc.
|
||||
See ``llvm-dwarfdump --help`` for the complete list of supported sections.
|
||||
Use ``all`` to dump all DWARF sections. It is the default.
|
||||
Disassemble all supported DWARF sections.
|
||||
|
||||
.. option:: --arch=<arch>
|
||||
|
||||
Dump DWARF debug information for the specified CPU architecture.
|
||||
Architectures may be specified by name or by number. This
|
||||
option can be specified multiple times, once for each desired
|
||||
architecture. All CPU architectures will be printed by
|
||||
default.
|
||||
|
||||
.. option:: -c, --show-children
|
||||
|
||||
Show a debug info entry's children when using
|
||||
the :option:`--debug-info`, :option:`--find`,
|
||||
and :option:`--name` options.
|
||||
|
||||
.. option:: -f <name>, --find=<name>
|
||||
|
||||
Search for the exact text <name> in the accelerator tables
|
||||
and print the matching debug information entries.
|
||||
When there is no accelerator tables or the name of the DIE
|
||||
you are looking for is not found in the accelerator tables,
|
||||
try using the slower but more complete :option:`--name` option.
|
||||
|
||||
.. option:: -F, --show-form
|
||||
|
||||
Show DWARF form types after the DWARF attribute types.
|
||||
|
||||
.. option:: -h, --help
|
||||
|
||||
Show help and usage for this command.
|
||||
|
||||
.. option:: -i, --ignore-case
|
||||
|
||||
Ignore case distinctions in when searching entries by name
|
||||
or by regular expression.
|
||||
|
||||
.. option:: -n <pattern>, --name=<pattern>
|
||||
|
||||
Find and print all debug info entries whose name
|
||||
(`DW_AT_name` attribute) matches the exact text in
|
||||
<pattern>. Use the :option:`--regex` option to have
|
||||
<pattern> become a regular expression for more flexible
|
||||
pattern matching.
|
||||
|
||||
.. option:: --lookup=<address>
|
||||
|
||||
Lookup <address> in the debug information and print out the file,
|
||||
function, block, and line table details.
|
||||
|
||||
.. option:: -o <path>, --out-file=<path>
|
||||
|
||||
Redirect output to a file specified by <path>.
|
||||
|
||||
.. option:: -p, --show-parents
|
||||
|
||||
Show a debug info entry's parent objects when using the
|
||||
:option:`--debug-info`, :option:`--find`, and
|
||||
:option:`--name` options.
|
||||
|
||||
.. option:: -r <n>, --recurse-depth=<n>
|
||||
|
||||
Only recurse to a maximum depth of <n> when dumping debug info
|
||||
entries.
|
||||
|
||||
.. option:: --statistics
|
||||
|
||||
Collect debug info quality metrics and print the results
|
||||
as machine-readable single-line JSON output.
|
||||
|
||||
.. option:: -x, --regex
|
||||
|
||||
Treat any <pattern> strings as regular expressions when searching
|
||||
instead of just as an exact string match.
|
||||
|
||||
.. option:: -u, --uuid
|
||||
|
||||
Show the UUID for each architecture.
|
||||
|
||||
.. option:: --diff
|
||||
|
||||
Dump the output in a format that is more friendly for comparing
|
||||
DWARF output from two different files.
|
||||
|
||||
.. option:: -v, --verbose
|
||||
|
||||
Display verbose information when dumping. This can help to debug
|
||||
DWARF issues.
|
||||
|
||||
.. option:: --verify
|
||||
|
||||
Verify the structure of the DWARF information by verifying the
|
||||
compile unit chains, DIE relationships graph, address
|
||||
ranges, and more.
|
||||
|
||||
.. option:: --version
|
||||
|
||||
Display the version of the tool.
|
||||
|
||||
.. option:: --debug-abbrev, --debug-aranges, --debug-cu-index, --debug-frame [=<offset>], --debug-gnu-pubnames, --debug-gnu-pubtypes, --debug-info [=<offset>], --debug-line [=<offset>], --debug-loc [=<offset>], --debug-macro, --debug-pubnames, --debug-pubtypes, --debug-ranges, --debug-str, --debug-str-offsets, --debug-tu-index, --debug-types, --eh-frame, --gdb-index, --apple-names, --apple-types, --apple-namespaces, --apple-objc
|
||||
|
||||
Dump the specified DWARF section by name. Only the
|
||||
`.debug_info` section is shown by default. Some entries
|
||||
support adding an `=<offset>` as a way to provide an
|
||||
optional offset of the exact entry to dump within the
|
||||
respective section. When an offset is provided, only the
|
||||
entry at that offset will be dumped, else the entire
|
||||
section will be dumped. Children of items at a specific
|
||||
offset can be dumped by also using the
|
||||
:option:`--show-children` option where applicable.
|
||||
|
||||
EXIT STATUS
|
||||
-----------
|
||||
|
||||
:program:`llvm-dwarfdump` returns 0 if the input files were parsed and dumped
|
||||
successfully. Otherwise, it returns 1.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
||||
:manpage:`dsymutil(1)`
|
||||
|
585
docs/CommandGuide/llvm-pdbutil.rst
Normal file
585
docs/CommandGuide/llvm-pdbutil.rst
Normal file
@ -0,0 +1,585 @@
|
||||
llvm-pdbutil - PDB File forensics and diagnostics
|
||||
=================================================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
:program:`llvm-pdbutil` [*subcommand*] [*options*]
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
Display types, symbols, CodeView records, and other information from a
|
||||
PDB file, as well as manipulate and create PDB files. :program:`llvm-pdbutil`
|
||||
is normally used by FileCheck-based tests to test LLVM's PDB reading and
|
||||
writing functionality, but can also be used for general PDB file investigation
|
||||
and forensics, or as a replacement for cvdump.
|
||||
|
||||
Subcommands
|
||||
-----------
|
||||
|
||||
:program:`llvm-pdbutil` is separated into several subcommands each tailored to
|
||||
a different purpose. A brief summary of each command follows, with more detail
|
||||
in the sections that follow.
|
||||
|
||||
* :ref:`pretty_subcommand` - Dump symbol and type information in a format that
|
||||
tries to look as much like the original source code as possible.
|
||||
* :ref:`dump_subcommand` - Dump low level types and structures from the PDB
|
||||
file, including CodeView records, hash tables, PDB streams, etc.
|
||||
* :ref:`bytes_subcommand` - Dump data from the PDB file's streams, records,
|
||||
types, symbols, etc as raw bytes.
|
||||
* :ref:`yaml2pdb_subcommand` - Given a yaml description of a PDB file, produce
|
||||
a valid PDB file that matches that description.
|
||||
* :ref:`pdb2yaml_subcommand` - For a given PDB file, produce a YAML
|
||||
description of some or all of the file in a way that the PDB can be
|
||||
reconstructed.
|
||||
* :ref:`merge_subcommand` - Given two PDBs, produce a third PDB that is the
|
||||
result of merging the two input PDBs.
|
||||
|
||||
.. _pretty_subcommand:
|
||||
|
||||
pretty
|
||||
~~~~~~
|
||||
|
||||
.. program:: llvm-pdbutil pretty
|
||||
|
||||
.. important::
|
||||
The **pretty** subcommand is built on the Windows DIA SDK, and as such is not
|
||||
supported on non-Windows platforms.
|
||||
|
||||
USAGE: :program:`llvm-pdbutil` pretty [*options*] <input PDB file>
|
||||
|
||||
Summary
|
||||
^^^^^^^^^^^
|
||||
|
||||
The *pretty* subcommand displays a very high level representation of your
|
||||
program's debug info. Since it is built on the Windows DIA SDK which is the
|
||||
standard API that Windows tools and debuggers query debug information, it
|
||||
presents a more authoritative view of how a debugger is going to interpret your
|
||||
debug information than a mode which displays low-level CodeView records.
|
||||
|
||||
Options
|
||||
^^^^^^^
|
||||
|
||||
Filtering and Sorting Options
|
||||
+++++++++++++++++++++++++++++
|
||||
|
||||
.. note::
|
||||
*exclude* filters take priority over *include* filters. So if a filter
|
||||
matches both an include and an exclude rule, then it is excluded.
|
||||
|
||||
.. option:: -exclude-compilands=<string>
|
||||
|
||||
When dumping compilands, compiland source-file contributions, or per-compiland
|
||||
symbols, this option instructs **llvm-pdbutil** to omit any compilands that
|
||||
match the specified regular expression.
|
||||
|
||||
.. option:: -exclude-symbols=<string>
|
||||
|
||||
When dumping global, public, or per-compiland symbols, this option instructs
|
||||
**llvm-pdbutil** to omit any symbols that match the specified regular
|
||||
expression.
|
||||
|
||||
.. option:: -exclude-types=<string>
|
||||
|
||||
When dumping types, this option instructs **llvm-pdbutil** to omit any types
|
||||
that match the specified regular expression.
|
||||
|
||||
.. option:: -include-compilands=<string>
|
||||
|
||||
When dumping compilands, compiland source-file contributions, or per-compiland
|
||||
symbols, limit the initial search to only those compilands that match the
|
||||
specified regular expression.
|
||||
|
||||
.. option:: -include-symbols=<string>
|
||||
|
||||
When dumping global, public, or per-compiland symbols, limit the initial
|
||||
search to only those symbols that match the specified regular expression.
|
||||
|
||||
.. option:: -include-types=<string>
|
||||
|
||||
When dumping types, limit the initial search to only those types that match
|
||||
the specified regular expression.
|
||||
|
||||
.. option:: -min-class-padding=<uint>
|
||||
|
||||
Only display types that have at least the specified amount of alignment
|
||||
padding, accounting for padding in base classes and aggregate field members.
|
||||
|
||||
.. option:: -min-class-padding-imm=<uint>
|
||||
|
||||
Only display types that have at least the specified amount of alignment
|
||||
padding, ignoring padding in base classes and aggregate field members.
|
||||
|
||||
.. option:: -min-type-size=<uint>
|
||||
|
||||
Only display types T where sizeof(T) is greater than or equal to the specified
|
||||
amount.
|
||||
|
||||
.. option:: -no-compiler-generated
|
||||
|
||||
Don't show compiler generated types and symbols
|
||||
|
||||
.. option:: -no-enum-definitions
|
||||
|
||||
When dumping an enum, don't show the full enum (e.g. the individual enumerator
|
||||
values).
|
||||
|
||||
.. option:: -no-system-libs
|
||||
|
||||
Don't show symbols from system libraries
|
||||
|
||||
Symbol Type Options
|
||||
+++++++++++++++++++
|
||||
.. option:: -all
|
||||
|
||||
Implies all other options in this category.
|
||||
|
||||
.. option:: -class-definitions=<format>
|
||||
|
||||
Displays class definitions in the specified format.
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
=all - Display all class members including data, constants, typedefs, functions, etc (default)
|
||||
=layout - Only display members that contribute to class size.
|
||||
=none - Don't display class definitions (e.g. only display the name and base list)
|
||||
|
||||
.. option:: -class-order
|
||||
|
||||
Displays classes in the specified order.
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
=none - Undefined / no particular sort order (default)
|
||||
=name - Sort classes by name
|
||||
=size - Sort classes by size
|
||||
=padding - Sort classes by amount of padding
|
||||
=padding-pct - Sort classes by percentage of space consumed by padding
|
||||
=padding-imm - Sort classes by amount of immediate padding
|
||||
=padding-pct-imm - Sort classes by percentage of space consumed by immediate padding
|
||||
|
||||
.. option:: -class-recurse-depth=<uint>
|
||||
|
||||
When dumping class definitions, stop after recursing the specified number of times. The
|
||||
default is 0, which is no limit.
|
||||
|
||||
.. option:: -classes
|
||||
|
||||
Display classes
|
||||
|
||||
.. option:: -compilands
|
||||
|
||||
Display compilands (e.g. object files)
|
||||
|
||||
.. option:: -enums
|
||||
|
||||
Display enums
|
||||
|
||||
.. option:: -externals
|
||||
|
||||
Dump external (e.g. exported) symbols
|
||||
|
||||
.. option:: -globals
|
||||
|
||||
Dump global symbols
|
||||
|
||||
.. option:: -lines
|
||||
|
||||
Dump the mappings between source lines and code addresses.
|
||||
|
||||
.. option:: -module-syms
|
||||
|
||||
Display symbols (variables, functions, etc) for each compiland
|
||||
|
||||
.. option:: -sym-types=<types>
|
||||
|
||||
Type of symbols to dump when -globals, -externals, or -module-syms is
|
||||
specified. (default all)
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
=thunks - Display thunk symbols
|
||||
=data - Display data symbols
|
||||
=funcs - Display function symbols
|
||||
=all - Display all symbols (default)
|
||||
|
||||
.. option:: -symbol-order=<order>
|
||||
|
||||
For symbols dumped via the -module-syms, -globals, or -externals options, sort
|
||||
the results in specified order.
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
=none - Undefined / no particular sort order
|
||||
=name - Sort symbols by name
|
||||
=size - Sort symbols by size
|
||||
|
||||
.. option:: -typedefs
|
||||
|
||||
Display typedef types
|
||||
|
||||
.. option:: -types
|
||||
|
||||
Display all types (implies -classes, -enums, -typedefs)
|
||||
|
||||
Other Options
|
||||
+++++++++++++
|
||||
|
||||
.. option:: -color-output
|
||||
|
||||
Force color output on or off. By default, color if used if outputting to a
|
||||
terminal.
|
||||
|
||||
.. option:: -load-address=<uint>
|
||||
|
||||
When displaying relative virtual addresses, assume the process is loaded at the
|
||||
given address and display what would be the absolute address.
|
||||
|
||||
.. _dump_subcommand:
|
||||
|
||||
dump
|
||||
~~~~
|
||||
|
||||
USAGE: :program:`llvm-pdbutil` dump [*options*] <input PDB file>
|
||||
|
||||
.. program:: llvm-pdbutil dump
|
||||
|
||||
Summary
|
||||
^^^^^^^^^^^
|
||||
|
||||
The **dump** subcommand displays low level information about the structure of a
|
||||
PDB file. It is used heavily by LLVM's testing infrastructure, but can also be
|
||||
used for PDB forensics. It serves a role similar to that of Microsoft's
|
||||
`cvdump` tool.
|
||||
|
||||
.. note::
|
||||
The **dump** subcommand exposes internal details of the file format. As
|
||||
such, the reader should be familiar with :doc:`/PDB/index` before using this
|
||||
command.
|
||||
|
||||
Options
|
||||
^^^^^^^
|
||||
|
||||
MSF Container Options
|
||||
+++++++++++++++++++++
|
||||
|
||||
.. option:: -streams
|
||||
|
||||
dump a summary of all of the streams in the PDB file.
|
||||
|
||||
.. option:: -stream-blocks
|
||||
|
||||
In conjunction with :option:`-streams`, add information to the output about
|
||||
what blocks the specified stream occupies.
|
||||
|
||||
.. option:: -summary
|
||||
|
||||
Dump MSF and PDB header information.
|
||||
|
||||
Module & File Options
|
||||
+++++++++++++++++++++
|
||||
|
||||
.. option:: -modi=<uint>
|
||||
|
||||
For all options that dump information from each module/compiland, limit to
|
||||
the specified module.
|
||||
|
||||
.. option:: -files
|
||||
|
||||
Dump the source files that contribute to each displayed module.
|
||||
|
||||
.. option:: -il
|
||||
|
||||
Dump inlinee line information (DEBUG_S_INLINEELINES CodeView subsection)
|
||||
|
||||
.. option:: -l
|
||||
|
||||
Dump line information (DEBUG_S_LINES CodeView subsection)
|
||||
|
||||
.. option:: -modules
|
||||
|
||||
Dump compiland information
|
||||
|
||||
.. option:: -xme
|
||||
|
||||
Dump cross module exports (DEBUG_S_CROSSSCOPEEXPORTS CodeView subsection)
|
||||
|
||||
.. option:: -xmi
|
||||
|
||||
Dump cross module imports (DEBUG_S_CROSSSCOPEIMPORTS CodeView subsection)
|
||||
|
||||
Symbol Options
|
||||
++++++++++++++
|
||||
|
||||
.. option:: -globals
|
||||
|
||||
dump global symbol records
|
||||
|
||||
.. option:: -global-extras
|
||||
|
||||
dump additional information about the globals, such as hash buckets and hash
|
||||
values.
|
||||
|
||||
.. option:: -publics
|
||||
|
||||
dump public symbol records
|
||||
|
||||
.. option:: -public-extras
|
||||
|
||||
dump additional information about the publics, such as hash buckets and hash
|
||||
values.
|
||||
|
||||
.. option:: -symbols
|
||||
|
||||
dump symbols (functions, variables, etc) for each module dumped.
|
||||
|
||||
.. option:: -sym-data
|
||||
|
||||
For each symbol record dumped as a result of the :option:`-symbols` option,
|
||||
display the full bytes of the record in binary as well.
|
||||
|
||||
Type Record Options
|
||||
+++++++++++++++++++
|
||||
|
||||
.. option:: -types
|
||||
|
||||
Dump CodeView type records from TPI stream
|
||||
|
||||
.. option:: -type-extras
|
||||
|
||||
Dump additional information from the TPI stream, such as hashes and the type
|
||||
index offsets array.
|
||||
|
||||
.. option:: -type-data
|
||||
|
||||
For each type record dumped, display the full bytes of the record in binary as
|
||||
well.
|
||||
|
||||
.. option:: -type-index=<uint>
|
||||
|
||||
Only dump types with the specified type index.
|
||||
|
||||
.. option:: -ids
|
||||
|
||||
Dump CodeView type records from IPI stream.
|
||||
|
||||
.. option:: -id-extras
|
||||
|
||||
Dump additional information from the IPI stream, such as hashes and the type
|
||||
index offsets array.
|
||||
|
||||
.. option:: -id-data
|
||||
|
||||
For each ID record dumped, display the full bytes of the record in binary as
|
||||
well.
|
||||
|
||||
.. option:: -id-index=<uint>
|
||||
|
||||
only dump ID records with the specified hexadecimal type index.
|
||||
|
||||
.. option:: -dependents
|
||||
|
||||
When used in conjunction with :option:`-type-index` or :option:`-id-index`,
|
||||
dumps the entire dependency graph for the specified index instead of just the
|
||||
single record with the specified index. For example, if type index 0x4000 is
|
||||
a function whose return type has index 0x3000, and you specify
|
||||
`-dependents=0x4000`, then this would dump both records (as well as any other
|
||||
dependents in the tree).
|
||||
|
||||
Miscellaneous Options
|
||||
+++++++++++++++++++++
|
||||
|
||||
.. option:: -all
|
||||
|
||||
Implies most other options.
|
||||
|
||||
.. option:: -section-contribs
|
||||
|
||||
Dump section contributions.
|
||||
|
||||
.. option:: -section-headers
|
||||
|
||||
Dump image section headers.
|
||||
|
||||
.. option:: -section-map
|
||||
|
||||
Dump section map.
|
||||
|
||||
.. option:: -string-table
|
||||
|
||||
Dump PDB string table.
|
||||
|
||||
.. _bytes_subcommand:
|
||||
|
||||
bytes
|
||||
~~~~~
|
||||
|
||||
USAGE: :program:`llvm-pdbutil` bytes [*options*] <input PDB file>
|
||||
|
||||
.. program:: llvm-pdbutil bytes
|
||||
|
||||
Summary
|
||||
^^^^^^^
|
||||
|
||||
Like the **dump** subcommand, the **bytes** subcommand displays low level
|
||||
information about the structure of a PDB file, but it is used for even deeper
|
||||
forensics. The **bytes** subcommand finds various structures in a PDB file
|
||||
based on the command line options specified, and dumps them in hex. Someone
|
||||
working on support for emitting PDBs would use this heavily, for example, to
|
||||
compare one PDB against another PDB to ensure byte-for-byte compatibility. It
|
||||
is not enough to simply compare the bytes of an entire file, or an entire stream
|
||||
because it's perfectly fine for the same structure to exist at different
|
||||
locations in two different PDBs, and "finding" the structure is half the battle.
|
||||
|
||||
Options
|
||||
^^^^^^^
|
||||
|
||||
MSF File Options
|
||||
++++++++++++++++
|
||||
|
||||
.. option:: -block-range=<start[-end]>
|
||||
|
||||
Dump binary data from specified range of MSF file blocks.
|
||||
|
||||
.. option:: -byte-range=<start[-end]>
|
||||
|
||||
Dump binary data from specified range of bytes in the file.
|
||||
|
||||
.. option:: -fpm
|
||||
|
||||
Dump the MSF free page map.
|
||||
|
||||
.. option:: -stream-data=<string>
|
||||
|
||||
Dump binary data from the specified streams. Format is SN[:Start][@Size].
|
||||
For example, `-stream-data=7:3@12` dumps 12 bytes from stream 7, starting
|
||||
at offset 3 in the stream.
|
||||
|
||||
PDB Stream Options
|
||||
++++++++++++++++++
|
||||
|
||||
.. option:: -name-map
|
||||
|
||||
Dump bytes of PDB Name Map
|
||||
|
||||
DBI Stream Options
|
||||
++++++++++++++++++
|
||||
|
||||
.. option:: -ec
|
||||
|
||||
Dump the edit and continue map substream of the DBI stream.
|
||||
|
||||
.. option:: -files
|
||||
|
||||
Dump the file info substream of the DBI stream.
|
||||
|
||||
.. option:: -modi
|
||||
|
||||
Dump the modi substream of the DBI stream.
|
||||
|
||||
.. option:: -sc
|
||||
|
||||
Dump section contributions substream of the DBI stream.
|
||||
|
||||
.. option:: -sm
|
||||
|
||||
Dump the section map from the DBI stream.
|
||||
|
||||
.. option:: -type-server
|
||||
|
||||
Dump the type server map from the DBI stream.
|
||||
|
||||
Module Options
|
||||
++++++++++++++
|
||||
|
||||
.. option:: -mod=<uint>
|
||||
|
||||
Limit all options in this category to the specified module index. By default,
|
||||
options in this category will dump bytes from all modules.
|
||||
|
||||
.. option:: -chunks
|
||||
|
||||
Dump the bytes of each module's C13 debug subsection.
|
||||
|
||||
.. option:: -split-chunks
|
||||
|
||||
When specified with :option:`-chunks`, split the C13 debug subsection into a
|
||||
separate chunk for each subsection type, and dump them separately.
|
||||
|
||||
.. option:: -syms
|
||||
|
||||
Dump the symbol record substream from each module.
|
||||
|
||||
Type Record Options
|
||||
+++++++++++++++++++
|
||||
|
||||
.. option:: -id=<uint>
|
||||
|
||||
Dump the record from the IPI stream with the given type index.
|
||||
|
||||
.. option:: -type=<uint>
|
||||
|
||||
Dump the record from the TPI stream with the given type index.
|
||||
|
||||
.. _pdb2yaml_subcommand:
|
||||
|
||||
pdb2yaml
|
||||
~~~~~~~~
|
||||
|
||||
USAGE: :program:`llvm-pdbutil` pdb2yaml [*options*] <input PDB file>
|
||||
|
||||
.. program:: llvm-pdbutil pdb2yaml
|
||||
|
||||
Summary
|
||||
^^^^^^^
|
||||
|
||||
Options
|
||||
^^^^^^^
|
||||
|
||||
.. _yaml2pdb_subcommand:
|
||||
|
||||
yaml2pdb
|
||||
~~~~~~~~
|
||||
|
||||
USAGE: :program:`llvm-pdbutil` yaml2pdb [*options*] <input YAML file>
|
||||
|
||||
.. program:: llvm-pdbutil yaml2pdb
|
||||
|
||||
Summary
|
||||
^^^^^^^
|
||||
|
||||
Generate a PDB file from a YAML description. The YAML syntax is not described
|
||||
here. Instead, use :ref:`llvm-pdbutil pdb2yaml <pdb2yaml_subcommand>` and
|
||||
examine the output for an example starting point.
|
||||
|
||||
Options
|
||||
^^^^^^^
|
||||
|
||||
.. option:: -pdb=<file-name>
|
||||
|
||||
Write the resulting PDB to the specified file.
|
||||
|
||||
.. _merge_subcommand:
|
||||
|
||||
merge
|
||||
~~~~~
|
||||
|
||||
USAGE: :program:`llvm-pdbutil` merge [*options*] <input PDB file 1> <input PDB file 2>
|
||||
|
||||
.. program:: llvm-pdbutil merge
|
||||
|
||||
Summary
|
||||
^^^^^^^
|
||||
|
||||
Merge two PDB files into a single file.
|
||||
|
||||
Options
|
||||
^^^^^^^
|
||||
|
||||
.. option:: -pdb=<file-name>
|
||||
|
||||
Write the resulting PDB to the specified file.
|
@ -1251,9 +1251,7 @@ Unices have a relatively low limit on command-line length. It is therefore
|
||||
customary to use the so-called 'response files' to circumvent this
|
||||
restriction. These files are mentioned on the command-line (using the "@file")
|
||||
syntax. The program reads these files and inserts the contents into argv,
|
||||
thereby working around the command-line length limits. Response files are
|
||||
enabled by an optional fourth argument to `cl::ParseEnvironmentOptions`_ and
|
||||
`cl::ParseCommandLineOptions`_.
|
||||
thereby working around the command-line length limits.
|
||||
|
||||
Top-Level Classes and Functions
|
||||
-------------------------------
|
||||
@ -1324,8 +1322,7 @@ option variables once ``argc`` and ``argv`` are available.
|
||||
|
||||
The ``cl::ParseCommandLineOptions`` function requires two parameters (``argc``
|
||||
and ``argv``), but may also take an optional third parameter which holds
|
||||
`additional extra text`_ to emit when the ``-help`` option is invoked, and a
|
||||
fourth boolean parameter that enables `response files`_.
|
||||
`additional extra text`_ to emit when the ``-help`` option is invoked.
|
||||
|
||||
.. _cl::ParseEnvironmentOptions:
|
||||
|
||||
@ -1340,9 +1337,8 @@ command line option variables just like `cl::ParseCommandLineOptions`_ does.
|
||||
|
||||
It takes four parameters: the name of the program (since ``argv`` may not be
|
||||
available, it can't just look in ``argv[0]``), the name of the environment
|
||||
variable to examine, the optional `additional extra text`_ to emit when the
|
||||
``-help`` option is invoked, and the boolean switch that controls whether
|
||||
`response files`_ should be read.
|
||||
variable to examine, and the optional `additional extra text`_ to emit when the
|
||||
``-help`` option is invoked.
|
||||
|
||||
``cl::ParseEnvironmentOptions`` will break the environment variable's value up
|
||||
into words and then process them using `cl::ParseCommandLineOptions`_.
|
||||
|
@ -119,7 +119,7 @@ ABI
|
||||
===
|
||||
|
||||
* `System V Application Binary Interface <http://www.sco.com/developers/gabi/latest/contents.html>`_
|
||||
* `Itanium C++ ABI <http://mentorembedded.github.io/cxx-abi/>`_
|
||||
* `Itanium C++ ABI <http://itanium-cxx-abi.github.io/cxx-abi/>`_
|
||||
|
||||
Linux
|
||||
-----
|
||||
|
@ -258,7 +258,7 @@ The coverage mapping variable generated by Clang has 3 fields:
|
||||
i32 2, ; The number of function records
|
||||
i32 20, ; The length of the string that contains the encoded translation unit filenames
|
||||
i32 20, ; The length of the string that contains the encoded coverage mapping data
|
||||
i32 1, ; Coverage mapping format version
|
||||
i32 2, ; Coverage mapping format version
|
||||
},
|
||||
[2 x { i64, i32, i64 }] [ ; Function records
|
||||
{ i64, i32, i64 } {
|
||||
@ -274,6 +274,8 @@ The coverage mapping variable generated by Clang has 3 fields:
|
||||
[40 x i8] c"..." ; Encoded data (dissected later)
|
||||
}, section "__llvm_covmap", align 8
|
||||
|
||||
The current version of the format is version 3. The only difference from version 2 is that a special encoding for column end locations was introduced to indicate gap regions.
|
||||
|
||||
The function record layout has evolved since version 1. In version 1, the function record for *foo* is defined as follows:
|
||||
|
||||
.. code-block:: llvm
|
||||
@ -296,7 +298,7 @@ The coverage mapping header has the following fields:
|
||||
|
||||
* The length of the string in the third field of *__llvm_coverage_mapping* that contains the encoded coverage mapping data.
|
||||
|
||||
* The format version. The current version is 2 (encoded as a 1).
|
||||
* The format version. The current version is 3 (encoded as a 2).
|
||||
|
||||
.. _function records:
|
||||
|
||||
@ -602,4 +604,6 @@ The source range record contains the following fields:
|
||||
* *numLines*: The difference between the ending line and the starting line
|
||||
of the current mapping region.
|
||||
|
||||
* *columnEnd*: The ending column of the mapping region.
|
||||
* *columnEnd*: The ending column of the mapping region. If the high bit is set,
|
||||
the current mapping region is a gap area. A count for a gap area is only used
|
||||
as the line execution count if there are no other regions on a line.
|
||||
|
@ -188,7 +188,7 @@ problem, we have a notion of an 'owner' for a piece of the code. The sole
|
||||
responsibility of a code owner is to ensure that a commit to their area of the
|
||||
code is appropriately reviewed, either by themself or by someone else. The list
|
||||
of current code owners can be found in the file
|
||||
`CODE_OWNERS.TXT <http://llvm.org/klaus/llvm/blob/master/CODE_OWNERS.TXT>`_
|
||||
`CODE_OWNERS.TXT <http://git.llvm.org/klaus/llvm/blob/master/CODE_OWNERS.TXT>`_
|
||||
in the root of the LLVM source tree.
|
||||
|
||||
Note that code ownership is completely different than reviewers: anyone can
|
||||
|
@ -32,13 +32,13 @@ execution of an application.
|
||||
|
||||
A more complete description of the Itanium ABI exception handling runtime
|
||||
support of can be found at `Itanium C++ ABI: Exception Handling
|
||||
<http://mentorembedded.github.com/cxx-abi/abi-eh.html>`_. A description of the
|
||||
<http://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html>`_. A description of the
|
||||
exception frame format can be found at `Exception Frames
|
||||
<http://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html>`_,
|
||||
with details of the DWARF 4 specification at `DWARF 4 Standard
|
||||
<http://dwarfstd.org/Dwarf4Std.php>`_. A description for the C++ exception
|
||||
table formats can be found at `Exception Handling Tables
|
||||
<http://mentorembedded.github.com/cxx-abi/exceptions.pdf>`_.
|
||||
<http://itanium-cxx-abi.github.io/cxx-abi/exceptions.pdf>`_.
|
||||
|
||||
Setjmp/Longjmp Exception Handling
|
||||
---------------------------------
|
||||
|
274
docs/FuzzingLLVM.rst
Normal file
274
docs/FuzzingLLVM.rst
Normal file
@ -0,0 +1,274 @@
|
||||
================================
|
||||
Fuzzing LLVM libraries and tools
|
||||
================================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 2
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
The LLVM tree includes a number of fuzzers for various components. These are
|
||||
built on top of :doc:`LibFuzzer <LibFuzzer>`.
|
||||
|
||||
|
||||
Available Fuzzers
|
||||
=================
|
||||
|
||||
clang-fuzzer
|
||||
------------
|
||||
|
||||
A |generic fuzzer| that tries to compile textual input as C++ code. Some of the
|
||||
bugs this fuzzer has reported are `on bugzilla`__ and `on OSS Fuzz's
|
||||
tracker`__.
|
||||
|
||||
__ https://llvm.org/pr23057
|
||||
__ https://bugs.chromium.org/p/oss-fuzz/issues/list?q=proj-llvm+clang-fuzzer
|
||||
|
||||
clang-proto-fuzzer
|
||||
------------------
|
||||
|
||||
A |protobuf fuzzer| that compiles valid C++ programs generated from a protobuf
|
||||
class that describes a subset of the C++ language.
|
||||
|
||||
This fuzzer accepts clang command line options after `ignore_remaining_args=1`.
|
||||
For example, the following command will fuzz clang with a higher optimization
|
||||
level:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
% bin/clang-proto-fuzzer <corpus-dir> -ignore_remaining_args=1 -O3
|
||||
|
||||
clang-format-fuzzer
|
||||
-------------------
|
||||
|
||||
A |generic fuzzer| that runs clang-format_ on C++ text fragments. Some of the
|
||||
bugs this fuzzer has reported are `on bugzilla`__
|
||||
and `on OSS Fuzz's tracker`__.
|
||||
|
||||
.. _clang-format: https://clang.llvm.org/docs/ClangFormat.html
|
||||
__ https://llvm.org/pr23052
|
||||
__ https://bugs.chromium.org/p/oss-fuzz/issues/list?q=proj-llvm+clang-format-fuzzer
|
||||
|
||||
llvm-as-fuzzer
|
||||
--------------
|
||||
|
||||
A |generic fuzzer| that tries to parse text as :doc:`LLVM assembly <LangRef>`.
|
||||
Some of the bugs this fuzzer has reported are `on bugzilla`__.
|
||||
|
||||
__ https://llvm.org/pr24639
|
||||
|
||||
llvm-dwarfdump-fuzzer
|
||||
---------------------
|
||||
|
||||
A |generic fuzzer| that interprets inputs as object files and runs
|
||||
:doc:`llvm-dwarfdump <CommandGuide/llvm-dwarfdump>` on them. Some of the bugs
|
||||
this fuzzer has reported are `on OSS Fuzz's tracker`__
|
||||
|
||||
__ https://bugs.chromium.org/p/oss-fuzz/issues/list?q=proj-llvm+llvm-dwarfdump-fuzzer
|
||||
|
||||
llvm-demangle-fuzzer
|
||||
---------------------
|
||||
|
||||
A |generic fuzzer| for the Itanium demangler used in various LLVM tools. We've
|
||||
fuzzed __cxa_demangle to death, why not fuzz LLVM's implementation of the same
|
||||
function!
|
||||
|
||||
llvm-isel-fuzzer
|
||||
----------------
|
||||
|
||||
A |LLVM IR fuzzer| aimed at finding bugs in instruction selection.
|
||||
|
||||
This fuzzer accepts flags after `ignore_remaining_args=1`. The flags match
|
||||
those of :doc:`llc <CommandGuide/llc>` and the triple is required. For example,
|
||||
the following command would fuzz AArch64 with :doc:`GlobalISel`:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
% bin/llvm-isel-fuzzer <corpus-dir> -ignore_remaining_args=1 -mtriple aarch64 -global-isel -O0
|
||||
|
||||
Some flags can also be specified in the binary name itself in order to support
|
||||
OSS Fuzz, which has trouble with required arguments. To do this, you can copy
|
||||
or move ``llvm-isel-fuzzer`` to ``llvm-isel-fuzzer--x-y-z``, separating options
|
||||
from the binary name using "--". The valid options are architecture names
|
||||
(``aarch64``, ``x86_64``), optimization levels (``O0``, ``O2``), or specific
|
||||
keywords, like ``gisel`` for enabling global instruction selection. In this
|
||||
mode, the same example could be run like so:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
% bin/llvm-isel-fuzzer--aarch64-O0-gisel <corpus-dir>
|
||||
|
||||
llvm-opt-fuzzer
|
||||
---------------
|
||||
|
||||
A |LLVM IR fuzzer| aimed at finding bugs in optimization passes.
|
||||
|
||||
It receives optimzation pipeline and runs it for each fuzzer input.
|
||||
|
||||
Interface of this fuzzer almost directly mirrors ``llvm-isel-fuzzer``. Both
|
||||
``mtriple`` and ``passes`` arguments are required. Passes are specified in a
|
||||
format suitable for the new pass manager.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
% bin/llvm-opt-fuzzer <corpus-dir> -ignore_remaining_args=1 -mtriple x86_64 -passes instcombine
|
||||
|
||||
Similarly to the ``llvm-isel-fuzzer`` arguments in some predefined configurations
|
||||
might be embedded directly into the binary file name:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
% bin/llvm-opt-fuzzer--x86_64-instcombine <corpus-dir>
|
||||
|
||||
llvm-mc-assemble-fuzzer
|
||||
-----------------------
|
||||
|
||||
A |generic fuzzer| that fuzzes the MC layer's assemblers by treating inputs as
|
||||
target specific assembly.
|
||||
|
||||
Note that this fuzzer has an unusual command line interface which is not fully
|
||||
compatible with all of libFuzzer's features. Fuzzer arguments must be passed
|
||||
after ``--fuzzer-args``, and any ``llc`` flags must use two dashes. For
|
||||
example, to fuzz the AArch64 assembler you might use the following command:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
llvm-mc-fuzzer --triple=aarch64-linux-gnu --fuzzer-args -max_len=4
|
||||
|
||||
This scheme will likely change in the future.
|
||||
|
||||
llvm-mc-disassemble-fuzzer
|
||||
--------------------------
|
||||
|
||||
A |generic fuzzer| that fuzzes the MC layer's disassemblers by treating inputs
|
||||
as assembled binary data.
|
||||
|
||||
Note that this fuzzer has an unusual command line interface which is not fully
|
||||
compatible with all of libFuzzer's features. See the notes above about
|
||||
``llvm-mc-assemble-fuzzer`` for details.
|
||||
|
||||
|
||||
.. |generic fuzzer| replace:: :ref:`generic fuzzer <fuzzing-llvm-generic>`
|
||||
.. |protobuf fuzzer|
|
||||
replace:: :ref:`libprotobuf-mutator based fuzzer <fuzzing-llvm-protobuf>`
|
||||
.. |LLVM IR fuzzer|
|
||||
replace:: :ref:`structured LLVM IR fuzzer <fuzzing-llvm-ir>`
|
||||
|
||||
|
||||
Mutators and Input Generators
|
||||
=============================
|
||||
|
||||
The inputs for a fuzz target are generated via random mutations of a
|
||||
:ref:`corpus <libfuzzer-corpus>`. There are a few options for the kinds of
|
||||
mutations that a fuzzer in LLVM might want.
|
||||
|
||||
.. _fuzzing-llvm-generic:
|
||||
|
||||
Generic Random Fuzzing
|
||||
----------------------
|
||||
|
||||
The most basic form of input mutation is to use the built in mutators of
|
||||
LibFuzzer. These simply treat the input corpus as a bag of bits and make random
|
||||
mutations. This type of fuzzer is good for stressing the surface layers of a
|
||||
program, and is good at testing things like lexers, parsers, or binary
|
||||
protocols.
|
||||
|
||||
Some of the in-tree fuzzers that use this type of mutator are `clang-fuzzer`_,
|
||||
`clang-format-fuzzer`_, `llvm-as-fuzzer`_, `llvm-dwarfdump-fuzzer`_,
|
||||
`llvm-mc-assemble-fuzzer`_, and `llvm-mc-disassemble-fuzzer`_.
|
||||
|
||||
.. _fuzzing-llvm-protobuf:
|
||||
|
||||
Structured Fuzzing using ``libprotobuf-mutator``
|
||||
------------------------------------------------
|
||||
|
||||
We can use libprotobuf-mutator_ in order to perform structured fuzzing and
|
||||
stress deeper layers of programs. This works by defining a protobuf class that
|
||||
translates arbitrary data into structurally interesting input. Specifically, we
|
||||
use this to work with a subset of the C++ language and perform mutations that
|
||||
produce valid C++ programs in order to exercise parts of clang that are more
|
||||
interesting than parser error handling.
|
||||
|
||||
To build this kind of fuzzer you need `protobuf`_ and its dependencies
|
||||
installed, and you need to specify some extra flags when configuring the build
|
||||
with :doc:`CMake <CMake>`. For example, `clang-proto-fuzzer`_ can be enabled by
|
||||
adding ``-DCLANG_ENABLE_PROTO_FUZZER=ON`` to the flags described in
|
||||
:ref:`building-fuzzers`.
|
||||
|
||||
The only in-tree fuzzer that uses ``libprotobuf-mutator`` today is
|
||||
`clang-proto-fuzzer`_.
|
||||
|
||||
.. _libprotobuf-mutator: https://github.com/google/libprotobuf-mutator
|
||||
.. _protobuf: https://github.com/google/protobuf
|
||||
|
||||
.. _fuzzing-llvm-ir:
|
||||
|
||||
Structured Fuzzing of LLVM IR
|
||||
-----------------------------
|
||||
|
||||
We also use a more direct form of structured fuzzing for fuzzers that take
|
||||
:doc:`LLVM IR <LangRef>` as input. This is achieved through the ``FuzzMutate``
|
||||
library, which was `discussed at EuroLLVM 2017`_.
|
||||
|
||||
The ``FuzzMutate`` library is used to structurally fuzz backends in
|
||||
`llvm-isel-fuzzer`_.
|
||||
|
||||
.. _discussed at EuroLLVM 2017: https://www.youtube.com/watch?v=UBbQ_s6hNgg
|
||||
|
||||
|
||||
Building and Running
|
||||
====================
|
||||
|
||||
.. _building-fuzzers:
|
||||
|
||||
Configuring LLVM to Build Fuzzers
|
||||
---------------------------------
|
||||
|
||||
Fuzzers will be built and linked to libFuzzer by default as long as you build
|
||||
LLVM with sanitizer coverage enabled. You would typically also enable at least
|
||||
one sanitizer to find bugs faster. The most common way to build the fuzzers is
|
||||
by adding the following two flags to your CMake invocation:
|
||||
``-DLLVM_USE_SANITIZER=Address -DLLVM_USE_SANITIZE_COVERAGE=On``.
|
||||
|
||||
.. note:: If you have ``compiler-rt`` checked out in an LLVM tree when building
|
||||
with sanitizers, you'll want to specify ``-DLLVM_BUILD_RUNTIME=Off``
|
||||
to avoid building the sanitizers themselves with sanitizers enabled.
|
||||
|
||||
Continuously Running and Finding Bugs
|
||||
-------------------------------------
|
||||
|
||||
There used to be a public buildbot running LLVM fuzzers continuously, and while
|
||||
this did find issues, it didn't have a very good way to report problems in an
|
||||
actionable way. Because of this, we're moving towards using `OSS Fuzz`_ more
|
||||
instead.
|
||||
|
||||
You can browse the `LLVM project issue list`_ for the bugs found by
|
||||
`LLVM on OSS Fuzz`_. These are also mailed to the `llvm-bugs mailing
|
||||
list`_.
|
||||
|
||||
.. _OSS Fuzz: https://github.com/google/oss-fuzz
|
||||
.. _LLVM project issue list:
|
||||
https://bugs.chromium.org/p/oss-fuzz/issues/list?q=Proj-llvm
|
||||
.. _LLVM on OSS Fuzz:
|
||||
https://github.com/google/oss-fuzz/blob/master/projects/llvm
|
||||
.. _llvm-bugs mailing list:
|
||||
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs
|
||||
|
||||
|
||||
Utilities for Writing Fuzzers
|
||||
=============================
|
||||
|
||||
There are some utilities available for writing fuzzers in LLVM.
|
||||
|
||||
Some helpers for handling the command line interface are available in
|
||||
``include/llvm/FuzzMutate/FuzzerCLI.h``, including functions to parse command
|
||||
line options in a consistent way and to implement standalone main functions so
|
||||
your fuzzer can be built and tested when not built against libFuzzer.
|
||||
|
||||
There is also some handling of the CMake config for fuzzers, where you should
|
||||
use the ``add_llvm_fuzzer`` to set up fuzzer targets. This function works
|
||||
similarly to functions such as ``add_llvm_tool``, but they take care of linking
|
||||
to LibFuzzer when appropriate and can be passed the ``DUMMY_MAIN`` argument to
|
||||
enable standalone testing.
|
@ -52,6 +52,12 @@ Here's the short story for getting up and running quickly with LLVM:
|
||||
* ``cd llvm/tools``
|
||||
* ``svn co http://llvm.org/svn/llvm-project/cfe/trunk clang``
|
||||
|
||||
#. Checkout Extra Clang Tools **[Optional]**:
|
||||
|
||||
* ``cd where-you-want-llvm-to-live``
|
||||
* ``cd llvm/tools/clang/tools``
|
||||
* ``svn co http://llvm.org/svn/llvm-project/clang-tools-extra/trunk extra``
|
||||
|
||||
#. Checkout LLD linker **[Optional]**:
|
||||
|
||||
* ``cd where-you-want-llvm-to-live``
|
||||
@ -91,9 +97,9 @@ Here's the short story for getting up and running quickly with LLVM:
|
||||
|
||||
#. Configure and build LLVM and Clang:
|
||||
|
||||
*Warning:* Make sure you've checked out *all of* the source code
|
||||
*Warning:* Make sure you've checked out *all of* the source code
|
||||
before trying to configure with cmake. cmake does not pickup newly
|
||||
added source directories in incremental builds.
|
||||
added source directories in incremental builds.
|
||||
|
||||
The build uses `CMake <CMake.html>`_. LLVM requires CMake 3.4.3 to build. It
|
||||
is generally recommended to use a recent CMake, especially if you're
|
||||
@ -137,8 +143,8 @@ Here's the short story for getting up and running quickly with LLVM:
|
||||
* CMake will generate build targets for each tool and library, and most
|
||||
LLVM sub-projects generate their own ``check-<project>`` target.
|
||||
|
||||
* Running a serial build will be *slow*. Make sure you run a
|
||||
parallel build; for ``make``, use ``make -j``.
|
||||
* Running a serial build will be *slow*. Make sure you run a
|
||||
parallel build; for ``make``, use ``make -j``.
|
||||
|
||||
* For more information see `CMake <CMake.html>`_
|
||||
|
||||
@ -146,7 +152,7 @@ Here's the short story for getting up and running quickly with LLVM:
|
||||
`below`_.
|
||||
|
||||
Consult the `Getting Started with LLVM`_ section for detailed information on
|
||||
configuring and compiling LLVM. Go to `Directory Layout`_ to learn about the
|
||||
configuring and compiling LLVM. Go to `Directory Layout`_ to learn about the
|
||||
layout of the source code tree.
|
||||
|
||||
Requirements
|
||||
@ -191,10 +197,10 @@ Windows x64 x86-64 Visual Studio
|
||||
Note that Debug builds require a lot of time and disk space. An LLVM-only build
|
||||
will need about 1-3 GB of space. A full build of LLVM and Clang will need around
|
||||
15-20 GB of disk space. The exact space requirements will vary by system. (It
|
||||
is so large because of all the debugging information and the fact that the
|
||||
libraries are statically linked into multiple tools).
|
||||
is so large because of all the debugging information and the fact that the
|
||||
libraries are statically linked into multiple tools).
|
||||
|
||||
If you you are space-constrained, you can build only selected tools or only
|
||||
If you you are space-constrained, you can build only selected tools or only
|
||||
selected targets. The Release build requires considerably less space.
|
||||
|
||||
The LLVM suite *may* compile on other platforms, but it is not guaranteed to do
|
||||
@ -460,34 +466,13 @@ populate it with the LLVM source code, Makefiles, test directories, and local
|
||||
copies of documentation files.
|
||||
|
||||
If you want to get a specific release (as opposed to the most recent revision),
|
||||
you can checkout it from the '``tags``' directory (instead of '``trunk``'). The
|
||||
you can check it out from the '``tags``' directory (instead of '``trunk``'). The
|
||||
following releases are located in the following subdirectories of the '``tags``'
|
||||
directory:
|
||||
|
||||
* Release 3.4: **RELEASE_34/final**
|
||||
* Release 3.3: **RELEASE_33/final**
|
||||
* Release 3.2: **RELEASE_32/final**
|
||||
* Release 3.1: **RELEASE_31/final**
|
||||
* Release 3.0: **RELEASE_30/final**
|
||||
* Release 2.9: **RELEASE_29/final**
|
||||
* Release 2.8: **RELEASE_28**
|
||||
* Release 2.7: **RELEASE_27**
|
||||
* Release 2.6: **RELEASE_26**
|
||||
* Release 2.5: **RELEASE_25**
|
||||
* Release 2.4: **RELEASE_24**
|
||||
* Release 2.3: **RELEASE_23**
|
||||
* Release 2.2: **RELEASE_22**
|
||||
* Release 2.1: **RELEASE_21**
|
||||
* Release 2.0: **RELEASE_20**
|
||||
* Release 1.9: **RELEASE_19**
|
||||
* Release 1.8: **RELEASE_18**
|
||||
* Release 1.7: **RELEASE_17**
|
||||
* Release 1.6: **RELEASE_16**
|
||||
* Release 1.5: **RELEASE_15**
|
||||
* Release 1.4: **RELEASE_14**
|
||||
* Release 1.3: **RELEASE_13**
|
||||
* Release 1.2: **RELEASE_12**
|
||||
* Release 1.1: **RELEASE_11**
|
||||
* Release 3.5.0 and later: **RELEASE_350/final** and so on
|
||||
* Release 2.9 through 3.4: **RELEASE_29/final** and so on
|
||||
* Release 1.1 through 2.8: **RELEASE_11** and so on
|
||||
* Release 1.0: **RELEASE_1**
|
||||
|
||||
If you would like to get the LLVM test suite (a separate package as of 1.4), you
|
||||
@ -512,43 +497,43 @@ clone of LLVM via:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% git clone http://llvm.org/git/llvm.git
|
||||
% git clone https://git.llvm.org/git/llvm.git/
|
||||
|
||||
If you want to check out clang too, run:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% cd llvm/tools
|
||||
% git clone http://llvm.org/git/clang.git
|
||||
% git clone https://git.llvm.org/git/clang.git/
|
||||
|
||||
If you want to check out compiler-rt (required to build the sanitizers), run:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% cd llvm/projects
|
||||
% git clone http://llvm.org/git/compiler-rt.git
|
||||
% git clone https://git.llvm.org/git/compiler-rt.git/
|
||||
|
||||
If you want to check out libomp (required for OpenMP support), run:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% cd llvm/projects
|
||||
% git clone http://llvm.org/git/openmp.git
|
||||
% git clone https://git.llvm.org/git/openmp.git/
|
||||
|
||||
If you want to check out libcxx and libcxxabi (optional), run:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% cd llvm/projects
|
||||
% git clone http://llvm.org/git/libcxx.git
|
||||
% git clone http://llvm.org/git/libcxxabi.git
|
||||
% git clone https://git.llvm.org/git/libcxx.git/
|
||||
% git clone https://git.llvm.org/git/libcxxabi.git/
|
||||
|
||||
If you want to check out the Test Suite Source Code (optional), run:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% cd llvm/projects
|
||||
% git clone http://llvm.org/git/test-suite.git
|
||||
% git clone https://git.llvm.org/git/test-suite.git/
|
||||
|
||||
Since the upstream repository is in Subversion, you should use ``git
|
||||
pull --rebase`` instead of ``git pull`` to avoid generating a non-linear history
|
||||
@ -622,7 +607,7 @@ To set up clone from which you can submit code using ``git-svn``, run:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% git clone http://llvm.org/git/llvm.git
|
||||
% git clone https://git.llvm.org/git/llvm.git/
|
||||
% cd llvm
|
||||
% git svn init https://llvm.org/svn/llvm-project/llvm/trunk --username=<username>
|
||||
% git config svn-remote.svn.fetch :refs/remotes/origin/master
|
||||
@ -630,7 +615,7 @@ To set up clone from which you can submit code using ``git-svn``, run:
|
||||
|
||||
# If you have clang too:
|
||||
% cd tools
|
||||
% git clone http://llvm.org/git/clang.git
|
||||
% git clone https://git.llvm.org/git/clang.git/
|
||||
% cd clang
|
||||
% git svn init https://llvm.org/svn/llvm-project/cfe/trunk --username=<username>
|
||||
% git config svn-remote.svn.fetch :refs/remotes/origin/master
|
||||
@ -1010,7 +995,7 @@ Directory Layout
|
||||
================
|
||||
|
||||
One useful source of information about the LLVM source base is the LLVM `doxygen
|
||||
<http://www.doxygen.org/>`_ documentation available at
|
||||
<http://www.doxygen.org/>`_ documentation available at
|
||||
`<http://llvm.org/doxygen/>`_. The following is a brief introduction to code
|
||||
layout:
|
||||
|
||||
@ -1026,13 +1011,13 @@ Public header files exported from the LLVM library. The three main subdirectorie
|
||||
|
||||
``llvm/include/llvm``
|
||||
|
||||
All LLVM-specific header files, and subdirectories for different portions of
|
||||
All LLVM-specific header files, and subdirectories for different portions of
|
||||
LLVM: ``Analysis``, ``CodeGen``, ``Target``, ``Transforms``, etc...
|
||||
|
||||
``llvm/include/llvm/Support``
|
||||
|
||||
Generic support libraries provided with LLVM but not necessarily specific to
|
||||
LLVM. For example, some C++ STL utilities and a Command Line option processing
|
||||
Generic support libraries provided with LLVM but not necessarily specific to
|
||||
LLVM. For example, some C++ STL utilities and a Command Line option processing
|
||||
library store header files here.
|
||||
|
||||
``llvm/include/llvm/Config``
|
||||
@ -1045,12 +1030,12 @@ Public header files exported from the LLVM library. The three main subdirectorie
|
||||
``llvm/lib``
|
||||
------------
|
||||
|
||||
Most source files are here. By putting code in libraries, LLVM makes it easy to
|
||||
Most source files are here. By putting code in libraries, LLVM makes it easy to
|
||||
share code among the `tools`_.
|
||||
|
||||
``llvm/lib/IR/``
|
||||
|
||||
Core LLVM source files that implement core classes like Instruction and
|
||||
Core LLVM source files that implement core classes like Instruction and
|
||||
BasicBlock.
|
||||
|
||||
``llvm/lib/AsmParser/``
|
||||
@ -1063,23 +1048,23 @@ share code among the `tools`_.
|
||||
|
||||
``llvm/lib/Analysis/``
|
||||
|
||||
A variety of program analyses, such as Call Graphs, Induction Variables,
|
||||
A variety of program analyses, such as Call Graphs, Induction Variables,
|
||||
Natural Loop Identification, etc.
|
||||
|
||||
``llvm/lib/Transforms/``
|
||||
|
||||
IR-to-IR program transformations, such as Aggressive Dead Code Elimination,
|
||||
Sparse Conditional Constant Propagation, Inlining, Loop Invariant Code Motion,
|
||||
IR-to-IR program transformations, such as Aggressive Dead Code Elimination,
|
||||
Sparse Conditional Constant Propagation, Inlining, Loop Invariant Code Motion,
|
||||
Dead Global Elimination, and many others.
|
||||
|
||||
``llvm/lib/Target/``
|
||||
|
||||
Files describing target architectures for code generation. For example,
|
||||
Files describing target architectures for code generation. For example,
|
||||
``llvm/lib/Target/X86`` holds the X86 machine description.
|
||||
|
||||
``llvm/lib/CodeGen/``
|
||||
|
||||
The major parts of the code generator: Instruction Selector, Instruction
|
||||
The major parts of the code generator: Instruction Selector, Instruction
|
||||
Scheduling, and Register Allocation.
|
||||
|
||||
``llvm/lib/MC/``
|
||||
@ -1088,7 +1073,7 @@ share code among the `tools`_.
|
||||
|
||||
``llvm/lib/ExecutionEngine/``
|
||||
|
||||
Libraries for directly executing bitcode at runtime in interpreted and
|
||||
Libraries for directly executing bitcode at runtime in interpreted and
|
||||
JIT-compiled scenarios.
|
||||
|
||||
``llvm/lib/Support/``
|
||||
@ -1099,7 +1084,7 @@ share code among the `tools`_.
|
||||
``llvm/projects``
|
||||
-----------------
|
||||
|
||||
Projects not strictly part of LLVM but shipped with LLVM. This is also the
|
||||
Projects not strictly part of LLVM but shipped with LLVM. This is also the
|
||||
directory for creating your own LLVM-based projects which leverage the LLVM
|
||||
build system.
|
||||
|
||||
@ -1112,8 +1097,8 @@ are intended to run quickly and cover a lot of territory without being exhaustiv
|
||||
``test-suite``
|
||||
--------------
|
||||
|
||||
A comprehensive correctness, performance, and benchmarking test suite for LLVM.
|
||||
Comes in a separate Subversion module because not every LLVM user is interested
|
||||
A comprehensive correctness, performance, and benchmarking test suite for LLVM.
|
||||
Comes in a separate Subversion module because not every LLVM user is interested
|
||||
in such a comprehensive suite. For details see the :doc:`Testing Guide
|
||||
<TestingGuide>` document.
|
||||
|
||||
@ -1194,7 +1179,7 @@ because they are code generators for parts of the infrastructure.
|
||||
|
||||
``emacs/``
|
||||
|
||||
Emacs and XEmacs syntax highlighting for LLVM assembly files and TableGen
|
||||
Emacs and XEmacs syntax highlighting for LLVM assembly files and TableGen
|
||||
description files. See the ``README`` for information on using them.
|
||||
|
||||
``getsrcs.sh``
|
||||
|
@ -76,6 +76,11 @@ Here's the short story for getting up and running quickly with LLVM:
|
||||
|
||||
* With anonymous Subversion access:
|
||||
|
||||
*Note:* some regression tests require Unix-style line ending (``\n``). To
|
||||
pass all regression tests, please add two lines *enable-auto-props = yes*
|
||||
and *\* = svn:mime-type=application/octet-stream* to
|
||||
``C:\Users\<username>\AppData\Roaming\Subversion\config``.
|
||||
|
||||
1. ``cd <where-you-want-llvm-to-live>``
|
||||
2. ``svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm``
|
||||
3. ``cd llvm``
|
||||
|
@ -304,10 +304,13 @@ As opposed to SelectionDAG, there are no legalization phases. In particular,
|
||||
Legalization is iterative, and all state is contained in GMIR. To maintain the
|
||||
validity of the intermediate code, instructions are introduced:
|
||||
|
||||
* ``G_SEQUENCE`` --- concatenate multiple registers into a single wider
|
||||
register.
|
||||
* ``G_MERGE_VALUES`` --- concatenate multiple registers of the same
|
||||
size into a single wider register.
|
||||
|
||||
* ``G_EXTRACT`` --- extract multiple registers (as contiguous sequences of bits)
|
||||
* ``G_UNMERGE_VALUES`` --- extract multiple registers of the same size
|
||||
from a single wider register.
|
||||
|
||||
* ``G_EXTRACT`` --- extract a simple register (as contiguous sequences of bits)
|
||||
from a single wider register.
|
||||
|
||||
As they are expected to be temporary byproducts of the legalization process,
|
||||
@ -500,16 +503,69 @@ The simple API consists of:
|
||||
This target-provided method is responsible for mutating (or replacing) a
|
||||
possibly-generic MI into a fully target-specific equivalent.
|
||||
It is also responsible for doing the necessary constraining of gvregs into the
|
||||
appropriate register classes.
|
||||
appropriate register classes as well as passing through COPY instructions to
|
||||
the register allocator.
|
||||
|
||||
The ``InstructionSelector`` can fold other instructions into the selected MI,
|
||||
by walking the use-def chain of the vreg operands.
|
||||
As GlobalISel is Global, this folding can occur across basic blocks.
|
||||
|
||||
``TODO``:
|
||||
Currently, the Select pass is implemented with hand-written c++, similar to
|
||||
FastISel, rather than backed by tblgen'erated pattern-matching.
|
||||
We intend to eventually reuse SelectionDAG patterns.
|
||||
SelectionDAG Rule Imports
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
TableGen will import SelectionDAG rules and provide the following function to
|
||||
execute them:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
bool selectImpl(MachineInstr &MI)
|
||||
|
||||
The ``--stats`` option can be used to determine what proportion of rules were
|
||||
successfully imported. The easiest way to use this is to copy the
|
||||
``-gen-globalisel`` tablegen command from ``ninja -v`` and modify it.
|
||||
|
||||
Similarly, the ``--warn-on-skipped-patterns`` option can be used to obtain the
|
||||
reasons that rules weren't imported. This can be used to focus on the most
|
||||
important rejection reasons.
|
||||
|
||||
PatLeaf Predicates
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
PatLeafs cannot be imported because their C++ is implemented in terms of
|
||||
``SDNode`` objects. PatLeafs that handle immediate predicates should be
|
||||
replaced by ``ImmLeaf``, ``IntImmLeaf``, or ``FPImmLeaf`` as appropriate.
|
||||
|
||||
There's no standard answer for other PatLeafs. Some standard predicates have
|
||||
been baked into TableGen but this should not generally be done.
|
||||
|
||||
Custom SDNodes
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
Custom SDNodes should be mapped to Target Pseudos using ``GINodeEquiv``. This
|
||||
will cause the instruction selector to import them but you will also need to
|
||||
ensure the target pseudo is introduced to the MIR before the instruction
|
||||
selector. Any preceeding pass is suitable but the legalizer will be a
|
||||
particularly common choice.
|
||||
|
||||
ComplexPatterns
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
ComplexPatterns cannot be imported because their C++ is implemented in terms of
|
||||
``SDNode`` objects. GlobalISel versions should be defined with
|
||||
``GIComplexOperandMatcher`` and mapped to ComplexPattern with
|
||||
``GIComplexPatternEquiv``.
|
||||
|
||||
The following predicates are useful for porting ComplexPattern:
|
||||
|
||||
* isBaseWithConstantOffset() - Check for base+offset structures
|
||||
* isOperandImmEqual() - Check for a particular constant
|
||||
* isObviouslySafeToFold() - Check for reasons an instruction can't be sunk and folded into another.
|
||||
|
||||
There are some important points for the C++ implementation:
|
||||
|
||||
* Don't modify MIR in the predicate
|
||||
* Renderer lambdas should capture by value to avoid use-after-free. They will be used after the predicate returns.
|
||||
* Only create instructions in a renderer lambda. GlobalISel won't clean up things you create but don't use.
|
||||
|
||||
|
||||
.. _maintainability:
|
||||
@ -633,5 +689,14 @@ Additionally:
|
||||
|
||||
* ``TargetPassConfig`` --- create the passes constituting the pipeline,
|
||||
including additional passes not included in the :ref:`pipeline`.
|
||||
* ``GISelAccessor`` --- setup the various subtarget-provided classes, with a
|
||||
graceful fallback to no-op when GlobalISel isn't enabled.
|
||||
|
||||
.. _other_resources:
|
||||
|
||||
Resources
|
||||
=========
|
||||
|
||||
* `Global Instruction Selection - A Proposal by Quentin Colombet @LLVMDevMeeting 2015 <https://www.youtube.com/watch?v=F6GGbYtae3g>`_
|
||||
* `Global Instruction Selection - Status by Quentin Colombet, Ahmed Bougacha, and Tim Northover @LLVMDevMeeting 2016 <https://www.youtube.com/watch?v=6tfb344A7w8>`_
|
||||
* `GlobalISel - LLVM's Latest Instruction Selection Framework by Diana Picus @FOSDEM17 <https://www.youtube.com/watch?v=d6dF6E4BPeU>`_
|
||||
* GlobalISel: Past, Present, and Future by Quentin Colombet and Ahmed Bougacha @LLVMDevMeeting 2017
|
||||
* Head First into GlobalISel by Daniel Sanders, Aditya Nandakumar, and Justin Bogner @LLVMDevMeeting 2017
|
||||
|
201
docs/HowToCrossCompileBuiltinsOnArm.rst
Normal file
201
docs/HowToCrossCompileBuiltinsOnArm.rst
Normal file
@ -0,0 +1,201 @@
|
||||
===================================================================
|
||||
How to Cross Compile Compiler-rt Builtins For Arm
|
||||
===================================================================
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
This document contains information about building and testing the builtins part
|
||||
of compiler-rt for an Arm target, from an x86_64 Linux machine.
|
||||
|
||||
While this document concentrates on Arm and Linux the general principles should
|
||||
apply to other targets supported by compiler-rt. Further contributions for other
|
||||
targets are welcome.
|
||||
|
||||
The instructions in this document depend on libraries and programs external to
|
||||
LLVM, there are many ways to install and configure these dependencies so you
|
||||
may need to adapt the instructions here to fit your own local situation.
|
||||
|
||||
Prerequisites
|
||||
=============
|
||||
|
||||
In this use case we'll be using CMake on a Debian-based Linux system,
|
||||
cross-compiling from an x86_64 host to a hard-float Armv7-A target. We'll be
|
||||
using as many of the LLVM tools as we can, but it is possible to use GNU
|
||||
equivalents.
|
||||
|
||||
* ``A build of LLVM/clang for the llvm-tools and llvm-config``
|
||||
* ``The qemu-arm user mode emulator``
|
||||
* ``An arm-linux-gnueabihf sysroot``
|
||||
|
||||
See https://compiler-rt.llvm.org/ for more information about the dependencies
|
||||
on clang and LLVM.
|
||||
|
||||
``qemu-arm`` should be available as a package for your Linux distribution.
|
||||
|
||||
The most complicated of the prequisites to satisfy is the arm-linux-gnueabihf
|
||||
sysroot. The :doc:`HowToCrossCompileLLVM` has information about how to use the
|
||||
Linux distributions multiarch support to fulfill the dependencies for building
|
||||
LLVM. Alternatively, as building and testing just the compiler-rt builtins
|
||||
requires fewer dependencies than LLVM, it is possible to use the Linaro
|
||||
arm-linux-gnueabihf gcc installation as our sysroot.
|
||||
|
||||
Building compiler-rt builtins for Arm
|
||||
=====================================
|
||||
We will be doing a standalone build of compiler-rt using the following cmake
|
||||
options.
|
||||
|
||||
* ``path/to/llvm/projects/compiler-rt``
|
||||
* ``-DCOMPILER_RT_BUILD_BUILTINS=ON``
|
||||
* ``-DCOMPILER_RT_BUILD_SANITIZERS=OFF``
|
||||
* ``-DCOMPILER_RT_BUILD_XRAY=OFF``
|
||||
* ``-DCOMPILER_RT_BUILD_LIBFUZZER=OFF``
|
||||
* ``-DCOMPILER_RT_BUILD_PROFILE=OFF``
|
||||
* ``-DCMAKE_C_COMPILER=/path/to/clang``
|
||||
* ``-DCMAKE_AR=/path/to/llvm-ar``
|
||||
* ``-DCMAKE_NM=/path/to/llvm-nm``
|
||||
* ``-DCMAKE_RANLIB=/path/to/llvm-ranlib``
|
||||
* ``-DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=lld"``
|
||||
* ``-DCMAKE_C_COMPILER_TARGET="arm-linux-gnueabihf"``
|
||||
* ``-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON``
|
||||
* ``-DLLVM_CONFIG_PATH=/path/to/llvm-config``
|
||||
* ``-DCMAKE_C_FLAGS="build-c-flags"``
|
||||
|
||||
The build-c-flags need to be sufficient to pass the C-make compiler check and
|
||||
to compile compiler-rt. When using a GCC 7 Linaro arm-linux-gnueabihf
|
||||
installation the following flags are needed:
|
||||
|
||||
* ``--target=arm-linux-gnueabihf``
|
||||
* ``--march=armv7a``
|
||||
* ``--gcc-toolchain=/path/to/dir/toolchain``
|
||||
* ``--sysroot=/path/to/toolchain/arm-linux-gnueabihf/libc``
|
||||
|
||||
Depending on how your sysroot is laid out, you may not need ``--gcc-toolchain``.
|
||||
For example if you have added armhf as an architecture using your Linux
|
||||
distributions multiarch support then you should be able to use ``--sysroot=/``.
|
||||
|
||||
Once cmake has completed the builtins can be built with ``ninja builtins``
|
||||
|
||||
Testing compiler-rt builtins using qemu-arm
|
||||
===========================================
|
||||
To test the builtins library we need to add a few more cmake flags to enable
|
||||
testing and set up the compiler and flags for test case. We must also tell
|
||||
cmake that we wish to run the tests on ``qemu-arm``.
|
||||
|
||||
* ``-DCOMPILER_RT_EMULATOR="qemu-arm -L /path/to/armhf/sysroot``
|
||||
* ``-DCOMPILER_RT_INCLUDE_TESTS=ON``
|
||||
* ``-DCOMPILER_RT_TEST_COMPILER="/path/to/clang"``
|
||||
* ``-DCOMPILER_RT_TEST_COMPILER_CFLAGS="test-c-flags"``
|
||||
|
||||
The ``/path/to/armhf/sysroot`` should be the same as the one passed to
|
||||
``--sysroot`` in the "build-c-flags".
|
||||
|
||||
The "test-c-flags" can be the same as the "build-c-flags", with the addition
|
||||
of ``"-fuse-ld=lld`` if you wish to use lld to link the tests.
|
||||
|
||||
Once cmake has completed the tests can be built and run using
|
||||
``ninja check-builtins``
|
||||
|
||||
Modifications for other Targets
|
||||
===============================
|
||||
|
||||
Arm Soft-Float Target
|
||||
---------------------
|
||||
The instructions for the Arm hard-float target can be used for the soft-float
|
||||
target by substituting soft-float equivalents for the sysroot and target. The
|
||||
target to use is:
|
||||
|
||||
* ``-DCMAKE_C_COMPILER_TARGET=arm-linux-gnueabi``
|
||||
|
||||
Depending on whether you want to use floating point instructions or not you
|
||||
may need extra c-flags such as ``-mfloat-abi=softfp`` for use of floating-point
|
||||
instructions, and ``-mfloat-abi=soft -mfpu=none`` for software floating-point
|
||||
emulation.
|
||||
|
||||
AArch64 Target
|
||||
--------------
|
||||
The instructions for Arm can be used for AArch64 by substituting AArch64
|
||||
equivalents for the sysroot, emulator and target.
|
||||
|
||||
* ``-DCMAKE_C_COMPILER_TARGET=aarch64-linux-gnu``
|
||||
* ``-DCOMPILER_RT_EMULATOR="qemu-aarch64 -L /path/to/aarch64/sysroot``
|
||||
|
||||
The CMAKE_C_FLAGS and COMPILER_RT_TEST_COMPILER_CFLAGS may also need:
|
||||
``"--sysroot=/path/to/aarch64/sysroot --gcc-toolchain=/path/to/gcc-toolchain"``
|
||||
|
||||
Armv6-m, Armv7-m and Armv7E-M targets
|
||||
-------------------------------------
|
||||
If you wish to build, but not test compiler-rt for Armv6-M, Armv7-M or Armv7E-M
|
||||
then the easiest way is to use the BaremetalARM.cmake recipe in
|
||||
clang/cmake/caches.
|
||||
|
||||
You will need a bare metal sysroot such as that provided by the GNU ARM
|
||||
Embedded toolchain.
|
||||
|
||||
The libraries can be built with the cmake options:
|
||||
|
||||
* ``-DBAREMETAL_ARMV6M_SYSROOT=/path/to/bare/metal/sysroot``
|
||||
* ``-DBAREMETAL_ARMV7M_SYSROOT=/path/to/bare/metal/sysroot``
|
||||
* ``-DBAREMETAL_ARMV7EM_SYSROOT=/path/to/bare/metal/sysroot``
|
||||
* ``-C /path/to/llvm/source/tools/clang/cmake/caches/BaremetalARM.cmake``
|
||||
|
||||
**Note** that for the recipe to work the compiler-rt source must be checked out
|
||||
into the directory llvm/runtimes and not llvm/projects.
|
||||
|
||||
To build and test the libraries using a similar method to Armv7-A is possible
|
||||
but more difficult. The main problems are:
|
||||
|
||||
* There isn't a ``qemu-arm`` user-mode emulator for bare-metal systems. The ``qemu-system-arm`` can be used but this is significantly more difficult to setup.
|
||||
* The target to compile compiler-rt have the suffix -none-eabi. This uses the BareMetal driver in clang and by default won't find the libraries needed to pass the cmake compiler check.
|
||||
|
||||
As the Armv6-M, Armv7-M and Armv7E-M builds of compiler-rt only use instructions
|
||||
that are supported on Armv7-A we can still get most of the value of running the
|
||||
tests using the same ``qemu-arm`` that we used for Armv7-A by building and
|
||||
running the test cases for Armv7-A but using the builtins compiled for
|
||||
Armv6-M, Armv7-M or Armv7E-M. This will not catch instructions that are
|
||||
supported on Armv7-A but not Armv6-M, Armv7-M and Armv7E-M.
|
||||
|
||||
To get the cmake compile test to pass the libraries needed to successfully link
|
||||
the test application will need to be manually added to ``CMAKE_CFLAGS``.
|
||||
Alternatively if you are using version 3.6 or above of cmake you can use
|
||||
``CMAKE_TRY_COMPILE_TARGET=STATIC_LIBRARY`` to skip the link step.
|
||||
|
||||
* ``-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY``
|
||||
* ``-DCOMPILER_RT_OS_DIR="baremetal"``
|
||||
* ``-DCOMPILER_RT_BUILD_BUILTINS=ON``
|
||||
* ``-DCOMPILER_RT_BUILD_SANITIZERS=OFF``
|
||||
* ``-DCOMPILER_RT_BUILD_XRAY=OFF``
|
||||
* ``-DCOMPILER_RT_BUILD_LIBFUZZER=OFF``
|
||||
* ``-DCOMPILER_RT_BUILD_PROFILE=OFF``
|
||||
* ``-DCMAKE_C_COMPILER=${host_install_dir}/bin/clang``
|
||||
* ``-DCMAKE_C_COMPILER_TARGET="your *-none-eabi target"``
|
||||
* ``-DCMAKE_AR=/path/to/llvm-ar``
|
||||
* ``-DCMAKE_NM=/path/to/llvm-nm``
|
||||
* ``-DCMAKE_RANLIB=/path/to/llvm-ranlib``
|
||||
* ``-DCOMPILER_RT_BAREMETAL_BUILD=ON``
|
||||
* ``-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON``
|
||||
* ``-DLLVM_CONFIG_PATH=/path/to/llvm-config``
|
||||
* ``-DCMAKE_C_FLAGS="build-c-flags"``
|
||||
* ``-DCMAKE_ASM_FLAGS="${arm_cflags}"``
|
||||
* ``-DCOMPILER_RT_EMULATOR="qemu-arm -L /path/to/armv7-A/sysroot"``
|
||||
* ``-DCOMPILER_RT_INCLUDE_TESTS=ON``
|
||||
* ``-DCOMPILER_RT_TEST_COMPILER="/path/to/clang"``
|
||||
* ``-DCOMPILER_RT_TEST_COMPILER_CFLAGS="test-c-flags"``
|
||||
|
||||
The Armv6-M builtins will use the soft-float ABI. When compiling the tests for
|
||||
Armv7-A we must include ``"-mthumb -mfloat-abi=soft -mfpu=none"`` in the
|
||||
test-c-flags. We must use an Armv7-A soft-float abi sysroot for ``qemu-arm``.
|
||||
|
||||
Unfortunately at time of writing the Armv7-M and Armv7E-M builds of
|
||||
compiler-rt will always include assembler files including floating point
|
||||
instructions. This means that building for a cpu without a floating point unit
|
||||
requires something like removing the arm_Thumb1_VFPv2_SOURCES from the
|
||||
arm_Thumb1_SOURCES in builtins/CMakeLists.txt. The float-abi of the compiler-rt
|
||||
library must be matched by the float abi of the Armv7-A sysroot used by
|
||||
qemu-arm.
|
||||
|
||||
Depending on the linker used for the test cases you may encounter BuildAttribute
|
||||
mismatches between the M-profile objects from compiler-rt and the A-profile
|
||||
objects from the test. The lld linker does not check the BuildAttributes so it
|
||||
can be used to link the tests by adding -fuse-ld=lld to the
|
||||
``COMPILER_RT_TEST_COMPILER_CFLAGS``.
|
@ -256,6 +256,28 @@ If a bug can't be reproduced, or stops being a blocker, it should be removed
|
||||
from the Meta and its priority decreased to *normal*. Debugging can continue,
|
||||
but on trunk.
|
||||
|
||||
Merge Requests
|
||||
--------------
|
||||
|
||||
You can use any of the following methods to request that a revision from trunk
|
||||
be merged into a release branch:
|
||||
|
||||
#. Use the ``utils/release/merge-request.sh`` script which will automatically
|
||||
file a bug_ requesting that the patch be merged. e.g. To request revision
|
||||
12345 be merged into the branch for the 5.0.1 release:
|
||||
``llvm.src/utils/release/merge-request.sh -stable-version 5.0 -r 12345 -user bugzilla@example.com``
|
||||
|
||||
#. Manually file a bug_ with the subject: "Merge r12345 into the X.Y branch",
|
||||
enter the commit(s) that you want merged in the "Fixed by Commit(s)" and mark
|
||||
it as a blocker of the current release bug. Release bugs are given aliases
|
||||
in the form of release-x.y.z, so to mark a bug as a blocker for the 5.0.1
|
||||
release, just enter release-5.0.1 in the "Blocks" field.
|
||||
|
||||
#. Reply to the commit email on llvm-commits for the revision to merge and cc
|
||||
the release manager.
|
||||
|
||||
.. _bug: https://bugs.llvm.org/
|
||||
|
||||
Release Patch Rules
|
||||
-------------------
|
||||
|
||||
|
493
docs/LangRef.rst
493
docs/LangRef.rst
File diff suppressed because it is too large
Load Diff
@ -109,6 +109,11 @@ G
|
||||
Garbage Collection. The practice of using reachability analysis instead of
|
||||
explicit memory management to reclaim unused memory.
|
||||
|
||||
**GEP**
|
||||
``GetElementPtr``. An LLVM IR instruction that is used to get the address
|
||||
of a subelement of an aggregate data structure. It is documented in detail
|
||||
`here <http://llvm.org/docs/GetElementPtr.html>`_.
|
||||
|
||||
**GVN**
|
||||
Global Value Numbering. GVN is a pass that partitions values computed by a
|
||||
function into congruence classes. Values ending up in the same congruence
|
||||
|
@ -24,28 +24,9 @@ Versions
|
||||
========
|
||||
|
||||
LibFuzzer is under active development so you will need the current
|
||||
(or at least a very recent) version of the Clang compiler.
|
||||
(or at least a very recent) version of the Clang compiler (see `building Clang from trunk`_)
|
||||
|
||||
(If `building Clang from trunk`_ is too time-consuming or difficult, then
|
||||
the Clang binaries that the Chromium developers build are likely to be
|
||||
fairly recent:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
mkdir TMP_CLANG
|
||||
cd TMP_CLANG
|
||||
git clone https://chromium.googlesource.com/chromium/src/tools/clang
|
||||
cd ..
|
||||
TMP_CLANG/clang/scripts/update.py
|
||||
|
||||
This installs the Clang binary as
|
||||
``./third_party/llvm-build/Release+Asserts/bin/clang``)
|
||||
|
||||
The libFuzzer code resides in the LLVM repository, and requires a recent Clang
|
||||
compiler to build (and is used to `fuzz various parts of LLVM itself`_).
|
||||
However the fuzzer itself does not (and should not) depend on any part of LLVM
|
||||
infrastructure and can be used for other projects without requiring the rest
|
||||
of LLVM.
|
||||
Refer to https://releases.llvm.org/5.0.0/docs/LibFuzzer.html for documentation on the older version.
|
||||
|
||||
|
||||
Getting Started
|
||||
@ -90,40 +71,33 @@ Some important things to remember about fuzz targets:
|
||||
Fuzzer Usage
|
||||
------------
|
||||
|
||||
Very recent versions of Clang (> April 20 2017) include libFuzzer,
|
||||
and no installation is necessary.
|
||||
In order to fuzz your binary, use the `-fsanitize=fuzzer` flag during the compilation::
|
||||
Recent versions of Clang (starting from 6.0) include libFuzzer, and no extra installation is necessary.
|
||||
|
||||
clang -fsanitize=fuzzer,address mytarget.c
|
||||
In order to build your fuzzer binary, use the `-fsanitize=fuzzer` flag during the
|
||||
compilation and linking. In most cases you may want to combine libFuzzer with
|
||||
AddressSanitizer_ (ASAN), UndefinedBehaviorSanitizer_ (UBSAN), or both::
|
||||
|
||||
Otherwise, build the libFuzzer library as a static archive, without any sanitizer
|
||||
options. Note that the libFuzzer library contains the ``main()`` function:
|
||||
clang -g -O1 -fsanitize=fuzzer mytarget.c # Builds the fuzz target w/o sanitizers
|
||||
clang -g -O1 -fsanitize=fuzzer,address mytarget.c # Builds the fuzz target with ASAN
|
||||
clang -g -O1 -fsanitize=fuzzer,signed-integer-overflow mytarget.c # Builds the fuzz target with a part of UBSAN
|
||||
|
||||
.. code-block:: console
|
||||
This will perform the necessary instrumentation, as well as linking with the libFuzzer library.
|
||||
Note that ``-fsanitize=fuzzer`` links in the libFuzzer's ``main()`` symbol.
|
||||
|
||||
svn co http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer # or git clone https://chromium.googlesource.com/chromium/llvm-project/llvm/lib/Fuzzer
|
||||
./Fuzzer/build.sh # Produces libFuzzer.a
|
||||
If modifying ``CFLAGS`` of a large project, which also compiles executables
|
||||
requiring their own ``main`` symbol, it may be desirable to request just the
|
||||
instrumentation without linking::
|
||||
|
||||
Then build the fuzzing target function and the library under test using
|
||||
the SanitizerCoverage_ option, which instruments the code so that the fuzzer
|
||||
can retrieve code coverage information (to guide the fuzzing). Linking with
|
||||
the libFuzzer code then gives a fuzzer executable.
|
||||
clang -fsanitize=fuzzer-no-link mytarget.c
|
||||
|
||||
You should also enable one or more of the *sanitizers*, which help to expose
|
||||
latent bugs by making incorrect behavior generate errors at runtime:
|
||||
Then libFuzzer can be linked to the desired driver by passing in
|
||||
``-fsanitize=fuzzer`` during the linking stage.
|
||||
|
||||
- AddressSanitizer_ (ASAN) detects memory access errors. Use `-fsanitize=address`.
|
||||
- UndefinedBehaviorSanitizer_ (UBSAN) detects the use of various features of C/C++ that are explicitly
|
||||
listed as resulting in undefined behavior. Use `-fsanitize=undefined -fno-sanitize-recover=undefined`
|
||||
or any individual UBSAN check, e.g. `-fsanitize=signed-integer-overflow -fno-sanitize-recover=undefined`.
|
||||
You may combine ASAN and UBSAN in one build.
|
||||
- MemorySanitizer_ (MSAN) detects uninitialized reads: code whose behavior relies on memory
|
||||
contents that have not been initialized to a specific value. Use `-fsanitize=memory`.
|
||||
MSAN can not be combined with other sanirizers and should be used as a seprate build.
|
||||
Using MemorySanitizer_ (MSAN) with libFuzzer is possible too, but tricky.
|
||||
The exact details are out of scope, we expect to simplify this in future
|
||||
versions.
|
||||
|
||||
Finally, link with ``libFuzzer.a``::
|
||||
|
||||
clang -fsanitize-coverage=trace-pc-guard -fsanitize=address your_lib.cc fuzz_target.cc libFuzzer.a -o my_fuzzer
|
||||
.. _libfuzzer-corpus:
|
||||
|
||||
Corpus
|
||||
------
|
||||
@ -161,7 +135,6 @@ Only the inputs that trigger new coverage will be added to the first corpus.
|
||||
|
||||
./my_fuzzer -merge=1 CURRENT_CORPUS_DIR NEW_POTENTIALLY_INTERESTING_INPUTS_DIR
|
||||
|
||||
|
||||
Running
|
||||
-------
|
||||
|
||||
@ -208,6 +181,33 @@ running with ``-jobs=30`` on a 12-core machine would run 6 workers by default,
|
||||
with each worker averaging 5 bugs by completion of the entire process.
|
||||
|
||||
|
||||
Resuming merge
|
||||
--------------
|
||||
|
||||
Merging large corpora may be time consuming, and it is often desirable to do it
|
||||
on preemptable VMs, where the process may be killed at any time.
|
||||
In order to seamlessly resume the merge, use the ``-merge_control_file`` flag
|
||||
and use ``killall -SIGUSR1 /path/to/fuzzer/binary`` to stop the merge gracefully. Example:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% rm -f SomeLocalPath
|
||||
% ./my_fuzzer CORPUS1 CORPUS2 -merge=1 -merge_control_file=SomeLocalPath
|
||||
...
|
||||
MERGE-INNER: using the control file 'SomeLocalPath'
|
||||
...
|
||||
# While this is running, do `killall -SIGUSR1 my_fuzzer` in another console
|
||||
==9015== INFO: libFuzzer: exiting as requested
|
||||
|
||||
# This will leave the file SomeLocalPath with the partial state of the merge.
|
||||
# Now, you can continue the merge by executing the same command. The merge
|
||||
# will continue from where it has been interrupted.
|
||||
% ./my_fuzzer CORPUS1 CORPUS2 -merge=1 -merge_control_file=SomeLocalPath
|
||||
...
|
||||
MERGE-OUTER: non-empty control file provided: 'SomeLocalPath'
|
||||
MERGE-OUTER: control file ok, 32 files total, first not processed file 20
|
||||
...
|
||||
|
||||
Options
|
||||
=======
|
||||
|
||||
@ -246,6 +246,10 @@ The most important command line options are:
|
||||
the process is treated as a failure case.
|
||||
The limit is checked in a separate thread every second.
|
||||
If running w/o ASAN/MSAN, you may use 'ulimit -v' instead.
|
||||
``-malloc_limit_mb``
|
||||
If non-zero, the fuzzer will exit if the target tries to allocate this
|
||||
number of Mb with one malloc call.
|
||||
If zero (default) same limit as rss_limit_mb is applied.
|
||||
``-timeout_exitcode``
|
||||
Exit code (default 77) used if libFuzzer reports a timeout.
|
||||
``-error_exitcode``
|
||||
@ -257,6 +261,10 @@ The most important command line options are:
|
||||
If set to 1, any corpus inputs from the 2nd, 3rd etc. corpus directories
|
||||
that trigger new code coverage will be merged into the first corpus
|
||||
directory. Defaults to 0. This flag can be used to minimize a corpus.
|
||||
``-merge_control_file``
|
||||
Specify a control file used for the merge proccess.
|
||||
If a merge process gets killed it tries to leave this file in a state
|
||||
suitable for resuming the merge. By default a temporary file will be used.
|
||||
``-minimize_crash``
|
||||
If 1, minimizes the provided crash input.
|
||||
Use with -runs=N or -max_total_time=N to limit the number of attempts.
|
||||
@ -278,6 +286,9 @@ The most important command line options are:
|
||||
``-use_counters``
|
||||
Use `coverage counters`_ to generate approximate counts of how often code
|
||||
blocks are hit; defaults to 1.
|
||||
``-reduce_inputs``
|
||||
Try to reduce the size of inputs while preserving their full feature sets;
|
||||
defaults to 1.
|
||||
``-use_value_profile``
|
||||
Use `value profile`_ to guide corpus expansion; defaults to 0.
|
||||
``-only_ascii``
|
||||
@ -305,10 +316,6 @@ The most important command line options are:
|
||||
- 1 : close ``stdout``
|
||||
- 2 : close ``stderr``
|
||||
- 3 : close both ``stdout`` and ``stderr``.
|
||||
``-print_coverage``
|
||||
If 1, print coverage information as text at exit.
|
||||
``-dump_coverage``
|
||||
If 1, dump coverage information as a .sancov file at exit.
|
||||
|
||||
For the full list of flags run the fuzzer binary with ``-help=1``.
|
||||
|
||||
@ -345,6 +352,9 @@ possible event codes are:
|
||||
``NEW``
|
||||
The fuzzer has created a test input that covers new areas of the code
|
||||
under test. This input will be saved to the primary corpus directory.
|
||||
``REDUCE``
|
||||
The fuzzer has found a better (smaller) input that triggers previously
|
||||
discovered features (set ``-reduce_inputs=0`` to disable).
|
||||
``pulse``
|
||||
The fuzzer has generated 2\ :sup:`n` inputs (generated periodically to reassure
|
||||
the user that the fuzzer is still working).
|
||||
@ -465,7 +475,7 @@ Tracing CMP instructions
|
||||
------------------------
|
||||
|
||||
With an additional compiler flag ``-fsanitize-coverage=trace-cmp``
|
||||
(see SanitizerCoverageTraceDataFlow_)
|
||||
(on by default as part of ``-fsanitize=fuzzer``, see SanitizerCoverageTraceDataFlow_)
|
||||
libFuzzer will intercept CMP instructions and guide mutations based
|
||||
on the arguments of intercepted CMP instructions. This may slow down
|
||||
the fuzzing but is very likely to improve the results.
|
||||
@ -473,7 +483,6 @@ the fuzzing but is very likely to improve the results.
|
||||
Value Profile
|
||||
-------------
|
||||
|
||||
*EXPERIMENTAL*.
|
||||
With ``-fsanitize-coverage=trace-cmp``
|
||||
and extra run-time flag ``-use_value_profile=1`` the fuzzer will
|
||||
collect value profiles for the parameters of compare instructions
|
||||
@ -535,7 +544,7 @@ Periodically restart both fuzzers so that they can use each other's findings.
|
||||
Currently, there is no simple way to run both fuzzing engines in parallel while sharing the same corpus dir.
|
||||
|
||||
You may also use AFL on your target function ``LLVMFuzzerTestOneInput``:
|
||||
see an example `here <https://github.com/llvm-mirror/llvm/blob/master/lib/Fuzzer/afl/afl_driver.cpp>`__.
|
||||
see an example `here <https://github.com/llvm-mirror/compiler-rt/tree/master/lib/fuzzer/afl>`__.
|
||||
|
||||
How good is my fuzzer?
|
||||
----------------------
|
||||
@ -543,28 +552,12 @@ How good is my fuzzer?
|
||||
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:
|
||||
|
||||
.. code-block:: console
|
||||
We recommend to use
|
||||
`Clang Coverage <http://clang.llvm.org/docs/SourceBasedCodeCoverage.html>`_,
|
||||
to visualize and study your code coverage
|
||||
(`example <https://github.com/google/fuzzer-test-suite/blob/master/tutorial/libFuzzerTutorial.md#visualizing-coverage>`_).
|
||||
|
||||
./fuzzer CORPUS_DIR -runs=0 -print_coverage=1
|
||||
|
||||
This will run all tests in the CORPUS_DIR but will not perform any fuzzing.
|
||||
At the end of the process it will print text describing what code has been covered and what hasn't.
|
||||
|
||||
Alternatively, use
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
./fuzzer CORPUS_DIR -runs=0 -dump_coverage=1
|
||||
|
||||
which will dump a ``.sancov`` file with coverage information.
|
||||
See SanitizerCoverage_ for details on querying the file using the ``sancov`` tool.
|
||||
|
||||
You may also use other ways to visualize coverage,
|
||||
e.g. using `Clang coverage <http://clang.llvm.org/docs/SourceBasedCodeCoverage.html>`_,
|
||||
but those will require
|
||||
you to rebuild the code with different compiler flags.
|
||||
|
||||
User-supplied mutators
|
||||
----------------------
|
||||
@ -621,75 +614,17 @@ you will eventually run out of RAM (see the ``-rss_limit_mb`` flag).
|
||||
Developing libFuzzer
|
||||
====================
|
||||
|
||||
Building libFuzzer as a part of LLVM project and running its test requires
|
||||
fresh clang as the host compiler and special CMake configuration:
|
||||
LibFuzzer is built as a part of LLVM project by default on macos and Linux.
|
||||
Users of other operating systems can explicitly request compilation using
|
||||
``-DLIBFUZZER_ENABLE=YES`` flag.
|
||||
Tests are run using ``check-fuzzer`` target from the build directory
|
||||
which was configured with ``-DLIBFUZZER_ENABLE_TESTS=ON`` flag.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
cmake -GNinja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DLLVM_USE_SANITIZER=Address -DLLVM_USE_SANITIZE_COVERAGE=YES -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_ASSERTIONS=ON /path/to/llvm
|
||||
ninja check-fuzzer
|
||||
|
||||
|
||||
Fuzzing components of LLVM
|
||||
==========================
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 1
|
||||
|
||||
To build any of the LLVM fuzz targets use the build instructions above.
|
||||
|
||||
clang-format-fuzzer
|
||||
-------------------
|
||||
The inputs are random pieces of C++-like text.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
ninja clang-format-fuzzer
|
||||
mkdir CORPUS_DIR
|
||||
./bin/clang-format-fuzzer CORPUS_DIR
|
||||
|
||||
Optionally build other kinds of binaries (ASan+Debug, MSan, UBSan, etc).
|
||||
|
||||
Tracking bug: https://llvm.org/bugs/show_bug.cgi?id=23052
|
||||
|
||||
clang-fuzzer
|
||||
------------
|
||||
|
||||
The behavior is very similar to ``clang-format-fuzzer``.
|
||||
|
||||
Tracking bug: https://llvm.org/bugs/show_bug.cgi?id=23057
|
||||
|
||||
llvm-as-fuzzer
|
||||
--------------
|
||||
|
||||
Tracking bug: https://llvm.org/bugs/show_bug.cgi?id=24639
|
||||
|
||||
llvm-mc-fuzzer
|
||||
--------------
|
||||
|
||||
This tool fuzzes the MC layer. Currently it is only able to fuzz the
|
||||
disassembler but it is hoped that assembly, and round-trip verification will be
|
||||
added in future.
|
||||
|
||||
When run in dissassembly mode, the inputs are opcodes to be disassembled. The
|
||||
fuzzer will consume as many instructions as possible and will stop when it
|
||||
finds an invalid instruction or runs out of data.
|
||||
|
||||
Please note that the command line interface differs slightly from that of other
|
||||
fuzzers. The fuzzer arguments should follow ``--fuzzer-args`` and should have
|
||||
a single dash, while other arguments control the operation mode and target in a
|
||||
similar manner to ``llvm-mc`` and should have two dashes. For example:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
llvm-mc-fuzzer --triple=aarch64-linux-gnu --disassemble --fuzzer-args -max_len=4 -jobs=10
|
||||
|
||||
Buildbot
|
||||
--------
|
||||
|
||||
A buildbot continuously runs the above fuzzers for LLVM components, with results
|
||||
shown at http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fuzzer .
|
||||
|
||||
FAQ
|
||||
=========================
|
||||
|
||||
@ -748,6 +683,8 @@ network, crypto.
|
||||
|
||||
Trophies
|
||||
========
|
||||
* Thousands of bugs found on OSS-Fuzz: https://opensource.googleblog.com/2017/05/oss-fuzz-five-months-later-and.html
|
||||
|
||||
* GLIBC: https://sourceware.org/glibc/wiki/FuzzingLibc
|
||||
|
||||
* MUSL LIBC: `[1] <http://git.musl-libc.org/cgit/musl/commit/?id=39dfd58417ef642307d90306e1c7e50aaec5a35c>`__ `[2] <http://www.openwall.com/lists/oss-security/2015/03/30/3>`__
|
||||
@ -774,6 +711,8 @@ Trophies
|
||||
|
||||
* `Linux Kernel's BPF verifier <https://github.com/iovisor/bpf-fuzzer>`_
|
||||
|
||||
* `Linux Kernel's Crypto code <https://www.spinics.net/lists/stable/msg199712.html>`_
|
||||
|
||||
* Capstone: `[1] <https://github.com/aquynh/capstone/issues/600>`__ `[2] <https://github.com/aquynh/capstone/commit/6b88d1d51eadf7175a8f8a11b690684443b11359>`__
|
||||
|
||||
* file:`[1] <http://bugs.gw.com/view.php?id=550>`__ `[2] <http://bugs.gw.com/view.php?id=551>`__ `[3] <http://bugs.gw.com/view.php?id=553>`__ `[4] <http://bugs.gw.com/view.php?id=554>`__
|
||||
@ -792,6 +731,8 @@ Trophies
|
||||
|
||||
* `Wireshark <https://bugs.wireshark.org/bugzilla/buglist.cgi?bug_status=UNCONFIRMED&bug_status=CONFIRMED&bug_status=IN_PROGRESS&bug_status=INCOMPLETE&bug_status=RESOLVED&bug_status=VERIFIED&f0=OP&f1=OP&f2=product&f3=component&f4=alias&f5=short_desc&f7=content&f8=CP&f9=CP&j1=OR&o2=substring&o3=substring&o4=substring&o5=substring&o6=substring&o7=matches&order=bug_id%20DESC&query_format=advanced&v2=libfuzzer&v3=libfuzzer&v4=libfuzzer&v5=libfuzzer&v6=libfuzzer&v7=%22libfuzzer%22>`_
|
||||
|
||||
* `QEMU <https://researchcenter.paloaltonetworks.com/2017/09/unit42-palo-alto-networks-discovers-new-qemu-vulnerability/>`_
|
||||
|
||||
.. _pcre2: http://www.pcre.org/
|
||||
.. _AFL: http://lcamtuf.coredump.cx/afl/
|
||||
.. _Radamsa: https://github.com/aoh/radamsa
|
||||
@ -800,7 +741,7 @@ Trophies
|
||||
.. _AddressSanitizer: http://clang.llvm.org/docs/AddressSanitizer.html
|
||||
.. _LeakSanitizer: http://clang.llvm.org/docs/LeakSanitizer.html
|
||||
.. _Heartbleed: http://en.wikipedia.org/wiki/Heartbleed
|
||||
.. _FuzzerInterface.h: https://github.com/llvm-mirror/llvm/blob/master/lib/Fuzzer/FuzzerInterface.h
|
||||
.. _FuzzerInterface.h: https://github.com/llvm-mirror/compiler-rt/blob/master/lib/fuzzer/FuzzerInterface.h
|
||||
.. _3.7.0: http://llvm.org/releases/3.7.0/docs/LibFuzzer.html
|
||||
.. _building Clang from trunk: http://clang.llvm.org/get_started.html
|
||||
.. _MemorySanitizer: http://clang.llvm.org/docs/MemorySanitizer.html
|
||||
@ -809,4 +750,4 @@ Trophies
|
||||
.. _`value profile`: #value-profile
|
||||
.. _`caller-callee pairs`: http://clang.llvm.org/docs/SanitizerCoverage.html#caller-callee-coverage
|
||||
.. _BoringSSL: https://boringssl.googlesource.com/boringssl/
|
||||
.. _`fuzz various parts of LLVM itself`: `Fuzzing components of LLVM`_
|
||||
|
||||
|
@ -121,6 +121,8 @@ Tests are more accessible and future proof when simplified:
|
||||
contains dummy functions (see above). The .mir loader will create the
|
||||
IR functions automatically in this case.
|
||||
|
||||
.. _limitations:
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
@ -238,6 +240,8 @@ in the block's definition:
|
||||
The block's name should be identical to the name of the IR block that this
|
||||
machine block is based on.
|
||||
|
||||
.. _block-references:
|
||||
|
||||
Block References
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
@ -246,13 +250,25 @@ blocks are referenced using the following syntax:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
%bb.<id>[.<name>]
|
||||
%bb.<id>
|
||||
|
||||
Examples:
|
||||
Example:
|
||||
|
||||
.. code-block:: llvm
|
||||
|
||||
%bb.0
|
||||
|
||||
The following syntax is also supported, but the former syntax is preferred for
|
||||
block references:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
%bb.<id>[.<name>]
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: llvm
|
||||
|
||||
%bb.1.then
|
||||
|
||||
Successors
|
||||
@ -418,7 +434,40 @@ immediate machine operand ``-42``:
|
||||
|
||||
%eax = MOV32ri -42
|
||||
|
||||
.. TODO: Describe the CIMM (Rare) and FPIMM immediate operands.
|
||||
An immediate operand is also used to represent a subregister index when the
|
||||
machine instruction has one of the following opcodes:
|
||||
|
||||
- ``EXTRACT_SUBREG``
|
||||
|
||||
- ``INSERT_SUBREG``
|
||||
|
||||
- ``REG_SEQUENCE``
|
||||
|
||||
- ``SUBREG_TO_REG``
|
||||
|
||||
In case this is true, the Machine Operand is printed according to the target.
|
||||
|
||||
For example:
|
||||
|
||||
In AArch64RegisterInfo.td:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
def sub_32 : SubRegIndex<32>;
|
||||
|
||||
If the third operand is an immediate with the value ``15`` (target-dependent
|
||||
value), based on the instruction's opcode and the operand's index the operand
|
||||
will be printed as ``%subreg.sub_32``:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
%1:gpr64 = SUBREG_TO_REG 0, %0, %subreg.sub_32
|
||||
|
||||
For integers > 64bit, we use a special machine operand, ``MO_CImmediate``,
|
||||
which stores the immediate in a ``ConstantInt`` using an ``APInt`` (LLVM's
|
||||
arbitrary precision integers).
|
||||
|
||||
.. TODO: Describe the FPIMM immediate operands.
|
||||
|
||||
.. _register-operands:
|
||||
|
||||
@ -484,6 +533,9 @@ corresponding internal ``llvm::RegState`` representation:
|
||||
* - ``debug-use``
|
||||
- ``RegState::Debug``
|
||||
|
||||
* - ``renamable``
|
||||
- ``RegState::Renamable``
|
||||
|
||||
.. _subregister-indices:
|
||||
|
||||
Subregister Indices
|
||||
@ -501,6 +553,53 @@ lower bits from the 32-bit virtual register 0 to the 8-bit virtual register 1:
|
||||
The names of the subregister indices are target specific, and are typically
|
||||
defined in the target's ``*RegisterInfo.td`` file.
|
||||
|
||||
Constant Pool Indices
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A constant pool index (CPI) operand is printed using its index in the
|
||||
function's ``MachineConstantPool`` and an offset.
|
||||
|
||||
For example, a CPI with the index 1 and offset 8:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
%1:gr64 = MOV64ri %const.1 + 8
|
||||
|
||||
For a CPI with the index 0 and offset -12:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
%1:gr64 = MOV64ri %const.0 - 12
|
||||
|
||||
A constant pool entry is bound to a LLVM IR ``Constant`` or a target-specific
|
||||
``MachineConstantPoolValue``. When serializing all the function's constants the
|
||||
following format is used:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
constants:
|
||||
- id: <index>
|
||||
value: <value>
|
||||
alignment: <alignment>
|
||||
isTargetSpecific: <target-specific>
|
||||
|
||||
where ``<index>`` is a 32-bit unsigned integer, ``<value>`` is a `LLVM IR Constant
|
||||
<https://www.llvm.org/docs/LangRef.html#constants>`_, alignment is a 32-bit
|
||||
unsigned integer, and ``<target-specific>`` is either true or false.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
constants:
|
||||
- id: 0
|
||||
value: 'double 3.250000e+00'
|
||||
alignment: 8
|
||||
- id: 1
|
||||
value: 'g-(LPC0+8)'
|
||||
alignment: 4
|
||||
isTargetSpecific: true
|
||||
|
||||
Global Value Operands
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@ -520,24 +619,91 @@ If the identifier doesn't match the regular expression
|
||||
The unnamed global values are represented using an unsigned numeric value with
|
||||
the '@' prefix, like in the following examples: ``@0``, ``@989``.
|
||||
|
||||
Target-dependent Index Operands
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A target index operand is a target-specific index and an offset. The
|
||||
target-specific index is printed using target-specific names and a positive or
|
||||
negative offset.
|
||||
|
||||
For example, the ``amdgpu-constdata-start`` is associated with the index ``0``
|
||||
in the AMDGPU backend. So if we have a target index operand with the index 0
|
||||
and the offset 8:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
%sgpr2 = S_ADD_U32 _, target-index(amdgpu-constdata-start) + 8, implicit-def _, implicit-def _
|
||||
|
||||
Jump-table Index Operands
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A jump-table index operand with the index 0 is printed as following:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
tBR_JTr killed %r0, %jump-table.0
|
||||
|
||||
A machine jump-table entry contains a list of ``MachineBasicBlocks``. When serializing all the function's jump-table entries, the following format is used:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
jumpTable:
|
||||
kind: <kind>
|
||||
entries:
|
||||
- id: <index>
|
||||
blocks: [ <bbreference>, <bbreference>, ... ]
|
||||
|
||||
where ``<kind>`` is describing how the jump table is represented and emitted (plain address, relocations, PIC, etc.), and each ``<index>`` is a 32-bit unsigned integer and ``blocks`` contains a list of :ref:`machine basic block references <block-references>`.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
jumpTable:
|
||||
kind: inline
|
||||
entries:
|
||||
- id: 0
|
||||
blocks: [ '%bb.3', '%bb.9', '%bb.4.d3' ]
|
||||
- id: 1
|
||||
blocks: [ '%bb.7', '%bb.7', '%bb.4.d3', '%bb.5' ]
|
||||
|
||||
External Symbol Operands
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
An external symbol operand is represented using an identifier with the ``$``
|
||||
prefix. The identifier is surrounded with ""'s and escaped if it has any
|
||||
special non-printable characters in it.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
CALL64pcrel32 $__stack_chk_fail, csr_64, implicit %rsp, implicit-def %rsp
|
||||
|
||||
MCSymbol Operands
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
A MCSymbol operand is holding a pointer to a ``MCSymbol``. For the limitations
|
||||
of this operand in MIR, see :ref:`limitations <limitations>`.
|
||||
|
||||
The syntax is:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
EH_LABEL <mcsymbol Ltmp1>
|
||||
|
||||
.. TODO: Describe the parsers default behaviour when optional YAML attributes
|
||||
are missing.
|
||||
.. TODO: Describe the syntax for the bundled instructions.
|
||||
.. TODO: Describe the syntax for virtual register YAML definitions.
|
||||
.. TODO: Describe the machine function's YAML flag attributes.
|
||||
.. TODO: Describe the syntax for the external symbol and register
|
||||
mask machine operands.
|
||||
.. TODO: Describe the syntax for the register mask machine operands.
|
||||
.. TODO: Describe the frame information YAML mapping.
|
||||
.. TODO: Describe the syntax of the stack object machine operands and their
|
||||
YAML definitions.
|
||||
.. TODO: Describe the syntax of the constant pool machine operands and their
|
||||
YAML definitions.
|
||||
.. TODO: Describe the syntax of the jump table machine operands and their
|
||||
YAML definitions.
|
||||
.. TODO: Describe the syntax of the block address machine operands.
|
||||
.. TODO: Describe the syntax of the CFI index machine operands.
|
||||
.. TODO: Describe the syntax of the metadata machine operands, and the
|
||||
instructions debug location attribute.
|
||||
.. TODO: Describe the syntax of the target index machine operands.
|
||||
.. TODO: Describe the syntax of the register live out machine operands.
|
||||
.. TODO: Describe the syntax of the machine memory operands.
|
||||
|
@ -499,7 +499,7 @@ The output we get from ``llc`` (as of LLVM 3.4):
|
||||
.reg .s32 %r<2>;
|
||||
.reg .s64 %rl<8>;
|
||||
|
||||
// BB#0: // %entry
|
||||
// %bb.0: // %entry
|
||||
ld.param.u64 %rl1, [kernel_param_0];
|
||||
mov.u32 %r1, %tid.x;
|
||||
mul.wide.s32 %rl2, %r1, 4;
|
||||
@ -897,7 +897,7 @@ This gives us the following PTX (excerpt):
|
||||
.reg .s32 %r<21>;
|
||||
.reg .s64 %rl<8>;
|
||||
|
||||
// BB#0: // %entry
|
||||
// %bb.0: // %entry
|
||||
ld.param.u64 %rl2, [kernel_param_0];
|
||||
mov.u32 %r3, %tid.x;
|
||||
ld.param.u64 %rl3, [kernel_param_1];
|
||||
@ -921,7 +921,7 @@ This gives us the following PTX (excerpt):
|
||||
abs.f32 %f4, %f1;
|
||||
setp.gtu.f32 %p4, %f4, 0f7F800000;
|
||||
@%p4 bra BB0_4;
|
||||
// BB#3: // %__nv_isnanf.exit5.i
|
||||
// %bb.3: // %__nv_isnanf.exit5.i
|
||||
abs.f32 %f5, %f2;
|
||||
setp.le.f32 %p5, %f5, 0f7F800000;
|
||||
@%p5 bra BB0_5;
|
||||
@ -953,7 +953,7 @@ This gives us the following PTX (excerpt):
|
||||
selp.f32 %f110, 0f7F800000, %f99, %p16;
|
||||
setp.eq.f32 %p17, %f110, 0f7F800000;
|
||||
@%p17 bra BB0_28;
|
||||
// BB#27:
|
||||
// %bb.27:
|
||||
fma.rn.f32 %f110, %f110, %f108, %f110;
|
||||
BB0_28: // %__internal_accurate_powf.exit.i
|
||||
setp.lt.f32 %p18, %f1, 0f00000000;
|
||||
|
@ -441,6 +441,15 @@ the program where they can be handled appropriately. Handling the error may be
|
||||
as simple as reporting the issue to the user, or it may involve attempts at
|
||||
recovery.
|
||||
|
||||
.. note::
|
||||
|
||||
While it would be ideal to use this error handling scheme throughout
|
||||
LLVM, there are places where this hasn't been practical to apply. In
|
||||
situations where you absolutely must emit a non-programmatic error and
|
||||
the ``Error`` model isn't workable you can call ``report_fatal_error``,
|
||||
which will call installed error handlers, print a message, and exit the
|
||||
program.
|
||||
|
||||
Recoverable errors are modeled using LLVM's ``Error`` scheme. This scheme
|
||||
represents errors using function return values, similar to classic C integer
|
||||
error codes, or C++'s ``std::error_code``. However, the ``Error`` class is
|
||||
@ -486,7 +495,7 @@ that inherits from the ErrorInfo utility, E.g.:
|
||||
|
||||
Error printFormattedFile(StringRef Path) {
|
||||
if (<check for valid format>)
|
||||
return make_error<InvalidObjectFile>(Path);
|
||||
return make_error<BadFileFormat>(Path);
|
||||
// print file contents.
|
||||
return Error::success();
|
||||
}
|
||||
@ -1224,7 +1233,7 @@ Define your DebugCounter like this:
|
||||
.. code-block:: c++
|
||||
|
||||
DEBUG_COUNTER(DeleteAnInstruction, "passname-delete-instruction",
|
||||
"Controls which instructions get delete").
|
||||
"Controls which instructions get delete");
|
||||
|
||||
The ``DEBUG_COUNTER`` macro defines a static variable, whose name
|
||||
is specified by the first argument. The name of the counter
|
||||
@ -2105,7 +2114,7 @@ is stored in the same allocation as the Value of a pair).
|
||||
StringMap also provides query methods that take byte ranges, so it only ever
|
||||
copies a string if a value is inserted into the table.
|
||||
|
||||
StringMap iteratation order, however, is not guaranteed to be deterministic, so
|
||||
StringMap iteration order, however, is not guaranteed to be deterministic, so
|
||||
any uses which require that should instead use a std::map.
|
||||
|
||||
.. _dss_indexmap:
|
||||
|
@ -82,8 +82,14 @@ The design of VPlan follows several high-level guidelines:
|
||||
replicated VF*UF times to handle scalarized and predicated instructions.
|
||||
Innerloops are also modelled as SESE regions.
|
||||
|
||||
Low-level Design
|
||||
================
|
||||
7. Support instruction-level analysis and transformation, as part of Planning
|
||||
Step 2.b: During vectorization instructions may need to be traversed, moved,
|
||||
replaced by other instructions or be created. For example, vector idiom
|
||||
detection and formation involves searching for and optimizing instruction
|
||||
patterns.
|
||||
|
||||
Definitions
|
||||
===========
|
||||
The low-level design of VPlan comprises of the following classes.
|
||||
|
||||
:LoopVectorizationPlanner:
|
||||
@ -139,11 +145,64 @@ The low-level design of VPlan comprises of the following classes.
|
||||
instructions; e.g., cloned once, replicated multiple times or widened
|
||||
according to selected VF.
|
||||
|
||||
:VPValue:
|
||||
The base of VPlan's def-use relations class hierarchy. When instantiated, it
|
||||
models a constant or a live-in Value in VPlan. It has users, which are of type
|
||||
VPUser, but no operands.
|
||||
|
||||
:VPUser:
|
||||
A VPValue representing a general vertex in the def-use graph of VPlan. It has
|
||||
operands which are of type VPValue. When instantiated, it represents a
|
||||
live-out Instruction that exists outside VPlan. VPUser is similar in some
|
||||
aspects to LLVM's User class.
|
||||
|
||||
:VPInstruction:
|
||||
A VPInstruction is both a VPRecipe and a VPUser. It models a single
|
||||
VPlan-level instruction to be generated if the VPlan is executed, including
|
||||
its opcode and possibly additional characteristics. It is the basis for
|
||||
writing instruction-level analyses and optimizations in VPlan as creating,
|
||||
replacing or moving VPInstructions record both def-use and scheduling
|
||||
decisions. VPInstructions also extend LLVM IR's opcodes with idiomatic
|
||||
operations that enrich the Vectorizer's semantics.
|
||||
|
||||
:VPTransformState:
|
||||
Stores information used for generating output IR, passed from
|
||||
LoopVectorizationPlanner to its selected VPlan for execution, and used to pass
|
||||
additional information down to VPBlocks and VPRecipes.
|
||||
|
||||
The Planning Process and VPlan Roadmap
|
||||
======================================
|
||||
|
||||
Transforming the Loop Vectorizer to use VPlan follows a staged approach. First,
|
||||
VPlan is used to record the final vectorization decisions, and to execute them:
|
||||
the Hierarchical CFG models the planned control-flow, and Recipes capture
|
||||
decisions taken inside basic-blocks. Next, VPlan will be used also as the basis
|
||||
for taking these decisions, effectively turning them into a series of
|
||||
VPlan-to-VPlan algorithms. Finally, VPlan will support the planning process
|
||||
itself including cost-based analyses for making these decisions, to fully
|
||||
support compositional and iterative decision making.
|
||||
|
||||
Some decisions are local to an instruction in the loop, such as whether to widen
|
||||
it into a vector instruction or replicate it, keeping the generated instructions
|
||||
in place. Other decisions, however, involve moving instructions, replacing them
|
||||
with other instructions, and/or introducing new instructions. For example, a
|
||||
cast may sink past a later instruction and be widened to handle first-order
|
||||
recurrence; an interleave group of strided gathers or scatters may effectively
|
||||
move to one place where they are replaced with shuffles and a common wide vector
|
||||
load or store; new instructions may be introduced to compute masks, shuffle the
|
||||
elements of vectors, and pack scalar values into vectors or vice-versa.
|
||||
|
||||
In order for VPlan to support making instruction-level decisions and analyses,
|
||||
it needs to model the relevant instructions along with their def/use relations.
|
||||
This too follows a staged approach: first, the new instructions that compute
|
||||
masks are modeled as VPInstructions, along with their induced def/use subgraph.
|
||||
This effectively models masks in VPlan, facilitating VPlan-based predication.
|
||||
Next, the logic embedded within each Recipe for generating its instructions at
|
||||
VPlan execution time, will instead take part in the planning process by modeling
|
||||
them as VPInstructions. Finally, only logic that applies to instructions as a
|
||||
group will remain in Recipes, such as interleave groups and potentially other
|
||||
idiom groups having synergistic cost.
|
||||
|
||||
Related LLVM components
|
||||
-----------------------
|
||||
1. SLP Vectorizer: one can compare the VPlan model with LLVM's existing SLP
|
||||
@ -152,6 +211,9 @@ Related LLVM components
|
||||
2. RegionInfo: one can compare VPlan's H-CFG with the Region Analysis as used by
|
||||
Polly [7]_.
|
||||
|
||||
3. Loop Vectorizer: the Vectorization Plan aims to upgrade the infrastructure of
|
||||
the Loop Vectorizer and extend it to handle outer loops [8,9]_.
|
||||
|
||||
References
|
||||
----------
|
||||
.. [1] "Outer-loop vectorization: revisited for short SIMD architectures", Dorit
|
||||
@ -180,3 +242,6 @@ References
|
||||
|
||||
.. [8] "Introducing VPlan to the Loop Vectorizer", Gil Rapaport and Ayal Zaks,
|
||||
European LLVM Developers' Meeting 2017.
|
||||
|
||||
.. [9] "Extending LoopVectorizer: OpenMP4.5 SIMD and Outer Loop
|
||||
Auto-Vectorization", Intel Vectorizer Team, LLVM Developers' Meeting 2016.
|
||||
|
@ -1,10 +1,15 @@
|
||||
========================
|
||||
LLVM 5.0.0 Release Notes
|
||||
LLVM 6.0.0 Release Notes
|
||||
========================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
.. warning::
|
||||
These are in-progress notes for the upcoming LLVM 6 release.
|
||||
Release notes for previous releases can be found on
|
||||
`the Download Page <http://releases.llvm.org/download.html>`_.
|
||||
|
||||
|
||||
Introduction
|
||||
============
|
||||
@ -21,244 +26,97 @@ have questions or comments, the `LLVM Developer's Mailing List
|
||||
<http://lists.llvm.org/mailman/listinfo/llvm-dev>`_ is a good place to send
|
||||
them.
|
||||
|
||||
Note that if you are reading this file from a Subversion checkout or the main
|
||||
LLVM web page, this document applies to the *next* release, not the current
|
||||
one. To see the release notes for a specific release, please see the `releases
|
||||
page <http://llvm.org/releases/>`_.
|
||||
|
||||
Non-comprehensive list of changes in this release
|
||||
=================================================
|
||||
.. NOTE
|
||||
For small 1-3 sentence descriptions, just add an entry at the end of
|
||||
this list. If your description won't fit comfortably in one bullet
|
||||
point (e.g. maybe you would like to give an example of the
|
||||
functionality, or simply have a lot to talk about), see the `NOTE` below
|
||||
for adding a new subsection.
|
||||
|
||||
* LLVM's ``WeakVH`` has been renamed to ``WeakTrackingVH`` and a new ``WeakVH``
|
||||
has been introduced. The new ``WeakVH`` nulls itself out on deletion, but
|
||||
does not track values across RAUW.
|
||||
* The ``Redirects`` argument of ``llvm::sys::ExecuteAndWait`` and
|
||||
``llvm::sys::ExecuteNoWait`` was changed to an ``ArrayRef`` of optional
|
||||
``StringRef``'s to make it safer and more convenient to use.
|
||||
|
||||
* A new library named ``BinaryFormat`` has been created which holds a collection
|
||||
of code which previously lived in ``Support``. This includes the
|
||||
``file_magic`` structure and ``identify_magic`` functions, as well as all the
|
||||
structure and type definitions for DWARF, ELF, COFF, WASM, and MachO file
|
||||
formats.
|
||||
* The backend name was added to the Target Registry to allow run-time
|
||||
information to be fed back into TableGen. Out-of-tree targets will need to add
|
||||
the name used in the `def X : Target` definition to the call to
|
||||
`RegisterTarget`.
|
||||
|
||||
* The tool ``llvm-pdbdump`` has been renamed ``llvm-pdbutil`` to better reflect
|
||||
its nature as a general purpose PDB manipulation / diagnostics tool that does
|
||||
more than just dumping contents.
|
||||
* The ``Debugify`` pass was added to ``opt`` to facilitate testing of debug
|
||||
info preservation. This pass attaches synthetic ``DILocations`` and
|
||||
``DIVariables`` to the instructions in a ``Module``. The ``CheckDebugify``
|
||||
pass determines how much of the metadata is lost.
|
||||
|
||||
* The ``BBVectorize`` pass has been removed. It was fully replaced and no
|
||||
longer used back in 2014 but we didn't get around to removing it. Now it is
|
||||
gone. The SLP vectorizer is the suggested non-loop vectorization pass.
|
||||
* Note..
|
||||
|
||||
* A new tool opt-viewer.py has been added to visualize optimization remarks in
|
||||
HTML. The tool processes the YAML files produced by clang with the
|
||||
-fsave-optimization-record option.
|
||||
.. NOTE
|
||||
If you would like to document a larger change, then you can add a
|
||||
subsection about it right here. You can copy the following boilerplate
|
||||
and un-indent it (the indentation causes it to be inside this comment).
|
||||
|
||||
* A new CMake macro ``LLVM_REVERSE_ITERATION`` has been added. If enabled, all
|
||||
supported unordered LLVM containers would be iterated in reverse order. This
|
||||
is useful for uncovering non-determinism caused by iteration of unordered
|
||||
containers. Currently, it supports reverse iteration of SmallPtrSet and
|
||||
DenseMap.
|
||||
|
||||
* A new tool ``llvm-dlltool`` has been added to create short import libraries
|
||||
from GNU style definition files. The tool utilizes the PE COFF SPEC Import
|
||||
Library Format and PE COFF Auxiliary Weak Externals Format to achieve
|
||||
compatibility with LLD and MSVC LINK.
|
||||
Special New Feature
|
||||
-------------------
|
||||
|
||||
Makes programs 10x faster by doing Special New Thing.
|
||||
|
||||
Changes to the LLVM IR
|
||||
----------------------
|
||||
|
||||
* The datalayout string may now indicate an address space to use for
|
||||
the pointer type of ``alloca`` rather than the default of 0.
|
||||
|
||||
* Added ``speculatable`` attribute indicating a function which has no
|
||||
side-effects which could inhibit hoisting of calls.
|
||||
|
||||
Changes to the Arm Targets
|
||||
Changes to the ARM Backend
|
||||
--------------------------
|
||||
|
||||
During this release the AArch64 target has:
|
||||
During this release ...
|
||||
|
||||
* A much improved Global ISel at O0.
|
||||
* Support for ARMv8.1 8.2 and 8.3 instructions.
|
||||
* New scheduler information for ThunderX2.
|
||||
* Some SVE type changes but not much more than that.
|
||||
* Made instruction fusion more aggressive, resulting in speedups
|
||||
for code making use of AArch64 AES instructions. AES fusion has been
|
||||
enabled for most Cortex-A cores and the AArch64MacroFusion pass was moved
|
||||
to the generic MacroFusion pass.
|
||||
* Added preferred function alignments for most Cortex-A cores.
|
||||
* OpenMP "offload-to-self" base support.
|
||||
|
||||
During this release the ARM target has:
|
||||
|
||||
* Improved, but still mostly broken, Global ISel.
|
||||
* Scheduling models update, new schedule for Cortex-A57.
|
||||
* Hardware breakpoint support in LLDB.
|
||||
* New assembler error handling, with spelling corrections and multiple
|
||||
suggestions on how to fix problems.
|
||||
* Improved mixed ARM/Thumb code generation. Some cases in which wrong
|
||||
relocations were emitted have been fixed.
|
||||
* Added initial support for mixed ARM/Thumb link-time optimization, using the
|
||||
thumb-mode target feature.
|
||||
|
||||
Changes to the MIPS Target
|
||||
--------------------------
|
||||
|
||||
* The microMIPS64R6 backend is deprecated and will be removed in the next
|
||||
release.
|
||||
|
||||
* The MIPS backend now directly supports vector types for arguments and return
|
||||
values (previously this required ABI specific LLVM IR).
|
||||
|
||||
* Added documentation for how the MIPS backend handles address lowering.
|
||||
|
||||
* Added a GCC compatible option -m(no-)madd4 to control the generation of four
|
||||
operand multiply addition/subtraction instructions.
|
||||
|
||||
* Added basic support for the XRay instrumentation system.
|
||||
|
||||
* Added support for more assembly aliases and macros.
|
||||
|
||||
* Added support for the ``micromips`` and ``nomicromips`` function attributes
|
||||
which control micromips code generation on a per function basis.
|
||||
|
||||
* Added the ``long-calls`` feature for non-pic environments. This feature is
|
||||
used where the callee is out of range of the caller using a standard call
|
||||
sequence. It must be enabled specifically.
|
||||
|
||||
* Added support for performing microMIPS code generation via function
|
||||
attributes.
|
||||
|
||||
* Added experimental support for the static relocation model for the N64 ABI.
|
||||
|
||||
* Added partial support for the MT ASE.
|
||||
|
||||
* Added basic support for code size reduction for microMIPS.
|
||||
|
||||
* Fixed numerous bugs including: multi-precision arithmetic support, various
|
||||
vectorization bugs, debug information for thread local variables, debug
|
||||
sections lacking the correct flags, crashing when disassembling sections
|
||||
whose size is not a multiple of two or four.
|
||||
During this release ...
|
||||
|
||||
|
||||
Changes to the PowerPC Target
|
||||
-----------------------------
|
||||
|
||||
* Additional support and exploitation of POWER ISA 3.0: vabsdub, vabsduh,
|
||||
vabsduw, modsw, moduw, modsd, modud, lxv, stxv, vextublx, vextubrx, vextuhlx,
|
||||
vextuhrx, vextuwlx, vextuwrx, vextsb2w, vextsb2d, vextsh2w, vextsh2d, and
|
||||
vextsw2d
|
||||
|
||||
* Implemented Optimal Code Sequences from The PowerPC Compiler Writer's Guide.
|
||||
|
||||
* Enable -fomit-frame-pointer by default.
|
||||
|
||||
* Improved handling of bit reverse intrinsic.
|
||||
|
||||
* Improved handling of memcpy and memcmp functions.
|
||||
|
||||
* Improved handling of branches with static branch hints.
|
||||
|
||||
* Improved codegen for atomic load_acquire.
|
||||
|
||||
* Improved block placement during code layout
|
||||
|
||||
* Many improvements to instruction selection and code generation
|
||||
|
||||
During this release ...
|
||||
|
||||
Changes to the X86 Target
|
||||
-------------------------
|
||||
|
||||
* Added initial AMD Ryzen (znver1) scheduler support.
|
||||
|
||||
* Added support for Intel Goldmont CPUs.
|
||||
|
||||
* Add support for avx512vpopcntdq instructions.
|
||||
|
||||
* Added heuristics to convert CMOV into branches when it may be profitable.
|
||||
|
||||
* More aggressive inlining of memcmp calls.
|
||||
|
||||
* Improve vXi64 shuffles on 32-bit targets.
|
||||
|
||||
* Improved use of PMOVMSKB for any_of/all_of comparision reductions.
|
||||
|
||||
* Improved Silvermont, Sandybridge, and Jaguar (btver2) schedulers.
|
||||
|
||||
* Improved support for AVX512 vector rotations.
|
||||
|
||||
* Added support for AMD Lightweight Profiling (LWP) instructions.
|
||||
|
||||
* Avoid using slow LEA instructions.
|
||||
|
||||
* Use alternative sequences for multiply by constant.
|
||||
|
||||
* Improved lowering of strided shuffles.
|
||||
|
||||
* Improved the AVX512 cost model used by the vectorizer.
|
||||
|
||||
* Fix scalar code performance when AVX512 is enabled by making i1's illegal.
|
||||
|
||||
* Fixed many inline assembly bugs.
|
||||
|
||||
* Preliminary support for tracing NetBSD processes and core files with a single
|
||||
thread in LLDB.
|
||||
During this release ...
|
||||
|
||||
Changes to the AMDGPU Target
|
||||
-----------------------------
|
||||
|
||||
* Initial gfx9 support
|
||||
During this release ...
|
||||
|
||||
Changes to the AVR Target
|
||||
-----------------------------
|
||||
|
||||
This release consists mainly of bugfixes and implementations of features
|
||||
required for compiling basic Rust programs.
|
||||
During this release ...
|
||||
|
||||
* Enable the branch relaxation pass so that we don't crash on large
|
||||
stack load/stores
|
||||
Changes to the OCaml bindings
|
||||
-----------------------------
|
||||
|
||||
* Add support for lowering bit-rotations to the native ``ror`` and ``rol``
|
||||
instructions
|
||||
|
||||
* Fix bug where function pointers were treated as pointers to RAM and not
|
||||
pointers to program memory
|
||||
|
||||
* Fix broken code generation for shift-by-variable expressions
|
||||
|
||||
* Support zero-sized types in argument lists; this is impossible in C,
|
||||
but possible in Rust
|
||||
During this release ...
|
||||
|
||||
|
||||
Changes to the C API
|
||||
--------------------
|
||||
|
||||
* Deprecated the ``LLVMAddBBVectorizePass`` interface since the ``BBVectorize``
|
||||
pass has been removed. It is now a no-op and will be removed in the next
|
||||
release. Use ``LLVMAddSLPVectorizePass`` instead to get the supported SLP
|
||||
vectorizer.
|
||||
During this release ...
|
||||
|
||||
|
||||
External Open Source Projects Using LLVM 5
|
||||
External Open Source Projects Using LLVM 6
|
||||
==========================================
|
||||
|
||||
Zig Programming Language
|
||||
------------------------
|
||||
|
||||
`Zig <http://ziglang.org>`_ is an open-source programming language designed
|
||||
for robustness, optimality, and clarity. It integrates closely with C and is
|
||||
intended to eventually take the place of C. It uses LLVM to produce highly
|
||||
optimized native code and to cross-compile for any target out of the box. Zig
|
||||
is in alpha; with a beta release expected in September.
|
||||
|
||||
LDC - the LLVM-based D compiler
|
||||
-------------------------------
|
||||
|
||||
`D <http://dlang.org>`_ is a language with C-like syntax and static typing. It
|
||||
pragmatically combines efficiency, control, and modeling power, with safety and
|
||||
programmer productivity. D supports powerful concepts like Compile-Time Function
|
||||
Execution (CTFE) and Template Meta-Programming, provides an innovative approach
|
||||
to concurrency and offers many classical paradigms.
|
||||
|
||||
`LDC <http://wiki.dlang.org/LDC>`_ uses the frontend from the reference compiler
|
||||
combined with LLVM as backend to produce efficient native code. LDC targets
|
||||
x86/x86_64 systems like Linux, OS X, FreeBSD and Windows and also Linux on ARM
|
||||
and PowerPC (32/64 bit). Ports to other architectures like AArch64 and MIPS64
|
||||
are underway.
|
||||
* A project...
|
||||
|
||||
|
||||
Additional Information
|
||||
|
@ -126,14 +126,14 @@ For example, using the environment variable:
|
||||
|
||||
.. code::
|
||||
|
||||
SCUDO_OPTIONS="DeleteSizeMismatch=1:QuarantineSizeMb=16" ./a.out
|
||||
SCUDO_OPTIONS="DeleteSizeMismatch=1:QuarantineSizeKb=64" ./a.out
|
||||
|
||||
Or using the function:
|
||||
|
||||
.. code::
|
||||
.. code:: cpp
|
||||
|
||||
extern "C" const char *__scudo_default_options() {
|
||||
return "DeleteSizeMismatch=1:QuarantineSizeMb=16";
|
||||
return "DeleteSizeMismatch=1:QuarantineSizeKb=64";
|
||||
}
|
||||
|
||||
|
||||
@ -142,11 +142,14 @@ The following options are available:
|
||||
+-----------------------------+----------------+----------------+------------------------------------------------+
|
||||
| Option | 64-bit default | 32-bit default | Description |
|
||||
+-----------------------------+----------------+----------------+------------------------------------------------+
|
||||
| QuarantineSizeMb | 64 | 16 | The size (in Mb) of quarantine used to delay |
|
||||
| QuarantineSizeKb | 256 | 64 | The size (in Kb) of quarantine used to delay |
|
||||
| | | | the actual deallocation of chunks. Lower value |
|
||||
| | | | may reduce memory usage but decrease the |
|
||||
| | | | effectiveness of the mitigation; a negative |
|
||||
| | | | value will fallback to a default of 64Mb. |
|
||||
| | | | value will fallback to the defaults. |
|
||||
+-----------------------------+----------------+----------------+------------------------------------------------+
|
||||
| QuarantineChunksUpToSize | 2048 | 512 | Size (in bytes) up to which chunks can be |
|
||||
| | | | quarantined. |
|
||||
+-----------------------------+----------------+----------------+------------------------------------------------+
|
||||
| ThreadLocalQuarantineSizeKb | 1024 | 256 | The size (in Kb) of per-thread cache use to |
|
||||
| | | | offload the global quarantine. Lower value may |
|
||||
|
@ -171,7 +171,48 @@ Debugger intrinsic functions
|
||||
----------------------------
|
||||
|
||||
LLVM uses several intrinsic functions (name prefixed with "``llvm.dbg``") to
|
||||
provide debug information at various points in generated code.
|
||||
track source local variables through optimization and code generation.
|
||||
|
||||
``llvm.dbg.addr``
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: llvm
|
||||
|
||||
void @llvm.dbg.addr(metadata, metadata, metadata)
|
||||
|
||||
This intrinsic provides information about a local element (e.g., variable).
|
||||
The first argument is metadata holding the address of variable, typically a
|
||||
static alloca in the function entry block. The second argument is a
|
||||
`local variable <LangRef.html#dilocalvariable>`_ containing a description of
|
||||
the variable. The third argument is a `complex expression
|
||||
<LangRef.html#diexpression>`_. An `llvm.dbg.addr` intrinsic describes the
|
||||
*address* of a source variable.
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
%i.addr = alloca i32, align 4
|
||||
call void @llvm.dbg.addr(metadata i32* %i.addr, metadata !1,
|
||||
metadata !DIExpression()), !dbg !2
|
||||
!1 = !DILocalVariable(name: "i", ...) ; int i
|
||||
!2 = !DILocation(...)
|
||||
...
|
||||
%buffer = alloca [256 x i8], align 8
|
||||
; The address of i is buffer+64.
|
||||
call void @llvm.dbg.addr(metadata [256 x i8]* %buffer, metadata !3,
|
||||
metadata !DIExpression(DW_OP_plus, 64)), !dbg !4
|
||||
!3 = !DILocalVariable(name: "i", ...) ; int i
|
||||
!4 = !DILocation(...)
|
||||
|
||||
A frontend should generate exactly one call to ``llvm.dbg.addr`` at the point
|
||||
of declaration of a source variable. Optimization passes that fully promote the
|
||||
variable from memory to SSA values will replace this call with possibly
|
||||
multiple calls to `llvm.dbg.value`. Passes that delete stores are effectively
|
||||
partial promotion, and they will insert a mix of calls to ``llvm.dbg.value``
|
||||
and ``llvm.dbg.addr`` to track the source variable value when it is available.
|
||||
After optimization, there may be multiple calls to ``llvm.dbg.addr`` describing
|
||||
the program points where the variables lives in memory. All calls for the same
|
||||
concrete source variable must agree on the memory location.
|
||||
|
||||
|
||||
``llvm.dbg.declare``
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
@ -180,26 +221,14 @@ provide debug information at various points in generated code.
|
||||
|
||||
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 <LangRef.html#dilocalvariable>`_ containing a
|
||||
description of the variable. The third argument is a `complex expression
|
||||
<LangRef.html#diexpression>`_. An `llvm.dbg.declare` instrinsic describes the
|
||||
*location* of a source variable.
|
||||
|
||||
.. code-block:: llvm
|
||||
|
||||
%i.addr = alloca i32, align 4
|
||||
call void @llvm.dbg.declare(metadata i32* %i.addr, metadata !1, metadata !2), !dbg !3
|
||||
!1 = !DILocalVariable(name: "i", ...) ; int i
|
||||
!2 = !DIExpression()
|
||||
!3 = !DILocation(...)
|
||||
...
|
||||
%buffer = alloca [256 x i8], align 8
|
||||
; The address of i is buffer+64.
|
||||
call void @llvm.dbg.declare(metadata [256 x i8]* %buffer, metadata !1, metadata !2)
|
||||
!1 = !DILocalVariable(name: "i", ...) ; int i
|
||||
!2 = !DIExpression(DW_OP_plus, 64)
|
||||
This intrinsic is identical to `llvm.dbg.addr`, except that there can only be
|
||||
one call to `llvm.dbg.declare` for a given concrete `local variable
|
||||
<LangRef.html#dilocalvariable>`_. It is not control-dependent, meaning that if
|
||||
a call to `llvm.dbg.declare` exists and has a valid location argument, that
|
||||
address is considered to be the true home of the variable across its entire
|
||||
lifetime. This makes it hard for optimizations to preserve accurate debug info
|
||||
in the presence of ``llvm.dbg.declare``, so we are transitioning away from it,
|
||||
and we plan to deprecate it in future LLVM releases.
|
||||
|
||||
|
||||
``llvm.dbg.value``
|
||||
@ -207,14 +236,13 @@ description of the variable. The third argument is a `complex expression
|
||||
|
||||
.. code-block:: llvm
|
||||
|
||||
void @llvm.dbg.value(metadata, i64, metadata, metadata)
|
||||
void @llvm.dbg.value(metadata, 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
|
||||
<LangRef.html#dilocalvariable>`_ containing a description of the variable. The
|
||||
fourth argument is a `complex expression <LangRef.html#diexpression>`_.
|
||||
argument is a `local variable <LangRef.html#dilocalvariable>`_ containing a
|
||||
description of the variable. The third argument is a `complex expression
|
||||
<LangRef.html#diexpression>`_.
|
||||
|
||||
Object lifetimes and scoping
|
||||
============================
|
||||
@ -243,6 +271,9 @@ following C fragment, for example:
|
||||
8. X = Y;
|
||||
9. }
|
||||
|
||||
.. FIXME: Update the following example to use llvm.dbg.addr once that is the
|
||||
default in clang.
|
||||
|
||||
Compiled to LLVM, this function would be represented like this:
|
||||
|
||||
.. code-block:: text
|
||||
|
@ -172,7 +172,7 @@ SSA value ``%obj.relocated`` which represents the potentially changed value of
|
||||
``%obj`` after the safepoint and update any following uses appropriately. The
|
||||
resulting relocation sequence is:
|
||||
|
||||
.. code-block:: text
|
||||
.. code-block:: llvm
|
||||
|
||||
define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj)
|
||||
gc "statepoint-example" {
|
||||
@ -273,7 +273,7 @@ afterwards.
|
||||
If we extend our previous example to include a pointless derived pointer,
|
||||
we get:
|
||||
|
||||
.. code-block:: text
|
||||
.. code-block:: llvm
|
||||
|
||||
define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj)
|
||||
gc "statepoint-example" {
|
||||
@ -319,7 +319,7 @@ 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:: text
|
||||
.. code-block:: llvm
|
||||
|
||||
@flag = thread_local global i32 0, align 4
|
||||
|
||||
@ -702,7 +702,7 @@ whitelist or use one of the predefined ones.
|
||||
|
||||
As an example, given this code:
|
||||
|
||||
.. code-block:: text
|
||||
.. code-block:: llvm
|
||||
|
||||
define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj)
|
||||
gc "statepoint-example" {
|
||||
@ -712,7 +712,7 @@ As an example, given this code:
|
||||
|
||||
The pass would produce this IR:
|
||||
|
||||
.. code-block:: text
|
||||
.. code-block:: llvm
|
||||
|
||||
define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj)
|
||||
gc "statepoint-example" {
|
||||
@ -789,7 +789,7 @@ As an example, given input IR of the following:
|
||||
|
||||
This pass would produce the following IR:
|
||||
|
||||
.. code-block:: text
|
||||
.. code-block:: llvm
|
||||
|
||||
define void @test() gc "statepoint-example" {
|
||||
call void @do_safepoint()
|
||||
|
@ -128,7 +128,7 @@ address points of the vtables of A, B and D respectively). If we then load
|
||||
an address from that pointer, we know that the address can only be one of
|
||||
``&A::f``, ``&B::f`` or ``&D::f``.
|
||||
|
||||
.. _address point: https://mentorembedded.github.io/cxx-abi/abi.html#vtable-general
|
||||
.. _address point: https://itanium-cxx-abi.github.io/cxx-abi/abi.html#vtable-general
|
||||
|
||||
Testing Addresses For Type Membership
|
||||
=====================================
|
||||
@ -223,4 +223,4 @@ efficiently to minimize the sizes of the underlying bitsets.
|
||||
ret void
|
||||
}
|
||||
|
||||
.. _GlobalLayoutBuilder: http://llvm.org/klaus/llvm/blob/master/include/llvm/Transforms/IPO/LowerTypeTests.h
|
||||
.. _GlobalLayoutBuilder: http://git.llvm.org/klaus/llvm/blob/master/include/llvm/Transforms/IPO/LowerTypeTests.h
|
||||
|
@ -1008,10 +1008,50 @@ Instruction Scheduling
|
||||
----------------------
|
||||
|
||||
Instruction itineraries can be queried using MCDesc::getSchedClass(). The
|
||||
value can be named by an enumemation in llvm::XXX::Sched namespace generated
|
||||
value can be named by an enumeration in llvm::XXX::Sched namespace generated
|
||||
by TableGen in XXXGenInstrInfo.inc. The name of the schedule classes are
|
||||
the same as provided in XXXSchedule.td plus a default NoItinerary class.
|
||||
|
||||
The schedule models are generated by TableGen by the SubtargetEmitter,
|
||||
using the ``CodeGenSchedModels`` class. This is distinct from the itinerary
|
||||
method of specifying machine resource use. The tool ``utils/schedcover.py``
|
||||
can be used to determine which instructions have been covered by the
|
||||
schedule model description and which haven't. The first step is to use the
|
||||
instructions below to create an output file. Then run ``schedcover.py`` on the
|
||||
output file:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ <src>/utils/schedcover.py <build>/lib/Target/AArch64/tblGenSubtarget.with
|
||||
instruction, default, CortexA53Model, CortexA57Model, CycloneModel, ExynosM1Model, FalkorModel, KryoModel, ThunderX2T99Model, ThunderXT8XModel
|
||||
ABSv16i8, WriteV, , , CyWriteV3, M1WriteNMISC1, FalkorWr_2VXVY_2cyc, KryoWrite_2cyc_XY_XY_150ln, ,
|
||||
ABSv1i64, WriteV, , , CyWriteV3, M1WriteNMISC1, FalkorWr_1VXVY_2cyc, KryoWrite_2cyc_XY_noRSV_67ln, ,
|
||||
...
|
||||
|
||||
To capture the debug output from generating a schedule model, change to the
|
||||
appropriate target directory and use the following command:
|
||||
command with the ``subtarget-emitter`` debug option:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ <build>/bin/llvm-tblgen -debug-only=subtarget-emitter -gen-subtarget \
|
||||
-I <src>/lib/Target/<target> -I <src>/include \
|
||||
-I <src>/lib/Target <src>/lib/Target/<target>/<target>.td \
|
||||
-o <build>/lib/Target/<target>/<target>GenSubtargetInfo.inc.tmp \
|
||||
> tblGenSubtarget.dbg 2>&1
|
||||
|
||||
Where ``<build>`` is the build directory, ``src`` is the source directory,
|
||||
and ``<target>`` is the name of the target.
|
||||
To double check that the above command is what is needed, one can capture the
|
||||
exact TableGen command from a build by using:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
$ VERBOSE=1 make ...
|
||||
|
||||
and search for ``llvm-tblgen`` commands in the output.
|
||||
|
||||
|
||||
Instruction Relation Mapping
|
||||
----------------------------
|
||||
|
||||
|
@ -1032,7 +1032,7 @@ implementation for the interface.
|
||||
Pass Statistics
|
||||
===============
|
||||
|
||||
The `Statistic <http://llvm.org/doxygen/Statistic_8h-source.html>`_ class is
|
||||
The `Statistic <http://llvm.org/doxygen/Statistic_8h_source.html>`_ class is
|
||||
designed to be an easy way to expose various success metrics from passes.
|
||||
These statistics are printed at the end of a run, when the :option:`-stats`
|
||||
command line option is enabled on the command line. See the :ref:`Statistics
|
||||
@ -1043,7 +1043,7 @@ section <Statistic>` in the Programmer's Manual for details.
|
||||
What PassManager does
|
||||
---------------------
|
||||
|
||||
The `PassManager <http://llvm.org/doxygen/PassManager_8h-source.html>`_ `class
|
||||
The `PassManager <http://llvm.org/doxygen/PassManager_8h_source.html>`_ `class
|
||||
<http://llvm.org/doxygen/classllvm_1_1PassManager.html>`_ takes a list of
|
||||
passes, ensures their :ref:`prerequisites <writing-an-llvm-pass-interaction>`
|
||||
are set up correctly, and then schedules passes to run efficiently. All of the
|
||||
|
@ -75,11 +75,11 @@ GCC-style attributes or C++11-style attributes.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
[[clang::xray_always_intrument]] void always_instrumented();
|
||||
[[clang::xray_always_instrument]] void always_instrumented();
|
||||
|
||||
[[clang::xray_never_instrument]] void never_instrumented();
|
||||
|
||||
void alt_always_instrumented() __attribute__((xray_always_intrument));
|
||||
void alt_always_instrumented() __attribute__((xray_always_instrument));
|
||||
|
||||
void alt_never_instrumented() __attribute__((xray_never_instrument));
|
||||
|
||||
@ -143,17 +143,30 @@ variable, where we list down the options and their defaults below.
|
||||
| | | | instrumentation points |
|
||||
| | | | before main. |
|
||||
+-------------------+-----------------+---------------+------------------------+
|
||||
| xray_naive_log | ``bool`` | ``true`` | Whether to install |
|
||||
| | | | the naive log |
|
||||
| | | | implementation. |
|
||||
| xray_mode | ``const char*`` | ``""`` | Default mode to |
|
||||
| | | | install and initialize |
|
||||
| | | | before ``main``. |
|
||||
+-------------------+-----------------+---------------+------------------------+
|
||||
| xray_logfile_base | ``const char*`` | ``xray-log.`` | Filename base for the |
|
||||
| | | | XRay logfile. |
|
||||
+-------------------+-----------------+---------------+------------------------+
|
||||
| xray_fdr_log | ``bool`` | ``false`` | Whether to install the |
|
||||
| | | | Flight Data Recorder |
|
||||
| xray_naive_log | ``bool`` | ``false`` | **DEPRECATED:** Use |
|
||||
| | | | xray_mode=xray-basic |
|
||||
| | | | instead. Whether to |
|
||||
| | | | install the basic log |
|
||||
| | | | the naive log |
|
||||
| | | | implementation. |
|
||||
+-------------------+-----------------+---------------+------------------------+
|
||||
| xray_fdr_log | ``bool`` | ``false`` | **DEPRECATED:** Use |
|
||||
| | | | xray_mode=xray-fdr |
|
||||
| | | | instead. Whether to |
|
||||
| | | | install the Flight |
|
||||
| | | | Data Recorder |
|
||||
| | | | (FDR) mode. |
|
||||
+-------------------+-----------------+---------------+------------------------+
|
||||
| verbosity | ``int`` | ``0`` | Runtime verbosity |
|
||||
| | | | level. |
|
||||
+-------------------+-----------------+---------------+------------------------+
|
||||
|
||||
|
||||
If you choose to not use the default logging implementation that comes with the
|
||||
@ -196,6 +209,9 @@ on your application, you may set the ``xray_fdr_log`` option to ``true`` in the
|
||||
``XRAY_OPTIONS`` environment variable (while also optionally setting the
|
||||
``xray_naive_log`` to ``false``).
|
||||
|
||||
When the buffers are flushed to disk, the result is a binary trace format
|
||||
described by `XRay FDR format <XRayFDRFormat.html>`_
|
||||
|
||||
When FDR mode is on, it will keep writing and recycling memory buffers until
|
||||
the logging implementation is finalized -- at which point it can be flushed and
|
||||
re-initialised later. To do this programmatically, we follow the workflow
|
||||
@ -238,6 +254,14 @@ following API:
|
||||
- ``__xray_set_log_impl(...)``: This function takes a struct of type
|
||||
``XRayLogImpl``, which is defined in ``xray/xray_log_interface.h``, part of
|
||||
the XRay compiler-rt installation.
|
||||
- ``__xray_log_register_mode(...)``: Register a logging implementation against
|
||||
a string Mode. The implementation is an instance of ``XRayLogImpl`` defined
|
||||
in ``xray/xray_log_interface.h``.
|
||||
- ``__xray_log_select_mode(...)``: Select the mode to install, associated with
|
||||
a string Mode. Only implementations registered with
|
||||
``__xray_log_register_mode(...)`` can be chosen with this function. When
|
||||
successful, has the same effects as calling ``__xray_set_log_impl(...)`` with
|
||||
the registered logging implementation.
|
||||
- ``__xray_log_init(...)``: This function allows for initializing and
|
||||
re-initializing an installed logging implementation. See
|
||||
``xray/xray_log_interface.h`` for details, part of the XRay compiler-rt
|
||||
@ -255,10 +279,15 @@ supports the following subcommands:
|
||||
- ``account``: Performs basic function call accounting statistics with various
|
||||
options for sorting, and output formats (supports CSV, YAML, and
|
||||
console-friendly TEXT).
|
||||
- ``convert``: Converts an XRay log file from one format to another. Currently
|
||||
only converts to YAML.
|
||||
- ``convert``: Converts an XRay log file from one format to another. We can
|
||||
convert from binary XRay traces (both naive and FDR mode) to YAML,
|
||||
`flame-graph <https://github.com/brendangregg/FlameGraph>`_ friendly text
|
||||
formats, as well as `Chrome Trace Viewer (catapult)
|
||||
<https://github.com/catapult-project/catapult>` formats.
|
||||
- ``graph``: Generates a DOT graph of the function call relationships between
|
||||
functions found in an XRay trace.
|
||||
- ``stack``: Reconstructs function call stacks from a timeline of function
|
||||
calls in an XRay trace.
|
||||
|
||||
These subcommands use various library components found as part of the XRay
|
||||
libraries, distributed with the LLVM distribution. These are:
|
||||
@ -271,7 +300,7 @@ libraries, distributed with the LLVM distribution. These are:
|
||||
associated with edges and vertices.
|
||||
- ``llvm/XRay/InstrumentationMap.h``: A convenient tool for analyzing the
|
||||
instrumentation map in XRay-instrumented object files and binaries. The
|
||||
``extract`` subcommand uses this particular library.
|
||||
``extract`` and ``stack`` subcommands uses this particular library.
|
||||
|
||||
Future Work
|
||||
===========
|
||||
@ -279,13 +308,17 @@ Future Work
|
||||
There are a number of ongoing efforts for expanding the toolset building around
|
||||
the XRay instrumentation system.
|
||||
|
||||
Trace Analysis
|
||||
--------------
|
||||
Trace Analysis Tools
|
||||
--------------------
|
||||
|
||||
We have more subcommands and modes that we're thinking of developing, in the
|
||||
following forms:
|
||||
|
||||
- ``stack``: Reconstruct the function call stacks in a timeline.
|
||||
- Work is in progress to integrate with or develop tools to visualize findings
|
||||
from an XRay trace. Particularly, the ``stack`` tool is being expanded to
|
||||
output formats that allow graphing and exploring the duration of time in each
|
||||
call stack.
|
||||
- With a large instrumented binary, the size of generated XRay traces can
|
||||
quickly become unwieldy. We are working on integrating pruning techniques and
|
||||
heuristics for the analysis tools to sift through the traces and surface only
|
||||
relevant information.
|
||||
|
||||
More Platforms
|
||||
--------------
|
||||
|
@ -60,7 +60,7 @@ to enable XRay at application start. To do this, XRay checks the
|
||||
$ ./bin/llc input.ll
|
||||
|
||||
# We need to set the XRAY_OPTIONS to enable some features.
|
||||
$ XRAY_OPTIONS="patch_premain=true" ./bin/llc input.ll
|
||||
$ XRAY_OPTIONS="patch_premain=true xray_mode=xray-basic verbosity=1" ./bin/llc input.ll
|
||||
==69819==XRay: Log file in 'xray-log.llc.m35qPB'
|
||||
|
||||
At this point we now have an XRay trace we can start analysing.
|
||||
@ -100,7 +100,7 @@ this data in a spreadsheet, we can output the results as CSV using the
|
||||
|
||||
If we want to get a textual representation of the raw trace we can use the
|
||||
``llvm-xray convert`` tool to get YAML output. The first few lines of that
|
||||
ouput for an example trace would look like the following:
|
||||
output for an example trace would look like the following:
|
||||
|
||||
::
|
||||
|
||||
@ -195,6 +195,70 @@ Given the above two files we can re-build by providing those two files as
|
||||
arguments to clang as ``-fxray-always-instrument=always-instrument.txt`` or
|
||||
``-fxray-never-instrument=never-instrument.txt``.
|
||||
|
||||
The XRay stack tool
|
||||
-------------------
|
||||
|
||||
Given a trace, and optionally an instrumentation map, the ``llvm-xray stack``
|
||||
command can be used to analyze a call stack graph constructed from the function
|
||||
call timeline.
|
||||
|
||||
The simplest way to use the command is simply to output the top stacks by call
|
||||
count and time spent.
|
||||
|
||||
::
|
||||
|
||||
$ llvm-xray stack xray-log.llc.5rqxkU -instr_map ./bin/llc
|
||||
|
||||
Unique Stacks: 3069
|
||||
Top 10 Stacks by leaf sum:
|
||||
|
||||
Sum: 9633790
|
||||
lvl function count sum
|
||||
#0 main 1 58421550
|
||||
#1 compileModule(char**, llvm::LLVMContext&) 1 51440360
|
||||
#2 llvm::legacy::PassManagerImpl::run(llvm::Module&) 1 40535375
|
||||
#3 llvm::FPPassManager::runOnModule(llvm::Module&) 2 39337525
|
||||
#4 llvm::FPPassManager::runOnFunction(llvm::Function&) 6 39331465
|
||||
#5 llvm::PMDataManager::verifyPreservedAnalysis(llvm::Pass*) 399 16628590
|
||||
#6 llvm::PMTopLevelManager::findAnalysisPass(void const*) 4584 15155600
|
||||
#7 llvm::PMDataManager::findAnalysisPass(void const*, bool) 32088 9633790
|
||||
|
||||
..etc..
|
||||
|
||||
In the default mode, identical stacks on different threads are independently
|
||||
aggregated. In a multithreaded program, you may end up having identical call
|
||||
stacks fill your list of top calls.
|
||||
|
||||
To address this, you may specify the ``-aggregate-threads`` or
|
||||
``-per-thread-stacks`` flags. ``-per-thread-stacks`` treats the thread id as an
|
||||
implicit root in each call stack tree, while ``-aggregate-threads`` combines
|
||||
identical stacks from all threads.
|
||||
|
||||
Flame Graph Generation
|
||||
----------------------
|
||||
|
||||
The ``llvm-xray stack`` tool may also be used to generate flamegraphs for
|
||||
visualizing your instrumented invocations. The tool does not generate the graphs
|
||||
themselves, but instead generates a format that can be used with Brendan Gregg's
|
||||
FlameGraph tool, currently available on `github
|
||||
<https://github.com/brendangregg/FlameGraph>`_.
|
||||
|
||||
To generate output for a flamegraph, a few more options are necessary.
|
||||
|
||||
- ``-all-stacks`` - Emits all of the stacks instead of just the top stacks.
|
||||
- ``-stack-format`` - Choose the flamegraph output format 'flame'.
|
||||
- ``-aggregation-type`` - Choose the metric to graph.
|
||||
|
||||
You may pipe the command output directly to the flamegraph tool to obtain an
|
||||
svg file.
|
||||
|
||||
::
|
||||
|
||||
$llvm-xray stack xray-log.llc.5rqxkU -instr_map ./bin/llc -stack-format=flame -aggregation-type=time -all-stacks | \
|
||||
/path/to/FlameGraph/flamegraph.pl > flamegraph.svg
|
||||
|
||||
If you open the svg in a browser, mouse events allow exploring the call stacks.
|
||||
|
||||
Further Exploration
|
||||
-------------------
|
||||
|
||||
@ -211,11 +275,11 @@ application.
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
[[clang::xray_always_intrument]] void f() {
|
||||
[[clang::xray_always_instrument]] void f() {
|
||||
std::cerr << '.';
|
||||
}
|
||||
|
||||
[[clang::xray_always_intrument]] void g() {
|
||||
[[clang::xray_always_instrument]] void g() {
|
||||
for (int i = 0; i < 1 << 10; ++i) {
|
||||
std::cerr << '-';
|
||||
}
|
||||
|
401
docs/XRayFDRFormat.rst
Normal file
401
docs/XRayFDRFormat.rst
Normal file
@ -0,0 +1,401 @@
|
||||
======================================
|
||||
XRay Flight Data Recorder Trace Format
|
||||
======================================
|
||||
|
||||
:Version: 1 as of 2017-07-20
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
When gathering XRay traces in Flight Data Recorder mode, each thread of an
|
||||
application will claim buffers to fill with trace data, which at some point
|
||||
is finalized and flushed.
|
||||
|
||||
A goal of the profiler is to minimize overhead, so the flushed data directly
|
||||
corresponds to the buffer.
|
||||
|
||||
This document describes the format of a trace file.
|
||||
|
||||
|
||||
General
|
||||
=======
|
||||
|
||||
Each trace file corresponds to a sequence of events in a particular thread.
|
||||
|
||||
The file has a header followed by a sequence of discriminated record types.
|
||||
|
||||
The endianness of byte fields matches the endianess of the platform which
|
||||
produced the trace file.
|
||||
|
||||
|
||||
Header Section
|
||||
==============
|
||||
|
||||
A trace file begins with a 32 byte header.
|
||||
|
||||
+-------------------+-----------------+----------------------------------------+
|
||||
| Field | Size (bytes) | Description |
|
||||
+===================+=================+========================================+
|
||||
| version | ``2`` | Anticipates versioned readers. This |
|
||||
| | | document describes the format when |
|
||||
| | | version == 1 |
|
||||
+-------------------+-----------------+----------------------------------------+
|
||||
| type | ``2`` | An enumeration encoding the type of |
|
||||
| | | trace. Flight Data Recorder mode |
|
||||
| | | traces have type == 1 |
|
||||
+-------------------+-----------------+----------------------------------------+
|
||||
| bitfield | ``4`` | Holds parameters that are not aligned |
|
||||
| | | to bytes. Further described below. |
|
||||
+-------------------+-----------------+----------------------------------------+
|
||||
| cycle_frequency | ``8`` | The frequency in hertz of the CPU |
|
||||
| | | oscillator used to measure duration of |
|
||||
| | | events in ticks. |
|
||||
+-------------------+-----------------+----------------------------------------+
|
||||
| buffer_size | ``8`` | The size in bytes of the data portion |
|
||||
| | | of the trace following the header. |
|
||||
+-------------------+-----------------+----------------------------------------+
|
||||
| reserved | ``8`` | Reserved for future use. |
|
||||
+-------------------+-----------------+----------------------------------------+
|
||||
|
||||
The bitfield parameter of the file header is composed of the following fields.
|
||||
|
||||
+-------------------+----------------+-----------------------------------------+
|
||||
| Field | Size (bits) | Description |
|
||||
+===================+================+=========================================+
|
||||
| constant_tsc | ``1`` | Whether the platform's timestamp |
|
||||
| | | counter used to record ticks between |
|
||||
| | | events ticks at a constant frequency |
|
||||
| | | despite CPU frequency changes. |
|
||||
| | | 0 == non-constant. 1 == constant. |
|
||||
+-------------------+----------------+-----------------------------------------+
|
||||
| nonstop_tsc | ``1`` | Whether the tsc continues to count |
|
||||
| | | despite whether the CPU is in a low |
|
||||
| | | power state. 0 == stop. 1 == non-stop. |
|
||||
+-------------------+----------------+-----------------------------------------+
|
||||
| reserved | ``30`` | Not meaningful. |
|
||||
+-------------------+----------------+-----------------------------------------+
|
||||
|
||||
|
||||
Data Section
|
||||
============
|
||||
|
||||
Following the header in a trace is a data section with size matching the
|
||||
buffer_size field in the header.
|
||||
|
||||
The data section is a stream of elements of different types.
|
||||
|
||||
There are a few categories of data in the sequence.
|
||||
|
||||
- ``Function Records``: Function Records contain the timing of entry into and
|
||||
exit from function execution. Function Records have 8 bytes each.
|
||||
|
||||
- ``Metadata Records``: Metadata records serve many purposes. Mostly, they
|
||||
capture information that may be too costly to record for each function, but
|
||||
that is required to contextualize the fine-grained timings. They also are used
|
||||
as markers for user-defined Event Data payloads. Metadata records have 16
|
||||
bytes each.
|
||||
|
||||
- ``Event Data``: Free form data may be associated with events that are traced
|
||||
by the binary and encode data defined by a handler function. Event data is
|
||||
always preceded with a marker record which indicates how large it is.
|
||||
|
||||
- ``Function Arguments``: The arguments to some functions are included in the
|
||||
trace. These are either pointer addresses or primitives that are read and
|
||||
logged independently of their types in a high level language. To the tracer,
|
||||
they are all simply numbers. Function Records that have attached arguments
|
||||
will indicate their presence on the function entry record. We only support
|
||||
logging contiguous function argument sequences starting with argument zero,
|
||||
which will be the "this" pointer for member function invocations. For example,
|
||||
we don't support logging the first and third argument.
|
||||
|
||||
A reader of the memory format must maintain a state machine. The format makes no
|
||||
attempt to pad for alignment, and it is not seekable.
|
||||
|
||||
|
||||
Function Records
|
||||
----------------
|
||||
|
||||
Function Records have an 8 byte layout. This layout encodes information to
|
||||
reconstruct a call stack of instrumented function and their durations.
|
||||
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| Field | Size (bits) | Description |
|
||||
+===============+==============+===============================================+
|
||||
| discriminant | ``1`` | Indicates whether a reader should read a |
|
||||
| | | Function or Metadata record. Set to ``0`` for |
|
||||
| | | Function records. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| action | ``3`` | Specifies whether the function is being |
|
||||
| | | entered, exited, or is a non-standard entry |
|
||||
| | | or exit produced by optimizations. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| function_id | ``28`` | A numeric ID for the function. Resolved to a |
|
||||
| | | name via the xray instrumentation map. The |
|
||||
| | | instrumentation map is built by xray at |
|
||||
| | | compile time into an object file and pairs |
|
||||
| | | the function ids to addresses. It is used for |
|
||||
| | | patching and as a lookup into the binary's |
|
||||
| | | symbols to obtain names. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| tsc_delta | ``32`` | The number of ticks of the timestamp counter |
|
||||
| | | since a previous record recorded a delta or |
|
||||
| | | other TSC resetting event. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
|
||||
On little-endian machines, the bitfields are ordered from least significant bit
|
||||
bit to most significant bit. A reader can read an 8 bit value and apply the mask
|
||||
``0x01`` for the discriminant. Similarly, they can read 32 bits and unsigned
|
||||
shift right by ``0x04`` to obtain the function_id field.
|
||||
|
||||
On big-endian machine, the bitfields are written in order from most significant
|
||||
bit to least significant bit. A reader would read an 8 bit value and unsigned
|
||||
shift right by 7 bits for the discriminant. The function_id field could be
|
||||
obtained by reading a 32 bit value and applying the mask ``0x0FFFFFFF``.
|
||||
|
||||
Function action types are as follows.
|
||||
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| Type | Number | Description |
|
||||
+===============+==============+===============================================+
|
||||
| Entry | ``0`` | Typical function entry. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| Exit | ``1`` | Typical function exit. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| Tail_Exit | ``2`` | An exit from a function due to tail call |
|
||||
| | | optimization. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| Entry_Args | ``3`` | A function entry that records arguments. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
|
||||
Entry_Args records do not contain the arguments themselves. Instead, metadata
|
||||
records for each of the logged args follow the function record in the stream.
|
||||
|
||||
|
||||
Metadata Records
|
||||
----------------
|
||||
|
||||
Interspersed throughout the buffer are 16 byte Metadata records. For typically
|
||||
instrumented binaries, they will be sparser than Function records, and they
|
||||
provide a fuller picture of the binary execution state.
|
||||
|
||||
Metadata record layout is partially record dependent, but they share a common
|
||||
structure.
|
||||
|
||||
The same bit field rules described for function records apply to the first byte
|
||||
of MetadataRecords. Within this byte, little endian machines use lsb to msb
|
||||
ordering and big endian machines use msb to lsb ordering.
|
||||
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| Field | Size | Description |
|
||||
+===============+==============+===============================================+
|
||||
| discriminant | ``1 bit`` | Indicates whether a reader should read a |
|
||||
| | | Function or Metadata record. Set to ``1`` for |
|
||||
| | | Metadata records. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| record_kind | ``7 bits`` | The type of Metadata record. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| data | ``15 bytes`` | A data field used differently for each record |
|
||||
| | | type. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
|
||||
Here is a table of the enumerated record kinds.
|
||||
|
||||
+--------+---------------------------+
|
||||
| Number | Type |
|
||||
+========+===========================+
|
||||
| 0 | NewBuffer |
|
||||
+--------+---------------------------+
|
||||
| 1 | EndOfBuffer |
|
||||
+--------+---------------------------+
|
||||
| 2 | NewCPUId |
|
||||
+--------+---------------------------+
|
||||
| 3 | TSCWrap |
|
||||
+--------+---------------------------+
|
||||
| 4 | WallTimeMarker |
|
||||
+--------+---------------------------+
|
||||
| 5 | CustomEventMarker |
|
||||
+--------+---------------------------+
|
||||
| 6 | CallArgument |
|
||||
+--------+---------------------------+
|
||||
|
||||
|
||||
NewBuffer Records
|
||||
-----------------
|
||||
|
||||
Each buffer begins with a NewBuffer record immediately after the header.
|
||||
It records the thread ID of the thread that the trace belongs to.
|
||||
|
||||
Its data segment is as follows.
|
||||
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| Field | Size (bytes) | Description |
|
||||
+===============+==============+===============================================+
|
||||
| thread_Id | ``2`` | Thread ID for buffer. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| reserved | ``13`` | Unused. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
|
||||
|
||||
WallClockTime Records
|
||||
---------------------
|
||||
|
||||
Following the NewBuffer record, each buffer records an absolute time as a frame
|
||||
of reference for the durations recorded by timestamp counter deltas.
|
||||
|
||||
Its data segment is as follows.
|
||||
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| Field | Size (bytes) | Description |
|
||||
+===============+==============+===============================================+
|
||||
| seconds | ``8`` | Seconds on absolute timescale. The starting |
|
||||
| | | point is unspecified and depends on the |
|
||||
| | | implementation and platform configured by the |
|
||||
| | | tracer. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| microseconds | ``4`` | The microsecond component of the time. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| reserved | ``3`` | Unused. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
|
||||
|
||||
NewCpuId Records
|
||||
----------------
|
||||
|
||||
Each function entry invokes a routine to determine what CPU is executing.
|
||||
Typically, this is done with readtscp, which reads the timestamp counter at the
|
||||
same time.
|
||||
|
||||
If the tracing detects that the execution has switched CPUs or if this is the
|
||||
first instrumented entry point, the tracer will output a NewCpuId record.
|
||||
|
||||
Its data segment is as follows.
|
||||
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| Field | Size (bytes) | Description |
|
||||
+===============+==============+===============================================+
|
||||
| cpu_id | ``2`` | CPU Id. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| absolute_tsc | ``8`` | The absolute value of the timestamp counter. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| reserved | ``5`` | Unused. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
|
||||
|
||||
TSCWrap Records
|
||||
---------------
|
||||
|
||||
Since each function record uses a 32 bit value to represent the number of ticks
|
||||
of the timestamp counter since the last reference, it is possible for this value
|
||||
to overflow, particularly for sparsely instrumented binaries.
|
||||
|
||||
When this delta would not fit into a 32 bit representation, a reference absolute
|
||||
timestamp counter record is written in the form of a TSCWrap record.
|
||||
|
||||
Its data segment is as follows.
|
||||
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| Field | Size (bytes) | Description |
|
||||
+===============+==============+===============================================+
|
||||
| absolute_tsc | ``8`` | Timestamp counter value. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| reserved | ``7`` | Unused. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
|
||||
|
||||
CallArgument Records
|
||||
--------------------
|
||||
|
||||
Immediately following an Entry_Args type function record, there may be one or
|
||||
more CallArgument records that contain the traced function's parameter values.
|
||||
|
||||
The order of the CallArgument Record sequency corresponds one to one with the
|
||||
order of the function parameters.
|
||||
|
||||
CallArgument data segment:
|
||||
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| Field | Size (bytes) | Description |
|
||||
+===============+==============+===============================================+
|
||||
| argument | ``8`` | Numeric argument (may be pointer address). |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| reserved | ``7`` | Unused. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
|
||||
|
||||
CustomEventMarker Records
|
||||
-------------------------
|
||||
|
||||
XRay provides the feature of logging custom events. This may be leveraged to
|
||||
record tracing info for RPCs or similarly trace data that is application
|
||||
specific.
|
||||
|
||||
Custom Events themselves are an unstructured (application defined) segment of
|
||||
memory with arbitrary size within the buffer. They are preceded by
|
||||
CustomEventMarkers to indicate their presence and size.
|
||||
|
||||
CustomEventMarker data segment:
|
||||
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| Field | Size (bytes) | Description |
|
||||
+===============+==============+===============================================+
|
||||
| event_size | ``4`` | Size of preceded event. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| absolute_tsc | ``8`` | A timestamp counter of the event. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
| reserved | ``3`` | Unused. |
|
||||
+---------------+--------------+-----------------------------------------------+
|
||||
|
||||
|
||||
EndOfBuffer Records
|
||||
-------------------
|
||||
|
||||
An EndOfBuffer record type indicates that there is no more trace data in this
|
||||
buffer. The reader is expected to seek past the remaining buffer_size expressed
|
||||
before the start of buffer and look for either another header or EOF.
|
||||
|
||||
|
||||
Format Grammar and Invariants
|
||||
=============================
|
||||
|
||||
Not all sequences of Metadata records and Function records are valid data. A
|
||||
sequence should be parsed as a state machine. The expectations for a valid
|
||||
format can be expressed as a context free grammar.
|
||||
|
||||
This is an attempt to explain the format with statements in EBNF format.
|
||||
|
||||
- Format := Header ThreadBuffer* EOF
|
||||
|
||||
- ThreadBuffer := NewBuffer WallClockTime NewCPUId BodySequence* End
|
||||
|
||||
- BodySequence := NewCPUId | TSCWrap | Function | CustomEvent
|
||||
|
||||
- Function := (Function_Entry_Args CallArgument*) | Function_Other_Type
|
||||
|
||||
- CustomEvent := CustomEventMarker CustomEventUnstructuredMemory
|
||||
|
||||
- End := EndOfBuffer RemainingBufferSizeToSkip
|
||||
|
||||
|
||||
Function Record Order
|
||||
---------------------
|
||||
|
||||
There are a few clarifications that may help understand what is expected of
|
||||
Function records.
|
||||
|
||||
- Functions with an Exit are expected to have a corresponding Entry or
|
||||
Entry_Args function record precede them in the trace.
|
||||
|
||||
- Tail_Exit Function records record the Function ID of the function whose return
|
||||
address the program counter will take. In other words, the final function that
|
||||
would be popped off of the call stack if tail call optimization was not used.
|
||||
|
||||
- Not all functions marked for instrumentation are necessarily in the trace. The
|
||||
tracer uses heuristics to preserve the trace for non-trivial functions.
|
||||
|
||||
- Not every entry must have a traced Exit or Tail Exit. The buffer may run out
|
||||
of space or the program may request for the tracer to finalize toreturn the
|
||||
buffer before an instrumented function exits.
|
@ -466,7 +466,7 @@ looks like:
|
||||
return StringRef();
|
||||
}
|
||||
// Determine if this scalar needs quotes.
|
||||
static bool mustQuote(StringRef) { return true; }
|
||||
static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
|
||||
};
|
||||
|
||||
Block Scalars
|
||||
|
@ -48,9 +48,9 @@ copyright = u'2003-%d, LLVM Project' % date.today().year
|
||||
# built documents.
|
||||
#
|
||||
# The short version.
|
||||
version = '5'
|
||||
version = '6'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '5'
|
||||
release = '6'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@ -1,6 +1,11 @@
|
||||
Overview
|
||||
========
|
||||
|
||||
.. warning::
|
||||
|
||||
If you are using a released version of LLVM, see `the download page
|
||||
<http://llvm.org/releases/>`_ to find your documentation.
|
||||
|
||||
The LLVM compiler infrastructure supports a wide range of projects, from
|
||||
industrial strength compilers to specialized JIT applications to small
|
||||
research projects.
|
||||
@ -63,6 +68,7 @@ representation.
|
||||
CMakePrimer
|
||||
AdvancedBuilds
|
||||
HowToBuildOnARM
|
||||
HowToCrossCompileBuiltinsOnArm
|
||||
HowToCrossCompileLLVM
|
||||
CommandGuide/index
|
||||
GettingStarted
|
||||
@ -100,6 +106,9 @@ representation.
|
||||
:doc:`HowToBuildOnARM`
|
||||
Notes on building and testing LLVM/Clang on ARM.
|
||||
|
||||
:doc:`HowToCrossCompileBuiltinsOnArm`
|
||||
Notes on cross-building and testing the compiler-rt builtins for Arm.
|
||||
|
||||
:doc:`HowToCrossCompileLLVM`
|
||||
Notes on cross-building and testing LLVM/Clang.
|
||||
|
||||
@ -154,7 +163,7 @@ representation.
|
||||
misunderstood instruction.
|
||||
|
||||
:doc:`Frontend/PerformanceTips`
|
||||
A collection of tips for frontend authors on how to generate IR
|
||||
A collection of tips for frontend authors on how to generate IR
|
||||
which LLVM is able to effectively optimize.
|
||||
|
||||
:doc:`Docker`
|
||||
@ -178,6 +187,7 @@ For developers of applications which use LLVM as a library.
|
||||
ProgrammersManual
|
||||
Extensions
|
||||
LibFuzzer
|
||||
FuzzingLLVM
|
||||
ScudoHardenedAllocator
|
||||
OptBisect
|
||||
|
||||
@ -211,7 +221,6 @@ For developers of applications which use LLVM as a library.
|
||||
|
||||
`Doxygen generated documentation <http://llvm.org/doxygen/>`_
|
||||
(`classes <http://llvm.org/doxygen/inherits.html>`_)
|
||||
(`tarball <http://llvm.org/doxygen/doxygen.tar.gz>`_)
|
||||
|
||||
`Documentation for Go bindings <http://godoc.org/llvm.org/llvm/bindings/go/llvm>`_
|
||||
|
||||
@ -224,6 +233,9 @@ For developers of applications which use LLVM as a library.
|
||||
:doc:`LibFuzzer`
|
||||
A library for writing in-process guided fuzzers.
|
||||
|
||||
:doc:`FuzzingLLVM`
|
||||
Information on writing and using Fuzzers to find bugs in LLVM.
|
||||
|
||||
:doc:`ScudoHardenedAllocator`
|
||||
A library that implements a security-hardened `malloc()`.
|
||||
|
||||
@ -275,7 +287,9 @@ For API clients and LLVM developers.
|
||||
GlobalISel
|
||||
XRay
|
||||
XRayExample
|
||||
XRayFDRFormat
|
||||
PDB/index
|
||||
CFIVerify
|
||||
|
||||
:doc:`WritingAnLLVMPass`
|
||||
Information on how to write LLVM transformations and analyses.
|
||||
@ -406,6 +420,9 @@ For API clients and LLVM developers.
|
||||
:doc:`The Microsoft PDB File Format <PDB/index>`
|
||||
A detailed description of the Microsoft PDB (Program Database) file format.
|
||||
|
||||
:doc:`CFIVerify`
|
||||
A description of the verification tool for Control Flow Integrity.
|
||||
|
||||
Development Process Documentation
|
||||
=================================
|
||||
|
||||
|
@ -75,8 +75,7 @@ will look like:
|
||||
std::unique_ptr<Module> M = buildModule();
|
||||
JIT J;
|
||||
Handle H = J.addModule(*M);
|
||||
int (*Main)(int, char*[]) =
|
||||
(int(*)(int, char*[])J.findSymbol("main").getAddress();
|
||||
int (*Main)(int, char*[]) = (int(*)(int, char*[]))J.getSymbolAddress("main");
|
||||
int Result = Main();
|
||||
J.removeModule(H);
|
||||
|
||||
@ -111,14 +110,24 @@ usual include guards and #includes [2]_, we get to the definition of our class:
|
||||
#ifndef LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H
|
||||
#define LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H
|
||||
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
||||
#include "llvm/ExecutionEngine/JITSymbol.h"
|
||||
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
|
||||
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
|
||||
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
|
||||
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
|
||||
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
|
||||
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
|
||||
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/Mangler.h"
|
||||
#include "llvm/Support/DynamicLibrary.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
namespace orc {
|
||||
@ -127,38 +136,39 @@ usual include guards and #includes [2]_, we get to the definition of our class:
|
||||
private:
|
||||
std::unique_ptr<TargetMachine> TM;
|
||||
const DataLayout DL;
|
||||
ObjectLinkingLayer<> ObjectLayer;
|
||||
IRCompileLayer<decltype(ObjectLayer)> CompileLayer;
|
||||
RTDyldObjectLinkingLayer ObjectLayer;
|
||||
IRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
|
||||
|
||||
public:
|
||||
typedef decltype(CompileLayer)::ModuleSetHandleT ModuleHandleT;
|
||||
using ModuleHandle = decltype(CompileLayer)::ModuleHandleT;
|
||||
|
||||
Our class begins with four members: A TargetMachine, TM, which will be used
|
||||
to build our LLVM compiler instance; A DataLayout, DL, which will be used for
|
||||
Our class begins with four members: A TargetMachine, TM, which will be used to
|
||||
build our LLVM compiler instance; A DataLayout, DL, which will be used for
|
||||
symbol mangling (more on that later), and two ORC *layers*: an
|
||||
ObjectLinkingLayer and a IRCompileLayer. We'll be talking more about layers in
|
||||
the next chapter, but for now you can think of them as analogous to LLVM
|
||||
RTDyldObjectLinkingLayer and a CompileLayer. We'll be talking more about layers
|
||||
in the next chapter, but for now you can think of them as analogous to LLVM
|
||||
Passes: they wrap up useful JIT utilities behind an easy to compose interface.
|
||||
The first layer, ObjectLinkingLayer, is the foundation of our JIT: it takes
|
||||
in-memory object files produced by a compiler and links them on the fly to make
|
||||
them executable. This JIT-on-top-of-a-linker design was introduced in MCJIT,
|
||||
however the linker was hidden inside the MCJIT class. In ORC we expose the
|
||||
linker so that clients can access and configure it directly if they need to. In
|
||||
this tutorial our ObjectLinkingLayer will just be used to support the next layer
|
||||
in our stack: the IRCompileLayer, which will be responsible for taking LLVM IR,
|
||||
compiling it, and passing the resulting in-memory object files down to the
|
||||
object linking layer below.
|
||||
The first layer, ObjectLayer, is the foundation of our JIT: it takes in-memory
|
||||
object files produced by a compiler and links them on the fly to make them
|
||||
executable. This JIT-on-top-of-a-linker design was introduced in MCJIT, however
|
||||
the linker was hidden inside the MCJIT class. In ORC we expose the linker so
|
||||
that clients can access and configure it directly if they need to. In this
|
||||
tutorial our ObjectLayer will just be used to support the next layer in our
|
||||
stack: the CompileLayer, which will be responsible for taking LLVM IR, compiling
|
||||
it, and passing the resulting in-memory object files down to the object linking
|
||||
layer below.
|
||||
|
||||
That's it for member variables, after that we have a single typedef:
|
||||
ModuleHandleT. This is the handle type that will be returned from our JIT's
|
||||
ModuleHandle. This is the handle type that will be returned from our JIT's
|
||||
addModule method, and can be passed to the removeModule method to remove a
|
||||
module. The IRCompileLayer class already provides a convenient handle type
|
||||
(IRCompileLayer::ModuleSetHandleT), so we just alias our ModuleHandleT to this.
|
||||
(IRCompileLayer::ModuleHandleT), so we just alias our ModuleHandle to this.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
KaleidoscopeJIT()
|
||||
: TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
|
||||
ObjectLayer([]() { return std::make_shared<SectionMemoryManager>(); }),
|
||||
CompileLayer(ObjectLayer, SimpleCompiler(*TM)) {
|
||||
llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
|
||||
}
|
||||
@ -166,17 +176,22 @@ module. The IRCompileLayer class already provides a convenient handle type
|
||||
TargetMachine &getTargetMachine() { return *TM; }
|
||||
|
||||
Next up we have our class constructor. We begin by initializing TM using the
|
||||
EngineBuilder::selectTarget helper method, which constructs a TargetMachine for
|
||||
the current process. Next we use our newly created TargetMachine to initialize
|
||||
DL, our DataLayout. Then we initialize our IRCompileLayer. Our IRCompile layer
|
||||
needs two things: (1) A reference to our object linking layer, and (2) a
|
||||
compiler instance to use to perform the actual compilation from IR to object
|
||||
files. We use the off-the-shelf SimpleCompiler instance for now. Finally, in
|
||||
the body of the constructor, we call the DynamicLibrary::LoadLibraryPermanently
|
||||
method with a nullptr argument. Normally the LoadLibraryPermanently method is
|
||||
called with the path of a dynamic library to load, but when passed a null
|
||||
pointer it will 'load' the host process itself, making its exported symbols
|
||||
available for execution.
|
||||
EngineBuilder::selectTarget helper method which constructs a TargetMachine for
|
||||
the current process. Then we use our newly created TargetMachine to initialize
|
||||
DL, our DataLayout. After that we need to initialize our ObjectLayer. The
|
||||
ObjectLayer requires a function object that will build a JIT memory manager for
|
||||
each module that is added (a JIT memory manager manages memory allocations,
|
||||
memory permissions, and registration of exception handlers for JIT'd code). For
|
||||
this we use a lambda that returns a SectionMemoryManager, an off-the-shelf
|
||||
utility that provides all the basic memory management functionality required for
|
||||
this chapter. Next we initialize our CompileLayer. The CompileLayer needs two
|
||||
things: (1) A reference to our object layer, and (2) a compiler instance to use
|
||||
to perform the actual compilation from IR to object files. We use the
|
||||
off-the-shelf SimpleCompiler instance for now. Finally, in the body of the
|
||||
constructor, we call the DynamicLibrary::LoadLibraryPermanently method with a
|
||||
nullptr argument. Normally the LoadLibraryPermanently method is called with the
|
||||
path of a dynamic library to load, but when passed a null pointer it will 'load'
|
||||
the host process itself, making its exported symbols available for execution.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
@ -191,48 +206,36 @@ available for execution.
|
||||
return Sym;
|
||||
return JITSymbol(nullptr);
|
||||
},
|
||||
[](const std::string &S) {
|
||||
[](const std::string &Name) {
|
||||
if (auto SymAddr =
|
||||
RTDyldMemoryManager::getSymbolAddressInProcess(Name))
|
||||
return JITSymbol(SymAddr, JITSymbolFlags::Exported);
|
||||
return JITSymbol(nullptr);
|
||||
});
|
||||
|
||||
// Build a singleton module set to hold our module.
|
||||
std::vector<std::unique_ptr<Module>> Ms;
|
||||
Ms.push_back(std::move(M));
|
||||
|
||||
// Add the set to the JIT with the resolver we created above and a newly
|
||||
// created SectionMemoryManager.
|
||||
return CompileLayer.addModuleSet(std::move(Ms),
|
||||
make_unique<SectionMemoryManager>(),
|
||||
std::move(Resolver));
|
||||
return cantFail(CompileLayer.addModule(std::move(M),
|
||||
std::move(Resolver)));
|
||||
}
|
||||
|
||||
Now we come to the first of our JIT API methods: addModule. This method is
|
||||
responsible for adding IR to the JIT and making it available for execution. In
|
||||
this initial implementation of our JIT we will make our modules "available for
|
||||
execution" by adding them straight to the IRCompileLayer, which will
|
||||
immediately compile them. In later chapters we will teach our JIT to be lazier
|
||||
and instead add the Modules to a "pending" list to be compiled if and when they
|
||||
are first executed.
|
||||
execution" by adding them straight to the CompileLayer, which will immediately
|
||||
compile them. In later chapters we will teach our JIT to defer compilation
|
||||
of individual functions until they're actually called.
|
||||
|
||||
To add our module to the IRCompileLayer we need to supply two auxiliary objects
|
||||
(as well as the module itself): a memory manager and a symbol resolver. The
|
||||
memory manager will be responsible for managing the memory allocated to JIT'd
|
||||
machine code, setting memory permissions, and registering exception handling
|
||||
tables (if the JIT'd code uses exceptions). For our memory manager we will use
|
||||
the SectionMemoryManager class: another off-the-shelf utility that provides all
|
||||
the basic functionality we need. The second auxiliary class, the symbol
|
||||
resolver, is more interesting for us. It exists to tell the JIT where to look
|
||||
when it encounters an *external symbol* in the module we are adding. External
|
||||
To add our module to the CompileLayer we need to supply both the module and a
|
||||
symbol resolver. The symbol resolver is responsible for supplying the JIT with
|
||||
an address for each *external symbol* in the module we are adding. External
|
||||
symbols are any symbol not defined within the module itself, including calls to
|
||||
functions outside the JIT and calls to functions defined in other modules that
|
||||
have already been added to the JIT. It may seem as though modules added to the
|
||||
JIT should "know about one another" by default, but since we would still have to
|
||||
have already been added to the JIT. (It may seem as though modules added to the
|
||||
JIT should know about one another by default, but since we would still have to
|
||||
supply a symbol resolver for references to code outside the JIT it turns out to
|
||||
be easier to just re-use this one mechanism for all symbol resolution. This has
|
||||
the added benefit that the user has full control over the symbol resolution
|
||||
be easier to re-use this one mechanism for all symbol resolution.) This has the
|
||||
added benefit that the user has full control over the symbol resolution
|
||||
process. Should we search for definitions within the JIT first, then fall back
|
||||
on external definitions? Or should we prefer external definitions where
|
||||
available and only JIT code if we don't already have an available
|
||||
@ -263,12 +266,13 @@ symbol definition via either of these paths, the JIT will refuse to accept our
|
||||
module, returning a "symbol not found" error.
|
||||
|
||||
Now that we've built our symbol resolver, we're ready to add our module to the
|
||||
JIT. We do this by calling the CompileLayer's addModuleSet method [4]_. Since
|
||||
we only have a single Module and addModuleSet expects a collection, we will
|
||||
create a vector of modules and add our module as the only member. Since we
|
||||
have already typedef'd our ModuleHandleT type to be the same as the
|
||||
CompileLayer's handle type, we can return the handle from addModuleSet
|
||||
directly from our addModule method.
|
||||
JIT. We do this by calling the CompileLayer's addModule method. The addModule
|
||||
method returns an ``Expected<CompileLayer::ModuleHandle>``, since in more
|
||||
advanced JIT configurations it could fail. In our basic configuration we know
|
||||
that it will always succeed so we use the cantFail utility to assert that no
|
||||
error occurred, and extract the handle value. Since we have already typedef'd
|
||||
our ModuleHandle type to be the same as the CompileLayer's handle type, we can
|
||||
return the unwrapped handle directly.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
@ -279,19 +283,29 @@ directly from our addModule method.
|
||||
return CompileLayer.findSymbol(MangledNameStream.str(), true);
|
||||
}
|
||||
|
||||
JITTargetAddress getSymbolAddress(const std::string Name) {
|
||||
return cantFail(findSymbol(Name).getAddress());
|
||||
}
|
||||
|
||||
void removeModule(ModuleHandle H) {
|
||||
CompileLayer.removeModuleSet(H);
|
||||
cantFail(CompileLayer.removeModule(H));
|
||||
}
|
||||
|
||||
Now that we can add code to our JIT, we need a way to find the symbols we've
|
||||
added to it. To do that we call the findSymbol method on our IRCompileLayer,
|
||||
but with a twist: We have to *mangle* the name of the symbol we're searching
|
||||
for first. The reason for this is that the ORC JIT components use mangled
|
||||
symbols internally the same way a static compiler and linker would, rather
|
||||
than using plain IR symbol names. The kind of mangling will depend on the
|
||||
DataLayout, which in turn depends on the target platform. To allow us to
|
||||
remain portable and search based on the un-mangled name, we just re-produce
|
||||
this mangling ourselves.
|
||||
added to it. To do that we call the findSymbol method on our CompileLayer, but
|
||||
with a twist: We have to *mangle* the name of the symbol we're searching for
|
||||
first. The ORC JIT components use mangled symbols internally the same way a
|
||||
static compiler and linker would, rather than using plain IR symbol names. This
|
||||
allows JIT'd code to interoperate easily with precompiled code in the
|
||||
application or shared libraries. The kind of mangling will depend on the
|
||||
DataLayout, which in turn depends on the target platform. To allow us to remain
|
||||
portable and search based on the un-mangled name, we just re-produce this
|
||||
mangling ourselves.
|
||||
|
||||
Next we have a convenience function, getSymbolAddress, which returns the address
|
||||
of a given symbol. Like CompileLayer's addModule function, JITSymbol's getAddress
|
||||
function is allowed to fail [4]_, however we know that it will not in our simple
|
||||
example, so we wrap it in a call to cantFail.
|
||||
|
||||
We now come to the last method in our JIT API: removeModule. This method is
|
||||
responsible for destructing the MemoryManager and SymbolResolver that were
|
||||
@ -302,7 +316,10 @@ treated as a duplicate definition when the next top-level expression is
|
||||
entered. It is generally good to free any module that you know you won't need
|
||||
to call further, just to free up the resources dedicated to it. However, you
|
||||
don't strictly need to do this: All resources will be cleaned up when your
|
||||
JIT class is destructed, if they haven't been freed before then.
|
||||
JIT class is destructed, if they haven't been freed before then. Like
|
||||
``CompileLayer::addModule`` and ``JITSymbol::getAddress``, removeModule may
|
||||
fail in general but will never fail in our example, so we wrap it in a call to
|
||||
cantFail.
|
||||
|
||||
This brings us to the end of Chapter 1 of Building a JIT. You now have a basic
|
||||
but fully functioning JIT stack that you can use to take LLVM IR and make it
|
||||
@ -321,7 +338,7 @@ example, use:
|
||||
.. code-block:: bash
|
||||
|
||||
# Compile
|
||||
clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core orc native` -O3 -o toy
|
||||
clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core orcjit native` -O3 -o toy
|
||||
# Run
|
||||
./toy
|
||||
|
||||
@ -337,36 +354,45 @@ Here is the code:
|
||||
left as an exercise for the reader. (The KaleidoscopeJIT.h used in the
|
||||
original tutorials will be a helpful reference).
|
||||
|
||||
.. [2] +-----------------------+-----------------------------------------------+
|
||||
| File | Reason for inclusion |
|
||||
+=======================+===============================================+
|
||||
| ExecutionEngine.h | Access to the EngineBuilder::selectTarget |
|
||||
| | method. |
|
||||
+-----------------------+-----------------------------------------------+
|
||||
| | Access to the |
|
||||
| RTDyldMemoryManager.h | RTDyldMemoryManager::getSymbolAddressInProcess|
|
||||
| | method. |
|
||||
+-----------------------+-----------------------------------------------+
|
||||
| CompileUtils.h | Provides the SimpleCompiler class. |
|
||||
+-----------------------+-----------------------------------------------+
|
||||
| IRCompileLayer.h | Provides the IRCompileLayer class. |
|
||||
+-----------------------+-----------------------------------------------+
|
||||
| | Access the createLambdaResolver function, |
|
||||
| LambdaResolver.h | which provides easy construction of symbol |
|
||||
| | resolvers. |
|
||||
+-----------------------+-----------------------------------------------+
|
||||
| ObjectLinkingLayer.h | Provides the ObjectLinkingLayer class. |
|
||||
+-----------------------+-----------------------------------------------+
|
||||
| Mangler.h | Provides the Mangler class for platform |
|
||||
| | specific name-mangling. |
|
||||
+-----------------------+-----------------------------------------------+
|
||||
| DynamicLibrary.h | Provides the DynamicLibrary class, which |
|
||||
| | makes symbols in the host process searchable. |
|
||||
+-----------------------+-----------------------------------------------+
|
||||
.. [2] +-----------------------------+-----------------------------------------------+
|
||||
| File | Reason for inclusion |
|
||||
+=============================+===============================================+
|
||||
| STLExtras.h | LLVM utilities that are useful when working |
|
||||
| | with the STL. |
|
||||
+-----------------------------+-----------------------------------------------+
|
||||
| ExecutionEngine.h | Access to the EngineBuilder::selectTarget |
|
||||
| | method. |
|
||||
+-----------------------------+-----------------------------------------------+
|
||||
| | Access to the |
|
||||
| RTDyldMemoryManager.h | RTDyldMemoryManager::getSymbolAddressInProcess|
|
||||
| | method. |
|
||||
+-----------------------------+-----------------------------------------------+
|
||||
| CompileUtils.h | Provides the SimpleCompiler class. |
|
||||
+-----------------------------+-----------------------------------------------+
|
||||
| IRCompileLayer.h | Provides the IRCompileLayer class. |
|
||||
+-----------------------------+-----------------------------------------------+
|
||||
| | Access the createLambdaResolver function, |
|
||||
| LambdaResolver.h | which provides easy construction of symbol |
|
||||
| | resolvers. |
|
||||
+-----------------------------+-----------------------------------------------+
|
||||
| RTDyldObjectLinkingLayer.h | Provides the RTDyldObjectLinkingLayer class. |
|
||||
+-----------------------------+-----------------------------------------------+
|
||||
| Mangler.h | Provides the Mangler class for platform |
|
||||
| | specific name-mangling. |
|
||||
+-----------------------------+-----------------------------------------------+
|
||||
| DynamicLibrary.h | Provides the DynamicLibrary class, which |
|
||||
| | makes symbols in the host process searchable. |
|
||||
+-----------------------------+-----------------------------------------------+
|
||||
| | A fast output stream class. We use the |
|
||||
| raw_ostream.h | raw_string_ostream subclass for symbol |
|
||||
| | mangling |
|
||||
+-----------------------------+-----------------------------------------------+
|
||||
| TargetMachine.h | LLVM target machine description class. |
|
||||
+-----------------------------+-----------------------------------------------+
|
||||
|
||||
.. [3] Actually they don't have to be lambdas, any object with a call operator
|
||||
will do, including plain old functions or std::functions.
|
||||
|
||||
.. [4] ORC layers accept sets of Modules, rather than individual ones, so that
|
||||
all Modules in the set could be co-located by the memory manager, though
|
||||
this feature is not yet implemented.
|
||||
.. [4] ``JITSymbol::getAddress`` will force the JIT to compile the definition of
|
||||
the symbol if it hasn't already been compiled, and since the compilation
|
||||
process could fail getAddress must be able to return this failure.
|
||||
|
@ -46,7 +46,7 @@ Chapter 1 and compose an ORC *IRTransformLayer* on top. We will look at how the
|
||||
IRTransformLayer works in more detail below, but the interface is simple: the
|
||||
constructor for this layer takes a reference to the layer below (as all layers
|
||||
do) plus an *IR optimization function* that it will apply to each Module that
|
||||
is added via addModuleSet:
|
||||
is added via addModule:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
@ -54,19 +54,20 @@ is added via addModuleSet:
|
||||
private:
|
||||
std::unique_ptr<TargetMachine> TM;
|
||||
const DataLayout DL;
|
||||
ObjectLinkingLayer<> ObjectLayer;
|
||||
RTDyldObjectLinkingLayer<> ObjectLayer;
|
||||
IRCompileLayer<decltype(ObjectLayer)> CompileLayer;
|
||||
|
||||
typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>
|
||||
OptimizeFunction;
|
||||
using OptimizeFunction =
|
||||
std::function<std::shared_ptr<Module>(std::shared_ptr<Module>)>;
|
||||
|
||||
IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
|
||||
|
||||
public:
|
||||
typedef decltype(OptimizeLayer)::ModuleSetHandleT ModuleHandle;
|
||||
using ModuleHandle = decltype(OptimizeLayer)::ModuleHandleT;
|
||||
|
||||
KaleidoscopeJIT()
|
||||
: TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
|
||||
ObjectLayer([]() { return std::make_shared<SectionMemoryManager>(); }),
|
||||
CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
|
||||
OptimizeLayer(CompileLayer,
|
||||
[this](std::unique_ptr<Module> M) {
|
||||
@ -101,9 +102,8 @@ define below.
|
||||
.. code-block:: c++
|
||||
|
||||
// ...
|
||||
return OptimizeLayer.addModuleSet(std::move(Ms),
|
||||
make_unique<SectionMemoryManager>(),
|
||||
std::move(Resolver));
|
||||
return cantFail(OptimizeLayer.addModule(std::move(M),
|
||||
std::move(Resolver)));
|
||||
// ...
|
||||
|
||||
.. code-block:: c++
|
||||
@ -115,17 +115,17 @@ define below.
|
||||
.. code-block:: c++
|
||||
|
||||
// ...
|
||||
OptimizeLayer.removeModuleSet(H);
|
||||
cantFail(OptimizeLayer.removeModule(H));
|
||||
// ...
|
||||
|
||||
Next we need to replace references to 'CompileLayer' with references to
|
||||
OptimizeLayer in our key methods: addModule, findSymbol, and removeModule. In
|
||||
addModule we need to be careful to replace both references: the findSymbol call
|
||||
inside our resolver, and the call through to addModuleSet.
|
||||
inside our resolver, and the call through to addModule.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
std::unique_ptr<Module> optimizeModule(std::unique_ptr<Module> M) {
|
||||
std::shared_ptr<Module> optimizeModule(std::shared_ptr<Module> M) {
|
||||
// Create a function pass manager.
|
||||
auto FPM = llvm::make_unique<legacy::FunctionPassManager>(M.get());
|
||||
|
||||
@ -166,37 +166,30 @@ implementations of the layer concept that can be devised:
|
||||
template <typename BaseLayerT, typename TransformFtor>
|
||||
class IRTransformLayer {
|
||||
public:
|
||||
typedef typename BaseLayerT::ModuleSetHandleT ModuleSetHandleT;
|
||||
using ModuleHandleT = typename BaseLayerT::ModuleHandleT;
|
||||
|
||||
IRTransformLayer(BaseLayerT &BaseLayer,
|
||||
TransformFtor Transform = TransformFtor())
|
||||
: BaseLayer(BaseLayer), Transform(std::move(Transform)) {}
|
||||
|
||||
template <typename ModuleSetT, typename MemoryManagerPtrT,
|
||||
typename SymbolResolverPtrT>
|
||||
ModuleSetHandleT addModuleSet(ModuleSetT Ms,
|
||||
MemoryManagerPtrT MemMgr,
|
||||
SymbolResolverPtrT Resolver) {
|
||||
|
||||
for (auto I = Ms.begin(), E = Ms.end(); I != E; ++I)
|
||||
*I = Transform(std::move(*I));
|
||||
|
||||
return BaseLayer.addModuleSet(std::move(Ms), std::move(MemMgr),
|
||||
std::move(Resolver));
|
||||
Expected<ModuleHandleT>
|
||||
addModule(std::shared_ptr<Module> M,
|
||||
std::shared_ptr<JITSymbolResolver> Resolver) {
|
||||
return BaseLayer.addModule(Transform(std::move(M)), std::move(Resolver));
|
||||
}
|
||||
|
||||
void removeModuleSet(ModuleSetHandleT H) { BaseLayer.removeModuleSet(H); }
|
||||
void removeModule(ModuleHandleT H) { BaseLayer.removeModule(H); }
|
||||
|
||||
JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
|
||||
return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
|
||||
}
|
||||
|
||||
JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
|
||||
JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
|
||||
bool ExportedSymbolsOnly) {
|
||||
return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly);
|
||||
}
|
||||
|
||||
void emitAndFinalize(ModuleSetHandleT H) {
|
||||
void emitAndFinalize(ModuleHandleT H) {
|
||||
BaseLayer.emitAndFinalize(H);
|
||||
}
|
||||
|
||||
@ -215,14 +208,14 @@ comments. It is a template class with two template arguments: ``BaesLayerT`` and
|
||||
``TransformFtor`` that provide the type of the base layer and the type of the
|
||||
"transform functor" (in our case a std::function) respectively. This class is
|
||||
concerned with two very simple jobs: (1) Running every IR Module that is added
|
||||
with addModuleSet through the transform functor, and (2) conforming to the ORC
|
||||
with addModule through the transform functor, and (2) conforming to the ORC
|
||||
layer interface. The interface consists of one typedef and five methods:
|
||||
|
||||
+------------------+-----------------------------------------------------------+
|
||||
| Interface | Description |
|
||||
+==================+===========================================================+
|
||||
| | Provides a handle that can be used to identify a module |
|
||||
| ModuleSetHandleT | set when calling findSymbolIn, removeModuleSet, or |
|
||||
| ModuleHandleT | set when calling findSymbolIn, removeModule, or |
|
||||
| | emitAndFinalize. |
|
||||
+------------------+-----------------------------------------------------------+
|
||||
| | Takes a given set of Modules and makes them "available |
|
||||
@ -231,28 +224,28 @@ layer interface. The interface consists of one typedef and five methods:
|
||||
| | the address of the symbols should be read/writable (for |
|
||||
| | data symbols), or executable (for function symbols) after |
|
||||
| | JITSymbol::getAddress() is called. Note: This means that |
|
||||
| addModuleSet | addModuleSet doesn't have to compile (or do any other |
|
||||
| addModule | addModule doesn't have to compile (or do any other |
|
||||
| | work) up-front. It *can*, like IRCompileLayer, act |
|
||||
| | eagerly, but it can also simply record the module and |
|
||||
| | take no further action until somebody calls |
|
||||
| | JITSymbol::getAddress(). In IRTransformLayer's case |
|
||||
| | addModuleSet eagerly applies the transform functor to |
|
||||
| | addModule eagerly applies the transform functor to |
|
||||
| | each module in the set, then passes the resulting set |
|
||||
| | of mutated modules down to the layer below. |
|
||||
+------------------+-----------------------------------------------------------+
|
||||
| | Removes a set of modules from the JIT. Code or data |
|
||||
| removeModuleSet | defined in these modules will no longer be available, and |
|
||||
| removeModule | defined in these modules will no longer be available, and |
|
||||
| | the memory holding the JIT'd definitions will be freed. |
|
||||
+------------------+-----------------------------------------------------------+
|
||||
| | Searches for the named symbol in all modules that have |
|
||||
| | previously been added via addModuleSet (and not yet |
|
||||
| findSymbol | removed by a call to removeModuleSet). In |
|
||||
| | previously been added via addModule (and not yet |
|
||||
| findSymbol | removed by a call to removeModule). In |
|
||||
| | IRTransformLayer we just pass the query on to the layer |
|
||||
| | below. In our REPL this is our default way to search for |
|
||||
| | function definitions. |
|
||||
+------------------+-----------------------------------------------------------+
|
||||
| | Searches for the named symbol in the module set indicated |
|
||||
| | by the given ModuleSetHandleT. This is just an optimized |
|
||||
| | by the given ModuleHandleT. This is just an optimized |
|
||||
| | search, better for lookup-speed when you know exactly |
|
||||
| | a symbol definition should be found. In IRTransformLayer |
|
||||
| findSymbolIn | we just pass this query on to the layer below. In our |
|
||||
@ -262,7 +255,7 @@ layer interface. The interface consists of one typedef and five methods:
|
||||
| | we just added. |
|
||||
+------------------+-----------------------------------------------------------+
|
||||
| | Forces all of the actions required to make the code and |
|
||||
| | data in a module set (represented by a ModuleSetHandleT) |
|
||||
| | data in a module set (represented by a ModuleHandleT) |
|
||||
| | accessible. Behaves as if some symbol in the set had been |
|
||||
| | searched for and JITSymbol::getSymbolAddress called. This |
|
||||
| emitAndFinalize | is rarely needed, but can be useful when dealing with |
|
||||
@ -276,11 +269,11 @@ wrinkles like emitAndFinalize for performance), similar to the basic JIT API
|
||||
operations we identified in Chapter 1. Conforming to the layer concept allows
|
||||
classes to compose neatly by implementing their behaviors in terms of the these
|
||||
same operations, carried out on the layer below. For example, an eager layer
|
||||
(like IRTransformLayer) can implement addModuleSet by running each module in the
|
||||
(like IRTransformLayer) can implement addModule by running each module in the
|
||||
set through its transform up-front and immediately passing the result to the
|
||||
layer below. A lazy layer, by contrast, could implement addModuleSet by
|
||||
layer below. A lazy layer, by contrast, could implement addModule by
|
||||
squirreling away the modules doing no other up-front work, but applying the
|
||||
transform (and calling addModuleSet on the layer below) when the client calls
|
||||
transform (and calling addModule on the layer below) when the client calls
|
||||
findSymbol instead. The JIT'd program behavior will be the same either way, but
|
||||
these choices will have different performance characteristics: Doing work
|
||||
eagerly means the JIT takes longer up-front, but proceeds smoothly once this is
|
||||
@ -319,7 +312,7 @@ IRTransformLayer added to enable optimization. To build this example, use:
|
||||
.. code-block:: bash
|
||||
|
||||
# Compile
|
||||
clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core orc native` -O3 -o toy
|
||||
clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core orcjit native` -O3 -o toy
|
||||
# Run
|
||||
./toy
|
||||
|
||||
@ -329,8 +322,8 @@ Here is the code:
|
||||
:language: c++
|
||||
|
||||
.. [1] When we add our top-level expression to the JIT, any calls to functions
|
||||
that we defined earlier will appear to the ObjectLinkingLayer as
|
||||
external symbols. The ObjectLinkingLayer will call the SymbolResolver
|
||||
that we defined in addModuleSet, which in turn calls findSymbol on the
|
||||
that we defined earlier will appear to the RTDyldObjectLinkingLayer as
|
||||
external symbols. The RTDyldObjectLinkingLayer will call the SymbolResolver
|
||||
that we defined in addModule, which in turn calls findSymbol on the
|
||||
OptimizeLayer, at which point even a lazy transform layer will have to
|
||||
do its work.
|
||||
|
@ -21,7 +21,7 @@ Lazy Compilation
|
||||
|
||||
When we add a module to the KaleidoscopeJIT class from Chapter 2 it is
|
||||
immediately optimized, compiled and linked for us by the IRTransformLayer,
|
||||
IRCompileLayer and ObjectLinkingLayer respectively. This scheme, where all the
|
||||
IRCompileLayer and RTDyldObjectLinkingLayer respectively. This scheme, where all the
|
||||
work to make a Module executable is done up front, is simple to understand and
|
||||
its performance characteristics are easy to reason about. However, it will lead
|
||||
to very high startup times if the amount of code to be compiled is large, and
|
||||
@ -33,7 +33,7 @@ the ORC APIs provide us with a layer to lazily compile LLVM IR:
|
||||
*CompileOnDemandLayer*.
|
||||
|
||||
The CompileOnDemandLayer class conforms to the layer interface described in
|
||||
Chapter 2, but its addModuleSet method behaves quite differently from the layers
|
||||
Chapter 2, but its addModule method behaves quite differently from the layers
|
||||
we have seen so far: rather than doing any work up front, it just scans the
|
||||
Modules being added and arranges for each function in them to be compiled the
|
||||
first time it is called. To do this, the CompileOnDemandLayer creates two small
|
||||
@ -73,21 +73,22 @@ lazy compilation. We just need a few changes to the source:
|
||||
private:
|
||||
std::unique_ptr<TargetMachine> TM;
|
||||
const DataLayout DL;
|
||||
std::unique_ptr<JITCompileCallbackManager> CompileCallbackManager;
|
||||
ObjectLinkingLayer<> ObjectLayer;
|
||||
IRCompileLayer<decltype(ObjectLayer)> CompileLayer;
|
||||
RTDyldObjectLinkingLayer ObjectLayer;
|
||||
IRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
|
||||
|
||||
typedef std::function<std::unique_ptr<Module>(std::unique_ptr<Module>)>
|
||||
OptimizeFunction;
|
||||
using OptimizeFunction =
|
||||
std::function<std::shared_ptr<Module>(std::shared_ptr<Module>)>;
|
||||
|
||||
IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
|
||||
|
||||
std::unique_ptr<JITCompileCallbackManager> CompileCallbackManager;
|
||||
CompileOnDemandLayer<decltype(OptimizeLayer)> CODLayer;
|
||||
|
||||
public:
|
||||
typedef decltype(CODLayer)::ModuleSetHandleT ModuleHandle;
|
||||
using ModuleHandle = decltype(CODLayer)::ModuleHandleT;
|
||||
|
||||
First we need to include the CompileOnDemandLayer.h header, then add two new
|
||||
members: a std::unique_ptr<CompileCallbackManager> and a CompileOnDemandLayer,
|
||||
members: a std::unique_ptr<JITCompileCallbackManager> and a CompileOnDemandLayer,
|
||||
to our class. The CompileCallbackManager member is used by the CompileOnDemandLayer
|
||||
to create the compile callback needed for each function.
|
||||
|
||||
@ -95,9 +96,10 @@ to create the compile callback needed for each function.
|
||||
|
||||
KaleidoscopeJIT()
|
||||
: TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
|
||||
ObjectLayer([]() { return std::make_shared<SectionMemoryManager>(); }),
|
||||
CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
|
||||
OptimizeLayer(CompileLayer,
|
||||
[this](std::unique_ptr<Module> M) {
|
||||
[this](std::shared_ptr<Module> M) {
|
||||
return optimizeModule(std::move(M));
|
||||
}),
|
||||
CompileCallbackManager(
|
||||
@ -133,7 +135,7 @@ our CompileCallbackManager. Finally, we need to supply an "indirect stubs
|
||||
manager builder": a utility function that constructs IndirectStubManagers, which
|
||||
are in turn used to build the stubs for the functions in each module. The
|
||||
CompileOnDemandLayer will call the indirect stub manager builder once for each
|
||||
call to addModuleSet, and use the resulting indirect stubs manager to create
|
||||
call to addModule, and use the resulting indirect stubs manager to create
|
||||
stubs for all functions in all modules in the set. If/when the module set is
|
||||
removed from the JIT the indirect stubs manager will be deleted, freeing any
|
||||
memory allocated to the stubs. We supply this function by using the
|
||||
@ -144,9 +146,8 @@ createLocalIndirectStubsManagerBuilder utility.
|
||||
// ...
|
||||
if (auto Sym = CODLayer.findSymbol(Name, false))
|
||||
// ...
|
||||
return CODLayer.addModuleSet(std::move(Ms),
|
||||
make_unique<SectionMemoryManager>(),
|
||||
std::move(Resolver));
|
||||
return cantFail(CODLayer.addModule(std::move(Ms),
|
||||
std::move(Resolver)));
|
||||
// ...
|
||||
|
||||
// ...
|
||||
@ -154,7 +155,7 @@ createLocalIndirectStubsManagerBuilder utility.
|
||||
// ...
|
||||
|
||||
// ...
|
||||
CODLayer.removeModuleSet(H);
|
||||
CODLayer.removeModule(H);
|
||||
// ...
|
||||
|
||||
Finally, we need to replace the references to OptimizeLayer in our addModule,
|
||||
@ -173,7 +174,7 @@ layer added to enable lazy function-at-a-time compilation. To build this example
|
||||
.. code-block:: bash
|
||||
|
||||
# Compile
|
||||
clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core orc native` -O3 -o toy
|
||||
clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core orcjit native` -O3 -o toy
|
||||
# Run
|
||||
./toy
|
||||
|
||||
|
@ -36,7 +36,7 @@ Kaleidoscope ASTS. To build this example, use:
|
||||
.. code-block:: bash
|
||||
|
||||
# Compile
|
||||
clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core orc native` -O3 -o toy
|
||||
clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core orcjit native` -O3 -o toy
|
||||
# Run
|
||||
./toy
|
||||
|
||||
|
@ -40,8 +40,10 @@ Kaleidoscope ASTS. To build this example, use:
|
||||
.. code-block:: bash
|
||||
|
||||
# Compile
|
||||
clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core orc native` -O3 -o toy
|
||||
clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core orcjit native` -O3 -o toy
|
||||
clang++ -g Server/server.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core orcjit native` -O3 -o toy-server
|
||||
# Run
|
||||
./toy-server &
|
||||
./toy
|
||||
|
||||
Here is the code for the modified KaleidoscopeJIT:
|
||||
|
@ -41,7 +41,7 @@
|
||||
// Cases -1 and 7 are caught by a C++ test harness where the validity of
|
||||
// of a C++ catch(...) clause catching a generated exception with a
|
||||
// type info type of 7 is explained by: example in rules 1.6.4 in
|
||||
// http://mentorembedded.github.com/cxx-abi/abi-eh.html (v1.22)
|
||||
// http://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html (v1.22)
|
||||
//
|
||||
// This code uses code from the llvm compiler-rt project and the llvm
|
||||
// Kaleidoscope project.
|
||||
@ -101,7 +101,7 @@ struct OurExceptionType_t {
|
||||
///
|
||||
/// Note: The above unwind.h defines struct _Unwind_Exception to be aligned
|
||||
/// on a double word boundary. This is necessary to match the standard:
|
||||
/// http://mentorembedded.github.com/cxx-abi/abi-eh.html
|
||||
/// http://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
|
||||
struct OurBaseException_t {
|
||||
struct OurExceptionType_t type;
|
||||
|
||||
@ -299,7 +299,7 @@ void deleteOurException(OurUnwindException *expToDelete) {
|
||||
/// This function is the struct _Unwind_Exception API mandated delete function
|
||||
/// used by foreign exception handlers when deleting our exception
|
||||
/// (OurException), instances.
|
||||
/// @param reason See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html
|
||||
/// @param reason See @link http://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
|
||||
/// @unlink
|
||||
/// @param expToDelete exception instance to delete
|
||||
void deleteFromUnwindOurException(_Unwind_Reason_Code reason,
|
||||
@ -489,7 +489,7 @@ static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) {
|
||||
/// are supported. Filters are not supported.
|
||||
/// See Variable Length Data in:
|
||||
/// @link http://dwarfstd.org/Dwarf3.pdf @unlink
|
||||
/// Also see @link http://mentorembedded.github.com/cxx-abi/abi-eh.html @unlink
|
||||
/// Also see @link http://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html @unlink
|
||||
/// @param resultAction reference variable which will be set with result
|
||||
/// @param classInfo our array of type info pointers (to globals)
|
||||
/// @param actionEntry index into above type info array or 0 (clean up).
|
||||
@ -583,7 +583,7 @@ static bool handleActionValue(int64_t *resultAction,
|
||||
|
||||
|
||||
/// Deals with the Language specific data portion of the emitted dwarf code.
|
||||
/// See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html @unlink
|
||||
/// See @link http://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html @unlink
|
||||
/// @param version unsupported (ignored), unwind version
|
||||
/// @param lsda language specific data area
|
||||
/// @param _Unwind_Action actions minimally supported unwind stage
|
||||
@ -767,7 +767,7 @@ static _Unwind_Reason_Code handleLsda(int version, const uint8_t *lsda,
|
||||
|
||||
/// This is the personality function which is embedded (dwarf emitted), in the
|
||||
/// dwarf unwind info block. Again see: JITDwarfEmitter.cpp.
|
||||
/// See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html @unlink
|
||||
/// See @link http://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html @unlink
|
||||
/// @param version unsupported (ignored), unwind version
|
||||
/// @param _Unwind_Action actions minimally supported unwind stage
|
||||
/// (forced specifically not supported)
|
||||
@ -814,7 +814,7 @@ _Unwind_Reason_Code ourPersonality(int version, _Unwind_Action actions,
|
||||
/// Generates our _Unwind_Exception class from a given character array.
|
||||
/// thereby handling arbitrary lengths (not in standard), and handling
|
||||
/// embedded \0s.
|
||||
/// See @link http://mentorembedded.github.com/cxx-abi/abi-eh.html @unlink
|
||||
/// See @link http://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html @unlink
|
||||
/// @param classChars char array to encode. NULL values not checkedf
|
||||
/// @param classCharsSize number of chars in classChars. Value is not checked.
|
||||
/// @returns class value
|
||||
@ -1571,7 +1571,7 @@ void runExceptionThrow(llvm::ExecutionEngine *engine,
|
||||
catch (...) {
|
||||
// Catch all exceptions including our generated ones. This latter
|
||||
// functionality works according to the example in rules 1.6.4 of
|
||||
// http://mentorembedded.github.com/cxx-abi/abi-eh.html (v1.22),
|
||||
// http://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html (v1.22),
|
||||
// given that these will be exceptions foreign to C++
|
||||
// (the _Unwind_Exception::exception_class should be different from
|
||||
// the one used by C++).
|
||||
|
@ -86,6 +86,10 @@ public:
|
||||
return CompileLayer.findSymbol(MangledNameStream.str(), true);
|
||||
}
|
||||
|
||||
JITTargetAddress getSymbolAddress(const std::string Name) {
|
||||
return cantFail(findSymbol(Name).getAddress());
|
||||
}
|
||||
|
||||
void removeModule(ModuleHandle H) {
|
||||
cantFail(CompileLayer.removeModule(H));
|
||||
}
|
||||
|
@ -1144,13 +1144,11 @@ static void HandleTopLevelExpression() {
|
||||
auto H = TheJIT->addModule(std::move(TheModule));
|
||||
InitializeModule();
|
||||
|
||||
// Search the JIT for the __anon_expr symbol.
|
||||
auto ExprSymbol = TheJIT->findSymbol("__anon_expr");
|
||||
assert(ExprSymbol && "Function not found");
|
||||
|
||||
// Get the symbol's address and cast it to the right type (takes no
|
||||
// arguments, returns a double) so we can call it as a native function.
|
||||
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
|
||||
// Get the anonymous expression's address and cast it to the right type,
|
||||
// double(*)(), so we can call it as a native function.
|
||||
double (*FP)() =
|
||||
(double (*)())(intptr_t)TheJIT->getSymbolAddress("__anon_expr");
|
||||
assert(FP && "Failed to codegen function");
|
||||
fprintf(stderr, "Evaluated to %f\n", FP());
|
||||
|
||||
// Delete the anonymous expression module from the JIT.
|
||||
|
@ -135,7 +135,7 @@ public:
|
||||
Error addFunctionAST(std::unique_ptr<FunctionAST> FnAST) {
|
||||
// Create a CompileCallback - this is the re-entry point into the compiler
|
||||
// for functions that haven't been compiled yet.
|
||||
auto CCInfo = CompileCallbackMgr->getCompileCallback();
|
||||
auto CCInfo = cantFail(CompileCallbackMgr->getCompileCallback());
|
||||
|
||||
// Create an indirect stub. This serves as the functions "canonical
|
||||
// definition" - an unchanging (constant address) entry point to the
|
||||
|
@ -72,7 +72,7 @@ namespace llvm {
|
||||
namespace orc {
|
||||
|
||||
// Typedef the remote-client API.
|
||||
using MyRemote = remote::OrcRemoteTargetClient<FDRPCChannel>;
|
||||
using MyRemote = remote::OrcRemoteTargetClient;
|
||||
|
||||
class KaleidoscopeJIT {
|
||||
private:
|
||||
@ -98,13 +98,7 @@ public:
|
||||
"", SmallVector<std::string, 0>())),
|
||||
DL(TM->createDataLayout()),
|
||||
ObjectLayer([&Remote]() {
|
||||
std::unique_ptr<MyRemote::RCMemoryManager> MemMgr;
|
||||
if (auto Err = Remote.createRemoteMemoryManager(MemMgr)) {
|
||||
logAllUnhandledErrors(std::move(Err), errs(),
|
||||
"Error creating remote memory manager:");
|
||||
exit(1);
|
||||
}
|
||||
return MemMgr;
|
||||
return cantFail(Remote.createRemoteMemoryManager());
|
||||
}),
|
||||
CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
|
||||
OptimizeLayer(CompileLayer,
|
||||
@ -119,13 +113,7 @@ public:
|
||||
exit(1);
|
||||
}
|
||||
CompileCallbackMgr = &*CCMgrOrErr;
|
||||
std::unique_ptr<MyRemote::RCIndirectStubsManager> ISM;
|
||||
if (auto Err = Remote.createIndirectStubsManager(ISM)) {
|
||||
logAllUnhandledErrors(std::move(Err), errs(),
|
||||
"Error creating indirect stubs manager:");
|
||||
exit(1);
|
||||
}
|
||||
IndirectStubsMgr = std::move(ISM);
|
||||
IndirectStubsMgr = cantFail(Remote.createIndirectStubsManager());
|
||||
llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
|
||||
}
|
||||
|
||||
@ -164,7 +152,7 @@ public:
|
||||
Error addFunctionAST(std::unique_ptr<FunctionAST> FnAST) {
|
||||
// Create a CompileCallback - this is the re-entry point into the compiler
|
||||
// for functions that haven't been compiled yet.
|
||||
auto CCInfo = CompileCallbackMgr->getCompileCallback();
|
||||
auto CCInfo = cantFail(CompileCallbackMgr->getCompileCallback());
|
||||
|
||||
// Create an indirect stub. This serves as the functions "canonical
|
||||
// definition" - an unchanging (constant address) entry point to the
|
||||
|
@ -1277,7 +1277,7 @@ int main(int argc, char *argv[]) {
|
||||
BinopPrecedence['*'] = 40; // highest.
|
||||
|
||||
auto TCPChannel = connect();
|
||||
auto Remote = ExitOnErr(MyRemote::Create(*TCPChannel));
|
||||
auto Remote = ExitOnErr(MyRemote::Create(*TCPChannel, ExitOnErr));
|
||||
TheJIT = llvm::make_unique<KaleidoscopeJIT>(*Remote);
|
||||
|
||||
// Automatically inject a definition for 'printExprResult'.
|
||||
|
@ -11,4 +11,4 @@ add_llvm_example(ParallelJIT
|
||||
ParallelJIT.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(ParallelJIT ${LLVM_PTHREAD_LIB})
|
||||
target_link_libraries(ParallelJIT PRIVATE ${LLVM_PTHREAD_LIB})
|
||||
|
@ -1136,6 +1136,16 @@ LLVMTypeRef LLVMLabelTypeInContext(LLVMContextRef C);
|
||||
*/
|
||||
LLVMTypeRef LLVMX86MMXTypeInContext(LLVMContextRef C);
|
||||
|
||||
/**
|
||||
* Create a token type in a context.
|
||||
*/
|
||||
LLVMTypeRef LLVMTokenTypeInContext(LLVMContextRef C);
|
||||
|
||||
/**
|
||||
* Create a metadata type in a context.
|
||||
*/
|
||||
LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C);
|
||||
|
||||
/**
|
||||
* These are similar to the above functions except they operate on the
|
||||
* global context.
|
||||
|
232
include/llvm-c/DebugInfo.h
Normal file
232
include/llvm-c/DebugInfo.h
Normal file
@ -0,0 +1,232 @@
|
||||
//===------------ DebugInfo.h - LLVM C API Debug Info API -----------------===//
|
||||
//
|
||||
// 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 C API endpoints for generating DWARF Debug Info
|
||||
///
|
||||
/// Note: This interface is experimental. It is *NOT* stable, and may be
|
||||
/// changed without warning.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_C_DEBUGINFO_H
|
||||
#define LLVM_C_DEBUGINFO_H
|
||||
|
||||
#include "llvm-c/Core.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Debug info flags.
|
||||
*/
|
||||
typedef enum {
|
||||
LLVMDIFlagZero = 0,
|
||||
LLVMDIFlagPrivate = 1,
|
||||
LLVMDIFlagProtected = 2,
|
||||
LLVMDIFlagPublic = 3,
|
||||
LLVMDIFlagFwdDecl = 1 << 2,
|
||||
LLVMDIFlagAppleBlock = 1 << 3,
|
||||
LLVMDIFlagBlockByrefStruct = 1 << 4,
|
||||
LLVMDIFlagVirtual = 1 << 5,
|
||||
LLVMDIFlagArtificial = 1 << 6,
|
||||
LLVMDIFlagExplicit = 1 << 7,
|
||||
LLVMDIFlagPrototyped = 1 << 8,
|
||||
LLVMDIFlagObjcClassComplete = 1 << 9,
|
||||
LLVMDIFlagObjectPointer = 1 << 10,
|
||||
LLVMDIFlagVector = 1 << 11,
|
||||
LLVMDIFlagStaticMember = 1 << 12,
|
||||
LLVMDIFlagLValueReference = 1 << 13,
|
||||
LLVMDIFlagRValueReference = 1 << 14,
|
||||
LLVMDIFlagReserved = 1 << 15,
|
||||
LLVMDIFlagSingleInheritance = 1 << 16,
|
||||
LLVMDIFlagMultipleInheritance = 2 << 16,
|
||||
LLVMDIFlagVirtualInheritance = 3 << 16,
|
||||
LLVMDIFlagIntroducedVirtual = 1 << 18,
|
||||
LLVMDIFlagBitField = 1 << 19,
|
||||
LLVMDIFlagNoReturn = 1 << 20,
|
||||
LLVMDIFlagMainSubprogram = 1 << 21,
|
||||
LLVMDIFlagIndirectVirtualBase = (1 << 2) | (1 << 5),
|
||||
LLVMDIFlagAccessibility = LLVMDIFlagPrivate | LLVMDIFlagProtected |
|
||||
LLVMDIFlagPublic,
|
||||
LLVMDIFlagPtrToMemberRep = LLVMDIFlagSingleInheritance |
|
||||
LLVMDIFlagMultipleInheritance |
|
||||
LLVMDIFlagVirtualInheritance
|
||||
} LLVMDIFlags;
|
||||
|
||||
/**
|
||||
* Source languages known by DWARF.
|
||||
*/
|
||||
typedef enum {
|
||||
LLVMDWARFSourceLanguageC89,
|
||||
LLVMDWARFSourceLanguageC,
|
||||
LLVMDWARFSourceLanguageAda83,
|
||||
LLVMDWARFSourceLanguageC_plus_plus,
|
||||
LLVMDWARFSourceLanguageCobol74,
|
||||
LLVMDWARFSourceLanguageCobol85,
|
||||
LLVMDWARFSourceLanguageFortran77,
|
||||
LLVMDWARFSourceLanguageFortran90,
|
||||
LLVMDWARFSourceLanguagePascal83,
|
||||
LLVMDWARFSourceLanguageModula2,
|
||||
// New in DWARF v3:
|
||||
LLVMDWARFSourceLanguageJava,
|
||||
LLVMDWARFSourceLanguageC99,
|
||||
LLVMDWARFSourceLanguageAda95,
|
||||
LLVMDWARFSourceLanguageFortran95,
|
||||
LLVMDWARFSourceLanguagePLI,
|
||||
LLVMDWARFSourceLanguageObjC,
|
||||
LLVMDWARFSourceLanguageObjC_plus_plus,
|
||||
LLVMDWARFSourceLanguageUPC,
|
||||
LLVMDWARFSourceLanguageD,
|
||||
// New in DWARF v4:
|
||||
LLVMDWARFSourceLanguagePython,
|
||||
// New in DWARF v5:
|
||||
LLVMDWARFSourceLanguageOpenCL,
|
||||
LLVMDWARFSourceLanguageGo,
|
||||
LLVMDWARFSourceLanguageModula3,
|
||||
LLVMDWARFSourceLanguageHaskell,
|
||||
LLVMDWARFSourceLanguageC_plus_plus_03,
|
||||
LLVMDWARFSourceLanguageC_plus_plus_11,
|
||||
LLVMDWARFSourceLanguageOCaml,
|
||||
LLVMDWARFSourceLanguageRust,
|
||||
LLVMDWARFSourceLanguageC11,
|
||||
LLVMDWARFSourceLanguageSwift,
|
||||
LLVMDWARFSourceLanguageJulia,
|
||||
LLVMDWARFSourceLanguageDylan,
|
||||
LLVMDWARFSourceLanguageC_plus_plus_14,
|
||||
LLVMDWARFSourceLanguageFortran03,
|
||||
LLVMDWARFSourceLanguageFortran08,
|
||||
LLVMDWARFSourceLanguageRenderScript,
|
||||
LLVMDWARFSourceLanguageBLISS,
|
||||
// Vendor extensions:
|
||||
LLVMDWARFSourceLanguageMips_Assembler,
|
||||
LLVMDWARFSourceLanguageGOOGLE_RenderScript,
|
||||
LLVMDWARFSourceLanguageBORLAND_Delphi
|
||||
} LLVMDWARFSourceLanguage;
|
||||
|
||||
/**
|
||||
* The amount of debug information to emit.
|
||||
*/
|
||||
typedef enum {
|
||||
LLVMDWARFEmissionNone = 0,
|
||||
LLVMDWARFEmissionFull,
|
||||
LLVMDWARFEmissionLineTablesOnly
|
||||
} LLVMDWARFEmissionKind;
|
||||
|
||||
/**
|
||||
* The current debug metadata version number.
|
||||
*/
|
||||
unsigned LLVMDebugMetadataVersion(void);
|
||||
|
||||
/**
|
||||
* The version of debug metadata that's present in the provided \c Module.
|
||||
*/
|
||||
unsigned LLVMGetModuleDebugMetadataVersion(LLVMModuleRef Module);
|
||||
|
||||
/**
|
||||
* Strip debug info in the module if it exists.
|
||||
* To do this, we remove all calls to the debugger intrinsics and any named
|
||||
* metadata for debugging. We also remove debug locations for instructions.
|
||||
* Return true if module is modified.
|
||||
*/
|
||||
LLVMBool LLVMStripModuleDebugInfo(LLVMModuleRef Module);
|
||||
|
||||
/**
|
||||
* Construct a builder for a module, and do not allow for unresolved nodes
|
||||
* attached to the module.
|
||||
*/
|
||||
LLVMDIBuilderRef LLVMCreateDIBuilderDisallowUnresolved(LLVMModuleRef M);
|
||||
|
||||
/**
|
||||
* Construct a builder for a module and collect unresolved nodes attached
|
||||
* to the module in order to resolve cycles during a call to
|
||||
* \c LLVMDIBuilderFinalize.
|
||||
*/
|
||||
LLVMDIBuilderRef LLVMCreateDIBuilder(LLVMModuleRef M);
|
||||
|
||||
/**
|
||||
* Deallocates the \c DIBuilder and everything it owns.
|
||||
* @note You must call \c LLVMDIBuilderFinalize before this
|
||||
*/
|
||||
void LLVMDisposeDIBuilder(LLVMDIBuilderRef Builder);
|
||||
|
||||
/**
|
||||
* Construct any deferred debug info descriptors.
|
||||
*/
|
||||
void LLVMDIBuilderFinalize(LLVMDIBuilderRef Builder);
|
||||
|
||||
/**
|
||||
* A CompileUnit provides an anchor for all debugging
|
||||
* information generated during this instance of compilation.
|
||||
* \param Lang Source programming language, eg.
|
||||
* \c LLVMDWARFSourceLanguageC99
|
||||
* \param FileRef File info.
|
||||
* \param Producer Identify the producer of debugging information
|
||||
* and code. Usually this is a compiler
|
||||
* version string.
|
||||
* \param ProducerLen The length of the C string passed to \c Producer.
|
||||
* \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 FlagsLen The length of the C string passed to \c Flags.
|
||||
* \param RuntimeVer 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 SplitNameLen The length of the C string passed to \c SplitName.
|
||||
* \param Kind The kind of debug information to generate.
|
||||
* \param DWOId The DWOId if this is a split skeleton compile unit.
|
||||
* \param SplitDebugInlining Whether to emit inline debug info.
|
||||
* \param DebugInfoForProfiling Whether to emit extra debug info for
|
||||
* profile collection.
|
||||
*/
|
||||
LLVMMetadataRef LLVMDIBuilderCreateCompileUnit(
|
||||
LLVMDIBuilderRef Builder, LLVMDWARFSourceLanguage Lang,
|
||||
LLVMMetadataRef FileRef, const char *Producer, size_t ProducerLen,
|
||||
LLVMBool isOptimized, const char *Flags, size_t FlagsLen,
|
||||
unsigned RuntimeVer, const char *SplitName, size_t SplitNameLen,
|
||||
LLVMDWARFEmissionKind Kind, unsigned DWOId, LLVMBool SplitDebugInlining,
|
||||
LLVMBool DebugInfoForProfiling);
|
||||
|
||||
/**
|
||||
* Create a file descriptor to hold debugging information for a file.
|
||||
* \param Builder The \c DIBuilder.
|
||||
* \param Filename File name.
|
||||
* \param FilenameLen The length of the C string passed to \c Filename.
|
||||
* \param Directory Directory.
|
||||
* \param DirectoryLen The length of the C string passed to \c Directory.
|
||||
*/
|
||||
LLVMMetadataRef
|
||||
LLVMDIBuilderCreateFile(LLVMDIBuilderRef Builder, const char *Filename,
|
||||
size_t FilenameLen, const char *Directory,
|
||||
size_t DirectoryLen);
|
||||
|
||||
/**
|
||||
* Creates a new DebugLocation that describes a source location.
|
||||
* \param Line The line in the source file.
|
||||
* \param Column The column in the source file.
|
||||
* \param Scope The scope in which the location resides.
|
||||
* \param InlinedAt The scope where this location was inlined, if at all.
|
||||
* (optional).
|
||||
* \note If the item to which this location is attached cannot be
|
||||
* attributed to a source line, pass 0 for the line and column.
|
||||
*/
|
||||
LLVMMetadataRef
|
||||
LLVMDIBuilderCreateDebugLocation(LLVMContextRef Ctx, unsigned Line,
|
||||
unsigned Column, LLVMMetadataRef Scope,
|
||||
LLVMMetadataRef InlinedAt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
@ -30,7 +30,6 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct LLVMOpaqueSharedModule *LLVMSharedModuleRef;
|
||||
typedef struct LLVMOpaqueSharedObjectBuffer *LLVMSharedObjectBufferRef;
|
||||
typedef struct LLVMOrcOpaqueJITStack *LLVMOrcJITStackRef;
|
||||
typedef uint32_t LLVMOrcModuleHandle;
|
||||
typedef uint64_t LLVMOrcTargetAddress;
|
||||
@ -67,18 +66,6 @@ LLVMSharedModuleRef LLVMOrcMakeSharedModule(LLVMModuleRef Mod);
|
||||
|
||||
void LLVMOrcDisposeSharedModuleRef(LLVMSharedModuleRef SharedMod);
|
||||
|
||||
/**
|
||||
* Get an LLVMSharedObjectBufferRef from an LLVMMemoryBufferRef.
|
||||
*/
|
||||
LLVMSharedObjectBufferRef
|
||||
LLVMOrcMakeSharedObjectBuffer(LLVMMemoryBufferRef ObjBuffer);
|
||||
|
||||
/**
|
||||
* Dispose of a shared object buffer.
|
||||
*/
|
||||
void
|
||||
LLVMOrcDisposeSharedObjectBufferRef(LLVMSharedObjectBufferRef SharedObjBuffer);
|
||||
|
||||
/**
|
||||
* Create an ORC JIT stack.
|
||||
*
|
||||
@ -155,10 +142,15 @@ LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack,
|
||||
|
||||
/**
|
||||
* Add an object file.
|
||||
*
|
||||
* This method takes ownership of the given memory buffer and attempts to add
|
||||
* it to the JIT as an object file.
|
||||
* Clients should *not* dispose of the 'Obj' argument: the JIT will manage it
|
||||
* from this call onwards.
|
||||
*/
|
||||
LLVMOrcErrorCode LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack,
|
||||
LLVMOrcModuleHandle *RetHandle,
|
||||
LLVMSharedObjectBufferRef Obj,
|
||||
LLVMMemoryBufferRef Obj,
|
||||
LLVMOrcSymbolResolverFn SymbolResolver,
|
||||
void *SymbolResolverCtx);
|
||||
|
||||
|
@ -34,6 +34,9 @@ void LLVMAddArgumentPromotionPass(LLVMPassManagerRef PM);
|
||||
/** See llvm::createConstantMergePass function. */
|
||||
void LLVMAddConstantMergePass(LLVMPassManagerRef PM);
|
||||
|
||||
/** See llvm::createCalledValuePropagationPass function. */
|
||||
void LLVMAddCalledValuePropagationPass(LLVMPassManagerRef PM);
|
||||
|
||||
/** See llvm::createDeadArgEliminationPass function. */
|
||||
void LLVMAddDeadArgEliminationPass(LLVMPassManagerRef PM);
|
||||
|
||||
|
@ -44,9 +44,6 @@ void LLVMAddAlignmentFromAssumptionsPass(LLVMPassManagerRef PM);
|
||||
/** See llvm::createCFGSimplificationPass function. */
|
||||
void LLVMAddCFGSimplificationPass(LLVMPassManagerRef PM);
|
||||
|
||||
/** See llvm::createLateCFGSimplificationPass function. */
|
||||
void LLVMAddLateCFGSimplificationPass(LLVMPassManagerRef PM);
|
||||
|
||||
/** See llvm::createDeadStoreEliminationPass function. */
|
||||
void LLVMAddDeadStoreEliminationPass(LLVMPassManagerRef PM);
|
||||
|
||||
|
@ -1119,6 +1119,21 @@ public:
|
||||
llvm_unreachable("Unexpected semantics");
|
||||
}
|
||||
|
||||
/// We don't rely on operator== working on double values, as
|
||||
/// it returns true for things that are clearly not equal, like -0.0 and 0.0.
|
||||
/// As such, this method can be used to do an exact bit-for-bit comparison of
|
||||
/// two floating point values.
|
||||
///
|
||||
/// We leave the version with the double argument here because it's just so
|
||||
/// convenient to write "2.0" and the like. Without this function we'd
|
||||
/// have to duplicate its logic everywhere it's called.
|
||||
bool isExactlyValue(double V) const {
|
||||
bool ignored;
|
||||
APFloat Tmp(V);
|
||||
Tmp.convert(getSemantics(), APFloat::rmNearestTiesToEven, &ignored);
|
||||
return bitwiseIsEqual(Tmp);
|
||||
}
|
||||
|
||||
unsigned int convertToHexString(char *DST, unsigned int HexDigits,
|
||||
bool UpperCase, roundingMode RM) const {
|
||||
APFLOAT_DISPATCH_ON_SEMANTICS(
|
||||
|
@ -1724,13 +1724,13 @@ public:
|
||||
/// @{
|
||||
|
||||
/// \returns the floor log base 2 of this APInt.
|
||||
unsigned logBase2() const { return BitWidth - 1 - countLeadingZeros(); }
|
||||
unsigned logBase2() const { return getActiveBits() - 1; }
|
||||
|
||||
/// \returns the ceil log base 2 of this APInt.
|
||||
unsigned ceilLogBase2() const {
|
||||
APInt temp(*this);
|
||||
--temp;
|
||||
return BitWidth - temp.countLeadingZeros();
|
||||
return temp.getActiveBits();
|
||||
}
|
||||
|
||||
/// \returns the nearest log base 2 of this APInt. Ties round up.
|
||||
|
@ -294,7 +294,7 @@ namespace llvm {
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
|
||||
/// Construct an empty MutableArrayRef.
|
||||
/*implicit*/ MutableArrayRef() : ArrayRef<T>() {}
|
||||
/*implicit*/ MutableArrayRef() = default;
|
||||
|
||||
/// Construct an empty MutableArrayRef from None.
|
||||
/*implicit*/ MutableArrayRef(NoneType) : ArrayRef<T>() {}
|
||||
|
@ -911,7 +911,7 @@ public:
|
||||
size_t getBitCapacity() const { return Bits.size() * BITWORD_SIZE; }
|
||||
};
|
||||
|
||||
static inline size_t capacity_in_bytes(const BitVector &X) {
|
||||
inline size_t capacity_in_bytes(const BitVector &X) {
|
||||
return X.getMemorySize();
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "llvm/Support/AlignOf.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/ReverseIteration.h"
|
||||
#include "llvm/Support/type_traits.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
@ -67,18 +68,26 @@ public:
|
||||
DenseMapIterator<KeyT, ValueT, KeyInfoT, BucketT, true>;
|
||||
|
||||
inline iterator begin() {
|
||||
// When the map is empty, avoid the overhead of AdvancePastEmptyBuckets().
|
||||
return empty() ? end() : iterator(getBuckets(), getBucketsEnd(), *this);
|
||||
// When the map is empty, avoid the overhead of advancing/retreating past
|
||||
// empty buckets.
|
||||
if (empty())
|
||||
return end();
|
||||
if (shouldReverseIterate<KeyT>())
|
||||
return makeIterator(getBucketsEnd() - 1, getBuckets(), *this);
|
||||
return makeIterator(getBuckets(), getBucketsEnd(), *this);
|
||||
}
|
||||
inline iterator end() {
|
||||
return iterator(getBucketsEnd(), getBucketsEnd(), *this, true);
|
||||
return makeIterator(getBucketsEnd(), getBucketsEnd(), *this, true);
|
||||
}
|
||||
inline const_iterator begin() const {
|
||||
return empty() ? end()
|
||||
: const_iterator(getBuckets(), getBucketsEnd(), *this);
|
||||
if (empty())
|
||||
return end();
|
||||
if (shouldReverseIterate<KeyT>())
|
||||
return makeConstIterator(getBucketsEnd() - 1, getBuckets(), *this);
|
||||
return makeConstIterator(getBuckets(), getBucketsEnd(), *this);
|
||||
}
|
||||
inline const_iterator end() const {
|
||||
return const_iterator(getBucketsEnd(), getBucketsEnd(), *this, true);
|
||||
return makeConstIterator(getBucketsEnd(), getBucketsEnd(), *this, true);
|
||||
}
|
||||
|
||||
LLVM_NODISCARD bool empty() const {
|
||||
@ -107,17 +116,23 @@ public:
|
||||
}
|
||||
|
||||
const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
|
||||
unsigned NumEntries = getNumEntries();
|
||||
for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
|
||||
if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) {
|
||||
if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) {
|
||||
P->getSecond().~ValueT();
|
||||
--NumEntries;
|
||||
}
|
||||
if (isPodLike<KeyT>::value && isPodLike<ValueT>::value) {
|
||||
// Use a simpler loop when these are trivial types.
|
||||
for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P)
|
||||
P->getFirst() = EmptyKey;
|
||||
} else {
|
||||
unsigned NumEntries = getNumEntries();
|
||||
for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) {
|
||||
if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) {
|
||||
if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) {
|
||||
P->getSecond().~ValueT();
|
||||
--NumEntries;
|
||||
}
|
||||
P->getFirst() = EmptyKey;
|
||||
}
|
||||
}
|
||||
assert(NumEntries == 0 && "Node count imbalance!");
|
||||
}
|
||||
assert(NumEntries == 0 && "Node count imbalance!");
|
||||
setNumEntries(0);
|
||||
setNumTombstones(0);
|
||||
}
|
||||
@ -131,13 +146,13 @@ public:
|
||||
iterator find(const_arg_type_t<KeyT> Val) {
|
||||
BucketT *TheBucket;
|
||||
if (LookupBucketFor(Val, TheBucket))
|
||||
return iterator(TheBucket, getBucketsEnd(), *this, true);
|
||||
return makeIterator(TheBucket, getBucketsEnd(), *this, true);
|
||||
return end();
|
||||
}
|
||||
const_iterator find(const_arg_type_t<KeyT> Val) const {
|
||||
const BucketT *TheBucket;
|
||||
if (LookupBucketFor(Val, TheBucket))
|
||||
return const_iterator(TheBucket, getBucketsEnd(), *this, true);
|
||||
return makeConstIterator(TheBucket, getBucketsEnd(), *this, true);
|
||||
return end();
|
||||
}
|
||||
|
||||
@ -150,14 +165,14 @@ public:
|
||||
iterator find_as(const LookupKeyT &Val) {
|
||||
BucketT *TheBucket;
|
||||
if (LookupBucketFor(Val, TheBucket))
|
||||
return iterator(TheBucket, getBucketsEnd(), *this, true);
|
||||
return makeIterator(TheBucket, getBucketsEnd(), *this, true);
|
||||
return end();
|
||||
}
|
||||
template<class LookupKeyT>
|
||||
const_iterator find_as(const LookupKeyT &Val) const {
|
||||
const BucketT *TheBucket;
|
||||
if (LookupBucketFor(Val, TheBucket))
|
||||
return const_iterator(TheBucket, getBucketsEnd(), *this, true);
|
||||
return makeConstIterator(TheBucket, getBucketsEnd(), *this, true);
|
||||
return end();
|
||||
}
|
||||
|
||||
@ -191,14 +206,16 @@ public:
|
||||
std::pair<iterator, bool> try_emplace(KeyT &&Key, Ts &&... Args) {
|
||||
BucketT *TheBucket;
|
||||
if (LookupBucketFor(Key, TheBucket))
|
||||
return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
|
||||
false); // Already in map.
|
||||
return std::make_pair(
|
||||
makeIterator(TheBucket, getBucketsEnd(), *this, true),
|
||||
false); // Already in map.
|
||||
|
||||
// Otherwise, insert the new element.
|
||||
TheBucket =
|
||||
InsertIntoBucket(TheBucket, std::move(Key), std::forward<Ts>(Args)...);
|
||||
return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
|
||||
true);
|
||||
return std::make_pair(
|
||||
makeIterator(TheBucket, getBucketsEnd(), *this, true),
|
||||
true);
|
||||
}
|
||||
|
||||
// Inserts key,value pair into the map if the key isn't already in the map.
|
||||
@ -208,13 +225,15 @@ public:
|
||||
std::pair<iterator, bool> try_emplace(const KeyT &Key, Ts &&... Args) {
|
||||
BucketT *TheBucket;
|
||||
if (LookupBucketFor(Key, TheBucket))
|
||||
return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
|
||||
false); // Already in map.
|
||||
return std::make_pair(
|
||||
makeIterator(TheBucket, getBucketsEnd(), *this, true),
|
||||
false); // Already in map.
|
||||
|
||||
// Otherwise, insert the new element.
|
||||
TheBucket = InsertIntoBucket(TheBucket, Key, std::forward<Ts>(Args)...);
|
||||
return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
|
||||
true);
|
||||
return std::make_pair(
|
||||
makeIterator(TheBucket, getBucketsEnd(), *this, true),
|
||||
true);
|
||||
}
|
||||
|
||||
/// Alternate version of insert() which allows a different, and possibly
|
||||
@ -227,14 +246,16 @@ public:
|
||||
const LookupKeyT &Val) {
|
||||
BucketT *TheBucket;
|
||||
if (LookupBucketFor(Val, TheBucket))
|
||||
return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
|
||||
false); // Already in map.
|
||||
return std::make_pair(
|
||||
makeIterator(TheBucket, getBucketsEnd(), *this, true),
|
||||
false); // Already in map.
|
||||
|
||||
// Otherwise, insert the new element.
|
||||
TheBucket = InsertIntoBucketWithLookup(TheBucket, std::move(KV.first),
|
||||
std::move(KV.second), Val);
|
||||
return std::make_pair(iterator(TheBucket, getBucketsEnd(), *this, true),
|
||||
true);
|
||||
return std::make_pair(
|
||||
makeIterator(TheBucket, getBucketsEnd(), *this, true),
|
||||
true);
|
||||
}
|
||||
|
||||
/// insert - Range insertion of pairs.
|
||||
@ -405,6 +426,26 @@ protected:
|
||||
}
|
||||
|
||||
private:
|
||||
iterator makeIterator(BucketT *P, BucketT *E,
|
||||
DebugEpochBase &Epoch,
|
||||
bool NoAdvance=false) {
|
||||
if (shouldReverseIterate<KeyT>()) {
|
||||
BucketT *B = P == getBucketsEnd() ? getBuckets() : P + 1;
|
||||
return iterator(B, E, Epoch, NoAdvance);
|
||||
}
|
||||
return iterator(P, E, Epoch, NoAdvance);
|
||||
}
|
||||
|
||||
const_iterator makeConstIterator(const BucketT *P, const BucketT *E,
|
||||
const DebugEpochBase &Epoch,
|
||||
const bool NoAdvance=false) const {
|
||||
if (shouldReverseIterate<KeyT>()) {
|
||||
const BucketT *B = P == getBucketsEnd() ? getBuckets() : P + 1;
|
||||
return const_iterator(B, E, Epoch, NoAdvance);
|
||||
}
|
||||
return const_iterator(P, E, Epoch, NoAdvance);
|
||||
}
|
||||
|
||||
unsigned getNumEntries() const {
|
||||
return static_cast<const DerivedT *>(this)->getNumEntries();
|
||||
}
|
||||
@ -1089,7 +1130,13 @@ public:
|
||||
bool NoAdvance = false)
|
||||
: DebugEpochBase::HandleBase(&Epoch), Ptr(Pos), End(E) {
|
||||
assert(isHandleInSync() && "invalid construction!");
|
||||
if (!NoAdvance) AdvancePastEmptyBuckets();
|
||||
|
||||
if (NoAdvance) return;
|
||||
if (shouldReverseIterate<KeyT>()) {
|
||||
RetreatPastEmptyBuckets();
|
||||
return;
|
||||
}
|
||||
AdvancePastEmptyBuckets();
|
||||
}
|
||||
|
||||
// Converting ctor from non-const iterators to const iterators. SFINAE'd out
|
||||
@ -1103,10 +1150,14 @@ public:
|
||||
|
||||
reference operator*() const {
|
||||
assert(isHandleInSync() && "invalid iterator access!");
|
||||
if (shouldReverseIterate<KeyT>())
|
||||
return Ptr[-1];
|
||||
return *Ptr;
|
||||
}
|
||||
pointer operator->() const {
|
||||
assert(isHandleInSync() && "invalid iterator access!");
|
||||
if (shouldReverseIterate<KeyT>())
|
||||
return &(Ptr[-1]);
|
||||
return Ptr;
|
||||
}
|
||||
|
||||
@ -1127,6 +1178,11 @@ public:
|
||||
|
||||
inline DenseMapIterator& operator++() { // Preincrement
|
||||
assert(isHandleInSync() && "invalid iterator access!");
|
||||
if (shouldReverseIterate<KeyT>()) {
|
||||
--Ptr;
|
||||
RetreatPastEmptyBuckets();
|
||||
return *this;
|
||||
}
|
||||
++Ptr;
|
||||
AdvancePastEmptyBuckets();
|
||||
return *this;
|
||||
@ -1138,6 +1194,7 @@ public:
|
||||
|
||||
private:
|
||||
void AdvancePastEmptyBuckets() {
|
||||
assert(Ptr <= End);
|
||||
const KeyT Empty = KeyInfoT::getEmptyKey();
|
||||
const KeyT Tombstone = KeyInfoT::getTombstoneKey();
|
||||
|
||||
@ -1145,11 +1202,20 @@ private:
|
||||
KeyInfoT::isEqual(Ptr->getFirst(), Tombstone)))
|
||||
++Ptr;
|
||||
}
|
||||
|
||||
void RetreatPastEmptyBuckets() {
|
||||
assert(Ptr >= End);
|
||||
const KeyT Empty = KeyInfoT::getEmptyKey();
|
||||
const KeyT Tombstone = KeyInfoT::getTombstoneKey();
|
||||
|
||||
while (Ptr != End && (KeyInfoT::isEqual(Ptr[-1].getFirst(), Empty) ||
|
||||
KeyInfoT::isEqual(Ptr[-1].getFirst(), Tombstone)))
|
||||
--Ptr;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename KeyT, typename ValueT, typename KeyInfoT>
|
||||
static inline size_t
|
||||
capacity_in_bytes(const DenseMap<KeyT, ValueT, KeyInfoT> &X) {
|
||||
template <typename KeyT, typename ValueT, typename KeyInfoT>
|
||||
inline size_t capacity_in_bytes(const DenseMap<KeyT, ValueT, KeyInfoT> &X) {
|
||||
return X.getMemorySize();
|
||||
}
|
||||
|
||||
|
@ -239,6 +239,16 @@ public:
|
||||
return L1;
|
||||
}
|
||||
|
||||
// isEquivalent - Return true if V1 is equivalent to V2. This can happen if
|
||||
// V1 is equal to V2 or if they belong to one equivalence class.
|
||||
bool isEquivalent(const ElemTy &V1, const ElemTy &V2) const {
|
||||
// Fast path: any element is equivalent to itself.
|
||||
if (V1 == V2)
|
||||
return true;
|
||||
auto It = findLeader(V1);
|
||||
return It != member_end() && It == findLeader(V2);
|
||||
}
|
||||
|
||||
class member_iterator : public std::iterator<std::forward_iterator_tag,
|
||||
const ElemTy, ptrdiff_t> {
|
||||
friend class EquivalenceClasses;
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- llvm/ADT/FoldingSet.h - Uniquing Hash Set ---------------*- C++ -*-===//
|
||||
//===- llvm/ADT/FoldingSet.h - Uniquing Hash Set ----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -115,11 +115,9 @@ class FoldingSetBase {
|
||||
|
||||
protected:
|
||||
/// Buckets - Array of bucket chains.
|
||||
///
|
||||
void **Buckets;
|
||||
|
||||
/// NumBuckets - Length of the Buckets array. Always a power of 2.
|
||||
///
|
||||
unsigned NumBuckets;
|
||||
|
||||
/// NumNodes - Number of nodes in the folding set. Growth occurs when NumNodes
|
||||
@ -135,14 +133,13 @@ public:
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// Node - This class is used to maintain the singly linked bucket list in
|
||||
/// a folding set.
|
||||
///
|
||||
class Node {
|
||||
private:
|
||||
// NextInFoldingSetBucket - next link in the bucket list.
|
||||
void *NextInFoldingSetBucket;
|
||||
void *NextInFoldingSetBucket = nullptr;
|
||||
|
||||
public:
|
||||
Node() : NextInFoldingSetBucket(nullptr) {}
|
||||
Node() = default;
|
||||
|
||||
// Accessors
|
||||
void *getNextInBucket() const { return NextInFoldingSetBucket; }
|
||||
@ -221,7 +218,6 @@ protected:
|
||||
|
||||
/// DefaultFoldingSetTrait - This class provides default implementations
|
||||
/// for FoldingSetTrait implementations.
|
||||
///
|
||||
template<typename T> struct DefaultFoldingSetTrait {
|
||||
static void Profile(const T &X, FoldingSetNodeID &ID) {
|
||||
X.Profile(ID);
|
||||
@ -307,7 +303,6 @@ public:
|
||||
/// FoldingSetNodeID - This class is used to gather all the unique data bits of
|
||||
/// a node. When all the bits are gathered this class is used to produce a
|
||||
/// hash value for the node.
|
||||
///
|
||||
class FoldingSetNodeID {
|
||||
/// Bits - Vector of all the data bits that make the node unique.
|
||||
/// Use a SmallVector to avoid a heap allocation in the common case.
|
||||
@ -320,7 +315,6 @@ public:
|
||||
: Bits(Ref.getData(), Ref.getData() + Ref.getSize()) {}
|
||||
|
||||
/// Add* - Add various data types to Bit data.
|
||||
///
|
||||
void AddPointer(const void *Ptr);
|
||||
void AddInteger(signed I);
|
||||
void AddInteger(unsigned I);
|
||||
@ -344,7 +338,6 @@ public:
|
||||
unsigned ComputeHash() const;
|
||||
|
||||
/// operator== - Used to compare two nodes to each other.
|
||||
///
|
||||
bool operator==(const FoldingSetNodeID &RHS) const;
|
||||
bool operator==(const FoldingSetNodeIDRef RHS) const;
|
||||
|
||||
@ -363,7 +356,7 @@ public:
|
||||
};
|
||||
|
||||
// Convenience type to hide the implementation of the folding set.
|
||||
typedef FoldingSetBase::Node FoldingSetNode;
|
||||
using FoldingSetNode = FoldingSetBase::Node;
|
||||
template<class T> class FoldingSetIterator;
|
||||
template<class T> class FoldingSetBucketIterator;
|
||||
|
||||
@ -415,15 +408,17 @@ protected:
|
||||
~FoldingSetImpl() = default;
|
||||
|
||||
public:
|
||||
typedef FoldingSetIterator<T> iterator;
|
||||
using iterator = FoldingSetIterator<T>;
|
||||
|
||||
iterator begin() { return iterator(Buckets); }
|
||||
iterator end() { return iterator(Buckets+NumBuckets); }
|
||||
|
||||
typedef FoldingSetIterator<const T> const_iterator;
|
||||
using const_iterator = FoldingSetIterator<const T>;
|
||||
|
||||
const_iterator begin() const { return const_iterator(Buckets); }
|
||||
const_iterator end() const { return const_iterator(Buckets+NumBuckets); }
|
||||
|
||||
typedef FoldingSetBucketIterator<T> bucket_iterator;
|
||||
using bucket_iterator = FoldingSetBucketIterator<T>;
|
||||
|
||||
bucket_iterator bucket_begin(unsigned hash) {
|
||||
return bucket_iterator(Buckets + (hash & (NumBuckets-1)));
|
||||
@ -503,9 +498,7 @@ template <class T> class FoldingSet final : public FoldingSetImpl<T> {
|
||||
}
|
||||
|
||||
public:
|
||||
explicit FoldingSet(unsigned Log2InitSize = 6)
|
||||
: Super(Log2InitSize) {}
|
||||
|
||||
explicit FoldingSet(unsigned Log2InitSize = 6) : Super(Log2InitSize) {}
|
||||
FoldingSet(FoldingSet &&Arg) = default;
|
||||
FoldingSet &operator=(FoldingSet &&RHS) = default;
|
||||
};
|
||||
@ -552,8 +545,7 @@ class ContextualFoldingSet final : public FoldingSetImpl<T> {
|
||||
|
||||
public:
|
||||
explicit ContextualFoldingSet(Ctx Context, unsigned Log2InitSize = 6)
|
||||
: Super(Log2InitSize), Context(Context)
|
||||
{}
|
||||
: Super(Log2InitSize), Context(Context) {}
|
||||
|
||||
Ctx getContext() const { return Context; }
|
||||
};
|
||||
@ -569,15 +561,15 @@ class FoldingSetVector {
|
||||
VectorT Vector;
|
||||
|
||||
public:
|
||||
explicit FoldingSetVector(unsigned Log2InitSize = 6)
|
||||
: Set(Log2InitSize) {
|
||||
}
|
||||
explicit FoldingSetVector(unsigned Log2InitSize = 6) : Set(Log2InitSize) {}
|
||||
|
||||
using iterator = pointee_iterator<typename VectorT::iterator>;
|
||||
|
||||
typedef pointee_iterator<typename VectorT::iterator> iterator;
|
||||
iterator begin() { return Vector.begin(); }
|
||||
iterator end() { return Vector.end(); }
|
||||
|
||||
typedef pointee_iterator<typename VectorT::const_iterator> const_iterator;
|
||||
using const_iterator = pointee_iterator<typename VectorT::const_iterator>;
|
||||
|
||||
const_iterator begin() const { return Vector.begin(); }
|
||||
const_iterator end() const { return Vector.end(); }
|
||||
|
||||
@ -667,15 +659,13 @@ public:
|
||||
/// FoldingSetBucketIteratorImpl - This is the common bucket iterator support
|
||||
/// shared by all folding sets, which knows how to walk a particular bucket
|
||||
/// of a folding set hash table.
|
||||
|
||||
class FoldingSetBucketIteratorImpl {
|
||||
protected:
|
||||
void *Ptr;
|
||||
|
||||
explicit FoldingSetBucketIteratorImpl(void **Bucket);
|
||||
|
||||
FoldingSetBucketIteratorImpl(void **Bucket, bool)
|
||||
: Ptr(Bucket) {}
|
||||
FoldingSetBucketIteratorImpl(void **Bucket, bool) : Ptr(Bucket) {}
|
||||
|
||||
void advance() {
|
||||
void *Probe = static_cast<FoldingSetNode*>(Ptr)->getNextInBucket();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user