mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-03 08:30:47 +03:00
Merge branch 'master' into merge-2.075
Conflicts: runtime/druntime
This commit is contained in:
commit
d7f68dbeb3
28 changed files with 489 additions and 261 deletions
|
@ -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 ..
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
#
|
#
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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()));
|
||||||
|
|
|
@ -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
|
||||||
|
|
64
driver/cl_options-llvm.cpp
Normal file
64
driver/cl_options-llvm.cpp
Normal 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
36
driver/cl_options-llvm.h
Normal 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
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
69
tests/codegen/gh2346.d
Normal 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);
|
18
tests/codegen/nested_lazy_gh2302.d
Normal file
18
tests/codegen/nested_lazy_gh2302.d
Normal 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(); }
|
|
@ -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()
|
||||||
|
|
9
tests/linking/rt_options.d
Normal file
9
tests/linking/rt_options.d
Normal 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");
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue