diff --git a/CMakeLists.txt b/CMakeLists.txt index e52bf64..68808f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,6 +76,8 @@ include(FindPkgConfig) find_package(PkgConfig REQUIRED) pkg_search_module(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +link_libraries(PkgConfig::GLIB) + # ------------------------------------------------ # # TOML-C99 # # ------------------------------------------------ # @@ -96,6 +98,21 @@ set_target_properties(tomlc99 include_directories(${PROJECT_SOURCE_DIR}/dep/tomlc99) +link_libraries(tomlc99) + +# ------------------------------------------------ # +# LLD-C-Layer # +# ------------------------------------------------ # + +add_subdirectory(dep/lldcl) + +# Link lld libs and C++ LIBC +link_libraries(lldcl + lldCommon + lldCOFF + lldELF + lldMinGW + stdc++) # ------------------------------------------------ # # LLVM backend # @@ -144,10 +161,6 @@ set_target_properties(release OUTPUT_NAME "gsc" RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/release) -target_link_libraries(release PkgConfig::GLIB) - -target_link_libraries(release tomlc99) - # FIXME: cannot compile with /O2 because of /RTC1 flag if (MSVC) set(RELEASE_FLAGS) @@ -183,10 +196,6 @@ set_target_properties(debug OUTPUT_NAME "gsc" RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/debug) -target_link_libraries(debug PkgConfig::GLIB) - -target_link_libraries(debug tomlc99) - if (MSVC) set(DEBUG_FLAGS /DEBUG) else() @@ -216,10 +225,6 @@ set_target_properties(check OUTPUT_NAME "gsc" RUNTIME_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/check) -target_link_libraries(check PkgConfig::GLIB) - -target_link_libraries(check tomlc99) - if (MSVC) set(CHECK_FLAGS /DEBUG /WX) else() diff --git a/dep/lldcl/CMakeLists.txt b/dep/lldcl/CMakeLists.txt new file mode 100644 index 0000000..c4cfbeb --- /dev/null +++ b/dep/lldcl/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.15...3.25) + +project(gemstone + VERSION 0.1.0 + DESCRIPTION "programming language compiler lld c++ layer" + LANGUAGES CXX) + +set(GEMSTONE_BINARY_DIR ${PROJECT_SOURCE_DIR}/../../bin) + +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# ------------------------------------------------ # +# LLVM # +# ------------------------------------------------ # + +# Fetch LLVM link configuration +execute_process(COMMAND llvm-config --libs all + OUTPUT_VARIABLE LLVM_LIBS) +# Strip whitespace from output +string(STRIP "${LLVM_LIBS}" LLVM_LIBS) +# Link all targets to LLVM +link_libraries(${LLVM_LIBS}) + +execute_process(COMMAND llvm-config --includedir + OUTPUT_VARIABLE LLVM_INCLUDE_DIR) +string(STRIP "${LLVM_INCLUDE_DIR}" LLVM_INCLUDE_DIR) +include_directories(${LLVM_INCLUDE_DIR}) + +file(GLOB_RECURSE SOURCE_FILES *.cpp) + +add_library(lldcl ${SOURCE_FILES}) +target_link_libraries(lldcl) +set_target_properties(lldcl + PROPERTIES + OUTPUT_NAME "lldcl" + ARCHIVE_OUTPUT_DIRECTORY ${GEMSTONE_BINARY_DIR}/dep) diff --git a/dep/lldcl/lldcl.cpp b/dep/lldcl/lldcl.cpp new file mode 100644 index 0000000..30f0c4e --- /dev/null +++ b/dep/lldcl/lldcl.cpp @@ -0,0 +1,50 @@ +// +// Created by servostar on 6/8/24. +// +// based on: https://github.com/llvm/llvm-project/blob/main/lld/unittests/AsLibAll/AllDrivers.cpp +// https://github.com/numba/llvmlite/blob/main/ffi/linker.cpp + +#include +#include + +/* + * Gemstone supports Windows (COFF, MinGW) and GNU/Linux (ELF) + */ + +LLD_HAS_DRIVER(coff) +LLD_HAS_DRIVER(elf) +LLD_HAS_DRIVER(mingw) +// LLD_HAS_DRIVER(macho) +// LLD_HAS_DRIVER(wasm) + +#define LLD_COFF_ELF_MINGW_DRIVER { {lld::WinLink, &lld::coff::link}, {lld::Gnu, &lld::elf::link}, {lld::MinGW, &lld::mingw::link} } + +extern "C" { + +/** + * @brief C-wrapper for lldMain which is written in C++ + * @param Argc + * @param Argv + * @param outstr + * @return + */ +int lld_main(int Argc, const char **Argv, const char **outstr) { + // StdOut + std::string stdout; + llvm::raw_string_ostream stdout_stream(stdout); + + // StdErr + std::string stderr; + llvm::raw_string_ostream stderr_stream(stderr); + + // convert arguments + std::vector Args(Argv, Argv + Argc); + + lld::Result result = lld::lldMain(Args, stdout_stream, stderr_stream, LLD_COFF_ELF_MINGW_DRIVER); + + *outstr = strdup(stdout.c_str()); + + return !result.retCode && result.canRunAgain; +} + +} // extern "C" diff --git a/src/llvm/link/lld.c b/src/llvm/link/lld.c index 7aa5be4..f4e2d24 100644 --- a/src/llvm/link/lld.c +++ b/src/llvm/link/lld.c @@ -5,6 +5,11 @@ #include #include +/* + * call the LLD linker + */ +extern int lld_main(int Argc, const char **Argv, const char **outstr); + const char* get_absolute_link_path(const TargetConfig* config, const char* link_target_name) { for (guint i = 0; i < config->link_search_paths->len; i++) { @@ -72,6 +77,18 @@ TargetLinkConfig* lld_create_link_config(const Target* target, const TargetConfi BackendError lld_link_target(TargetLinkConfig* config) { BackendError err = SUCCESS; + const char* message = NULL; + int status = lld_main(0, NULL, &message); + + if (message != NULL) { + print_message(Warning, "Message from LLD: %s", message); + free((void*) message); + } + + if (status != 0) { + err = new_backend_impl_error(Implementation, NULL, "failed to link target"); + } + return err; }