diff --git a/CMakeLists.txt b/CMakeLists.txt index 07287a3..e80f362 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,6 +69,11 @@ execute_process( OUTPUT_VARIABLE LLVM_LINK_MODE OUTPUT_STRIP_TRAILING_WHITESPACE) +cmake_print_variables("LLVM libs: ${LLVM_LIBRARIES}") +cmake_print_variables("LLVM libdirs: ${LLVM_LIBDIRS}") +cmake_print_variables("LLVM system libs: ${LLVM_SYSTEM_LIBS}") +cmake_print_variables("LLVM link mode: ${LLVM_LINK_MODE}") + if (${LLVM_LINK_MODE} STREQUAL "shared") # We always ask for the system libs corresponding to static linking, # since on some distros LLD is only available as a static library @@ -79,12 +84,34 @@ if (${LLVM_LINK_MODE} STREQUAL "shared") ERROR_QUIET # Some installations have no static libs, we just ignore the failure OUTPUT_STRIP_TRAILING_WHITESPACE) string(REPLACE " " ";" LLVM_STATIC_SYSTEM_LIBS "${LLVM_STATIC_SYSTEM_LIBS_SPACES}") + 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) set(LLVM_LIBRARIES ${LLVM_LIBRARIES} ${LLVM_SYSTEM_LIBS} ${LLVM_STATIC_SYSTEM_LIBS}) else() + 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) + set(LLVM_LIBRARIES ${LLVM_LIBRARIES} ${LLVM_SYSTEM_LIBS}) endif() +set(lld_libs + ${LLD_COFF} + ${LLD_ELF} + ${LLD_COMMON} + ${LLD_MINGW} + ${LLD_MACHO} + ${LLD_WASM} +) + execute_process( COMMAND ${LLVM_CONFIG_EXE} --includedir OUTPUT_VARIABLE LLVM_INCLUDE_DIRS_SPACES @@ -124,11 +151,13 @@ add_executable("${COMPILER_NAME}" "bootstrap/bloat-buster/main.c" "bootstrap/bloat-buster/pdb_image.c" "bootstrap/bloat-buster/llvm.cpp" + "bootstrap/bloat-buster/lld_driver.c" + "bootstrap/bloat-buster/lld_api.cpp" ) target_compile_definitions(${COMPILER_NAME} PRIVATE ${LLVM_DEFINITIONS}) cmake_print_variables("LLVM definitions: ${LLVM_DEFINITIONS}") target_include_directories(${COMPILER_NAME} PRIVATE ${LLVM_INCLUDE_DIRS}) target_link_directories(${COMPILER_NAME} PRIVATE ${LLVM_LIBRARY_DIRS}) -target_link_libraries(${COMPILER_NAME} PRIVATE ${LIBRARY_NAME} ${LLVM_LIBRARIES}) +target_link_libraries(${COMPILER_NAME} PRIVATE ${LIBRARY_NAME} ${LLVM_LIBRARIES} ${lld_libs}) diff --git a/bootstrap/bloat-buster/lld_api.cpp b/bootstrap/bloat-buster/lld_api.cpp new file mode 100644 index 0000000..964da71 --- /dev/null +++ b/bootstrap/bloat-buster/lld_api.cpp @@ -0,0 +1,55 @@ +#include + +#include +#include +#include +#include + +#define lld_api_function_signature(name) bool name(llvm::ArrayRef args, llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput) + +#define lld_link_decl(link_name) \ +namespace link_name \ +{\ + lld_api_function_signature(link);\ +} + +typedef lld_api_function_signature(LinkerFunction); + +namespace lld +{ + lld_link_decl(coff); + lld_link_decl(elf); + lld_link_decl(mingw); + lld_link_decl(macho); + lld_link_decl(wasm); +} + +fn u8 lld_api_generic(LLDArguments args, LinkerFunction linker_function) +{ + auto arguments = llvm::ArrayRef(args.argument_pointer, args.argument_count); + std::string stdout_string; + llvm::raw_string_ostream stdout_stream(stdout_string); + + std::string stderr_string; + llvm::raw_string_ostream stderr_stream(stderr_string); + u8 result = linker_function(arguments, stdout_stream, stderr_stream, args.exit_early, args.disable_output); + // assert(result == (stdout_string.length() == 0)); + // assert(result == (stderr_string.length() == 0)); + + print_string(String{(u8*)stdout_string.data(), stdout_string.length()}); + print_string(String{(u8*)stderr_string.data(), stderr_string.length()}); + + return result; +} + +#define lld_api_function_impl(link_name) \ +lld_api_function_decl(link_name)\ +{\ + return lld_api_generic(args, lld::link_name::link);\ +} + +lld_api_function_impl(coff) +lld_api_function_impl(elf) +lld_api_function_impl(mingw) +lld_api_function_impl(macho) +lld_api_function_impl(wasm) diff --git a/bootstrap/bloat-buster/lld_driver.c b/bootstrap/bloat-buster/lld_driver.c new file mode 100644 index 0000000..27bc916 --- /dev/null +++ b/bootstrap/bloat-buster/lld_driver.c @@ -0,0 +1,239 @@ +#include +#include +#include + +fn String linux_crt_find_path() +{ + auto flags = (OSFileOpenFlags) { + .read = 1, + }; + auto permissions = (OSFilePermissions) { + .readable = 1, + .writable = 1, + }; + if (os_file_descriptor_is_valid(os_file_open(strlit("/usr/lib/crti.o"), flags, permissions))) + { + return strlit("/usr/lib"); + } + + if (os_file_descriptor_is_valid(os_file_open(strlit("/usr/lib/x86_64-linux-gnu/crti.o"), flags, permissions))) + { + return strlit("/usr/lib/x86_64-linux-gnu"); + } + + todo(); +} + +fn String windows_msvc_find_path() +{ + auto flags = (OSFileOpenFlags) { + .read = 1, + .directory = 1, + }; + auto permissions = (OSFilePermissions) { + .readable = 1, + }; + String possibilities[] = { + strlit("C:/Program Files/Microsoft Visual Studio/2022/Enterprise"), + strlit("C:/Program Files/Microsoft Visual Studio/2022/Community"), + }; + for (u64 i = 0; i < array_length(possibilities); i += 1) + { + auto possibility = possibilities[i]; + auto fd = os_file_open(possibility, flags, permissions); + + if (os_file_descriptor_is_valid(fd)) + { + return possibility; + } + } + + failed_execution(); +} + +fn void linux_add_crt_item(Arena* arena, VirtualBufferP(char)* args, String crt_path, String item) +{ + String parts[] = { + crt_path, + strlit("/"), + item, + }; + *vb_add(args, 1) = string_to_c(arena_join_string(arena, (Slice(String))array_to_slice(parts))); +} + +SliceP(char) lld_driver(Arena* arena, LinkerArguments arguments) +{ + VirtualBufferP(char) args = {}; + + char* driver; + switch (arguments.target.os) + { + case OPERATING_SYSTEM_LINUX: + driver = "ld.lld"; + break; + case OPERATING_SYSTEM_MAC: + driver = "ld64.lld"; + break; + case OPERATING_SYSTEM_WINDOWS: + driver = "lld-link"; + break; + } + *vb_add(&args, 1) = driver; + + if (arguments.target.os != OPERATING_SYSTEM_WINDOWS) + { + *vb_add(&args, 1) = "--error-limit=0"; + } + + switch (arguments.target.os) + { + case OPERATING_SYSTEM_WINDOWS: + { + String parts[] = { + strlit("-out:"), + arguments.out_path, + }; + auto arg = arena_join_string(arena, (Slice(String))array_to_slice(parts)); + *vb_add(&args, 1) = string_to_c(arg); + } break; + default: + { + *vb_add(&args, 1) = "-o"; + *vb_add(&args, 1) = string_to_c(arguments.out_path); + } break; + } + + if (arguments.target.os != OPERATING_SYSTEM_WINDOWS) + { + for (u64 i = 0; i < arguments.objects.length; i += 1) + { + *vb_add(&args, 1) = string_to_c(arguments.objects.pointer[i]); + } + } + + switch (arguments.target.os) + { + case OPERATING_SYSTEM_LINUX: + { + if (arguments.link_libcpp && !arguments.link_libc) + { + failed_execution(); + } + + if (arguments.link_libc) + { + auto crt_path = linux_crt_find_path(); + + *vb_add(&args, 1) = "-dynamic-linker"; + + String dynamic_linker_filename; + switch (arguments.target.cpu) + { + case CPU_ARCH_X86_64: + dynamic_linker_filename = strlit("ld-linux-x86-64.so.2"); + break; + case CPU_ARCH_AARCH64: + dynamic_linker_filename = strlit("ld-linux-aarch64.so.1"); + break; + } + + linux_add_crt_item(arena, &args, crt_path, dynamic_linker_filename); + linux_add_crt_item(arena, &args, crt_path, strlit("crt1.o")); + + *vb_add(&args, 1) = "-L"; + *vb_add(&args, 1) = string_to_c(crt_path); + + + *vb_add(&args, 1) = "--as-needed"; + *vb_add(&args, 1) = "-lm"; + *vb_add(&args, 1) = "-lpthread"; + *vb_add(&args, 1) = "-lc"; + *vb_add(&args, 1) = "-ldl"; + *vb_add(&args, 1) = "-lrt"; + *vb_add(&args, 1) = "-lutil"; + + linux_add_crt_item(arena, &args, crt_path, strlit("crtn.o")); + + if (arguments.link_libcpp) + { + // TODO: implement better path finding + linux_add_crt_item(arena, &args, crt_path, strlit("libstdc++.so.6")); + } + } + + for (u64 i = 0; i < arguments.libraries.length; i += 1) + { + auto library = arguments.libraries.pointer[i]; + String library_pieces[] = { + strlit("-l"), + library, + }; + auto library_argument = arena_join_string(arena, (Slice(String))array_to_slice(library_pieces)); + *vb_add(&args, 1) = string_to_c(library_argument); + } + } break; + case OPERATING_SYSTEM_MAC: + { + *vb_add(&args, 1) = "-dynamic"; + *vb_add(&args, 1) = "-platform_version"; + *vb_add(&args, 1) = "macos"; + *vb_add(&args, 1) = "15.0.0"; + *vb_add(&args, 1) = "15.0.0"; + *vb_add(&args, 1) = "-arch"; + *vb_add(&args, 1) = "arm64"; + *vb_add(&args, 1) = "-syslibroot"; + *vb_add(&args, 1) = "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk"; + + if (string_ends_with(arguments.out_path, strlit(".dylib"))) + { + *vb_add(&args, 1) = "-e"; + *vb_add(&args, 1) = "_main"; + } + + *vb_add(&args, 1) = "-lSystem"; + + if (arguments.link_libcpp) + { + *vb_add(&args, 1) = "-lc++"; + } + } break; + case OPERATING_SYSTEM_WINDOWS: + { + if (arguments.link_libcpp && !arguments.link_libc) + { + failed_execution(); + } + + auto msvc_path = windows_msvc_find_path(); + + if (arguments.link_libc) + { + *vb_add(&args, 1) = "-defaultlib:libcmt"; + + { + // String parts[] = { + // strlit("-libpath:"), + // msvc_path, + // strlit("/"), + // strlit("VC/Tools/MSVC/14.41.34120/lib/x64"), + // }; + // auto arg = arena_join_string(arena, (Slice(String)) array_to_slice(parts)); + } + + if (arguments.link_libcpp) + { + todo(); + } + + for (u64 i = 0; i < arguments.objects.length; i += 1) + { + *vb_add(&args, 1) = string_to_c(arguments.objects.pointer[i]); + } + } + // clang -v main.c + // "C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.41.34120\\bin\\Hostx64\\x64\\link.exe" -out:a.exe -defaultlib:libcmt -defaultlib:oldnames "-libpath:C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.41.34120\\lib\\x64" "-libpath:C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.41.34120\\atlmfc\\lib\\x64" "-libpath:C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.22621.0\\ucrt\\x64" "-libpath:C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.22621.0\\um\\x64" "-libpath:C:\\Users\\David\\scoop\\apps\\llvm\\19.1.3\\lib\\clang\\19\\lib\\windows" -nologo "C:\\Users\\David\\AppData\\Local\\Temp\\main-706820.o" + } break; + } + + return (SliceP(char)){ .pointer = args.pointer, .length = args.length }; +} diff --git a/bootstrap/bloat-buster/llvm.cpp b/bootstrap/bloat-buster/llvm.cpp index 01162d7..82c1313 100644 --- a/bootstrap/bloat-buster/llvm.cpp +++ b/bootstrap/bloat-buster/llvm.cpp @@ -100,7 +100,7 @@ namespace llvm target_triple = string_ref("aarch64-apple-macosx-none"); break; case OPERATING_SYSTEM_WINDOWS: - target_triple = string_ref("x86_64-windows-gnu"); + target_triple = string_ref("x86_64-pc-windows-msvc"); break; } diff --git a/bootstrap/bloat-buster/main.c b/bootstrap/bloat-buster/main.c index aa9e5b8..e9b5f1a 100644 --- a/bootstrap/bloat-buster/main.c +++ b/bootstrap/bloat-buster/main.c @@ -8,6 +8,8 @@ #include #include #include +#include +#include #ifdef __APPLE__ #define clang_path "/opt/homebrew/opt/llvm/bin/clang" @@ -38,17 +40,6 @@ STRUCT(GetOrPut(T)) \ auto compiler_name = strlit("bb"); -fn void print_string(String message) -{ -#ifndef SILENT - // TODO: check writes - os_file_write(os_stdout_get(), message); - // assert(result >= 0); - // assert((u64)result == message.length); -#else - unused(message); -#endif -} STRUCT(ElfRelocation) { @@ -20821,21 +20812,21 @@ may_be_unused fn String write_pe(Thread* thread, ObjectOptions options) auto pdb = pdb_build(thread); // TODO: -#if _WIN32 - auto pdb_path = arena_join_string(thread->arena, (Slice(String))array_to_slice(to_join)); - auto fd = os_file_open(strlit("mydbg.pdb"), (OSFileOpenFlags) { - .write = 1, - .truncate = 1, - .create = 1, - }, (OSFilePermissions) { - .readable = 1, - .writable = 1, - }); - - os_file_write(fd, pdb); - - os_file_close(fd); -#endif +// #if _WIN32 +// auto pdb_path = arena_join_string(thread->arena, (Slice(String))array_to_slice(to_join)); +// auto fd = os_file_open(strlit("mydbg.pdb"), (OSFileOpenFlags) { +// .write = 1, +// .truncate = 1, +// .create = 1, +// }, (OSFilePermissions) { +// .readable = 1, +// .writable = 1, +// }); +// +// os_file_write(fd, pdb); +// +// os_file_close(fd); +// #endif // Check if file matches #define CHECK_PE_MATCH 0 @@ -24328,6 +24319,39 @@ fn void code_generation(Thread* restrict thread, CodegenOptions options) { // TODO: delete, this is testing llvm_codegen(options, object_path); + + auto lld_args = lld_driver(thread->arena, (LinkerArguments) { + .target = options.target, + .out_path = exe_path, + .objects = (Slice(String)) { .pointer = &object_path, .length = 1 }, + .link_libc = 1, + }); + + LLDArguments arguments = { + .disable_output = 0, + .exit_early = 1, + .argument_pointer = (const char**)lld_args.pointer, + .argument_count = lld_args.length, + }; + + u8 result; + switch (options.target.os) + { + case OPERATING_SYSTEM_LINUX: + result = lld_elf_link(arguments); + break; + case OPERATING_SYSTEM_MAC: + result = lld_macho_link(arguments); + break; + case OPERATING_SYSTEM_WINDOWS: + result = lld_coff_link(arguments); + break; + } + + if (!result) + { + failed_execution(); + } } break; case COMPILER_BACKEND_BB: { diff --git a/bootstrap/include/bloat-buster/base.h b/bootstrap/include/bloat-buster/base.h index 813c0fb..33b4f99 100644 --- a/bootstrap/include/bloat-buster/base.h +++ b/bootstrap/include/bloat-buster/base.h @@ -202,3 +202,13 @@ fn Target native_target_get() return target; } + +STRUCT(LinkerArguments) +{ + Target target; + String out_path; + Slice(String) objects; + Slice(String) libraries; + u8 link_libc:1; + u8 link_libcpp:1; +}; diff --git a/bootstrap/include/bloat-buster/lld_api.h b/bootstrap/include/bloat-buster/lld_api.h new file mode 100644 index 0000000..b27f791 --- /dev/null +++ b/bootstrap/include/bloat-buster/lld_api.h @@ -0,0 +1,17 @@ +#include + +STRUCT(LLDArguments) +{ + const char** argument_pointer; + u32 argument_count; + u8 exit_early; + u8 disable_output; +}; + +#define lld_api_function_decl(link_name) u8 lld_ ## link_name ## _link(LLDArguments args) + +EXPORT lld_api_function_decl(coff); +EXPORT lld_api_function_decl(elf); +EXPORT lld_api_function_decl(mingw); +EXPORT lld_api_function_decl(macho); +EXPORT lld_api_function_decl(coff); diff --git a/bootstrap/include/bloat-buster/lld_driver.h b/bootstrap/include/bloat-buster/lld_driver.h new file mode 100644 index 0000000..f23c7ec --- /dev/null +++ b/bootstrap/include/bloat-buster/lld_driver.h @@ -0,0 +1,4 @@ +#include +#include + +EXPORT SliceP(char) lld_driver(Arena* arena, LinkerArguments arguments); diff --git a/bootstrap/include/std/os.h b/bootstrap/include/std/os.h index 3189a07..dfab787 100644 --- a/bootstrap/include/std/os.h +++ b/bootstrap/include/std/os.h @@ -9,6 +9,7 @@ STRUCT(OSFileOpenFlags) u32 write:1; u32 read:1; u32 create:1; + u32 directory:1; }; STRUCT(OSFilePermissions) @@ -91,3 +92,5 @@ EXPORT FileDescriptor os_stdout_get(); EXPORT void os_directory_make(String path); EXPORT void calibrate_cpu_timer(); + +EXPORT void print_string(String string); diff --git a/bootstrap/include/std/string.h b/bootstrap/include/std/string.h index aac6ec5..95b54f5 100644 --- a/bootstrap/include/std/string.h +++ b/bootstrap/include/std/string.h @@ -1,5 +1,6 @@ #include -s32 string_first_ch(String string, u8 ch); -s64 string_last_ch(String string, u8 ch); -u8 string_starts_with(String string, String start); +EXPORT s32 string_first_ch(String string, u8 ch); +EXPORT s64 string_last_ch(String string, u8 ch); +EXPORT u8 string_starts_with(String string, String start); +EXPORT u8 string_ends_with(String string, String end); diff --git a/bootstrap/include/std/virtual_buffer.h b/bootstrap/include/std/virtual_buffer.h index 07e5da9..d39993c 100644 --- a/bootstrap/include/std/virtual_buffer.h +++ b/bootstrap/include/std/virtual_buffer.h @@ -26,6 +26,7 @@ decl_vbp(s32); decl_vb(s64); decl_vbp(s64); decl_vb(String); +decl_vbp(char); #define vb_size_of_element(vb) sizeof(*((vb)->pointer)) #define vb_add(vb, count) (typeof((vb)->pointer)) vb_generic_add((VirtualBuffer(u8)*)(vb), (vb_size_of_element(vb)), (count)) diff --git a/bootstrap/runner/runner.c b/bootstrap/runner/runner.c index d77d750..7b92c40 100644 --- a/bootstrap/runner/runner.c +++ b/bootstrap/runner/runner.c @@ -83,10 +83,6 @@ STRUCT(TestOptions) fn void run_tests(Arena* arena, String compiler_path, TestOptions const * const test_options, char** envp) { - print("\n===========================\n"); - print("COMPILER BUILD [OK]\n"); - print("===========================\n\n"); - Target target = native_target_get(); for (u32 test_i = 0; test_i < test_options->test_paths.length; test_i += 1) diff --git a/bootstrap/std/os.c b/bootstrap/std/os.c index e8a7dd8..4a65aea 100644 --- a/bootstrap/std/os.c +++ b/bootstrap/std/os.c @@ -849,11 +849,10 @@ FileDescriptor os_file_open(String path, OSFileOpenFlags flags, OSFilePermission { assert(path.pointer[path.length] == 0); #if _WIN32 - DWORD dwDesiredAccess = 0; - dwDesiredAccess |= permissions.readable * GENERIC_READ; - dwDesiredAccess |= permissions.writable * GENERIC_WRITE; - dwDesiredAccess |= permissions.executable * GENERIC_EXECUTE; + dwDesiredAccess |= flags.read * GENERIC_READ; + dwDesiredAccess |= flags.write * GENERIC_WRITE; + dwDesiredAccess |= flags.executable * GENERIC_EXECUTE; DWORD dwShareMode = 0; LPSECURITY_ATTRIBUTES lpSecurityAttributes = 0; DWORD dwCreationDisposition = 0; @@ -861,8 +860,10 @@ FileDescriptor os_file_open(String path, OSFileOpenFlags flags, OSFilePermission dwCreationDisposition |= flags.create * CREATE_ALWAYS; DWORD dwFlagsAndAttributes = 0; dwFlagsAndAttributes |= FILE_ATTRIBUTE_NORMAL; + dwFlagsAndAttributes |= flags.directory * FILE_FLAG_BACKUP_SEMANTICS; HANDLE hTemplateFile = 0; - auto handle = CreateFileA((char*)path.pointer, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); + + auto handle = CreateFileA(string_to_c(path), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); return handle; #else int posix_flags = 0; @@ -1431,7 +1432,7 @@ void run_command(Arena* arena, CStringSlice arguments, char* envp[]) DWORD exit_code; if (GetExitCodeProcess(process_information.hProcess, &exit_code)) { - print("Process ran with exit code: {u32:x}\n", exit_code); + print("Process ran with exit code: 0x{u32:x}\n", exit_code); if (exit_code != 0) { failed_execution(); @@ -1543,3 +1544,15 @@ void run_command(Arena* arena, CStringSlice arguments, char* envp[]) } #endif } + +void print_string(String message) +{ +#ifndef SILENT + // TODO: check writes + os_file_write(os_stdout_get(), message); + // assert(result >= 0); + // assert((u64)result == message.length); +#else + unused(message); +#endif +} diff --git a/bootstrap/std/string.c b/bootstrap/std/string.c index f9e37de..a182554 100644 --- a/bootstrap/std/string.c +++ b/bootstrap/std/string.c @@ -61,3 +61,27 @@ u8 string_starts_with(String string, String start) return result; } + +u8 string_ends_with(String string, String end) +{ + u8 result = 0; + + if (likely(end.length <= string.length)) + { + u64 i; + u64 offset = string.length - end.length; + for (i = 0; i < end.length; i += 1) + { + auto start_ch = end.pointer[i]; + auto string_ch = string.pointer[i + offset]; + if (unlikely(string_ch != start_ch)) + { + break; + } + } + + result = i == end.length; + } + + return result; +} diff --git a/project.sh b/project.sh index fbb1fd9..b4c5c0f 100755 --- a/project.sh +++ b/project.sh @@ -6,6 +6,7 @@ C_COMPILER_PATH=clang CXX_COMPILER_PATH=clang++ ASM_COMPILER_PATH=clang + if [[ -z "${BIRTH_OS-}" ]]; then case "$OSTYPE" in msys*) @@ -23,6 +24,16 @@ if [[ -z "${BIRTH_OS-}" ]]; then esac fi +case "$BIRTH_OS" in + linux) + ls -las / + ls -las /usr + ls -las /usr/lib + ;; + *) + ;; +esac + if [[ -z "${BIRTH_ARCH-}" ]]; then case "$(uname -m)" in x86_64) @@ -42,7 +53,7 @@ if [[ -z "${CMAKE_BUILD_TYPE-}" ]]; then fi if [[ -z "${CMAKE_PREFIX_PATH-}" ]]; then - CMAKE_PREFIX_PATH="" + CMAKE_PREFIX_PATH="$HOME/Downloads/llvm-$BIRTH_ARCH-$BIRTH_OS-$CMAKE_BUILD_TYPE" fi @@ -59,6 +70,14 @@ case $BIRTH_OS in ASM_COMPILER_OPT_ARG="" ;; esac +case $BIRTH_OS in + linux) + USE_MOLD_OPT_ARG=-DCMAKE_EXE_LINKER_FLAGS="-fuse-ld=mold" + ;; + *) + USE_MOLD_OPT_ARG="" + ;; +esac mkdir -p $build_dir cmake . \ @@ -69,9 +88,11 @@ cmake . \ -DCMAKE_C_COMPILER=$C_COMPILER_PATH \ -DCMAKE_CXX_COMPILER=$CXX_COMPILER_PATH \ -DCMAKE_ASM_COMPILER=$ASM_COMPILER_PATH \ + $USE_MOLD_OPT_ARG \ $C_COMPILER_OPT_ARG \ $CXX_COMPILER_OPT_ARG \ $ASM_COMPILER_OPT_ARG + cd $build_dir ninja -v cd $original_dir