diff --git a/CMakeLists.txt b/CMakeLists.txt index cb37c30b42..532119b42e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,18 +7,11 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules") # Locate LLVM. # -# This would actually better be named named EXTRA_LLVM_TARGETS, as it allows -# additional targets (beside the native one) to be specified. It affects the -# LLVM libraries linked and is converted to a preprocessor define used in -# gen/main.cpp. -set(EXTRA_LLVM_MODULES "" CACHE STRING - "Extra LLVM targets to link in (see llvm-config --targets-built)") -separate_arguments(EXTRA_LLVM_MODULES) - # We need to find exactly the right LLVM version, our code usually does not # work across LLVM »minor« releases. find_package(LLVM 3.0 EXACT REQUIRED - bitwriter linker ipo instrumentation backend ${EXTRA_LLVM_MODULES}) + all-targets bitwriter linker ipo instrumentation backend ${EXTRA_LLVM_MODULES}) +math(EXPR LDC_LLVM_VER ${LLVM_VERSION_MAJOR}*100+${LLVM_VERSION_MINOR}) # # Locate libconfig++. @@ -94,7 +87,7 @@ set_target_properties( idgen impcnvgen PROPERTIES LINKER_LANGUAGE CXX RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${DMDFE_PATH} - COMPILE_FLAGS ${LLVM_CXXFLAGS} + COMPILE_FLAGS "${LLVM_CXXFLAGS}" ) get_target_property(IDGEN_LOC idgen LOCATION) get_target_property(IMPCNVGEN_LOC impcnvgen LOCATION) @@ -123,68 +116,6 @@ set(LDC_GENERATED ${PROJECT_BINARY_DIR}/${DMDFE_PATH}/impcnvtab.c ) -# -# Set up target defines. -# - -set(DEFAULT_TARGET ${LLVM_HOST_TARGET} CACHE STRING "default target") -add_definitions(-DDEFAULT_TARGET_TRIPLE="${DEFAULT_TARGET}") - -# Generate the alternate target triple (x86 on x86_64 and vice versa.) -if(LLVM_HOST_TARGET MATCHES "i[3-9]86-") - string(REGEX REPLACE "^i[3-9]86-(.*)" "x86_64-\\1" HOST_ALT_TARGET ${LLVM_HOST_TARGET}) -elseif(LLVM_HOST_TARGET MATCHES "^x86_64-.*") - string(REGEX REPLACE "^x86_64-(.*)" "i686-\\1" HOST_ALT_TARGET ${LLVM_HOST_TARGET}) -endif() -set(DEFAULT_ALT_TARGET ${HOST_ALT_TARGET} CACHE STRING "default alt target") -add_definitions(-DDEFAULT_ALT_TARGET_TRIPLE="${DEFAULT_ALT_TARGET}") - -# -# Detect host architecture. -# The code borrowed from llvm's config-x.cmake. -# -# This is only needed to initialize the llvm native target which is -# exactly the purpose of llvm::InitializeNativeTarget* functions. -# Unfortunately, there is a bug in llvm's cmake script that prevents -# the asm parser from being initialized when the functions are used. -# So we have to do the dirty work ourselves. -string(REGEX MATCH "^[^-]*" HOST_ARCH ${LLVM_HOST_TARGET}) -if(HOST_ARCH MATCHES "i[2-6]86") - set(HOST_ARCH X86) -elseif(HOST_ARCH STREQUAL "x86") - set(HOST_ARCH X86) -elseif(HOST_ARCH STREQUAL "amd64") - set(HOST_ARCH X86) -elseif(HOST_ARCH STREQUAL "x86_64") - set(HOST_ARCH X86) -elseif(HOST_ARCH MATCHES "sparc") - set(HOST_ARCH Sparc) -elseif(HOST_ARCH MATCHES "powerpc") - set(HOST_ARCH PowerPC) -elseif(HOST_ARCH MATCHES "alpha") - set(HOST_ARCH Alpha) -elseif(HOST_ARCH MATCHES "arm") - set(HOST_ARCH ARM) -elseif(HOST_ARCH MATCHES "mips") - set(HOST_ARCH Mips) -elseif(HOST_ARCH MATCHES "xcore") - set(HOST_ARCH XCore) -elseif(HOST_ARCH MATCHES "msp430") - set(HOST_ARCH MSP430) -else(HOST_ARCH MATCHES "i[2-6]86") - message(FATAL_ERROR "Unknown architecture ${HOST_ARCH}") -endif(HOST_ARCH MATCHES "i[2-6]86") - -# Pass the list of LLVM targets as preprocessor constants. -foreach(TARGET ${HOST_ARCH} ${EXTRA_LLVM_MODULES}) - set(LLVM_MODULES_DEFINE "${LLVM_MODULES_DEFINE} LLVM_TARGET(${TARGET})") -endforeach(TARGET) - -set_source_files_properties( - ${PROJECT_SOURCE_DIR}/driver/main.cpp PROPERTIES - COMPILE_DEFINITIONS LDC_TARGETS=${LLVM_MODULES_DEFINE} -) - # # Gather source files. # @@ -270,6 +201,8 @@ add_definitions( -DIN_LLVM -DOPAQUE_VTBLS -DLDC_INSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}" + -DLDC_LLVM_VER=${LDC_LLVM_VER} + -DLDC_LLVM_VERSION_STRING="${LLVM_VERSION_STRING}" ) if(UNIX) @@ -317,7 +250,7 @@ set_target_properties( ) # LDFLAGS should actually be in target property LINK_FLAGS, but this works, and gets around linking problems -target_link_libraries(${LDC_LIB} "${LLVM_LDFLAGS} ${LLVM_LIBRARIES}") +target_link_libraries(${LDC_LIB} "${LLVM_LDFLAGS}" ${LLVM_LIBRARIES}) if(WIN32) target_link_libraries(${LDC_LIB} imagehlp psapi) elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") @@ -362,7 +295,7 @@ set_target_properties(${LDMD_EXE} PROPERTIES # use symbols from libdl, ..., so LLVM_LDFLAGS must come _after_ them in the # command line. Maybe this could be improved using library groups, at least with # GNU ld. -target_link_libraries(${LDMD_EXE} "${LLVM_LDFLAGS} ${LLVM_LIBRARIES} ${LLVM_LDFLAGS}") +target_link_libraries(${LDMD_EXE} "${LLVM_LDFLAGS}" ${LLVM_LIBRARIES} "${LLVM_LDFLAGS}") # # Install target. diff --git a/cmake/Modules/FindLLVM.cmake b/cmake/Modules/FindLLVM.cmake index 5e29bc8be2..25121025a4 100644 --- a/cmake/Modules/FindLLVM.cmake +++ b/cmake/Modules/FindLLVM.cmake @@ -49,41 +49,48 @@ if (NOT LLVM_CONFIG) endif() endif() else() - # llvm-config is written in Perl, thus we need to locate it first. - if(LLVM_FIND_QUIETLY) - set(_quiet_arg QUIET) - endif() - find_package(Perl ${_quiet_arg}) - - if(NOT PERL_FOUND) - if (NOT FIND_LLVM_QUIETLY) - message(WARNING "Need Perl to execute llvm-config.") + macro(llvm_set var flag) + if(LLVM_FIND_QUIETLY) + set(_quiet_arg ERROR_QUIET) endif() - else() - macro(llvm_set var flag) - if(LLVM_FIND_QUIETLY) - set(_quiet_arg ERROR_QUIET) - endif() - execute_process( - COMMAND ${PERL_EXECUTABLE} ${LLVM_CONFIG} --${flag} ${LLVM_FIND_COMPONENTS} - OUTPUT_VARIABLE LLVM_${var} - OUTPUT_STRIP_TRAILING_WHITESPACE ${_quiet_arg} - ) - endmacro() + execute_process( + COMMAND ${LLVM_CONFIG} --${flag} + OUTPUT_VARIABLE LLVM_${var} + OUTPUT_STRIP_TRAILING_WHITESPACE + ${_quiet_arg} + ) + endmacro() + macro(llvm_set_libs var flag prefix) + if(LLVM_FIND_QUIETLY) + set(_quiet_arg ERROR_QUIET) + endif() + execute_process( + COMMAND ${LLVM_CONFIG} --${flag} ${LLVM_FIND_COMPONENTS} + OUTPUT_VARIABLE tmplibs + OUTPUT_STRIP_TRAILING_WHITESPACE + ${_quiet_arg} + ) + string(REGEX MATCHALL "${prefix}[^ ]+" LLVM_${var} ${tmplibs}) + endmacro() - llvm_set(CXXFLAGS cxxflags) - llvm_set(HOST_TARGET host-target) - llvm_set(INCLUDE_DIRS includedir) - llvm_set(LDFLAGS ldflags) - llvm_set(LIBRARIES libfiles) - llvm_set(LIBRARY_DIRS libdir) - llvm_set(ROOT_DIR prefix) - llvm_set(VERSION_STRING version) + llvm_set(VERSION_STRING version) + if(${LLVM_VERSION_STRING} MATCHES "3.0[A-Za-z]*") + # Version 3.0 does not support component all-targets + llvm_set(TARGETS_BUILT targets-built) + list(REMOVE_ITEM LLVM_FIND_COMPONENTS "all-targets" index) + list(APPEND LLVM_FIND_COMPONENTS ${LLVM_TARGETS_BUILT}) endif() + llvm_set(CXXFLAGS cxxflags) + llvm_set(HOST_TARGET host-target) + llvm_set(INCLUDE_DIRS includedir) + llvm_set(LDFLAGS ldflags) + llvm_set(LIBRARY_DIRS libdir) + llvm_set_libs(LIBRARIES libfiles "${LLVM_LIBRARY_DIRS}/") + llvm_set(ROOT_DIR prefix) endif() string(REGEX REPLACE "([0-9]+).*" "\\1" LLVM_VERSION_MAJOR "${LLVM_VERSION_STRING}" ) -string(REGEX REPLACE "[0-9]+\\.([0-9]+).*" "\\1" LLVM_VERSION_MINOR "${LLVM_VERSION_STRING}" ) +string(REGEX REPLACE "[0-9]+\\.([0-9]+).*[A-Za-z]*" "\\1" LLVM_VERSION_MINOR "${LLVM_VERSION_STRING}" ) # Use the default CMake facilities for handling QUIET/REQUIRED. include(FindPackageHandleStandardArgs) diff --git a/driver/main.cpp b/driver/main.cpp index 2b97ba61a8..a294a7d834 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -3,6 +3,7 @@ // some things are taken from llvm's llc tool // which uses the llvm license +#include "gen/llvmcompat.h" #include "gen/llvm.h" #include "llvm/LinkAllVMCore.h" #include "llvm/Linker.h" @@ -85,7 +86,7 @@ void printVersion() { printf("D Language Documentation: http://d-programming-language.org/index.html\n" "LDC Homepage: https://github.com/ldc-developers/ldc\n"); printf("\n"); - printf(" Default target: %s\n", DEFAULT_TARGET_TRIPLE); + printf(" Default target: %s\n", llvm::sys::getDefaultTargetTriple().c_str()); std::string CPU = llvm::sys::getHostCPUName(); if (CPU == "generic") CPU = "(unknown)"; printf(" Host CPU: %s\n", CPU.c_str()); @@ -219,14 +220,11 @@ int main(int argc, char** argv) // Initialize LLVM. // Initialize targets first, so that --version shows registered targets. -#define LLVM_TARGET(A) \ - LLVMInitialize##A##TargetInfo(); \ - LLVMInitialize##A##Target(); \ - LLVMInitialize##A##AsmPrinter(); \ - LLVMInitialize##A##AsmParser(); \ - LLVMInitialize##A##TargetMC(); -LDC_TARGETS -#undef LLVM_TARGET + llvm::InitializeAllTargetInfos(); + llvm::InitializeAllTargets(); + llvm::InitializeAllTargetMCs(); + llvm::InitializeAllAsmPrinters(); + llvm::InitializeAllAsmParsers(); // Handle fixed-up arguments! cl::SetVersionPrinter(&printVersion); @@ -451,10 +449,22 @@ LDC_TARGETS fatal(); // override triple if needed - const char* defaultTriple = DEFAULT_TARGET_TRIPLE; - if ((sizeof(void*) == 4 && m64bits) || (sizeof(void*) == 8 && m32bits)) + std::string defaultTriple = llvm::sys::getDefaultTargetTriple(); + if (sizeof(void*) == 4 && m64bits) { - defaultTriple = DEFAULT_ALT_TARGET_TRIPLE; +#if LDC_LLVM_VER >= 301 + defaultTriple = llvm::Triple(defaultTriple).get64BitArchVariant().str(); +#else + defaultTriple = llvm::Triple__get64BitArchVariant(defaultTriple).str(); +#endif + } + else if (sizeof(void*) == 8 && m32bits) + { +#if LDC_LLVM_VER >= 301 + defaultTriple = llvm::Triple(defaultTriple).get32BitArchVariant().str(); +#else + defaultTriple = llvm::Triple__get32BitArchVariant(defaultTriple).str(); +#endif } // did the user override the target triple? @@ -465,7 +475,7 @@ LDC_TARGETS error("you must specify a target triple as well with -mtriple when using the -march option"); fatal(); } - global.params.targetTriple = defaultTriple; + global.params.targetTriple = defaultTriple.c_str(); } else { @@ -603,79 +613,61 @@ LDC_TARGETS // parse the OS out of the target triple // see http://gcc.gnu.org/install/specific.html for details // also llvm's different SubTargets have useful information - size_t npos = std::string::npos; - - // windows - if (triple.find("win32") != npos) + switch (llvm::Triple(triple).getOS()) { - global.params.os = OSWindows; - VersionCondition::addPredefinedGlobalIdent("Windows"); - VersionCondition::addPredefinedGlobalIdent("Win32"); - if (global.params.is64bit) { - VersionCondition::addPredefinedGlobalIdent("Win64"); - } - } - // FIXME: mingw - else if (triple.find("mingw") != npos) - { - global.params.os = OSWindows; - VersionCondition::addPredefinedGlobalIdent("Windows"); - VersionCondition::addPredefinedGlobalIdent("Win32"); - VersionCondition::addPredefinedGlobalIdent("mingw32"); - VersionCondition::addPredefinedGlobalIdent("MinGW"); - if (global.params.is64bit) { - VersionCondition::addPredefinedGlobalIdent("Win64"); - } - } - // FIXME: cygwin - else if (triple.find("cygwin") != npos) - { - error("CygWin is not yet supported"); - fatal(); - } - // linux - else if (triple.find("linux") != npos) - { - global.params.os = OSLinux; - VersionCondition::addPredefinedGlobalIdent("linux"); - VersionCondition::addPredefinedGlobalIdent("Posix"); - } - // haiku - else if (triple.find("haiku") != npos) - { - global.params.os = OSHaiku; - VersionCondition::addPredefinedGlobalIdent("Haiku"); - VersionCondition::addPredefinedGlobalIdent("Posix"); - } - // darwin - else if (triple.find("-darwin") != npos) - { - global.params.os = OSMacOSX; - VersionCondition::addPredefinedGlobalIdent("OSX"); - VersionCondition::addPredefinedGlobalIdent("darwin"); - VersionCondition::addPredefinedGlobalIdent("Posix"); - } - // freebsd - else if (triple.find("-freebsd") != npos) - { - global.params.os = OSFreeBSD; - VersionCondition::addPredefinedGlobalIdent("freebsd"); - VersionCondition::addPredefinedGlobalIdent("FreeBSD"); - VersionCondition::addPredefinedGlobalIdent("Posix"); - } - // solaris - else if (triple.find("-solaris") != npos) - { - global.params.os = OSSolaris; - VersionCondition::addPredefinedGlobalIdent("solaris"); - VersionCondition::addPredefinedGlobalIdent("Solaris"); - VersionCondition::addPredefinedGlobalIdent("Posix"); - } - // unsupported - else - { - error("target '%s' is not yet supported", global.params.targetTriple); - fatal(); + case llvm::Triple::Win32: + global.params.os = OSWindows; + VersionCondition::addPredefinedGlobalIdent("Windows"); + VersionCondition::addPredefinedGlobalIdent("Win32"); + if (global.params.is64bit) { + VersionCondition::addPredefinedGlobalIdent("Win64"); + } + break; + case llvm::Triple::MinGW32: + global.params.os = OSWindows; + VersionCondition::addPredefinedGlobalIdent("Windows"); + VersionCondition::addPredefinedGlobalIdent("Win32"); + VersionCondition::addPredefinedGlobalIdent("mingw32"); + VersionCondition::addPredefinedGlobalIdent("MinGW"); + if (global.params.is64bit) { + VersionCondition::addPredefinedGlobalIdent("Win64"); + } + break; + case llvm::Triple::Cygwin: + error("CygWin is not yet supported"); + fatal(); + break; + case llvm::Triple::Linux: + global.params.os = OSLinux; + VersionCondition::addPredefinedGlobalIdent("linux"); + VersionCondition::addPredefinedGlobalIdent("Posix"); + break; + case llvm::Triple::Haiku: + global.params.os = OSHaiku; + VersionCondition::addPredefinedGlobalIdent("Haiku"); + VersionCondition::addPredefinedGlobalIdent("Posix"); + break; + case llvm::Triple::Darwin: + global.params.os = OSMacOSX; + VersionCondition::addPredefinedGlobalIdent("OSX"); + VersionCondition::addPredefinedGlobalIdent("darwin"); + VersionCondition::addPredefinedGlobalIdent("Posix"); + break; + case llvm::Triple::FreeBSD: + global.params.os = OSFreeBSD; + VersionCondition::addPredefinedGlobalIdent("freebsd"); + VersionCondition::addPredefinedGlobalIdent("FreeBSD"); + VersionCondition::addPredefinedGlobalIdent("Posix"); + break; + case llvm::Triple::Solaris: + global.params.os = OSSolaris; + VersionCondition::addPredefinedGlobalIdent("solaris"); + VersionCondition::addPredefinedGlobalIdent("Solaris"); + VersionCondition::addPredefinedGlobalIdent("Posix"); + break; + default: + error("target '%s' is not yet supported", global.params.targetTriple); + fatal(); } if (global.params.os == OSWindows) { diff --git a/gen/llvmcompat.cpp b/gen/llvmcompat.cpp new file mode 100644 index 0000000000..11bf153f49 --- /dev/null +++ b/gen/llvmcompat.cpp @@ -0,0 +1,83 @@ +#include "gen/llvmcompat.h" +#include "llvm/Config/llvm-config.h" +#include "llvm/ADT/Triple.h" +#include + +#if LDC_LLVM_VER == 300 +namespace llvm { + namespace sys { + std::string getDefaultTargetTriple() { + return LLVM_HOSTTRIPLE; + } + } + + Triple Triple__get32BitArchVariant(const std::string& triple) { + Triple T(triple); + switch (T.getArch()) { + case Triple::UnknownArch: + case Triple::msp430: + T.setArch(Triple::UnknownArch); + break; + + case Triple::amdil: + case Triple::arm: + case Triple::cellspu: + case Triple::le32: + case Triple::mblaze: + case Triple::mips: + case Triple::mipsel: + case Triple::ppc: + case Triple::sparc: + case Triple::tce: + case Triple::thumb: + case Triple::x86: + case Triple::xcore: + // Already 32-bit. + break; + + case Triple::mips64: T.setArch(Triple::mips); break; + case Triple::mips64el: T.setArch(Triple::mipsel); break; + case Triple::ppc64: T.setArch(Triple::ppc); break; + case Triple::sparcv9: T.setArch(Triple::sparc); break; + case Triple::x86_64: T.setArch(Triple::x86); break; + } + return T; + } + + Triple Triple__get64BitArchVariant(const std::string& triple) { + Triple T(triple); + switch (T.getArch()) { + case Triple::UnknownArch: + case Triple::amdil: + case Triple::arm: + case Triple::cellspu: + case Triple::le32: + case Triple::mblaze: + case Triple::msp430: + case Triple::tce: + case Triple::thumb: + case Triple::xcore: + T.setArch(Triple::UnknownArch); + break; + + case Triple::mips64: + case Triple::mips64el: + case Triple::ppc64: + case Triple::sparcv9: + case Triple::x86_64: + // Already 64-bit. + break; + + case Triple::mips: T.setArch(Triple::mips64); break; + case Triple::mipsel: T.setArch(Triple::mips64el); break; + case Triple::ppc: T.setArch(Triple::ppc64); break; + case Triple::sparc: T.setArch(Triple::sparcv9); break; + case Triple::x86: T.setArch(Triple::x86_64); break; + } + return T; + } + +} +#endif + + diff --git a/gen/llvmcompat.h b/gen/llvmcompat.h new file mode 100644 index 0000000000..693e828c82 --- /dev/null +++ b/gen/llvmcompat.h @@ -0,0 +1,26 @@ +#ifdef _MSC_VER +#pragma once +#endif + +#ifndef LDC_LLVMCOMPAT_H +#define LDC_LLVMCOMPAT_H + +#include "llvm/ADT/Triple.h" +#include + +#if !defined(LDC_LLVM_VER) +#error "Please specify value for LDC_LLVM_VER." +#endif + +#if LDC_LLVM_VER == 300 +namespace llvm { + namespace sys { + std::string getDefaultTargetTriple(); + } + + Triple Triple__get32BitArchVariant(const std::string&_this); + Triple Triple__get64BitArchVariant(const std::string& _this); +} +#endif + +#endif