diff options
| author | gingerBill <gingerBill@users.noreply.github.com> | 2023-06-23 14:33:01 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-06-23 14:33:01 +0100 |
| commit | 26a5614572afd39fc35fc32b47d5f7e5e9771e56 (patch) | |
| tree | ed94ed8589d3d0e32a5a8e494319bfcf292d27cd /src/main.cpp | |
| parent | f36e19e86fe88198fc1d17426afea577920efbf8 (diff) | |
| parent | 19ea0906332e6185cd0eefe873179b9058ccd725 (diff) | |
Merge branch 'master' into skytrias-vendor-additions
Diffstat (limited to 'src/main.cpp')
| -rw-r--r-- | src/main.cpp | 485 |
1 files changed, 253 insertions, 232 deletions
diff --git a/src/main.cpp b/src/main.cpp index e816906d6..2198b4536 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,31 +3,56 @@ #include "common.cpp" #include "timings.cpp" #include "tokenizer.cpp" +#if defined(GB_SYSTEM_WINDOWS) + #pragma warning(push) + #pragma warning(disable: 4505) +#endif #include "big_int.cpp" +#if defined(GB_SYSTEM_WINDOWS) + #pragma warning(pop) +#endif #include "exact_value.cpp" #include "build_settings.cpp" - gb_global ThreadPool global_thread_pool; -void init_global_thread_pool(void) { +gb_internal void init_global_thread_pool(void) { isize thread_count = gb_max(build_context.thread_count, 1); - isize worker_count = thread_count-1; // NOTE(bill): The main thread will also be used for work - thread_pool_init(&global_thread_pool, permanent_allocator(), worker_count, "ThreadPoolWorker"); + isize worker_count = thread_count; // +1 + thread_pool_init(&global_thread_pool, worker_count, "ThreadPoolWorker"); } -bool global_thread_pool_add_task(WorkerTaskProc *proc, void *data) { +gb_internal bool thread_pool_add_task(WorkerTaskProc *proc, void *data) { return thread_pool_add_task(&global_thread_pool, proc, data); } -void global_thread_pool_wait(void) { +gb_internal void thread_pool_wait(void) { thread_pool_wait(&global_thread_pool); } -void debugf(char const *fmt, ...) { +gb_internal i64 PRINT_PEAK_USAGE(void) { + if (build_context.show_more_timings) { + #if defined(GB_SYSTEM_WINDOWS) + PROCESS_MEMORY_COUNTERS p = {sizeof(p)}; + if (GetProcessMemoryInfo(GetCurrentProcess(), &p, sizeof(p))) { + gb_printf("\n"); + gb_printf("Peak Memory Size: %.3f MiB\n", (cast(f64)p.PeakWorkingSetSize) / cast(f64)(1024ull * 1024ull)); + return cast(i64)p.PeakWorkingSetSize; + } + #endif + } + return 0; +} + + +gb_global BlockingMutex debugf_mutex; + +gb_internal void debugf(char const *fmt, ...) { if (build_context.show_debug_messages) { + mutex_lock(&debugf_mutex); gb_printf_err("[DEBUG] "); va_list va; va_start(va, fmt); (void)gb_printf_err_va(fmt, va); va_end(va); + mutex_unlock(&debugf_mutex); } } @@ -58,11 +83,10 @@ gb_global Timings global_timings = {0}; #endif #endif -#include "query_data.cpp" #include "bug_report.cpp" // NOTE(bill): 'name' is used in debugging and profiling modes -i32 system_exec_command_line_app(char const *name, char const *fmt, ...) { +gb_internal i32 system_exec_command_line_app(char const *name, char const *fmt, ...) { isize const cmd_cap = 64<<20; // 64 MiB should be more than enough char *cmd_line = gb_alloc_array(gb_heap_allocator(), char, cmd_cap); isize cmd_len = 0; @@ -124,7 +148,7 @@ i32 system_exec_command_line_app(char const *name, char const *fmt, ...) { } -i32 linker_stage(lbGenerator *gen) { +gb_internal i32 linker_stage(lbGenerator *gen) { i32 result = 0; Timings *timings = &global_timings; @@ -207,15 +231,14 @@ i32 linker_stage(lbGenerator *gen) { StringSet libs = {}; - string_set_init(&libs, heap_allocator(), 64); + string_set_init(&libs, 64); defer (string_set_destroy(&libs)); StringSet asm_files = {}; - string_set_init(&asm_files, heap_allocator(), 64); + string_set_init(&asm_files, 64); defer (string_set_destroy(&asm_files)); - for_array(j, gen->foreign_libraries) { - Entity *e = gen->foreign_libraries[j]; + for (Entity *e : gen->foreign_libraries) { GB_ASSERT(e->kind == Entity_LibraryName); for_array(i, e->LibraryName.paths) { String lib = string_trim_whitespace(e->LibraryName.paths[i]); @@ -255,6 +278,13 @@ i32 linker_stage(lbGenerator *gen) { } } + for (Entity *e : gen->foreign_libraries) { + GB_ASSERT(e->kind == Entity_LibraryName); + if (e->LibraryName.extra_linker_flags.len != 0) { + lib_str = gb_string_append_fmt(lib_str, " %.*s", LIT(e->LibraryName.extra_linker_flags)); + } + } + if (build_context.build_mode == BuildMode_DynamicLibrary) { link_settings = gb_string_append_fmt(link_settings, " /DLL"); } else { @@ -278,8 +308,7 @@ i32 linker_stage(lbGenerator *gen) { gbString object_files = gb_string_make(heap_allocator(), ""); defer (gb_string_free(object_files)); - for_array(i, gen->output_object_paths) { - String object_path = gen->output_object_paths[i]; + for (String const &object_path : gen->output_object_paths) { object_files = gb_string_append_fmt(object_files, "\"%.*s\" ", LIT(object_path)); } @@ -313,12 +342,18 @@ i32 linker_stage(lbGenerator *gen) { } } + switch (build_context.build_mode) { + case BuildMode_Executable: + link_settings = gb_string_append_fmt(link_settings, " /NOIMPLIB /NOEXP"); + break; + } + result = system_exec_command_line_app("msvc-link", "\"%.*slink.exe\" %s %.*s -OUT:\"%.*s\" %s " "/nologo /incremental:no /opt:ref /subsystem:%s " - " %.*s " - " %.*s " - " %s " + "%.*s " + "%.*s " + "%s " "", LIT(vs_exe_path), object_files, LIT(res_path), LIT(output_filename), link_settings, @@ -334,9 +369,9 @@ i32 linker_stage(lbGenerator *gen) { result = system_exec_command_line_app("msvc-lld-link", "\"%.*s\\bin\\lld-link\" %s -OUT:\"%.*s\" %s " "/nologo /incremental:no /opt:ref /subsystem:%s " - " %.*s " - " %.*s " - " %s " + "%.*s " + "%.*s " + "%s " "", LIT(build_context.ODIN_ROOT), object_files, LIT(output_filename), link_settings, @@ -366,14 +401,13 @@ i32 linker_stage(lbGenerator *gen) { defer (gb_string_free(lib_str)); StringSet libs = {}; - string_set_init(&libs, heap_allocator(), 64); + string_set_init(&libs, 64); defer (string_set_destroy(&libs)); - for_array(j, gen->foreign_libraries) { - Entity *e = gen->foreign_libraries[j]; + for (Entity *e : gen->foreign_libraries) { GB_ASSERT(e->kind == Entity_LibraryName); - for_array(i, e->LibraryName.paths) { - String lib = string_trim_whitespace(e->LibraryName.paths[i]); + for (String lib : e->LibraryName.paths) { + lib = string_trim_whitespace(lib); if (lib.len == 0) { continue; } @@ -422,11 +456,16 @@ i32 linker_stage(lbGenerator *gen) { } } + for (Entity *e : gen->foreign_libraries) { + GB_ASSERT(e->kind == Entity_LibraryName); + if (e->LibraryName.extra_linker_flags.len != 0) { + lib_str = gb_string_append_fmt(lib_str, " %.*s", LIT(e->LibraryName.extra_linker_flags)); + } + } gbString object_files = gb_string_make(heap_allocator(), ""); defer (gb_string_free(object_files)); - for_array(i, gen->output_object_paths) { - String object_path = gen->output_object_paths[i]; + for (String object_path : gen->output_object_paths) { object_files = gb_string_append_fmt(object_files, "\"%.*s\" ", LIT(object_path)); } @@ -524,7 +563,7 @@ i32 linker_stage(lbGenerator *gen) { return result; } -Array<String> setup_args(int argc, char const **argv) { +gb_internal Array<String> setup_args(int argc, char const **argv) { gbAllocator a = heap_allocator(); #if defined(GB_SYSTEM_WINDOWS) @@ -553,18 +592,18 @@ Array<String> setup_args(int argc, char const **argv) { #endif } -void print_usage_line(i32 indent, char const *fmt, ...) { +gb_internal void print_usage_line(i32 indent, char const *fmt, ...) { while (indent --> 0) { - gb_printf_err("\t"); + gb_printf("\t"); } va_list va; va_start(va, fmt); - gb_printf_err_va(fmt, va); + gb_printf_va(fmt, va); va_end(va); - gb_printf_err("\n"); + gb_printf("\n"); } -void usage(String argv0) { +gb_internal void usage(String argv0) { print_usage_line(0, "%.*s is a tool for managing Odin source code", LIT(argv0)); print_usage_line(0, "Usage:"); print_usage_line(1, "%.*s command [arguments]", LIT(argv0)); @@ -573,7 +612,6 @@ void usage(String argv0) { print_usage_line(1, " one must contain the program's entry point, all must be in the same package."); print_usage_line(1, "run same as 'build', but also then runs the newly compiled executable."); print_usage_line(1, "check parse, and type check a directory of .odin files"); - print_usage_line(1, "query parse, type check, and output a .json file containing information about the program"); print_usage_line(1, "strip-semicolon parse, type check, and remove unneeded semicolons from the entire program"); print_usage_line(1, "test build and runs procedures with the attribute @(test) in the initial package"); print_usage_line(1, "doc generate documentation on a directory of .odin files"); @@ -613,18 +651,17 @@ enum BuildFlagKind { BuildFlag_NoEntryPoint, BuildFlag_UseLLD, BuildFlag_UseSeparateModules, - BuildFlag_ThreadedChecker, BuildFlag_NoThreadedChecker, BuildFlag_ShowDebugMessages, BuildFlag_Vet, BuildFlag_VetExtra, - BuildFlag_UseLLVMApi, BuildFlag_IgnoreUnknownAttributes, BuildFlag_ExtraLinkerFlags, BuildFlag_ExtraAssemblerFlags, BuildFlag_Microarch, BuildFlag_TargetFeatures, BuildFlag_MinimumOSVersion, + BuildFlag_NoThreadLocal, BuildFlag_RelocMode, BuildFlag_DisableRedZone, @@ -633,12 +670,11 @@ enum BuildFlagKind { BuildFlag_DisallowDo, BuildFlag_DefaultToNilAllocator, - BuildFlag_InsertSemicolon, BuildFlag_StrictStyle, BuildFlag_StrictStyleInitOnly, BuildFlag_ForeignErrorProcedures, - BuildFlag_DisallowRTTI, - BuildFlag_UseStaticMapCalls, + BuildFlag_NoRTTI, + BuildFlag_DynamicMapCalls, BuildFlag_Compact, BuildFlag_GlobalDefinitions, @@ -650,11 +686,14 @@ enum BuildFlagKind { BuildFlag_IgnoreWarnings, BuildFlag_WarningsAsErrors, + BuildFlag_TerseErrors, BuildFlag_VerboseErrors, BuildFlag_ErrorPosStyle, + BuildFlag_MaxErrorCount, // internal use only BuildFlag_InternalIgnoreLazy, + BuildFlag_InternalIgnoreLLVMBuild, #if defined(GB_SYSTEM_WINDOWS) BuildFlag_IgnoreVsSearch, @@ -687,12 +726,12 @@ struct BuildFlag { }; -void add_flag(Array<BuildFlag> *build_flags, BuildFlagKind kind, String name, BuildFlagParamKind param_kind, u32 command_support, bool allow_mulitple=false) { +gb_internal void add_flag(Array<BuildFlag> *build_flags, BuildFlagKind kind, String name, BuildFlagParamKind param_kind, u32 command_support, bool allow_mulitple=false) { BuildFlag flag = {kind, name, param_kind, command_support, allow_mulitple}; array_add(build_flags, flag); } -ExactValue build_param_to_exact_value(String name, String param) { +gb_internal ExactValue build_param_to_exact_value(String name, String param) { ExactValue value = {}; /* @@ -747,7 +786,7 @@ ExactValue build_param_to_exact_value(String name, String param) { } // Writes a did-you-mean message for formerly deprecated flags. -void did_you_mean_flag(String flag) { +gb_internal void did_you_mean_flag(String flag) { gbAllocator a = heap_allocator(); String name = copy_string(a, flag); defer (gb_free(a, name.text)); @@ -760,7 +799,7 @@ void did_you_mean_flag(String flag) { gb_printf_err("Unknown flag: '%.*s'\n", LIT(flag)); } -bool parse_build_flags(Array<String> args) { +gb_internal bool parse_build_flags(Array<String> args) { auto build_flags = array_make<BuildFlag>(heap_allocator(), 0, BuildFlag_COUNT); add_flag(&build_flags, BuildFlag_Help, str_lit("help"), BuildFlagParam_None, Command_all); add_flag(&build_flags, BuildFlag_SingleFile, str_lit("file"), BuildFlagParam_None, Command__does_build | Command__does_check); @@ -783,17 +822,16 @@ bool parse_build_flags(Array<String> args) { add_flag(&build_flags, BuildFlag_Debug, str_lit("debug"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_DisableAssert, str_lit("disable-assert"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoBoundsCheck, str_lit("no-bounds-check"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_NoThreadLocal, str_lit("no-thread-local"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoDynamicLiterals, str_lit("no-dynamic-literals"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoCRT, str_lit("no-crt"), BuildFlagParam_None, Command__does_build); add_flag(&build_flags, BuildFlag_NoEntryPoint, str_lit("no-entry-point"), BuildFlagParam_None, Command__does_check &~ Command_test); add_flag(&build_flags, BuildFlag_UseLLD, str_lit("lld"), BuildFlagParam_None, Command__does_build); add_flag(&build_flags, BuildFlag_UseSeparateModules, str_lit("use-separate-modules"), BuildFlagParam_None, Command__does_build); - add_flag(&build_flags, BuildFlag_ThreadedChecker, str_lit("threaded-checker"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoThreadedChecker, str_lit("no-threaded-checker"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_ShowDebugMessages, str_lit("show-debug-messages"), BuildFlagParam_None, Command_all); add_flag(&build_flags, BuildFlag_Vet, str_lit("vet"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_VetExtra, str_lit("vet-extra"), BuildFlagParam_None, Command__does_check); - add_flag(&build_flags, BuildFlag_UseLLVMApi, str_lit("llvm-api"), BuildFlagParam_None, Command__does_build); add_flag(&build_flags, BuildFlag_IgnoreUnknownAttributes, str_lit("ignore-unknown-attributes"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_ExtraLinkerFlags, str_lit("extra-linker-flags"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_ExtraAssemblerFlags, str_lit("extra-assembler-flags"), BuildFlagParam_String, Command__does_build); @@ -808,20 +846,14 @@ bool parse_build_flags(Array<String> args) { add_flag(&build_flags, BuildFlag_DisallowDo, str_lit("disallow-do"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_DefaultToNilAllocator, str_lit("default-to-nil-allocator"), BuildFlagParam_None, Command__does_check); - add_flag(&build_flags, BuildFlag_InsertSemicolon, str_lit("insert-semicolon"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_StrictStyle, str_lit("strict-style"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_StrictStyleInitOnly, str_lit("strict-style-init-only"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_ForeignErrorProcedures, str_lit("foreign-error-procedures"), BuildFlagParam_None, Command__does_check); - add_flag(&build_flags, BuildFlag_DisallowRTTI, str_lit("disallow-rtti"), BuildFlagParam_None, Command__does_check); - - add_flag(&build_flags, BuildFlag_UseStaticMapCalls, str_lit("use-static-map-calls"), BuildFlagParam_None, Command__does_check); - - - add_flag(&build_flags, BuildFlag_Compact, str_lit("compact"), BuildFlagParam_None, Command_query); - add_flag(&build_flags, BuildFlag_GlobalDefinitions, str_lit("global-definitions"), BuildFlagParam_None, Command_query); - add_flag(&build_flags, BuildFlag_GoToDefinitions, str_lit("go-to-definitions"), BuildFlagParam_None, Command_query); + add_flag(&build_flags, BuildFlag_NoRTTI, str_lit("no-rtti"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_NoRTTI, str_lit("disallow-rtti"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_DynamicMapCalls, str_lit("dynamic-map-calls"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_Short, str_lit("short"), BuildFlagParam_None, Command_doc); add_flag(&build_flags, BuildFlag_AllPackages, str_lit("all-packages"), BuildFlagParam_None, Command_doc); @@ -829,10 +861,13 @@ bool parse_build_flags(Array<String> args) { add_flag(&build_flags, BuildFlag_IgnoreWarnings, str_lit("ignore-warnings"), BuildFlagParam_None, Command_all); add_flag(&build_flags, BuildFlag_WarningsAsErrors, str_lit("warnings-as-errors"), BuildFlagParam_None, Command_all); + add_flag(&build_flags, BuildFlag_TerseErrors, str_lit("terse-errors"), BuildFlagParam_None, Command_all); add_flag(&build_flags, BuildFlag_VerboseErrors, str_lit("verbose-errors"), BuildFlagParam_None, Command_all); add_flag(&build_flags, BuildFlag_ErrorPosStyle, str_lit("error-pos-style"), BuildFlagParam_String, Command_all); + add_flag(&build_flags, BuildFlag_MaxErrorCount, str_lit("max-error-count"), BuildFlagParam_Integer, Command_all); add_flag(&build_flags, BuildFlag_InternalIgnoreLazy, str_lit("internal-ignore-lazy"), BuildFlagParam_None, Command_all); + add_flag(&build_flags, BuildFlag_InternalIgnoreLLVMBuild, str_lit("internal-ignore-llvm-build"),BuildFlagParam_None, Command_all); #if defined(GB_SYSTEM_WINDOWS) add_flag(&build_flags, BuildFlag_IgnoreVsSearch, str_lit("ignore-vs-search"), BuildFlagParam_None, Command__does_build); @@ -848,8 +883,7 @@ bool parse_build_flags(Array<String> args) { bool set_flags[BuildFlag_COUNT] = {}; bool bad_flags = false; - for_array(i, flag_args) { - String flag = flag_args[i]; + for (String flag : flag_args) { if (flag[0] != '-') { gb_printf_err("Invalid flag: %.*s\n", LIT(flag)); continue; @@ -878,8 +912,7 @@ bool parse_build_flags(Array<String> args) { bool found = false; BuildFlag found_bf = {}; - for_array(build_flag_index, build_flags) { - BuildFlag bf = build_flags[build_flag_index]; + for (BuildFlag const &bf : build_flags) { if (bf.name == name) { found = true; found_bf = bf; @@ -998,11 +1031,17 @@ bool parse_build_flags(Array<String> args) { } case BuildFlag_OptimizationMode: { GB_ASSERT(value.kind == ExactValue_String); - if (value.value_string == "minimal") { + if (value.value_string == "none") { + build_context.custom_optimization_level = true; + build_context.optimization_level = -1; + } else if (value.value_string == "minimal") { + build_context.custom_optimization_level = true; build_context.optimization_level = 0; } else if (value.value_string == "size") { + build_context.custom_optimization_level = true; build_context.optimization_level = 1; } else if (value.value_string == "speed") { + build_context.custom_optimization_level = true; build_context.optimization_level = 2; } else { gb_printf_err("Invalid optimization mode for -o:<string>, got %.*s\n", LIT(value.value_string)); @@ -1010,6 +1049,7 @@ bool parse_build_flags(Array<String> args) { gb_printf_err("\tminimal\n"); gb_printf_err("\tsize\n"); gb_printf_err("\tspeed\n"); + gb_printf_err("\tnone (useful for -debug builds)\n"); bad_flags = true; } break; @@ -1305,26 +1345,17 @@ bool parse_build_flags(Array<String> args) { case BuildFlag_NoEntryPoint: build_context.no_entry_point = true; break; + case BuildFlag_NoThreadLocal: + build_context.no_thread_local = true; + break; case BuildFlag_UseLLD: build_context.use_lld = true; break; case BuildFlag_UseSeparateModules: build_context.use_separate_modules = true; break; - case BuildFlag_ThreadedChecker: { - #if defined(DEFAULT_TO_THREADED_CHECKER) - gb_printf_err("-threaded-checker is the default on this platform\n"); - bad_flags = true; - #endif - build_context.threaded_checker = true; - break; - } case BuildFlag_NoThreadedChecker: { - #if !defined(DEFAULT_TO_THREADED_CHECKER) - gb_printf_err("-no-threaded-checker is the default on this platform\n"); - bad_flags = true; - #endif - build_context.threaded_checker = false; + build_context.no_threaded_checker = true; break; } case BuildFlag_ShowDebugMessages: @@ -1338,11 +1369,6 @@ bool parse_build_flags(Array<String> args) { build_context.vet_extra = true; break; } - case BuildFlag_UseLLVMApi: { - gb_printf_err("-llvm-api flag is not required any more\n"); - bad_flags = true; - break; - } case BuildFlag_IgnoreUnknownAttributes: build_context.ignore_unknown_attributes = true; break; @@ -1414,11 +1440,15 @@ bool parse_build_flags(Array<String> args) { case BuildFlag_DisallowDo: build_context.disallow_do = true; break; - case BuildFlag_DisallowRTTI: - build_context.disallow_rtti = true; + case BuildFlag_NoRTTI: + if (name == "disallow-rtti") { + gb_printf_err("'-disallow-rtti' has been replaced with '-no-rtti'\n"); + bad_flags = true; + } + build_context.no_rtti = true; break; - case BuildFlag_UseStaticMapCalls: - build_context.use_static_map_calls = true; + case BuildFlag_DynamicMapCalls: + build_context.dynamic_map_calls = true; break; case BuildFlag_DefaultToNilAllocator: build_context.ODIN_DEFAULT_TO_NIL_ALLOCATOR = true; @@ -1426,11 +1456,6 @@ bool parse_build_flags(Array<String> args) { case BuildFlag_ForeignErrorProcedures: build_context.ODIN_FOREIGN_ERROR_PROCEDURES = true; break; - case BuildFlag_InsertSemicolon: { - gb_printf_err("-insert-semicolon flag is not required any more\n"); - bad_flags = true; - break; - } case BuildFlag_StrictStyle: { if (build_context.strict_style_init_only) { gb_printf_err("-strict-style and -strict-style-init-only cannot be used together\n"); @@ -1445,39 +1470,6 @@ bool parse_build_flags(Array<String> args) { build_context.strict_style_init_only = true; break; } - case BuildFlag_Compact: { - if (!build_context.query_data_set_settings.ok) { - gb_printf_err("Invalid use of -compact flag, only allowed with 'odin query'\n"); - bad_flags = true; - } else { - build_context.query_data_set_settings.compact = true; - } - break; - } - case BuildFlag_GlobalDefinitions: { - if (!build_context.query_data_set_settings.ok) { - gb_printf_err("Invalid use of -global-definitions flag, only allowed with 'odin query'\n"); - bad_flags = true; - } else if (build_context.query_data_set_settings.kind != QueryDataSet_Invalid) { - gb_printf_err("Invalid use of -global-definitions flag, a previous flag for 'odin query' was set\n"); - bad_flags = true; - } else { - build_context.query_data_set_settings.kind = QueryDataSet_GlobalDefinitions; - } - break; - } - case BuildFlag_GoToDefinitions: { - if (!build_context.query_data_set_settings.ok) { - gb_printf_err("Invalid use of -go-to-definitions flag, only allowed with 'odin query'\n"); - bad_flags = true; - } else if (build_context.query_data_set_settings.kind != QueryDataSet_Invalid) { - gb_printf_err("Invalid use of -global-definitions flag, a previous flag for 'odin query' was set\n"); - bad_flags = true; - } else { - build_context.query_data_set_settings.kind = QueryDataSet_GoToDefinitions; - } - break; - } case BuildFlag_Short: build_context.cmd_doc_flags |= CmdDocFlag_Short; break; @@ -1505,8 +1497,13 @@ bool parse_build_flags(Array<String> args) { } break; } + + case BuildFlag_TerseErrors: + build_context.hide_error_line = true; + break; case BuildFlag_VerboseErrors: - build_context.show_error_line = true; + gb_printf_err("-verbose-errors is not the default, -terse-errors can now disable it\n"); + build_context.hide_error_line = false; break; case BuildFlag_ErrorPosStyle: @@ -1522,9 +1519,23 @@ bool parse_build_flags(Array<String> args) { } break; + case BuildFlag_MaxErrorCount: { + i64 count = big_int_to_i64(&value.value_integer); + if (count <= 0) { + gb_printf_err("-%.*s must be greater than 0", LIT(bf.name)); + bad_flags = true; + } else { + build_context.max_error_count = cast(isize)count; + } + break; + } + case BuildFlag_InternalIgnoreLazy: build_context.ignore_lazy = true; break; + case BuildFlag_InternalIgnoreLLVMBuild: + build_context.ignore_llvm_build = true; + break; #if defined(GB_SYSTEM_WINDOWS) case BuildFlag_IgnoreVsSearch: { GB_ASSERT(value.kind == ExactValue_Invalid); @@ -1638,20 +1649,10 @@ bool parse_build_flags(Array<String> args) { gb_printf_err("`-export-timings:<format>` requires `-show-timings` or `-show-more-timings` to be present\n"); bad_flags = true; } - - if (build_context.query_data_set_settings.ok) { - if (build_context.query_data_set_settings.kind == QueryDataSet_Invalid) { - gb_printf_err("'odin query' requires a flag determining the kind of query data set to be returned\n"); - gb_printf_err("\t-global-definitions : outputs a JSON file of global definitions\n"); - gb_printf_err("\t-go-to-definitions : outputs a OGTD binary file of go to definitions for identifiers within an Odin project\n"); - bad_flags = true; - } - } - return !bad_flags; } -void timings_export_all(Timings *t, Checker *c, bool timings_are_finalized = false) { +gb_internal void timings_export_all(Timings *t, Checker *c, bool timings_are_finalized = false) { GB_ASSERT((!(build_context.export_timings_format == TimingsExportUnspecified) && build_context.export_timings_file.len > 0)); /* @@ -1690,10 +1691,9 @@ void timings_export_all(Timings *t, Checker *c, bool timings_are_finalized = fal isize files = 0; isize packages = p->packages.count; isize total_file_size = 0; - for_array(i, p->packages) { - files += p->packages[i]->files.count; - for_array(j, p->packages[i]->files) { - AstFile *file = p->packages[i]->files[j]; + for (AstPackage *pkg : p->packages) { + files += pkg->files.count; + for (AstFile *file : pkg->files) { total_file_size += file->tokenizer.end - file->tokenizer.start; } } @@ -1717,8 +1717,7 @@ void timings_export_all(Timings *t, Checker *c, bool timings_are_finalized = fal gb_fprintf(&f, "\t\t{\"name\": \"%.*s\", \"millis\": %.3f},\n", LIT(t->total.label), total_time); - for_array(i, t->sections) { - TimeStamp ts = t->sections[i]; + for (TimeStamp const &ts : t->sections) { f64 section_time = time_stamp(ts, t->freq, unit); gb_fprintf(&f, "\t\t{\"name\": \"%.*s\", \"millis\": %.3f},\n", LIT(ts.label), section_time); @@ -1739,8 +1738,7 @@ void timings_export_all(Timings *t, Checker *c, bool timings_are_finalized = fal */ gb_fprintf(&f, "\"%.*s\", %d\n", LIT(t->total.label), int(total_time)); - for_array(i, t->sections) { - TimeStamp ts = t->sections[i]; + for (TimeStamp const &ts : t->sections) { f64 section_time = time_stamp(ts, t->freq, unit); gb_fprintf(&f, "\"%.*s\", %d\n", LIT(ts.label), int(section_time)); } @@ -1749,7 +1747,7 @@ void timings_export_all(Timings *t, Checker *c, bool timings_are_finalized = fal gb_printf("Done.\n"); } -void show_timings(Checker *c, Timings *t) { +gb_internal void show_timings(Checker *c, Timings *t) { Parser *p = c->parser; isize lines = p->total_line_count; isize tokens = p->total_token_count; @@ -1758,10 +1756,9 @@ void show_timings(Checker *c, Timings *t) { isize total_file_size = 0; f64 total_tokenizing_time = 0; f64 total_parsing_time = 0; - for_array(i, p->packages) { - files += p->packages[i]->files.count; - for_array(j, p->packages[i]->files) { - AstFile *file = p->packages[i]->files[j]; + for (AstPackage *pkg : p->packages) { + files += pkg->files.count; + for (AstFile *file : pkg->files) { total_tokenizing_time += file->time_to_tokenize; total_parsing_time += file->time_to_parse; total_file_size += file->tokenizer.end - file->tokenizer.start; @@ -1770,6 +1767,8 @@ void show_timings(Checker *c, Timings *t) { timings_print_all(t); + PRINT_PEAK_USAGE(); + if (!(build_context.export_timings_format == TimingsExportUnspecified)) { timings_export_all(t, c, true); } @@ -1812,8 +1811,7 @@ void show_timings(Checker *c, Timings *t) { } { TimeStamp ts = {}; - for_array(i, t->sections) { - TimeStamp s = t->sections[i]; + for (TimeStamp const &s : t->sections) { if (s.label == "parse files") { ts = s; break; @@ -1836,8 +1834,7 @@ void show_timings(Checker *c, Timings *t) { { TimeStamp ts = {}; TimeStamp ts_end = {}; - for_array(i, t->sections) { - TimeStamp s = t->sections[i]; + for (TimeStamp const &s : t->sections) { if (s.label == "type check") { ts = s; } @@ -1878,13 +1875,23 @@ void show_timings(Checker *c, Timings *t) { } } -void remove_temp_files(lbGenerator *gen) { +gb_internal void remove_temp_files(lbGenerator *gen) { if (build_context.keep_temp_files) return; + switch (build_context.build_mode) { + case BuildMode_Executable: + case BuildMode_DynamicLibrary: + break; + + case BuildMode_Object: + case BuildMode_Assembly: + case BuildMode_LLVM_IR: + return; + } + TIME_SECTION("remove keep temp files"); - for_array(i, gen->output_temp_paths) { - String path = gen->output_temp_paths[i]; + for (String const &path : gen->output_temp_paths) { gb_file_remove(cast(char const *)path.text); } @@ -1892,8 +1899,7 @@ void remove_temp_files(lbGenerator *gen) { switch (build_context.build_mode) { case BuildMode_Executable: case BuildMode_DynamicLibrary: - for_array(i, gen->output_object_paths) { - String path = gen->output_object_paths[i]; + for (String const &path : gen->output_object_paths) { gb_file_remove(cast(char const *)path.text); } break; @@ -1902,7 +1908,7 @@ void remove_temp_files(lbGenerator *gen) { } -void print_show_help(String const arg0, String const &command) { +gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(0, "%.*s is a tool for managing Odin source code", LIT(arg0)); print_usage_line(0, "Usage:"); print_usage_line(1, "%.*s %.*s [arguments]", LIT(arg0), LIT(command)); @@ -1931,8 +1937,6 @@ void print_show_help(String const arg0, String const &command) { print_usage_line(3, "odin check filename.odin -file # Type check single-file package, must contain entry point."); } else if (command == "test") { print_usage_line(1, "test Build and runs procedures with the attribute @(test) in the initial package"); - } else if (command == "query") { - print_usage_line(1, "query [experimental] Parse, type check, and output a .json file containing information about the program"); } else if (command == "doc") { print_usage_line(1, "doc generate documentation from a directory of .odin files"); print_usage_line(2, "Examples:"); @@ -1987,7 +1991,7 @@ void print_show_help(String const arg0, String const &command) { print_usage_line(1, "-o:<string>"); print_usage_line(2, "Set the optimization mode for compilation"); - print_usage_line(2, "Accepted values: minimal, size, speed"); + print_usage_line(2, "Accepted values: minimal, size, speed, none"); print_usage_line(2, "Example: -o:speed"); print_usage_line(0, ""); } @@ -2093,6 +2097,10 @@ void print_show_help(String const arg0, String const &command) { print_usage_line(2, "Disables automatic linking with the C Run Time"); print_usage_line(0, ""); + print_usage_line(1, "-no-thread-local"); + print_usage_line(2, "Ignore @thread_local attribute, effectively treating the program as if it is single-threaded"); + print_usage_line(0, ""); + print_usage_line(1, "-lld"); print_usage_line(2, "Use the LLD linker rather than the default"); print_usage_line(0, ""); @@ -2180,6 +2188,11 @@ void print_show_help(String const arg0, String const &command) { print_usage_line(1, "-disable-red-zone"); print_usage_line(2, "Disable red zone on a supported freestanding target"); + print_usage_line(0, ""); + + print_usage_line(1, "-dynamic-map-calls"); + print_usage_line(2, "Use dynamic map calls to minimize code generation at the cost of runtime execution"); + print_usage_line(0, ""); } if (check) { @@ -2207,8 +2220,21 @@ void print_show_help(String const arg0, String const &command) { print_usage_line(2, "Treats warning messages as error messages"); print_usage_line(0, ""); - print_usage_line(1, "-verbose-errors"); - print_usage_line(2, "Prints verbose error messages showing the code on that line and the location in that line"); + print_usage_line(1, "-terse-errors"); + print_usage_line(2, "Prints a terse error message without showing the code on that line and the location in that line"); + print_usage_line(0, ""); + + print_usage_line(1, "-error-pos-style:<string>"); + print_usage_line(2, "Options are 'unix', 'odin' and 'default' (odin)"); + print_usage_line(2, "'odin' file/path(45:3)"); + print_usage_line(2, "'unix' file/path:45:3:"); + print_usage_line(0, ""); + + + print_usage_line(1, "-max-error-count:<integer>"); + print_usage_line(2, "Set the maximum number of errors that can be displayed before the compiler terminates"); + print_usage_line(2, "Must be an integer >0"); + print_usage_line(2, "If not set, the default max error count is %d", DEFAULT_MAX_ERROR_COLLECTOR_COUNT); print_usage_line(0, ""); print_usage_line(1, "-foreign-error-procedures"); @@ -2248,12 +2274,11 @@ void print_show_help(String const arg0, String const &command) { } } -void print_show_unused(Checker *c) { +gb_internal void print_show_unused(Checker *c) { CheckerInfo *info = &c->info; auto unused = array_make<Entity *>(permanent_allocator(), 0, info->entities.count); - for_array(i, info->entities) { - Entity *e = info->entities[i]; + for (Entity *e : info->entities) { if (e == nullptr) { continue; } @@ -2300,8 +2325,7 @@ void print_show_unused(Checker *c) { AstPackage *curr_pkg = nullptr; EntityKind curr_entity_kind = Entity_Invalid; - for_array(i, unused) { - Entity *e = unused[i]; + for (Entity *e : unused) { if (curr_pkg != e->pkg) { curr_pkg = e->pkg; curr_entity_kind = Entity_Invalid; @@ -2322,7 +2346,7 @@ void print_show_unused(Checker *c) { print_usage_line(0, ""); } -bool check_env(void) { +gb_internal bool check_env(void) { gbAllocator a = heap_allocator(); char const *odin_root = gb_get_env("ODIN_ROOT", a); defer (gb_free(a, cast(void *)odin_root)); @@ -2348,25 +2372,24 @@ struct StripSemicolonFile { i64 written; }; -gbFileError write_file_with_stripped_tokens(gbFile *f, AstFile *file, i64 *written_) { +gb_internal gbFileError write_file_with_stripped_tokens(gbFile *f, AstFile *file, i64 *written_) { i64 written = 0; gbFileError err = gbFileError_None; u8 const *file_data = file->tokenizer.start; i32 prev_offset = 0; i32 const end_offset = cast(i32)(file->tokenizer.end - file->tokenizer.start); - for_array(i, file->tokens) { - Token *token = &file->tokens[i]; - if (token->flags & (TokenFlag_Remove|TokenFlag_Replace)) { - i32 offset = token->pos.offset; + for (Token const &token : file->tokens) { + if (token.flags & (TokenFlag_Remove|TokenFlag_Replace)) { + i32 offset = token.pos.offset; i32 to_write = offset-prev_offset; if (!gb_file_write(f, file_data+prev_offset, to_write)) { return gbFileError_Invalid; } written += to_write; - prev_offset = token_pos_end(*token).offset; + prev_offset = token_pos_end(token).offset; } - if (token->flags & TokenFlag_Replace) { - if (token->kind == Token_Ellipsis) { + if (token.flags & TokenFlag_Replace) { + if (token.kind == Token_Ellipsis) { if (!gb_file_write(f, "..=", 3)) { return gbFileError_Invalid; } @@ -2388,24 +2411,19 @@ gbFileError write_file_with_stripped_tokens(gbFile *f, AstFile *file, i64 *writt return err; } -int strip_semicolons(Parser *parser) { +gb_internal int strip_semicolons(Parser *parser) { isize file_count = 0; - for_array(i, parser->packages) { - AstPackage *pkg = parser->packages[i]; + for (AstPackage *pkg : parser->packages) { file_count += pkg->files.count; } auto generated_files = array_make<StripSemicolonFile>(permanent_allocator(), 0, file_count); - for_array(i, parser->packages) { - AstPackage *pkg = parser->packages[i]; - for_array(j, pkg->files) { - AstFile *file = pkg->files[j]; - + for (AstPackage *pkg : parser->packages) { + for (AstFile *file : pkg->files) { bool nothing_to_change = true; - for_array(i, file->tokens) { - Token *token = &file->tokens[i]; - if (token->flags) { + for (Token const &token : file->tokens) { + if (token.flags) { nothing_to_change = false; break; } @@ -2433,9 +2451,8 @@ int strip_semicolons(Parser *parser) { isize generated_count = 0; bool failed = false; - for_array(i, generated_files) { - auto *file = &generated_files[i]; - char const *filename = cast(char const *)file->new_fullpath.text; + for (StripSemicolonFile &file : generated_files) { + char const *filename = cast(char const *)file.new_fullpath.text; gbFileError err = gbFileError_None; defer (if (err != gbFileError_None) { failed = true; @@ -2453,11 +2470,11 @@ int strip_semicolons(Parser *parser) { defer (err = gb_file_truncate(&f, written)); debugf("Write file with stripped tokens: %s\n", filename); - err = write_file_with_stripped_tokens(&f, file->file, &written); + err = write_file_with_stripped_tokens(&f, file.file, &written); if (err) { break; } - file->written = written; + file.written = written; } if (failed) { @@ -2472,12 +2489,10 @@ int strip_semicolons(Parser *parser) { isize overwritten_files = 0; - for_array(i, generated_files) { - auto *file = &generated_files[i]; - - char const *old_fullpath = cast(char const *)file->old_fullpath.text; - char const *old_fullpath_backup = cast(char const *)file->old_fullpath_backup.text; - char const *new_fullpath = cast(char const *)file->new_fullpath.text; + for (StripSemicolonFile const &file : generated_files) { + char const *old_fullpath = cast(char const *)file.old_fullpath.text; + char const *old_fullpath_backup = cast(char const *)file.old_fullpath_backup.text; + char const *new_fullpath = cast(char const *)file.new_fullpath.text; debugf("Copy '%s' to '%s'\n", old_fullpath, old_fullpath_backup); if (!gb_file_copy(old_fullpath, old_fullpath_backup, false)) { @@ -2532,27 +2547,46 @@ int strip_semicolons(Parser *parser) { return cast(int)failed; } +gb_internal void init_terminal(void) { + build_context.has_ansi_terminal_colours = false; +#if defined(GB_SYSTEM_WINDOWS) + HANDLE hnd = GetStdHandle(STD_ERROR_HANDLE); + DWORD mode = 0; + if (GetConsoleMode(hnd, &mode)) { + enum {FLAG_ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004}; + if (SetConsoleMode(hnd, mode|FLAG_ENABLE_VIRTUAL_TERMINAL_PROCESSING)) { + build_context.has_ansi_terminal_colours = true; + } + } +#endif + + if (!build_context.has_ansi_terminal_colours) { + gbAllocator a = heap_allocator(); + char const *odin_terminal_ = gb_get_env("ODIN_TERMINAL", a); + defer (gb_free(a, cast(void *)odin_terminal_)); + String odin_terminal = make_string_c(odin_terminal_); + if (str_eq_ignore_case(odin_terminal, str_lit("ansi"))) { + build_context.has_ansi_terminal_colours = true; + } + } +} + int main(int arg_count, char const **arg_ptr) { if (arg_count < 2) { usage(make_string_c(arg_ptr[0])); return 1; } + virtual_memory_init(); timings_init(&global_timings, str_lit("Total Time"), 2048); defer (timings_destroy(&global_timings)); MAIN_TIME_SECTION("initialization"); - virtual_memory_init(); - mutex_init(&fullpath_mutex); - mutex_init(&hash_exact_value_mutex); - mutex_init(&global_type_name_objc_metadata_mutex); - - init_string_buffer_memory(); init_string_interner(); init_global_error_collector(); init_keyword_hash_table(); - init_type_mutex(); + init_terminal(); if (!check_env()) { return 1; @@ -2563,9 +2597,9 @@ int main(int arg_count, char const **arg_ptr) { add_library_collection(str_lit("core"), get_fullpath_relative(heap_allocator(), odin_root_dir(), str_lit("core"))); add_library_collection(str_lit("vendor"), get_fullpath_relative(heap_allocator(), odin_root_dir(), str_lit("vendor"))); - map_init(&build_context.defined_values, heap_allocator()); + map_init(&build_context.defined_values); build_context.extra_packages.allocator = heap_allocator(); - string_set_init(&build_context.test_names, heap_allocator()); + string_set_init(&build_context.test_names); Array<String> args = setup_args(arg_count, arg_ptr); @@ -2627,15 +2661,6 @@ int main(int arg_count, char const **arg_ptr) { build_context.command_kind = Command_strip_semicolon; build_context.no_output_files = true; init_filename = args[2]; - } else if (command == "query") { - if (args.count < 3) { - usage(args[0]); - return 1; - } - build_context.command_kind = Command_query; - build_context.no_output_files = true; - build_context.query_data_set_settings.ok = true; - init_filename = args[2]; } else if (command == "doc") { if (args.count < 3) { usage(args[0]); @@ -2824,12 +2849,8 @@ int main(int arg_count, char const **arg_ptr) { print_show_unused(checker); } - if (build_context.query_data_set_settings.ok) { - generate_and_print_query_data(checker, &global_timings); - } else { - if (build_context.show_timings) { - show_timings(checker, &global_timings); - } + if (build_context.show_timings) { + show_timings(checker, &global_timings); } if (global_error_collector.count != 0) { @@ -2844,19 +2865,19 @@ int main(int arg_count, char const **arg_ptr) { if (!lb_init_generator(gen, checker)) { return 1; } - lb_generate_code(gen); - - switch (build_context.build_mode) { - case BuildMode_Executable: - case BuildMode_DynamicLibrary: - i32 result = linker_stage(gen); - if (result) { - if (build_context.show_timings) { - show_timings(checker, &global_timings); + if (lb_generate_code(gen)) { + switch (build_context.build_mode) { + case BuildMode_Executable: + case BuildMode_DynamicLibrary: + i32 result = linker_stage(gen); + if (result) { + if (build_context.show_timings) { + show_timings(checker, &global_timings); + } + return result; } - return result; + break; } - break; } remove_temp_files(gen); |