gemstone/src/llvm/link/lld.c

117 lines
4.1 KiB
C

//
// Created by servostar on 6/4/24.
//
#include <llvm/link/lld.h>
#include <sys/log.h>
#include <mem/cache.h>
#include <sys/col.h>
#include <link/lib.h>
const char* get_absolute_link_path(const TargetConfig* config, const char* link_target_name) {
INFO("resolving absolute path for link target: %s", 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);
INFO("searching at: %s", link_directory_path);
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);
char* cached_canonical = mem_strdup(MemoryNamespaceLld, canonical);
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);
g_free(canonical);
if (exists && !is_dir) {
INFO("link target found at: %s", cached_canonical);
return cached_canonical;
}
}
// file not found
return NULL;
}
TargetLinkConfig* lld_create_link_config(__attribute__((unused)) const Target* target, const TargetConfig* target_config, const Module* module) {
DEBUG("generating link configuration");
TargetLinkConfig* config = mem_alloc(MemoryNamespaceLld, sizeof(TargetLinkConfig));
config->fatal_warnings = target_config->lld_fatal_warnings;
config->object_file_names = mem_new_g_array(MemoryNamespaceLld, sizeof(char*));
config->colorize = stdout_supports_ansi_esc();
config->driver = target_config->driver;
// append build object file
char* basename = g_strjoin(".", target_config->name, "o", NULL);
char* filename = g_build_filename(target_config->archive_directory, basename, NULL);
g_free(basename);
const char* target_object = get_absolute_link_path(target_config, (const char*) filename);
if (target_object == NULL) {
ERROR("failed to resolve path to target object: %s", filename);
g_free(filename);
lld_delete_link_config(config);
g_free(filename);
return NULL;
}
g_free(filename);
{
// output file after linking
basename = g_strjoin(".", target_config->name, "out", NULL);
filename = g_build_filename(target_config->output_directory, basename, NULL);
config->output_file = mem_strdup(MemoryNamespaceLld, filename);
g_free(basename);
g_free(filename);
}
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* library = g_strjoin("", "libgsc", dependency, ".a", NULL);
const char* dependency_object = get_absolute_link_path(target_config, library);
if (dependency_object == NULL) {
ERROR("failed to resolve path to dependency object: %s", library);
print_message(Warning, "failed to resolve path to dependency object: %s", dependency); lld_delete_link_config(config);
lld_delete_link_config(config);
g_free((void*) library);
return NULL;
}
g_free((void*) library);
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) {
if (link_run(config)) {
return SUCCESS;
}
return new_backend_impl_error(Implementation, NULL, "linking failed");
}
void lld_delete_link_config(TargetLinkConfig* config) {
mem_free(config->object_file_names);
mem_free(config);
}