Merge branch 'master' into merge-2.075

Conflicts:
	runtime/druntime
This commit is contained in:
Martin 2017-10-01 18:28:44 +02:00
commit d7f68dbeb3
28 changed files with 489 additions and 261 deletions

View file

@ -58,7 +58,7 @@ jobs:
export HOST_LDMD=$PWD/ldc2-$HOST_LDC_VERSION-linux-x86_64/bin/ldmd2 export HOST_LDMD=$PWD/ldc2-$HOST_LDC_VERSION-linux-x86_64/bin/ldmd2
mkdir bootstrap mkdir bootstrap
cd bootstrap cd bootstrap
cmake -G Ninja -DLDC_WITH_LLD=OFF -DLLVM_ROOT_DIR=$PWD/../llvm-$LLVM_VERSION -DBUILD_SHARED_LIBS=OFF -DD_COMPILER=$HOST_LDMD .. cmake -G Ninja -DLLVM_ROOT_DIR=$PWD/../llvm-$LLVM_VERSION -DBUILD_SHARED_LIBS=OFF -DD_COMPILER=$HOST_LDMD ..
ninja -j3 ninja -j3
bin/ldc2 -version bin/ldc2 -version
cd .. cd ..
@ -68,7 +68,7 @@ jobs:
export HOST_LDMD=$PWD/bootstrap/bin/ldmd2 export HOST_LDMD=$PWD/bootstrap/bin/ldmd2
mkdir build mkdir build
cd build cd build
cmake -G Ninja -DLDC_WITH_LLD=OFF -DLLVM_ROOT_DIR=$PWD/../llvm-$LLVM_VERSION -DLDC_INSTALL_LTOPLUGIN=ON -DLDC_INSTALL_LLVM_RUNTIME_LIBS=ON -DD_COMPILER=$HOST_LDMD .. cmake -G Ninja -DLLVM_ROOT_DIR=$PWD/../llvm-$LLVM_VERSION -DLDC_INSTALL_LTOPLUGIN=ON -DLDC_INSTALL_LLVM_RUNTIME_LIBS=ON -DD_COMPILER=$HOST_LDMD ..
ninja -j3 all all-test-runners ninja -j3 all all-test-runners
bin/ldc2 -version bin/ldc2 -version
cd .. cd ..

View file

@ -6,7 +6,7 @@ matrix:
include: include:
- os: linux - os: linux
d: ldc d: ldc
env: LLVM_VERSION=5.0.0 OPTS="-DLIB_SUFFIX=64 -DLDC_WITH_LLD=OFF" env: LLVM_VERSION=5.0.0 OPTS="-DLIB_SUFFIX=64"
- os: linux - os: linux
d: ldc d: ldc
env: LLVM_VERSION=4.0.1 OPTS="-DLIB_SUFFIX=64" env: LLVM_VERSION=4.0.1 OPTS="-DLIB_SUFFIX=64"
@ -21,7 +21,7 @@ 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-2 OPTS="-DBUILD_SHARED_LIBS=OFF" LLVM_SPIRV_AVAILABLE=ON env: LLVM_VERSION=6.0.0-4 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"
@ -30,7 +30,7 @@ matrix:
cache: cache:
directories: directories:
- llvm-spirv-6.0.0-2 - llvm-spirv-6.0.0-4
- llvm-5.0.0 - llvm-5.0.0
- llvm-4.0.1 - llvm-4.0.1
- llvm-4.0.0 - llvm-4.0.0
@ -60,7 +60,7 @@ before_install:
fi; fi;
if [ -z "$(ls -A llvm-$LLVM_VERSION)" ]; then if [ -z "$(ls -A llvm-$LLVM_VERSION)" ]; then
if [ -n "${LLVM_SPIRV_AVAILABLE}" ]; then if [ -n "${LLVM_SPIRV_AVAILABLE}" ]; then
wget -O llvm-spirv-$LLVM_VERSION.tar.bz2 https://github.com/thewilsonator/llvm/releases/download/pre-intrinsics/LLVM-6.0.0svn-Darwin.tar.bz2; wget -O llvm-spirv-$LLVM_VERSION.tar.bz2 https://github.com/thewilsonator/llvm/releases/download/pre-intrinsics/LLVM-6.0.0svn-Darwin-2.tar.bz2;
mkdir llvm-spirv-$LLVM_VERSION; mkdir llvm-spirv-$LLVM_VERSION;
tar -xjf llvm-spirv-$LLVM_VERSION.tar.bz2 --strip 1 -C llvm-spirv-$LLVM_VERSION; tar -xjf llvm-spirv-$LLVM_VERSION.tar.bz2 --strip 1 -C llvm-spirv-$LLVM_VERSION;
else else

View file

@ -339,6 +339,7 @@ set(DRV_SRC
driver/cache.cpp driver/cache.cpp
driver/cl_options.cpp driver/cl_options.cpp
driver/cl_options_sanitizers.cpp driver/cl_options_sanitizers.cpp
driver/cl_options-llvm.cpp
driver/codegenerator.cpp driver/codegenerator.cpp
driver/configfile.cpp driver/configfile.cpp
driver/dcomputecodegenerator.cpp driver/dcomputecodegenerator.cpp
@ -358,6 +359,7 @@ set(DRV_HDR
driver/cache_pruning.h driver/cache_pruning.h
driver/cl_options.h driver/cl_options.h
driver/cl_options_sanitizers.h driver/cl_options_sanitizers.h
driver/cl_options-llvm.h
driver/codegenerator.h driver/codegenerator.h
driver/configfile.h driver/configfile.h
driver/dcomputecodegenerator.h driver/dcomputecodegenerator.h
@ -475,7 +477,7 @@ endif()
# #
# Enable building with riscv-llvm, for full RISC-V support. # Enable building with riscv-llvm, for full RISC-V support.
# #
option(RISCV_LLVM_DEV, "full RISC-V support with riscv-llvm") option(RISCV_LLVM_DEV "full RISC-V support with riscv-llvm")
mark_as_advanced(RISCV_LLVM_DEV) mark_as_advanced(RISCV_LLVM_DEV)
if(RISCV_LLVM_DEV) if(RISCV_LLVM_DEV)
append("-DRISCV_LLVM_DEV" LDC_CXXFLAGS) append("-DRISCV_LLVM_DEV" LDC_CXXFLAGS)
@ -723,6 +725,16 @@ build_d_executable(
"LDMD_CXX_LIB" "LDMD_CXX_LIB"
) )
# Little helper.
function(copy_and_rename_file source_path target_path)
get_filename_component(source_name ${source_path} NAME)
get_filename_component(target_dir ${target_path} DIRECTORY)
file(MAKE_DIRECTORY ${target_dir})
# don't preserve source file permissions, see https://github.com/ldc-developers/ldc/issues/2337
file(COPY ${source_path} DESTINATION ${target_dir} NO_SOURCE_PERMISSIONS)
file(RENAME ${target_dir}/${source_name} ${target_path})
endfunction()
# #
# Locate LLVM's LTO binary and use it (LLVM >= 3.9) # Locate LLVM's LTO binary and use it (LLVM >= 3.9)
# #
@ -742,8 +754,8 @@ if (NOT (LDC_LLVM_VER LESS 309) AND LDC_INSTALL_LTOPLUGIN)
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}")
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}) copy_and_rename_file(${LLVM_LTO_BINARY} ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/${LDC_LTO_BINARY_NAME})
configure_file(${LLVM_LTO_BINARY} ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/${LDC_LTO_BINARY_NAME} COPYONLY) install(PROGRAMS ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/${LDC_LTO_BINARY_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX})
else() else()
message(STATUS "Not found: ${LLVM_LTO_BINARY}") message(STATUS "Not found: ${LLVM_LTO_BINARY}")
endif() endif()
@ -765,12 +777,12 @@ function(copy_compilerrt_lib llvm_lib_name ldc_lib_name fixup_dylib)
set(llvm_lib_path ${LLVM_LIBRARY_DIRS}/clang/${LLVM_VERSION_STRING_CROPPED}/lib/${llvm_lib_name}) set(llvm_lib_path ${LLVM_LIBRARY_DIRS}/clang/${LLVM_VERSION_STRING_CROPPED}/lib/${llvm_lib_name})
if(EXISTS ${llvm_lib_path}) if(EXISTS ${llvm_lib_path})
message(STATUS "Copying runtime library: ${llvm_lib_path} --> ${ldc_lib_name}") message(STATUS "Copying runtime library: ${llvm_lib_path} --> ${ldc_lib_name}")
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}) set(ldc_lib_path ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/${ldc_lib_name})
configure_file(${llvm_lib_path} ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/${ldc_lib_name} COPYONLY) copy_and_rename_file(${llvm_lib_path} ${ldc_lib_path})
if (fixup_dylib) if (fixup_dylib)
execute_process(COMMAND install_name_tool -id @rpath/${ldc_lib_name} ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/${ldc_lib_name}) execute_process(COMMAND install_name_tool -id @rpath/${ldc_lib_name} ${ldc_lib_path})
endif() endif()
install(FILES ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/${ldc_lib_name} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}) install(FILES ${ldc_lib_path} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX})
else() else()
message(STATUS "Not found: ${llvm_lib_path}") message(STATUS "Not found: ${llvm_lib_path}")
endif() endif()
@ -796,7 +808,7 @@ if (LDC_INSTALL_LLVM_RUNTIME_LIBS)
if(EXISTS ${LLVM_LIBFUZZER_PATH}) if(EXISTS ${LLVM_LIBFUZZER_PATH})
message(STATUS "Copying libFuzzer library: ${LLVM_LIBFUZZER_PATH} --> libFuzzer.a") message(STATUS "Copying libFuzzer library: ${LLVM_LIBFUZZER_PATH} --> libFuzzer.a")
file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}) file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX})
configure_file(${LLVM_LIBFUZZER_PATH} ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/libFuzzer.a COPYONLY) file(COPY ${LLVM_LIBFUZZER_PATH} DESTINATION ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX})
install(FILES ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/libFuzzer.a DESTINATION ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}) install(FILES ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/libFuzzer.a DESTINATION ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX})
else() else()
message(STATUS "Not found: ${LLVM_LIBFUZZER_PATH}") message(STATUS "Not found: ${LLVM_LIBFUZZER_PATH}")
@ -866,11 +878,8 @@ endif()
install(FILES ${PROJECT_BINARY_DIR}/bin/${LDC_EXE}_install.conf DESTINATION ${CONF_INST_DIR} RENAME ${LDC_EXE}.conf) install(FILES ${PROJECT_BINARY_DIR}/bin/${LDC_EXE}_install.conf DESTINATION ${CONF_INST_DIR} RENAME ${LDC_EXE}.conf)
if(MSVC) if(MSVC)
file(COPY vcbuild/ DESTINATION ${PROJECT_BINARY_DIR}/bin FILES_MATCHING PATTERN "*.bat")
install(DIRECTORY vcbuild/ DESTINATION ${CMAKE_INSTALL_PREFIX}/bin FILES_MATCHING PATTERN "*.bat") install(DIRECTORY vcbuild/ DESTINATION ${CMAKE_INSTALL_PREFIX}/bin FILES_MATCHING PATTERN "*.bat")
# Also put the VCBuild scripts in the build/bin folder, so that ${PROJECT_BINARY_DIR}/bin/ldc2 is functional.
# This is necessary for the IR tests that use ${PROJECT_BINARY_DIR}/bin/ldc2.
configure_file(vcbuild/dumpEnv.bat ${PROJECT_BINARY_DIR}/bin/dumpEnv.bat COPYONLY)
configure_file(vcbuild/msvcEnv.bat ${PROJECT_BINARY_DIR}/bin/msvcEnv.bat COPYONLY)
endif() endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
@ -884,11 +893,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
install(DIRECTORY bash_completion.d/ DESTINATION ${BASH_COMPLETION_COMPLETIONSDIR}) install(DIRECTORY bash_completion.d/ DESTINATION ${BASH_COMPLETION_COMPLETIONSDIR})
endif() endif()
# Also install LLVM's LTO binary if available
if(EXISTS ${LLVM_LTO_BINARY})
install(PROGRAMS ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX}/${LDC_LTO_BINARY_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX})
endif()
# #
# Packaging # Packaging
# #

View file

@ -2569,7 +2569,10 @@ extern (C++) abstract class Type : RootObject
} }
else if (ident == Id.__xalignof) else if (ident == Id.__xalignof)
{ {
e = new IntegerExp(loc, alignsize(), Type.tsize_t); const explicitAlignment = alignment();
const naturalAlignment = alignsize();
const actualAlignment = (explicitAlignment == STRUCTALIGN_DEFAULT ? naturalAlignment : explicitAlignment);
e = new IntegerExp(loc, actualAlignment, Type.tsize_t);
} }
else if (ident == Id._init) else if (ident == Id._init)
{ {

View file

@ -50,7 +50,7 @@ bool Symtab = true;
bool Deterministic = true; bool Deterministic = true;
bool Thin = false; bool Thin = false;
void fail(Twine Error) { outs() << "llvm-ar: " << Error << ".\n"; } void fail(Twine Error) { errs() << "llvm-ar: " << Error << ".\n"; }
void fail(std::error_code EC, std::string Context = {}) { void fail(std::error_code EC, std::string Context = {}) {
if (Context.empty()) if (Context.empty())
@ -79,6 +79,12 @@ int addMember(std::vector<NewArchiveMember> &Members, StringRef FileName,
fail(std::move(Error), FileName); fail(std::move(Error), FileName);
return 1; return 1;
} }
#if LDC_LLVM_VER >= 500
// Use the basename of the object path for the member name.
NMOrErr->MemberName = sys::path::filename(NMOrErr->MemberName);
#endif
if (Pos == -1) if (Pos == -1)
Members.push_back(std::move(*NMOrErr)); Members.push_back(std::move(*NMOrErr));
else else
@ -197,13 +203,15 @@ int performWriteOperation(object::Archive *OldArchive,
else else
Kind = getKindFromMember(NewMembers.front()); Kind = getKindFromMember(NewMembers.front());
const auto Result = auto Result =
writeArchive(ArchiveName, NewMembers, Symtab, Kind, Deterministic, Thin, writeArchive(ArchiveName, NewMembers, Symtab, Kind, Deterministic, Thin,
std::move(OldArchiveBuf)); std::move(OldArchiveBuf));
#if LDC_LLVM_VER >= 600 #if LDC_LLVM_VER >= 600
if (Result) { if (Result) {
fail("error writing '" + ArchiveName + "': " + Result.message()); handleAllErrors(std::move(Result), [](ErrorInfoBase &EIB) {
fail("error writing '" + ArchiveName + "': " + EIB.message());
});
return 1; return 1;
} }
#else #else
@ -221,7 +229,7 @@ int performWriteOperation() {
auto Buf = MemoryBuffer::getFile(ArchiveName, -1, false); auto Buf = MemoryBuffer::getFile(ArchiveName, -1, false);
std::error_code EC = Buf.getError(); std::error_code EC = Buf.getError();
if (EC && EC != errc::no_such_file_or_directory) { if (EC && EC != errc::no_such_file_or_directory) {
fail("error opening '" + ArchiveName + "': " + EC.message() + "!"); fail("error opening '" + ArchiveName + "': " + EC.message());
return 1; return 1;
} }
@ -230,9 +238,7 @@ int performWriteOperation() {
object::Archive Archive(Buf.get()->getMemBufferRef(), Err); object::Archive Archive(Buf.get()->getMemBufferRef(), Err);
EC = errorToErrorCode(std::move(Err)); EC = errorToErrorCode(std::move(Err));
if (EC) { if (EC) {
fail( fail(EC, ("error loading '" + ArchiveName + "': " + EC.message()).str());
EC,
("error loading '" + ArchiveName + "': " + EC.message() + "!").str());
return 1; return 1;
} }
return performWriteOperation(&Archive, std::move(Buf.get())); return performWriteOperation(&Archive, std::move(Buf.get()));

View file

@ -302,14 +302,18 @@ void outputIR2ObjRelevantCmdlineArgs(llvm::raw_ostream &hash_os) {
// sharing the cache). // sharing the cache).
outputOptimizationSettings(hash_os); outputOptimizationSettings(hash_os);
opts::outputSanitizerSettings(hash_os); opts::outputSanitizerSettings(hash_os);
hash_os << opts::mCPU; hash_os << opts::getCPUStr();
for (auto &attr : opts::mAttrs) { hash_os << opts::getFeaturesStr();
hash_os << attr; hash_os << opts::floatABI;
} #if LDC_LLVM_VER >= 309
hash_os << opts::mFloatABI; const auto relocModel = opts::getRelocModel();
hash_os << opts::mRelocModel; if (relocModel.hasValue())
hash_os << opts::mCodeModel; hash_os << relocModel.getValue();
hash_os << opts::disableFpElim; #else
hash_os << opts::getRelocModel();
#endif
hash_os << opts::getCodeModel();
hash_os << opts::disableFPElim();
} }
// Output to `hash_os` all environment flags that influence object code output // Output to `hash_os` all environment flags that influence object code output

View file

@ -0,0 +1,64 @@
//===-- cl_options-llvm.cpp -----------------------------------------------===//
//
// LDC the LLVM D compiler
//
// This file is distributed under the BSD-style LDC license. See the LICENSE
// file for details.
//
//===----------------------------------------------------------------------===//
#include "driver/cl_options-llvm.h"
// Pull in command-line options and helper functions from special LLVM header
// shared by multiple LLVM tools.
#include "llvm/CodeGen/CommandFlags.h"
static cl::opt<bool>
DisableRedZone("disable-red-zone", cl::ZeroOrMore,
cl::desc("Do not emit code that uses the red zone."));
// Now expose the helper functions (with static linkage) via external wrappers
// in the opts namespace, including some additional helper functions.
namespace opts {
std::string getArchStr() { return ::MArch; }
#if LDC_LLVM_VER >= 309
Optional<Reloc::Model> getRelocModel() { return ::getRelocModel(); }
#else
Reloc::Model getRelocModel() { return ::RelocModel; }
#endif
CodeModel::Model getCodeModel() { return ::CMModel; }
bool disableFPElim() { return ::DisableFPElim; }
bool disableRedZone() { return ::DisableRedZone; }
bool printTargetFeaturesHelp() {
if (MCPU == "help")
return true;
return std::any_of(MAttrs.begin(), MAttrs.end(),
[](const std::string &a) { return a == "help"; });
}
TargetOptions InitTargetOptionsFromCodeGenFlags() {
return ::InitTargetOptionsFromCodeGenFlags();
}
std::string getCPUStr() { return ::getCPUStr(); }
std::string getFeaturesStr() { return ::getFeaturesStr(); }
} // namespace opts
#if LDC_WITH_LLD && LDC_LLVM_VER >= 500
// LLD 5.0 uses the shared header too (for LTO) and exposes some wrappers in
// the lld namespace. Define them here to prevent the LLD object from being
// linked in with its conflicting command-line options.
namespace lld {
TargetOptions InitTargetOptionsFromCodeGenFlags() {
return ::InitTargetOptionsFromCodeGenFlags();
}
CodeModel::Model GetCodeModelFromCMModel() { return CMModel; }
}
#endif // LDC_WITH_LLD && LDC_LLVM_VER >= 500

36
driver/cl_options-llvm.h Normal file
View file

@ -0,0 +1,36 @@
//===-- driver/cl_options-llvm.h - LLVM command line options ----*- C++ -*-===//
//
// LDC the LLVM D compiler
//
// This file is distributed under the BSD-style LDC license. See the LICENSE
// file for details.
//
//===----------------------------------------------------------------------===//
#ifndef LDC_DRIVER_CL_OPTIONS_LLVM_H
#define LDC_DRIVER_CL_OPTIONS_LLVM_H
#include "llvm/ADT/Optional.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Target/TargetOptions.h"
namespace opts {
std::string getArchStr();
#if LDC_LLVM_VER >= 309
llvm::Optional<llvm::Reloc::Model> getRelocModel();
#else
llvm::Reloc::Model getRelocModel();
#endif
llvm::CodeModel::Model getCodeModel();
bool disableFPElim();
bool disableRedZone();
bool printTargetFeaturesHelp();
llvm::TargetOptions InitTargetOptionsFromCodeGenFlags();
std::string getCPUStr();
std::string getFeaturesStr();
}
#endif

View file

@ -134,10 +134,6 @@ static cl::opt<ubyte, true> debugInfo(
clEnumValN(3, "gline-tables-only", "Add line tables only")), clEnumValN(3, "gline-tables-only", "Add line tables only")),
cl::location(global.params.symdebug), cl::init(0)); cl::location(global.params.symdebug), cl::init(0));
static cl::opt<unsigned, true>
dwarfVersion("dwarf-version", cl::desc("Dwarf version"), cl::ZeroOrMore,
cl::location(global.params.dwarfVersion), cl::Hidden);
cl::opt<bool> noAsm("noasm", cl::desc("Disallow use of inline assembler"), cl::opt<bool> noAsm("noasm", cl::desc("Disallow use of inline assembler"),
cl::ZeroOrMore); cl::ZeroOrMore);
@ -175,12 +171,6 @@ static cl::opt<bool, true>
cl::desc("Remove generated object files on success"), cl::desc("Remove generated object files on success"),
cl::location(global.params.cleanupObjectFiles)); cl::location(global.params.cleanupObjectFiles));
// Disabling Red Zone
cl::opt<bool, true>
disableRedZone("disable-red-zone", cl::ZeroOrMore,
cl::desc("Do not emit code that uses the red zone."),
cl::location(global.params.disableRedZone));
// DDoc options // DDoc options
static cl::opt<bool, true> doDdoc("D", cl::desc("Generate documentation"), static cl::opt<bool, true> doDdoc("D", cl::desc("Generate documentation"),
cl::location(global.params.doDocComments), cl::location(global.params.doDocComments),
@ -296,21 +286,10 @@ cl::opt<std::string>
"'-deps' alone prints module dependencies " "'-deps' alone prints module dependencies "
"(imports/file/version/debug/lib)")); "(imports/file/version/debug/lib)"));
cl::opt<std::string> mArch("march", cl::ZeroOrMore,
cl::desc("Architecture to generate code for:"));
cl::opt<bool> m32bits("m32", cl::desc("32 bit target"), cl::ZeroOrMore); cl::opt<bool> m32bits("m32", cl::desc("32 bit target"), cl::ZeroOrMore);
cl::opt<bool> m64bits("m64", cl::desc("64 bit target"), cl::ZeroOrMore); cl::opt<bool> m64bits("m64", cl::desc("64 bit target"), cl::ZeroOrMore);
cl::opt<std::string>
mCPU("mcpu", cl::ZeroOrMore, cl::value_desc("cpu-name"), cl::init(""),
cl::desc("Target a specific cpu type (-mcpu=help for details)"));
cl::list<std::string>
mAttrs("mattr", cl::CommaSeparated, cl::value_desc("a1,+a2,-a3,..."),
cl::desc("Target specific attributes (-mattr=help for details)"));
cl::opt<std::string> mTargetTriple("mtriple", cl::ZeroOrMore, cl::opt<std::string> mTargetTriple("mtriple", cl::ZeroOrMore,
cl::desc("Override target triple")); cl::desc("Override target triple"));
@ -325,54 +304,7 @@ static cl::list<std::string, StringsAdapter> modFileAliasStrings(
cl::value_desc("<package.module>=<filespec>"), cl::value_desc("<package.module>=<filespec>"),
cl::location(modFileAliasStringsStore)); cl::location(modFileAliasStringsStore));
cl::opt<llvm::Reloc::Model> mRelocModel( FloatABI::Type floatABI; // Storage for the dynamically created float-abi option.
"relocation-model", cl::desc("Relocation model"), cl::ZeroOrMore,
#if LDC_LLVM_VER < 309
cl::init(llvm::Reloc::Default),
#endif
clEnumValues(
#if LDC_LLVM_VER < 309
clEnumValN(llvm::Reloc::Default, "default",
"Target default relocation model"),
#endif
clEnumValN(llvm::Reloc::Static, "static", "Non-relocatable code"),
clEnumValN(llvm::Reloc::PIC_, "pic",
"Fully relocatable, position independent code"),
clEnumValN(llvm::Reloc::DynamicNoPIC, "dynamic-no-pic",
"Relocatable external references, non-relocatable code")));
cl::opt<llvm::CodeModel::Model> mCodeModel(
"code-model", cl::desc("Code model"), cl::ZeroOrMore,
#if LDC_LLVM_VER < 600
cl::init(llvm::CodeModel::Default),
clEnumValues(
clEnumValN(llvm::CodeModel::Default, "default",
"Target default code model"),
#else
cl::init(llvm::CodeModel::Small),
clEnumValues(
#endif
clEnumValN(llvm::CodeModel::Small, "small", "Small code model"),
clEnumValN(llvm::CodeModel::Kernel, "kernel", "Kernel code model"),
clEnumValN(llvm::CodeModel::Medium, "medium", "Medium code model"),
clEnumValN(llvm::CodeModel::Large, "large", "Large code model")));
cl::opt<FloatABI::Type> mFloatABI(
"float-abi", cl::desc("ABI/operations to use for floating-point types:"),
cl::ZeroOrMore, cl::init(FloatABI::Default),
clEnumValues(
clEnumValN(FloatABI::Default, "default",
"Target default floating-point ABI"),
clEnumValN(FloatABI::Soft, "soft",
"Software floating-point ABI and operations"),
clEnumValN(FloatABI::SoftFP, "softfp",
"Soft-float ABI, but hardware floating-point instructions"),
clEnumValN(FloatABI::Hard, "hard",
"Hardware floating-point ABI and instructions")));
cl::opt<bool>
disableFpElim("disable-fp-elim", cl::ZeroOrMore,
cl::desc("Disable frame pointer elimination optimization"));
static cl::opt<bool, true, FlagParser<bool>> static cl::opt<bool, true, FlagParser<bool>>
asserts("asserts", cl::ZeroOrMore, cl::desc("(*) Enable assertions"), asserts("asserts", cl::ZeroOrMore, cl::desc("(*) Enable assertions"),
@ -437,12 +369,10 @@ cl::opt<bool> disableLinkerStripDead(
// Math options // Math options
bool fFastMath; // Storage for the dynamically created ffast-math option. bool fFastMath; // Storage for the dynamically created ffast-math option.
llvm::FastMathFlags defaultFMF; llvm::FastMathFlags defaultFMF;
void setDefaultMathOptions(llvm::TargetMachine &target) { void setDefaultMathOptions(llvm::TargetOptions &targetOptions) {
if (fFastMath) { if (fFastMath) {
defaultFMF.setUnsafeAlgebra(); defaultFMF.setUnsafeAlgebra();
targetOptions.UnsafeFPMath = true;
llvm::TargetOptions &TO = target.Options;
TO.UnsafeFPMath = true;
} }
} }
@ -560,6 +490,7 @@ void createClashingOptions() {
// is a clash in the command line options. // is a clash in the command line options.
renameAndHide("color", "llvm-color"); renameAndHide("color", "llvm-color");
renameAndHide("ffast-math", "llvm-ffast-math"); renameAndHide("ffast-math", "llvm-ffast-math");
renameAndHide("float-abi", "llvm-float-abi");
// Step 2. Add the LDC options. // Step 2. Add the LDC options.
new cl::opt<bool, true, FlagParser<bool>>( new cl::opt<bool, true, FlagParser<bool>>(
@ -567,6 +498,19 @@ void createClashingOptions() {
cl::desc("(*) Force colored console output")); cl::desc("(*) Force colored console output"));
new cl::opt<bool, true>("ffast-math", cl::ZeroOrMore, cl::location(fFastMath), new cl::opt<bool, true>("ffast-math", cl::ZeroOrMore, cl::location(fFastMath),
cl::desc("Set @fastmath for all functions.")); cl::desc("Set @fastmath for all functions."));
new cl::opt<FloatABI::Type, true>(
"float-abi", cl::desc("ABI/operations to use for floating-point types:"),
cl::ZeroOrMore, cl::location(floatABI), cl::init(FloatABI::Default),
clEnumValues(
clEnumValN(FloatABI::Default, "default",
"Target default floating-point ABI"),
clEnumValN(FloatABI::Soft, "soft",
"Software floating-point ABI and operations"),
clEnumValN(
FloatABI::SoftFP, "softfp",
"Soft-float ABI, but hardware floating-point instructions"),
clEnumValN(FloatABI::Hard, "hard",
"Hardware floating-point ABI and instructions")));
} }
/// Hides command line options exposed from within LLVM that are unlikely /// Hides command line options exposed from within LLVM that are unlikely
@ -603,6 +547,15 @@ void hideLLVMOptions() {
"verify-region-info", "verify-scev", "verify-scev-maps", "verify-region-info", "verify-scev", "verify-scev-maps",
"x86-early-ifcvt", "x86-use-vzeroupper", "x86-recip-refinement-steps", "x86-early-ifcvt", "x86-use-vzeroupper", "x86-recip-refinement-steps",
"thread-model", "exception-model", "enable-fp-mad",
"enable-unsafe-fp-math", "enable-no-infs-fp-math",
"enable-no-nans-fp-math", "enable-no-trapping-fp-math",
"denormal-fp-math", "recip", "nozero-initialized-in-bss", "tailcallopt",
"stack-symbol-ordering", "stack-alignment", "enable-pie", "use-ctors",
"emulated-tls", "unique-section-names", "jump-table-type", "meabi",
"debugger-tune", "asm-instrumentation", "mc-relax-all",
"incremental-linker-compatible", "asm-show-inst", "pie-copy-relocations",
// We enable -fdata-sections/-ffunction-sections by default where it makes // We enable -fdata-sections/-ffunction-sections by default where it makes
// sense for reducing code size, so hide them to avoid confusion. // sense for reducing code size, so hide them to avoid confusion.
// //
@ -611,7 +564,20 @@ void hideLLVMOptions() {
// on the target triple (and thus we do not know it until after the // on the target triple (and thus we do not know it until after the
// command // command
// line has been parsed). // line has been parsed).
"fdata-sections", "ffunction-sections"}; "fdata-sections", "ffunction-sections", "data-sections",
"function-sections"};
// pulled in from shared LLVM headers, but unused or not desired in LDC
static const char *const removedOptions[] = {"disable-tail-calls",
"fatal-warnings",
"filetype",
"no-deprecated-warn",
"no-warn",
"stackrealign",
"start-after",
"stop-after",
"trap-func",
"W"};
llvm::StringMap<cl::Option *> &map = cl::getRegisteredOptions(); llvm::StringMap<cl::Option *> &map = cl::getRegisteredOptions();
for (const auto name : hiddenOptions) { for (const auto name : hiddenOptions) {
@ -622,6 +588,13 @@ void hideLLVMOptions() {
it->second->setHiddenFlag(cl::Hidden); it->second->setHiddenFlag(cl::Hidden);
} }
} }
for (const auto name : removedOptions) {
auto it = map.find(name);
if (it != map.end()) {
map.erase(it);
}
}
} }
} // namespace opts } // namespace opts

View file

@ -15,6 +15,7 @@
#ifndef LDC_DRIVER_CL_OPTIONS_H #ifndef LDC_DRIVER_CL_OPTIONS_H
#define LDC_DRIVER_CL_OPTIONS_H #define LDC_DRIVER_CL_OPTIONS_H
#include "driver/cl_options-llvm.h"
#include "driver/targetmachine.h" #include "driver/targetmachine.h"
#include "gen/cl_helpers.h" #include "gen/cl_helpers.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
@ -69,24 +70,18 @@ extern cl::opt<std::string> cacheDir;
extern cl::list<std::string> linkerSwitches; extern cl::list<std::string> linkerSwitches;
extern cl::list<std::string> ccSwitches; extern cl::list<std::string> ccSwitches;
extern cl::opt<std::string> mArch;
extern cl::opt<bool> m32bits; extern cl::opt<bool> m32bits;
extern cl::opt<bool> m64bits; extern cl::opt<bool> m64bits;
extern cl::opt<std::string> mCPU;
extern cl::list<std::string> mAttrs;
extern cl::opt<std::string> mTargetTriple; extern cl::opt<std::string> mTargetTriple;
extern cl::opt<std::string> mABI; extern cl::opt<std::string> mABI;
extern cl::opt<llvm::Reloc::Model> mRelocModel; extern FloatABI::Type floatABI;
extern cl::opt<llvm::CodeModel::Model> mCodeModel;
extern cl::opt<bool> disableFpElim;
extern cl::opt<FloatABI::Type> mFloatABI;
extern cl::opt<bool> linkonceTemplates; extern cl::opt<bool> linkonceTemplates;
extern cl::opt<bool> disableLinkerStripDead; extern cl::opt<bool> disableLinkerStripDead;
// Math options // Math options
extern bool fFastMath; extern bool fFastMath;
extern llvm::FastMathFlags defaultFMF; extern llvm::FastMathFlags defaultFMF;
void setDefaultMathOptions(llvm::TargetMachine &target); void setDefaultMathOptions(llvm::TargetOptions &targetOptions);
extern cl::opt<BOUNDSCHECK> boundsCheck; extern cl::opt<BOUNDSCHECK> boundsCheck;
extern bool nonSafeBoundsChecks; extern bool nonSafeBoundsChecks;

View file

@ -198,8 +198,18 @@ void outputSanitizerSettings(llvm::raw_ostream &hash_os) {
} }
bool functionIsInSanitizerBlacklist(FuncDeclaration *funcDecl) { bool functionIsInSanitizerBlacklist(FuncDeclaration *funcDecl) {
return sanitizerBlacklist && if (!sanitizerBlacklist)
sanitizerBlacklist->inSection("fun", mangleExact(funcDecl)); return false;
#if LDC_LLVM_VER >= 600
// 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
// of that too.
return sanitizerBlacklist->inSection("" /* section name */, "fun",
mangleExact(funcDecl));
#else
return sanitizerBlacklist->inSection("fun", mangleExact(funcDecl));
#endif
} }
} // namespace opts } // namespace opts

View file

@ -30,12 +30,18 @@ extern Module *g_entrypointModule;
/// The module that contains the actual D main() (_Dmain) definition. /// The module that contains the actual D main() (_Dmain) definition.
extern Module *g_dMainModule; extern Module *g_dMainModule;
#if LDC_LLVM_VER < 600
namespace llvm {
using ToolOutputFile = tool_output_file;
}
#endif
namespace { namespace {
std::unique_ptr<llvm::tool_output_file> std::unique_ptr<llvm::ToolOutputFile>
createAndSetDiagnosticsOutputFile(IRState &irs, llvm::LLVMContext &ctx, createAndSetDiagnosticsOutputFile(IRState &irs, llvm::LLVMContext &ctx,
llvm::StringRef filename) { llvm::StringRef filename) {
std::unique_ptr<llvm::tool_output_file> diagnosticsOutputFile; std::unique_ptr<llvm::ToolOutputFile> diagnosticsOutputFile;
#if LDC_LLVM_VER >= 400 #if LDC_LLVM_VER >= 400
// Set LLVM Diagnostics outputfile if requested // Set LLVM Diagnostics outputfile if requested
@ -49,7 +55,7 @@ createAndSetDiagnosticsOutputFile(IRState &irs, llvm::LLVMContext &ctx,
} }
std::error_code EC; std::error_code EC;
diagnosticsOutputFile = llvm::make_unique<llvm::tool_output_file>( diagnosticsOutputFile = llvm::make_unique<llvm::ToolOutputFile>(
diagnosticsFilename, EC, llvm::sys::fs::F_None); diagnosticsFilename, EC, llvm::sys::fs::F_None);
if (EC) { if (EC) {
irs.dmodule->error("Could not create file %s: %s", irs.dmodule->error("Could not create file %s: %s",
@ -258,7 +264,7 @@ void CodeGenerator::writeAndFreeLLModule(const char *filename) {
llvm::Metadata *IdentNode[] = {llvm::MDString::get(ir_->context(), Version)}; llvm::Metadata *IdentNode[] = {llvm::MDString::get(ir_->context(), Version)};
IdentMetadata->addOperand(llvm::MDNode::get(ir_->context(), IdentNode)); IdentMetadata->addOperand(llvm::MDNode::get(ir_->context(), IdentNode));
std::unique_ptr<llvm::tool_output_file> diagnosticsOutputFile = std::unique_ptr<llvm::ToolOutputFile> diagnosticsOutputFile =
createAndSetDiagnosticsOutputFile(*ir_, context_, filename); createAndSetDiagnosticsOutputFile(*ir_, context_, filename);
writeModule(&ir_->module, filename); writeModule(&ir_->module, filename);

View file

@ -107,7 +107,13 @@ char *concat(const char *a, int b) {
*/ */
int execute(const std::string &exePath, const char **args) { int execute(const std::string &exePath, const char **args) {
std::string errorMsg; std::string errorMsg;
int rc = ls::ExecuteAndWait(exePath, args, nullptr, nullptr, 0, 0, &errorMsg); int rc = ls::ExecuteAndWait(exePath, args, nullptr,
#if LDC_LLVM_VER >= 600
{},
#else
nullptr,
#endif
0, 0, &errorMsg);
if (!errorMsg.empty()) { if (!errorMsg.empty()) {
error("Error executing %s: %s", exePath.c_str(), errorMsg.c_str()); error("Error executing %s: %s", exePath.c_str(), errorMsg.c_str());
} }

View file

@ -118,8 +118,9 @@ void ArgsBuilder::addLTOGoldPluginFlags() {
if (opts::isUsingThinLTO()) if (opts::isUsingThinLTO())
addLdFlag("-plugin-opt=thinlto"); addLdFlag("-plugin-opt=thinlto");
if (!opts::mCPU.empty()) const auto cpu = gTargetMachine->getTargetCPU();
addLdFlag(llvm::Twine("-plugin-opt=mcpu=") + opts::mCPU); if (!cpu.empty())
addLdFlag(llvm::Twine("-plugin-opt=mcpu=") + cpu);
// Use the O-level passed to LDC as the O-level for LTO, but restrict it to // Use the O-level passed to LDC as the O-level for LTO, but restrict it to
// the [0, 3] range that can be passed to the linker plugin. // the [0, 3] range that can be passed to the linker plugin.

View file

@ -104,18 +104,6 @@ static cl::opt<bool> linkDebugLib(
"link-debuglib", cl::ZeroOrMore, "link-debuglib", cl::ZeroOrMore,
cl::desc("Link with libraries specified in -debuglib, not -defaultlib")); cl::desc("Link with libraries specified in -debuglib, not -defaultlib"));
#if LDC_LLVM_VER >= 309
static inline llvm::Optional<llvm::Reloc::Model> getRelocModel() {
if (mRelocModel.getNumOccurrences()) {
llvm::Reloc::Model R = mRelocModel;
return R;
}
return llvm::None;
}
#else
static inline llvm::Reloc::Model getRelocModel() { return mRelocModel; }
#endif
// This function exits the program. // This function exits the program.
void printVersion(llvm::raw_ostream &OS) { void printVersion(llvm::raw_ostream &OS) {
OS << "LDC - the LLVM D compiler (" << global.ldc_version << "):\n"; OS << "LDC - the LLVM D compiler (" << global.ldc_version << "):\n";
@ -372,8 +360,7 @@ void parseCommandLine(int argc, char **argv, Strings &sourceFiles,
const_cast<char **>(allArguments.data()), const_cast<char **>(allArguments.data()),
"LDC - the LLVM D compiler\n"); "LDC - the LLVM D compiler\n");
helpOnly = mCPU == "help" || helpOnly = opts::printTargetFeaturesHelp();
(std::find(mAttrs.begin(), mAttrs.end(), "help") != mAttrs.end());
if (helpOnly) { if (helpOnly) {
auto triple = llvm::Triple(cfg_triple); auto triple = llvm::Triple(cfg_triple);
std::string errMsg; std::string errMsg;
@ -597,19 +584,12 @@ void parseCommandLine(int argc, char **argv, Strings &sourceFiles,
error(Loc(), "-lib and -shared switches cannot be used together"); error(Loc(), "-lib and -shared switches cannot be used together");
} }
#if LDC_LLVM_VER >= 309
if (global.params.dll && !mRelocModel.getNumOccurrences()) {
#else
if (global.params.dll && mRelocModel == llvm::Reloc::Default) {
#endif
mRelocModel = llvm::Reloc::PIC_;
}
if (soname.getNumOccurrences() > 0 && !global.params.dll) { if (soname.getNumOccurrences() > 0 && !global.params.dll) {
error(Loc(), "-soname can be used only when building a shared library"); error(Loc(), "-soname can be used only when building a shared library");
} }
global.params.hdrStripPlainFunctions = !opts::hdrKeepAllBodies; global.params.hdrStripPlainFunctions = !opts::hdrKeepAllBodies;
global.params.disableRedZone = opts::disableRedZone();
} }
void initializePasses() { void initializePasses() {
@ -1006,7 +986,8 @@ int cppmain(int argc, char **argv) {
} }
// Set up the TargetMachine. // Set up the TargetMachine.
if ((m32bits || m64bits) && (!mArch.empty() || !mTargetTriple.empty())) { const auto arch = getArchStr();
if ((m32bits || m64bits) && (!arch.empty() || !mTargetTriple.empty())) {
error(Loc(), "-m32 and -m64 switches cannot be used together with -march " error(Loc(), "-m32 and -m64 switches cannot be used together with -march "
"and -mtriple switches"); "and -mtriple switches");
} }
@ -1021,9 +1002,21 @@ int cppmain(int argc, char **argv) {
fatal(); fatal();
} }
auto relocModel = getRelocModel();
#if LDC_LLVM_VER >= 309
if (global.params.dll && !relocModel.hasValue()) {
#else
if (global.params.dll && relocModel == llvm::Reloc::Default) {
#endif
relocModel = llvm::Reloc::PIC_;
}
gTargetMachine = createTargetMachine( gTargetMachine = createTargetMachine(
mTargetTriple, mArch, mCPU, mAttrs, bitness, mFloatABI, getRelocModel(), mTargetTriple, arch, opts::getCPUStr(), opts::getFeaturesStr(), bitness,
mCodeModel, codeGenOptLevel(), disableFpElim, disableLinkerStripDead); floatABI, relocModel, opts::getCodeModel(), codeGenOptLevel(),
disableLinkerStripDead);
opts::setDefaultMathOptions(gTargetMachine->Options);
#if LDC_LLVM_VER >= 308 #if LDC_LLVM_VER >= 308
static llvm::DataLayout DL = gTargetMachine->createDataLayout(); static llvm::DataLayout DL = gTargetMachine->createDataLayout();
@ -1044,6 +1037,7 @@ int cppmain(int argc, char **argv) {
global.params.isLP64 = gDataLayout->getPointerSizeInBits() == 64; global.params.isLP64 = gDataLayout->getPointerSizeInBits() == 64;
global.params.is64bit = triple->isArch64Bit(); global.params.is64bit = triple->isArch64Bit();
global.params.hasObjectiveC = objc_isSupported(*triple); global.params.hasObjectiveC = objc_isSupported(*triple);
global.params.dwarfVersion = gTargetMachine->Options.MCOptions.DwarfVersion;
// mscoff enables slightly different handling of interface functions // mscoff enables slightly different handling of interface functions
// in the front end // in the front end
global.params.mscoff = triple->isKnownWindowsMSVCEnvironment(); global.params.mscoff = triple->isKnownWindowsMSVCEnvironment();
@ -1051,8 +1045,6 @@ int cppmain(int argc, char **argv) {
global.obj_ext = "obj"; global.obj_ext = "obj";
} }
opts::setDefaultMathOptions(*gTargetMachine);
// allocate the target abi // allocate the target abi
gABI = TargetABI::getTarget(); gABI = TargetABI::getTarget();

View file

@ -15,6 +15,7 @@
#include "driver/cl_options.h" #include "driver/cl_options.h"
#include "driver/targetmachine.h" #include "driver/targetmachine.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h" #include "llvm/ADT/Triple.h"
#include "llvm/MC/SubtargetFeature.h" #include "llvm/MC/SubtargetFeature.h"
@ -27,6 +28,7 @@
#include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetOptions.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "mars.h" #include "mars.h"
#include "driver/cl_options.h"
#include "gen/logger.h" #include "gen/logger.h"
static const char *getABI(const llvm::Triple &triple) { static const char *getABI(const llvm::Triple &triple) {
@ -197,28 +199,13 @@ static std::string getAArch64TargetCPU(const llvm::Triple &triple) {
return "generic"; return "generic";
} }
/// Returns the LLVM name of the target CPU to use given the provided /// Returns the LLVM name of the default CPU for the provided target triple.
/// -mcpu argument and target triple. static std::string getTargetCPU(const llvm::Triple &triple) {
static std::string getTargetCPU(const std::string &cpu,
const llvm::Triple &triple) {
if (!cpu.empty()) {
if (cpu != "native") {
return cpu;
}
// FIXME: Reject attempts to use -mcpu=native unless the target matches
// the host.
std::string hostCPU = llvm::sys::getHostCPUName();
if (!hostCPU.empty() && hostCPU != "generic") {
return hostCPU;
}
}
switch (triple.getArch()) { switch (triple.getArch()) {
default: default:
// We don't know about the specifics of this platform, just return the // We don't know about the specifics of this platform, just return the
// empty string and let LLVM decide. // empty string and let LLVM decide.
return cpu; return "";
case llvm::Triple::x86: case llvm::Triple::x86:
case llvm::Triple::x86_64: case llvm::Triple::x86_64:
return getX86TargetCPU(triple); return getX86TargetCPU(triple);
@ -355,17 +342,18 @@ const llvm::Target *lookupTarget(const std::string &arch, llvm::Triple &triple,
} }
llvm::TargetMachine * llvm::TargetMachine *
createTargetMachine(std::string targetTriple, std::string arch, std::string cpu, createTargetMachine(const std::string targetTriple, const std::string arch,
std::vector<std::string> attrs, std::string cpu, const std::string featuresString,
ExplicitBitness::Type bitness, FloatABI::Type floatABI, const ExplicitBitness::Type bitness,
FloatABI::Type floatABI,
#if LDC_LLVM_VER >= 309 #if LDC_LLVM_VER >= 309
llvm::Optional<llvm::Reloc::Model> relocModel, llvm::Optional<llvm::Reloc::Model> relocModel,
#else #else
llvm::Reloc::Model relocModel, llvm::Reloc::Model relocModel,
#endif #endif
llvm::CodeModel::Model codeModel, const llvm::CodeModel::Model codeModel,
llvm::CodeGenOpt::Level codeGenOptLevel, const llvm::CodeGenOpt::Level codeGenOptLevel,
bool noFramePointerElim, bool noLinkerStripDead) { const bool noLinkerStripDead) {
// Determine target triple. If the user didn't explicitly specify one, use // Determine target triple. If the user didn't explicitly specify one, use
// the one set at LLVM configure time. // the one set at LLVM configure time.
llvm::Triple triple; llvm::Triple triple;
@ -398,47 +386,40 @@ createTargetMachine(std::string targetTriple, std::string arch, std::string cpu,
fatal(); fatal();
} }
// Package up features to be passed to target/subtarget.
llvm::SubtargetFeatures features;
features.getDefaultSubtargetFeatures(triple);
if (cpu == "native") {
llvm::StringMap<bool> hostFeatures;
if (llvm::sys::getHostCPUFeatures(hostFeatures)) {
for (const auto &hf : hostFeatures) {
features.AddFeature(
std::string(hf.second ? "+" : "-").append(hf.first()));
}
}
}
for (auto &attr : attrs) {
features.AddFeature(attr);
}
// With an empty CPU string, LLVM will default to the host CPU, which is // With an empty CPU string, LLVM will default to the host CPU, which is
// usually not what we want (expected behavior from other compilers is // usually not what we want (expected behavior from other compilers is
// to default to "generic"). // to default to "generic").
cpu = getTargetCPU(cpu, triple); if (cpu.empty() || cpu == "generic") {
cpu = getTargetCPU(triple);
if (cpu.empty())
cpu = "generic";
}
// Package up features to be passed to target/subtarget.
llvm::SmallVector<llvm::StringRef, 8> features;
// NOTE: needs a persistent (non-temporary) string
auto splitAndAddFeatures = [&features](llvm::StringRef str) {
str.split(features, ",", -1, /* KeepEmpty */ false);
};
llvm::SubtargetFeatures defaultSubtargetFeatures;
defaultSubtargetFeatures.getDefaultSubtargetFeatures(triple);
const std::string defaultSubtargetFeaturesString =
defaultSubtargetFeatures.getString();
splitAndAddFeatures(defaultSubtargetFeaturesString);
splitAndAddFeatures(featuresString);
// cmpxchg16b is not available on old 64bit CPUs. Enable code generation // cmpxchg16b is not available on old 64bit CPUs. Enable code generation
// if the user did not make an explicit choice. // if the user did not make an explicit choice.
if (cpu == "x86-64") { if (cpu == "x86-64") {
const char *cx16_plus = "+cx16"; const bool has_cx16 =
const char *cx16_minus = "-cx16"; std::any_of(features.begin(), features.end(),
bool cx16 = false; [](llvm::StringRef f) { return f.substr(1) == "cx16"; });
for (auto &attr : attrs) { if (!has_cx16) {
if (attr == cx16_plus || attr == cx16_minus) { features.push_back("+cx16");
cx16 = true;
}
} }
if (!cx16) {
features.AddFeature(cx16_plus);
}
}
if (Logger::enabled()) {
Logger::println("Targeting '%s' (CPU '%s' with features '%s')",
triple.str().c_str(), cpu.c_str(),
features.getString().c_str());
} }
// Handle cases where LLVM picks wrong default relocModel // Handle cases where LLVM picks wrong default relocModel
@ -473,26 +454,28 @@ createTargetMachine(std::string targetTriple, std::string arch, std::string cpu,
} }
} }
if (floatABI == FloatABI::Default) { llvm::TargetOptions targetOptions = opts::InitTargetOptionsFromCodeGenFlags();
if (targetOptions.MCOptions.ABIName.empty())
targetOptions.MCOptions.ABIName = getABI(triple);
auto ldcFloatABI = floatABI;
if (ldcFloatABI == FloatABI::Default) {
switch (triple.getArch()) { switch (triple.getArch()) {
default: // X86, ... default: // X86, ...
floatABI = FloatABI::Hard; ldcFloatABI = FloatABI::Hard;
break; break;
case llvm::Triple::arm: case llvm::Triple::arm:
case llvm::Triple::thumb: case llvm::Triple::thumb:
floatABI = getARMFloatABI(triple, getLLVMArchSuffixForARM(cpu)); ldcFloatABI = getARMFloatABI(triple, getLLVMArchSuffixForARM(cpu));
break; break;
} }
} }
llvm::TargetOptions targetOptions; switch (ldcFloatABI) {
targetOptions.MCOptions.ABIName = getABI(triple);
switch (floatABI) {
default: default:
llvm_unreachable("Floating point ABI type unknown."); llvm_unreachable("Floating point ABI type unknown.");
case FloatABI::Soft: case FloatABI::Soft:
features.AddFeature("+soft-float"); features.push_back("+soft-float");
targetOptions.FloatABIType = llvm::FloatABI::Soft; targetOptions.FloatABIType = llvm::FloatABI::Soft;
break; break;
case FloatABI::SoftFP: case FloatABI::SoftFP:
@ -514,11 +497,20 @@ createTargetMachine(std::string targetTriple, std::string arch, std::string cpu,
targetOptions.DataSections = true; targetOptions.DataSections = true;
} }
return target->createTargetMachine(triple.str(), cpu, features.getString(), const std::string finalFeaturesString =
targetOptions, relocModel, codeModel, llvm::join(features.begin(), features.end(), ",");
if (Logger::enabled()) {
Logger::println("Targeting '%s' (CPU '%s' with features '%s')",
triple.str().c_str(), cpu.c_str(),
finalFeaturesString.c_str());
}
return target->createTargetMachine(triple.str(), cpu, finalFeaturesString,
targetOptions, relocModel, opts::getCodeModel(),
codeGenOptLevel); codeGenOptLevel);
} }
ComputeBackend::Type getComputeTargetType(llvm::Module* m) { ComputeBackend::Type getComputeTargetType(llvm::Module* m) {
llvm::Triple::ArchType a = llvm::Triple(m->getTargetTriple()).getArch(); llvm::Triple::ArchType a = llvm::Triple(m->getTargetTriple()).getArch();
if (a == llvm::Triple::spir || a == llvm::Triple::spir64) if (a == llvm::Triple::spir || a == llvm::Triple::spir64)

View file

@ -52,18 +52,19 @@ ComputeBackend::Type getComputeTargetType(llvm::Module*);
* parameters and the host platform defaults. * parameters and the host platform defaults.
* *
* Does not depend on any global state. * Does not depend on any global state.
*/ */
llvm::TargetMachine *createTargetMachine( llvm::TargetMachine *
std::string targetTriple, std::string arch, std::string cpu, createTargetMachine(std::string targetTriple, std::string arch, std::string cpu,
std::vector<std::string> attrs, ExplicitBitness::Type bitness, std::string featuresString, ExplicitBitness::Type bitness,
FloatABI::Type floatABI, FloatABI::Type floatABI,
#if LDC_LLVM_VER >= 309 #if LDC_LLVM_VER >= 309
llvm::Optional<llvm::Reloc::Model> relocModel, llvm::Optional<llvm::Reloc::Model> relocModel,
#else #else
llvm::Reloc::Model relocModel, llvm::Reloc::Model relocModel,
#endif #endif
llvm::CodeModel::Model codeModel, llvm::CodeGenOpt::Level codeGenOptLevel, llvm::CodeModel::Model codeModel,
bool noFramePointerElim, bool noLinkerStripDead); llvm::CodeGenOpt::Level codeGenOptLevel,
bool noLinkerStripDead);
/** /**
* Returns the Mips ABI which is used for code generation. * Returns the Mips ABI which is used for code generation.

View file

@ -171,7 +171,12 @@ int executeToolAndWait(const std::string &tool_,
// Execute tool. // Execute tool.
std::string errstr; std::string errstr;
if (int status = llvm::sys::ExecuteAndWait(tool, &realargs[0], nullptr, if (int status = llvm::sys::ExecuteAndWait(tool, &realargs[0], nullptr,
nullptr, 0, 0, &errstr)) { #if LDC_LLVM_VER >= 600
{},
#else
nullptr,
#endif
0, 0, &errstr)) {
error(Loc(), "%s failed with status: %d", tool.c_str(), status); error(Loc(), "%s failed with status: %d", tool.c_str(), status);
if (!errstr.empty()) { if (!errstr.empty()) {
error(Loc(), "message: %s", errstr.c_str()); error(Loc(), "message: %s", errstr.c_str());

View file

@ -56,7 +56,7 @@ public:
is64 ? "nvptx64-nvidia-cuda" : "nvptx-nvidia-cuda", is64 ? "nvptx64-nvidia-cuda" : "nvptx-nvidia-cuda",
is64 ? "nvptx64" : "nvptx", "sm_" + ldc::to_string(tversion / 10), {}, is64 ? "nvptx64" : "nvptx", "sm_" + ldc::to_string(tversion / 10), {},
is64 ? ExplicitBitness::M64 : ExplicitBitness::M32, ::FloatABI::Hard, is64 ? ExplicitBitness::M64 : ExplicitBitness::M32, ::FloatABI::Hard,
llvm::Reloc::Static, llvm::CodeModel::Medium, codeGenOptLevel(), false, llvm::Reloc::Static, llvm::CodeModel::Medium, codeGenOptLevel(),
false); false);
} }

View file

@ -460,7 +460,7 @@ void applyTargetMachineAttributes(llvm::Function &func,
// Frame pointer elimination // Frame pointer elimination
func.addFnAttr("no-frame-pointer-elim", func.addFnAttr("no-frame-pointer-elim",
opts::disableFpElim ? "true" : "false"); opts::disableFPElim() ? "true" : "false");
} }
} // anonymous namespace } // anonymous namespace

View file

@ -384,12 +384,19 @@ static void DtoCreateNestedContextType(FuncDeclaration *fd) {
irLocal.nestedDepth = depth; irLocal.nestedDepth = depth;
LLType *t = nullptr; LLType *t = nullptr;
if (vd->isRef() || vd->isOut()) if (vd->isRef() || vd->isOut()) {
t = DtoType(vd->type->pointerTo()); t = DtoType(vd->type->pointerTo());
else if (vd->isParameter() && (vd->storage_class & STClazy)) } else if (vd->isParameter() && (vd->storage_class & STClazy)) {
t = getIrParameter(vd)->value->getType()->getContainedType(0); // The LL type is a delegate (LL struct).
else // Depending on the used TargetABI, the LL parameter is either a struct or
// a pointer to a struct (`byval` attribute, ExplicitByvalRewrite).
t = getIrParameter(vd)->value->getType();
if (t->isPointerTy())
t = t->getPointerElementType();
assert(t->isStructTy());
} else {
t = DtoMemType(vd->type); t = DtoMemType(vd->type);
}
builder.addType(t, getTypeAllocSize(t)); builder.addType(t, getTypeAllocSize(t));
@ -477,7 +484,6 @@ void DtoCreateNestedContext(FuncGenState &funcGen) {
IrLocal *irLocal = getIrLocal(vd); IrLocal *irLocal = getIrLocal(vd);
LLValue *gep = DtoGEPi(frame, 0, irLocal->nestedIndex, vd->toChars()); LLValue *gep = DtoGEPi(frame, 0, irLocal->nestedIndex, vd->toChars());
LLSmallVector<int64_t, 2> dwarfAddrOps;
if (vd->isParameter()) { if (vd->isParameter()) {
IF_LOG Logger::println("nested param: %s", vd->toChars()); IF_LOG Logger::println("nested param: %s", vd->toChars());
LOG_SCOPE LOG_SCOPE
@ -505,6 +511,7 @@ void DtoCreateNestedContext(FuncGenState &funcGen) {
} }
if (global.params.symdebug) { if (global.params.symdebug) {
LLSmallVector<int64_t, 1> dwarfAddrOps;
#if LDC_LLVM_VER < 500 #if LDC_LLVM_VER < 500
// Because we are passing a GEP instead of an alloca to // Because we are passing a GEP instead of an alloca to
// llvm.dbg.declare, we have to make the address dereference explicit. // llvm.dbg.declare, we have to make the address dereference explicit.

View file

@ -203,22 +203,44 @@ IrTypeAggr::IrTypeAggr(AggregateDeclaration *ad)
aggr(ad) {} aggr(ad) {}
bool IrTypeAggr::isPacked(AggregateDeclaration *ad) { bool IrTypeAggr::isPacked(AggregateDeclaration *ad) {
const auto aggregateSize = (ad->sizeok == SIZEOKdone ? ad->structsize : ~0u); // If the aggregate's size is unknown, any field with type alignment > 1 will
// make it packed.
unsigned aggregateSize = ~0u;
unsigned aggregateAlignment = 1;
if (ad->sizeok == SIZEOKdone) {
aggregateSize = ad->structsize;
const auto naturalAlignment = ad->alignsize;
auto explicitAlignment = STRUCTALIGN_DEFAULT;
if (auto sd = ad->isStructDeclaration())
explicitAlignment = sd->alignment;
aggregateAlignment = explicitAlignment == STRUCTALIGN_DEFAULT
? naturalAlignment
: explicitAlignment;
}
// Classes apparently aren't padded; their size may not match the alignment.
assert((ad->isClassDeclaration() ||
(aggregateSize & (aggregateAlignment - 1)) == 0) &&
"Size not a multiple of alignment?");
// For unions, only a subset of the fields are actually used for the IR type - // For unions, only a subset of the fields are actually used for the IR type -
// don't care. // don't care (about a few potentially needlessly packed IR structs).
for (const auto field : ad->fields) { for (const auto field : ad->fields) {
// The aggregate's size and the field offset need to be multiples of the const auto naturalFieldTypeAlignment = field->type->alignsize();
// field's natural alignment, otherwise the aggregate type is unnaturally const auto explicitFieldTypeAlignment = field->type->alignment();
// aligned, and LLVM would insert padding. const auto fieldTypeAlignment =
const auto naturalFieldAlignment = field->type->alignsize(); explicitFieldTypeAlignment == STRUCTALIGN_DEFAULT
const auto mask = naturalFieldAlignment - 1; ? naturalFieldTypeAlignment
: explicitFieldTypeAlignment;
// If the aggregate's size is unknown, any field with natural alignment > 1 // The aggregate size, aggregate alignment and the field offset need to be
// will make it packed. // multiples of the field type's alignment, otherwise the aggregate type is
if ((aggregateSize & mask) != 0 || (field->offset & mask) != 0) { // unnaturally aligned, and LLVM would insert padding.
const auto mask = fieldTypeAlignment - 1;
if ((aggregateSize | aggregateAlignment | field->offset) & mask)
return true; return true;
}
} }
return false; return false;

@ -1 +1 @@
Subproject commit 5f7abf31084726c96669fc66e03ce822b3c2e5e5 Subproject commit 924c993b400f8de9268aa5ed3fce144693645849

69
tests/codegen/gh2346.d Normal file
View file

@ -0,0 +1,69 @@
// RUN: %ldc -output-ll -of=%t.ll %s && FileCheck %s < %t.ll
// Make sure the LL struct is packed due to an unnatural overall alignment of 1.
// CHECK-DAG: %gh2346.UnalignedUInt = type <{ i32 }>
struct UnalignedUInt {
align(1) uint a;
}
static assert(UnalignedUInt.alignof == 1);
static assert(UnalignedUInt.sizeof == 4);
// Then there's no need to pack naturally aligned containers.
// CHECK-DAG: %gh2346.Container = type { i8, %gh2346.UnalignedUInt }
struct Container {
ubyte one;
UnalignedUInt two;
}
static assert(Container.alignof == 1);
static assert(Container.sizeof == 5);
static assert(Container.two.offsetof == 1);
// CHECK-DAG: %gh2346.UnalignedUInt2 = type <{ i32 }>
struct UnalignedUInt2 {
align(2) uint a;
}
static assert(UnalignedUInt2.alignof == 2);
static assert(UnalignedUInt2.sizeof == 4);
// CHECK-DAG: %gh2346.Container2 = type { i8, [1 x i8], %gh2346.UnalignedUInt2 }
struct Container2 {
ubyte one;
UnalignedUInt2 two;
}
static assert(Container2.alignof == 2);
static assert(Container2.sizeof == 6);
static assert(Container2.two.offsetof == 2);
// CHECK-DAG: %gh2346.PackedContainer2 = type <{ i8, %gh2346.UnalignedUInt2 }>
struct PackedContainer2 {
ubyte one;
align(1) UnalignedUInt2 two;
}
static assert(PackedContainer2.alignof == 1);
static assert(PackedContainer2.sizeof == 5);
static assert(PackedContainer2.two.offsetof == 1);
// CHECK-DAG: %gh2346.WeirdContainer = type { i8, [1 x i8], %gh2346.UnalignedUInt, [2 x i8] }
align(4) struct WeirdContainer {
ubyte one;
align(2) UnalignedUInt two;
}
static assert(WeirdContainer.alignof == 4);
static assert(WeirdContainer.sizeof == 8);
static assert(WeirdContainer.two.offsetof == 2);
// CHECK-DAG: %gh2346.ExplicitlyUnalignedUInt2 = type <{ i32 }>
align(2) struct ExplicitlyUnalignedUInt2 {
uint a;
}
static assert(ExplicitlyUnalignedUInt2.alignof == 2);
static assert(ExplicitlyUnalignedUInt2.sizeof == 4);
// CHECK-DAG: %gh2346.AnotherContainer = type { i8, [1 x i8], %gh2346.ExplicitlyUnalignedUInt2 }
struct AnotherContainer {
ubyte one;
ExplicitlyUnalignedUInt2 two;
}
static assert(AnotherContainer.alignof == 2);
static assert(AnotherContainer.sizeof == 6);
static assert(AnotherContainer.two.offsetof == 2);

View file

@ -0,0 +1,18 @@
// RUN: %ldc -output-ll -of=%t.ll %s && FileCheck %s < %t.ll
// RUN: %ldc -run %s
void foo()
{
auto impl(T)(lazy T field)
{
// Make sure `field` is a closure variable with delegate type (LL struct).
// CHECK: %nest.impl = type { { i8*, i32 (i8*)* } }
auto ff() { return field; }
auto a = field;
return ff() + a;
}
auto r = impl(123);
assert(r == 246);
}
void main() { foo(); }

View file

@ -1,13 +1,13 @@
// Tests that // Tests that
// - we dont try to link with one file on the commandline that is @compute // - we don't try to link with one file on the commandline that is @compute
// - truning on debugging doesn't ICE // - turning on debugging doesn't ICE
// - dont analyse uninstansiated templates // - don't analyse uninstantiated templates
// - typeid generated for hashing of struct (typeid(const(T))) is ignored and does not error // - typeid generated for hashing of struct (typeid(const(T))) is ignored and does not error
// REQUIRES: target_NVPTX // REQUIRES: target_NVPTX
// RUN: %ldc -mdcompute-targets=cuda-350 -g // RUN: %ldc -mdcompute-targets=cuda-350 -g %s
@compute(Compilefor.deviceOnly) module dcompute; @compute(CompileFor.deviceOnly) module dcompute;
import ldc.dcompute; import ldc.dcompute;
@kernel void foo() @kernel void foo()

View file

@ -0,0 +1,9 @@
// RUN: %ldc -run %s
extern(C) __gshared string[] rt_options = [ "key=value" ];
void main()
{
import rt.config;
assert(rt_configOption("key") == "value");
}

View file

@ -40,8 +40,13 @@ int main(int argc, const char **argv) {
} }
std::string ErrMsg; std::string ErrMsg;
int Result = sys::ExecuteAndWait(*Program, argv, nullptr, nullptr, 0, 0, int Result = sys::ExecuteAndWait(*Program, argv, nullptr,
&ErrMsg); #if LDC_LLVM_VER >= 600
{},
#else
nullptr,
#endif
0, 0, &ErrMsg);
#ifdef _WIN32 #ifdef _WIN32
// Handle abort() in msvcrt -- It has exit code as 3. abort(), aka // Handle abort() in msvcrt -- It has exit code as 3. abort(), aka
// unreachable, should be recognized as a crash. However, some binaries use // unreachable, should be recognized as a crash. However, some binaries use