diff --git a/.arcconfig b/.arcconfig index 413b70b05f7..ef3e3276aef 100644 --- a/.arcconfig +++ b/.arcconfig @@ -1,4 +1,4 @@ { "project_id" : "compiler-rt", - "conduit_uri" : "http://llvm-reviews.chandlerc.com/" + "conduit_uri" : "http://reviews.llvm.org/" } diff --git a/.gitignore b/.gitignore index 7c534314923..2a7bdd6a891 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ darwin_fat clang_darwin multi_arch +*.sw? diff --git a/CMakeLists.txt b/CMakeLists.txt index a4424086c69..a6a4ed96105 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,49 +1,166 @@ # CMake build for CompilerRT. # # This build assumes that CompilerRT is checked out into the -# 'projects/compiler-rt' inside of an LLVM tree, it is not a stand-alone build -# system. +# 'projects/compiler-rt' inside of an LLVM tree. +# Standalone build system for CompilerRT is not yet ready. # # An important constraint of the build is that it only produces libraries # based on the ability of the host toolchain to target various platforms. -include(LLVMParseArguments) +# Check if compiler-rt is built as a standalone project. +if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + project(CompilerRT C CXX) + set(COMPILER_RT_STANDALONE_BUILD TRUE) +else() + set(COMPILER_RT_STANDALONE_BUILD FALSE) +endif() # The CompilerRT build system requires CMake version 2.8.8 or higher in order # to use its support for building convenience "libraries" as a collection of # .o files. This is particularly useful in producing larger, more complex # runtime libraries. -cmake_minimum_required(VERSION 2.8.8) +if (NOT MSVC) + cmake_minimum_required(VERSION 2.8.8) +else() + # Version 2.8.12.1 is required to build with Visual Studion 2013. + cmake_minimum_required(VERSION 2.8.12.1) +endif() + +# FIXME: It may be removed when we use 2.8.12. +if(CMAKE_VERSION VERSION_LESS 2.8.12) + # Invalidate a couple of keywords. + set(cmake_2_8_12_INTERFACE) + set(cmake_2_8_12_PRIVATE) +else() + # Use ${cmake_2_8_12_KEYWORD} intead of KEYWORD in target_link_libraries(). + set(cmake_2_8_12_INTERFACE INTERFACE) + set(cmake_2_8_12_PRIVATE PRIVATE) + if(POLICY CMP0022) + cmake_policy(SET CMP0022 NEW) # automatic when 2.8.12 is required + endif() +endif() # Top level target used to build all compiler-rt libraries. -add_custom_target(compiler-rt) +add_custom_target(compiler-rt ALL) -# Compute the Clang version from the LLVM version. -# FIXME: We should be able to reuse CLANG_VERSION variable calculated -# in Clang cmake files, instead of copying the rules here. -string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION - ${PACKAGE_VERSION}) -# Setup the paths where compiler-rt runtimes and headers should be stored. -set(LIBCLANG_INSTALL_PATH lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}) -string(TOLOWER ${CMAKE_SYSTEM_NAME} LIBCLANG_OS_DIR) -set(CLANG_RESOURCE_DIR ${LLVM_BINARY_DIR}/lib/clang/${CLANG_VERSION}) -set(COMPILER_RT_LIBRARY_OUTPUT_DIR ${CLANG_RESOURCE_DIR}/lib/${LIBCLANG_OS_DIR}) +if (NOT COMPILER_RT_STANDALONE_BUILD) + # Compute the Clang version from the LLVM version. + # FIXME: We should be able to reuse CLANG_VERSION variable calculated + # in Clang cmake files, instead of copying the rules here. + string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" CLANG_VERSION + ${PACKAGE_VERSION}) + # Setup the paths where compiler-rt runtimes and headers should be stored. + set(COMPILER_RT_OUTPUT_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/clang/${CLANG_VERSION}) + set(COMPILER_RT_EXEC_OUTPUT_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR}) + set(COMPILER_RT_INSTALL_PATH lib${LLVM_LIBDIR_SUFFIX}/clang/${CLANG_VERSION}) + option(COMPILER_RT_INCLUDE_TESTS "Generate and build compiler-rt unit tests." + ${LLVM_INCLUDE_TESTS}) + option(COMPILER_RT_ENABLE_WERROR "Fail and stop if warning is triggered" + ${LLVM_ENABLE_WERROR}) + # Use just-built Clang to compile/link tests on all platforms, except for + # Windows where we need to use clang-cl instead. + if(NOT MSVC) + set(COMPILER_RT_TEST_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang) + else() + set(COMPILER_RT_TEST_COMPILER ${LLVM_RUNTIME_OUTPUT_INTDIR}/clang.exe) + endif() +else() + # Take output dir and install path from the user. + set(COMPILER_RT_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR} CACHE PATH + "Path where built compiler-rt libraries should be stored.") + set(COMPILER_RT_EXEC_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/bin CACHE PATH + "Path where built compiler-rt executables should be stored.") + set(COMPILER_RT_INSTALL_PATH ${CMAKE_INSTALL_PREFIX} CACHE PATH + "Path where built compiler-rt libraries should be installed.") + option(COMPILER_RT_INCLUDE_TESTS "Generate and build compiler-rt unit tests." OFF) + option(COMPILER_RT_ENABLE_WERROR "Fail and stop if warning is triggered" OFF) + # Use a host compiler to compile/link tests. + set(COMPILER_RT_TEST_COMPILER ${CMAKE_C_COMPILER} CACHE PATH "Compiler to use for testing") + + if (NOT LLVM_CONFIG_PATH) + find_program(LLVM_CONFIG_PATH "llvm-config" + DOC "Path to llvm-config binary") + if (NOT LLVM_CONFIG_PATH) + message(FATAL_ERROR "llvm-config not found: specify LLVM_CONFIG_PATH") + endif() + endif() + execute_process( + COMMAND ${LLVM_CONFIG_PATH} "--obj-root" "--bindir" "--libdir" "--src-root" + RESULT_VARIABLE HAD_ERROR + OUTPUT_VARIABLE CONFIG_OUTPUT) + if (HAD_ERROR) + message(FATAL_ERROR "llvm-config failed with status ${HAD_ERROR}") + endif() + string(REGEX REPLACE "[ \t]*[\r\n]+[ \t]*" ";" CONFIG_OUTPUT ${CONFIG_OUTPUT}) + list(GET CONFIG_OUTPUT 0 LLVM_BINARY_DIR) + list(GET CONFIG_OUTPUT 1 LLVM_TOOLS_BINARY_DIR) + list(GET CONFIG_OUTPUT 2 LLVM_LIBRARY_DIR) + list(GET CONFIG_OUTPUT 3 LLVM_MAIN_SRC_DIR) + + # Make use of LLVM CMake modules. + file(TO_CMAKE_PATH ${LLVM_BINARY_DIR} LLVM_BINARY_DIR_CMAKE_STYLE) + set(LLVM_CMAKE_PATH "${LLVM_BINARY_DIR_CMAKE_STYLE}/share/llvm/cmake") + list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_PATH}") + # Get some LLVM variables from LLVMConfig. + include("${LLVM_CMAKE_PATH}/LLVMConfig.cmake") + + set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib) + + # Find Python interpreter. + set(Python_ADDITIONAL_VERSIONS 2.7 2.6 2.5) + include(FindPythonInterp) + if(NOT PYTHONINTERP_FOUND) + message(FATAL_ERROR " + Unable to find Python interpreter required testing. Please install Python + or specify the PYTHON_EXECUTABLE CMake variable.") + endif() + + # Define default arguments to lit. + set(LIT_ARGS_DEFAULT "-sv") + if (MSVC OR XCODE) + set(LIT_ARGS_DEFAULT "${LIT_ARGS_DEFAULT} --no-progress-bar") + endif() + set(LLVM_LIT_ARGS "${LIT_ARGS_DEFAULT}" CACHE STRING "Default options for lit") +endif() + +if("${COMPILER_RT_TEST_COMPILER}" MATCHES "clang[+]*$") + set(COMPILER_RT_TEST_COMPILER_ID Clang) +elseif("${COMPILER_RT_TEST_COMPILER}" MATCHES "clang.*.exe$") + set(COMPILER_RT_TEST_COMPILER_ID Clang) +else() + set(COMPILER_RT_TEST_COMPILER_ID GNU) +endif() + +# Tests using XFAIL use the first value in COMPILER_RT_TEST_TARGET_TRIPLE +set(COMPILER_RT_TEST_TARGET_TRIPLE ${TARGET_TRIPLE} CACHE STRING + "Default triple for cross-compiled executables") +string(REPLACE "-" ";" TARGET_TRIPLE_LIST ${COMPILER_RT_TEST_TARGET_TRIPLE}) +list(GET TARGET_TRIPLE_LIST 0 COMPILER_RT_TEST_TARGET_ARCH) +list(GET TARGET_TRIPLE_LIST 1 COMPILER_RT_TEST_TARGET_OS) +list(GET TARGET_TRIPLE_LIST 2 COMPILER_RT_TEST_TARGET_ABI) + +if ("${COMPILER_RT_TEST_TARGET_ABI}" STREQUAL "androideabi") + set(ANDROID 1) +endif() + +string(TOLOWER ${CMAKE_SYSTEM_NAME} COMPILER_RT_OS_DIR) +set(COMPILER_RT_LIBRARY_OUTPUT_DIR + ${COMPILER_RT_OUTPUT_DIR}/lib/${COMPILER_RT_OS_DIR}) set(COMPILER_RT_LIBRARY_INSTALL_DIR - ${LIBCLANG_INSTALL_PATH}/lib/${LIBCLANG_OS_DIR}) + ${COMPILER_RT_INSTALL_PATH}/lib/${COMPILER_RT_OS_DIR}) -# Add path for custom modules +# Add path for custom compiler-rt modules. set(CMAKE_MODULE_PATH - ${CMAKE_MODULE_PATH} + "${CMAKE_CURRENT_SOURCE_DIR}/cmake" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules" + ${CMAKE_MODULE_PATH} ) -include(AddCompilerRT) +include(CompilerRTUtils) set(COMPILER_RT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(COMPILER_RT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) # Setup custom SDK sysroots. -set(COMPILER_RT_DARWIN_SDK_SYSROOT ${COMPILER_RT_SOURCE_DIR}/SDKs/darwin) set(COMPILER_RT_LINUX_SDK_SYSROOT ${COMPILER_RT_SOURCE_DIR}/SDKs/linux) -include(SanitizerUtils) # Detect whether the current target platform is 32-bit or 64-bit, and setup # the correct commandline flags needed to attempt to target 32-bit and 64-bit. @@ -59,9 +176,6 @@ else() set(TARGET_32_BIT_CFLAGS "") endif() -# List of architectures we can target. -set(COMPILER_RT_SUPPORTED_ARCH) - function(get_target_flags_for_arch arch out_var) list(FIND COMPILER_RT_SUPPORTED_ARCH ${arch} ARCH_INDEX) if(ARCH_INDEX EQUAL -1) @@ -71,115 +185,103 @@ function(get_target_flags_for_arch arch out_var) endif() endfunction() -# Try to compile a very simple source file to ensure we can target the given -# platform. We use the results of these tests to build only the various target -# runtime libraries supported by our current compilers cross-compiling -# abilities. -set(SIMPLE_SOURCE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/simple.c) -file(WRITE ${SIMPLE_SOURCE} "#include \nint main() {}") - -# test_target_arch( ) -# Sets the target flags for a given architecture and determines if this -# architecture is supported by trying to build a simple file. -macro(test_target_arch arch) - set(TARGET_${arch}_CFLAGS ${ARGN}) - try_compile(CAN_TARGET_${arch} ${CMAKE_BINARY_DIR} ${SIMPLE_SOURCE} - COMPILE_DEFINITIONS "${TARGET_${arch}_CFLAGS}" - CMAKE_FLAGS "-DCMAKE_EXE_LINKER_FLAGS:STRING=${TARGET_${arch}_CFLAGS}") - if(${CAN_TARGET_${arch}}) - list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch}) - endif() -endmacro() - -if("${LLVM_NATIVE_ARCH}" STREQUAL "X86") - if (NOT MSVC) - test_target_arch(x86_64 ${TARGET_64_BIT_CFLAGS}) - endif() - test_target_arch(i386 ${TARGET_32_BIT_CFLAGS}) -elseif("${LLVM_NATIVE_ARCH}" STREQUAL "PowerPC") - test_target_arch(powerpc64 ${TARGET_64_BIT_CFLAGS}) -endif() - -# We only support running instrumented tests when we're not cross compiling -# and target a unix-like system. On Android we define the rules for building -# unit tests, but don't execute them. -if("${CMAKE_HOST_SYSTEM}" STREQUAL "${CMAKE_SYSTEM}" AND UNIX AND NOT ANDROID) +# We support running instrumented tests when we're not cross compiling +# and target a UNIX-like system or Windows. +# We can run tests on Android even when we are cross-compiling. +if(("${CMAKE_HOST_SYSTEM}" STREQUAL "${CMAKE_SYSTEM}" AND (UNIX OR MSVC)) OR ANDROID + OR COMPILER_RT_EMULATOR) option(COMPILER_RT_CAN_EXECUTE_TESTS "Can we execute instrumented tests" ON) else() option(COMPILER_RT_CAN_EXECUTE_TESTS "Can we execute instrumented tests" OFF) endif() -# Check if compiler-rt is built with libc++. -find_flag_in_string("${CMAKE_CXX_FLAGS}" "-stdlib=libc++" - COMPILER_RT_USES_LIBCXX) - -function(filter_available_targets out_var) - set(archs) - foreach(arch ${ARGN}) - list(FIND COMPILER_RT_SUPPORTED_ARCH ${arch} ARCH_INDEX) - if(NOT (ARCH_INDEX EQUAL -1) AND CAN_TARGET_${arch}) - list(APPEND archs ${arch}) - endif() - endforeach() - set(${out_var} ${archs} PARENT_SCOPE) -endfunction() - option(COMPILER_RT_DEBUG "Build runtimes with full debug info" OFF) - # COMPILER_RT_DEBUG_PYBOOL is used by lit.common.configured.in. pythonize_bool(COMPILER_RT_DEBUG) -# Provide some common commmandline flags for Sanitizer runtimes. -if (NOT MSVC) - set(SANITIZER_COMMON_CFLAGS - -fPIC - -fno-builtin - -fno-exceptions - -fomit-frame-pointer - -funwind-tables - -fno-stack-protector - -Wno-gnu # Variadic macros with 0 arguments for ... - -fvisibility=hidden - ) - if (NOT COMPILER_RT_DEBUG) - list(APPEND SANITIZER_COMMON_CFLAGS -O3) - endif() +# We have to support both static and dynamic/shared runtime on Windows. +# Android only works with dynamic runtime. +if(WIN32 OR ANDROID) +option(COMPILER_RT_BUILD_SHARED_ASAN "Build shared version of AddressSanitizer runtime" ON) else() - set(SANITIZER_COMMON_CFLAGS - /MT - /Zi - /Oy- - /GS- - /wd4722 - ) +option(COMPILER_RT_BUILD_SHARED_ASAN "Build shared version of AddressSanitizer runtime" OFF) endif() -# Build sanitizer runtimes with debug info. (MSVC gets /Zi above) -if (NOT MSVC) - check_cxx_compiler_flag(-gline-tables-only SUPPORTS_GLINE_TABLES_ONLY_FLAG) - if(SUPPORTS_GLINE_TABLES_ONLY_FLAG AND NOT COMPILER_RT_DEBUG) - list(APPEND SANITIZER_COMMON_CFLAGS -gline-tables-only) - else() - list(APPEND SANITIZER_COMMON_CFLAGS -g) - endif() -endif() -# Warnings suppressions. -check_cxx_compiler_flag(-Wno-variadic-macros SUPPORTS_NO_VARIADIC_MACROS_FLAG) -if(SUPPORTS_NO_VARIADIC_MACROS_FLAG) - list(APPEND SANITIZER_COMMON_CFLAGS -Wno-variadic-macros) -endif() -check_cxx_compiler_flag(-Wno-c99-extensions SUPPORTS_NO_C99_EXTENSIONS_FLAG) -if(SUPPORTS_NO_C99_EXTENSIONS_FLAG) - list(APPEND SANITIZER_COMMON_CFLAGS -Wno-c99-extensions) -endif() -# Sanitizer may not have libstdc++, so we can have problems with virtual -# destructors. -check_cxx_compiler_flag(-Wno-non-virtual-dtor SUPPORTS_NO_NON_VIRTUAL_DTOR_FLAG) -if (SUPPORTS_NO_NON_VIRTUAL_DTOR_FLAG) - list(APPEND SANITIZER_COMMON_CFLAGS -Wno-non-virtual-dtor) -endif() -check_cxx_compiler_flag(-Wglobal-constructors SUPPORTS_GLOBAL_CONSTRUCTORS_FLAG) -# Not all sanitizers forbid global constructors. +#================================ +# Setup Compiler Flags +#================================ +include(config-ix) + +if(MSVC) + append_string_if(COMPILER_RT_HAS_W3_FLAG /W3 CMAKE_C_FLAGS CMAKE_CXX_FLAGS) +else() + append_string_if(COMPILER_RT_HAS_WALL_FLAG -Wall CMAKE_C_FLAGS CMAKE_CXX_FLAGS) +endif() +if(COMPILER_RT_ENABLE_WERROR) + append_string_if(COMPILER_RT_HAS_WERROR_FLAG -Werror CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + append_string_if(COMPILER_RT_HAS_WX_FLAG /WX CMAKE_C_FLAGS CMAKE_CXX_FLAGS) +endif() + +append_string_if(COMPILER_RT_HAS_STD_CXX11_FLAG -std=c++11 CMAKE_CXX_FLAGS) + +# Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP. +if(NOT COMPILER_RT_HAS_FUNC_SYMBOL) + add_definitions(-D__func__=__FUNCTION__) +endif() + +# Provide some common commmandline flags for Sanitizer runtimes. +append_list_if(COMPILER_RT_HAS_FPIC_FLAG -fPIC SANITIZER_COMMON_CFLAGS) +append_list_if(COMPILER_RT_HAS_FNO_BUILTIN_FLAG -fno-builtin SANITIZER_COMMON_CFLAGS) +append_list_if(COMPILER_RT_HAS_FNO_EXCEPTIONS_FLAG -fno-exceptions SANITIZER_COMMON_CFLAGS) +append_list_if(COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG -fomit-frame-pointer SANITIZER_COMMON_CFLAGS) +append_list_if(COMPILER_RT_HAS_FUNWIND_TABLES_FLAG -funwind-tables SANITIZER_COMMON_CFLAGS) +append_list_if(COMPILER_RT_HAS_FNO_STACK_PROTECTOR_FLAG -fno-stack-protector SANITIZER_COMMON_CFLAGS) +append_list_if(COMPILER_RT_HAS_FVISIBILITY_HIDDEN_FLAG -fvisibility=hidden SANITIZER_COMMON_CFLAGS) +append_list_if(COMPILER_RT_HAS_FNO_FUNCTION_SECTIONS_FLAG -fno-function-sections SANITIZER_COMMON_CFLAGS) + +if(MSVC) + # Replace the /MD[d] flags with /MT. + # FIXME: In fact, sanitizers should support both /MT and /MD, see PR20214. + if(COMPILER_RT_HAS_MT_FLAG) + foreach(flag_var + CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) + if(${flag_var} MATCHES "/MD") + string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") + elseif(${flag_var} MATCHES "/MDd") + string(REGEX REPLACE "/MDd" "/MT" ${flag_var} "${${flag_var}}") + endif() + endforeach() + endif() + append_list_if(COMPILER_RT_HAS_Oy_FLAG /Oy- SANITIZER_COMMON_CFLAGS) + append_list_if(COMPILER_RT_HAS_GS_FLAG /GS- SANITIZER_COMMON_CFLAGS) +endif() + +# Build with optimization, unless we're in debug mode. If we're using MSVC, +# always respect the optimization flags set by CMAKE_BUILD_TYPE instead. +if(NOT COMPILER_RT_DEBUG AND NOT MSVC) + list(APPEND SANITIZER_COMMON_CFLAGS -O3) +endif() + +# Build sanitizer runtimes with debug info. +if(COMPILER_RT_HAS_GLINE_TABLES_ONLY_FLAG) + list(APPEND SANITIZER_COMMON_CFLAGS -gline-tables-only) +elseif(COMPILER_RT_HAS_G_FLAG) + list(APPEND SANITIZER_COMMON_CFLAGS -g) +elseif(COMPILER_RT_HAS_Zi_FLAG) + list(APPEND SANITIZER_COMMON_CFLAGS /Zi) +endif() + +# Turn off several warnings. +append_list_if(COMPILER_RT_HAS_WGNU_FLAG -Wno-gnu SANITIZER_COMMON_CFLAGS) +append_list_if(COMPILER_RT_HAS_WVARIADIC_MACROS_FLAG -Wno-variadic-macros SANITIZER_COMMON_CFLAGS) +append_list_if(COMPILER_RT_HAS_WC99_EXTENSIONS_FLAG -Wno-c99-extensions SANITIZER_COMMON_CFLAGS) +append_list_if(COMPILER_RT_HAS_WNON_VIRTUAL_DTOR_FLAG -Wno-non-virtual-dtor SANITIZER_COMMON_CFLAGS) +append_list_if(COMPILER_RT_HAS_WD4146_FLAG /wd4146 SANITIZER_COMMON_CFLAGS) +append_list_if(COMPILER_RT_HAS_WD4291_FLAG /wd4291 SANITIZER_COMMON_CFLAGS) +append_list_if(COMPILER_RT_HAS_WD4391_FLAG /wd4391 SANITIZER_COMMON_CFLAGS) +append_list_if(COMPILER_RT_HAS_WD4722_FLAG /wd4722 SANITIZER_COMMON_CFLAGS) +append_list_if(COMPILER_RT_HAS_WD4800_FLAG /wd4800 SANITIZER_COMMON_CFLAGS) if(APPLE) # Obtain the iOS Simulator SDK path from xcodebuild. execute_process( @@ -187,18 +289,17 @@ if(APPLE) OUTPUT_VARIABLE IOSSIM_SDK_DIR OUTPUT_STRIP_TRAILING_WHITESPACE ) + string(REGEX MATCH "-mmacosx-version-min=" + MACOSX_VERSION_MIN_FLAG "${CMAKE_CXX_FLAGS}") set(SANITIZER_COMMON_SUPPORTED_DARWIN_OS osx) - if (IOSSIM_SDK_DIR) + if (IOSSIM_SDK_DIR AND NOT MACOSX_VERSION_MIN_FLAG) list(APPEND SANITIZER_COMMON_SUPPORTED_DARWIN_OS iossim) endif() - if(COMPILER_RT_USES_LIBCXX) - set(SANITIZER_MIN_OSX_VERSION 10.7) - else() - set(SANITIZER_MIN_OSX_VERSION 10.6) - endif() + set(SANITIZER_MIN_OSX_VERSION 10.7) + set(CMAKE_OSX_DEPLOYMENT_TARGET "") # We're setting the flag manually below. set(DARWIN_osx_CFLAGS -mmacosx-version-min=${SANITIZER_MIN_OSX_VERSION}) - set(DARWIN_iossim_CFLAGS + set(DARWIN_iossim_CFLAGS -mios-simulator-version-min=7.0 -isysroot ${IOSSIM_SDK_DIR}) set(DARWIN_osx_LINKFLAGS) set(DARWIN_iossim_LINKFLAGS @@ -207,26 +308,18 @@ if(APPLE) -isysroot ${IOSSIM_SDK_DIR}) endif() -# Architectures supported by Sanitizer runtimes. Specific sanitizers may -# support only subset of these (e.g. TSan works on x86_64 only). -filter_available_targets(SANITIZER_COMMON_SUPPORTED_ARCH - x86_64 i386 powerpc64) - add_subdirectory(include) -set(SANITIZER_COMMON_LIT_TEST_DEPS - clang clang-headers FileCheck count not llvm-nm llvm-symbolizer - compiler-rt-headers) -# Check code style when running lit tests for sanitizers. -if(UNIX) - list(APPEND SANITIZER_COMMON_LIT_TEST_DEPS SanitizerLintCheck) +set(COMPILER_RT_LIBCXX_PATH ${LLVM_MAIN_SRC_DIR}/projects/libcxx) +if(EXISTS ${COMPILER_RT_LIBCXX_PATH}/) + set(COMPILER_RT_HAS_LIBCXX_SOURCES TRUE) +else() + set(COMPILER_RT_HAS_LIBCXX_SOURCES FALSE) endif() add_subdirectory(lib) -if(LLVM_INCLUDE_TESTS) - # Currently the tests have not been ported to CMake, so disable this - # directory. - # - #add_subdirectory(test) +if(COMPILER_RT_INCLUDE_TESTS) + add_subdirectory(unittests) endif() +add_subdirectory(test) diff --git a/CODE_OWNERS.TXT b/CODE_OWNERS.TXT new file mode 100644 index 00000000000..2159ad7b845 --- /dev/null +++ b/CODE_OWNERS.TXT @@ -0,0 +1,57 @@ +This file is a list of the people responsible for ensuring that patches for a +particular part of compiler-rt are reviewed, either by themself or by +someone else. They are also the gatekeepers for their part of compiler-rt, with +the final word on what goes in or not. + +The list is sorted by surname and formatted to allow easy grepping and +beautification by scripts. The fields are: name (N), email (E), web-address +(W), PGP key ID and fingerprint (P), description (D), and snail-mail address +(S). + +N: Peter Collingbourne +E: peter@pcc.me.uk +D: DataFlowSanitizer + +N: Daniel Dunbar +E: daniel@zuster.org +D: Makefile build + +N: Timur Iskhodzhanov +E: timurrrr@google.com +D: AddressSanitizer for Windows + +N: Howard Hinnant +E: howard.hinnant@gmail.com +D: builtins library + +N: Sergey Matveev +E: earthdok@google.com +D: LeakSanitizer + +N: Alexander Potapenko +E: glider@google.com +D: MacOS/iOS port of sanitizers + +N: Alexey Samsonov +E: samsonov@google.com +D: CMake build, test suite + +N: Kostya Serebryany +E: kcc@google.com +D: AddressSanitizer, sanitizer_common, porting sanitizers to another platforms + +N: Richard Smith +E: richard-llvm@metafoo.co.uk +D: UndefinedBehaviorSanitizer + +N: Evgeniy Stepanov +E: eugenis@google.com +D: MemorySanitizer, Android port of sanitizers + +N: Dmitry Vyukov +E: dvyukov@google.com +D: ThreadSanitizer + +N: Bill Wendling +E: isanbard@gmail.com +D: Profile runtime library diff --git a/CREDITS.TXT b/CREDITS.TXT index 818f4fa104d..6964eba020b 100644 --- a/CREDITS.TXT +++ b/CREDITS.TXT @@ -22,3 +22,15 @@ D: Maintain Solaris & AuroraUX ports of Compiler-RT N: Howard Hinnant E: hhinnant@apple.com D: Architect and primary author of compiler-rt + +N: Guan-Hong Liu +E: koviankevin@hotmail.com +D: IEEE Quad-precision functions + +N: Joerg Sonnenberger +E: joerg@NetBSD.org +D: Maintains NetBSD port. + +N: Matt Thomas +E: matt@NetBSD.org +D: ARM improvements. diff --git a/LICENSE.TXT b/LICENSE.TXT index 6aab1f694cc..aee8347b0c3 100644 --- a/LICENSE.TXT +++ b/LICENSE.TXT @@ -14,7 +14,7 @@ Full text of the relevant licenses is included below. University of Illinois/NCSA Open Source License -Copyright (c) 2009-2013 by the contributors listed in CREDITS.TXT +Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT All rights reserved. @@ -55,7 +55,7 @@ SOFTWARE. ============================================================================== -Copyright (c) 2009-2013 by the contributors listed in CREDITS.TXT +Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -89,9 +89,3 @@ other licenses gives permission to use the names of the LLVM Team or the University of Illinois to endorse or promote products derived from this Software. -The following pieces of software have additional or alternate copyrights, -licenses, and/or restrictions: - -Program Directory -------- --------- -mach_override lib/interception/mach_override diff --git a/Makefile b/Makefile index 6747ea4d431..ac3daac5fce 100644 --- a/Makefile +++ b/Makefile @@ -249,10 +249,10 @@ $(call Set,Tmp.CFLAGS,$(strip \ $(Tmp.ObjPath)/%.o: $(Tmp.SrcPath)/%.s $(Tmp.Dependencies) $(Tmp.ObjPath)/.dir $(Summary) " ASSEMBLE: $(Tmp.Name)/$(Tmp.Config)/$(Tmp.Arch): $$<" - $(Verb) $(Tmp.CC) $(Tmp.CFLAGS) -c -o $$@ $$< + $(Verb) $(Tmp.CC) $(COMMON_ASMFLAGS) $(Tmp.CFLAGS) -c -o $$@ $$< $(Tmp.ObjPath)/%.o: $(Tmp.SrcPath)/%.S $(Tmp.Dependencies) $(Tmp.ObjPath)/.dir $(Summary) " ASSEMBLE: $(Tmp.Name)/$(Tmp.Config)/$(Tmp.Arch): $$<" - $(Verb) $(Tmp.CC) $(Tmp.CFLAGS) -c -o $$@ $$< + $(Verb) $(Tmp.CC) $(COMMON_ASMFLAGS) $(Tmp.CFLAGS) -c -o $$@ $$< $(Tmp.ObjPath)/%.o: $(Tmp.SrcPath)/%.c $(Tmp.Dependencies) $(Tmp.ObjPath)/.dir $(Summary) " COMPILE: $(Tmp.Name)/$(Tmp.Config)/$(Tmp.Arch): $$<" $(Verb) $(Tmp.CC) $(COMMON_CFLAGS) $(Tmp.CFLAGS) -c -o $$@ $$< diff --git a/README.txt b/README.txt index b37c0aecdeb..fc8843246e2 100644 --- a/README.txt +++ b/README.txt @@ -9,335 +9,3 @@ terms of the license agreement found in LICENSE.txt. ================================ -This is a replacement library for libgcc. Each function is contained -in its own file. Each function has a corresponding unit test under -test/Unit. - -A rudimentary script to test each file is in the file called -test/Unit/test. - -Here is the specification for this library: - -http://gcc.gnu.org/onlinedocs/gccint/Libgcc.html#Libgcc - -Here is a synopsis of the contents of this library: - -typedef int si_int; -typedef unsigned su_int; - -typedef long long di_int; -typedef unsigned long long du_int; - -// Integral bit manipulation - -di_int __ashldi3(di_int a, si_int b); // a << b -ti_int __ashlti3(ti_int a, si_int b); // a << b - -di_int __ashrdi3(di_int a, si_int b); // a >> b arithmetic (sign fill) -ti_int __ashrti3(ti_int a, si_int b); // a >> b arithmetic (sign fill) -di_int __lshrdi3(di_int a, si_int b); // a >> b logical (zero fill) -ti_int __lshrti3(ti_int a, si_int b); // a >> b logical (zero fill) - -si_int __clzsi2(si_int a); // count leading zeros -si_int __clzdi2(di_int a); // count leading zeros -si_int __clzti2(ti_int a); // count leading zeros -si_int __ctzsi2(si_int a); // count trailing zeros -si_int __ctzdi2(di_int a); // count trailing zeros -si_int __ctzti2(ti_int a); // count trailing zeros - -si_int __ffsdi2(di_int a); // find least significant 1 bit -si_int __ffsti2(ti_int a); // find least significant 1 bit - -si_int __paritysi2(si_int a); // bit parity -si_int __paritydi2(di_int a); // bit parity -si_int __parityti2(ti_int a); // bit parity - -si_int __popcountsi2(si_int a); // bit population -si_int __popcountdi2(di_int a); // bit population -si_int __popcountti2(ti_int a); // bit population - -uint32_t __bswapsi2(uint32_t a); // a byteswapped, arm only -uint64_t __bswapdi2(uint64_t a); // a byteswapped, arm only - -// Integral arithmetic - -di_int __negdi2 (di_int a); // -a -ti_int __negti2 (ti_int a); // -a -di_int __muldi3 (di_int a, di_int b); // a * b -ti_int __multi3 (ti_int a, ti_int b); // a * b -si_int __divsi3 (si_int a, si_int b); // a / b signed -di_int __divdi3 (di_int a, di_int b); // a / b signed -ti_int __divti3 (ti_int a, ti_int b); // a / b signed -su_int __udivsi3 (su_int n, su_int d); // a / b unsigned -du_int __udivdi3 (du_int a, du_int b); // a / b unsigned -tu_int __udivti3 (tu_int a, tu_int b); // a / b unsigned -si_int __modsi3 (si_int a, si_int b); // a % b signed -di_int __moddi3 (di_int a, di_int b); // a % b signed -ti_int __modti3 (ti_int a, ti_int b); // a % b signed -su_int __umodsi3 (su_int a, su_int b); // a % b unsigned -du_int __umoddi3 (du_int a, du_int b); // a % b unsigned -tu_int __umodti3 (tu_int a, tu_int b); // a % b unsigned -du_int __udivmoddi4(du_int a, du_int b, du_int* rem); // a / b, *rem = a % b unsigned -tu_int __udivmodti4(tu_int a, tu_int b, tu_int* rem); // a / b, *rem = a % b unsigned -su_int __udivmodsi4(su_int a, su_int b, su_int* rem); // a / b, *rem = a % b unsigned -si_int __divmodsi4(si_int a, si_int b, si_int* rem); // a / b, *rem = a % b signed - - - -// Integral arithmetic with trapping overflow - -si_int __absvsi2(si_int a); // abs(a) -di_int __absvdi2(di_int a); // abs(a) -ti_int __absvti2(ti_int a); // abs(a) - -si_int __negvsi2(si_int a); // -a -di_int __negvdi2(di_int a); // -a -ti_int __negvti2(ti_int a); // -a - -si_int __addvsi3(si_int a, si_int b); // a + b -di_int __addvdi3(di_int a, di_int b); // a + b -ti_int __addvti3(ti_int a, ti_int b); // a + b - -si_int __subvsi3(si_int a, si_int b); // a - b -di_int __subvdi3(di_int a, di_int b); // a - b -ti_int __subvti3(ti_int a, ti_int b); // a - b - -si_int __mulvsi3(si_int a, si_int b); // a * b -di_int __mulvdi3(di_int a, di_int b); // a * b -ti_int __mulvti3(ti_int a, ti_int b); // a * b - - -// Integral arithmetic which returns if overflow - -si_int __mulosi4(si_int a, si_int b, int* overflow); // a * b, overflow set to one if result not in signed range -di_int __mulodi4(di_int a, di_int b, int* overflow); // a * b, overflow set to one if result not in signed range -ti_int __muloti4(ti_int a, ti_int b, int* overflow); // a * b, overflow set to - one if result not in signed range - - -// Integral comparison: a < b -> 0 -// a == b -> 1 -// a > b -> 2 - -si_int __cmpdi2 (di_int a, di_int b); -si_int __cmpti2 (ti_int a, ti_int b); -si_int __ucmpdi2(du_int a, du_int b); -si_int __ucmpti2(tu_int a, tu_int b); - -// Integral / floating point conversion - -di_int __fixsfdi( float a); -di_int __fixdfdi( double a); -di_int __fixxfdi(long double a); - -ti_int __fixsfti( float a); -ti_int __fixdfti( double a); -ti_int __fixxfti(long double a); -uint64_t __fixtfdi(long double input); // ppc only, doesn't match documentation - -su_int __fixunssfsi( float a); -su_int __fixunsdfsi( double a); -su_int __fixunsxfsi(long double a); - -du_int __fixunssfdi( float a); -du_int __fixunsdfdi( double a); -du_int __fixunsxfdi(long double a); - -tu_int __fixunssfti( float a); -tu_int __fixunsdfti( double a); -tu_int __fixunsxfti(long double a); -uint64_t __fixunstfdi(long double input); // ppc only - -float __floatdisf(di_int a); -double __floatdidf(di_int a); -long double __floatdixf(di_int a); -long double __floatditf(int64_t a); // ppc only - -float __floattisf(ti_int a); -double __floattidf(ti_int a); -long double __floattixf(ti_int a); - -float __floatundisf(du_int a); -double __floatundidf(du_int a); -long double __floatundixf(du_int a); -long double __floatunditf(uint64_t a); // ppc only - -float __floatuntisf(tu_int a); -double __floatuntidf(tu_int a); -long double __floatuntixf(tu_int a); - -// Floating point raised to integer power - -float __powisf2( float a, si_int b); // a ^ b -double __powidf2( double a, si_int b); // a ^ b -long double __powixf2(long double a, si_int b); // a ^ b -long double __powitf2(long double a, si_int b); // ppc only, a ^ b - -// Complex arithmetic - -// (a + ib) * (c + id) - - float _Complex __mulsc3( float a, float b, float c, float d); - double _Complex __muldc3(double a, double b, double c, double d); -long double _Complex __mulxc3(long double a, long double b, - long double c, long double d); -long double _Complex __multc3(long double a, long double b, - long double c, long double d); // ppc only - -// (a + ib) / (c + id) - - float _Complex __divsc3( float a, float b, float c, float d); - double _Complex __divdc3(double a, double b, double c, double d); -long double _Complex __divxc3(long double a, long double b, - long double c, long double d); -long double _Complex __divtc3(long double a, long double b, - long double c, long double d); // ppc only - - -// Runtime support - -// __clear_cache() is used to tell process that new instructions have been -// written to an address range. Necessary on processors that do not have -// a unified instuction and data cache. -void __clear_cache(void* start, void* end); - -// __enable_execute_stack() is used with nested functions when a trampoline -// function is written onto the stack and that page range needs to be made -// executable. -void __enable_execute_stack(void* addr); - -// __gcc_personality_v0() is normally only called by the system unwinder. -// C code (as opposed to C++) normally does not need a personality function -// because there are no catch clauses or destructors to be run. But there -// is a C language extension __attribute__((cleanup(func))) which marks local -// variables as needing the cleanup function "func" to be run when the -// variable goes out of scope. That includes when an exception is thrown, -// so a personality handler is needed. -_Unwind_Reason_Code __gcc_personality_v0(int version, _Unwind_Action actions, - uint64_t exceptionClass, struct _Unwind_Exception* exceptionObject, - _Unwind_Context_t context); - -// for use with some implementations of assert() in -void __eprintf(const char* format, const char* assertion_expression, - const char* line, const char* file); - - - -// Power PC specific functions - -// There is no C interface to the saveFP/restFP functions. They are helper -// functions called by the prolog and epilog of functions that need to save -// a number of non-volatile float point registers. -saveFP -restFP - -// PowerPC has a standard template for trampoline functions. This function -// generates a custom trampoline function with the specific realFunc -// and localsPtr values. -void __trampoline_setup(uint32_t* trampOnStack, int trampSizeAllocated, - const void* realFunc, void* localsPtr); - -// adds two 128-bit double-double precision values ( x + y ) -long double __gcc_qadd(long double x, long double y); - -// subtracts two 128-bit double-double precision values ( x - y ) -long double __gcc_qsub(long double x, long double y); - -// multiples two 128-bit double-double precision values ( x * y ) -long double __gcc_qmul(long double x, long double y); - -// divides two 128-bit double-double precision values ( x / y ) -long double __gcc_qdiv(long double a, long double b); - - -// ARM specific functions - -// There is no C interface to the switch* functions. These helper functions -// are only needed by Thumb1 code for efficient switch table generation. -switch16 -switch32 -switch8 -switchu8 - -// There is no C interface to the *_vfp_d8_d15_regs functions. There are -// called in the prolog and epilog of Thumb1 functions. When the C++ ABI use -// SJLJ for exceptions, each function with a catch clause or destuctors needs -// to save and restore all registers in it prolog and epliog. But there is -// no way to access vector and high float registers from thumb1 code, so the -// compiler must add call outs to these helper functions in the prolog and -// epilog. -restore_vfp_d8_d15_regs -save_vfp_d8_d15_regs - - -// Note: long ago ARM processors did not have floating point hardware support. -// Floating point was done in software and floating point parameters were -// passed in integer registers. When hardware support was added for floating -// point, new *vfp functions were added to do the same operations but with -// floating point parameters in floating point registers. - -// Undocumented functions - -float __addsf3vfp(float a, float b); // Appears to return a + b -double __adddf3vfp(double a, double b); // Appears to return a + b -float __divsf3vfp(float a, float b); // Appears to return a / b -double __divdf3vfp(double a, double b); // Appears to return a / b -int __eqsf2vfp(float a, float b); // Appears to return one - // iff a == b and neither is NaN. -int __eqdf2vfp(double a, double b); // Appears to return one - // iff a == b and neither is NaN. -double __extendsfdf2vfp(float a); // Appears to convert from - // float to double. -int __fixdfsivfp(double a); // Appears to convert from - // double to int. -int __fixsfsivfp(float a); // Appears to convert from - // float to int. -unsigned int __fixunssfsivfp(float a); // Appears to convert from - // float to unsigned int. -unsigned int __fixunsdfsivfp(double a); // Appears to convert from - // double to unsigned int. -double __floatsidfvfp(int a); // Appears to convert from - // int to double. -float __floatsisfvfp(int a); // Appears to convert from - // int to float. -double __floatunssidfvfp(unsigned int a); // Appears to convert from - // unisgned int to double. -float __floatunssisfvfp(unsigned int a); // Appears to convert from - // unisgned int to float. -int __gedf2vfp(double a, double b); // Appears to return __gedf2 - // (a >= b) -int __gesf2vfp(float a, float b); // Appears to return __gesf2 - // (a >= b) -int __gtdf2vfp(double a, double b); // Appears to return __gtdf2 - // (a > b) -int __gtsf2vfp(float a, float b); // Appears to return __gtsf2 - // (a > b) -int __ledf2vfp(double a, double b); // Appears to return __ledf2 - // (a <= b) -int __lesf2vfp(float a, float b); // Appears to return __lesf2 - // (a <= b) -int __ltdf2vfp(double a, double b); // Appears to return __ltdf2 - // (a < b) -int __ltsf2vfp(float a, float b); // Appears to return __ltsf2 - // (a < b) -double __muldf3vfp(double a, double b); // Appears to return a * b -float __mulsf3vfp(float a, float b); // Appears to return a * b -int __nedf2vfp(double a, double b); // Appears to return __nedf2 - // (a != b) -double __negdf2vfp(double a); // Appears to return -a -float __negsf2vfp(float a); // Appears to return -a -float __negsf2vfp(float a); // Appears to return -a -double __subdf3vfp(double a, double b); // Appears to return a - b -float __subsf3vfp(float a, float b); // Appears to return a - b -float __truncdfsf2vfp(double a); // Appears to convert from - // double to float. -int __unorddf2vfp(double a, double b); // Appears to return __unorddf2 -int __unordsf2vfp(float a, float b); // Appears to return __unordsf2 - - -Preconditions are listed for each function at the definition when there are any. -Any preconditions reflect the specification at -http://gcc.gnu.org/onlinedocs/gccint/Libgcc.html#Libgcc. - -Assumptions are listed in "int_lib.h", and in individual files. Where possible -assumptions are checked at compile time. diff --git a/SDKs/darwin/README.txt b/SDKs/darwin/README.txt deleted file mode 100644 index ea30af358b2..00000000000 --- a/SDKs/darwin/README.txt +++ /dev/null @@ -1,3 +0,0 @@ -The Darwin platforms are all similar enough we roll them into one SDK, and use -preprocessor tricks to get the right definitions for the few things which -diverge between OS X and iOS. diff --git a/SDKs/darwin/usr/include/errno.h b/SDKs/darwin/usr/include/errno.h deleted file mode 100644 index f06e5371339..00000000000 --- a/SDKs/darwin/usr/include/errno.h +++ /dev/null @@ -1,17 +0,0 @@ -/* ===-- errno.h - stub SDK header for compiler-rt --------------------------=== - * - * The LLVM Compiler Infrastructure - * - * This file is dual licensed under the MIT and the University of Illinois Open - * Source Licenses. See LICENSE.TXT for details. - * - * ===-----------------------------------------------------------------------=== - * - * This is a stub SDK header file. This file is not part of the interface of - * this library nor an official version of the appropriate SDK header. It is - * intended only to stub the features of this header required by compiler-rt. - * - * ===-----------------------------------------------------------------------=== - */ - -#include diff --git a/SDKs/darwin/usr/include/fcntl.h b/SDKs/darwin/usr/include/fcntl.h deleted file mode 100644 index a5f91e3a5bc..00000000000 --- a/SDKs/darwin/usr/include/fcntl.h +++ /dev/null @@ -1,17 +0,0 @@ -/* ===-- fcntl.h - stub SDK header for compiler-rt --------------------------=== - * - * The LLVM Compiler Infrastructure - * - * This file is dual licensed under the MIT and the University of Illinois Open - * Source Licenses. See LICENSE.TXT for details. - * - * ===-----------------------------------------------------------------------=== - * - * This is a stub SDK header file. This file is not part of the interface of - * this library nor an official version of the appropriate SDK header. It is - * intended only to stub the features of this header required by compiler-rt. - * - * ===-----------------------------------------------------------------------=== - */ - -#include diff --git a/SDKs/darwin/usr/include/limits.h b/SDKs/darwin/usr/include/limits.h deleted file mode 100644 index 5495a784f12..00000000000 --- a/SDKs/darwin/usr/include/limits.h +++ /dev/null @@ -1,23 +0,0 @@ -/* ===-- limits.h - stub SDK header for compiler-rt -------------------------=== - * - * The LLVM Compiler Infrastructure - * - * This file is dual licensed under the MIT and the University of Illinois Open - * Source Licenses. See LICENSE.TXT for details. - * - * ===-----------------------------------------------------------------------=== - * - * This is a stub SDK header file. This file is not part of the interface of - * this library nor an official version of the appropriate SDK header. It is - * intended only to stub the features of this header required by compiler-rt. - * - * ===-----------------------------------------------------------------------=== - */ - -#ifndef __LIMITS_H__ -#define __LIMITS_H__ - -/* This is only here as a landing pad for the include_next from the compiler's - built-in limits.h. */ - -#endif /* __LIMITS_H__ */ diff --git a/SDKs/darwin/usr/include/stdio.h b/SDKs/darwin/usr/include/stdio.h deleted file mode 100644 index 006652fb9b8..00000000000 --- a/SDKs/darwin/usr/include/stdio.h +++ /dev/null @@ -1,89 +0,0 @@ -/* ===-- stdio.h - stub SDK header for compiler-rt --------------------------=== - * - * The LLVM Compiler Infrastructure - * - * This file is dual licensed under the MIT and the University of Illinois Open - * Source Licenses. See LICENSE.TXT for details. - * - * ===-----------------------------------------------------------------------=== - * - * This is a stub SDK header file. This file is not part of the interface of - * this library nor an official version of the appropriate SDK header. It is - * intended only to stub the features of this header required by compiler-rt. - * - * ===-----------------------------------------------------------------------=== - */ - -#ifndef __STDIO_H__ -#define __STDIO_H__ - -#if defined(__cplusplus) -extern "C" { -#endif - -typedef struct __sFILE FILE; -typedef __SIZE_TYPE__ size_t; - -/* Determine the appropriate fdopen, fopen(), and fwrite() functions. */ -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) -# if defined(__i386) -# define __FDOPEN_NAME "_fdopen$UNIX2003" -# define __FOPEN_NAME "_fopen$UNIX2003" -# define __FWRITE_NAME "_fwrite$UNIX2003" -# elif defined(__x86_64__) -# define __FDOPEN_NAME "_fdopen" -# define __FOPEN_NAME "_fopen" -# define __FWRITE_NAME "_fwrite" -# elif defined(__arm) -# define __FDOPEN_NAME "_fdopen" -# define __FOPEN_NAME "_fopen" -# define __FWRITE_NAME "_fwrite" -# else -# error "unrecognized architecture for targetting OS X" -# endif -#elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) -# if defined(__i386) || defined (__x86_64) -# define __FDOPEN_NAME "_fdopen" -# define __FOPEN_NAME "_fopen" -# define __FWRITE_NAME "_fwrite" -# elif defined(__arm) -# define __FDOPEN_NAME "_fdopen" -# define __FOPEN_NAME "_fopen" -# define __FWRITE_NAME "_fwrite" -# else -# error "unrecognized architecture for targetting iOS" -# endif -#else -# error "unrecognized architecture for targetting Darwin" -#endif - -# define stderr __stderrp -extern FILE *__stderrp; - -#ifndef SEEK_SET -#define SEEK_SET 0 /* set file offset to offset */ -#endif -#ifndef SEEK_CUR -#define SEEK_CUR 1 /* set file offset to current plus offset */ -#endif -#ifndef SEEK_END -#define SEEK_END 2 /* set file offset to EOF plus offset */ -#endif - -int fclose(FILE *); -int fflush(FILE *); -FILE *fopen(const char * __restrict, const char * __restrict) __asm(__FOPEN_NAME); -FILE *fdopen(int, const char *) __asm(__FDOPEN_NAME); -int fprintf(FILE * __restrict, const char * __restrict, ...); -size_t fwrite(const void * __restrict, size_t, size_t, FILE * __restrict) - __asm(__FWRITE_NAME); -size_t fread(void * __restrict, size_t, size_t, FILE * __restrict); -long ftell(FILE *); -int fseek(FILE *, long, int); -int snprintf(char * __restrict, size_t, const char * __restrict, ...); - -#if defined(__cplusplus) -} -#endif - -#endif /* __STDIO_H__ */ diff --git a/SDKs/darwin/usr/include/stdlib.h b/SDKs/darwin/usr/include/stdlib.h deleted file mode 100644 index b6d3171cff4..00000000000 --- a/SDKs/darwin/usr/include/stdlib.h +++ /dev/null @@ -1,32 +0,0 @@ -/* ===-- stdlib.h - stub SDK header for compiler-rt -------------------------=== - * - * The LLVM Compiler Infrastructure - * - * This file is dual licensed under the MIT and the University of Illinois Open - * Source Licenses. See LICENSE.TXT for details. - * - * ===-----------------------------------------------------------------------=== - * - * This is a stub SDK header file. This file is not part of the interface of - * this library nor an official version of the appropriate SDK header. It is - * intended only to stub the features of this header required by compiler-rt. - * - * ===-----------------------------------------------------------------------=== - */ - -#ifndef __STDLIB_H__ -#define __STDLIB_H__ - -#define NULL ((void *)0) - -typedef __SIZE_TYPE__ size_t; - -void abort(void) __attribute__((__noreturn__)); -int atexit(void (*)(void)); -int atoi(const char *); -void free(void *); -char *getenv(const char *); -void *malloc(size_t); -void *realloc(void *, size_t); - -#endif /* __STDLIB_H__ */ diff --git a/SDKs/darwin/usr/include/string.h b/SDKs/darwin/usr/include/string.h deleted file mode 100644 index c6ab5d8e587..00000000000 --- a/SDKs/darwin/usr/include/string.h +++ /dev/null @@ -1,52 +0,0 @@ -/* ===-- string.h - stub SDK header for compiler-rt -------------------------=== - * - * The LLVM Compiler Infrastructure - * - * This file is dual licensed under the MIT and the University of Illinois Open - * Source Licenses. See LICENSE.TXT for details. - * - * ===-----------------------------------------------------------------------=== - * - * This is a stub SDK header file. This file is not part of the interface of - * this library nor an official version of the appropriate SDK header. It is - * intended only to stub the features of this header required by compiler-rt. - * - * ===-----------------------------------------------------------------------=== - */ - -#ifndef __STRING_H__ -#define __STRING_H__ - -typedef __SIZE_TYPE__ size_t; - -int memcmp(const void *, const void *, size_t); -void *memcpy(void *, const void *, size_t); -void *memset(void *, int, size_t); -char *strcat(char *, const char *); -char *strcpy(char *, const char *); -char *strdup(const char *); -size_t strlen(const char *); -char *strncpy(char *, const char *, size_t); - -/* Determine the appropriate strerror() function. */ -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) -# if defined(__i386) -# define __STRERROR_NAME "_strerror$UNIX2003" -# elif defined(__x86_64__) || defined(__arm) -# define __STRERROR_NAME "_strerror" -# else -# error "unrecognized architecture for targetting OS X" -# endif -#elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) -# if defined(__i386) || defined (__x86_64) || defined(__arm) -# define __STRERROR_NAME "_strerror" -# else -# error "unrecognized architecture for targetting iOS" -# endif -#else -# error "unrecognized architecture for targetting Darwin" -#endif - -char *strerror(int) __asm(__STRERROR_NAME); - -#endif /* __STRING_H__ */ diff --git a/SDKs/darwin/usr/include/sys/errno.h b/SDKs/darwin/usr/include/sys/errno.h deleted file mode 100644 index 4befe385535..00000000000 --- a/SDKs/darwin/usr/include/sys/errno.h +++ /dev/null @@ -1,31 +0,0 @@ -/* ===-- errno.h - stub SDK header for compiler-rt --------------------------=== - * - * The LLVM Compiler Infrastructure - * - * This file is dual licensed under the MIT and the University of Illinois Open - * Source Licenses. See LICENSE.TXT for details. - * - * ===-----------------------------------------------------------------------=== - * - * This is a stub SDK header file. This file is not part of the interface of - * this library nor an official version of the appropriate SDK header. It is - * intended only to stub the features of this header required by compiler-rt. - * - * ===-----------------------------------------------------------------------=== - */ - -#ifndef _SYS_ERRNO_H_ -#define _SYS_ERRNO_H_ - -#if defined(__cplusplus) -extern "C" { -#endif - -extern int *__error(void); -#define errno (*__error()) - -#if defined(__cplusplus) -} -#endif - -#endif diff --git a/SDKs/darwin/usr/include/sys/fcntl.h b/SDKs/darwin/usr/include/sys/fcntl.h deleted file mode 100644 index b71706bf453..00000000000 --- a/SDKs/darwin/usr/include/sys/fcntl.h +++ /dev/null @@ -1,52 +0,0 @@ -/* ===-- fcntl.h - stub SDK header for compiler-rt --------------------------=== - * - * The LLVM Compiler Infrastructure - * - * This file is dual licensed under the MIT and the University of Illinois Open - * Source Licenses. See LICENSE.TXT for details. - * - * ===-----------------------------------------------------------------------=== - * - * This is a stub SDK header file. This file is not part of the interface of - * this library nor an official version of the appropriate SDK header. It is - * intended only to stub the features of this header required by compiler-rt. - * - * ===-----------------------------------------------------------------------=== - */ - -#ifndef _SYS_FCNTL_H_ -#define _SYS_FCNTL_H_ - -/* Determine the appropriate open function. */ -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) -# if defined(__i386) -# define __OPEN_NAME "_open$UNIX2003" -# elif defined(__x86_64__) -# define __OPEN_NAME "_open" -# elif defined(__arm) -# define __OPEN_NAME "_open" -# else -# error "unrecognized architecture for targetting OS X" -# endif -#elif defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) -# if defined(__i386) || defined (__x86_64) -# define __OPEN_NAME "_open" -# elif defined(__arm) -# define __OPEN_NAME "_open" -# else -# error "unrecognized architecture for targetting iOS" -# endif -#else -# error "unrecognized architecture for targetting Darwin" -#endif - -#define O_RDONLY 0x0000 /* open for reading only */ -#define O_WRONLY 0x0001 /* open for writing only */ -#define O_RDWR 0x0002 /* open for reading and writing */ -#define O_ACCMODE 0x0003 /* mask for above modes */ - -#define O_CREAT 0x0200 /* create if nonexistant */ - -int open(const char *, int, ...) __asm(__OPEN_NAME); - -#endif /* !_SYS_FCNTL_H_ */ diff --git a/SDKs/darwin/usr/include/sys/mman.h b/SDKs/darwin/usr/include/sys/mman.h deleted file mode 100644 index 84561f1b6ab..00000000000 --- a/SDKs/darwin/usr/include/sys/mman.h +++ /dev/null @@ -1,42 +0,0 @@ -/* ===-- mman.h - stub SDK header for compiler-rt ---------------------------=== - * - * The LLVM Compiler Infrastructure - * - * This file is dual licensed under the MIT and the University of Illinois Open - * Source Licenses. See LICENSE.TXT for details. - * - * ===-----------------------------------------------------------------------=== - * - * This is a stub SDK header file. This file is not part of the interface of - * this library nor an official version of the appropriate SDK header. It is - * intended only to stub the features of this header required by compiler-rt. - * - * ===-----------------------------------------------------------------------=== - */ - -#ifndef __SYS_MMAN_H__ -#define __SYS_MMAN_H__ - -typedef __SIZE_TYPE__ size_t; - -#define PROT_NONE 0x00 -#define PROT_READ 0x01 -#define PROT_WRITE 0x02 -#define PROT_EXEC 0x04 - -#define MAP_SHARED 0x0001 -#define MAP_PRIVATE 0x0002 - -#define MAP_FILE 0x0000 -#define MAP_ANON 0x1000 - -#define MS_ASYNC 0x0001 -#define MS_INVALIDATE 0x0002 -#define MS_SYNC 0x0010 - -void *mmap(void *addr, size_t len, int prot, int flags, int fd, - long long offset); -int munmap(void *addr, size_t len); -int msync(void *addr, size_t len, int flags); - -#endif /* __SYS_MMAN_H__ */ diff --git a/SDKs/darwin/usr/include/sys/stat.h b/SDKs/darwin/usr/include/sys/stat.h deleted file mode 100644 index 6225f908168..00000000000 --- a/SDKs/darwin/usr/include/sys/stat.h +++ /dev/null @@ -1,25 +0,0 @@ -/* ===-- stat.h - stub SDK header for compiler-rt ---------------------------=== - * - * The LLVM Compiler Infrastructure - * - * This file is dual licensed under the MIT and the University of Illinois Open - * Source Licenses. See LICENSE.TXT for details. - * - * ===-----------------------------------------------------------------------=== - * - * This is a stub SDK header file. This file is not part of the interface of - * this library nor an official version of the appropriate SDK header. It is - * intended only to stub the features of this header required by compiler-rt. - * - * ===-----------------------------------------------------------------------=== - */ - -#ifndef __SYS_STAT_H__ -#define __SYS_STAT_H__ - -typedef unsigned short uint16_t; -typedef uint16_t mode_t; - -int mkdir(const char *, mode_t); - -#endif /* __SYS_STAT_H__ */ diff --git a/SDKs/darwin/usr/include/sys/types.h b/SDKs/darwin/usr/include/sys/types.h deleted file mode 100644 index b425767b831..00000000000 --- a/SDKs/darwin/usr/include/sys/types.h +++ /dev/null @@ -1,20 +0,0 @@ -/* ===-- types.h - stub SDK header for compiler-rt --------------------------=== - * - * The LLVM Compiler Infrastructure - * - * This file is dual licensed under the MIT and the University of Illinois Open - * Source Licenses. See LICENSE.TXT for details. - * - * ===-----------------------------------------------------------------------=== - * - * This is a stub SDK header file. This file is not part of the interface of - * this library nor an official version of the appropriate SDK header. It is - * intended only to stub the features of this header required by compiler-rt. - * - * ===-----------------------------------------------------------------------=== - */ - -#ifndef __SYS_TYPES_H__ -#define __SYS_TYPES_H__ - -#endif /* __SYS_TYPES_H__ */ diff --git a/SDKs/linux/usr/include/stdio.h b/SDKs/linux/usr/include/stdio.h index fba593640c3..e2161daa468 100644 --- a/SDKs/linux/usr/include/stdio.h +++ b/SDKs/linux/usr/include/stdio.h @@ -35,6 +35,7 @@ extern int fflush(FILE *); extern FILE *fopen(const char * restrict, const char * restrict); extern FILE *fdopen(int, const char * restrict); extern int fprintf(FILE * restrict, const char * restrict, ...); +extern int fputc(int, FILE *); extern size_t fwrite(const void * restrict, size_t, size_t, FILE * restrict); extern size_t fread(void * restrict, size_t, size_t, FILE * restrict); extern long ftell(FILE *); diff --git a/cmake/Modules/AddCompilerRT.cmake b/cmake/Modules/AddCompilerRT.cmake index fd117ac522c..3edd854fdee 100644 --- a/cmake/Modules/AddCompilerRT.cmake +++ b/cmake/Modules/AddCompilerRT.cmake @@ -1,4 +1,5 @@ include(AddLLVM) +include(ExternalProject) include(LLVMParseArguments) include(CompilerRTUtils) @@ -13,7 +14,7 @@ macro(add_compiler_rt_object_library name arch) parse_arguments(LIB "SOURCES;CFLAGS;DEFS" "" ${ARGN}) add_library(${name}.${arch} OBJECT ${LIB_SOURCES}) set_target_compile_flags(${name}.${arch} - ${TARGET_${arch}_CFLAGS} ${LIB_CFLAGS}) + ${CMAKE_CXX_FLAGS} ${TARGET_${arch}_CFLAGS} ${LIB_CFLAGS}) set_property(TARGET ${name}.${arch} APPEND PROPERTY COMPILE_DEFINITIONS ${LIB_DEFS}) else() @@ -37,34 +38,47 @@ macro(add_compiler_rt_darwin_object_library name os) COMPILE_DEFINITIONS ${LIB_DEFS}) endmacro() -# Adds static runtime for a given architecture and puts it in the proper -# directory in the build and install trees. -# add_compiler_rt_static_runtime( -# SOURCES -# CFLAGS -# DEFS ) -macro(add_compiler_rt_static_runtime name arch) +# Adds static or shared runtime for a given architecture and puts it in the +# proper directory in the build and install trees. +# add_compiler_rt_runtime( {STATIC,SHARED} +# SOURCES +# CFLAGS +# DEFS +# OUTPUT_NAME ) +macro(add_compiler_rt_runtime name arch type) if(CAN_TARGET_${arch}) - parse_arguments(LIB "SOURCES;CFLAGS;DEFS" "" ${ARGN}) - add_library(${name} STATIC ${LIB_SOURCES}) + parse_arguments(LIB "SOURCES;CFLAGS;DEFS;OUTPUT_NAME" "" ${ARGN}) + add_library(${name} ${type} ${LIB_SOURCES}) # Setup compile flags and definitions. set_target_compile_flags(${name} ${TARGET_${arch}_CFLAGS} ${LIB_CFLAGS}) + set_target_link_flags(${name} + ${TARGET_${arch}_CFLAGS} ${LIB_CFLAGS}) set_property(TARGET ${name} APPEND PROPERTY COMPILE_DEFINITIONS ${LIB_DEFS}) # Setup correct output directory in the build tree. set_target_properties(${name} PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR}) + ARCHIVE_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR} + LIBRARY_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR} + RUNTIME_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR}) + if ("${LIB_OUTPUT_NAME}" STREQUAL "") + set_target_properties(${name} PROPERTIES + OUTPUT_NAME ${name}${COMPILER_RT_OS_SUFFIX}) + else() + set_target_properties(${name} PROPERTIES + OUTPUT_NAME ${LIB_OUTPUT_NAME}) + endif() # Add installation command. install(TARGETS ${name} - ARCHIVE DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR}) - add_dependencies(compiler-rt ${name}) + ARCHIVE DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR} + LIBRARY DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR} + RUNTIME DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR}) else() message(FATAL_ERROR "Archtecture ${arch} can't be targeted") endif() endmacro() -# Same as add_compiler_rt_static_runtime, but creates a universal library +# Same as add_compiler_rt_runtime(... STATIC), but creates a universal library # for several architectures. # add_compiler_rt_osx_static_runtime( ARCH # SOURCES @@ -81,7 +95,6 @@ macro(add_compiler_rt_osx_static_runtime name) ARCHIVE_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR}) install(TARGETS ${name} ARCHIVE DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR}) - add_dependencies(compiler-rt ${name}) endmacro() # Adds dynamic runtime library on osx/iossim, which supports multiple @@ -104,20 +117,43 @@ macro(add_compiler_rt_darwin_dynamic_runtime name os) LIBRARY_OUTPUT_DIRECTORY ${COMPILER_RT_LIBRARY_OUTPUT_DIR}) install(TARGETS ${name} LIBRARY DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR}) - add_dependencies(compiler-rt ${name}) endmacro() +set(COMPILER_RT_TEST_CFLAGS) + # Unittests support. set(COMPILER_RT_GTEST_PATH ${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest) set(COMPILER_RT_GTEST_SOURCE ${COMPILER_RT_GTEST_PATH}/src/gtest-all.cc) -set(COMPILER_RT_GTEST_INCLUDE_CFLAGS +set(COMPILER_RT_GTEST_CFLAGS -DGTEST_NO_LLVM_RAW_OSTREAM=1 + -DGTEST_HAS_RTTI=0 -I${COMPILER_RT_GTEST_PATH}/include -I${COMPILER_RT_GTEST_PATH} ) -# Use Clang to link objects into a single executable with just-built -# Clang, using specific link flags. Make executable a part of provided +if(MSVC) + # clang doesn't support exceptions on Windows yet. + list(APPEND COMPILER_RT_TEST_CFLAGS + -D_HAS_EXCEPTIONS=0) + + # We should teach clang to understand "#pragma intrinsic", see PR19898. + list(APPEND COMPILER_RT_TEST_CFLAGS -Wno-undefined-inline) + + # Clang doesn't support SEH on Windows yet. + list(APPEND COMPILER_RT_GTEST_CFLAGS -DGTEST_HAS_SEH=0) + + # gtest use a lot of stuff marked as deprecated on Windows. + list(APPEND COMPILER_RT_GTEST_CFLAGS -Wno-deprecated-declarations) + + # Visual Studio 2012 only supports up to 8 template parameters in + # std::tr1::tuple by default, but gtest requires 10 + if(MSVC_VERSION EQUAL 1700) + list(APPEND COMPILER_RT_GTEST_CFLAGS -D_VARIADIC_MAX=10) + endif() +endif() + +# Link objects into a single executable with COMPILER_RT_TEST_COMPILER, +# using specified link flags. Make executable a part of provided # test_suite. # add_compiler_rt_test( # OBJECTS @@ -126,20 +162,98 @@ set(COMPILER_RT_GTEST_INCLUDE_CFLAGS macro(add_compiler_rt_test test_suite test_name) parse_arguments(TEST "OBJECTS;DEPS;LINK_FLAGS" "" ${ARGN}) set(output_bin "${CMAKE_CURRENT_BINARY_DIR}/${test_name}") + # Use host compiler in a standalone build, and just-built Clang otherwise. + if(NOT COMPILER_RT_STANDALONE_BUILD) + list(APPEND TEST_DEPS clang) + endif() + # If we're not on MSVC, include the linker flags from CMAKE but override them + # with the provided link flags. This ensures that flags which are required to + # link programs at all are included, but the changes needed for the test + # trump. With MSVC we can't do that because CMake is set up to run link.exe + # when linking, not the compiler. Here, we hack it to use the compiler + # because we want to use -fsanitize flags. + if(NOT MSVC) + set(TEST_LINK_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${TEST_LINK_FLAGS}") + separate_arguments(TEST_LINK_FLAGS) + endif() add_custom_target(${test_name} - COMMAND clang ${TEST_OBJECTS} -o "${output_bin}" + COMMAND ${COMPILER_RT_TEST_COMPILER} ${TEST_OBJECTS} + -o "${output_bin}" ${TEST_LINK_FLAGS} - DEPENDS clang ${TEST_DEPS}) + DEPENDS ${TEST_DEPS}) # Make the test suite depend on the binary. add_dependencies(${test_suite} ${test_name}) endmacro() macro(add_compiler_rt_resource_file target_name file_name) set(src_file "${CMAKE_CURRENT_SOURCE_DIR}/${file_name}") - set(dst_file "${CLANG_RESOURCE_DIR}/${file_name}") - add_custom_target(${target_name} + set(dst_file "${COMPILER_RT_OUTPUT_DIR}/${file_name}") + add_custom_command(OUTPUT ${dst_file} + DEPENDS ${src_file} COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src_file} ${dst_file} - DEPENDS ${file_name}) + COMMENT "Copying ${file_name}...") + add_custom_target(${target_name} DEPENDS ${dst_file}) # Install in Clang resource directory. - install(FILES ${file_name} DESTINATION ${LIBCLANG_INSTALL_PATH}) + install(FILES ${file_name} DESTINATION ${COMPILER_RT_INSTALL_PATH}) +endmacro() + +macro(add_compiler_rt_script name) + set(dst ${COMPILER_RT_EXEC_OUTPUT_DIR}/${name}) + set(src ${CMAKE_CURRENT_SOURCE_DIR}/${name}) + add_custom_command(OUTPUT ${dst} + DEPENDS ${src} + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst} + COMMENT "Copying ${name}...") + add_custom_target(${name} DEPENDS ${dst}) + install(FILES ${dst} + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE + DESTINATION ${COMPILER_RT_INSTALL_PATH}/bin) +endmacro(add_compiler_rt_script src name) + +# Builds custom version of libc++ and installs it in . +# Can be used to build sanitized versions of libc++ for running unit tests. +# add_custom_libcxx( +# DEPS +# CFLAGS ) +macro(add_custom_libcxx name prefix) + if(NOT COMPILER_RT_HAS_LIBCXX_SOURCES) + message(FATAL_ERROR "libcxx not found!") + endif() + + parse_arguments(LIBCXX "DEPS;CFLAGS" "" ${ARGN}) + foreach(flag ${LIBCXX_CFLAGS}) + set(flagstr "${flagstr} ${flag}") + endforeach() + set(LIBCXX_CFLAGS ${flagstr}) + + if(NOT COMPILER_RT_STANDALONE_BUILD) + list(APPEND LIBCXX_DEPS clang) + endif() + + ExternalProject_Add(${name} + PREFIX ${prefix} + SOURCE_DIR ${COMPILER_RT_LIBCXX_PATH} + CMAKE_ARGS -DCMAKE_C_COMPILER=${COMPILER_RT_TEST_COMPILER} + -DCMAKE_CXX_COMPILER=${COMPILER_RT_TEST_COMPILER} + -DCMAKE_C_FLAGS=${LIBCXX_CFLAGS} + -DCMAKE_CXX_FLAGS=${LIBCXX_CFLAGS} + -DCMAKE_BUILD_TYPE=Release + -DCMAKE_INSTALL_PREFIX:PATH= + LOG_BUILD 1 + LOG_CONFIGURE 1 + LOG_INSTALL 1 + ) + + ExternalProject_Add_Step(${name} force-reconfigure + DEPENDERS configure + ALWAYS 1 + ) + + ExternalProject_Add_Step(${name} clobber + COMMAND ${CMAKE_COMMAND} -E remove_directory + COMMAND ${CMAKE_COMMAND} -E make_directory + COMMENT "Clobberring ${name} build directory..." + DEPENDERS configure + DEPENDS ${LIBCXX_DEPS} + ) endmacro() diff --git a/cmake/Modules/CompilerRTCompile.cmake b/cmake/Modules/CompilerRTCompile.cmake index 2794cabe59c..af3df8ff4f4 100644 --- a/cmake/Modules/CompilerRTCompile.cmake +++ b/cmake/Modules/CompilerRTCompile.cmake @@ -1,6 +1,6 @@ include(LLVMParseArguments) -# Compile a source into an object file with just-built Clang using +# Compile a source into an object file with COMPILER_RT_TEST_COMPILER using # a provided compile flags and dependenices. # clang_compile( # CFLAGS @@ -8,9 +8,74 @@ include(LLVMParseArguments) macro(clang_compile object_file source) parse_arguments(SOURCE "CFLAGS;DEPS" "" ${ARGN}) get_filename_component(source_rpath ${source} REALPATH) + if(NOT COMPILER_RT_STANDALONE_BUILD) + list(APPEND SOURCE_DEPS clang) + endif() + if (TARGET CompilerRTUnitTestCheckCxx) + list(APPEND SOURCE_DEPS CompilerRTUnitTestCheckCxx) + endif() + string(REGEX MATCH "[.](cc|cpp)$" is_cxx ${source_rpath}) + if(is_cxx) + string(REPLACE " " ";" global_flags "${CMAKE_CXX_FLAGS}") + else() + string(REPLACE " " ";" global_flags "${CMAKE_C_FLAGS}") + endif() + # On Windows, CMAKE_*_FLAGS are built for MSVC but we use the GCC clang.exe + # which doesn't support flags starting with "/smth". Replace those with + # "-smth" equivalents. + if(MSVC) + string(REGEX REPLACE "^/" "-" global_flags "${global_flags}") + string(REPLACE ";/" ";-" global_flags "${global_flags}") + endif() + # Ignore unknown warnings. CMAKE_CXX_FLAGS may contain GCC-specific options + # which are not supported by Clang. + list(APPEND global_flags -Wno-unknown-warning-option) + set(compile_flags ${global_flags} ${SOURCE_CFLAGS}) add_custom_command( OUTPUT ${object_file} - COMMAND clang ${SOURCE_CFLAGS} -c -o "${object_file}" ${source_rpath} + COMMAND ${COMPILER_RT_TEST_COMPILER} ${compile_flags} -c + -o "${object_file}" + ${source_rpath} MAIN_DEPENDENCY ${source} - DEPENDS clang ${SOURCE_DEPS}) + DEPENDS ${SOURCE_DEPS}) +endmacro() + +# On Darwin, there are no system-wide C++ headers and the just-built clang is +# therefore not able to compile C++ files unless they are copied/symlinked into +# ${LLVM_BINARY_DIR}/include/c++ +# The just-built clang is used to build compiler-rt unit tests. Let's detect +# this before we try to build the tests and print out a suggestion how to fix +# it. +# On other platforms, this is currently not an issue. +macro(clang_compiler_add_cxx_check) + if (APPLE) + set(CMD + "echo '#include ' | ${COMPILER_RT_TEST_COMPILER} -E -x c++ - > /dev/null" + "if [ $? != 0 ] " + " then echo" + " echo 'Your just-built clang cannot find C++ headers, which are needed to build and run compiler-rt tests.'" + " echo 'You should copy or symlink your system C++ headers into ${LLVM_BINARY_DIR}/include/c++'" + " if [ -d $(dirname $(dirname $(xcrun -f clang)))/include/c++ ]" + " then echo 'e.g. with:'" + " echo ' cp -r' $(dirname $(dirname $(xcrun -f clang)))/include/c++ '${LLVM_BINARY_DIR}/include/'" + " elif [ -d $(dirname $(dirname $(xcrun -f clang)))/lib/c++ ]" + " then echo 'e.g. with:'" + " echo ' cp -r' $(dirname $(dirname $(xcrun -f clang)))/lib/c++ '${LLVM_BINARY_DIR}/include/'" + " fi" + " echo 'This can also be fixed by checking out the libcxx project from llvm.org and installing the headers'" + " echo 'into your build directory:'" + " echo ' cd ${LLVM_SOURCE_DIR}/projects && svn co http://llvm.org/svn/llvm-project/libcxx/trunk libcxx'" + " echo ' cd ${LLVM_BINARY_DIR} && make -C ${LLVM_SOURCE_DIR}/projects/libcxx installheaders HEADER_DIR=${LLVM_BINARY_DIR}/include'" + " echo" + " false" + "fi" + ) + add_custom_target(CompilerRTUnitTestCheckCxx + COMMAND bash -c "${CMD}" + COMMENT "Checking that just-built clang can find C++ headers..." + VERBATIM) + if (TARGET clang) + ADD_DEPENDENCIES(CompilerRTUnitTestCheckCxx clang) + endif() + endif() endmacro() diff --git a/cmake/Modules/CompilerRTLink.cmake b/cmake/Modules/CompilerRTLink.cmake index 85030a725e1..0f0e53a3b2f 100644 --- a/cmake/Modules/CompilerRTLink.cmake +++ b/cmake/Modules/CompilerRTLink.cmake @@ -1,14 +1,18 @@ include(LLVMParseArguments) -# Link a shared library with just-built Clang. +# Link a shared library with COMPILER_RT_TEST_COMPILER. # clang_link_shared( # OBJECTS # LINKFLAGS # DEPS ) macro(clang_link_shared so_file) parse_arguments(SOURCE "OBJECTS;LINKFLAGS;DEPS" "" ${ARGN}) + if(NOT COMPILER_RT_STANDALONE_BUILD) + list(APPEND SOURCE_DEPS clang) + endif() add_custom_command( OUTPUT ${so_file} - COMMAND clang -o "${so_file}" -shared ${SOURCE_LINKFLAGS} ${SOURCE_OBJECTS} - DEPENDS clang ${SOURCE_DEPS}) + COMMAND ${COMPILER_RT_TEST_COMPILER} -o "${so_file}" -shared + ${SOURCE_LINKFLAGS} ${SOURCE_OBJECTS} + DEPENDS ${SOURCE_DEPS}) endmacro() diff --git a/cmake/Modules/CompilerRTUtils.cmake b/cmake/Modules/CompilerRTUtils.cmake index fce37e3eb49..ae59732928a 100644 --- a/cmake/Modules/CompilerRTUtils.cmake +++ b/cmake/Modules/CompilerRTUtils.cmake @@ -2,6 +2,7 @@ # define a handy helper function for it. The compile flags setting in CMake # has serious issues that make its syntax challenging at best. function(set_target_compile_flags target) + set(argstring "") foreach(arg ${ARGN}) set(argstring "${argstring} ${arg}") endforeach() @@ -9,24 +10,13 @@ function(set_target_compile_flags target) endfunction() function(set_target_link_flags target) + set(argstring "") foreach(arg ${ARGN}) set(argstring "${argstring} ${arg}") endforeach() set_property(TARGET ${target} PROPERTY LINK_FLAGS "${argstring}") endfunction() -# Check if a given flag is present in a space-separated flag_string. -# Store the result in out_var. -function(find_flag_in_string flag_string flag out_var) - string(REPLACE " " ";" flag_list ${flag_string}) - list(FIND flag_list ${flag} flag_pos) - if(NOT flag_pos EQUAL -1) - set(${out_var} TRUE PARENT_SCOPE) - else() - set(${out_var} FALSE PARENT_SCOPE) - endif() -endfunction() - # Set the variable var_PYBOOL to True if var holds a true-ish string, # otherwise set it to False. macro(pythonize_bool var) @@ -36,3 +26,26 @@ macro(pythonize_bool var) set(${var}_PYBOOL False) endif() endmacro() + +# Appends value to all lists in ARGN, if the condition is true. +macro(append_list_if condition value) + if(${condition}) + foreach(list ${ARGN}) + list(APPEND ${list} ${value}) + endforeach() + endif() +endmacro() + +# Appends value to all strings in ARGN, if the condition is true. +macro(append_string_if condition value) + if(${condition}) + foreach(str ${ARGN}) + set(${str} "${${str}} ${value}") + endforeach() + endif() +endmacro() + +macro(append_no_rtti_flag list) + append_list_if(COMPILER_RT_HAS_FNO_RTTI_FLAG -fno-rtti ${list}) + append_list_if(COMPILER_RT_HAS_GR_FLAG /GR- ${list}) +endmacro() diff --git a/cmake/Modules/SanitizerUtils.cmake b/cmake/Modules/SanitizerUtils.cmake index 0836edee264..1ebc7030a57 100644 --- a/cmake/Modules/SanitizerUtils.cmake +++ b/cmake/Modules/SanitizerUtils.cmake @@ -12,21 +12,36 @@ set(SANITIZER_LINT_SCRIPT # symbol names that should be exported as well. # add_sanitizer_rt_symbols( ) macro(add_sanitizer_rt_symbols name) - get_target_property(libfile ${name} LOCATION) - set(symsfile "${libfile}.syms") - add_custom_command(OUTPUT ${symsfile} + set(stamp ${CMAKE_CURRENT_BINARY_DIR}/${name}.syms-stamp) + add_custom_command(OUTPUT ${stamp} COMMAND ${PYTHON_EXECUTABLE} - ${SANITIZER_GEN_DYNAMIC_LIST} ${libfile} ${ARGN} - > ${symsfile} + ${SANITIZER_GEN_DYNAMIC_LIST} $ ${ARGN} + > $.syms + COMMAND ${CMAKE_COMMAND} -E touch ${stamp} DEPENDS ${name} ${SANITIZER_GEN_DYNAMIC_LIST} ${ARGN} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Generating exported symbols for ${name}" VERBATIM) add_custom_target(${name}-symbols ALL - DEPENDS ${symsfile} + DEPENDS ${stamp} SOURCES ${SANITIZER_GEN_DYNAMIC_LIST} ${ARGN}) - install(FILES ${symsfile} DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR}) - add_dependencies(compiler-rt ${name}-symbols) + + if(NOT CMAKE_VERSION VERSION_LESS 3.0) + install(FILES $.syms + DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR}) + else() + # Per-config install location. + if(CMAKE_CONFIGURATION_TYPES) + foreach(c ${CMAKE_CONFIGURATION_TYPES}) + get_target_property(libfile ${name} LOCATION_${c}) + install(FILES ${libfile}.syms CONFIGURATIONS ${c} + DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR}) + endforeach() + else() + get_target_property(libfile ${name} LOCATION_${CMAKE_BUILD_TYPE}) + install(FILES ${libfile}.syms DESTINATION ${COMPILER_RT_LIBRARY_INSTALL_DIR}) + endif() + endif() endmacro() # Add target to check code style for sanitizer runtimes. @@ -34,6 +49,7 @@ if(UNIX) add_custom_target(SanitizerLintCheck COMMAND LLVM_CHECKOUT=${LLVM_MAIN_SRC_DIR} SILENT=1 TMPDIR= PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} + COMPILER_RT=${COMPILER_RT_SOURCE_DIR} ${SANITIZER_LINT_SCRIPT} DEPENDS ${SANITIZER_LINT_SCRIPT} COMMENT "Running lint check for sanitizer sources..." diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake new file mode 100644 index 00000000000..5f921bf97f5 --- /dev/null +++ b/cmake/config-ix.cmake @@ -0,0 +1,258 @@ +include(CheckCXXCompilerFlag) +include(CheckLibraryExists) +include(CheckSymbolExists) + +# CodeGen options. +check_cxx_compiler_flag(-fPIC COMPILER_RT_HAS_FPIC_FLAG) +check_cxx_compiler_flag(-fPIE COMPILER_RT_HAS_FPIE_FLAG) +check_cxx_compiler_flag(-fno-builtin COMPILER_RT_HAS_FNO_BUILTIN_FLAG) +check_cxx_compiler_flag(-fno-exceptions COMPILER_RT_HAS_FNO_EXCEPTIONS_FLAG) +check_cxx_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG) +check_cxx_compiler_flag(-funwind-tables COMPILER_RT_HAS_FUNWIND_TABLES_FLAG) +check_cxx_compiler_flag(-fno-stack-protector COMPILER_RT_HAS_FNO_STACK_PROTECTOR_FLAG) +check_cxx_compiler_flag(-fvisibility=hidden COMPILER_RT_HAS_FVISIBILITY_HIDDEN_FLAG) +check_cxx_compiler_flag(-fno-rtti COMPILER_RT_HAS_FNO_RTTI_FLAG) +check_cxx_compiler_flag(-ffreestanding COMPILER_RT_HAS_FFREESTANDING_FLAG) +check_cxx_compiler_flag("-Werror -fno-function-sections" COMPILER_RT_HAS_FNO_FUNCTION_SECTIONS_FLAG) +check_cxx_compiler_flag(-std=c++11 COMPILER_RT_HAS_STD_CXX11_FLAG) +check_cxx_compiler_flag(-ftls-model=initial-exec COMPILER_RT_HAS_FTLS_MODEL_INITIAL_EXEC) + +check_cxx_compiler_flag(/GR COMPILER_RT_HAS_GR_FLAG) +check_cxx_compiler_flag(/GS COMPILER_RT_HAS_GS_FLAG) +check_cxx_compiler_flag(/MT COMPILER_RT_HAS_MT_FLAG) +check_cxx_compiler_flag(/Oy COMPILER_RT_HAS_Oy_FLAG) + +# Debug info flags. +check_cxx_compiler_flag(-gline-tables-only COMPILER_RT_HAS_GLINE_TABLES_ONLY_FLAG) +check_cxx_compiler_flag(-g COMPILER_RT_HAS_G_FLAG) +check_cxx_compiler_flag(/Zi COMPILER_RT_HAS_Zi_FLAG) + +# Warnings. +check_cxx_compiler_flag(-Wall COMPILER_RT_HAS_WALL_FLAG) +check_cxx_compiler_flag(-Werror COMPILER_RT_HAS_WERROR_FLAG) +check_cxx_compiler_flag("-Werror -Wframe-larger-than=512" COMPILER_RT_HAS_WFRAME_LARGER_THAN_FLAG) +check_cxx_compiler_flag("-Werror -Wglobal-constructors" COMPILER_RT_HAS_WGLOBAL_CONSTRUCTORS_FLAG) +check_cxx_compiler_flag("-Werror -Wc99-extensions" COMPILER_RT_HAS_WC99_EXTENSIONS_FLAG) +check_cxx_compiler_flag("-Werror -Wgnu" COMPILER_RT_HAS_WGNU_FLAG) +check_cxx_compiler_flag("-Werror -Wnon-virtual-dtor" COMPILER_RT_HAS_WNON_VIRTUAL_DTOR_FLAG) +check_cxx_compiler_flag("-Werror -Wvariadic-macros" COMPILER_RT_HAS_WVARIADIC_MACROS_FLAG) + +check_cxx_compiler_flag(/W3 COMPILER_RT_HAS_W3_FLAG) +check_cxx_compiler_flag(/WX COMPILER_RT_HAS_WX_FLAG) +check_cxx_compiler_flag(/wd4146 COMPILER_RT_HAS_WD4146_FLAG) +check_cxx_compiler_flag(/wd4291 COMPILER_RT_HAS_WD4291_FLAG) +check_cxx_compiler_flag(/wd4391 COMPILER_RT_HAS_WD4391_FLAG) +check_cxx_compiler_flag(/wd4722 COMPILER_RT_HAS_WD4722_FLAG) +check_cxx_compiler_flag(/wd4800 COMPILER_RT_HAS_WD4800_FLAG) + +# Symbols. +check_symbol_exists(__func__ "" COMPILER_RT_HAS_FUNC_SYMBOL) + +# Libraries. +check_library_exists(c printf "" COMPILER_RT_HAS_LIBC) +check_library_exists(dl dlopen "" COMPILER_RT_HAS_LIBDL) +check_library_exists(m pow "" COMPILER_RT_HAS_LIBM) +check_library_exists(pthread pthread_create "" COMPILER_RT_HAS_LIBPTHREAD) +check_library_exists(stdc++ __cxa_throw "" COMPILER_RT_HAS_LIBSTDCXX) + +# Architectures. + +# List of all architectures we can target. +set(COMPILER_RT_SUPPORTED_ARCH) + +# Try to compile a very simple source file to ensure we can target the given +# platform. We use the results of these tests to build only the various target +# runtime libraries supported by our current compilers cross-compiling +# abilities. +set(SIMPLE_SOURCE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/simple.cc) +file(WRITE ${SIMPLE_SOURCE} "#include \n#include \nint main() {}\n") + +# test_target_arch( ) +# Sets the target flags for a given architecture and determines if this +# architecture is supported by trying to build a simple file. +macro(test_target_arch arch) + set(TARGET_${arch}_CFLAGS ${ARGN}) + set(argstring "${CMAKE_EXE_LINKER_FLAGS}") + foreach(arg ${ARGN}) + set(argstring "${argstring} ${arg}") + endforeach() + try_compile(CAN_TARGET_${arch} ${CMAKE_BINARY_DIR} ${SIMPLE_SOURCE} + COMPILE_DEFINITIONS "${TARGET_${arch}_CFLAGS}" + OUTPUT_VARIABLE TARGET_${arch}_OUTPUT + CMAKE_FLAGS "-DCMAKE_EXE_LINKER_FLAGS:STRING=${argstring}") + if(${CAN_TARGET_${arch}}) + list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch}) + elseif("${COMPILER_RT_TEST_TARGET_ARCH}" MATCHES "${arch}") + # Bail out if we cannot target the architecture we plan to test. + message(FATAL_ERROR "Cannot compile for ${arch}:\n${TARGET_${arch}_OUTPUT}") + endif() +endmacro() + +# Add $arch as supported with no additional flags. +macro(add_default_target_arch arch) + set(TARGET_${arch}_CFLAGS "") + set(CAN_TARGET_${arch} 1) + list(APPEND COMPILER_RT_SUPPORTED_ARCH ${arch}) +endmacro() + +macro(detect_target_arch) + check_symbol_exists(__arm__ "" __ARM) + check_symbol_exists(__aarch64__ "" __AARCH64) + check_symbol_exists(__x86_64__ "" __X86_64) + check_symbol_exists(__i686__ "" __I686) + check_symbol_exists(__i386__ "" __I386) + check_symbol_exists(__mips__ "" __MIPS) + check_symbol_exists(__mips64__ "" __MIPS64) + if(__ARM) + add_default_target_arch(arm) + elseif(__AARCH64) + add_default_target_arch(aarch64) + elseif(__X86_64) + add_default_target_arch(x86_64) + elseif(__I686) + add_default_target_arch(i686) + elseif(__I386) + add_default_target_arch(i386) + elseif(__MIPS64) # must be checked before __MIPS + add_default_target_arch(mips64) + elseif(__MIPS) + add_default_target_arch(mips) + endif() +endmacro() + +# Generate the COMPILER_RT_SUPPORTED_ARCH list. +if(ANDROID) + # Can't rely on LLVM_NATIVE_ARCH in cross-compilation. + # Examine compiler output instead. + detect_target_arch() + set(COMPILER_RT_OS_SUFFIX "-android") +else() + if("${LLVM_NATIVE_ARCH}" STREQUAL "X86") + if (NOT MSVC) + test_target_arch(x86_64 ${TARGET_64_BIT_CFLAGS}) + endif() + test_target_arch(i386 ${TARGET_32_BIT_CFLAGS}) + elseif("${LLVM_NATIVE_ARCH}" STREQUAL "PowerPC") + test_target_arch(powerpc64 ${TARGET_64_BIT_CFLAGS}) + test_target_arch(powerpc64le ${TARGET_64_BIT_CFLAGS}) + elseif("${LLVM_NATIVE_ARCH}" STREQUAL "Mips") + if("${COMPILER_RT_TEST_TARGET_ARCH}" MATCHES "mipsel|mips64el") + # regex for mipsel, mips64el + test_target_arch(mipsel ${TARGET_32_BIT_CFLAGS}) + test_target_arch(mips64el ${TARGET_64_BIT_CFLAGS}) + else() + test_target_arch(mips ${TARGET_32_BIT_CFLAGS}) + test_target_arch(mips64 ${TARGET_64_BIT_CFLAGS}) + endif() + elseif("${COMPILER_RT_TEST_TARGET_ARCH}" MATCHES "arm") + test_target_arch(arm "-march=armv7-a") + elseif("${COMPILER_RT_TEST_TARGET_ARCH}" MATCHES "aarch32") + test_target_arch(aarch32 "-march=armv8-a") + elseif("${COMPILER_RT_TEST_TARGET_ARCH}" MATCHES "aarch64") + test_target_arch(aarch64 "-march=aarch64") + endif() + set(COMPILER_RT_OS_SUFFIX "") +endif() + +message(STATUS "Compiler-RT supported architectures: ${COMPILER_RT_SUPPORTED_ARCH}") + +# Takes ${ARGN} and puts only supported architectures in @out_var list. +function(filter_available_targets out_var) + set(archs) + foreach(arch ${ARGN}) + list(FIND COMPILER_RT_SUPPORTED_ARCH ${arch} ARCH_INDEX) + if(NOT (ARCH_INDEX EQUAL -1) AND CAN_TARGET_${arch}) + list(APPEND archs ${arch}) + endif() + endforeach() + set(${out_var} ${archs} PARENT_SCOPE) +endfunction() + +# Arhcitectures supported by compiler-rt libraries. +filter_available_targets(SANITIZER_COMMON_SUPPORTED_ARCH + x86_64 i386 i686 powerpc64 powerpc64le arm aarch64 mips mips64 mipsel mips64el) +filter_available_targets(ASAN_SUPPORTED_ARCH + x86_64 i386 i686 powerpc64 powerpc64le arm mips mipsel mips64 mips64el) +filter_available_targets(DFSAN_SUPPORTED_ARCH x86_64 mips64 mips64el) +filter_available_targets(LSAN_SUPPORTED_ARCH x86_64) +# LSan common files should be available on all architectures supported +# by other sanitizers (even if they build into dummy object files). +filter_available_targets(LSAN_COMMON_SUPPORTED_ARCH + ${SANITIZER_COMMON_SUPPORTED_ARCH}) +filter_available_targets(MSAN_SUPPORTED_ARCH x86_64 mips64 mips64el) +filter_available_targets(PROFILE_SUPPORTED_ARCH x86_64 i386 i686 arm mips mips64 + mipsel mips64el aarch64 powerpc64 powerpc64le) +filter_available_targets(TSAN_SUPPORTED_ARCH x86_64) +filter_available_targets(UBSAN_SUPPORTED_ARCH x86_64 i386 i686 arm aarch64 mips mipsel) + +if(ANDROID) + set(OS_NAME "Android") +else() + set(OS_NAME "${CMAKE_SYSTEM_NAME}") +endif() + +if (SANITIZER_COMMON_SUPPORTED_ARCH AND NOT LLVM_USE_SANITIZER AND + (OS_NAME MATCHES "Android|Darwin|Linux|FreeBSD" OR + (OS_NAME MATCHES "Windows" AND MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4))) + set(COMPILER_RT_HAS_SANITIZER_COMMON TRUE) +else() + set(COMPILER_RT_HAS_SANITIZER_COMMON FALSE) +endif() + +if (COMPILER_RT_HAS_SANITIZER_COMMON AND ASAN_SUPPORTED_ARCH) + set(COMPILER_RT_HAS_ASAN TRUE) +else() + set(COMPILER_RT_HAS_ASAN FALSE) +endif() + +# TODO: Add builtins support. + +if (COMPILER_RT_HAS_SANITIZER_COMMON AND DFSAN_SUPPORTED_ARCH AND + OS_NAME MATCHES "Linux") + set(COMPILER_RT_HAS_DFSAN TRUE) +else() + set(COMPILER_RT_HAS_DFSAN FALSE) +endif() + +if (COMPILER_RT_HAS_SANITIZER_COMMON AND LSAN_SUPPORTED_ARCH AND + OS_NAME MATCHES "Darwin|Linux|FreeBSD") + set(COMPILER_RT_HAS_LSAN TRUE) +else() + set(COMPILER_RT_HAS_LSAN FALSE) +endif() + +if (COMPILER_RT_HAS_SANITIZER_COMMON AND LSAN_COMMON_SUPPORTED_ARCH AND + OS_NAME MATCHES "Darwin|Linux|FreeBSD|Android") + set(COMPILER_RT_HAS_LSAN_COMMON TRUE) +else() + set(COMPILER_RT_HAS_LSAN_COMMON FALSE) +endif() + +if (COMPILER_RT_HAS_SANITIZER_COMMON AND MSAN_SUPPORTED_ARCH AND + OS_NAME MATCHES "Linux") + set(COMPILER_RT_HAS_MSAN TRUE) +else() + set(COMPILER_RT_HAS_MSAN FALSE) +endif() + +if (PROFILE_SUPPORTED_ARCH AND + OS_NAME MATCHES "Darwin|Linux|FreeBSD") + set(COMPILER_RT_HAS_PROFILE TRUE) +else() + set(COMPILER_RT_HAS_PROFILE FALSE) +endif() + +if (COMPILER_RT_HAS_SANITIZER_COMMON AND TSAN_SUPPORTED_ARCH AND + OS_NAME MATCHES "Linux|FreeBSD") + set(COMPILER_RT_HAS_TSAN TRUE) +else() + set(COMPILER_RT_HAS_TSAN FALSE) +endif() + +if (COMPILER_RT_HAS_SANITIZER_COMMON AND UBSAN_SUPPORTED_ARCH AND + OS_NAME MATCHES "Darwin|Linux|FreeBSD") + set(COMPILER_RT_HAS_UBSAN TRUE) +else() + set(COMPILER_RT_HAS_UBSAN FALSE) +endif() + diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index d8a73872ba4..7f8664e0997 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -1,16 +1,14 @@ set(SANITIZER_HEADERS + sanitizer/allocator_interface.h sanitizer/asan_interface.h sanitizer/common_interface_defs.h sanitizer/dfsan_interface.h sanitizer/linux_syscall_hooks.h sanitizer/lsan_interface.h - sanitizer/msan_interface.h) + sanitizer/msan_interface.h + sanitizer/tsan_interface_atomic.h) -set(output_dir ${LLVM_BINARY_DIR}/lib/clang/${CLANG_VERSION}/include) - -if(MSVC_IDE OR XCODE) - set(other_output_dir ${LLVM_BINARY_DIR}/bin/lib/clang/${CLANG_VERSION}/include) -endif() +set(output_dir ${COMPILER_RT_OUTPUT_DIR}/include) # Copy compiler-rt headers to the build tree. set(out_files) @@ -22,15 +20,6 @@ foreach( f ${SANITIZER_HEADERS} ) COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst} COMMENT "Copying compiler-rt's ${f}...") list(APPEND out_files ${dst}) - - if(other_output_dir) - set(other_dst ${other_output_dir}/${f}) - add_custom_command(OUTPUT ${other_dst} - DEPENDS ${src} - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${other_dst} - COMMENT "Copying compiler-rt's ${f}...") - list(APPEND out_files ${other_dst}) - endif() endforeach( f ) add_custom_target(compiler-rt-headers ALL DEPENDS ${out_files}) @@ -39,4 +28,4 @@ add_dependencies(compiler-rt compiler-rt-headers) # Install sanitizer headers. install(FILES ${SANITIZER_HEADERS} PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ - DESTINATION ${LIBCLANG_INSTALL_PATH}/include/sanitizer) + DESTINATION ${COMPILER_RT_INSTALL_PATH}/include/sanitizer) diff --git a/include/sanitizer/allocator_interface.h b/include/sanitizer/allocator_interface.h new file mode 100644 index 00000000000..ab251f89c61 --- /dev/null +++ b/include/sanitizer/allocator_interface.h @@ -0,0 +1,66 @@ +//===-- allocator_interface.h ---------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Public interface header for allocator used in sanitizers (ASan/TSan/MSan). +//===----------------------------------------------------------------------===// +#ifndef SANITIZER_ALLOCATOR_INTERFACE_H +#define SANITIZER_ALLOCATOR_INTERFACE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + /* Returns the estimated number of bytes that will be reserved by allocator + for request of "size" bytes. If allocator can't allocate that much + memory, returns the maximal possible allocation size, otherwise returns + "size". */ + size_t __sanitizer_get_estimated_allocated_size(size_t size); + + /* Returns true if p was returned by the allocator and + is not yet freed. */ + int __sanitizer_get_ownership(const volatile void *p); + + /* Returns the number of bytes reserved for the pointer p. + Requires (get_ownership(p) == true) or (p == 0). */ + size_t __sanitizer_get_allocated_size(const volatile void *p); + + /* Number of bytes, allocated and not yet freed by the application. */ + size_t __sanitizer_get_current_allocated_bytes(); + + /* Number of bytes, mmaped by the allocator to fulfill allocation requests. + Generally, for request of X bytes, allocator can reserve and add to free + lists a large number of chunks of size X to use them for future requests. + All these chunks count toward the heap size. Currently, allocator never + releases memory to OS (instead, it just puts freed chunks to free + lists). */ + size_t __sanitizer_get_heap_size(); + + /* Number of bytes, mmaped by the allocator, which can be used to fulfill + allocation requests. When a user program frees memory chunk, it can first + fall into quarantine and will count toward __sanitizer_get_free_bytes() + later. */ + size_t __sanitizer_get_free_bytes(); + + /* Number of bytes in unmapped pages, that are released to OS. Currently, + always returns 0. */ + size_t __sanitizer_get_unmapped_bytes(); + + /* Malloc hooks that may be optionally provided by user. + __sanitizer_malloc_hook(ptr, size) is called immediately after + allocation of "size" bytes, which returned "ptr". + __sanitizer_free_hook(ptr) is called immediately before + deallocation of "ptr". */ + void __sanitizer_malloc_hook(const volatile void *ptr, size_t size); + void __sanitizer_free_hook(const volatile void *ptr); +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/include/sanitizer/asan_interface.h b/include/sanitizer/asan_interface.h index 8adf3f17f24..435391486aa 100644 --- a/include/sanitizer/asan_interface.h +++ b/include/sanitizer/asan_interface.h @@ -50,22 +50,65 @@ extern "C" { ((void)(addr), (void)(size)) #endif - // Returns true iff addr is poisoned (i.e. 1-byte read/write access to this + // Returns 1 if addr is poisoned (i.e. 1-byte read/write access to this // address will result in error report from AddressSanitizer). - bool __asan_address_is_poisoned(void const volatile *addr); + // Otherwise returns 0. + int __asan_address_is_poisoned(void const volatile *addr); - // If at least on byte in [beg, beg+size) is poisoned, return the address + // If at least one byte in [beg, beg+size) is poisoned, return the address // of the first such byte. Otherwise return 0. void *__asan_region_is_poisoned(void *beg, size_t size); // Print the description of addr (useful when debugging in gdb). void __asan_describe_address(void *addr); + // Useful for calling from a debugger to get information about an ASan error. + // Returns 1 if an error has been (or is being) reported, otherwise returns 0. + int __asan_report_present(); + + // Useful for calling from a debugger to get information about an ASan error. + // If an error has been (or is being) reported, the following functions return + // the pc, bp, sp, address, access type (0 = read, 1 = write), access size and + // bug description (e.g. "heap-use-after-free"). Otherwise they return 0. + void *__asan_get_report_pc(); + void *__asan_get_report_bp(); + void *__asan_get_report_sp(); + void *__asan_get_report_address(); + int __asan_get_report_access_type(); + size_t __asan_get_report_access_size(); + const char *__asan_get_report_description(); + + // Useful for calling from the debugger to get information about a pointer. + // Returns the category of the given pointer as a constant string. + // Possible return values are "global", "stack", "stack-fake", "heap", + // "heap-invalid", "shadow-low", "shadow-gap", "shadow-high", "unknown". + // If global or stack, tries to also return the variable name, address and + // size. If heap, tries to return the chunk address and size. 'name' should + // point to an allocated buffer of size 'name_size'. + const char *__asan_locate_address(void *addr, char *name, size_t name_size, + void **region_address, size_t *region_size); + + // Useful for calling from the debugger to get the allocation stack trace + // and thread ID for a heap address. Stores up to 'size' frames into 'trace', + // returns the number of stored frames or 0 on error. + size_t __asan_get_alloc_stack(void *addr, void **trace, size_t size, + int *thread_id); + + // Useful for calling from the debugger to get the free stack trace + // and thread ID for a heap address. Stores up to 'size' frames into 'trace', + // returns the number of stored frames or 0 on error. + size_t __asan_get_free_stack(void *addr, void **trace, size_t size, + int *thread_id); + + // Useful for calling from the debugger to get the current shadow memory + // mapping. + void __asan_get_shadow_mapping(size_t *shadow_scale, size_t *shadow_offset); + // This is an internal function that is called to report an error. // However it is still a part of the interface because users may want to // set a breakpoint on this function in a debugger. void __asan_report_error(void *pc, void *bp, void *sp, - void *addr, bool is_write, size_t access_size); + void *addr, int is_write, size_t access_size); // Sets the exit code to use when reporting an error. // Returns the old value. @@ -82,40 +125,6 @@ extern "C" { // the program crashes before ASan report is printed. void __asan_on_error(); - // User may provide its own implementation for symbolization function. - // It should print the description of instruction at address "pc" to - // "out_buffer". Description should be at most "out_size" bytes long. - // User-specified function should return true if symbolization was - // successful. - bool __asan_symbolize(const void *pc, char *out_buffer, - int out_size); - - // Returns the estimated number of bytes that will be reserved by allocator - // for request of "size" bytes. If ASan allocator can't allocate that much - // memory, returns the maximal possible allocation size, otherwise returns - // "size". - size_t __asan_get_estimated_allocated_size(size_t size); - // Returns true if p was returned by the ASan allocator and - // is not yet freed. - bool __asan_get_ownership(const void *p); - // Returns the number of bytes reserved for the pointer p. - // Requires (get_ownership(p) == true) or (p == 0). - size_t __asan_get_allocated_size(const void *p); - // Number of bytes, allocated and not yet freed by the application. - size_t __asan_get_current_allocated_bytes(); - // Number of bytes, mmaped by asan allocator to fulfill allocation requests. - // Generally, for request of X bytes, allocator can reserve and add to free - // lists a large number of chunks of size X to use them for future requests. - // All these chunks count toward the heap size. Currently, allocator never - // releases memory to OS (instead, it just puts freed chunks to free lists). - size_t __asan_get_heap_size(); - // Number of bytes, mmaped by asan allocator, which can be used to fulfill - // allocation requests. When a user program frees memory chunk, it can first - // fall into quarantine and will count toward __asan_get_free_bytes() later. - size_t __asan_get_free_bytes(); - // Number of bytes in unmapped pages, that are released to OS. Currently, - // always returns 0. - size_t __asan_get_unmapped_bytes(); // Prints accumulated stats to stderr. Used for debugging. void __asan_print_accumulated_stats(); @@ -123,13 +132,23 @@ extern "C" { // a string containing ASan runtime options. See asan_flags.h for details. const char* __asan_default_options(); - // Malloc hooks that may be optionally provided by user. - // __asan_malloc_hook(ptr, size) is called immediately after - // allocation of "size" bytes, which returned "ptr". - // __asan_free_hook(ptr) is called immediately before - // deallocation of "ptr". - void __asan_malloc_hook(void *ptr, size_t size); - void __asan_free_hook(void *ptr); + // The following 2 functions facilitate garbage collection in presence of + // asan's fake stack. + + // Returns an opaque handler to be used later in __asan_addr_is_in_fake_stack. + // Returns NULL if the current thread does not have a fake stack. + void *__asan_get_current_fake_stack(); + + // If fake_stack is non-NULL and addr belongs to a fake frame in + // fake_stack, returns the address on real stack that corresponds to + // the fake frame and sets beg/end to the boundaries of this fake frame. + // Otherwise returns NULL and does not touch beg/end. + // If beg/end are NULL, they are not touched. + // This function may be called from a thread other than the owner of + // fake_stack, but the owner thread need to be alive. + void *__asan_addr_is_in_fake_stack(void *fake_stack, void *addr, void **beg, + void **end); + #ifdef __cplusplus } // extern "C" #endif diff --git a/include/sanitizer/common_interface_defs.h b/include/sanitizer/common_interface_defs.h index 4cc2aeae23c..9cb5ad88de6 100644 --- a/include/sanitizer/common_interface_defs.h +++ b/include/sanitizer/common_interface_defs.h @@ -24,13 +24,28 @@ #ifdef __cplusplus extern "C" { #endif + // Arguments for __sanitizer_sandbox_on_notify() below. + typedef struct { + // Enable sandbox support in sanitizer coverage. + int coverage_sandboxed; + // File descriptor to write coverage data to. If -1 is passed, a file will + // be pre-opened by __sanitizer_sandobx_on_notify(). This field has no + // effect if coverage_sandboxed == 0. + intptr_t coverage_fd; + // If non-zero, split the coverage data into well-formed blocks. This is + // useful when coverage_fd is a socket descriptor. Each block will contain + // a header, allowing data from multiple processes to be sent over the same + // socket. + unsigned int coverage_max_block_size; + } __sanitizer_sandbox_arguments; + // Tell the tools to write their reports to "path." instead of stderr. void __sanitizer_set_report_path(const char *path); // Notify the tools that the sandbox is going to be turned on. The reserved // parameter will be used in the future to hold a structure with functions // that the tools may call to bypass the sandbox. - void __sanitizer_sandbox_on_notify(void *reserved); + void __sanitizer_sandbox_on_notify(__sanitizer_sandbox_arguments *args); // This function is called by the tool when it has just finished reporting // an error. 'error_summary' is a one-line string that summarizes @@ -47,8 +62,17 @@ extern "C" { void __sanitizer_unaligned_store32(void *p, uint32_t x); void __sanitizer_unaligned_store64(void *p, uint64_t x); + // Initialize coverage. + void __sanitizer_cov_init(); // Record and dump coverage info. void __sanitizer_cov_dump(); + // Open .sancov.packed in the coverage directory and return the file + // descriptor. Returns -1 on failure, or if coverage dumping is disabled. + // This is intended for use by sandboxing code. + intptr_t __sanitizer_maybe_open_cov_file(const char *name); + // Get the number of total unique covered entities (blocks, edges, calls). + // This can be useful for coverage-directed in-process fuzzers. + uintptr_t __sanitizer_get_total_unique_coverage(); // Annotate the current state of a contiguous container, such as // std::vector, std::string or similar. @@ -56,7 +80,7 @@ extern "C" { // in a contiguous region of memory. The container owns the region of memory // [beg, end); the memory [beg, mid) is used to store the current elements // and the memory [mid, end) is reserved for future elements; - // end <= mid <= end. For example, in "std::vector<> v" + // beg <= mid <= end. For example, in "std::vector<> v" // beg = &v[0]; // end = beg + v.capacity() * sizeof(v[0]); // mid = beg + v.size() * sizeof(v[0]); @@ -70,9 +94,31 @@ extern "C" { // // Use with caution and don't use for anything other than vector-like classes. // - // For AddressSanitizer, 'beg' should be 8-aligned. - void __sanitizer_annotate_contiguous_container(void *beg, void *end, - void *old_mid, void *new_mid); + // For AddressSanitizer, 'beg' should be 8-aligned and 'end' should + // be either 8-aligned or it should point to the end of a separate heap-, + // stack-, or global- allocated buffer. I.e. the following will not work: + // int64_t x[2]; // 16 bytes, 8-aligned. + // char *beg = (char *)&x[0]; + // char *end = beg + 12; // Not 8 aligned, not the end of the buffer. + // This however will work fine: + // int32_t x[3]; // 12 bytes, but 8-aligned under AddressSanitizer. + // char *beg = (char*)&x[0]; + // char *end = beg + 12; // Not 8-aligned, but is the end of the buffer. + void __sanitizer_annotate_contiguous_container(const void *beg, + const void *end, + const void *old_mid, + const void *new_mid); + // Returns true if the contiguous container [beg, end) is properly poisoned + // (e.g. with __sanitizer_annotate_contiguous_container), i.e. if + // - [beg, mid) is addressable, + // - [mid, end) is unaddressable. + // Full verification requires O(end-beg) time; this function tries to avoid + // such complexity by touching only parts of the container around beg/mid/end. + int __sanitizer_verify_contiguous_container(const void *beg, const void *mid, + const void *end); + + // Print the stack trace leading to this call. Useful for debugging user code. + void __sanitizer_print_stack_trace(); #ifdef __cplusplus } // extern "C" diff --git a/include/sanitizer/dfsan_interface.h b/include/sanitizer/dfsan_interface.h index f14d45a2b2a..79dbf2f364c 100644 --- a/include/sanitizer/dfsan_interface.h +++ b/include/sanitizer/dfsan_interface.h @@ -39,6 +39,9 @@ struct dfsan_label_info { void *userdata; }; +/// Signature of the callback argument to dfsan_set_write_callback(). +typedef void (*dfsan_write_callback_t)(int fd, const void *buf, size_t count); + /// Computes the union of \c l1 and \c l2, possibly creating a union label in /// the process. dfsan_label dfsan_union(dfsan_label l1, dfsan_label l2); @@ -74,6 +77,20 @@ int dfsan_has_label(dfsan_label label, dfsan_label elem); /// that label, else returns 0. dfsan_label dfsan_has_label_with_desc(dfsan_label label, const char *desc); +/// Returns the number of labels allocated. +size_t dfsan_get_label_count(void); + +/// Sets a callback to be invoked on calls to write(). The callback is invoked +/// before the write is done. The write is not guaranteed to succeed when the +/// callback executes. Pass in NULL to remove any callback. +void dfsan_set_write_callback(dfsan_write_callback_t labeled_write_callback); + +/// Writes the labels currently used by the program to the given file +/// descriptor. The lines of the output have the following format: +/// +///