From f028bc274fb3926b0fc13bba57059bf32581ac1b Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Wed, 14 Apr 2021 13:53:34 +0200 Subject: [PATCH] Use the platform linker by default, which will just be a call to "cc" (the Win solution will be done later) --- src/build/build_options.h | 2 +- src/build/project_creation.h | 2 +- src/compiler/compiler.c | 15 ++++++- src/compiler/compiler_internal.h | 18 ++++---- src/compiler/linker.c | 70 ++++++++++++++++++++++++-------- src/compiler/llvm_codegen.c | 13 +++--- src/compiler/target.h | 2 +- src/compiler_tests/benchmark.c | 4 +- src/compiler_tests/benchmark.h | 2 +- src/compiler_tests/tests.h | 2 +- src/main.c | 2 +- src/utils/common.h | 2 +- src/utils/whereami.h | 2 +- 13 files changed, 92 insertions(+), 44 deletions(-) diff --git a/src/build/build_options.h b/src/build/build_options.h index 30d7fd5a5..ce44d99af 100644 --- a/src/build/build_options.h +++ b/src/build/build_options.h @@ -230,4 +230,4 @@ typedef struct BuildOptions parse_arguments(int argc, const char *argv[]); -ArchOsTarget arch_os_target_from_string(const char *target); \ No newline at end of file +ArchOsTarget arch_os_target_from_string(const char *target); diff --git a/src/build/project_creation.h b/src/build/project_creation.h index 0854a319f..f25f0029a 100644 --- a/src/build/project_creation.h +++ b/src/build/project_creation.h @@ -5,4 +5,4 @@ // a copy of which can be found in the LICENSE file. struct BuildOptions_; -void create_project(struct BuildOptions_ *build_options); \ No newline at end of file +void create_project(struct BuildOptions_ *build_options); diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index e436457dc..423ac5a60 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -182,9 +182,20 @@ void compiler_compile(BuildTarget *target) vec_add(obj_files, file_name); } - if (create_exe && obj_format_linking_supported(platform_target.object_format)) + if (create_exe) { - linker(target->name, obj_files, source_count); + if (target->arch_os_target == ARCH_OS_TARGET_DEFAULT) + { + platform_linker(target->name, obj_files, source_count); + } + else + { + if (!obj_format_linking_supported(platform_target.object_format) || !linker(target->name, obj_files, source_count)) + { + printf("No linking is performed due to missing linker support."); + target->run_after_compile = false; + } + } if (target->run_after_compile) { system(strformat("./%s", target->name)); diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 278cba00d..12bfe467d 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -1412,13 +1412,13 @@ extern const char *kw___trunc; #define AST_NEW_TOKEN(_kind, _token) new_ast(_kind, source_span_from_token_id(_token.id)) #define AST_NEW(_kind, _loc) new_ast(_kind, _loc) -ARENA_DEF(ast, Ast); -ARENA_DEF(expr, Expr); -ARENA_DEF(sourceloc, SourceLocation); -ARENA_DEF(toktype, char); -ARENA_DEF(tokdata, TokenData); -ARENA_DEF(decl, Decl); -ARENA_DEF(type_info, TypeInfo); +ARENA_DEF(ast, Ast) +ARENA_DEF(expr, Expr) +ARENA_DEF(sourceloc, SourceLocation) +ARENA_DEF(toktype, char) +ARENA_DEF(tokdata, TokenData) +ARENA_DEF(decl, Decl) +ARENA_DEF(type_info, TypeInfo) static inline bool ast_ok(Ast *ast) { return ast == NULL || ast->ast_kind != AST_POISONED; } static inline bool ast_poison(Ast *ast) { ast->ast_kind = AST_POISONED; return false; } @@ -1998,8 +1998,8 @@ static inline size_t type_min_alignment(size_t a, size_t b) } bool obj_format_linking_supported(ObjectFormatType format_type); -void linker(const char *output_file, const char **files, unsigned file_count); - +bool linker(const char *output_file, const char **files, unsigned file_count); +void platform_linker(const char *output_file, const char **files, unsigned file_count); #define TRY_AST_OR(_ast_stmt, _res) ({ Ast* _ast = (_ast_stmt); if (!ast_ok(_ast)) return _res; _ast; }) #define TRY_EXPR_OR(_expr_stmt, _res) ({ Expr* _expr = (_expr_stmt); if (!expr_ok(_expr)) return _res; _expr; }) diff --git a/src/compiler/linker.c b/src/compiler/linker.c index 304c2c0a4..2d30999a2 100644 --- a/src/compiler/linker.c +++ b/src/compiler/linker.c @@ -14,7 +14,7 @@ static void add_files(const char ***args, const char **files_to_link, unsigned f } } -static void link_exe(const char *output_file, const char **files_to_link, unsigned file_count) +static bool link_exe(const char *output_file, const char **files_to_link, unsigned file_count) { const char **args = NULL; vec_add(args, "-o"); @@ -24,7 +24,7 @@ static void link_exe(const char *output_file, const char **files_to_link, unsign switch (platform_target.os) { case OS_TYPE_WIN32: - break; + return false; case OS_TYPE_MACOSX: add_files(&args, files_to_link, file_count); vec_add(args, "-lSystem"); @@ -44,14 +44,13 @@ static void link_exe(const char *output_file, const char **files_to_link, unsign break; case OS_TYPE_WATCHOS: case OS_TYPE_IOS: - TODO + return false; case OS_TYPE_WASI: - break; + return false; case OS_TYPE_OPENBSD: case OS_TYPE_NETBSD: case OS_TYPE_FREE_BSD: - TODO - break; + return false; case OS_TYPE_LINUX: vec_add(args, "-m"); switch (platform_target.arch) @@ -84,21 +83,17 @@ static void link_exe(const char *output_file, const char **files_to_link, unsign vec_add(args, "--dynamic-linker=/lib64/ld-linux-x86-64.so.2"); break; case ARCH_TYPE_X86: - TODO - vec_add(args, "elf_i386"); - break; +// vec_add(args, "elf_i386"); + return false; case ARCH_TYPE_AARCH64: - TODO vec_add(args, "aarch64elf"); - break; + return false; case ARCH_TYPE_RISCV32: - TODO vec_add(args, "elf32lriscv"); - break; + return false; case ARCH_TYPE_RISCV64: vec_add(args, "elf64lriscv"); - TODO - break; + return false; default: UNREACHABLE } @@ -108,7 +103,7 @@ static void link_exe(const char *output_file, const char **files_to_link, unsign default: add_files(&args, files_to_link, file_count); vec_add(args, platform_target.pie ? "-pie" : "-no_pie"); - break; + return false; } bool success; @@ -133,6 +128,7 @@ static void link_exe(const char *output_file, const char **files_to_link, unsign { error_exit("Failed to create an executable: %s", error); } + return true; } bool obj_format_linking_supported(ObjectFormatType format_type) @@ -153,9 +149,47 @@ bool obj_format_linking_supported(ObjectFormatType format_type) UNREACHABLE } -void linker(const char *output_file, const char **files, unsigned file_count) + +const char *concat_string_parts(const char **args) { - link_exe(output_file, files, file_count); + unsigned size_needed = 0; + VECEACH(args, i) + { + size_needed += strlen(args[i]) + 1; + } + char *output = malloc_arena(size_needed); + char *ptr = output; + VECEACH(args, i) + { + unsigned len = strlen(args[i]); + memcpy(ptr, args[i], len); + ptr += len; + *(ptr++) = ' '; + } + ptr[-1] = '\0'; + return output; +} + +void platform_linker(const char *output_file, const char **files, unsigned file_count) +{ + const char **parts = NULL; + vec_add(parts, "cc"); + vec_add(parts, "-o"); + vec_add(parts, output_file); + for (unsigned i = 0; i < file_count; i++) + { + vec_add(parts, files[i]); + } + const char *output = concat_string_parts(parts); + if (system(output) != 0) + { + error_exit("Failed to link executable '%s' using command '%s'.\n", output_file, output); + } + printf("Program linked to executable '%s'.\n", output_file); +} +bool linker(const char *output_file, const char **files, unsigned file_count) +{ + return link_exe(output_file, files, file_count); } /** diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 89b702b9e..448f422ad 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -10,22 +10,25 @@ static void diagnostics_handler(LLVMDiagnosticInfoRef ref, void *context) { char *message = LLVMGetDiagInfoDescription(ref); LLVMDiagnosticSeverity severity = LLVMGetDiagInfoSeverity(ref); - const char *severerity_name = "unknown"; + const char *severity_name; switch (severity) { case LLVMDSError: error_exit("LLVM error generating code for %s: %s", ((GenContext *)context)->ast_context->module->name, message); case LLVMDSWarning: - severerity_name = "warning"; + severity_name = "warning"; break; case LLVMDSRemark: - severerity_name = "remark"; + severity_name = "remark"; break; case LLVMDSNote: - severerity_name = "note"; + severity_name = "note"; + break; + default: + severity_name = "message"; break; } - DEBUG_LOG("LLVM message [%s]: %s ", severerity_name, message); + DEBUG_LOG("LLVM %s: %s ", severity_name, message); LLVMDisposeMessage(message); } diff --git a/src/compiler/target.h b/src/compiler/target.h index d0a18b46b..28d2baf51 100644 --- a/src/compiler/target.h +++ b/src/compiler/target.h @@ -367,4 +367,4 @@ typedef struct } PlatformTarget; -extern PlatformTarget platform_target; \ No newline at end of file +extern PlatformTarget platform_target; diff --git a/src/compiler_tests/benchmark.c b/src/compiler_tests/benchmark.c index 83bace250..1d3a90643 100644 --- a/src/compiler_tests/benchmark.c +++ b/src/compiler_tests/benchmark.c @@ -9,9 +9,9 @@ static int begin = 0; void bench_begin(void) { - begin = clock(); + begin = (int)clock(); } double bench_mark(void) { return (double)(clock() - begin) / (double)CLOCKS_PER_SEC; -} \ No newline at end of file +} diff --git a/src/compiler_tests/benchmark.h b/src/compiler_tests/benchmark.h index 0ea570b00..1c7e9a9ae 100644 --- a/src/compiler_tests/benchmark.h +++ b/src/compiler_tests/benchmark.h @@ -6,4 +6,4 @@ void bench_begin(void); -double bench_mark(void); \ No newline at end of file +double bench_mark(void); diff --git a/src/compiler_tests/tests.h b/src/compiler_tests/tests.h index 499cd948d..c87c21e5b 100644 --- a/src/compiler_tests/tests.h +++ b/src/compiler_tests/tests.h @@ -5,4 +5,4 @@ // a copy of which can be found in the LICENSE file. -void compiler_tests(void); \ No newline at end of file +void compiler_tests(void); diff --git a/src/main.c b/src/main.c index ac9f5aade..57565f20d 100644 --- a/src/main.c +++ b/src/main.c @@ -21,7 +21,7 @@ int main(int argc, const char *argv[]) // Parse arguments. BuildOptions build_options = parse_arguments(argc, argv); - BuildTarget build_target = {}; + BuildTarget build_target = { .name = NULL }; switch (build_options.command) { diff --git a/src/utils/common.h b/src/utils/common.h index 7dd93912c..458af34b2 100644 --- a/src/utils/common.h +++ b/src/utils/common.h @@ -26,4 +26,4 @@ #else #define PLATFORM_WINDOWS 0 #define PLATFORM_POSIX 1 -#endif \ No newline at end of file +#endif diff --git a/src/utils/whereami.h b/src/utils/whereami.h index 1e56038e6..a2d9042af 100644 --- a/src/utils/whereami.h +++ b/src/utils/whereami.h @@ -4,4 +4,4 @@ // Use of this source code is governed by a LGPLv3.0 // a copy of which can be found in the LICENSE file. -const char *find_executable_path(void); \ No newline at end of file +const char *find_executable_path(void);