mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-03 16:41:06 +03:00
Merge branch 'master' into merge-2.079
Conflicts: runtime/druntime runtime/phobos
This commit is contained in:
commit
b144fe1123
17 changed files with 191 additions and 40 deletions
|
@ -21,16 +21,16 @@ matrix:
|
||||||
env: LLVM_VERSION=3.7.1 OPTS="-DTEST_COVERAGE=ON"
|
env: LLVM_VERSION=3.7.1 OPTS="-DTEST_COVERAGE=ON"
|
||||||
- os: osx
|
- os: osx
|
||||||
d: ldc-beta
|
d: ldc-beta
|
||||||
env: LLVM_VERSION=6.0.0-5 OPTS="-DBUILD_SHARED_LIBS=OFF" LLVM_SPIRV_AVAILABLE=ON
|
env: LLVM_VERSION=6.0.0 OPTS="-DBUILD_SHARED_LIBS=OFF" LLVM_SPIRV_AVAILABLE=ON
|
||||||
- os: osx
|
- os: osx
|
||||||
d: ldc
|
d: ldc
|
||||||
env: LLVM_VERSION=4.0.0 OPTS="-DBUILD_SHARED_LIBS=ON"
|
env: LLVM_VERSION=4.0.0 OPTS="-DBUILD_SHARED_LIBS=ON"
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- env: LLVM_VERSION=6.0.0-5 OPTS="-DBUILD_SHARED_LIBS=OFF" LLVM_SPIRV_AVAILABLE=ON
|
- env: LLVM_VERSION=6.0.0 OPTS="-DBUILD_SHARED_LIBS=OFF" LLVM_SPIRV_AVAILABLE=ON
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
- llvm-spirv-6.0.0-5
|
- llvm-spirv-6.0.0
|
||||||
- llvm-5.0.1
|
- llvm-5.0.1
|
||||||
- llvm-4.0.1
|
- llvm-4.0.1
|
||||||
- llvm-4.0.0
|
- llvm-4.0.0
|
||||||
|
@ -54,7 +54,7 @@ before_install:
|
||||||
-
|
-
|
||||||
if [ ! -e "$LLVM_ROOT_DIR/bin/llvm-config" ]; then
|
if [ ! -e "$LLVM_ROOT_DIR/bin/llvm-config" ]; then
|
||||||
if [ -n "${LLVM_SPIRV_AVAILABLE}" ]; then
|
if [ -n "${LLVM_SPIRV_AVAILABLE}" ]; then
|
||||||
wget -O llvm.tar.bz2 https://github.com/thewilsonator/llvm/releases/download/pre-intrinsics/LLVM-6.0.0svn-Darwin.tar.bz2;
|
wget -O llvm.tar.bz2 https://github.com/thewilsonator/llvm/releases/download/pre-intrinsics/LLVM-6.0.0-Darwin.tar.bz2;
|
||||||
else
|
else
|
||||||
if [ "${TRAVIS_OS_NAME}" = "linux" ]; then
|
if [ "${TRAVIS_OS_NAME}" = "linux" ]; then
|
||||||
if [ "${LLVM_VERSION}" = "4.0.1" ]; then
|
if [ "${LLVM_VERSION}" = "4.0.1" ]; then
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
cmake_minimum_required(VERSION 2.8)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
if(POLICY CMP0025)
|
||||||
|
cmake_policy(SET CMP0025 NEW)
|
||||||
|
endif()
|
||||||
|
|
||||||
project(ldc)
|
project(ldc)
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules")
|
||||||
|
@ -165,7 +169,7 @@ string(STRIP "${DDMD_DFLAGS}" DDMD_DFLAGS)
|
||||||
# as enabling warnings on the DMD frontend only leads to a lot of clutter in
|
# as enabling warnings on the DMD frontend only leads to a lot of clutter in
|
||||||
# the output (LLVM_CXXFLAGS sometimes already includes -Wall).
|
# the output (LLVM_CXXFLAGS sometimes already includes -Wall).
|
||||||
set(LDC_CXXFLAGS)
|
set(LDC_CXXFLAGS)
|
||||||
if(CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang"))
|
if(CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang"))
|
||||||
# Disable some noisy warnings:
|
# Disable some noisy warnings:
|
||||||
# * -Wunused-parameter triggers for LLVM headers
|
# * -Wunused-parameter triggers for LLVM headers
|
||||||
# * -Wmissing-field-initializer leads to reams of warnings in gen/asm-*.h
|
# * -Wmissing-field-initializer leads to reams of warnings in gen/asm-*.h
|
||||||
|
@ -176,7 +180,7 @@ if(CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang"))
|
||||||
# * -Wgnu-anonymous-struct and -Wnested-anon-types trigger for tokens.h.
|
# * -Wgnu-anonymous-struct and -Wnested-anon-types trigger for tokens.h.
|
||||||
# * -Wgnu-redeclared-enum triggers for various frontend headers.
|
# * -Wgnu-redeclared-enum triggers for various frontend headers.
|
||||||
append("-Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wno-non-virtual-dtor" LDC_CXXFLAGS)
|
append("-Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wno-non-virtual-dtor" LDC_CXXFLAGS)
|
||||||
if ((${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang"))
|
if ((${CMAKE_CXX_COMPILER_ID} MATCHES "Clang"))
|
||||||
append("-Wno-gnu-anonymous-struct -Wno-nested-anon-types -Wno-gnu-redeclared-enum" LDC_CXXFLAGS)
|
append("-Wno-gnu-anonymous-struct -Wno-nested-anon-types -Wno-gnu-redeclared-enum" LDC_CXXFLAGS)
|
||||||
endif()
|
endif()
|
||||||
if(CMAKE_COMPILER_IS_GNUCXX AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS "4.7.0")
|
if(CMAKE_COMPILER_IS_GNUCXX AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS "4.7.0")
|
||||||
|
@ -209,7 +213,7 @@ endif()
|
||||||
set(SANITIZE_CXXFLAGS)
|
set(SANITIZE_CXXFLAGS)
|
||||||
set(SANITIZE_LDFLAGS)
|
set(SANITIZE_LDFLAGS)
|
||||||
if(SANITIZE)
|
if(SANITIZE)
|
||||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||||
append("-fsanitize=address" SANITIZE_CXXFLAGS)
|
append("-fsanitize=address" SANITIZE_CXXFLAGS)
|
||||||
append("-fsanitize=address" SANITIZE_LDFLAGS)
|
append("-fsanitize=address" SANITIZE_LDFLAGS)
|
||||||
else()
|
else()
|
||||||
|
@ -244,7 +248,7 @@ if(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
endif()
|
endif()
|
||||||
# LLVM_CXXFLAGS may contain -Wno-maybe-uninitialized
|
# LLVM_CXXFLAGS may contain -Wno-maybe-uninitialized
|
||||||
# which is gcc-only options
|
# which is gcc-only options
|
||||||
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
|
if(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
|
||||||
string(REPLACE "-Wno-maybe-uninitialized " "" LLVM_CXXFLAGS ${LLVM_CXXFLAGS})
|
string(REPLACE "-Wno-maybe-uninitialized " "" LLVM_CXXFLAGS ${LLVM_CXXFLAGS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -378,11 +382,11 @@ if(LDC_DYNAMIC_COMPILE STREQUAL "AUTO")
|
||||||
set(LDC_DYNAMIC_COMPILE False) # must be a valid Python boolean constant (case sensitive)
|
set(LDC_DYNAMIC_COMPILE False) # must be a valid Python boolean constant (case sensitive)
|
||||||
if (NOT (LDC_LLVM_VER LESS 500))
|
if (NOT (LDC_LLVM_VER LESS 500))
|
||||||
set(LDC_DYNAMIC_COMPILE True)
|
set(LDC_DYNAMIC_COMPILE True)
|
||||||
message(STATUS "Building LDC with dynamic compilation support")
|
|
||||||
add_definitions(-DLDC_DYNAMIC_COMPILE)
|
add_definitions(-DLDC_DYNAMIC_COMPILE)
|
||||||
add_definitions(-DLDC_DYNAMIC_COMPILE_API_VERSION=1)
|
add_definitions(-DLDC_DYNAMIC_COMPILE_API_VERSION=1)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
message(STATUS "Building LDC with dynamic compilation support: ${LDC_DYNAMIC_COMPILE} (LDC_DYNAMIC_COMPILE=${LDC_DYNAMIC_COMPILE})")
|
||||||
|
|
||||||
#
|
#
|
||||||
# Includes, defines.
|
# Includes, defines.
|
||||||
|
@ -493,7 +497,7 @@ endif()
|
||||||
#
|
#
|
||||||
set(TEST_COVERAGE OFF CACHE BOOL "instrument compiler for code coverage analysis")
|
set(TEST_COVERAGE OFF CACHE BOOL "instrument compiler for code coverage analysis")
|
||||||
if(TEST_COVERAGE)
|
if(TEST_COVERAGE)
|
||||||
if(CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang"))
|
if(CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang"))
|
||||||
append("-O0 -g -fprofile-arcs -ftest-coverage" EXTRA_CXXFLAGS)
|
append("-O0 -g -fprofile-arcs -ftest-coverage" EXTRA_CXXFLAGS)
|
||||||
list(APPEND LLVM_LDFLAGS "-lgcov")
|
list(APPEND LLVM_LDFLAGS "-lgcov")
|
||||||
else()
|
else()
|
||||||
|
@ -559,18 +563,16 @@ else()
|
||||||
endif()
|
endif()
|
||||||
set(LDC_ENABLE_PLUGINS ${LDC_ENABLE_PLUGINS_DEFAULT} CACHE BOOL "Build LDC with plugin support (increases binary size)")
|
set(LDC_ENABLE_PLUGINS ${LDC_ENABLE_PLUGINS_DEFAULT} CACHE BOOL "Build LDC with plugin support (increases binary size)")
|
||||||
if(LDC_ENABLE_PLUGINS)
|
if(LDC_ENABLE_PLUGINS)
|
||||||
message(STATUS "Building LDC with plugin support (LDC_ENABLE_PLUGINS=ON)")
|
|
||||||
add_definitions(-DLDC_ENABLE_PLUGINS)
|
add_definitions(-DLDC_ENABLE_PLUGINS)
|
||||||
# For plugin support, we need to link with --export-dynamic on Unix.
|
# For plugin support, we need to link with --export-dynamic on Unix.
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
set(LDC_LINKERFLAG_LIST "${LDC_LINKERFLAG_LIST};-Wl,--export-dynamic")
|
set(LDC_LINKERFLAG_LIST "${LDC_LINKERFLAG_LIST};-Wl,--export-dynamic")
|
||||||
endif()
|
endif()
|
||||||
else()
|
|
||||||
message(STATUS "Building LDC without plugin support (LDC_ENABLE_PLUGINS=OFF)")
|
|
||||||
endif()
|
endif()
|
||||||
|
message(STATUS "Building LDC with plugin support ${LDC_ENABLE_PLUGINS} (LDC_ENABLE_PLUGINS=${LDC_ENABLE_PLUGINS})")
|
||||||
|
|
||||||
set(LDC_LINK_MANUALLY OFF)
|
set(LDC_LINK_MANUALLY OFF)
|
||||||
if(UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")))
|
if(UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")))
|
||||||
# On Unix-like systems, DMD and LDC will use the C compiler for linking, but
|
# On Unix-like systems, DMD and LDC will use the C compiler for linking, but
|
||||||
# will pass on -L options prefixed by -Xlinker to directly forward them to
|
# will pass on -L options prefixed by -Xlinker to directly forward them to
|
||||||
# the underlying ld. Since there are some flags the GCC driver handles itself
|
# the underlying ld. Since there are some flags the GCC driver handles itself
|
||||||
|
@ -737,7 +739,7 @@ if (NOT (LDC_LLVM_VER LESS 309) AND LDC_INSTALL_LTOPLUGIN)
|
||||||
set(LDC_LTO_BINARY_NAME LLVMgold-ldc.so)
|
set(LDC_LTO_BINARY_NAME LLVMgold-ldc.so)
|
||||||
endif()
|
endif()
|
||||||
if(EXISTS ${LLVM_LTO_BINARY})
|
if(EXISTS ${LLVM_LTO_BINARY})
|
||||||
message(STATUS "Also installing LTO binary: ${LLVM_LTO_BINARY}")
|
message(STATUS "Also installing LTO binary: ${LLVM_LTO_BINARY} (LDC_INSTALL_LTOPLUGIN=${LDC_INSTALL_LTOPLUGIN})")
|
||||||
copy_and_rename_file(${LLVM_LTO_BINARY} ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/${LDC_LTO_BINARY_NAME})
|
copy_and_rename_file(${LLVM_LTO_BINARY} ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/${LDC_LTO_BINARY_NAME})
|
||||||
install(PROGRAMS ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/${LDC_LTO_BINARY_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX})
|
install(PROGRAMS ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/${LDC_LTO_BINARY_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX})
|
||||||
else()
|
else()
|
||||||
|
|
|
@ -53,7 +53,8 @@ In addition, LDC is available from various package managers:
|
||||||
| Gentoo | `layman -a ldc` |
|
| Gentoo | `layman -a ldc` |
|
||||||
| Homebrew | `brew install ldc` |
|
| Homebrew | `brew install ldc` |
|
||||||
| Ubuntu | `apt install ldc` |
|
| Ubuntu | `apt install ldc` |
|
||||||
| Snap | `snap install --classic --channel=edge ldc` |
|
| Snap | `snap install --classic --channel=edge ldc2` |
|
||||||
|
| Nix/NixOS | `nix-env -i ldc` |
|
||||||
|
|
||||||
Note that these packages **might be outdated** as they are not
|
Note that these packages **might be outdated** as they are not
|
||||||
currently integrated into the project release process.
|
currently integrated into the project release process.
|
||||||
|
@ -112,5 +113,5 @@ Feedback of any kind is very much appreciated!
|
||||||
[1]: https://circleci.com/gh/ldc-developers/ldc/tree/master "Circle CI Build Status"
|
[1]: https://circleci.com/gh/ldc-developers/ldc/tree/master "Circle CI Build Status"
|
||||||
[2]: https://semaphoreci.com/ldc-developers/ldc "Semaphore CI Build Status"
|
[2]: https://semaphoreci.com/ldc-developers/ldc "Semaphore CI Build Status"
|
||||||
[3]: https://travis-ci.org/ldc-developers/ldc "Travis CI Build Status"
|
[3]: https://travis-ci.org/ldc-developers/ldc "Travis CI Build Status"
|
||||||
[4]: https://www.bountysource.com/teams/ldc-developers/issues "Bountysource"
|
[4]: https://ci.appveyor.com/project/kinke/ldc/history "AppVeyor CI Build Status"
|
||||||
[5]: https://ci.appveyor.com/project/kinke/ldc/history "AppVeyor CI Build Status"
|
[5]: https://www.bountysource.com/teams/ldc-developers/issues "Bountysource"
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "driver/cl_options_sanitizers.h"
|
#include "driver/cl_options_sanitizers.h"
|
||||||
|
|
||||||
#include "dmd/errors.h"
|
#include "dmd/errors.h"
|
||||||
|
#include "dmd/declaration.h"
|
||||||
#include "dmd/dsymbol.h"
|
#include "dmd/dsymbol.h"
|
||||||
#include "llvm/ADT/StringSwitch.h"
|
#include "llvm/ADT/StringSwitch.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
@ -199,14 +200,18 @@ bool functionIsInSanitizerBlacklist(FuncDeclaration *funcDecl) {
|
||||||
if (!sanitizerBlacklist)
|
if (!sanitizerBlacklist)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
auto funcName = mangleExact(funcDecl);
|
||||||
|
auto fileName = funcDecl->loc.filename;
|
||||||
|
|
||||||
#if LDC_LLVM_VER >= 600
|
#if LDC_LLVM_VER >= 600
|
||||||
// TODO: LLVM 6.0 supports sections (e.g. "[address]") in the blacklist file
|
// TODO: LLVM 6.0 supports sections (e.g. "[address]") in the blacklist file
|
||||||
// to only blacklist a function for a particular sanitizer. We could make use
|
// to only blacklist a function for a particular sanitizer. We could make use
|
||||||
// of that too.
|
// of that too.
|
||||||
return sanitizerBlacklist->inSection("" /* section name */, "fun",
|
return sanitizerBlacklist->inSection(/*Section=*/"", "fun", funcName) ||
|
||||||
mangleExact(funcDecl));
|
sanitizerBlacklist->inSection(/*Section=*/"", "src", fileName);
|
||||||
#else
|
#else
|
||||||
return sanitizerBlacklist->inSection("fun", mangleExact(funcDecl));
|
return sanitizerBlacklist->inSection("fun", funcName) ||
|
||||||
|
sanitizerBlacklist->inSection("src", fileName);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -169,6 +169,9 @@ void printVersionStdout() {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
// True when target triple has an uClibc environment
|
||||||
|
bool isUClibc = false;
|
||||||
|
|
||||||
// Helper function to handle -d-debug=* and -d-version=*
|
// Helper function to handle -d-debug=* and -d-version=*
|
||||||
void processVersions(std::vector<std::string> &list, const char *type,
|
void processVersions(std::vector<std::string> &list, const char *type,
|
||||||
unsigned &globalLevel, Strings *&globalIDs) {
|
unsigned &globalLevel, Strings *&globalIDs) {
|
||||||
|
@ -656,6 +659,19 @@ static void registerMipsABI() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if triple environment name starts with "uclibc" and change it to "gnu"
|
||||||
|
void fixupUClibcEnv()
|
||||||
|
{
|
||||||
|
llvm::Triple triple(mTargetTriple);
|
||||||
|
if (triple.getEnvironmentName().find("uclibc") != 0)
|
||||||
|
return;
|
||||||
|
std::string envName = triple.getEnvironmentName();
|
||||||
|
envName.replace(0, 6, "gnu");
|
||||||
|
triple.setEnvironmentName(envName);
|
||||||
|
mTargetTriple = triple.normalize();
|
||||||
|
isUClibc = true;
|
||||||
|
}
|
||||||
|
|
||||||
/// Register the float ABI.
|
/// Register the float ABI.
|
||||||
/// Also defines D_HardFloat or D_SoftFloat depending if FPU should be used
|
/// Also defines D_HardFloat or D_SoftFloat depending if FPU should be used
|
||||||
void registerPredefinedFloatABI(const char *soft, const char *hard,
|
void registerPredefinedFloatABI(const char *soft, const char *hard,
|
||||||
|
@ -731,6 +747,7 @@ void registerPredefinedTargetVersions() {
|
||||||
case llvm::Triple::mips:
|
case llvm::Triple::mips:
|
||||||
case llvm::Triple::mipsel:
|
case llvm::Triple::mipsel:
|
||||||
VersionCondition::addPredefinedGlobalIdent("MIPS");
|
VersionCondition::addPredefinedGlobalIdent("MIPS");
|
||||||
|
VersionCondition::addPredefinedGlobalIdent("MIPS32");
|
||||||
registerPredefinedFloatABI("MIPS_SoftFloat", "MIPS_HardFloat");
|
registerPredefinedFloatABI("MIPS_SoftFloat", "MIPS_HardFloat");
|
||||||
registerMipsABI();
|
registerMipsABI();
|
||||||
break;
|
break;
|
||||||
|
@ -841,11 +858,9 @@ void registerPredefinedTargetVersions() {
|
||||||
if (triple.getEnvironment() == llvm::Triple::Android) {
|
if (triple.getEnvironment() == llvm::Triple::Android) {
|
||||||
VersionCondition::addPredefinedGlobalIdent("Android");
|
VersionCondition::addPredefinedGlobalIdent("Android");
|
||||||
VersionCondition::addPredefinedGlobalIdent("CRuntime_Bionic");
|
VersionCondition::addPredefinedGlobalIdent("CRuntime_Bionic");
|
||||||
#if LDC_LLVM_VER >= 309
|
} else if (isMusl()) {
|
||||||
} else if (triple.isMusl()) {
|
|
||||||
VersionCondition::addPredefinedGlobalIdent("CRuntime_Musl");
|
VersionCondition::addPredefinedGlobalIdent("CRuntime_Musl");
|
||||||
#endif
|
} else if (isUClibc) {
|
||||||
} else if (triple.getEnvironmentName() == "uclibc") {
|
|
||||||
VersionCondition::addPredefinedGlobalIdent("CRuntime_UClibc");
|
VersionCondition::addPredefinedGlobalIdent("CRuntime_UClibc");
|
||||||
} else {
|
} else {
|
||||||
VersionCondition::addPredefinedGlobalIdent("CRuntime_Glibc");
|
VersionCondition::addPredefinedGlobalIdent("CRuntime_Glibc");
|
||||||
|
@ -1032,6 +1047,9 @@ int cppmain(int argc, char **argv) {
|
||||||
relocModel = llvm::Reloc::PIC_;
|
relocModel = llvm::Reloc::PIC_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check and fix environment for uClibc
|
||||||
|
fixupUClibcEnv();
|
||||||
|
|
||||||
gTargetMachine = createTargetMachine(
|
gTargetMachine = createTargetMachine(
|
||||||
mTargetTriple, arch, opts::getCPUStr(), opts::getFeaturesStr(), bitness,
|
mTargetTriple, arch, opts::getCPUStr(), opts::getFeaturesStr(), bitness,
|
||||||
floatABI, relocModel, opts::getCodeModel(), codeGenOptLevel(),
|
floatABI, relocModel, opts::getCodeModel(), codeGenOptLevel(),
|
||||||
|
|
|
@ -70,6 +70,14 @@ bool isTargetWindowsMSVC() {
|
||||||
return global.params.targetTriple->isWindowsMSVCEnvironment();
|
return global.params.targetTriple->isWindowsMSVCEnvironment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isMusl() {
|
||||||
|
#if LDC_LLVM_VER >= 309
|
||||||
|
return global.params.targetTriple->isMusl();
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Global context
|
* Global context
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
@ -311,7 +319,7 @@ void DtoCAssert(Module *M, Loc &loc, LLValue *msg) {
|
||||||
args.push_back(file);
|
args.push_back(file);
|
||||||
args.push_back(line);
|
args.push_back(line);
|
||||||
args.push_back(msg);
|
args.push_back(msg);
|
||||||
} else if (global.params.targetTriple->isOSSolaris()) {
|
} else if (global.params.targetTriple->isOSSolaris() || isMusl()) {
|
||||||
const auto irFunc = gIR->func();
|
const auto irFunc = gIR->func();
|
||||||
const auto funcName =
|
const auto funcName =
|
||||||
(irFunc && irFunc->decl) ? irFunc->decl->toPrettyChars() : "";
|
(irFunc && irFunc->decl) ? irFunc->decl->toPrettyChars() : "";
|
||||||
|
|
|
@ -27,6 +27,9 @@ struct IRState;
|
||||||
// An arrayreference type with initializer_list support (C++11):
|
// An arrayreference type with initializer_list support (C++11):
|
||||||
template <class T> using ArrayParam = llvm::ArrayRef<T>;
|
template <class T> using ArrayParam = llvm::ArrayRef<T>;
|
||||||
|
|
||||||
|
// Helper function because LLVM's isMusl wasn't around before 3.9.
|
||||||
|
bool isMusl();
|
||||||
|
|
||||||
llvm::LLVMContext& getGlobalContext();
|
llvm::LLVMContext& getGlobalContext();
|
||||||
|
|
||||||
// dynamic memory helpers
|
// dynamic memory helpers
|
||||||
|
|
|
@ -167,6 +167,8 @@ llvm::Function *getRuntimeFunction(const Loc &loc, llvm::Module &target,
|
||||||
// MSVC: void _assert(const char *msg, const char *file, unsigned line)
|
// MSVC: void _assert(const char *msg, const char *file, unsigned line)
|
||||||
// Solaris: void __assert_c99(const char *assertion, const char *filename, int line_num,
|
// Solaris: void __assert_c99(const char *assertion, const char *filename, int line_num,
|
||||||
// const char *funcname);
|
// const char *funcname);
|
||||||
|
// Musl: void __assert_fail(const char *assertion, const char *filename, int line_num,
|
||||||
|
// const char *funcname);
|
||||||
// else: void __assert(const char *msg, const char *file, unsigned line)
|
// else: void __assert(const char *msg, const char *file, unsigned line)
|
||||||
|
|
||||||
static const char *getCAssertFunctionName() {
|
static const char *getCAssertFunctionName() {
|
||||||
|
@ -176,6 +178,8 @@ static const char *getCAssertFunctionName() {
|
||||||
return "_assert";
|
return "_assert";
|
||||||
} else if (global.params.targetTriple->isOSSolaris()) {
|
} else if (global.params.targetTriple->isOSSolaris()) {
|
||||||
return "__assert_c99";
|
return "__assert_c99";
|
||||||
|
} else if (isMusl()) {
|
||||||
|
return "__assert_fail";
|
||||||
}
|
}
|
||||||
return "__assert";
|
return "__assert";
|
||||||
}
|
}
|
||||||
|
@ -184,7 +188,8 @@ static std::vector<Type *> getCAssertFunctionParamTypes() {
|
||||||
const auto voidPtr = Type::tvoidptr;
|
const auto voidPtr = Type::tvoidptr;
|
||||||
const auto uint = Type::tuns32;
|
const auto uint = Type::tuns32;
|
||||||
|
|
||||||
if (global.params.targetTriple->isOSDarwin() || global.params.targetTriple->isOSSolaris()) {
|
if (global.params.targetTriple->isOSDarwin() ||
|
||||||
|
global.params.targetTriple->isOSSolaris() || isMusl()) {
|
||||||
return {voidPtr, voidPtr, uint, voidPtr};
|
return {voidPtr, voidPtr, uint, voidPtr};
|
||||||
}
|
}
|
||||||
if (global.params.targetTriple->getEnvironment() == llvm::Triple::Android) {
|
if (global.params.targetTriple->getEnvironment() == llvm::Triple::Android) {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit beb176e469903504f305b0b25cd11a63fae549ec
|
Subproject commit 5430db37a533136520cd6b09a0e44e57ae29e4ae
|
|
@ -1 +1 @@
|
||||||
Subproject commit 171123dcb23db6b715abcbb93389ced5627363ac
|
Subproject commit aec6d0db9ddf3a223bb8ac4a5f27f320084b5abe
|
16
tests/sanitizers/fsanitize_blacklist_file1.d
Normal file
16
tests/sanitizers/fsanitize_blacklist_file1.d
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// Test sanitizer blacklist file functionality
|
||||||
|
// This file is _not_ blacklisted (file2 is)
|
||||||
|
|
||||||
|
// RUN: %ldc -c -output-ll -fsanitize=address \
|
||||||
|
// RUN: -fsanitize-blacklist=%S/inputs/fsanitize_blacklist_file.txt \
|
||||||
|
// RUN: -of=%t.ll %s && FileCheck %s < %t.ll
|
||||||
|
|
||||||
|
// CHECK-LABEL: define {{.*}}9foofoofoo
|
||||||
|
// CHECK-SAME: #[[ATTR_WITHASAN:[0-9]+]]
|
||||||
|
void foofoofoo(int* i)
|
||||||
|
{
|
||||||
|
// CHECK: call {{.*}}_asan
|
||||||
|
*i = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//CHECK: attributes #[[ATTR_WITHASAN]] ={{.*}}sanitize_address
|
15
tests/sanitizers/fsanitize_blacklist_file2.d
Normal file
15
tests/sanitizers/fsanitize_blacklist_file2.d
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// Test sanitizer blacklist file functionality
|
||||||
|
// This file is blacklisted (file1 is not)
|
||||||
|
|
||||||
|
// RUN: %ldc -c -output-ll -fsanitize=address \
|
||||||
|
// RUN: -fsanitize-blacklist=%S/inputs/fsanitize_blacklist_file.txt \
|
||||||
|
// RUN: -of=%t.ll %s && FileCheck %s < %t.ll
|
||||||
|
|
||||||
|
// CHECK-LABEL: define {{.*}}9foofoofoo
|
||||||
|
// CHECK-SAME: #[[ATTR_NOASAN:[0-9]+]]
|
||||||
|
void foofoofoo(int* i)
|
||||||
|
{
|
||||||
|
*i = 1;
|
||||||
|
}
|
||||||
|
//CHECK: attributes #[[ATTR_NOASAN]]
|
||||||
|
//CHECK-NOT: sanitize_address
|
24
tests/sanitizers/fuzz_mixin.d
Normal file
24
tests/sanitizers/fuzz_mixin.d
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
// Test the basic fuzz target mixin for a D-signature fuzz target.
|
||||||
|
|
||||||
|
// REQUIRES: atleast_llvm500
|
||||||
|
// REQUIRES: Fuzzer
|
||||||
|
// UNSUPPORTED: Windows
|
||||||
|
|
||||||
|
// RUN: %ldc -g -fsanitize=fuzzer %s -of=%t%exe
|
||||||
|
// RUN: not %t%exe 2>&1 | FileCheck %s
|
||||||
|
|
||||||
|
int FuzzMe(in ubyte[] data)
|
||||||
|
{
|
||||||
|
if ((data.length >= 3) && data[0] == 'F' && data[1] == 'U' && data[2] == 'Z')
|
||||||
|
{
|
||||||
|
// Testing this assertion also tests that druntime is initialized.
|
||||||
|
// CHECK: fuzz_mixin.d([[@LINE+1]]): Assertion failure
|
||||||
|
assert(false);
|
||||||
|
// CHECK: ERROR: libFuzzer: deadly signal
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
import ldc.libfuzzer;
|
||||||
|
mixin DefineTestOneInput!FuzzMe;
|
1
tests/sanitizers/inputs/fsanitize_blacklist_file.txt
Normal file
1
tests/sanitizers/inputs/fsanitize_blacklist_file.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
src:*fsanitize_blacklist_file2.d
|
|
@ -37,14 +37,19 @@ using namespace llvm;
|
||||||
|
|
||||||
enum ProfileFormat { PF_None = 0, PF_Text, PF_Binary, PF_GCC };
|
enum ProfileFormat { PF_None = 0, PF_Text, PF_Binary, PF_GCC };
|
||||||
|
|
||||||
static void exitWithError(const Twine &Message, StringRef Whence = "",
|
static void warn(StringRef Prefix, Twine Message, std::string Whence = "",
|
||||||
StringRef Hint = "") {
|
std::string Hint = "") {
|
||||||
errs() << "error: ";
|
errs() << Prefix;
|
||||||
if (!Whence.empty())
|
if (!Whence.empty())
|
||||||
errs() << Whence << ": ";
|
errs() << Whence << ": ";
|
||||||
errs() << Message << "\n";
|
errs() << Message << "\n";
|
||||||
if (!Hint.empty())
|
if (!Hint.empty())
|
||||||
errs() << Hint << "\n";
|
errs() << Hint << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
static void exitWithError(Twine Message, std::string Whence = "",
|
||||||
|
std::string Hint = "") {
|
||||||
|
warn("error: ", Message, Whence, Hint);
|
||||||
::exit(1);
|
::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +124,7 @@ struct WriterContext {
|
||||||
std::mutex Lock;
|
std::mutex Lock;
|
||||||
InstrProfWriter Writer;
|
InstrProfWriter Writer;
|
||||||
Error Err;
|
Error Err;
|
||||||
StringRef ErrWhence;
|
std::string ErrWhence;
|
||||||
std::mutex &ErrLock;
|
std::mutex &ErrLock;
|
||||||
SmallSet<instrprof_error, 4> &WriterErrorCodes;
|
SmallSet<instrprof_error, 4> &WriterErrorCodes;
|
||||||
|
|
||||||
|
@ -129,6 +134,22 @@ struct WriterContext {
|
||||||
ErrLock(ErrLock), WriterErrorCodes(WriterErrorCodes) {}
|
ErrLock(ErrLock), WriterErrorCodes(WriterErrorCodes) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Determine whether an error is fatal for profile merging.
|
||||||
|
static bool isFatalError(instrprof_error IPE) {
|
||||||
|
switch (IPE) {
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
case instrprof_error::success:
|
||||||
|
case instrprof_error::eof:
|
||||||
|
case instrprof_error::unknown_function:
|
||||||
|
case instrprof_error::hash_mismatch:
|
||||||
|
case instrprof_error::count_mismatch:
|
||||||
|
case instrprof_error::counter_overflow:
|
||||||
|
case instrprof_error::value_site_count_mismatch:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Load an input into a writer context.
|
/// Load an input into a writer context.
|
||||||
static void loadInput(const WeightedFile &Input, WriterContext *WC) {
|
static void loadInput(const WeightedFile &Input, WriterContext *WC) {
|
||||||
std::unique_lock<std::mutex> CtxGuard{WC->Lock};
|
std::unique_lock<std::mutex> CtxGuard{WC->Lock};
|
||||||
|
@ -137,6 +158,9 @@ static void loadInput(const WeightedFile &Input, WriterContext *WC) {
|
||||||
if (WC->Err)
|
if (WC->Err)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Copy the filename, because llvm::ThreadPool copied the input "const
|
||||||
|
// WeightedFile &" by value, making a reference to the filename within it
|
||||||
|
// invalid outside of this packaged task.
|
||||||
WC->ErrWhence = Input.Filename;
|
WC->ErrWhence = Input.Filename;
|
||||||
|
|
||||||
auto ReaderOrErr = InstrProfReader::create(Input.Filename);
|
auto ReaderOrErr = InstrProfReader::create(Input.Filename);
|
||||||
|
@ -174,12 +198,22 @@ static void loadInput(const WeightedFile &Input, WriterContext *WC) {
|
||||||
FuncName, firstTime);
|
FuncName, firstTime);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (Reader->hasError())
|
if (Reader->hasError()) {
|
||||||
WC->Err = Reader->getError();
|
if (Error E = Reader->getError()) {
|
||||||
|
instrprof_error IPE = InstrProfError::take(std::move(E));
|
||||||
|
if (isFatalError(IPE))
|
||||||
|
WC->Err = make_error<InstrProfError>(IPE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Merge the \p Src writer context into \p Dst.
|
/// Merge the \p Src writer context into \p Dst.
|
||||||
static void mergeWriterContexts(WriterContext *Dst, WriterContext *Src) {
|
static void mergeWriterContexts(WriterContext *Dst, WriterContext *Src) {
|
||||||
|
// If we've already seen a hard error, continuing with the merge would
|
||||||
|
// clobber it.
|
||||||
|
if (Dst->Err || Src->Err)
|
||||||
|
return;
|
||||||
|
|
||||||
bool Reported = false;
|
bool Reported = false;
|
||||||
Dst->Writer.mergeRecordsFromWriter(std::move(Src->Writer), [&](Error E) {
|
Dst->Writer.mergeRecordsFromWriter(std::move(Src->Writer), [&](Error E) {
|
||||||
if (Reported) {
|
if (Reported) {
|
||||||
|
@ -211,8 +245,8 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs,
|
||||||
|
|
||||||
// If NumThreads is not specified, auto-detect a good default.
|
// If NumThreads is not specified, auto-detect a good default.
|
||||||
if (NumThreads == 0)
|
if (NumThreads == 0)
|
||||||
NumThreads = std::max(1U, std::min(std::thread::hardware_concurrency(),
|
NumThreads =
|
||||||
unsigned(Inputs.size() / 2)));
|
std::min(hardware_concurrency(), unsigned((Inputs.size() + 1) / 2));
|
||||||
|
|
||||||
// Initialize the writer contexts.
|
// Initialize the writer contexts.
|
||||||
SmallVector<std::unique_ptr<WriterContext>, 4> Contexts;
|
SmallVector<std::unique_ptr<WriterContext>, 4> Contexts;
|
||||||
|
@ -254,10 +288,20 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle deferred hard errors encountered during merging.
|
// Handle deferred hard errors encountered during merging.
|
||||||
for (std::unique_ptr<WriterContext> &WC : Contexts)
|
for (std::unique_ptr<WriterContext> &WC : Contexts) {
|
||||||
if (WC->Err)
|
if (!WC->Err)
|
||||||
|
continue;
|
||||||
|
if (!WC->Err.isA<InstrProfError>())
|
||||||
exitWithError(std::move(WC->Err), WC->ErrWhence);
|
exitWithError(std::move(WC->Err), WC->ErrWhence);
|
||||||
|
|
||||||
|
instrprof_error IPE = InstrProfError::take(std::move(WC->Err));
|
||||||
|
if (isFatalError(IPE))
|
||||||
|
exitWithError(make_error<InstrProfError>(IPE), WC->ErrWhence);
|
||||||
|
else
|
||||||
|
warn("warning: ", toString(make_error<InstrProfError>(IPE)),
|
||||||
|
WC->ErrWhence);
|
||||||
|
}
|
||||||
|
|
||||||
InstrProfWriter &Writer = Contexts[0]->Writer;
|
InstrProfWriter &Writer = Contexts[0]->Writer;
|
||||||
if (OutputFormat == PF_Text) {
|
if (OutputFormat == PF_Text) {
|
||||||
if (Error E = Writer.writeText(Output))
|
if (Error E = Writer.writeText(Output))
|
||||||
|
@ -625,6 +669,8 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts,
|
||||||
if (ShowCounts && TextFormat)
|
if (ShowCounts && TextFormat)
|
||||||
return 0;
|
return 0;
|
||||||
std::unique_ptr<ProfileSummary> PS(Builder.getSummary());
|
std::unique_ptr<ProfileSummary> PS(Builder.getSummary());
|
||||||
|
OS << "Instrumentation level: "
|
||||||
|
<< (Reader->isIRLevelProfile() ? "IR" : "Front-end") << "\n";
|
||||||
if (ShowAllFunctions || !ShowFunction.empty())
|
if (ShowAllFunctions || !ShowFunction.empty())
|
||||||
OS << "Functions shown: " << ShownFunctions << "\n";
|
OS << "Functions shown: " << ShownFunctions << "\n";
|
||||||
OS << "Total functions: " << PS->getNumFunctions() << "\n";
|
OS << "Total functions: " << PS->getNumFunctions() << "\n";
|
||||||
|
|
|
@ -39,7 +39,7 @@ if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${FILECHECK_SRC})
|
||||||
)
|
)
|
||||||
target_link_libraries(FileCheck ${LLVM_LIBRARIES} ${TERMINFO_LIBS} ${CMAKE_DL_LIBS} ${LLVM_LDFLAGS})
|
target_link_libraries(FileCheck ${LLVM_LIBRARIES} ${TERMINFO_LIBS} ${CMAKE_DL_LIBS} ${LLVM_LDFLAGS})
|
||||||
else()
|
else()
|
||||||
message(STATUS "Skip building FileCheck, assuming it can be found in LLVM bin directory")
|
message(STATUS "Skip building FileCheck (source not found), assuming it can be found in LLVM bin directory")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Build `not` for testing
|
# Build `not` for testing
|
||||||
|
|
|
@ -62,6 +62,10 @@ static cl::list<std::string> ImplicitCheckNot(
|
||||||
"this pattern occur which are not matched by a positive pattern"),
|
"this pattern occur which are not matched by a positive pattern"),
|
||||||
cl::value_desc("pattern"));
|
cl::value_desc("pattern"));
|
||||||
|
|
||||||
|
static cl::list<std::string> GlobalDefines("D", cl::Prefix,
|
||||||
|
cl::desc("Define a variable to be used in capture patterns."),
|
||||||
|
cl::value_desc("VAR=VALUE"));
|
||||||
|
|
||||||
static cl::opt<bool> AllowEmptyInput(
|
static cl::opt<bool> AllowEmptyInput(
|
||||||
"allow-empty", cl::init(false),
|
"allow-empty", cl::init(false),
|
||||||
cl::desc("Allow the input file to be empty. This is useful when making\n"
|
cl::desc("Allow the input file to be empty. This is useful when making\n"
|
||||||
|
@ -1295,6 +1299,9 @@ bool CheckInput(SourceMgr &SM, StringRef Buffer,
|
||||||
/// VariableTable - This holds all the current filecheck variables.
|
/// VariableTable - This holds all the current filecheck variables.
|
||||||
StringMap<StringRef> VariableTable;
|
StringMap<StringRef> VariableTable;
|
||||||
|
|
||||||
|
for (const auto& Def : GlobalDefines)
|
||||||
|
VariableTable.insert(StringRef(Def).split('='));
|
||||||
|
|
||||||
unsigned i = 0, j = 0, e = CheckStrings.size();
|
unsigned i = 0, j = 0, e = CheckStrings.size();
|
||||||
while (true) {
|
while (true) {
|
||||||
StringRef CheckRegion;
|
StringRef CheckRegion;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue