From bd368f99efbc3eee5ab8ad99879f8098848dafc1 Mon Sep 17 00:00:00 2001 From: servostar Date: Thu, 6 Jun 2024 22:47:53 +0200 Subject: [PATCH] added: linker file discovery --- src/cfg/opt.c | 26 -------------- src/llvm/backend.c | 11 +++++- src/llvm/link/lld.c | 84 +++++++++++++++++++++++++++++++++++++++++++++ src/llvm/link/lld.h | 12 +++---- src/llvm/parser.c | 7 ++++ 5 files changed, 106 insertions(+), 34 deletions(-) diff --git a/src/cfg/opt.c b/src/cfg/opt.c index f45613c..2ef1856 100644 --- a/src/cfg/opt.c +++ b/src/cfg/opt.c @@ -107,32 +107,6 @@ TargetConfig* default_target_config() { return config; } -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++) { - const char* link_directory_path = g_array_index(config->link_search_paths, char*, i); - - char* path = g_build_filename(link_directory_path, link_target_name, NULL); - char* cwd = g_get_current_dir(); - char* canonical = g_canonicalize_filename(path, cwd); - - const gboolean exists = g_file_test(canonical, G_FILE_TEST_EXISTS); - const gboolean is_dir = g_file_test(canonical, G_FILE_TEST_IS_DIR); - - g_free(path); - g_free(cwd); - - if (exists && !is_dir) { - return canonical; - } - - g_free(canonical); - } - - // file not found - return NULL; -} - TargetConfig* default_target_config_from_args() { DEBUG("generating default target from command line..."); diff --git a/src/llvm/backend.c b/src/llvm/backend.c index e2b2646..1c536a8 100644 --- a/src/llvm/backend.c +++ b/src/llvm/backend.c @@ -48,12 +48,21 @@ LLVMCodeGenOptLevel llvm_opt_from_int(int level) { PANIC("invalid code generation optimization level: %d", level); } +static char* create_target_output_name(const TargetConfig* config) { + char* prefix = ""; + if (config->mode == Library) { + prefix = "lib"; + } + + return g_strjoin("", prefix, config->name, NULL); +} + Target create_target_from_config(const TargetConfig* config) { DEBUG("Building target from configuration"); Target target = create_native_target(); - target.name.str = config->name; + target.name.str = create_target_output_name(config); target.name.allocation = NONE; // freed later by compiler target.opt = llvm_opt_from_int(config->optimization_level); diff --git a/src/llvm/link/lld.c b/src/llvm/link/lld.c index 5622b22..62b5e65 100644 --- a/src/llvm/link/lld.c +++ b/src/llvm/link/lld.c @@ -3,4 +3,88 @@ // #include +#include +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++) { + const char* link_directory_path = g_array_index(config->link_search_paths, char*, i); + + char* path = g_build_filename(link_directory_path, link_target_name, NULL); + char* cwd = g_get_current_dir(); + char* canonical = g_canonicalize_filename(path, cwd); + + const gboolean exists = g_file_test(canonical, G_FILE_TEST_EXISTS); + const gboolean is_dir = g_file_test(canonical, G_FILE_TEST_IS_DIR); + + g_free(path); + g_free(cwd); + + if (exists && !is_dir) { + return canonical; + } + + g_free(canonical); + } + + // file not found + return NULL; +} + +TargetLinkConfig* lld_create_link_config(const Target* target, const TargetConfig* target_config, const Module* module) { + DEBUG("generating link configuration"); + + TargetLinkConfig* config = malloc(sizeof(TargetLinkConfig)); + + config->object_file_names = g_array_new(FALSE, FALSE, sizeof(char*)); + + // append build object file + const char* target_object = get_absolute_link_path(target_config, (const char*) target->name.str); + if (target_object == NULL) { + ERROR("failed to resolve path to target object: %s", target->name.str); + lld_delete_link_config(config); + return NULL; + } + + g_array_append_val(config->object_file_names, target_object); + INFO("resolved path of target object: %s", target_object); + + // resolve absolute paths to dependent library object files + DEBUG("resolving target dependencies..."); + for (guint i = 0; i < module->imports->len; i++) { + const char* dependency = g_array_index(module->imports, const char*, i); + + const char* dependency_object = get_absolute_link_path(target_config, dependency); + if (dependency_object == NULL) { + ERROR("failed to resolve path to dependency object: %s", dependency); + lld_delete_link_config(config); + return NULL; + } + g_array_append_val(config->object_file_names, dependency_object); + INFO("resolved path of target object: %s", dependency_object); + } + + INFO("resolved %d dependencies", config->object_file_names->len); + + return config; +} + +BackendError lld_link_target(TargetLinkConfig* config) { + BackendError err = SUCCESS; + + char* + + for (guint i = 0; i < config->object_file_names->len; i++) { + const char* path = g_array_index(config->object_file_names, const char*, i); + } + + return err; +} + +void lld_delete_link_config(TargetLinkConfig* config) { + for (guint i = 0; i < config->object_file_names->len; i++) { + free((void*) g_array_index(config->object_file_names, const char*, i)); + } + g_array_free(config->object_file_names, TRUE); + free(config); +} diff --git a/src/llvm/link/lld.h b/src/llvm/link/lld.h index 1916c3b..61d434b 100644 --- a/src/llvm/link/lld.h +++ b/src/llvm/link/lld.h @@ -8,12 +8,10 @@ #include #include -/** - * @brief Link the target by its configuration to the final output. - * @param target - * @param config - * @return - */ -BackendError link_target(const Target* target, const TargetConfig* config); +TargetLinkConfig* lld_create_link_config(const Target * target, const TargetConfig* target_config, const Module* module); + +BackendError lld_link_target(TargetLinkConfig* config); + +void lld_delete_link_config(TargetLinkConfig* config); #endif // LLVM_BACKEND_LLD_H diff --git a/src/llvm/parser.c b/src/llvm/parser.c index 02cd5a8..05181d9 100644 --- a/src/llvm/parser.c +++ b/src/llvm/parser.c @@ -15,6 +15,7 @@ #include #include #include +#include BackendError export_IR(LLVMBackendCompileUnit* unit, const Target* target, const TargetConfig* config) { @@ -242,6 +243,12 @@ BackendError parse_module(const Module* module, const TargetConfig* config) { export_module(unit, &target, config); + TargetLinkConfig* link_config = lld_create_link_config(&target, target, module); + + lld_link_target(link_config); + + lld_delete_link_config(link_config); + delete_target(target); }