Merge branch 'master' into merge-2.075

Conflicts:
	runtime/druntime
	runtime/phobos
This commit is contained in:
Martin 2017-08-12 18:21:21 +02:00
commit b085be1404
25 changed files with 543 additions and 262 deletions

View file

@ -108,12 +108,6 @@ file(MAKE_DIRECTORY
${PROJECT_BINARY_DIR}/${DDMDFE_PATH}
)
if(UNIX)
ENABLE_LANGUAGE(ASM)
elseif(MSVC)
ENABLE_LANGUAGE(ASM_MASM)
endif()
# Setup D compiler flags (DMD syntax, which also works with LDMD).
set(DDMD_DFLAGS "-wi")
set(DDMD_LFLAGS "")
@ -813,15 +807,24 @@ if(D_VERSION EQUAL 2)
endif()
add_subdirectory(tests)
# ldc-build-runtime tool
set(LDC_BUILD_RUNTIME_EXE_FULL ${PROJECT_BINARY_DIR}/bin/ldc-build-runtime${CMAKE_EXECUTABLE_SUFFIX})
build_d_executable(
"${LDC_BUILD_RUNTIME_EXE_FULL}"
"${PROJECT_BINARY_DIR}/ldc-build-runtime.d"
""
"${PROJECT_SOURCE_DIR}/runtime/ldc-build-runtime.d.in"
""
)
add_custom_target(ldc-build-runtime ALL DEPENDS ${LDC_BUILD_RUNTIME_EXE_FULL})
#
# Install target.
#
install(PROGRAMS ${LDC_EXE_FULL} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
install(PROGRAMS ${LDMD_EXE_FULL} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
if(NOT CMAKE_INSTALL_PREFIX STREQUAL "/usr")
install(PROGRAMS ${PROJECT_BINARY_DIR}/bin/build-ldc-runtime.sh DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
endif()
install(PROGRAMS ${LDC_BUILD_RUNTIME_EXE_FULL} DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
if(${BUILD_SHARED})
# For now, only install libldc if explicitly building the shared library.
# While it might theoretically be possible to use LDC as a static library

View file

@ -65,20 +65,19 @@ install:
appveyor DownloadFile "http://downloads.dlang.org/releases/2.x/$dmdVersion/dmd.$dmdVersion.windows.7z" -FileName dmd2.7z
7z x dmd2.7z > $null
Set-Item -path env:DMD -value c:\projects\dmd2\windows\bin\dmd.exe
c:\projects\dmd2\windows\bin\dmd.exe --version
} Else {
$ldcVersion = '1.3.0'
If ($Env:APPVEYOR_JOB_ARCH -eq 'x64') {
appveyor DownloadFile 'http://github.com/ldc-developers/ldc/releases/download/v1.0.0/ldc2-1.0.0-win64-msvc.zip' -FileName ldc2.zip
appveyor DownloadFile "http://github.com/ldc-developers/ldc/releases/download/v$ldcVersion/ldc2-$ldcVersion-win64-msvc.zip" -FileName ldc2.zip
7z x ldc2.zip > $null
Set-Item -path env:DMD -value c:\projects\ldc2-1.0.0-win64-msvc\bin\ldmd2.exe
c:\projects\ldc2-1.0.0-win64-msvc\bin\ldc2 --version
Set-Item -path env:DMD -value c:\projects\ldc2-$ldcVersion-win64-msvc\bin\ldmd2.exe
} Else {
appveyor DownloadFile 'http://github.com/ldc-developers/ldc/releases/download/v1.0.0/ldc2-1.0.0-win32-msvc.zip' -FileName ldc2.zip
appveyor DownloadFile "http://github.com/ldc-developers/ldc/releases/download/v$ldcVersion/ldc2-$ldcVersion-win32-msvc.zip" -FileName ldc2.zip
7z x ldc2.zip > $null
Set-Item -path env:DMD -value c:\projects\ldc2-1.0.0-win32-msvc\bin\ldmd2.exe
c:\projects\ldc2-1.0.0-win32-msvc\bin\ldc2 --version
Set-Item -path env:DMD -value c:\projects\ldc2-$ldcVersion-win32-msvc\bin\ldmd2.exe
}
}
& $Env:DMD --version
# Download & extract GNU make + utils (for dmd-testsuite)
- bash --version
- appveyor DownloadFile "https://dl.dropboxusercontent.com/s/4y36f5ydgrk4p5g/make-4.2.1.7z?dl=0" -FileName make.7z
@ -100,7 +99,8 @@ install:
- cd ..
# Set environment variables
- set PATH=%CD%\ninja;%CD%\make;%PATH%
- call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd.bat" -arch=%APPVEYOR_JOB_ARCH%
- if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2017" call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd.bat" -arch=%APPVEYOR_JOB_ARCH%
- if "%APPVEYOR_BUILD_WORKER_IMAGE%" == "Visual Studio 2015" call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" %APPVEYOR_JOB_ARCH%
# Print environment info
- set
- msbuild /version

View file

@ -8261,13 +8261,6 @@ extern (C++) final class TypeStruct : Type
AliasThisRec att = RECfwdref;
CPPMANGLE cppmangle = CPPMANGLE.def;
version(IN_LLVM)
{
// cache the hasUnalignedFields check
// 0 = not checked, 1 = aligned, 2 = unaligned
int unaligned;
}
extern (D) this(StructDeclaration sym)
{
super(Tstruct);

View file

@ -758,12 +758,6 @@ public:
AliasThisRec att;
CPPMANGLE cppmangle;
#if IN_LLVM
// cache the hasUnalignedFields check
// 0 = not checked, 1 = aligned, 2 = unaligned
int32_t unaligned;
#endif
const char *kind();
d_uns64 size(Loc loc);
unsigned alignsize();

View file

@ -15,8 +15,10 @@
#include "driver/cl_options_sanitizers.h"
#include "ddmd/errors.h"
#include "ddmd/dsymbol.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SpecialCaseList.h"
namespace {
@ -28,6 +30,13 @@ cl::list<std::string> fSanitize(
"suspicious behavior."),
cl::value_desc("checks"));
cl::list<std::string> fSanitizeBlacklist(
"fsanitize-blacklist", cl::CommaSeparated,
cl::desc("Add <file> to the blacklist files for the sanitizers."),
cl::value_desc("file"));
std::unique_ptr<llvm::SpecialCaseList> sanitizerBlacklist;
#ifdef ENABLE_COVERAGE_SANITIZER
cl::list<std::string> fSanitizeCoverage(
"fsanitize-coverage", cl::CommaSeparated,
@ -149,6 +158,14 @@ void initializeSanitizerOptionsFromCmdline()
sancovOpts.CoverageType = llvm::SanitizerCoverageOptions::SCK_Edge;
}
#endif
if (isAnySanitizerEnabled() && !fSanitizeBlacklist.empty()) {
std::string loadError;
sanitizerBlacklist =
llvm::SpecialCaseList::create(fSanitizeBlacklist, loadError);
if (!sanitizerBlacklist)
error(Loc(), "-fsanitize-blacklist error: %s", loadError.c_str());
}
}
#ifdef ENABLE_COVERAGE_SANITIZER
@ -180,4 +197,9 @@ void outputSanitizerSettings(llvm::raw_ostream &hash_os) {
#endif
}
bool functionIsInSanitizerBlacklist(FuncDeclaration *funcDecl) {
return sanitizerBlacklist &&
sanitizerBlacklist->inSection("fun", mangleExact(funcDecl));
}
} // namespace opts

View file

@ -23,6 +23,7 @@
#define ENABLE_COVERAGE_SANITIZER
#endif
class FuncDeclaration;
namespace llvm {
class raw_ostream;
}
@ -54,6 +55,8 @@ llvm::SanitizerCoverageOptions getSanitizerCoverageOptions();
void outputSanitizerSettings(llvm::raw_ostream &hash_os);
bool functionIsInSanitizerBlacklist(FuncDeclaration *funcDecl);
} // namespace opts
#endif // LDC_DRIVER_CL_OPTIONS_SANITIZERS_H

View file

@ -54,7 +54,7 @@ private:
virtual void addUserSwitches();
void addDefaultLibs();
virtual void addArch();
virtual void addTargetFlags();
#if LDC_LLVM_VER >= 309
void addLTOGoldPluginFlags();
@ -404,7 +404,7 @@ void ArgsBuilder::build(llvm::StringRef outputPath,
addDefaultLibs();
addArch();
addTargetFlags();
}
//////////////////////////////////////////////////////////////////////////////
@ -495,50 +495,8 @@ void ArgsBuilder::addDefaultLibs() {
//////////////////////////////////////////////////////////////////////////////
void ArgsBuilder::addArch() {
// Only specify -m32/-m64 for architectures where the two variants actually
// exist (as e.g. the GCC ARM toolchain doesn't recognize the switches).
// MIPS does not have -m32/-m64 but requires -mabi=.
if (global.params.targetTriple->get64BitArchVariant().getArch() !=
llvm::Triple::UnknownArch &&
global.params.targetTriple->get32BitArchVariant().getArch() !=
llvm::Triple::UnknownArch) {
if (global.params.targetTriple->get64BitArchVariant().getArch() ==
llvm::Triple::mips64 ||
global.params.targetTriple->get64BitArchVariant().getArch() ==
llvm::Triple::mips64el) {
switch (getMipsABI()) {
case MipsABI::EABI:
args.push_back("-mabi=eabi");
break;
case MipsABI::O32:
args.push_back("-mabi=32");
break;
case MipsABI::N32:
args.push_back("-mabi=n32");
break;
case MipsABI::N64:
args.push_back("-mabi=64");
break;
case MipsABI::Unknown:
break;
}
} else {
switch (global.params.targetTriple->getArch()) {
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
break;
default:
if (global.params.is64bit) {
args.push_back("-m64");
} else {
args.push_back("-m32");
}
}
}
}
void ArgsBuilder::addTargetFlags() {
appendTargetArgsForGcc(args);
}
//////////////////////////////////////////////////////////////////////////////
@ -556,7 +514,7 @@ class LdArgsBuilder : public ArgsBuilder {
opts::linkerSwitches.end());
}
void addArch() override {}
void addTargetFlags() override {}
void addLdFlag(const llvm::Twine &flag) override {
args.push_back(flag.str());

View file

@ -102,45 +102,7 @@ static void assemble(const std::string &asmpath, const std::string &objpath) {
args.push_back("-o");
args.push_back(objpath);
// Only specify -m32/-m64 for architectures where the two variants actually
// exist (as e.g. the GCC ARM toolchain doesn't recognize the switches).
// MIPS does not have -m32/-m64 but requires -mabi=.
if (global.params.targetTriple->get64BitArchVariant().getArch() !=
llvm::Triple::UnknownArch &&
global.params.targetTriple->get32BitArchVariant().getArch() !=
llvm::Triple::UnknownArch) {
if (global.params.targetTriple->get64BitArchVariant().getArch() ==
llvm::Triple::mips64 ||
global.params.targetTriple->get64BitArchVariant().getArch() ==
llvm::Triple::mips64el) {
switch (getMipsABI()) {
case MipsABI::EABI:
args.push_back("-mabi=eabi");
args.push_back("-march=mips32r2");
break;
case MipsABI::O32:
args.push_back("-mabi=32");
args.push_back("-march=mips32r2");
break;
case MipsABI::N32:
args.push_back("-mabi=n32");
args.push_back("-march=mips64r2");
break;
case MipsABI::N64:
args.push_back("-mabi=64");
args.push_back("-march=mips64r2");
break;
case MipsABI::Unknown:
break;
}
} else {
if (global.params.is64bit) {
args.push_back("-m64");
} else {
args.push_back("-m32");
}
}
}
appendTargetArgsForGcc(args);
// Run the compiler to assembly the program.
int R = executeToolAndWait(getGcc(), args, global.params.verbose);

View file

@ -10,6 +10,7 @@
#include "driver/tool.h"
#include "mars.h"
#include "driver/exe_path.h"
#include "driver/targetmachine.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
@ -70,6 +71,51 @@ std::string getGcc() {
#endif
}
////////////////////////////////////////////////////////////////////////////////
void appendTargetArgsForGcc(std::vector<std::string> &args) {
using llvm::Triple;
const auto &triple = *global.params.targetTriple;
const auto arch64 = triple.get64BitArchVariant().getArch();
const auto arch32 = triple.get32BitArchVariant().getArch();
// Only specify -m32/-m64 for architectures where the two variants actually
// exist (as e.g. the GCC ARM toolchain doesn't recognize the switches).
if (arch64 == Triple::UnknownArch || arch32 == Triple::UnknownArch ||
arch64 == Triple::aarch64 || arch64 == Triple::aarch64_be) {
return;
}
// MIPS does not have -m32/-m64 but requires -mabi=.
if (arch64 == Triple::mips64 || arch64 == Triple::mips64el) {
switch (getMipsABI()) {
case MipsABI::EABI:
args.push_back("-mabi=eabi");
args.push_back("-march=mips32r2");
break;
case MipsABI::O32:
args.push_back("-mabi=32");
args.push_back("-march=mips32r2");
break;
case MipsABI::N32:
args.push_back("-mabi=n32");
args.push_back("-march=mips64r2");
break;
case MipsABI::N64:
args.push_back("-mabi=64");
args.push_back("-march=mips64r2");
break;
case MipsABI::Unknown:
break;
}
return;
}
args.push_back(triple.isArch64Bit() ? "-m64" : "-m32");
}
//////////////////////////////////////////////////////////////////////////////
void createDirectoryForFileOrFail(llvm::StringRef fileName) {

View file

@ -21,6 +21,7 @@
#include "llvm/Support/CommandLine.h"
std::string getGcc();
void appendTargetArgsForGcc(std::vector<std::string> &args);
std::string getProgram(const char *name,
const llvm::cl::opt<std::string> *opt = nullptr,

View file

@ -954,7 +954,8 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
if (gABI->needsUnwindTables()) {
func->addFnAttr(LLAttribute::UWTable);
}
if (opts::isAnySanitizerEnabled()) {
if (opts::isAnySanitizerEnabled() &&
!opts::functionIsInSanitizerBlacklist(fd)) {
// Set the required sanitizer attribute.
if (opts::isSanitizerEnabled(opts::AddressSanitizer)) {
func->addFnAttr(LLAttribute::SanitizeAddress);
@ -997,14 +998,21 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
emitInstrumentationFnEnter(fd);
// this hack makes sure the frame pointer elimination optimization is
// disabled.
// this this eliminates a bunch of inline asm related issues.
// disable frame-pointer-elimination for functions with inline asm
if (fd->hasReturnExp & 8) // has inline asm
{
// emit a call to llvm_eh_unwind_init
#if LDC_LLVM_VER >= 309
func->addAttribute(
LLAttributeSet::FunctionIndex,
llvm::Attribute::get(gIR->context(), "no-frame-pointer-elim", "true"));
func->addAttribute(
LLAttributeSet::FunctionIndex,
llvm::Attribute::get(gIR->context(), "no-frame-pointer-elim-non-leaf"));
#else
// hack: emit a call to llvm_eh_unwind_init
LLFunction *hack = GET_INTRINSIC_DECL(eh_unwind_init);
gIR->ir->CreateCall(hack, {});
#endif
}
// give the 'this' parameter (an lvalue) storage and debug info

View file

@ -1302,42 +1302,6 @@ void DtoSetFuncDeclIntrinsicName(TemplateInstance *ti, TemplateDeclaration *td,
////////////////////////////////////////////////////////////////////////////////
bool hasUnalignedFields(Type *t) {
t = t->toBasetype();
if (t->ty == Tsarray) {
assert(t->nextOf()->size() % t->nextOf()->alignsize() == 0);
return hasUnalignedFields(t->nextOf());
}
if (t->ty != Tstruct) {
return false;
}
TypeStruct *ts = static_cast<TypeStruct *>(t);
if (ts->unaligned) {
return (ts->unaligned == 2);
}
StructDeclaration *sym = ts->sym;
// go through all the fields and try to find something unaligned
ts->unaligned = 2;
for (unsigned i = 0; i < sym->fields.dim; i++) {
VarDeclaration *f = static_cast<VarDeclaration *>(sym->fields.data[i]);
unsigned a = f->type->alignsize() - 1;
if (((f->offset + a) & ~a) != f->offset) {
return true;
}
if (f->type->toBasetype()->ty == Tstruct && hasUnalignedFields(f->type)) {
return true;
}
}
ts->unaligned = 1;
return false;
}
////////////////////////////////////////////////////////////////////////////////
size_t getMemberSize(Type *type) {
const dinteger_t dSize = type->size();
llvm::Type *const llType = DtoType(type);

View file

@ -127,9 +127,6 @@ LLConstant *DtoTypeInfoOf(Type *ty, bool base = true);
// target stuff
void findDefaultTarget();
/// Returns true if there is any unaligned type inside the aggregate.
bool hasUnalignedFields(Type *t);
/// Returns a pointer to the given member field of an aggregate.
///
/// 'src' is a pointer to the start of the memory of an 'ad' instance.

View file

@ -203,16 +203,24 @@ IrTypeAggr::IrTypeAggr(AggregateDeclaration *ad)
aggr(ad) {}
bool IrTypeAggr::isPacked(AggregateDeclaration *ad) {
if (ad->isUnionDeclaration()) {
return true;
}
for (unsigned i = 0; i < ad->fields.dim; i++) {
VarDeclaration *vd = static_cast<VarDeclaration *>(ad->fields.data[i]);
unsigned a = vd->type->alignsize() - 1;
if (((vd->offset + a) & ~a) != vd->offset) {
const auto aggregateSize = (ad->sizeok == SIZEOKdone ? ad->structsize : ~0u);
// For unions, only a subset of the fields are actually used for the IR type -
// don't care.
for (const auto field : ad->fields) {
// The aggregate's size and the field offset need to be multiples of the
// field's natural alignment, otherwise the aggregate type is unnaturally
// aligned, and LLVM would insert padding.
const auto naturalFieldAlignment = field->type->alignsize();
const auto mask = naturalFieldAlignment - 1;
// If the aggregate's size is unknown, any field with natural alignment > 1
// will make it packed.
if ((aggregateSize & mask) != 0 || (field->offset & mask) != 0) {
return true;
}
}
return false;
}

View file

@ -45,12 +45,7 @@ IrTypeStruct *IrTypeStruct::get(StructDeclaration *sd) {
return t;
}
t->packed = sd->alignment == 1;
if (!t->packed) {
// Unfortunately, the previous check is not enough in case the struct
// contains an align declaration. See issue 726.
t->packed = isPacked(sd);
}
// For ldc.dcomptetypes.Pointer!(uint n,T),
// emit { T addrspace(gIR->dcomputetarget->mapping[n])* }

View file

@ -10,6 +10,17 @@ if(NOT LDC_EXE)
if(NOT DEFINED D_VERSION OR NOT DEFINED DMDFE_MINOR_VERSION OR NOT DEFINED DMDFE_PATCH_VERSION)
message(FATAL_ERROR "Please define the CMake variables D_VERSION, DMDFE_MINOR_VERSION and DMDFE_PATCH_VERSION.")
endif()
# Helper function
function(append value)
foreach(variable ${ARGN})
if(${variable} STREQUAL "")
set(${variable} "${value}" PARENT_SCOPE)
else()
set(${variable} "${${variable}} ${value}" PARENT_SCOPE)
endif()
endforeach(variable)
endfunction()
endif()
#
@ -22,11 +33,13 @@ set(MULTILIB OFF CACHE BOOL "Buil
set(BUILD_BC_LIBS OFF CACHE BOOL "Build the runtime as LLVM bitcode libraries")
set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/include/d CACHE PATH "Path to install D modules to")
set(BUILD_SHARED_LIBS AUTO CACHE STRING "Whether to build the runtime as a shared library (ON|OFF|BOTH)")
set(D_FLAGS -w CACHE STRING "Runtime build flags, separated by ;")
set(D_FLAGS_DEBUG -g;-link-debuglib CACHE STRING "Runtime build flags (debug libraries), separated by ;")
set(D_FLAGS_RELEASE -O3;-release CACHE STRING "Runtime build flags (release libraries), separated by ;")
set(D_FLAGS -w CACHE STRING "Runtime D compiler flags, separated by ';'")
set(D_FLAGS_DEBUG -g;-link-debuglib CACHE STRING "Runtime D compiler flags (debug libraries), separated by ';'")
set(D_FLAGS_RELEASE -O3;-release CACHE STRING "Runtime D compiler flags (release libraries), separated by ';'")
set(COMPILE_ALL_D_FILES_AT_ONCE ON CACHE BOOL "Compile all D files for a lib in a single command line instead of separately")
set(C_SYSTEM_LIBS AUTO CACHE STRING "C system libraries for linking shared libraries and test runners, separated by ;")
set(RT_CFLAGS "" CACHE STRING "Runtime extra C compiler flags, separated by ' '")
set(LD_FLAGS "" CACHE STRING "Runtime extra C linker flags, separated by ' '")
set(C_SYSTEM_LIBS AUTO CACHE STRING "C system libraries for linking shared libraries and test runners, separated by ';'")
set(TARGET_SYSTEM AUTO CACHE STRING "Targeted platform for cross-compilation (e.g., 'Linux;UNIX', 'Darwin;APPLE;UNIX', 'Windows;MSVC')")
set(CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX})
@ -46,6 +59,12 @@ if("${TARGET_SYSTEM}" STREQUAL "AUTO")
endif()
endif()
if("${TARGET_SYSTEM}" MATCHES "UNIX")
ENABLE_LANGUAGE(ASM)
elseif("${TARGET_SYSTEM}" MATCHES "MSVC")
ENABLE_LANGUAGE(ASM_MASM)
endif()
include(CheckTypeSize)
check_type_size(void* ptr_size)
if(${ptr_size} MATCHES "^8$") ## if it's 64-bit OS
@ -241,7 +260,7 @@ if(LDC_EXE)
endif()
configure_file(${PROJECT_PARENT_DIR}/${CONFIG_NAME}.conf.in ${PROJECT_BINARY_DIR}/../bin/${LDC_EXE}.conf @ONLY)
configure_file(${PROJECT_PARENT_DIR}/${LDC_EXE}_install.conf.in ${PROJECT_BINARY_DIR}/../bin/${LDC_EXE}_install.conf @ONLY)
configure_file(${PROJECT_SOURCE_DIR}/build-ldc-runtime.sh.in ${PROJECT_BINARY_DIR}/../bin/build-ldc-runtime.sh @ONLY)
configure_file(${PROJECT_SOURCE_DIR}/ldc-build-runtime.d.in ${PROJECT_BINARY_DIR}/../ldc-build-runtime.d @ONLY)
endif()
#
@ -585,8 +604,6 @@ include(profile-rt/DefineBuildProfileRT.cmake)
# Set up build and install targets
#
set(RT_CFLAGS "")
if(MULTILIB AND "${TARGET_SYSTEM}" MATCHES "APPLE")
# On OS X, build "fat" libraries containing code for both architectures.
@ -675,13 +692,13 @@ install(FILES ${GCCBUILTINS} DESTINATION ${INCLUDE_INSTALL_DIR}/ldc)
# link the test runners against those. Some linker command-line magic is
# required to make sure all objects are pulled in.
macro(append_testrunner_linkflags lib name_suffix path_suffix target_suffix is_shared output_flags)
macro(append_testrunner_linkflags libname path_suffix is_shared output_flags)
# (Re)set variable 'tested_lib_path', initialize to directory containing the tested lib.
# It'll contain the full path to the linked-in library when 'returning' to calling build_test_runners().
set(tested_lib_path "${CMAKE_BINARY_DIR}/lib${path_suffix}")
if("${TARGET_SYSTEM}" MATCHES "MSVC")
set(tested_lib_path "${tested_lib_path}/${lib}${name_suffix}.lib")
set(tested_lib_path "${tested_lib_path}/${libname}.lib")
if("${is_shared}" STREQUAL "ON")
append("${tested_lib_path}" ${output_flags})
append("msvcrt.lib vcruntime.lib" ${output_flags})
@ -694,14 +711,14 @@ macro(append_testrunner_linkflags lib name_suffix path_suffix target_suffix is_s
if("${is_shared}" STREQUAL "ON")
append("-Wl,-rpath,${tested_lib_path}" ${output_flags})
if("${TARGET_SYSTEM}" MATCHES "APPLE")
set(tested_lib_path "${tested_lib_path}/lib${lib}${name_suffix}.dylib")
set(tested_lib_path "${tested_lib_path}/lib${libname}.dylib")
append("${tested_lib_path}" ${output_flags})
else()
set(tested_lib_path "${tested_lib_path}/lib${lib}${name_suffix}.so")
set(tested_lib_path "${tested_lib_path}/lib${libname}.so")
append("-Wl,--no-as-needed,${tested_lib_path},--as-needed" ${output_flags})
endif()
else()
set(tested_lib_path "${tested_lib_path}/lib${lib}${name_suffix}.a")
set(tested_lib_path "${tested_lib_path}/lib${libname}.a")
if("${TARGET_SYSTEM}" MATCHES "APPLE")
append("-Wl,-force_load,${tested_lib_path}" ${output_flags})
else()
@ -714,11 +731,12 @@ macro(append_testrunner_linkflags lib name_suffix path_suffix target_suffix is_s
endif()
endmacro()
set(_GLOBAL_TESTRUNNERS "" CACHE INTERNAL "List all test runner build targets")
set(_GLOBAL_TESTRUNNERS "" CACHE INTERNAL "List of all test runner build targets")
file(WRITE ${PROJECT_BINARY_DIR}/dummy.c "")
# Generates targets for a pair of druntime/Phobos test runners.
# The build targets are also appended to the _GLOBAL_TESTRUNNERS list.
function(build_test_runners name_suffix path_suffix d_flags linkflags is_shared)
function(build_test_runners name_suffix path_suffix d_flags c_flags linkflags is_shared)
set(target_suffix)
get_target_suffix("${name_suffix}" "${path_suffix}" target_suffix)
@ -732,31 +750,32 @@ function(build_test_runners name_suffix path_suffix d_flags linkflags is_shared)
test_runner_o
test_runner_bc
)
add_custom_target(test_runner${target_suffix} DEPENDS ${test_runner_o})
set(druntime_name druntime-test-runner${target_suffix})
add_executable(${druntime_name} EXCLUDE_FROM_ALL ${test_runner_o})
set(full_linkflags ${linkflags})
append_testrunner_linkflags("druntime-ldc-unittest" "${name_suffix}" "${path_suffix}" "${target_suffix}" "${is_shared}" full_linkflags)
add_dependencies(${druntime_name} druntime-ldc-unittest${target_suffix})
add_executable(${druntime_name} EXCLUDE_FROM_ALL ${PROJECT_BINARY_DIR}/dummy.c)
set(full_linkflags "${test_runner_o} ${linkflags}")
append_testrunner_linkflags("druntime-ldc-unittest${name_suffix}" "${path_suffix}" "${is_shared}" full_linkflags)
add_dependencies(${druntime_name} test_runner${target_suffix} druntime-ldc-unittest${target_suffix})
set_target_properties(${druntime_name} PROPERTIES
LINKER_LANGUAGE C
COMPILE_FLAGS ${c_flags}
LINK_FLAGS ${full_linkflags}
LINK_DEPENDS ${tested_lib_path}
LINK_DEPENDS "${test_runner_o};${tested_lib_path}"
)
add_test(build-${druntime_name} "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target ${druntime_name})
set(_GLOBAL_TESTRUNNERS "${_GLOBAL_TESTRUNNERS};${druntime_name}" CACHE INTERNAL "")
if(PHOBOS2_DIR)
set(phobos_name phobos2-test-runner${target_suffix})
add_executable(${phobos_name} EXCLUDE_FROM_ALL ${test_runner_o})
add_executable(${phobos_name} EXCLUDE_FROM_ALL ${PROJECT_BINARY_DIR}/dummy.c)
target_link_libraries(${phobos_name} druntime-ldc-unittest${target_suffix})
set(full_linkflags ${linkflags})
append_testrunner_linkflags("phobos2-ldc-unittest" "${name_suffix}" "${path_suffix}" "${target_suffix}" "${is_shared}" full_linkflags)
add_dependencies(${phobos_name} phobos2-ldc-unittest${target_suffix})
set(full_linkflags "${test_runner_o} ${linkflags}")
append_testrunner_linkflags("phobos2-ldc-unittest${name_suffix}" "${path_suffix}" "${is_shared}" full_linkflags)
add_dependencies(${phobos_name} test_runner${target_suffix} phobos2-ldc-unittest${target_suffix})
set_target_properties(${phobos_name} PROPERTIES
LINKER_LANGUAGE C
COMPILE_FLAGS ${c_flags}
LINK_FLAGS ${full_linkflags}
LINK_DEPENDS ${tested_lib_path}
LINK_DEPENDS "${test_runner_o};${tested_lib_path}"
)
add_test(build-${phobos_name} "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target ${phobos_name})
set(_GLOBAL_TESTRUNNERS "${_GLOBAL_TESTRUNNERS};${phobos_name}" CACHE INTERNAL "")
@ -766,6 +785,7 @@ endfunction()
# Generates targets for static and/or shared pairs of druntime/Phobos test runners.
function(build_test_runner_variant name_suffix path_suffix d_flags c_flags)
set(full_d_flags ${D_FLAGS} ${d_flags} -unittest)
set(full_c_flags "${RT_CFLAGS} ${c_flags}")
set(linkflags "${LD_FLAGS} ${c_flags}")
if("${TARGET_SYSTEM}" MATCHES "MSVC")
# enforce identical COMDAT folding, apparently needed for std.variant
@ -776,7 +796,7 @@ function(build_test_runner_variant name_suffix path_suffix d_flags c_flags)
set(unittest_libs "")
build_runtime_variant(
"${full_d_flags}"
"${RT_CFLAGS} ${c_flags}"
"${full_c_flags}"
"${linkflags}"
"-unittest${name_suffix}"
"${path_suffix}"
@ -789,11 +809,11 @@ function(build_test_runner_variant name_suffix path_suffix d_flags c_flags)
# static druntime/Phobos test runners
if(NOT ${BUILD_SHARED_LIBS} STREQUAL "ON")
build_test_runners("${name_suffix}" "${path_suffix}" "${full_d_flags}" "${linkflags}" "OFF")
build_test_runners("${name_suffix}" "${path_suffix}" "${full_d_flags}" "${full_c_flags}" "${linkflags}" "OFF")
endif()
# shared druntime/Phobos test runners
if(NOT ${BUILD_SHARED_LIBS} STREQUAL "OFF")
build_test_runners("${name_suffix}${SHARED_LIB_SUFFIX}" "${path_suffix}" "${full_d_flags}" "${linkflags}" "ON")
build_test_runners("${name_suffix}${SHARED_LIB_SUFFIX}" "${path_suffix}" "${full_d_flags}" "${full_c_flags}" "${linkflags}" "ON")
endif()
endfunction()

View file

@ -1,58 +0,0 @@
#!/bin/bash
set -eo pipefail
# Use LDC executable in the same directory as this script.
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
LDC_EXE="$DIR/ldc2"
if [ ! -e "$LDC_EXE" ]; then
echo "Aborting: LDC executable '$LDC_EXE' not found."
exit 1
fi
# Use environment variable LDC_SRC_DIR to use an existing LDC source tree.
if [ ! -z "$LDC_SRC_DIR" ]; then
if [ ! -d "$LDC_SRC_DIR" ]; then
echo "Aborting: LDC source directory '$LDC_SRC_DIR' not found."
exit 1
fi
LDC_SRC_DIR="$( cd "$LDC_SRC_DIR" && pwd )"
fi
# Set up build directory, using environment variable BUILD_DIR if set.
if [ -z "$BUILD_DIR" ]; then
BUILD_DIR="build-ldc-runtime.tmp"
fi
if [ -d "$BUILD_DIR" ]; then
echo "WARNING: build directory '$BUILD_DIR' already exists."
else
mkdir "$BUILD_DIR"
fi
set -x
cd "$BUILD_DIR"
if [ -z "$LDC_SRC_DIR" ]; then
LDC_SRC_DIR=ldc-src
# Download & extract LDC source archive if the directory doesn't exist yet.
if [ ! -d "$LDC_SRC_DIR" ]; then
wget -O ldc-src.tar.gz https://github.com/ldc-developers/ldc/releases/download/v@LDC_VERSION@/ldc-@LDC_VERSION@-src.tar.gz
mkdir "$LDC_SRC_DIR"
tar -xzf ldc-src.tar.gz --strip 1 -C "$LDC_SRC_DIR"
fi
fi
# Forward all script args to the CMake command line.
cmake "-DLDC_EXE_FULL=$LDC_EXE" -DD_VERSION=@D_VERSION@ \
-DDMDFE_MINOR_VERSION=@DMDFE_MINOR_VERSION@ \
-DDMDFE_PATCH_VERSION=@DMDFE_PATCH_VERSION@ "$@" "$LDC_SRC_DIR/runtime"
# Build.
if [ -z "$MAKE_ARGS" ]; then
MAKE_ARGS=-j4
echo "Environment variable MAKE_ARGS not set, defaulting to '$MAKE_ARGS'."
fi
make $MAKE_ARGS
echo "Runtime libraries built successfully into '$BUILD_DIR'."

@ -1 +1 @@
Subproject commit 6f48308009cd52fe1956d5c89cc6f15c0baa0dee
Subproject commit d6ad1b9dd51ceac6299c0e0c828b392c74a24d8e

View file

@ -0,0 +1,247 @@
module ldcBuildRuntime;
import core.stdc.stdlib : exit;
import std.file;
import std.path;
import std.stdio;
struct Config {
string ldcExecutable;
string buildDir;
bool resetBuildDir;
string ldcSourceDir;
bool ninja;
bool buildTestrunners;
string[] dFlags;
string[] cFlags;
string[] linkerFlags;
uint numBuildJobs;
string[string] cmakeVars;
}
string defaultLdcExecutable;
Config config;
int main(string[] args) {
version(Windows)
enum exeName = "ldc2.exe";
else
enum exeName = "ldc2";
defaultLdcExecutable = buildPath(thisExePath.dirName, exeName);
parseCommandLine(args);
findLdcExecutable();
prepareBuildDir();
prepareLdcSource();
runCMake();
build();
writefln("Runtime libraries built successfully into: %s", config.buildDir);
return 0;
}
void findLdcExecutable() {
if (config.ldcExecutable !is null) {
if (!config.ldcExecutable.exists) {
writefln("Error: LDC executable not found: %s", config.ldcExecutable);
exit(1);
}
config.ldcExecutable = config.ldcExecutable.absolutePath;
return;
}
if (defaultLdcExecutable.exists) {
config.ldcExecutable = defaultLdcExecutable;
return;
}
writeln("Please specify LDC executable via '--ldc=<path/to/ldc2[.exe]>'. Aborting.");
exit(1);
}
void prepareBuildDir() {
if (config.buildDir is null)
config.buildDir = "ldc-build-runtime.tmp";
if (config.buildDir.exists) {
if (!config.resetBuildDir) {
writefln("Warning: build directory already exists: %s", config.buildDir);
} else {
writefln("Resetting build directory: %s", config.buildDir);
import std.array : array;
auto items = dirEntries(config.buildDir, SpanMode.shallow, false).array;
const ldcSrc = buildPath(config.buildDir, "ldc-src");
foreach (i; items) {
if (i.isFile) {
remove(i.name);
} else if (i.isDir && i.name != ldcSrc) {
rmdirRecurse(i.name);
}
}
}
} else {
writefln("Creating build directory: %s", config.buildDir);
mkdirRecurse(config.buildDir);
}
config.buildDir = config.buildDir.absolutePath;
}
void prepareLdcSource() {
if (config.ldcSourceDir !is null) {
if (!config.ldcSourceDir.exists) {
writefln("Error: LDC source directory not found: %s", config.ldcSourceDir);
exit(1);
}
config.ldcSourceDir = config.ldcSourceDir.absolutePath;
return;
}
const ldcSrc = "ldc-src";
config.ldcSourceDir = buildPath(config.buildDir, ldcSrc);
if (buildPath(config.ldcSourceDir, "runtime").exists)
return;
// Download & extract LDC source archive if <buildDir>/ldc-src/runtime doesn't exist yet.
const wd = WorkingDirScope(config.buildDir);
auto ldcVersion = "@LDC_VERSION@";
void removeVersionSuffix(string beginning) {
import std.string : indexOf;
const suffixIndex = ldcVersion.indexOf(beginning);
if (suffixIndex > 0)
ldcVersion = ldcVersion[0 .. suffixIndex];
}
removeVersionSuffix("git-");
removeVersionSuffix("-dirty");
const localArchiveFile = "ldc-src.tar.gz";
if (!localArchiveFile.exists) {
import std.format : format;
const url = "https://github.com/ldc-developers/ldc/releases/download/v%1$s/ldc-%1$s-src.tar.gz".format(ldcVersion);
writefln("Downloading LDC source archive: %s", url);
import std.net.curl : download;
download(url, localArchiveFile);
if (getSize(localArchiveFile) < 1_048_576) {
writefln("Error: downloaded file is corrupt; has LDC v%s been released?", ldcVersion);
writefln("You can work around this by manually downloading a src package and moving it to: %s",
buildPath(config.buildDir, localArchiveFile));
localArchiveFile.remove;
exit(1);
}
}
if (!ldcSrc.exists)
mkdir(ldcSrc);
import std.array : split;
exec("tar -xzf ldc-src.tar.gz --strip 1 -C ldc-src".split);
}
void runCMake() {
import std.array : byPair, join;
const wd = WorkingDirScope(config.buildDir);
string[] args = [
"cmake",
"-DLDC_EXE_FULL=" ~ config.ldcExecutable,
"-DD_VERSION=@D_VERSION@",
"-DDMDFE_MINOR_VERSION=@DMDFE_MINOR_VERSION@",
"-DDMDFE_PATCH_VERSION=@DMDFE_PATCH_VERSION@",
"-DD_FLAGS=" ~ config.dFlags.join(";"),
"-DRT_CFLAGS=" ~ config.cFlags.join(" "),
"-DLD_FLAGS=" ~ config.linkerFlags.join(" "),
];
foreach (pair; config.cmakeVars.byPair)
args ~= "-D" ~ pair[0] ~ '=' ~ pair[1];
if (config.ninja)
args ~= [ "-G", "Ninja" ];
args ~= buildPath(config.ldcSourceDir, "runtime");
exec(args);
}
void build() {
const wd = WorkingDirScope(config.buildDir);
string[] args = [ config.ninja ? "ninja" : "make" ];
if (config.numBuildJobs != 0) {
import std.conv : to;
args ~= "-j" ~ config.numBuildJobs.to!string;
}
args ~= "all";
if (config.buildTestrunners)
args ~= "all-test-runners";
exec(args);
}
/*** helpers ***/
struct WorkingDirScope {
string originalPath;
this(string path) { originalPath = getcwd(); chdir(path); }
~this() { chdir(originalPath); }
}
void exec(string[] command ...) {
writeln("Invoking: ", command);
import std.process;
auto pid = spawnProcess(command);
const exitStatus = wait(pid);
if (exitStatus != 0) {
writeln("Error: command failed with status ", exitStatus);
exit(1);
}
}
void parseCommandLine(string[] args) {
import std.getopt : arraySep, getopt, defaultGetoptPrinter;
arraySep = ";";
auto helpInformation = getopt(
args,
"ldc", "Path to LDC executable (default: '" ~ defaultLdcExecutable ~ "')", &config.ldcExecutable,
"buildDir", "Path to build directory (default: './ldc-build-runtime.tmp')", &config.buildDir,
"reset", "If build directory exists, start with removing everything but the ldc-src subdirectory", &config.resetBuildDir,
"ldcSrcDir", "Path to LDC source directory (if not specified: downloads & extracts source archive into '<buildDir>/ldc-src')", &config.ldcSourceDir,
"ninja", "Use Ninja as CMake build system", &config.ninja,
"testrunners", "Build the testrunner executables too", &config.buildTestrunners,
"dFlags", "LDC flags for the D modules (separated by ';')", &config.dFlags,
"cFlags", "C/ASM compiler flags for the handful of C/ASM files (separated by ';')", &config.cFlags,
"linkerFlags", "C linker flags for shared libraries and testrunner executables (separated by ';')", &config.linkerFlags,
"j", "Number of parallel build jobs", &config.numBuildJobs
);
// getopt() removed all consumed args from `args`
import std.range : drop;
foreach (arg; args.drop(1)) {
import std.algorithm.searching : findSplit;
const r = arg.findSplit("=");
if (r[1].length == 0) {
helpInformation.helpWanted = true;
break;
}
config.cmakeVars[r[0]] = r[2];
}
if (helpInformation.helpWanted) {
defaultGetoptPrinter(
"Builds the LDC runtime libraries.\n" ~
"Programs required to be found in your PATH:\n" ~
" * CMake\n" ~
" * either Make or Ninja (recommended, enable with '--ninja')\n" ~
" * C toolchain (compiler and linker)\n" ~
" * tar (can be worked around via '--ldcSrcDir=path/to/src')\n" ~
"All arguments are optional.\n" ~
"CMake variables (see runtime/CMakeLists.txt in LDC source) can be specified via arguments like 'VAR=value'.\n",
helpInformation.options
);
exit(1);
}
}

@ -1 +1 @@
Subproject commit 14b5d6ef08ffa6fba50c70518cc895dc7e690e30
Subproject commit ab2907630688e8eb12d8ad305871f63a280e4969

29
tests/codegen/gh2235.d Normal file
View file

@ -0,0 +1,29 @@
// RUN: %ldc -output-ll -of=%t.ll %s && FileCheck %s < %t.ll
// RUN: %ldc -run %s
// CHECK: %gh2235.Foo = type <{
align(2) struct Foo {
long y;
byte z;
}
// CHECK: %gh2235.Bar = type <{
class Bar {
union {
bool b;
Foo foo;
}
byte x;
void set(Foo f) {
x = 99;
foo = f;
}
}
void main() {
Bar bar = new Bar();
Foo f;
bar.set(f);
assert(bar.x == 99);
}

View file

@ -0,0 +1,12 @@
// RUN: %ldc -no-integrated-as %s
// We currently rely on gcc/clang; no MSVC toolchain support yet.
// UNSUPPORTED: Windows
module noIntegratedAs;
void main()
{
import std.stdio;
writeln("This object is assembled externally and linked to an executable.");
}

View file

@ -0,0 +1,63 @@
// Test sanitizer blacklist functionality
// RUN: %ldc -c -output-ll -fsanitize=address \
// RUN: -fsanitize-blacklist=%S/inputs/fsanitize_blacklist.txt \
// RUN: -fsanitize-blacklist=%S/inputs/fsanitize_blacklist2.txt \
// RUN: -of=%t.ll %s && FileCheck %s < %t.ll
// Don't attempt to load the blacklist when no sanitizer is active
// RUN: %ldc -o- -fsanitize-blacklist=%S/thisfilecertainlydoesnotexist %s
// CHECK-LABEL: define {{.*}}9foofoofoo
// CHECK-SAME: #[[ATTR_WITHASAN:[0-9]+]]
void foofoofoo(int* i)
{
// CHECK: call {{.*}}_asan
*i = 1;
}
// CHECK-LABEL: define {{.*}}blacklisted
// CHECK-SAME: #[[ATTR_NOASAN:[0-9]+]]
extern (C) void blacklisted(int* i)
{
// CHECK-NOT: call {{.*}}_asan
*i = 1;
}
// Test blacklisted wildcard
// CHECK-LABEL: define {{.*}}10black_set1
// CHECK-SAME: #[[ATTR_NOASAN:[0-9]+]]
void black_set1(int* i)
{
// CHECK-NOT: call {{.*}}_asan
*i = 1;
}
// CHECK-LABEL: define {{.*}}10black_set2
// CHECK-SAME: #[[ATTR_NOASAN:[0-9]+]]
void black_set2(int* i)
{
// CHECK-NOT: call {{.*}}_asan
*i = 1;
}
// Test blacklisting of template class methods
class ABCDEF(T)
{
void method(int* i)
{
*i = 1;
}
}
// CHECK-LABEL: define {{.*}}TiZ6ABCDEF6method
// CHECK-SAME: #[[ATTR_NOASAN:[0-9]+]]
ABCDEF!int ofBlacklistedType;
// CHECK-LABEL: define {{.*}}TAyaZ6ABCDEF6method
// CHECK-SAME: #[[ATTR_WITHASAN:[0-9]+]]
ABCDEF!string ofInstrumentedType;
//CHECK: attributes #[[ATTR_WITHASAN]] ={{.*}}sanitize_address
//CHECK: attributes #[[ATTR_NOASAN]]
//CHECK-NOT: sanitize_address
//CHECK-SAME: }

View file

@ -0,0 +1,13 @@
# Blacklist for the sanitizers. Turns off instrumentation of particular
# functions or sources. Use with care. You may set location of blacklist
# at compile-time using -fsanitize-blacklist=<path> flag.
# Example usage:
# fun:*bad_function_name*
# src:file_with_tricky_code.cc
# global:*global_with_bad_access_or_initialization*
# global:*global_with_initialization_issues*=init
# type:*Namespace::ClassName*=init
fun:blacklisted
fun:*black_set*

View file

@ -0,0 +1 @@
fun:_D*TiZ6ABCDEF6method*