diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c31e4ac0..9dd403204 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,6 +63,7 @@ set(C3_LLVM_VERSION "auto" CACHE STRING "Use LLVM version [default: auto]") option(C3_USE_MIMALLOC "Use built-in mimalloc" OFF) option(C3_USE_TB "Use TB" OFF) set(C3_MIMALLOC_TAG "v1.7.3" CACHE STRING "Used version of mimalloc") +option(C3_WITH_LLVM "Build with LLVM" ON) set(C3_USE_MIMALLOC OFF) if(C3_USE_MIMALLOC) @@ -80,9 +81,11 @@ endif() if (NOT WIN32) find_package(CURL) endif() -if (NOT C3_LLVM_VERSION STREQUAL "auto") - if (${C3_LLVM_VERSION} VERSION_LESS 17 OR ${C3_LLVM_VERSION} VERSION_GREATER 20) - message(FATAL_ERROR "LLVM ${C3_LLVM_VERSION} is not supported!") +if(C3_WITH_LLVM) + if (NOT C3_LLVM_VERSION STREQUAL "auto") + if (${C3_LLVM_VERSION} VERSION_LESS 17 OR ${C3_LLVM_VERSION} VERSION_GREATER 20) + message(FATAL_ERROR "LLVM ${C3_LLVM_VERSION} is not supported!") + endif() endif() endif() @@ -112,113 +115,115 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) ) endif(C3_ENABLE_CLANGD_LSP) -if(CMAKE_C_COMPILER_ID STREQUAL "MSVC") - if (C3_LLVM_VERSION STREQUAL "auto") - set(C3_LLVM_VERSION "18") - endif() - FetchContent_Declare( - LLVM_Windows - URL https://github.com/c3lang/win-llvm/releases/download/llvm_18_1_8_with_rt/llvm-18.1.8-windows-amd64-msvc17-libcmt.7z - ) - FetchContent_Declare( - LLVM_Windows_debug - URL https://github.com/c3lang/win-llvm/releases/download/llvm_18_1_8_with_rt/llvm-18.1.8-windows-amd64-msvc17-libcmt-dbg.7z - ) - if(CMAKE_BUILD_TYPE STREQUAL "Debug") - message("Loading Windows LLVM debug libraries, this may take a while...") - FetchContent_MakeAvailable(LLVM_Windows_debug) - set(llvm_dir ${llvm_windows_debug_SOURCE_DIR}) - else() - message("Loading Windows LLVM libraries, this may take a while...") - FetchContent_MakeAvailable(LLVM_Windows) - set(llvm_dir ${llvm_windows_SOURCE_DIR}) - endif() - set(CMAKE_SYSTEM_PREFIX_PATH ${llvm_dir} ${CMAKE_SYSTEM_PREFIX_PATH}) +if(C3_WITH_LLVM) + if(CMAKE_C_COMPILER_ID STREQUAL "MSVC") + if (C3_LLVM_VERSION STREQUAL "auto") + set(C3_LLVM_VERSION "18") + endif() + FetchContent_Declare( + LLVM_Windows + URL https://github.com/c3lang/win-llvm/releases/download/llvm_18_1_8_with_rt/llvm-18.1.8-windows-amd64-msvc17-libcmt.7z + ) + FetchContent_Declare( + LLVM_Windows_debug + URL https://github.com/c3lang/win-llvm/releases/download/llvm_18_1_8_with_rt/llvm-18.1.8-windows-amd64-msvc17-libcmt-dbg.7z + ) + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + message("Loading Windows LLVM debug libraries, this may take a while...") + FetchContent_MakeAvailable(LLVM_Windows_debug) + set(llvm_dir ${llvm_windows_debug_SOURCE_DIR}) + else() + message("Loading Windows LLVM libraries, this may take a while...") + FetchContent_MakeAvailable(LLVM_Windows) + set(llvm_dir ${llvm_windows_SOURCE_DIR}) + endif() + set(CMAKE_SYSTEM_PREFIX_PATH ${llvm_dir} ${CMAKE_SYSTEM_PREFIX_PATH}) - find_package(LLVM REQUIRED CONFIG) - find_package(LLD REQUIRED CONFIG) -else() - if (NOT C3_LLVM_VERSION STREQUAL "auto") - find_package(LLVM ${C3_LLVM_VERSION} REQUIRED CONFIG) - else() find_package(LLVM REQUIRED CONFIG) + find_package(LLD REQUIRED CONFIG) + else() + if (NOT C3_LLVM_VERSION STREQUAL "auto") + find_package(LLVM ${C3_LLVM_VERSION} REQUIRED CONFIG) + else() + find_package(LLVM REQUIRED CONFIG) + endif() endif() -endif() -message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") -message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") -message(STATUS "Libraries located in: ${LLVM_LIBRARY_DIRS}") + message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") + message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") + message(STATUS "Libraries located in: ${LLVM_LIBRARY_DIRS}") -if (NOT LLVM_PACKAGE_VERSION VERSION_GREATER_EQUAL 15.0) - message(FATAL_ERROR "LLVM version 15.0 or later is required.") -endif() + if (NOT LLVM_PACKAGE_VERSION VERSION_GREATER_EQUAL 15.0) + message(FATAL_ERROR "LLVM version 15.0 or later is required.") + endif() -if(LLVM_ENABLE_RTTI) - message(STATUS "LLVM was built with RTTI") -else() - message(STATUS "LLVM was not built with RTTI") -endif() + if(LLVM_ENABLE_RTTI) + message(STATUS "LLVM was built with RTTI") + else() + message(STATUS "LLVM was not built with RTTI") + endif() -string(REPLACE "." ";" VERSION_LIST ${LLVM_PACKAGE_VERSION}) -list(GET VERSION_LIST 0 LLVM_MAJOR_VERSION) + string(REPLACE "." ";" VERSION_LIST ${LLVM_PACKAGE_VERSION}) + list(GET VERSION_LIST 0 LLVM_MAJOR_VERSION) -include_directories(${LLVM_INCLUDE_DIRS}) -link_directories(${LLVM_LIBRARY_DIRS}) -add_definitions(${LLVM_DEFINITIONS}) + include_directories(${LLVM_INCLUDE_DIRS}) + link_directories(${LLVM_LIBRARY_DIRS}) + add_definitions(${LLVM_DEFINITIONS}) -if(NOT C3_LINK_DYNAMIC) - set(LLVM_LINK_COMPONENTS - AllTargetsAsmParsers - AllTargetsCodeGens - AllTargetsDescs - AllTargetsDisassemblers - AllTargetsInfos - Analysis - AsmPrinter - BitReader - Core - DebugInfoPDB - InstCombine - IrReader - LibDriver - Linker - LTO - MC - MCDisassembler - native - nativecodegen - Object - Option - ScalarOpts - Support - Target - TransformUtils - WindowsManifest - WindowsDriver - ) + if(NOT C3_LINK_DYNAMIC) + set(LLVM_LINK_COMPONENTS + AllTargetsAsmParsers + AllTargetsCodeGens + AllTargetsDescs + AllTargetsDisassemblers + AllTargetsInfos + Analysis + AsmPrinter + BitReader + Core + DebugInfoPDB + InstCombine + IrReader + LibDriver + Linker + LTO + MC + MCDisassembler + native + nativecodegen + Object + Option + ScalarOpts + Support + Target + TransformUtils + WindowsManifest + WindowsDriver + ) - llvm_map_components_to_libnames(llvm_libs ${LLVM_LINK_COMPONENTS}) + llvm_map_components_to_libnames(llvm_libs ${LLVM_LINK_COMPONENTS}) - # These don't seem to be reliable on windows. - message(STATUS "using find_library") - find_library(LLD_COFF NAMES lldCOFF.lib lldCOFF.a liblldCOFF.a PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) - find_library(LLD_COMMON NAMES lldCommon.lib lldCommon.a liblldCommon.a PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) - find_library(LLD_ELF NAMES lldELF.lib lldELF.a liblldELF.a PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) - find_library(LLD_MACHO NAMES lldMachO.lib lldMachO.a liblldMachO.a PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) - find_library(LLD_MINGW NAMES lldMinGW.lib lldMinGW.a liblldMinGW.a PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) - find_library(LLD_WASM NAMES lldWasm.lib lldWasm.a liblldWasm.a PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) -else() - find_library(LLVM NAMES libLLVM.so PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) - set(llvm_libs ${LLVM}) + # These don't seem to be reliable on windows. + message(STATUS "using find_library") + find_library(LLD_COFF NAMES lldCOFF.lib lldCOFF.a liblldCOFF.a PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) + find_library(LLD_COMMON NAMES lldCommon.lib lldCommon.a liblldCommon.a PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) + find_library(LLD_ELF NAMES lldELF.lib lldELF.a liblldELF.a PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) + find_library(LLD_MACHO NAMES lldMachO.lib lldMachO.a liblldMachO.a PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) + find_library(LLD_MINGW NAMES lldMinGW.lib lldMinGW.a liblldMinGW.a PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) + find_library(LLD_WASM NAMES lldWasm.lib lldWasm.a liblldWasm.a PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) + else() + find_library(LLVM NAMES libLLVM.so PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) + set(llvm_libs ${LLVM}) - # These don't seem to be reliable on windows. - message(STATUS "using find_library") - find_library(LLD_COFF NAMES liblldCOFF.so PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) - find_library(LLD_COMMON NAMES liblldCommon.so PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) - find_library(LLD_ELF NAMES liblldELF.so PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) - find_library(LLD_MACHO NAMES liblldMachO.so PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) - find_library(LLD_MINGW NAMES liblldMinGW.so PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) - find_library(LLD_WASM NAMES liblldWasm.so PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) + # These don't seem to be reliable on windows. + message(STATUS "using find_library") + find_library(LLD_COFF NAMES liblldCOFF.so PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) + find_library(LLD_COMMON NAMES liblldCommon.so PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) + find_library(LLD_ELF NAMES liblldELF.so PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) + find_library(LLD_MACHO NAMES liblldMachO.so PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) + find_library(LLD_MINGW NAMES liblldMinGW.so PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) + find_library(LLD_WASM NAMES liblldWasm.so PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) + endif() endif() if (NOT(${CMAKE_BINARY_DIR} EQUAL ${CMAKE_SOURCE_DIR})) @@ -226,36 +231,36 @@ if (NOT(${CMAKE_BINARY_DIR} EQUAL ${CMAKE_SOURCE_DIR})) file(COPY ${CMAKE_SOURCE_DIR}/lib DESTINATION ${CMAKE_BINARY_DIR}) endif() -find_library(LLD_LOONG NAMES libLLVMLoongArchCodeGen.lib libLLVMLoongArchAsmParser.lib libLLVMLoongArchCodeGen.a libLLVMLoongArchAsmParser.a PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) -set(lld_libs - ${LLD_COFF} - ${LLD_COMMON} - ${LLD_WASM} - ${LLD_MINGW} - ${LLD_ELF} - ${LLD_MACHO} - ) - -if (APPLE) - set(lld_libs ${lld_libs} xar) - find_file(RT_ASAN_DYNAMIC NAMES libclang_rt.asan_osx_dynamic.dylib PATHS "${LLVM_LIBRARY_DIRS}/clang/${LLVM_MAJOR_VERSION}/lib/darwin") - find_file(RT_TSAN_DYNAMIC NAMES libclang_rt.tsan_osx_dynamic.dylib PATHS "${LLVM_LIBRARY_DIRS}/clang/${LLVM_MAJOR_VERSION}/lib/darwin") - find_file(RT_UBSAN_DYNAMIC NAMES libclang_rt.ubsan_osx_dynamic.dylib PATHS "${LLVM_LIBRARY_DIRS}/clang/${LLVM_MAJOR_VERSION}/lib/darwin") - find_file(RT_LSAN_DYNAMIC NAMES libclang_rt.lsan_osx_dynamic.dylib PATHS "${LLVM_LIBRARY_DIRS}/clang/${LLVM_MAJOR_VERSION}/lib/darwin") - set(sanitizer_runtime_libraries - ${RT_ASAN_DYNAMIC} - ${RT_TSAN_DYNAMIC} - # Unused - # ${RT_UBSAN_DYNAMIC} - # ${RT_LSAN_DYNAMIC} +if(C3_WITH_LLVM) + find_library(LLD_LOONG NAMES libLLVMLoongArchCodeGen.lib libLLVMLoongArchAsmParser.lib libLLVMLoongArchCodeGen.a libLLVMLoongArchAsmParser.a PATHS ${LLVM_LIBRARY_DIRS} NO_DEFAULT_PATH) + set(lld_libs + ${LLD_COFF} + ${LLD_COMMON} + ${LLD_WASM} + ${LLD_MINGW} + ${LLD_ELF} + ${LLD_MACHO} ) + + if (APPLE) + set(lld_libs ${lld_libs} xar) + find_file(RT_ASAN_DYNAMIC NAMES libclang_rt.asan_osx_dynamic.dylib PATHS "${LLVM_LIBRARY_DIRS}/clang/${LLVM_MAJOR_VERSION}/lib/darwin") + find_file(RT_TSAN_DYNAMIC NAMES libclang_rt.tsan_osx_dynamic.dylib PATHS "${LLVM_LIBRARY_DIRS}/clang/${LLVM_MAJOR_VERSION}/lib/darwin") + find_file(RT_UBSAN_DYNAMIC NAMES libclang_rt.ubsan_osx_dynamic.dylib PATHS "${LLVM_LIBRARY_DIRS}/clang/${LLVM_MAJOR_VERSION}/lib/darwin") + find_file(RT_LSAN_DYNAMIC NAMES libclang_rt.lsan_osx_dynamic.dylib PATHS "${LLVM_LIBRARY_DIRS}/clang/${LLVM_MAJOR_VERSION}/lib/darwin") + set(sanitizer_runtime_libraries + ${RT_ASAN_DYNAMIC} + ${RT_TSAN_DYNAMIC} + # Unused + # ${RT_UBSAN_DYNAMIC} + # ${RT_LSAN_DYNAMIC} + ) + endif() + + message(STATUS "linking to llvm libs ${lld_libs}") + message(STATUS "Found lld libs ${lld_libs}") endif() -message(STATUS "linking to llvm libs ${lld_libs}") -message(STATUS "Found lld libs ${lld_libs}") - - -add_library(c3c_wrappers STATIC wrapper/src/wrapper.cpp) add_library(miniz STATIC dependencies/miniz/miniz.c) add_executable(c3c @@ -279,7 +284,6 @@ add_executable(c3c src/compiler/json_output.c src/compiler/lexer.c src/compiler/linker.c - src/compiler/llvm_codegen.c src/compiler/abi/c_abi_aarch64.c src/compiler/abi/c_abi.c src/compiler/abi/c_abi_riscv.c @@ -287,14 +291,6 @@ add_executable(c3c src/compiler/abi/c_abi_win64.c src/compiler/abi/c_abi_x64.c src/compiler/abi/c_abi_x86.c - src/compiler/llvm_codegen_debug_info.c - src/compiler/llvm_codegen_expr.c - src/compiler/llvm_codegen_function.c - src/compiler/llvm_codegen_instr.c - src/compiler/llvm_codegen_module.c - src/compiler/llvm_codegen_stmt.c - src/compiler/llvm_codegen_type.c - src/compiler/llvm_codegen_value.c src/compiler/module.c src/compiler/number.c src/compiler/parse_expr.c @@ -337,12 +333,10 @@ add_executable(c3c src/utils/cpus.c src/utils/unzipper.c src/compiler/decltable.c - src/compiler/mac_support.c - src/compiler/llvm_codegen_storeload.c + src/compiler/mac_support.c src/compiler/windows_support.c src/compiler/codegen_asm.c - src/compiler/asm_target.c - src/compiler/llvm_codegen_builtins.c + src/compiler/asm_target.c src/compiler/expr.c src/utils/time.c src/utils/http.c @@ -365,6 +359,36 @@ else() COMMAND ${CMAKE_COMMAND} -P "${CMAKE_CURRENT_LIST_DIR}/git_hash.cmake") endif() +if(C3_WITH_LLVM) + target_sources(c3c PRIVATE + src/compiler/llvm_codegen.c + src/compiler/llvm_codegen_debug_info.c + src/compiler/llvm_codegen_expr.c + src/compiler/llvm_codegen_function.c + src/compiler/llvm_codegen_instr.c + src/compiler/llvm_codegen_module.c + src/compiler/llvm_codegen_stmt.c + src/compiler/llvm_codegen_type.c + src/compiler/llvm_codegen_value.c + src/compiler/llvm_codegen_storeload.c + src/compiler/llvm_codegen_builtins.c) + + target_compile_definitions(c3c PUBLIC LLVM_AVAILABLE=1) + + add_library(c3c_wrappers STATIC wrapper/src/wrapper.cpp) +else() + target_sources(c3c PRIVATE src/utils/hostinfo.c) + + target_compile_definitions(c3c PUBLIC LLVM_AVAILABLE=0) +endif() + +target_include_directories(c3c PRIVATE + "${CMAKE_SOURCE_DIR}/src/" + "${CMAKE_BINARY_DIR}") + +target_include_directories(miniz PUBLIC + "${CMAKE_SOURCE_DIR}/dependencies/miniz/") + if (C3_USE_TB) file(GLOB tilde-sources tilde-backend/src/tb/*.c @@ -397,25 +421,29 @@ if (C3_USE_TB) target_include_directories(c3c PRIVATE "${CMAKE_SOURCE_DIR}/tilde-backend/include/") + else() + target_compile_definitions(c3c PUBLIC TB_AVAILABLE=0) + endif() +if(C3_WITH_LLVM) + target_link_libraries(c3c ${llvm_libs} miniz c3c_wrappers ${lld_libs}) -target_include_directories(c3c PRIVATE - "${CMAKE_SOURCE_DIR}/src/" - "${CMAKE_SOURCE_DIR}/wrapper/include/" - "${CMAKE_BINARY_DIR}") + target_include_directories(c3c PRIVATE + "${CMAKE_SOURCE_DIR}/wrapper/include/") + target_include_directories(c3c_wrappers PRIVATE + "${CMAKE_SOURCE_DIR}/wrapper/include/") -target_include_directories(c3c_wrappers PRIVATE - "${CMAKE_SOURCE_DIR}/wrapper/include/") + target_link_libraries(c3c_wrappers ${llvm_libs} ${lld_libs}) -target_include_directories(miniz PUBLIC - "${CMAKE_SOURCE_DIR}/dependencies/miniz/") +else() -target_link_libraries(c3c_wrappers ${llvm_libs} ${lld_libs}) -target_link_libraries(c3c ${llvm_libs} miniz c3c_wrappers ${lld_libs}) + target_link_libraries(c3c ${llvm_libs} miniz ${lld_libs}) + +endif() if(C3_USE_MIMALLOC) target_link_libraries(c3c mimalloc-static) @@ -442,36 +470,44 @@ endif() if(MSVC) message("Adding MSVC options") target_compile_options(c3c PRIVATE /wd4068 /wd4090 /WX /Wv:18) - target_compile_options(c3c_wrappers PUBLIC /wd4624 /wd4267 /wd4244 /WX /Wv:18) - if (NOT LLVM_ENABLE_RTTI) - target_compile_options(c3c_wrappers PUBLIC /GR-) + if(C3_WITH_LLVM) + target_compile_options(c3c_wrappers PUBLIC /wd4624 /wd4267 /wd4244 /WX /Wv:18) + if(NOT LLVM_ENABLE_RTTI) + target_compile_options(c3c_wrappers PUBLIC /GR-) + endif() + target_link_options(c3c_wrappers PUBLIC /ignore:4099) endif() - target_link_options(c3c_wrappers PUBLIC /ignore:4099) if(CMAKE_BUILD_TYPE STREQUAL "Debug") target_compile_options(c3c PUBLIC /MTd) - target_compile_options(c3c_wrappers PUBLIC /MTd) + if (C3_WITH_LLVM) + target_compile_options(c3c_wrappers PUBLIC /MTd) + endif() target_compile_options(miniz PUBLIC /MTd) if (C3_USE_TB) target_compile_options(tilde-backend PUBLIC /MTd) endif() else() target_compile_options(c3c PUBLIC /MT) - target_compile_options(c3c_wrappers PUBLIC /MT) + if (C3_WITH_LLVM) + target_compile_options(c3c_wrappers PUBLIC /MT) + endif() target_compile_options(miniz PUBLIC /MT) if (C3_USE_TB) target_compile_options(tilde-backend PUBLIC /MT) endif() endif() - set(clang_lib_dir ${llvm_dir}/lib/clang/${C3_LLVM_VERSION}/lib/windows) - set(sanitizer_runtime_libraries - ${clang_lib_dir}/clang_rt.asan-x86_64.lib - ${clang_lib_dir}/clang_rt.asan_dynamic-x86_64.lib - ${clang_lib_dir}/clang_rt.asan_dynamic-x86_64.dll - ${clang_lib_dir}/clang_rt.asan_dynamic_runtime_thunk-x86_64.lib) + if(C3_WITH_LLVM) + set(clang_lib_dir ${llvm_dir}/lib/clang/${C3_LLVM_VERSION}/lib/windows) + set(sanitizer_runtime_libraries + ${clang_lib_dir}/clang_rt.asan-x86_64.lib + ${clang_lib_dir}/clang_rt.asan_dynamic-x86_64.lib + ${clang_lib_dir}/clang_rt.asan_dynamic-x86_64.dll + ${clang_lib_dir}/clang_rt.asan_dynamic_runtime_thunk-x86_64.lib) + endif() else() message(STATUS "using gcc/clang warning switches") target_link_options(c3c PRIVATE -pthread) - if (NOT LLVM_ENABLE_RTTI) + if (C3_WITH_LLVM AND NOT LLVM_ENABLE_RTTI) target_compile_options(c3c_wrappers PRIVATE -fno-rtti) endif() target_compile_options(c3c PRIVATE -pthread -Wall -Werror -Wno-unknown-pragmas -Wno-unused-result @@ -481,7 +517,7 @@ endif() install(TARGETS c3c DESTINATION bin) install(DIRECTORY lib/ DESTINATION lib/c3) -if (DEFINED sanitizer_runtime_libraries) +if (C3_WITH_LLVM AND DEFINED sanitizer_runtime_libraries) add_custom_command(TARGET c3c POST_BUILD COMMAND "${CMAKE_COMMAND}" -E rm -rf -- $/c3c_rt COMMAND "${CMAKE_COMMAND}" -E make_directory $/c3c_rt diff --git a/src/build/build_options.c b/src/build/build_options.c index 2140b7ccf..eb9e2b60f 100644 --- a/src/build/build_options.c +++ b/src/build/build_options.c @@ -484,8 +484,22 @@ static void print_version(void) #endif PRINTF("Installed directory: %s", find_executable_path()); PRINTF("Git Hash: %s", GIT_HASH); + +#if LLVM_AVAILABLE && TB_AVAILABLE + PRINTF("Backends: LLVM; TB"); +#elif LLVM_AVAILABLE + PRINTF("Backends: LLVM"); +#elif TB_AVAILABLE + PRINTF("Backends: TB"); +#else + + PRINTF("No backends available"); +#endif + +#if LLVM_AVAILABLE PRINTF("LLVM version: %s", llvm_version); PRINTF("LLVM default target: %s", llvm_target); +#endif } static void add_linker_arg(BuildOptions *options, const char *arg) diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 554ee97ed..46c9dafb6 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -7,8 +7,10 @@ #include "../utils/whereami.h" #if PLATFORM_POSIX #include -#endif +#endif +#if LLVM_AVAILABLE #include "c3_llvm.h" +#endif #include #define MAX_OUTPUT_FILES 1000000 @@ -111,11 +113,18 @@ typedef struct CompileData_ Task task; } CompileData; +#if LLVM_AVAILABLE void thread_compile_task_llvm(void *compile_data) { CompileData *data = compile_data; data->object_name = llvm_codegen(data->context); } +#else +void thread_compile_task_llvm(void *compile_data) +{ + error_exit("LLVM backend not available."); +} +#endif void thread_compile_task_tb(void *compile_data) { @@ -451,9 +460,13 @@ void compiler_compile(void) switch (compiler.build.backend) { case BACKEND_LLVM: +#if LLVM_AVAILABLE gen_contexts = llvm_gen(modules, module_count); task = &thread_compile_task_llvm; - break; +#else + error_exit("C3C compiled without LLVM!"); +#endif + break; case BACKEND_TB: gen_contexts = tilde_gen(modules, module_count); task = &thread_compile_task_tb; @@ -1242,8 +1255,14 @@ void compile() setup_bool_define("COMPILER_SAFE_MODE", safe_mode_enabled()); setup_bool_define("DEBUG_SYMBOLS", compiler.build.debug_info == DEBUG_INFO_FULL); setup_bool_define("BACKTRACE", compiler.build.show_backtrace != SHOW_BACKTRACE_OFF); - setup_int_define("LLVM_VERSION", llvm_version_major, type_int); - setup_bool_define("BENCHMARKING", compiler.build.benchmarking); + +#if LLVM_AVAILABLE + setup_int_define("LLVM_VERSION", llvm_version_major, type_int); +#else + setup_int_define("LLVM_VERSION", 0, type_int); +#endif + + setup_bool_define("BENCHMARKING", compiler.build.benchmarking); setup_int_define("JMP_BUF_SIZE", jump_buffer_size(), type_int); setup_bool_define("TESTING", compiler.build.testing); setup_bool_define("ADDRESS_SANITIZER", compiler.build.feature.sanitize_address); diff --git a/src/compiler/linker.c b/src/compiler/linker.c index d05a5ac44..5300d1b28 100644 --- a/src/compiler/linker.c +++ b/src/compiler/linker.c @@ -1,6 +1,8 @@ #include "compiler_internal.h" #include "../utils/whereami.h" +#if LLVM_AVAILABLE #include "c3_llvm.h" +#endif #if PLATFORM_POSIX #include @@ -714,6 +716,7 @@ static bool link_exe(const char *output_file, const char **files_to_link, unsign // This isn't used in most cases, but its contents should get freed after linking. bool success; +#if LLVM_AVAILABLE unsigned count = assemble_link_arguments(args, vec_size(args)); switch (compiler.platform.object_format) { @@ -732,6 +735,10 @@ static bool link_exe(const char *output_file, const char **files_to_link, unsign default: UNREACHABLE } +#else + success = false; + error = "linking (.exe) is not implemented for C3C compiled without LLVM"; +#endif if (!success) { error_exit("Failed to create an executable: %s", error); @@ -960,8 +967,9 @@ bool dynamic_lib_linker(const char *output_file, const char **files, unsigned fi return true; } bool success; - const char *error = NULL; - unsigned count = assemble_link_arguments(args, vec_size(args)); + const char *error = NULL; +#if LLVM_AVAILABLE + unsigned count = assemble_link_arguments(args, vec_size(args)); switch (compiler.platform.object_format) { case OBJ_FORMAT_COFF: @@ -979,6 +987,10 @@ bool dynamic_lib_linker(const char *output_file, const char **files, unsigned fi default: UNREACHABLE } +#else + success = false; + error = "linking not implemented for c3c compiled without llvm"; +#endif if (!success) { error_exit("Failed to create a dynamic library: %s", error); @@ -989,6 +1001,7 @@ bool dynamic_lib_linker(const char *output_file, const char **files, unsigned fi bool static_lib_linker(const char *output_file, const char **files, unsigned file_count) { +#if LLVM_AVAILABLE ArFormat format; switch (compiler.platform.os) { @@ -1009,6 +1022,9 @@ bool static_lib_linker(const char *output_file, const char **files, unsigned fil break; } return llvm_ar(output_file, files, file_count, format); +#else + return false; +#endif } bool linker(const char *output_file, const char **files, unsigned file_count) diff --git a/src/compiler/target.c b/src/compiler/target.c index 986444a0b..f22b8630f 100644 --- a/src/compiler/target.c +++ b/src/compiler/target.c @@ -1,8 +1,14 @@ +#if LLVM_AVAILABLE #include #include #include +#endif #include "compiler_internal.h" +#if LLVM_AVAILABLE #include "c3_llvm.h" +#else +#include "utils/hostinfo.h" +#endif static bool x64features_contains(X86Features *cpu_features, X86Feature feature); static ObjectFormatType object_format_from_os(OsType os, ArchType arch_type); @@ -782,17 +788,24 @@ static const char *x86_cpu_from_set(X86CpuSet set) case X86CPU_AVX512: return "x86-64-v4"; case X86CPU_NATIVE: +#if LLVM_AVAILABLE return LLVMGetHostCPUName(); - } +#else + return hostinfo_x86_cpu_name(); +#endif + } UNREACHABLE } static void x86_features_from_host(X86Features *cpu_features) { +#if LLVM_AVAILABLE char *features = LLVMGetHostCPUFeatures(); INFO_LOG("Detected the following host features: %s", features); - INFO_LOG("For %s", LLVMGetHostCPUName()); - char *tok = strtok(features, ","); + INFO_LOG("For %s", + LLVMGetHostCPUName()); + + char *tok = strtok(features, ","); *cpu_features = x86_feature_zero; while (tok != NULL) { @@ -822,6 +835,9 @@ static void x86_features_from_host(X86Features *cpu_features) tok = strtok(NULL, ","); } LLVMDisposeMessage(features); +#else + hostinfo_x86_features(cpu_features); +#endif } static void x86features_from_cpu(X86Features *cpu_features, X86CpuSet cpu_set) @@ -1530,7 +1546,7 @@ static AlignData os_target_alignment_of_int(OsType os, ArchType arch, uint32_t b case ARCH_TYPE_XTENSA: return (AlignData) { MIN(64u, bits), MIN(64u, bits) }; case ARCH_TYPE_X86_64: -#if LLVM_VERSION_MAJOR < 18 +#if !LLVM_AVAILABLE || LLVM_VERSION_MAJOR < 18 return (AlignData) { MIN(64u, bits), MIN(64u, bits) }; #else FALLTHROUGH; @@ -1543,7 +1559,7 @@ static AlignData os_target_alignment_of_int(OsType os, ArchType arch, uint32_t b return (AlignData) { bits, bits }; case ARCH_TYPE_X86: if (bits <= 32) return (AlignData) { bits, bits }; -#if LLVM_VERSION_MAJOR > 17 +#if !LLVM_AVAILABLE || LLVM_VERSION_MAJOR > 17 if (bits == 128) return (AlignData) { 128, 128 }; #endif if (os == OS_TYPE_ELFIAMCU) return (AlignData) { 32, 32 }; @@ -1718,19 +1734,6 @@ static bool arch_os_pic_default_forced(ArchType arch, OsType os) UNREACHABLE } - - - -#define INITIALIZE_TARGET(X) do { \ - DEBUG_LOG("Initialize target: %s.", #X); \ - LLVMInitialize ## X ## AsmParser(); \ - LLVMInitialize ## X ## AsmPrinter(); \ - LLVMInitialize ## X ## TargetInfo(); \ - LLVMInitialize ## X ## Target(); \ - LLVMInitialize ## X ## Disassembler(); \ - LLVMInitialize ## X ## TargetMC(); \ - } while(0) - INLINE const char *llvm_macos_target_triple(const char *triple) { if (compiler.build.macos.min_version) @@ -1755,6 +1758,17 @@ INLINE const char *llvm_macos_target_triple(const char *triple) return scratch_buffer_to_string(); } +#if LLVM_AVAILABLE +#define INITIALIZE_TARGET(X) do { \ + DEBUG_LOG("Initialize target: %s.", #X); \ + LLVMInitialize ## X ## AsmParser(); \ + LLVMInitialize ## X ## AsmPrinter(); \ + LLVMInitialize ## X ## TargetInfo(); \ + LLVMInitialize ## X ## Target(); \ + LLVMInitialize ## X ## Disassembler(); \ + LLVMInitialize ## X ## TargetMC(); \ + } while(0) + #if LLVM_VERSION_MAJOR > 19 #define XTENSA_AVAILABLE 1 #else @@ -1815,7 +1829,11 @@ void *llvm_target_machine_create(void) return result; } +#else +#define XTENSA_AVAILABLE 1 + +#endif void target_setup(BuildTarget *target) @@ -1843,6 +1861,7 @@ void target_setup(BuildTarget *target) compiler.platform.alloca_address_space = 0; +#if LLVM_AVAILABLE // Create a specific target machine LLVMCodeGenOptLevel level; @@ -1867,8 +1886,15 @@ void target_setup(BuildTarget *target) } compiler.platform.llvm_opt_level = (int)level; +#endif + INFO_LOG("Triple picked was %s.", compiler.platform.target_triple); - INFO_LOG("Default was %s.", LLVM_DEFAULT_TARGET_TRIPLE); + +#if LLVM_AVAILABLE + INFO_LOG("Default was %s.", LLVM_DEFAULT_TARGET_TRIPLE); +#else + INFO_LOG("Default was %s.", hostinfo_default_triple()); +#endif StringSlice target_triple_string = slice_from_string(compiler.platform.target_triple); compiler.platform.arch = arch_from_llvm_string(slice_next_token(&target_triple_string, '-')); diff --git a/src/compiler/target.h b/src/compiler/target.h index b3023919e..088888292 100644 --- a/src/compiler/target.h +++ b/src/compiler/target.h @@ -65,7 +65,9 @@ typedef struct typedef struct { const char *target_triple; - int llvm_opt_level; +#if LLVM_AVAILABLE + int llvm_opt_level; +#endif const char *cpu; const char *features; ArchType arch; diff --git a/src/utils/hostinfo.c b/src/utils/hostinfo.c new file mode 100644 index 000000000..f963096a7 --- /dev/null +++ b/src/utils/hostinfo.c @@ -0,0 +1,121 @@ +#include "../compiler/compiler_internal.h" + +#include "hostinfo.h" +#include + +static int is_le(void) { + unsigned int i = 1; + char *c; + c = (char *) &i; + return (*c == 1); +} + +ArchType hostinfo_arch_type(void) { +#if defined(__x86_64__) || defined(_M_X64) + return ARCH_TYPE_X86_64; +#elif defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86) + return ARCH_TYPE_X86; +#elif (defined(__arm__) && !defined(__thumb__)) || (defined(__TARGET_ARCH_ARM) && !defined(__TARGET_ARCH_THUMB)) || defined(__ARM) || defined(_M_ARM) || defined(_M_ARM_T) || defined(__ARM_ARCH) + return is_le() ? ARCH_TYPE_ARM : ARCH_TYPE_ARMB; +#elif defined(__thumb__) || defined(__TARGET_ARCH_THUMB) || defined(__ARM) || defined(_M_ARM) || defined(_M_ARM_T) || defined(__ARM_ARCH) + return is_le() ? ARCH_TYPE_THUMB : ARCH_TYPE_THUMBEB; +#elif defined(__aarch64__) || defined(_M_ARM64) + return is_le() ? ARCH_TYPE_AARCH64 : ARCH_TYPE_AARCH64_BE; +#elif defined(mips) || defined(__mips__) || defined(__mips) + return ARCH_UNSUPPORTED; +#elif defined(__sh__) + return ARCH_UNSUPPORTED; +#elif defined(__riscv) && defined(__riscv32) + return ARCH_TYPE_RISCV32; +#elif defined(__riscv) && defined(__riscv64) + return ARCH_TYPE_RISCV64; +#elif defined(__PPC64__) || defined(__ppc64__) || defined(_ARCH_PPC64) || defined(__powerpc64__) + return is_le() ? ARCH_TYPE_PPC64LE : ARCH_TYPE_PPC64; +#elif defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) || defined(__ppc__) || defined(__PPC__) || defined(_ARCH_PPC) + return ARCH_TYPE_PPC; +#elif defined(__sparc__) || defined(__sparc) + return ARCH_UNSUPPORTED +#else + return ARCH_UNSUPPORTED +#endif +} + +static const char * llvm_arch_name(ArchType ty) { + switch (ty) { + case ARCH_TYPE_X86_64: return "x86_64"; + case ARCH_TYPE_X86: return "x86"; + case ARCH_TYPE_ARM: return "arm"; + case ARCH_TYPE_ARMB: return "armbe"; + case ARCH_TYPE_AARCH64: return "aarch64"; + case ARCH_TYPE_AARCH64_BE: return "aarch64be"; + case ARCH_TYPE_THUMB: return "thumb"; + case ARCH_TYPE_THUMBEB: return "thumbeb"; + case ARCH_TYPE_WASM64: return "wasm64"; + case ARCH_TYPE_WASM32: return "wasm32"; + case ARCH_TYPE_XTENSA: return "xtensa"; + case ARCH_TYPE_PPC: return "ppc"; + case ARCH_TYPE_PPC64: return "ppc64"; + case ARCH_TYPE_PPC64LE: return "ppc64le"; + case ARCH_TYPE_RISCV32: return "riscv32"; + case ARCH_TYPE_RISCV64: return "riscv64"; + default: + case ARCH_TYPE_UNKNOWN: return "unknown"; + } +} + +void hostinfo_x86_features(X86Features *cpu_features) { +#if defined(__x86_64__) || defined(_M_X64) + // TODO +#endif +} + +EnvironmentType hostinfo_env_type(void) { + return ENV_TYPE_UNKNOWN; +} + +OsType hostinfo_os_type(void) { + if (system("freebsd-version -k") == 0) { + return OS_TYPE_FREE_BSD; + } + + if (system("uname -r") == 0) { + return OS_TYPE_LINUX; + } + + if (system("cd C:/Windows") == 0) { + return OS_TYPE_WIN32; + } + + return OS_TYPE_UNKNOWN; +} + +static const char * llvm_os_name(OsType os) { + switch (os) { + case OS_TYPE_FREE_BSD: return "frebsd"; + case OS_TYPE_LINUX: return "linux"; + case OS_TYPE_WIN32: return "win32"; + default: return "unknown"; + } +} + +VendorType hostinfo_vendor_type(void) { + return VENDOR_UNKNOWN; +} + +static char triple[128]; +static int triple_init = 0; + +const char * hostinfo_default_triple(void) { + if (!triple_init) { + sprintf(triple, "%s-unknown-unknown-%s", + llvm_arch_name(hostinfo_arch_type()), + llvm_os_name(hostinfo_os_type())); + triple_init = 1; + } + + return triple; +} + +const char * hostinfo_x86_cpu_name(void) { + return "x86"; +} diff --git a/src/utils/hostinfo.h b/src/utils/hostinfo.h new file mode 100644 index 000000000..b70ad4c56 --- /dev/null +++ b/src/utils/hostinfo.h @@ -0,0 +1,12 @@ +#if !defined(HOSTINFO_H) && !LLVM_AVAILABLE +#define HOSTINFO_H + +void hostinfo_x86_features(X86Features *cpu_features); +ArchType hostinfo_arch_type(void); +EnvironmentType hostinfo_env_type(void); +OsType hostinfo_os_type(void); +VendorType hostinfo_vendor_type(void); +const char * hostinfo_default_triple(void); +const char * hostinfo_x86_cpu_name(void); // for example: "x86-64", "x86-64-v4" + +#endif