aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
authorgingerBill <gingerBill@users.noreply.github.com>2023-06-23 14:33:01 +0100
committerGitHub <noreply@github.com>2023-06-23 14:33:01 +0100
commit26a5614572afd39fc35fc32b47d5f7e5e9771e56 (patch)
treeed94ed8589d3d0e32a5a8e494319bfcf292d27cd /src/main.cpp
parentf36e19e86fe88198fc1d17426afea577920efbf8 (diff)
parent19ea0906332e6185cd0eefe873179b9058ccd725 (diff)
Merge branch 'master' into skytrias-vendor-additions
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp485
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);