diff --git a/src/cfg/opt.c b/src/cfg/opt.c index 05551ba..9da7374 100644 --- a/src/cfg/opt.c +++ b/src/cfg/opt.c @@ -104,6 +104,8 @@ TargetConfig* default_target_config() { config->optimization_level = 1; config->root_module = NULL; config->link_search_paths = g_array_new(FALSE, FALSE, sizeof(char*)); + config->lld_fatal_warnings = FALSE; + config->gsc_fatal_warnings = FALSE; return config; } @@ -113,6 +115,16 @@ TargetConfig* default_target_config_from_args() { TargetConfig* config = default_target_config(); + gboolean fatal_warnings = is_option_set("all-fatal-warnings"); + + if (fatal_warnings || is_option_set("lld-fatal-warnings")) { + config->lld_fatal_warnings = true; + } + + if (fatal_warnings || is_option_set("gsc-fatal-warnings")) { + config->gsc_fatal_warnings = true; + } + if (is_option_set("print-ast")) { config->print_ast = true; } @@ -210,6 +222,9 @@ void print_help(void) { " --mode=[app|lib] set the compilation mode to either application or library", " --output=name name of output files without extension", " --link-paths=[paths,] set a list of directories to for libraries in", + " --all-fatal-warnings treat all warnings as errors", + " --lld-fatal-warnings treat linker warnings as errors", + " --gsc-fatal-warnings treat parser warnings as errors", "Options:", " --verbose print logs with level information or higher", " --debug print debug logs (if not disabled at compile time)", @@ -324,6 +339,8 @@ static int parse_target(const ProjectConfig *config, const toml_table_t *target_ get_str(&target_config->root_module, target_table, "root"); get_str(&target_config->output_directory, target_table, "output"); get_str(&target_config->archive_directory, target_table, "archive"); + get_bool(&target_config->lld_fatal_warnings, target_table, "lld_fatal_warnings"); + get_bool(&target_config->gsc_fatal_warnings, target_table, "gsc_fatal_warnings"); get_int(&target_config->optimization_level, target_table, "opt"); diff --git a/src/cfg/opt.h b/src/cfg/opt.h index c319d9f..1d1c67e 100644 --- a/src/cfg/opt.h +++ b/src/cfg/opt.h @@ -19,6 +19,10 @@ typedef struct TargetLinkConfig_t { // name of object files to link GArray* object_file_names; + // treat warnings as errors + gboolean fatal_warnings; + // colorize linker output + bool colorize; } TargetLinkConfig; typedef enum TargetCompilationMode_t { @@ -52,6 +56,10 @@ typedef struct TargetConfig_t { // path to look for object files // (can be extra library paths, auto included is output_directory) GArray* link_search_paths; + // treat linker warnings as errors + bool lld_fatal_warnings; + // treat parser warnings as errors + bool gsc_fatal_warnings; } TargetConfig; /** diff --git a/src/llvm/link/lld.c b/src/llvm/link/lld.c index f4e2d24..b3189c4 100644 --- a/src/llvm/link/lld.c +++ b/src/llvm/link/lld.c @@ -4,6 +4,8 @@ #include #include +#include +#include /* * call the LLD linker @@ -39,9 +41,11 @@ const char* get_absolute_link_path(const TargetConfig* config, const char* link_ TargetLinkConfig* lld_create_link_config(const Target* target, const TargetConfig* target_config, const Module* module) { DEBUG("generating link configuration"); - TargetLinkConfig* config = malloc(sizeof(TargetLinkConfig)); + TargetLinkConfig* config = mem_alloc(MemoryNamespaceLld, sizeof(TargetLinkConfig)); + config->fatal_warnings = target_config->lld_fatal_warnings; config->object_file_names = g_array_new(FALSE, FALSE, sizeof(char*)); + config->colorize = stdout_supports_ansi_esc(); // append build object file const char* target_object = get_absolute_link_path(target_config, (const char*) target->name.str); @@ -74,11 +78,35 @@ TargetLinkConfig* lld_create_link_config(const Target* target, const TargetConfi return config; } +GArray* lld_create_lld_arguments(TargetLinkConfig* config) { + GArray* argv = g_array_new(FALSE, FALSE, sizeof(char*)); + + if (config->fatal_warnings) { + g_array_append_val(argv, "--fatal-warnings"); + } + + if (config->colorize) { + g_array_append_val(argv, "--color-diagnostics=always"); + } + + for (guint i = 0; i < config->object_file_names->len; i++) { + char* object_file_path = g_array_index(config->object_file_names, char*, i); + char* argument = g_strjoin("", "-l", object_file_path, NULL); + g_array_append_val(argv, argument); + } + + return argv; +} + BackendError lld_link_target(TargetLinkConfig* config) { BackendError err = SUCCESS; + GArray* argv = lld_create_lld_arguments(config); + const char* message = NULL; - int status = lld_main(0, NULL, &message); + int status = lld_main((int) argv->len, (const char**) argv->data, &message); + + g_array_free(argv, TRUE); if (message != NULL) { print_message(Warning, "Message from LLD: %s", message); @@ -97,5 +125,5 @@ void lld_delete_link_config(TargetLinkConfig* config) { free((void*) g_array_index(config->object_file_names, const char*, i)); } g_array_free(config->object_file_names, TRUE); - free(config); + mem_free(config); } diff --git a/src/mem/cache.h b/src/mem/cache.h index d6ac067..8910ad1 100644 --- a/src/mem/cache.h +++ b/src/mem/cache.h @@ -16,6 +16,7 @@ typedef char* MemoryNamespaceName; #define MemoryNamespaceOpt "Options" #define MemoryNamespaceSet "SET" #define MemoryNamespaceLlvm "LLVM" +#define MemoryNamespaceLld "LLD" #define MemoryNamespaceIo "I/O" #define MemoryNamespaceStatic "Static"