Merge branch 'master' into merge-2.079

Conflicts:
	runtime/druntime
	runtime/phobos
This commit is contained in:
Martin 2018-03-30 00:06:01 +02:00
commit b144fe1123
17 changed files with 191 additions and 40 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View 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

View 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

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

View file

@ -0,0 +1 @@
src:*fsanitize_blacklist_file2.d

View file

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

View file

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

View file

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