From 25f1d0906d2b5a8276c3832783970a798c12cc6c Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Wed, 1 May 2024 22:12:37 +0200 Subject: compiler: improve target features support --- src/main.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 73 insertions(+), 6 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index ee7de7f81..93685acb9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -272,6 +272,7 @@ enum BuildFlagKind { BuildFlag_ExtraAssemblerFlags, BuildFlag_Microarch, BuildFlag_TargetFeatures, + BuildFlag_StrictTargetFeatures, BuildFlag_MinimumOSVersion, BuildFlag_NoThreadLocal, @@ -467,6 +468,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_ExtraAssemblerFlags, str_lit("extra-assembler-flags"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_Microarch, str_lit("microarch"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_TargetFeatures, str_lit("target-features"), BuildFlagParam_String, Command__does_build); + add_flag(&build_flags, BuildFlag_StrictTargetFeatures, str_lit("strict-target-features"), BuildFlagParam_None, Command__does_build); add_flag(&build_flags, BuildFlag_MinimumOSVersion, str_lit("minimum-os-version"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_RelocMode, str_lit("reloc-mode"), BuildFlagParam_String, Command__does_build); @@ -1083,6 +1085,9 @@ gb_internal bool parse_build_flags(Array args) { string_to_lower(&build_context.target_features_string); break; } + case BuildFlag_StrictTargetFeatures: + build_context.strict_target_features = true; + break; case BuildFlag_MinimumOSVersion: { GB_ASSERT(value.kind == ExactValue_String); build_context.minimum_os_version_string = value.value_string; @@ -1981,7 +1986,20 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(2, "Examples:"); print_usage_line(3, "-microarch:sandybridge"); print_usage_line(3, "-microarch:native"); - print_usage_line(3, "-microarch:? for a list"); + print_usage_line(3, "-microarch:\"?\" for a list"); + print_usage_line(0, ""); + + print_usage_line(1, "-target-features:"); + print_usage_line(2, "Specifies CPU features to enable on top of the enabled features implied by -microarch."); + print_usage_line(2, "Examples:"); + print_usage_line(3, "-target-features:atomics"); + print_usage_line(3, "-target-features:\"sse2,aes\""); + print_usage_line(3, "-target-features:\"?\" for a list"); + print_usage_line(0, ""); + + print_usage_line(1, "-strict-target-features"); + print_usage_line(2, "Makes @(enable_target_features=\"...\") behave the same way as @(require_target_features=\"...\")."); + print_usage_line(2, "This enforces that all generated code uses features supported by the combination of -target, -microarch, and -target-features."); print_usage_line(0, ""); print_usage_line(1, "-reloc-mode:"); @@ -2663,7 +2681,7 @@ int main(int arg_count, char const **arg_ptr) { // Check chosen microarchitecture. If not found or ?, print list. bool print_microarch_list = true; - if (build_context.microarch.len == 0) { + if (build_context.microarch.len == 0 || build_context.microarch == str_lit("native")) { // Autodetect, no need to print list. print_microarch_list = false; } else { @@ -2680,6 +2698,11 @@ int main(int arg_count, char const **arg_ptr) { } } + // Set and check build paths... + if (!init_build_paths(init_filename)) { + return 1; + } + String default_march = get_default_microarchitecture(); if (print_microarch_list) { if (build_context.microarch != "?") { @@ -2703,13 +2726,57 @@ int main(int arg_count, char const **arg_ptr) { return 0; } - // Set and check build paths... - if (!init_build_paths(init_filename)) { - return 1; + String march = get_final_microarchitecture(); + String default_features = get_default_features(); + { + String_Iterator it = {default_features, 0}; + for (;;) { + String str = string_split_iterator(&it, ','); + if (str == "") break; + string_set_add(&build_context.target_features_set, str); + } + } + + if (build_context.target_features_string.len != 0) { + String_Iterator target_it = {build_context.target_features_string, 0}; + for (;;) { + String item = string_split_iterator(&target_it, ','); + if (item == "") break; + + String invalid; + if (!check_target_feature_is_valid_for_target_arch(item, &invalid) && item != str_lit("help")) { + if (item != str_lit("?")) { + gb_printf_err("Unkown target feature '%.*s'.\n", LIT(invalid)); + } + gb_printf("Possible -target-features for target %.*s are:\n", LIT(target_arch_names[build_context.metrics.arch])); + gb_printf("\n"); + + String feature_list = target_features_list[build_context.metrics.arch]; + String_Iterator it = {feature_list, 0}; + for (;;) { + String str = string_split_iterator(&it, ','); + if (str == "") break; + if (check_single_target_feature_is_valid(default_features, str)) { + if (has_ansi_terminal_colours()) { + gb_printf("\t%.*s\x1b[38;5;244m (implied by target microarch %.*s)\x1b[0m\n", LIT(str), LIT(march)); + } else { + gb_printf("\t%.*s (implied by current microarch %.*s)\n", LIT(str), LIT(march)); + } + } else { + gb_printf("\t%.*s\n", LIT(str)); + } + } + + return 1; + } + + string_set_add(&build_context.target_features_set, item); + } } if (build_context.show_debug_messages) { - debugf("Selected microarch: %.*s\n", LIT(default_march)); + debugf("Selected microarch: %.*s\n", LIT(march)); + debugf("Default microarch features: %.*s\n", LIT(default_features)); for_array(i, build_context.build_paths) { String build_path = path_to_string(heap_allocator(), build_context.build_paths[i]); debugf("build_paths[%ld]: %.*s\n", i, LIT(build_path)); -- cgit v1.2.3 From bb58926b7a09b5b06b681d53e6d3e86e098f08e9 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Wed, 20 Mar 2024 00:38:02 +0100 Subject: llvm 18: general unix and darwin specifics --- build_odin.sh | 15 +- src/llvm_backend.cpp | 398 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/main.cpp | 7 +- 3 files changed, 401 insertions(+), 19 deletions(-) (limited to 'src/main.cpp') diff --git a/build_odin.sh b/build_odin.sh index 11ae830c7..328ac81bd 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -25,12 +25,14 @@ error() { if [ -z "$LLVM_CONFIG" ]; then # darwin, linux, openbsd - if [ -n "$(command -v llvm-config-17)" ]; then LLVM_CONFIG="llvm-config-17" + if [ -n "$(command -v llvm-config-18)" ]; then LLVM_CONFIG="llvm-config-18" + elif [ -n "$(command -v llvm-config-17)" ]; then LLVM_CONFIG="llvm-config-17" elif [ -n "$(command -v llvm-config-14)" ]; then LLVM_CONFIG="llvm-config-14" elif [ -n "$(command -v llvm-config-13)" ]; then LLVM_CONFIG="llvm-config-13" elif [ -n "$(command -v llvm-config-12)" ]; then LLVM_CONFIG="llvm-config-12" elif [ -n "$(command -v llvm-config-11)" ]; then LLVM_CONFIG="llvm-config-11" # freebsd + elif [ -n "$(command -v llvm-config18)" ]; then LLVM_CONFIG="llvm-config18" elif [ -n "$(command -v llvm-config17)" ]; then LLVM_CONFIG="llvm-config17" elif [ -n "$(command -v llvm-config14)" ]; then LLVM_CONFIG="llvm-config14" elif [ -n "$(command -v llvm-config13)" ]; then LLVM_CONFIG="llvm-config13" @@ -50,21 +52,20 @@ LLVM_VERSION_MAJOR="$(echo $LLVM_VERSION | awk -F. '{print $1}')" LLVM_VERSION_MINOR="$(echo $LLVM_VERSION | awk -F. '{print $2}')" LLVM_VERSION_PATCH="$(echo $LLVM_VERSION | awk -F. '{print $3}')" -if [ $LLVM_VERSION_MAJOR -lt 11 ] || - ([ $LLVM_VERSION_MAJOR -gt 14 ] && [ $LLVM_VERSION_MAJOR -lt 17 ]); then - error "Invalid LLVM version $LLVM_VERSION: must be 11, 12, 13, 14 or 17" +if [ $LLVM_VERSION_MAJOR -lt 11 ] || ([ $LLVM_VERSION_MAJOR -gt 14 ] && [ $LLVM_VERSION_MAJOR -lt 17 ]) || [ $LLVM_VERSION_MAJOR -gt 18 ]; then + error "Invalid LLVM version $LLVM_VERSION: must be 11, 12, 13, 14, 17 or 18" fi case "$OS_NAME" in Darwin) if [ "$OS_ARCH" = "arm64" ]; then - if [ $LLVM_VERSION_MAJOR -lt 13 ] || [ $LLVM_VERSION_MAJOR -gt 17 ]; then - error "Darwin Arm64 requires LLVM 13, 14 or 17" + if [ $LLVM_VERSION_MAJOR -lt 13 ]; then + error "Invalid LLVM version $LLVM_VERSION: Darwin Arm64 requires LLVM 13, 14, 17 or 18" fi fi CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" - LDFLAGS="$LDFLAGS -liconv -ldl -framework System -lLLVM" + LDFLAGS="$LDFLAGS -liconv -ldl -framework System -lLLVM -Wl,-rpath $($LLVM_CONFIG --libdir)" ;; FreeBSD) CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index fad130b99..be800a53f 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1508,6 +1508,7 @@ gb_internal WORKER_TASK_PROC(lb_llvm_module_pass_worker_proc) { case 1: // default // Passes removed: coro, openmp, sroa +#if LLVM_VERSION_MAJOR == 17 array_add(&passes, u8R"( annotation2metadata, forceattrs, @@ -1523,13 +1524,14 @@ globalopt, function( mem2reg, instcombine, - simplifycfg), - require, - function( - invalidate - ), - require, - cgscc( + simplifycfg +), +require, +function( + invalidate +), +require, +cgscc( devirt<4>( inline, inline, @@ -1630,10 +1632,138 @@ function( ), verify )"); +#else + array_add(&passes, u8R"( +annotation2metadata, +forceattrs, +inferattrs, +function( + lower-expect, + simplifycfg, + early-cse<> +), +ipsccp, +called-value-propagation, +globalopt, +function( + mem2reg, + instcombine, + simplifycfg +), +always-inline, +require, +function( + invalidate +), +require, +cgscc( + devirt<4>( + inline, + function-attrs, + function( + early-cse, + speculative-execution, + jump-threading, + correlated-propagation, + simplifycfg, + instcombine, + aggressive-instcombine, + tailcallelim, + simplifycfg, + reassociate, + constraint-elimination, + loop-mssa( + loop-instsimplify, + loop-simplifycfg, + licm, + loop-rotate, + licm, + simple-loop-unswitch + ), + simplifycfg, + instcombine, + loop( + loop-idiom, + indvars, + loop-deletion, + loop-unroll-full + ), + vector-combine, + mldst-motion, + gvn<>, + sccp, + bdce, + instcombine, + jump-threading, + correlated-propagation, + adce, + memcpyopt, + dse, + move-auto-init, + loop-mssa( + licm + ), + simplifycfg, + instcombine + ), + function-attrs, + function( + require + ) + ) +), +deadargelim, +globalopt, +globaldce, +elim-avail-extern, +rpo-function-attrs, +recompute-globalsaa, +function( + float2int, + lower-constant-intrinsics, + loop( + loop-rotate, + loop-deletion + ), + loop-distribute, + inject-tli-mappings, + loop-vectorize, + infer-alignment, + loop-load-elim, + instcombine, + simplifycfg, + slp-vectorizer, + vector-combine, + instcombine, + loop-unroll, + transform-warning, + infer-alignment, + instcombine, + loop-mssa( + licm + ), + alignment-from-assumptions, + loop-sink, + instsimplify, + div-rem-pairs, + tailcallelim, + simplifycfg +), +globaldce, +constmerge, +cg-profile, +rel-lookup-table-converter, +function( + annotation-remarks +), +verify +)"); +#endif break; // default // Passes removed: coro, openmp, sroa case 2: +#if LLVM_VERSION_MAJOR == 17 array_add(&passes, u8R"( annotation2metadata, forceattrs, @@ -1758,11 +1888,140 @@ function( ), verify )"); +#else + array_add(&passes, u8R"( +annotation2metadata, +forceattrs, +inferattrs, +function( + lower-expect, + simplifycfg, + early-cse<> +), +ipsccp, +called-value-propagation, +globalopt, +function( + mem2reg, + instcombine, + simplifycfg +), +always-inline, +require, +function( + invalidate +), +require, +cgscc( + devirt<4>( + inline, + function-attrs, + function( + early-cse, + speculative-execution, + jump-threading, + correlated-propagation, + simplifycfg, + instcombine, + aggressive-instcombine, + libcalls-shrinkwrap, + tailcallelim, + simplifycfg, + reassociate, + constraint-elimination, + loop-mssa( + loop-instsimplify, + loop-simplifycfg, + licm, + loop-rotate, + licm, + simple-loop-unswitch + ), + simplifycfg, + instcombine, + loop( + loop-idiom, + indvars, + loop-deletion, + loop-unroll-full + ), + vector-combine, + mldst-motion, + gvn<>, + sccp, + bdce, + instcombine, + jump-threading, + correlated-propagation, + adce, + memcpyopt, + dse, + move-auto-init, + loop-mssa( + licm + ), + simplifycfg, + instcombine + ), + function-attrs, + function( + require + ) + ) +), +deadargelim, +globalopt, +globaldce, +elim-avail-extern, +rpo-function-attrs, +recompute-globalsaa, +function( + float2int, + lower-constant-intrinsics, + loop( + loop-rotate, + loop-deletion + ), + loop-distribute, + inject-tli-mappings, + loop-vectorize, + infer-alignment, + loop-load-elim, + instcombine, + simplifycfg, + slp-vectorizer, + vector-combine, + instcombine, + loop-unroll, + transform-warning, + infer-alignment, + instcombine, + loop-mssa( + licm + ), + alignment-from-assumptions, + loop-sink, + instsimplify, + div-rem-pairs, + tailcallelim, + simplifycfg +), +globaldce, +constmerge, +cg-profile, +rel-lookup-table-converter, +function( + annotation-remarks +), +verify +)"); +#endif break; case 3: // default // Passes removed: coro, openmp, sroa +#if LLVM_VERSION_MAJOR == 17 array_add(&passes, u8R"( annotation2metadata, forceattrs, @@ -1890,6 +2149,131 @@ function( ), verify )"); +#else + array_add(&passes, u8R"( +annotation2metadata, +forceattrs, +inferattrs, +function( + lower-expect, + simplifycfg, + early-cse<>, + callsite-splitting +), +ipsccp, +called-value-propagation, +globalopt, +function( + mem2reg, + instcombine, + simplifycfg +), +always-inline, +require, +function(invalidate), +require, +cgscc( + devirt<4>( + inline, + function-attrs, + argpromotion, + function( + early-cse, + speculative-execution, + jump-threading, + correlated-propagation, + simplifycfg, + instcombine, + aggressive-instcombine, + libcalls-shrinkwrap, + tailcallelim, + simplifycfg, + reassociate, + constraint-elimination, + loop-mssa( + loop-instsimplify, + loop-simplifycfg, + licm, + loop-rotate, + licm, + simple-loop-unswitch + ), + simplifycfg, + instcombine, + loop( + loop-idiom, + indvars, + loop-deletion, + loop-unroll-full + ), + vector-combine, + mldst-motion, + gvn<>, + sccp, + bdce, + instcombine, + jump-threading, + correlated-propagation, + adce, + memcpyopt, + dse, + move-auto-init, + loop-mssa(licm), + simplifycfg, + instcombine + ), + function-attrs, + function( + require + ) + ) +), +deadargelim, +globalopt, +globaldce, +elim-avail-extern, +rpo-function-attrs, +recompute-globalsaa, +function( + float2int, + lower-constant-intrinsics, + chr, + loop( + loop-rotate, + loop-deletion + ), + loop-distribute, + inject-tli-mappings, + loop-vectorize, + infer-alignment, + loop-load-elim, + instcombine, + simplifycfg, + slp-vectorizer, + vector-combine, + instcombine, + loop-unroll, + transform-warning, + infer-alignment, + instcombine, + loop-mssa(licm), + alignment-from-assumptions, + loop-sink, + instsimplify, + div-rem-pairs, + tailcallelim, + simplifycfg +), +globaldce, +constmerge, +cg-profile, +rel-lookup-table-converter, +function( + annotation-remarks +), +verify +)"); +#endif break; } diff --git a/src/main.cpp b/src/main.cpp index 93685acb9..e76b0e380 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -86,11 +86,8 @@ gb_global Timings global_timings = {0}; #if defined(GB_SYSTEM_OSX) #include - #if LLVM_VERSION_MAJOR < 11 - #error LLVM Version 11+ is required => "brew install llvm@11" - #endif - #if (LLVM_VERSION_MAJOR > 14 && LLVM_VERSION_MAJOR < 17) || LLVM_VERSION_MAJOR > 17 - #error LLVM Version 11..=14 or =17 is required => "brew install llvm@14" + #if LLVM_VERSION_MAJOR < 11 || (LLVM_VERSION_MAJOR > 14 && LLVM_VERSION_MAJOR < 17) || LLVM_VERSION_MAJOR > 18 + #error LLVM Version 11..=14 or =18 is required => "brew install llvm@14" #endif #endif -- cgit v1.2.3 From e71cd871c45d99ce6f593b44002dc0e3ad57593b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 16 May 2024 14:27:05 +0100 Subject: Reimplement `-build-mode:static`/`-build-mode:lib` --- src/build_settings.cpp | 8 +++++++- src/checker.cpp | 1 + src/linker.cpp | 31 ++++++++++++++++++++++++------- src/main.cpp | 10 ++++++++++ 4 files changed, 42 insertions(+), 8 deletions(-) (limited to 'src/main.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 7eb198185..f4e957479 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -646,6 +646,7 @@ struct QueryDataSetSettings { enum BuildModeKind { BuildMode_Executable, BuildMode_DynamicLibrary, + BuildMode_StaticLibrary, BuildMode_Object, BuildMode_Assembly, BuildMode_LLVM_IR, @@ -2284,7 +2285,12 @@ gb_internal bool init_build_paths(String init_filename) { } else if (build_context.metrics.os == TargetOs_darwin) { output_extension = STR_LIT("dylib"); } - } else if (build_context.build_mode == BuildMode_Object) { + } else if (build_context.build_mode == BuildMode_StaticLibrary) { + output_extension = STR_LIT("a"); + if (build_context.metrics.os == TargetOs_windows) { + output_extension = STR_LIT("lib"); + } + }else if (build_context.build_mode == BuildMode_Object) { // By default use a .o object extension. output_extension = STR_LIT("o"); diff --git a/src/checker.cpp b/src/checker.cpp index 12c8f5291..7cda0aa42 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1044,6 +1044,7 @@ gb_internal void init_universal(void) { GlobalEnumValue values[BuildMode_COUNT] = { {"Executable", BuildMode_Executable}, {"Dynamic", BuildMode_DynamicLibrary}, + {"Static", BuildMode_StaticLibrary}, {"Object", BuildMode_Object}, {"Assembly", BuildMode_Assembly}, {"LLVM_IR", BuildMode_LLVM_IR}, diff --git a/src/linker.cpp b/src/linker.cpp index 33ca70462..c41f10593 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -212,10 +212,12 @@ gb_internal i32 linker_stage(LinkerData *gen) { link_settings = gb_string_append_fmt(link_settings, " /PDB:\"%.*s\"", LIT(pdb_path)); } - if (build_context.no_crt) { - link_settings = gb_string_append_fmt(link_settings, " /nodefaultlib"); - } else { - link_settings = gb_string_append_fmt(link_settings, " /defaultlib:libcmt"); + if (build_context.build_mode != BuildMode_StaticLibrary) { + if (build_context.no_crt) { + link_settings = gb_string_append_fmt(link_settings, " /nodefaultlib"); + } else { + link_settings = gb_string_append_fmt(link_settings, " /defaultlib:libcmt"); + } } if (build_context.ODIN_DEBUG) { @@ -257,20 +259,31 @@ gb_internal i32 linker_stage(LinkerData *gen) { } } + String linker_name = str_lit("link.exe"); switch (build_context.build_mode) { case BuildMode_Executable: link_settings = gb_string_append_fmt(link_settings, " /NOIMPLIB /NOEXP"); break; } + switch (build_context.build_mode) { + case BuildMode_StaticLibrary: + linker_name = str_lit("lib.exe"); + break; + default: + link_settings = gb_string_append_fmt(link_settings, " /incremental:no /opt:ref"); + 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 -OUT:\"%.*s\" %s " + "/nologo /subsystem:%.*s " "%.*s " "%.*s " "%s " "", - LIT(vs_exe_path), object_files, LIT(res_path), LIT(output_filename), + LIT(vs_exe_path), LIT(linker_name), object_files, LIT(res_path), LIT(output_filename), link_settings, LIT(build_context.ODIN_WINDOWS_SUBSYSTEM), LIT(build_context.link_flags), @@ -458,6 +471,10 @@ gb_internal i32 linker_stage(LinkerData *gen) { link_settings = gb_string_append_fmt(link_settings, "-nostdlib "); } + if (build_context.build_mode == BuildMode_StaticLibrary) { + compiler_error("TODO(bill): -build-mode:static on non-windows targets"); + } + // NOTE(dweiler): We use clang as a frontend for the linker as there are // other runtime and compiler support libraries that need to be linked in // very specific orders such as libgcc_s, ld-linux-so, unwind, etc. diff --git a/src/main.cpp b/src/main.cpp index e76b0e380..4df6f97d5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -989,6 +989,8 @@ gb_internal bool parse_build_flags(Array args) { build_context.build_mode = BuildMode_DynamicLibrary; } else if (str == "obj" || str == "object") { build_context.build_mode = BuildMode_Object; + } else if (str == "static" || str == "lib") { + build_context.build_mode = BuildMode_StaticLibrary; } else if (str == "exe") { build_context.build_mode = BuildMode_Executable; } else if (str == "asm" || str == "assembly" || str == "assembler") { @@ -999,6 +1001,7 @@ gb_internal bool parse_build_flags(Array args) { gb_printf_err("Unknown build mode '%.*s'\n", LIT(str)); gb_printf_err("Valid build modes:\n"); gb_printf_err("\tdll, shared, dynamic\n"); + gb_printf_err("\tlib, static\n"); gb_printf_err("\tobj, object\n"); gb_printf_err("\texe\n"); gb_printf_err("\tasm, assembly, assembler\n"); @@ -1637,6 +1640,7 @@ gb_internal void remove_temp_files(lbGenerator *gen) { switch (build_context.build_mode) { case BuildMode_Executable: + case BuildMode_StaticLibrary: case BuildMode_DynamicLibrary: break; @@ -1655,6 +1659,7 @@ gb_internal void remove_temp_files(lbGenerator *gen) { if (!build_context.keep_object_files) { switch (build_context.build_mode) { case BuildMode_Executable: + case BuildMode_StaticLibrary: case BuildMode_DynamicLibrary: for (String const &path : gen->output_object_paths) { gb_file_remove(cast(char const *)path.text); @@ -1833,6 +1838,9 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(3, "-build-mode:exe Builds as an executable."); print_usage_line(3, "-build-mode:dll Builds as a dynamically linked library."); print_usage_line(3, "-build-mode:shared Builds as a dynamically linked library."); + print_usage_line(3, "-build-mode:lib Builds as a statically linked library."); + print_usage_line(3, "-build-mode:static Builds as a statically linked library."); + print_usage_line(3, "-build-mode:lib Builds as an static library."); print_usage_line(3, "-build-mode:obj Builds as an object file."); print_usage_line(3, "-build-mode:object Builds as an object file."); print_usage_line(3, "-build-mode:assembly Builds as an assembly file."); @@ -2866,6 +2874,7 @@ int main(int arg_count, char const **arg_ptr) { switch (build_context.build_mode) { case BuildMode_Executable: + case BuildMode_StaticLibrary: case BuildMode_DynamicLibrary: i32 result = linker_stage(&linker_data); if (result) { @@ -2887,6 +2896,7 @@ int main(int arg_count, char const **arg_ptr) { if (lb_generate_code(gen)) { switch (build_context.build_mode) { case BuildMode_Executable: + case BuildMode_StaticLibrary: case BuildMode_DynamicLibrary: i32 result = linker_stage(gen); if (result) { -- cgit v1.2.3 From 7934e92d14de6166791e1483f986eb97fe06f595 Mon Sep 17 00:00:00 2001 From: tim4242 Date: Fri, 24 May 2024 01:04:41 +0200 Subject: Initial dependency file generation --- src/build_settings.cpp | 1 + src/main.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 49 insertions(+), 4 deletions(-) (limited to 'src/main.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index d9454ba9b..400e478fe 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -831,6 +831,7 @@ struct BuildContext { bool show_timings; TimingsExportFormat export_timings_format; String export_timings_file; + String export_dependencies_file; bool show_unused; bool show_unused_with_location; bool show_more_timings; diff --git a/src/main.cpp b/src/main.cpp index 4df6f97d5..d21eb21cb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -234,6 +234,7 @@ enum BuildFlagKind { BuildFlag_ShowMoreTimings, BuildFlag_ExportTimings, BuildFlag_ExportTimingsFile, + BuildFlag_ExportDependencies, BuildFlag_ShowSystemCalls, BuildFlag_ThreadCount, BuildFlag_KeepTempFiles, @@ -320,7 +321,6 @@ enum BuildFlagKind { BuildFlag_Subsystem, #endif - BuildFlag_COUNT, }; @@ -427,6 +427,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_ShowMoreTimings, str_lit("show-more-timings"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_ExportTimings, str_lit("export-timings"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_ExportTimingsFile, str_lit("export-timings-file"), BuildFlagParam_String, Command__does_check); + add_flag(&build_flags, BuildFlag_ExportDependencies, str_lit("export-dependencies"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_ShowUnused, str_lit("show-unused"), BuildFlagParam_None, Command_check); add_flag(&build_flags, BuildFlag_ShowUnusedWithLocation, str_lit("show-unused-with-location"), BuildFlagParam_None, Command_check); add_flag(&build_flags, BuildFlag_ShowSystemCalls, str_lit("show-system-calls"), BuildFlagParam_None, Command_all); @@ -753,6 +754,19 @@ gb_internal bool parse_build_flags(Array args) { break; } + case BuildFlag_ExportDependencies: { + GB_ASSERT(value.kind == ExactValue_String); + + String export_path = string_trim_whitespace(value.value_string); + if (is_build_flag_path_valid(export_path)) { + build_context.export_dependencies_file = path_to_full_path(heap_allocator(), export_path); + } else { + gb_printf_err("Invalid -export-dependencies path, got %.*s\n", LIT(export_path)); + bad_flags = true; + } + + break; + } case BuildFlag_ShowSystemCalls: { GB_ASSERT(value.kind == ExactValue_Invalid); build_context.show_system_calls = true; @@ -1790,6 +1804,11 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(2, "Example: -export-timings-file:timings.json"); print_usage_line(0, ""); + print_usage_line(1, "-export-dependencies:"); + print_usage_line(2, "Exports all source files used to create the output file in Make format."); + print_usage_line(2, "Example: -export-dependencies:odin.d"); + print_usage_line(0, ""); + print_usage_line(1, "-thread-count:"); print_usage_line(2, "Overrides the number of threads the compiler will use to compile with."); print_usage_line(2, "Example: -thread-count:2"); @@ -2916,10 +2935,35 @@ int main(int arg_count, char const **arg_ptr) { show_timings(checker, &global_timings); } - if (run_output) { - String exe_name = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Output]); - defer (gb_free(heap_allocator(), exe_name.text)); + String exe_name = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Output]); + defer (gb_free(heap_allocator(), exe_name.text)); + if (build_context.export_dependencies_file.len > 0) { + gbFile f = {}; + char * fileName = (char *)build_context.export_dependencies_file.text; + gbFileError err = gb_file_open_mode(&f, gbFileMode_Write, fileName); + if (err != gbFileError_None) { + gb_printf_err("Failed to export dependencies to: %s\n", fileName); + exit_with_errors(); + return 1; + } + defer (gb_file_close(&f)); + + gb_fprintf(&f, "%.*s:", LIT(exe_name)); + + for (isize i = parser->packages.count-1; i >= 0; i--) { + AstPackage *pkg = parser->packages[i]; + for (isize j = pkg->files.count-1; j >= 0; j--) { + AstFile *file = pkg->files[j]; + + gb_fprintf(&f, " \\\n %.*s", LIT(file->fullpath)); + } + } + + gb_fprintf(&f, "\n"); + } + + if (run_output) { return system_exec_command_line_app("odin run", "\"%.*s\" %.*s", LIT(exe_name), LIT(run_args_string)); } return 0; -- cgit v1.2.3 From 8664b88c8fe282aaabed6c3522802b63e39bcf02 Mon Sep 17 00:00:00 2001 From: tim4242 Date: Fri, 24 May 2024 01:20:45 +0200 Subject: Improved depdendency formatting to support paths containing spaces --- src/main.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index d21eb21cb..575745290 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2951,12 +2951,31 @@ int main(int arg_count, char const **arg_ptr) { gb_fprintf(&f, "%.*s:", LIT(exe_name)); + isize current_line_length = exe_name.len + 1; + for (isize i = parser->packages.count-1; i >= 0; i--) { AstPackage *pkg = parser->packages[i]; for (isize j = pkg->files.count-1; j >= 0; j--) { AstFile *file = pkg->files[j]; - gb_fprintf(&f, " \\\n %.*s", LIT(file->fullpath)); + /* Arbitrary line break value. Maybe make this better? */ + if (current_line_length >= 80-2) { + gb_file_write(&f, " \\\n ", 4); + current_line_length = 1; + } + + gb_file_write(&f, " ", 1); + current_line_length++; + + for (isize k = 0; k < file->fullpath.len; k++) { + char part = file->fullpath.text[k]; + if (part == ' ') { + gb_file_write(&f, "\\", 1); + current_line_length++; + } + gb_file_write(&f, &part, 1); + current_line_length++; + } } } -- cgit v1.2.3 From 0cba33075ff6d2b5059e8f6c6d2f5a7c92f02edf Mon Sep 17 00:00:00 2001 From: tim4242 Date: Fri, 24 May 2024 13:44:38 +0200 Subject: Add the option to export dependencies as JSON. --- src/build_settings.cpp | 7 +++ src/main.cpp | 164 ++++++++++++++++++++++++++++++++++--------------- 2 files changed, 120 insertions(+), 51 deletions(-) (limited to 'src/main.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 400e478fe..3bf168177 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -694,6 +694,12 @@ enum TimingsExportFormat : i32 { TimingsExportCSV = 2, }; +enum DependenciesExportFormat : i32 { + DependenciesExportUnspecified = 0, + DependenciesExportMake = 1, + DependenciesExportJson = 2, +}; + enum ErrorPosStyle { ErrorPosStyle_Default, // path(line:column) msg ErrorPosStyle_Unix, // path:line:column: msg @@ -831,6 +837,7 @@ struct BuildContext { bool show_timings; TimingsExportFormat export_timings_format; String export_timings_file; + DependenciesExportFormat export_dependencies_format; String export_dependencies_file; bool show_unused; bool show_unused_with_location; diff --git a/src/main.cpp b/src/main.cpp index 575745290..bceee83da 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -235,6 +235,7 @@ enum BuildFlagKind { BuildFlag_ExportTimings, BuildFlag_ExportTimingsFile, BuildFlag_ExportDependencies, + BuildFlag_ExportDependenciesFile, BuildFlag_ShowSystemCalls, BuildFlag_ThreadCount, BuildFlag_KeepTempFiles, @@ -427,7 +428,8 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_ShowMoreTimings, str_lit("show-more-timings"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_ExportTimings, str_lit("export-timings"), BuildFlagParam_String, Command__does_check); add_flag(&build_flags, BuildFlag_ExportTimingsFile, str_lit("export-timings-file"), BuildFlagParam_String, Command__does_check); - add_flag(&build_flags, BuildFlag_ExportDependencies, str_lit("export-dependencies"), BuildFlagParam_String, Command__does_check); + add_flag(&build_flags, BuildFlag_ExportDependencies, str_lit("export-dependencies"), BuildFlagParam_String, Command__does_build); + add_flag(&build_flags, BuildFlag_ExportDependenciesFile, str_lit("export-dependencies-file"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_ShowUnused, str_lit("show-unused"), BuildFlagParam_None, Command_check); add_flag(&build_flags, BuildFlag_ShowUnusedWithLocation, str_lit("show-unused-with-location"), BuildFlagParam_None, Command_check); add_flag(&build_flags, BuildFlag_ShowSystemCalls, str_lit("show-system-calls"), BuildFlagParam_None, Command_all); @@ -757,6 +759,23 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_ExportDependencies: { GB_ASSERT(value.kind == ExactValue_String); + if (value.value_string == "make") { + build_context.export_dependencies_format = DependenciesExportMake; + } else if (value.value_string == "json") { + build_context.export_dependencies_format = DependenciesExportJson; + } else { + gb_printf_err("Invalid export format for -export-dependencies:, got %.*s\n", LIT(value.value_string)); + gb_printf_err("Valid export formats:\n"); + gb_printf_err("\tmake\n"); + gb_printf_err("\tjson\n"); + bad_flags = true; + } + + break; + } + case BuildFlag_ExportDependenciesFile: { + GB_ASSERT(value.kind == ExactValue_String); + String export_path = string_trim_whitespace(value.value_string); if (is_build_flag_path_valid(export_path)) { build_context.export_dependencies_file = path_to_full_path(heap_allocator(), export_path); @@ -764,8 +783,8 @@ gb_internal bool parse_build_flags(Array args) { gb_printf_err("Invalid -export-dependencies path, got %.*s\n", LIT(export_path)); bad_flags = true; } - - break; + + break; } case BuildFlag_ShowSystemCalls: { GB_ASSERT(value.kind == ExactValue_Invalid); @@ -1649,6 +1668,74 @@ gb_internal void show_timings(Checker *c, Timings *t) { } } +gb_internal void export_dependencies(Parser *p) { + GB_ASSERT(build_context.export_dependencies_format != DependenciesExportUnspecified); + + if (build_context.export_dependencies_file.len <= 0) { + gb_printf_err("No dependency file specified with `-export-dependencies-file`\n"); + exit_with_errors(); + return; + } + + gbFile f = {}; + char * fileName = (char *)build_context.export_dependencies_file.text; + gbFileError err = gb_file_open_mode(&f, gbFileMode_Write, fileName); + if (err != gbFileError_None) { + gb_printf_err("Failed to export dependencies to: %s\n", fileName); + exit_with_errors(); + return; + } + defer (gb_file_close(&f)); + + if (build_context.export_dependencies_format == DependenciesExportMake) { + String exe_name = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Output]); + defer (gb_free(heap_allocator(), exe_name.text)); + + gb_fprintf(&f, "%.*s:", LIT(exe_name)); + + isize current_line_length = exe_name.len + 1; + + for(AstPackage *pkg : p->packages) { + for(AstFile *file : pkg->files) { + /* Arbitrary line break value. Maybe make this better? */ + if (current_line_length >= 80-2) { + gb_file_write(&f, " \\\n ", 4); + current_line_length = 1; + } + + gb_file_write(&f, " ", 1); + current_line_length++; + + for (isize k = 0; k < file->fullpath.len; k++) { + char part = file->fullpath.text[k]; + if (part == ' ') { + gb_file_write(&f, "\\", 1); + current_line_length++; + } + gb_file_write(&f, &part, 1); + current_line_length++; + } + } + } + + gb_fprintf(&f, "\n"); + } else if (build_context.export_dependencies_format == DependenciesExportJson) { + gb_fprintf(&f, "{\n"); + + gb_fprintf(&f, "\t\"source_files\": [\n"); + + for(AstPackage *pkg : p->packages) { + for(AstFile *file : pkg->files) { + gb_fprintf(&f, "\t\t\"%.*s\",\n", LIT(file->fullpath)); + } + } + + gb_fprintf(&f, "\t],\n"); + + gb_fprintf(&f, "}\n"); + } +} + gb_internal void remove_temp_files(lbGenerator *gen) { if (build_context.keep_temp_files) return; @@ -1804,9 +1891,16 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(2, "Example: -export-timings-file:timings.json"); print_usage_line(0, ""); - print_usage_line(1, "-export-dependencies:"); - print_usage_line(2, "Exports all source files used to create the output file in Make format."); - print_usage_line(2, "Example: -export-dependencies:odin.d"); + print_usage_line(1, "-export-dependencies:"); + print_usage_line(2, "Exports dependencies to one of a few formats. Requires `-export-dependencies-file`."); + print_usage_line(2, "Available options:"); + print_usage_line(3, "-export-dependencies:make Exports in Makefile format"); + print_usage_line(3, "-export-dependencies:json Exports in JSON format"); + print_usage_line(0, ""); + + print_usage_line(1, "-export-dependencies-file:"); + print_usage_line(2, "Specifies the filename for `-export-dependencies`."); + print_usage_line(2, "Example: -export-dependencies-file:dependencies.d"); print_usage_line(0, ""); print_usage_line(1, "-thread-count:"); @@ -2900,6 +2994,10 @@ int main(int arg_count, char const **arg_ptr) { if (build_context.show_timings) { show_timings(checker, &global_timings); } + + if (build_context.export_dependencies_format != DependenciesExportUnspecified) { + export_dependencies(parser); + } return result; } break; @@ -2922,6 +3020,10 @@ int main(int arg_count, char const **arg_ptr) { if (build_context.show_timings) { show_timings(checker, &global_timings); } + + if (build_context.export_dependencies_format != DependenciesExportUnspecified) { + export_dependencies(parser); + } return result; } break; @@ -2935,54 +3037,14 @@ int main(int arg_count, char const **arg_ptr) { show_timings(checker, &global_timings); } - String exe_name = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Output]); - defer (gb_free(heap_allocator(), exe_name.text)); - - if (build_context.export_dependencies_file.len > 0) { - gbFile f = {}; - char * fileName = (char *)build_context.export_dependencies_file.text; - gbFileError err = gb_file_open_mode(&f, gbFileMode_Write, fileName); - if (err != gbFileError_None) { - gb_printf_err("Failed to export dependencies to: %s\n", fileName); - exit_with_errors(); - return 1; - } - defer (gb_file_close(&f)); - - gb_fprintf(&f, "%.*s:", LIT(exe_name)); - - isize current_line_length = exe_name.len + 1; - - for (isize i = parser->packages.count-1; i >= 0; i--) { - AstPackage *pkg = parser->packages[i]; - for (isize j = pkg->files.count-1; j >= 0; j--) { - AstFile *file = pkg->files[j]; - - /* Arbitrary line break value. Maybe make this better? */ - if (current_line_length >= 80-2) { - gb_file_write(&f, " \\\n ", 4); - current_line_length = 1; - } - - gb_file_write(&f, " ", 1); - current_line_length++; - - for (isize k = 0; k < file->fullpath.len; k++) { - char part = file->fullpath.text[k]; - if (part == ' ') { - gb_file_write(&f, "\\", 1); - current_line_length++; - } - gb_file_write(&f, &part, 1); - current_line_length++; - } - } - } - - gb_fprintf(&f, "\n"); + if (build_context.export_dependencies_format != DependenciesExportUnspecified) { + export_dependencies(parser); } if (run_output) { + String exe_name = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Output]); + defer (gb_free(heap_allocator(), exe_name.text)); + return system_exec_command_line_app("odin run", "\"%.*s\" %.*s", LIT(exe_name), LIT(run_args_string)); } return 0; -- cgit v1.2.3 From cb8faf5b74cd0863e226908d2bebd4829b71cbc8 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Sat, 1 Jun 2024 07:04:20 -0400 Subject: Remove `-test-name` in favor of test runner option `-define:ODIN_TEST_NAMES=...` is capable of selecting test by package and name or name only, with the ability to access packages included by `-all-packages`. --- src/build_settings.cpp | 1 - src/checker.cpp | 29 ----------------------------- src/main.cpp | 24 ------------------------ 3 files changed, 54 deletions(-) (limited to 'src/main.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 376e56a8e..7bdec376b 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -893,7 +893,6 @@ struct BuildContext { u32 cmd_doc_flags; Array extra_packages; - StringSet test_names; bool test_all_packages; gbAffinity affinity; diff --git a/src/checker.cpp b/src/checker.cpp index 2fd274975..97e685d33 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -5852,35 +5852,6 @@ gb_internal void remove_neighbouring_duplicate_entires_from_sorted_array(Arrayinfo.testing_procedures, init_procedures_cmp); remove_neighbouring_duplicate_entires_from_sorted_array(&c->info.testing_procedures); - - if (build_context.test_names.entries.count == 0) { - return; - } - - AstPackage *pkg = c->info.init_package; - Scope *s = pkg->scope; - - for (String const &name : build_context.test_names) { - Entity *e = scope_lookup(s, name); - if (e == nullptr) { - Token tok = {}; - if (pkg->files.count != 0) { - tok = pkg->files[0]->tokens[0]; - } - error(tok, "Unable to find the test '%.*s' in 'package %.*s' ", LIT(name), LIT(pkg->name)); - } - } - - for (isize i = 0; i < c->info.testing_procedures.count; /**/) { - Entity *e = c->info.testing_procedures[i]; - String name = e->token.string; - if (!string_set_exists(&build_context.test_names, name)) { - array_ordered_remove(&c->info.testing_procedures, i); - } else { - i += 1; - } - } - } diff --git a/src/main.cpp b/src/main.cpp index 4df6f97d5..e7f076c7c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -276,8 +276,6 @@ enum BuildFlagKind { BuildFlag_RelocMode, BuildFlag_DisableRedZone, - BuildFlag_TestName, - BuildFlag_DisallowDo, BuildFlag_DefaultToNilAllocator, BuildFlag_DefaultToPanicAllocator, @@ -471,8 +469,6 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_RelocMode, str_lit("reloc-mode"), BuildFlagParam_String, Command__does_build); add_flag(&build_flags, BuildFlag_DisableRedZone, str_lit("disable-red-zone"), BuildFlagParam_None, Command__does_build); - add_flag(&build_flags, BuildFlag_TestName, str_lit("test-name"), BuildFlagParam_String, Command_test); - 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_DefaultToPanicAllocator, str_lit("default-to-panic-allocator"),BuildFlagParam_None, Command__does_check); @@ -1119,21 +1115,6 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_DisableRedZone: build_context.disable_red_zone = true; break; - case BuildFlag_TestName: { - GB_ASSERT(value.kind == ExactValue_String); - { - String name = value.value_string; - if (!string_is_valid_identifier(name)) { - gb_printf_err("Test name '%.*s' must be a valid identifier\n", LIT(name)); - bad_flags = true; - break; - } - string_set_add(&build_context.test_names, name); - - // NOTE(bill): Allow for multiple -test-name - continue; - } - } case BuildFlag_DisallowDo: build_context.disallow_do = true; break; @@ -1962,10 +1943,6 @@ gb_internal void print_show_help(String const arg0, String const &command) { } if (test_only) { - print_usage_line(1, "-test-name:"); - print_usage_line(2, "Runs specific test only by name."); - print_usage_line(0, ""); - print_usage_line(1, "-all-packages"); print_usage_line(2, "Tests all packages imported into the given initial package."); print_usage_line(0, ""); @@ -2489,7 +2466,6 @@ int main(int arg_count, char const **arg_ptr) { TIME_SECTION("init args"); map_init(&build_context.defined_values); build_context.extra_packages.allocator = heap_allocator(); - string_set_init(&build_context.test_names); Array args = setup_args(arg_count, arg_ptr); -- cgit v1.2.3 From f030603f0dc9c487221a8f65f5a1ccb7b345a237 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Sun, 2 Jun 2024 16:47:46 -0400 Subject: Fix #3660 This also prevents a segfault if you do `odin build .odin -file` --- src/main.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 4df6f97d5..80fc995cf 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2657,6 +2657,10 @@ int main(int arg_count, char const **arg_ptr) { gb_printf_err("Expected either a directory or a .odin file, got '%.*s'\n", LIT(init_filename)); return 1; } + if (!gb_file_exists(cast(const char*)init_filename.text)) { + gb_printf_err("The file '%.*s' was not found.\n", LIT(init_filename)); + return 1; + } } } } -- cgit v1.2.3 From 8455e159f5f6c6b1a3553d82ea891232fd56d336 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Wed, 5 Jun 2024 20:57:39 +0200 Subject: improve orca target --- base/runtime/core.odin | 15 ++++++++-- base/runtime/default_allocators_general.odin | 2 +- base/runtime/entry_wasm.odin | 36 ++++++++++++++++------- base/runtime/error_checks.odin | 4 +++ base/runtime/heap_allocator_orca.odin | 29 +++++++++++++++++++ base/runtime/heap_allocator_other.odin | 2 +- base/runtime/os_specific_orca.odin | 43 ++++++++++++++++++++++++++++ base/runtime/procs.odin | 2 +- core/fmt/fmt_os.odin | 1 + core/time/time_orca.odin | 24 ++++++++++++++++ src/build_settings.cpp | 9 +++--- src/linker.cpp | 36 ++++++++++++++++------- src/main.cpp | 28 ++++++++++++++++++ 13 files changed, 200 insertions(+), 31 deletions(-) create mode 100644 base/runtime/heap_allocator_orca.odin create mode 100644 base/runtime/os_specific_orca.odin create mode 100644 core/time/time_orca.odin (limited to 'src/main.cpp') diff --git a/base/runtime/core.odin b/base/runtime/core.odin index 47b9a690c..3e24060af 100644 --- a/base/runtime/core.odin +++ b/base/runtime/core.odin @@ -701,7 +701,7 @@ default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code when ODIN_OS == .Freestanding { // Do nothing } else { - when !ODIN_DISABLE_ASSERT { + when ODIN_OS != .Orca && !ODIN_DISABLE_ASSERT { print_caller_location(loc) print_string(" ") } @@ -710,7 +710,18 @@ default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code print_string(": ") print_string(message) } - print_byte('\n') + + when ODIN_OS == .Orca { + assert_fail( + cstring(raw_data(loc.file_path)), + cstring(raw_data(loc.procedure)), + loc.line, + "", + cstring(raw_data(orca_stderr_buffer[:orca_stderr_buffer_idx])), + ) + } else { + print_byte('\n') + } } trap() } diff --git a/base/runtime/default_allocators_general.odin b/base/runtime/default_allocators_general.odin index ab4dd1db8..64af6c904 100644 --- a/base/runtime/default_allocators_general.odin +++ b/base/runtime/default_allocators_general.odin @@ -6,7 +6,7 @@ when ODIN_DEFAULT_TO_NIL_ALLOCATOR { } else when ODIN_DEFAULT_TO_PANIC_ALLOCATOR { default_allocator_proc :: panic_allocator_proc default_allocator :: panic_allocator -} else when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 { +} else when ODIN_OS != .Orca && (ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32) { default_allocator :: default_wasm_allocator default_allocator_proc :: wasm_allocator_proc } else { diff --git a/base/runtime/entry_wasm.odin b/base/runtime/entry_wasm.odin index c608942ba..a24c6f4b7 100644 --- a/base/runtime/entry_wasm.odin +++ b/base/runtime/entry_wasm.odin @@ -6,15 +6,29 @@ package runtime import "base:intrinsics" when !ODIN_TEST && !ODIN_NO_ENTRY_POINT { - @(link_name="_start", linkage="strong", require, export) - _start :: proc "c" () { - context = default_context() - #force_no_inline _startup_runtime() - intrinsics.__entry_point() + when ODIN_OS == .Orca { + @(linkage="strong", require, export) + oc_on_init :: proc "c" () { + context = default_context() + #force_no_inline _startup_runtime() + intrinsics.__entry_point() + } + @(linkage="strong", require, export) + oc_on_terminate :: proc "c" () { + context = default_context() + #force_no_inline _cleanup_runtime() + } + } else { + @(link_name="_start", linkage="strong", require, export) + _start :: proc "c" () { + context = default_context() + #force_no_inline _startup_runtime() + intrinsics.__entry_point() + } + @(link_name="_end", linkage="strong", require, export) + _end :: proc "c" () { + context = default_context() + #force_no_inline _cleanup_runtime() + } } - @(link_name="_end", linkage="strong", require, export) - _end :: proc "c" () { - context = default_context() - #force_no_inline _cleanup_runtime() - } -} \ No newline at end of file +} diff --git a/base/runtime/error_checks.odin b/base/runtime/error_checks.odin index 742e06a71..32a895c3f 100644 --- a/base/runtime/error_checks.odin +++ b/base/runtime/error_checks.odin @@ -4,6 +4,8 @@ package runtime bounds_trap :: proc "contextless" () -> ! { when ODIN_OS == .Windows { windows_trap_array_bounds() + } else when ODIN_OS == .Orca { + abort_ext("", "", 0, "bounds trap") } else { trap() } @@ -13,6 +15,8 @@ bounds_trap :: proc "contextless" () -> ! { type_assertion_trap :: proc "contextless" () -> ! { when ODIN_OS == .Windows { windows_trap_type_assertion() + } else when ODIN_OS == .Orca { + abort_ext("", "", 0, "type assertion trap") } else { trap() } diff --git a/base/runtime/heap_allocator_orca.odin b/base/runtime/heap_allocator_orca.odin new file mode 100644 index 000000000..c22a67ca1 --- /dev/null +++ b/base/runtime/heap_allocator_orca.odin @@ -0,0 +1,29 @@ +//+build orca +//+private +package runtime + +foreign { + @(link_name="malloc") _orca_malloc :: proc "c" (size: int) -> rawptr --- + @(link_name="calloc") _orca_calloc :: proc "c" (num, size: int) -> rawptr --- + @(link_name="free") _orca_free :: proc "c" (ptr: rawptr) --- + @(link_name="realloc") _orca_realloc :: proc "c" (ptr: rawptr, size: int) -> rawptr --- +} + +_heap_alloc :: proc(size: int, zero_memory := true) -> rawptr { + if size <= 0 { + return nil + } + if zero_memory { + return _orca_calloc(1, size) + } else { + return _orca_malloc(size) + } +} + +_heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr { + return _orca_realloc(ptr, new_size) +} + +_heap_free :: proc(ptr: rawptr) { + _orca_free(ptr) +} diff --git a/base/runtime/heap_allocator_other.odin b/base/runtime/heap_allocator_other.odin index 45049c7e9..74536ada9 100644 --- a/base/runtime/heap_allocator_other.odin +++ b/base/runtime/heap_allocator_other.odin @@ -12,4 +12,4 @@ _heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr { _heap_free :: proc(ptr: rawptr) { unimplemented("base:runtime 'heap_free' procedure is not supported on this platform") -} \ No newline at end of file +} diff --git a/base/runtime/os_specific_orca.odin b/base/runtime/os_specific_orca.odin new file mode 100644 index 000000000..b6f5930ab --- /dev/null +++ b/base/runtime/os_specific_orca.odin @@ -0,0 +1,43 @@ +//+build orca +//+private +package runtime + +import "base:intrinsics" + +// Constants allowing to specify the level of logging verbosity. +log_level :: enum u32 { + // Only errors are logged. + ERROR = 0, + // Only warnings and errors are logged. + WARNING = 1, + // All messages are logged. + INFO = 2, + COUNT = 3, +} + +@(default_calling_convention="c", link_prefix="oc_") +foreign { + abort_ext :: proc(file: cstring, function: cstring, line: i32, fmt: cstring, #c_vararg args: ..any) -> ! --- + assert_fail :: proc(file: cstring, function: cstring, line: i32, src: cstring, fmt: cstring, #c_vararg args: ..any) -> ! --- + log_ext :: proc(level: log_level, function: cstring, file: cstring, line: i32, fmt: cstring, #c_vararg args: ..any) --- +} + +// NOTE: This is all pretty gross, don't look. + +// WASM is single threaded so this should be fine. +orca_stderr_buffer: [4096]byte +orca_stderr_buffer_idx: int + +_stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { + for b in data { + orca_stderr_buffer[orca_stderr_buffer_idx] = b + orca_stderr_buffer_idx += 1 + + if b == '\n' || orca_stderr_buffer_idx == len(orca_stderr_buffer)-1 { + log_ext(.ERROR, "", "", 0, cstring(raw_data(orca_stderr_buffer[:orca_stderr_buffer_idx]))) + orca_stderr_buffer_idx = 0 + } + } + + return len(data), 0 +} diff --git a/base/runtime/procs.odin b/base/runtime/procs.odin index c9347463b..002a6501f 100644 --- a/base/runtime/procs.odin +++ b/base/runtime/procs.odin @@ -25,7 +25,7 @@ when ODIN_NO_CRT && ODIN_OS == .Windows { RtlMoveMemory(dst, src, len) return dst } -} else when ODIN_NO_CRT || (ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32) { +} else when ODIN_NO_CRT || (ODIN_OS != .Orca && (ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32)) { // NOTE: on wasm, calls to these procs are generated (by LLVM) with type `i32` instead of `int`. // // NOTE: `#any_int` is also needed, because calls that we generate (and package code) diff --git a/core/fmt/fmt_os.odin b/core/fmt/fmt_os.odin index a403dcd65..9de0d43be 100644 --- a/core/fmt/fmt_os.odin +++ b/core/fmt/fmt_os.odin @@ -1,5 +1,6 @@ //+build !freestanding //+build !js +//+build !orca package fmt import "base:runtime" diff --git a/core/time/time_orca.odin b/core/time/time_orca.odin new file mode 100644 index 000000000..d222c8247 --- /dev/null +++ b/core/time/time_orca.odin @@ -0,0 +1,24 @@ +//+private +//+build orca +package time + +_IS_SUPPORTED :: false + +_now :: proc "contextless" () -> Time { + return {} +} + +_sleep :: proc "contextless" (d: Duration) { +} + +_tick_now :: proc "contextless" () -> Tick { + // mul_div_u64 :: proc "contextless" (val, num, den: i64) -> i64 { + // q := val / den + // r := val % den + // return q * num + r * num / den + // } + return {} +} + +_yield :: proc "contextless" () { +} diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 3c7ff3f1e..8a08c2b34 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1080,8 +1080,7 @@ gb_global TargetMetrics target_orca_wasm32 = { TargetOs_orca, TargetArch_wasm32, 4, 4, 8, 16, - str_lit("wasm32-wasi-js"), - // str_lit("e-m:e-p:32:32-i64:64-n32:64-S128"), + str_lit("wasm32-freestanding-js"), }; @@ -1161,6 +1160,7 @@ gb_global NamedTargetMetrics named_targets[] = { { str_lit("freestanding_wasm32"), &target_freestanding_wasm32 }, { str_lit("wasi_wasm32"), &target_wasi_wasm32 }, { str_lit("js_wasm32"), &target_js_wasm32 }, + { str_lit("orca_wasm32"), &target_orca_wasm32 }, { str_lit("freestanding_wasm64p32"), &target_freestanding_wasm64p32 }, { str_lit("js_wasm64p32"), &target_js_wasm64p32 }, @@ -2032,11 +2032,10 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta // } if (bc->no_entry_point || bc->metrics.os == TargetOs_orca) { link_flags = gb_string_appendc(link_flags, "--no-entry "); - bc->no_entry_point = true; // just in case for the "orca" target } - + bc->link_flags = make_string_c(link_flags); - + // Disallow on wasm bc->use_separate_modules = false; } else { diff --git a/src/linker.cpp b/src/linker.cpp index b699c0dfb..91055a604 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -13,6 +13,7 @@ struct LinkerData { }; gb_internal i32 system_exec_command_line_app(char const *name, char const *fmt, ...); +gb_internal bool system_exec_command_line_app_output(char const *command, gbString *output); #if defined(GB_SYSTEM_OSX) gb_internal void linker_enable_system_library_linking(LinkerData *ld) { @@ -69,27 +70,42 @@ gb_internal i32 linker_stage(LinkerData *gen) { if (is_arch_wasm()) { timings_start_section(timings, str_lit("wasm-ld")); - String extra_orca_flags = {}; + gbString extra_orca_flags = gb_string_make(temporary_allocator(), ""); + + gbString inputs = gb_string_make(temporary_allocator(), ""); + inputs = gb_string_append_fmt(inputs, "\"%.*s.o\"", LIT(output_filename)); - #if defined(GB_SYSTEM_WINDOWS) if (build_context.metrics.os == TargetOs_orca) { - extra_orca_flags = str_lit(" W:/orca/installation/dev-afb9591/bin/liborca_wasm.a --export-dynamic"); + // TODO: Orca windows. + + gbString orca_sdk_path = gb_string_make(temporary_allocator(), ""); + if (!system_exec_command_line_app_output("orca sdk-path", &orca_sdk_path)) { + gb_printf_err("executing `orca sdk-path` failed, make sure Orca is installed and added to your path\n"); + return 1; + } + if (gb_string_length(orca_sdk_path) == 0) { + gb_printf_err("executing `orca sdk-path` did not produce output\n"); + return 1; + } + inputs = gb_string_append_fmt(inputs, " \"%s/orca-libc/lib/crt1.o\" \"%s/orca-libc/lib/libc.o\"", orca_sdk_path, orca_sdk_path); + + extra_orca_flags = gb_string_append_fmt(extra_orca_flags, " -L \"%s/bin\" -lorca_wasm --export-dynamic", orca_sdk_path); } + + #if defined(GB_SYSTEM_WINDOWS) result = system_exec_command_line_app("wasm-ld", "\"%.*s\\bin\\wasm-ld\" \"%.*s.o\" -o \"%.*s\" %.*s %.*s %.*s", LIT(build_context.ODIN_ROOT), LIT(output_filename), LIT(output_filename), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags), LIT(extra_orca_flags)); #else - if (build_context.metrics.os == TargetOs_orca) { - extra_orca_flags = str_lit(" -L . -lorca --export-dynamic"); - } - result = system_exec_command_line_app("wasm-ld", - "wasm-ld \"%.*s.o\" -o \"%.*s\" %.*s %.*s %.*s", - LIT(output_filename), LIT(output_filename), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags), - LIT(extra_orca_flags)); + "wasm-ld %s -o \"%.*s\" %.*s %.*s %s", + inputs, LIT(output_filename), + LIT(build_context.link_flags), + LIT(build_context.extra_linker_flags), + extra_orca_flags); #endif return result; } diff --git a/src/main.cpp b/src/main.cpp index 3ca024ed9..a30cad059 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -155,6 +155,34 @@ gb_internal i32 system_exec_command_line_app(char const *name, char const *fmt, return exit_code; } +// TODO: windows. +gb_internal bool system_exec_command_line_app_output(char const *command, gbString *output) { + GB_ASSERT(output); + + u8 buffer[256]; + FILE *stream; + stream = popen(command, "r"); + if (!stream) { + return false; + } + defer (pclose(stream)); + + while (!feof(stream)) { + size_t n = fread(buffer, 1, 255, stream); + *output = gb_string_append_length(*output, buffer, n); + + if (ferror(stream)) { + return false; + } + } + + if (build_context.show_system_calls) { + gb_printf_err("[SYSTEM CALL OUTPUT] %s -> %s\n", command, *output); + } + + return true; +} + gb_internal Array setup_args(int argc, char const **argv) { gbAllocator a = heap_allocator(); -- cgit v1.2.3 From 08382cb05dc23816f36c0a52b23c4d501431f88c Mon Sep 17 00:00:00 2001 From: laytan Date: Wed, 5 Jun 2024 19:26:23 +0200 Subject: orca windows --- src/build_settings.cpp | 2 +- src/linker.cpp | 10 ++++------ src/main.cpp | 6 +++++- 3 files changed, 10 insertions(+), 8 deletions(-) (limited to 'src/main.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 8a08c2b34..05117a9b2 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1080,7 +1080,7 @@ gb_global TargetMetrics target_orca_wasm32 = { TargetOs_orca, TargetArch_wasm32, 4, 4, 8, 16, - str_lit("wasm32-freestanding-js"), + str_lit("wasm32-wasi-js"), }; diff --git a/src/linker.cpp b/src/linker.cpp index 91055a604..25c54a6ab 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -72,12 +72,10 @@ gb_internal i32 linker_stage(LinkerData *gen) { gbString extra_orca_flags = gb_string_make(temporary_allocator(), ""); - gbString inputs = gb_string_make(temporary_allocator(), ""); + gbString inputs = gb_string_make(temporary_allocator(), ""); inputs = gb_string_append_fmt(inputs, "\"%.*s.o\"", LIT(output_filename)); if (build_context.metrics.os == TargetOs_orca) { - // TODO: Orca windows. - gbString orca_sdk_path = gb_string_make(temporary_allocator(), ""); if (!system_exec_command_line_app_output("orca sdk-path", &orca_sdk_path)) { gb_printf_err("executing `orca sdk-path` failed, make sure Orca is installed and added to your path\n"); @@ -95,10 +93,10 @@ gb_internal i32 linker_stage(LinkerData *gen) { #if defined(GB_SYSTEM_WINDOWS) result = system_exec_command_line_app("wasm-ld", - "\"%.*s\\bin\\wasm-ld\" \"%.*s.o\" -o \"%.*s\" %.*s %.*s %.*s", + "\"%.*s\\bin\\wasm-ld\" %s -o \"%.*s\" %.*s %.*s %s", LIT(build_context.ODIN_ROOT), - LIT(output_filename), LIT(output_filename), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags), - LIT(extra_orca_flags)); + inputs, LIT(output_filename), LIT(build_context.link_flags), LIT(build_context.extra_linker_flags), + extra_orca_flags); #else result = system_exec_command_line_app("wasm-ld", "wasm-ld %s -o \"%.*s\" %.*s %.*s %s", diff --git a/src/main.cpp b/src/main.cpp index a30cad059..70def5802 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -155,7 +155,11 @@ gb_internal i32 system_exec_command_line_app(char const *name, char const *fmt, return exit_code; } -// TODO: windows. +#if defined(GB_SYSTEM_WINDOWS) +#define popen _popen +#define pclose _pclose +#endif + gb_internal bool system_exec_command_line_app_output(char const *command, gbString *output) { GB_ASSERT(output); -- cgit v1.2.3 From 9a95049393ea98ef6222bf217ab44dd127c3f960 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Mon, 22 Jan 2024 17:21:52 +0100 Subject: -show-defineables and -export-defineables --- src/build_settings.cpp | 2 + src/check_builtin.cpp | 11 ++++- src/checker.cpp | 2 + src/checker.hpp | 12 +++++ src/main.cpp | 124 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 150 insertions(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 251dd06dd..d25d553a9 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -844,6 +844,8 @@ struct BuildContext { bool show_unused; bool show_unused_with_location; bool show_more_timings; + bool show_defineables; + String export_defineables_file; bool show_system_calls; bool keep_temp_files; bool ignore_unknown_attributes; diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 7e3bcb7ee..b2afa3d0c 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1777,7 +1777,7 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o } String name = arg->Ident.token.string; - + operand->type = def.type; operand->mode = def.mode; @@ -1793,6 +1793,15 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o operand->value = found->Constant.value; } } + + Defineable defineable = {}; + defineable.name = name; + defineable.default_value = def.value; + defineable.pos = arg->Ident.token.pos; + + MUTEX_GUARD(&c->info->defineables_mutex); + array_add(&c->info->defineables, defineable); + } else { error(call, "Unknown directive call: #%.*s", LIT(name)); } diff --git a/src/checker.cpp b/src/checker.cpp index 8a58bb425..0f23e308b 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1275,6 +1275,7 @@ gb_internal void init_checker_info(CheckerInfo *i) { array_init(&i->init_procedures, a, 0, 0); array_init(&i->fini_procedures, a, 0, 0); array_init(&i->required_foreign_imports_through_force, a, 0, 0); + array_init(&i->defineables, a); map_init(&i->objc_msgSend_types); string_map_init(&i->load_file_cache); @@ -1304,6 +1305,7 @@ gb_internal void destroy_checker_info(CheckerInfo *i) { string_map_destroy(&i->packages); array_free(&i->variable_init_order); array_free(&i->required_foreign_imports_through_force); + array_free(&i->defineables); mpsc_destroy(&i->entity_queue); mpsc_destroy(&i->definition_queue); diff --git a/src/checker.hpp b/src/checker.hpp index 2ac4c8e7a..fc37f5769 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -376,6 +376,15 @@ struct GenTypesData { RecursiveMutex mutex; }; +struct Defineable { + String name; + ExactValue default_value; + TokenPos pos; + + String default_value_str; + String pos_str; +}; + // CheckerInfo stores all the symbol information for a type-checked program struct CheckerInfo { Checker *checker; @@ -402,6 +411,9 @@ struct CheckerInfo { Array entities; Array required_foreign_imports_through_force; + BlockingMutex defineables_mutex; + Array defineables; + // Below are accessed within procedures RwMutex global_untyped_mutex; diff --git a/src/main.cpp b/src/main.cpp index 70def5802..a3e87fb6a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -288,6 +288,9 @@ enum BuildFlagKind { BuildFlag_NoThreadedChecker, BuildFlag_ShowDebugMessages, + BuildFlag_ShowDefineables, + BuildFlag_ExportDefineables, + BuildFlag_Vet, BuildFlag_VetShadowing, BuildFlag_VetUnused, @@ -483,6 +486,9 @@ gb_internal bool parse_build_flags(Array args) { 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_ShowDefineables, str_lit("show-defineables"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_ExportDefineables, str_lit("export-defineables"), BuildFlagParam_String, Command__does_check); + add_flag(&build_flags, BuildFlag_Vet, str_lit("vet"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_VetUnused, str_lit("vet-unused"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_VetUnusedVariables, str_lit("vet-unused-variables"), BuildFlagParam_None, Command__does_check); @@ -814,6 +820,24 @@ gb_internal bool parse_build_flags(Array args) { break; } + case BuildFlag_ShowDefineables: { + GB_ASSERT(value.kind == ExactValue_Invalid); + build_context.show_defineables = true; + break; + } + case BuildFlag_ExportDefineables: { + GB_ASSERT(value.kind == ExactValue_String); + + String export_path = string_trim_whitespace(value.value_string); + if (is_build_flag_path_valid(export_path)) { + build_context.export_defineables_file = path_to_full_path(heap_allocator(), export_path); + } else { + gb_printf_err("Invalid -export-defineables path, got %.*s\n", LIT(export_path)); + bad_flags = true; + } + + break; + } case BuildFlag_ShowSystemCalls: { GB_ASSERT(value.kind == ExactValue_Invalid); build_context.show_system_calls = true; @@ -1553,6 +1577,84 @@ gb_internal void timings_export_all(Timings *t, Checker *c, bool timings_are_fin gb_printf("Done.\n"); } +gb_internal void temp_alloc_defineable_strings(Checker *c) { + for_array(i, c->info.defineables) { + Defineable *def = &c->info.defineables[i]; + def->default_value_str = make_string_c(write_exact_value_to_string(gb_string_make(temporary_allocator(), ""), def->default_value)); + def->pos_str = make_string_c(token_pos_to_string(def->pos)); + } +} + +gb_internal GB_COMPARE_PROC(defineables_cmp) { + Defineable *x = (Defineable *)a; + Defineable *y = (Defineable *)b; + + int cmp = 0; + + String x_file = get_file_path_string(x->pos.file_id); + String y_file = get_file_path_string(y->pos.file_id); + cmp = string_compare(x_file, y_file); + if (cmp) { + return cmp; + } + + return i32_cmp(x->pos.offset, y->pos.offset); +} + +gb_internal void sort_defineables(Checker *c) { + gb_sort_array(c->info.defineables.data, c->info.defineables.count, defineables_cmp); +} + +gb_internal void export_defineables(Checker *c, String path) { + gbFile f = {}; + gbFileError err = gb_file_open_mode(&f, gbFileMode_Write, (char *)path.text); + if (err != gbFileError_None) { + gb_printf_err("Failed to export defineables to: %.*s\n", LIT(path)); + gb_exit(1); + return; + } else { + gb_printf("Exporting defineables to '%.*s'...\n", LIT(path)); + } + defer (gb_file_close(&f)); + + gb_fprintf(&f, "Defineable,Default Value,Location\n"); + for_array(i, c->info.defineables) { + Defineable *def = &c->info.defineables[i]; + gb_fprintf(&f,"%.*s,%.*s,%.*s\n", LIT(def->name), LIT(def->default_value_str), LIT(def->pos_str)); + } +} + +gb_internal void show_defineables(Checker *c) { + int max_name_len = strlen("Defineable"); + int max_default_len = strlen("Default Value"); + int max_pos_len = strlen("Location"); + + for_array(i, c->info.defineables) { + Defineable *def = &c->info.defineables[i]; + if (def->name.len > max_name_len) { + max_name_len = def->name.len; + } + + if (def->default_value_str.len > max_default_len) { + max_default_len = def->default_value_str.len; + } + + if (def->pos_str.len > max_pos_len) { + max_pos_len = def->pos_str.len; + } + } + + printf("%-*s - %-*s - %-*s\n", max_name_len, "Defineable", max_default_len, "Default Value", max_pos_len, "Location"); + + for_array(i, c->info.defineables) { + Defineable *def = &c->info.defineables[i]; + printf("%-*.*s - %-*.*s - %-*.*s\n", + max_name_len, LIT(def->name), + max_default_len, LIT(def->default_value_str), + max_pos_len, LIT(def->pos_str)); + } +} + gb_internal void show_timings(Checker *c, Timings *t) { Parser *p = c->parser; isize lines = p->total_line_count; @@ -1955,6 +2057,15 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(2, "Usage in code:"); print_usage_line(3, "#config(SPAM, default_value)"); print_usage_line(0, ""); + + print_usage_line(1, "-show-defineables"); + print_usage_line(2, "Shows an overview of all the #config usages in the project."); + print_usage_line(0, ""); + + print_usage_line(1, "-export-defineables:"); + print_usage_line(2, "Exports an overview of all the #config usages in CSV format to the given file path."); + print_usage_line(2, "Example: -export-defineables:defineables.csv"); + print_usage_line(0, ""); } if (build) { @@ -2960,6 +3071,19 @@ int main(int arg_count, char const **arg_ptr) { print_all_errors(); } + if (build_context.show_defineables || build_context.export_defineables_file != "") { + TEMPORARY_ALLOCATOR_GUARD(); + temp_alloc_defineable_strings(checker); + sort_defineables(checker); + + if (build_context.show_defineables) { + show_defineables(checker); + } + + if (build_context.export_defineables_file != "") { + export_defineables(checker, build_context.export_defineables_file); + } + } if (build_context.command_kind == Command_strip_semicolon) { return strip_semicolons(parser); -- cgit v1.2.3 From b818a7713175d882a7f8b345cee59bd19b0d1d47 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Thu, 25 Jan 2024 02:16:30 +0100 Subject: check if -define is actually used --- src/check_builtin.cpp | 15 +++++++++++++-- src/checker.hpp | 1 + src/main.cpp | 33 ++++++++++++++++++++++++++++----- 3 files changed, 42 insertions(+), 7 deletions(-) (limited to 'src/main.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index b2afa3d0c..a74082fb2 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1756,6 +1756,17 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o operand->mode = Addressing_Constant; operand->value = exact_value_bool(is_defined); + // If the arg is a selector expression we don't add it, `-define` only allows identifiers. + if (arg->kind == Ast_Ident) { + Defineable defineable = {}; + defineable.name = arg->Ident.token.string; + defineable.default_value = exact_value_bool(false); + defineable.pos = arg->Ident.token.pos; + + MUTEX_GUARD(&c->info->defineables_mutex); + array_add(&c->info->defineables, defineable); + } + } else if (name == "config") { if (ce->args.count != 2) { error(call, "'#config' expects 2 argument, got %td", ce->args.count); @@ -1777,7 +1788,7 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o } String name = arg->Ident.token.string; - + operand->type = def.type; operand->mode = def.mode; @@ -1794,7 +1805,7 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o } } - Defineable defineable = {}; + Defineable defineable = {}; defineable.name = name; defineable.default_value = def.value; defineable.pos = arg->Ident.token.pos; diff --git a/src/checker.hpp b/src/checker.hpp index fc37f5769..9db5757e3 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -381,6 +381,7 @@ struct Defineable { ExactValue default_value; TokenPos pos; + // These strings are only computed from previous fields when defineables are being shown or exported. String default_value_str; String pos_str; }; diff --git a/src/main.cpp b/src/main.cpp index a3e87fb6a..eac1b7ed9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -822,9 +822,9 @@ gb_internal bool parse_build_flags(Array args) { } case BuildFlag_ShowDefineables: { GB_ASSERT(value.kind == ExactValue_Invalid); - build_context.show_defineables = true; - break; - } + build_context.show_defineables = true; + break; + } case BuildFlag_ExportDefineables: { GB_ASSERT(value.kind == ExactValue_String); @@ -1577,6 +1577,28 @@ gb_internal void timings_export_all(Timings *t, Checker *c, bool timings_are_fin gb_printf("Done.\n"); } +gb_internal void check_defines(BuildContext *bc, Checker *c) { + for (auto const &entry : bc->defined_values) { + String name = make_string_c(entry.key); + ExactValue value = entry.value; + GB_ASSERT(value.kind != ExactValue_Invalid); + + bool found = false; + for_array(i, c->info.defineables) { + Defineable *def = &c->info.defineables[i]; + if (def->name == name) { + found = true; + break; + } + } + + if (!found) { + warning(nullptr, "given -define:%s is unused in the project", name); + error_line("\tSuggestion: use the -show-defineables flag for an overview of the possible defines\n"); + } + } +} + gb_internal void temp_alloc_defineable_strings(Checker *c) { for_array(i, c->info.defineables) { Defineable *def = &c->info.defineables[i]; @@ -2059,11 +2081,11 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(0, ""); print_usage_line(1, "-show-defineables"); - print_usage_line(2, "Shows an overview of all the #config usages in the project."); + print_usage_line(2, "Shows an overview of all the #config/#defined usages in the project."); print_usage_line(0, ""); print_usage_line(1, "-export-defineables:"); - print_usage_line(2, "Exports an overview of all the #config usages in CSV format to the given file path."); + print_usage_line(2, "Exports an overview of all the #config/#defined usages in CSV format to the given file path."); print_usage_line(2, "Example: -export-defineables:defineables.csv"); print_usage_line(0, ""); } @@ -3063,6 +3085,7 @@ int main(int arg_count, char const **arg_ptr) { defer (destroy_checker(checker)); check_parsed_files(checker); + check_defines(&build_context, checker); if (any_errors()) { print_all_errors(); return 1; -- cgit v1.2.3 From fa086906865c04531b3803f1f0cb1ee17dfe5c7e Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Thu, 25 Jan 2024 16:35:22 +0100 Subject: explicit integer conversions --- src/main.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index eac1b7ed9..793030f3f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -820,7 +820,7 @@ gb_internal bool parse_build_flags(Array args) { break; } - case BuildFlag_ShowDefineables: { + case BuildFlag_ShowDefineables: { GB_ASSERT(value.kind == ExactValue_Invalid); build_context.show_defineables = true; break; @@ -837,7 +837,7 @@ gb_internal bool parse_build_flags(Array args) { } break; - } + } case BuildFlag_ShowSystemCalls: { GB_ASSERT(value.kind == ExactValue_Invalid); build_context.show_system_calls = true; @@ -1647,9 +1647,9 @@ gb_internal void export_defineables(Checker *c, String path) { } gb_internal void show_defineables(Checker *c) { - int max_name_len = strlen("Defineable"); - int max_default_len = strlen("Default Value"); - int max_pos_len = strlen("Location"); + isize max_name_len = gb_strlen("Defineable"); + isize max_default_len = gb_strlen("Default Value"); + isize max_pos_len = gb_strlen("Location"); for_array(i, c->info.defineables) { Defineable *def = &c->info.defineables[i]; @@ -1666,14 +1666,17 @@ gb_internal void show_defineables(Checker *c) { } } - printf("%-*s - %-*s - %-*s\n", max_name_len, "Defineable", max_default_len, "Default Value", max_pos_len, "Location"); + printf("%-*s - %-*s - %-*s\n", + cast(int)max_name_len, "Defineable", + cast(int)max_default_len, "Default Value", + cast(int)max_pos_len, "Location"); for_array(i, c->info.defineables) { Defineable *def = &c->info.defineables[i]; printf("%-*.*s - %-*.*s - %-*.*s\n", - max_name_len, LIT(def->name), - max_default_len, LIT(def->default_value_str), - max_pos_len, LIT(def->pos_str)); + cast(int)max_name_len, LIT(def->name), + cast(int)max_default_len, LIT(def->default_value_str), + cast(int)max_pos_len, LIT(def->pos_str)); } } -- cgit v1.2.3 From 315695b4f8b3437fb63cfc99c976b76be4cee173 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Fri, 7 Jun 2024 14:48:11 +0200 Subject: collect and show docs of defineables --- src/check_builtin.cpp | 8 ++++++- src/checker.hpp | 7 +++--- src/main.cpp | 62 ++++++++++++++++++++++++++++----------------------- 3 files changed, 45 insertions(+), 32 deletions(-) (limited to 'src/main.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index a74082fb2..54708b5ae 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1759,6 +1759,7 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o // If the arg is a selector expression we don't add it, `-define` only allows identifiers. if (arg->kind == Ast_Ident) { Defineable defineable = {}; + defineable.docs = nullptr; defineable.name = arg->Ident.token.string; defineable.default_value = exact_value_bool(false); defineable.pos = arg->Ident.token.pos; @@ -1769,7 +1770,7 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o } else if (name == "config") { if (ce->args.count != 2) { - error(call, "'#config' expects 2 argument, got %td", ce->args.count); + error(call, "'#config' expects 2 arguments, got %td", ce->args.count); return false; } Ast *arg = unparen_expr(ce->args[0]); @@ -1806,10 +1807,15 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o } Defineable defineable = {}; + defineable.docs = nullptr; defineable.name = name; defineable.default_value = def.value; defineable.pos = arg->Ident.token.pos; + if (c->decl) { + defineable.docs = c->decl->docs; + } + MUTEX_GUARD(&c->info->defineables_mutex); array_add(&c->info->defineables, defineable); diff --git a/src/checker.hpp b/src/checker.hpp index 9db5757e3..1a8cef29a 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -377,9 +377,10 @@ struct GenTypesData { }; struct Defineable { - String name; - ExactValue default_value; - TokenPos pos; + String name; + ExactValue default_value; + TokenPos pos; + CommentGroup *docs; // These strings are only computed from previous fields when defineables are being shown or exported. String default_value_str; diff --git a/src/main.cpp b/src/main.cpp index 793030f3f..530681d03 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1593,7 +1593,8 @@ gb_internal void check_defines(BuildContext *bc, Checker *c) { } if (!found) { - warning(nullptr, "given -define:%s is unused in the project", name); + ERROR_BLOCK(); + warning(nullptr, "given -define:%.*s is unused in the project", LIT(name)); error_line("\tSuggestion: use the -show-defineables flag for an overview of the possible defines\n"); } } @@ -1639,44 +1640,49 @@ gb_internal void export_defineables(Checker *c, String path) { } defer (gb_file_close(&f)); - gb_fprintf(&f, "Defineable,Default Value,Location\n"); + gbString docs = gb_string_make(heap_allocator(), ""); + defer (gb_string_free(docs)); + + gb_fprintf(&f, "Defineable,Default Value,Docs,Location\n"); for_array(i, c->info.defineables) { Defineable *def = &c->info.defineables[i]; - gb_fprintf(&f,"%.*s,%.*s,%.*s\n", LIT(def->name), LIT(def->default_value_str), LIT(def->pos_str)); + + gb_string_clear(docs); + if (def->docs) { + docs = gb_string_appendc(docs, "\""); + for (Token const &token : def->docs->list) { + for (isize i = 0; i < token.string.len; i++) { + u8 c = token.string.text[i]; + if (c == '"') { + docs = gb_string_appendc(docs, "\"\""); + } else { + docs = gb_string_append_length(docs, &c, 1); + } + } + } + docs = gb_string_appendc(docs, "\""); + } + + gb_fprintf(&f,"%.*s,%.*s,%s,%.*s\n", LIT(def->name), LIT(def->default_value_str), docs, LIT(def->pos_str)); } } gb_internal void show_defineables(Checker *c) { - isize max_name_len = gb_strlen("Defineable"); - isize max_default_len = gb_strlen("Default Value"); - isize max_pos_len = gb_strlen("Location"); - for_array(i, c->info.defineables) { Defineable *def = &c->info.defineables[i]; - if (def->name.len > max_name_len) { - max_name_len = def->name.len; + if (has_ansi_terminal_colours()) { + gb_printf("\x1b[0;90m"); } - - if (def->default_value_str.len > max_default_len) { - max_default_len = def->default_value_str.len; + printf("%.*s\n", LIT(def->pos_str)); + if (def->docs) { + for (Token const &token : def->docs->list) { + gb_printf("%.*s\n", LIT(token.string)); + } } - - if (def->pos_str.len > max_pos_len) { - max_pos_len = def->pos_str.len; + if (has_ansi_terminal_colours()) { + gb_printf("\x1b[0m"); } - } - - printf("%-*s - %-*s - %-*s\n", - cast(int)max_name_len, "Defineable", - cast(int)max_default_len, "Default Value", - cast(int)max_pos_len, "Location"); - - for_array(i, c->info.defineables) { - Defineable *def = &c->info.defineables[i]; - printf("%-*.*s - %-*.*s - %-*.*s\n", - cast(int)max_name_len, LIT(def->name), - cast(int)max_default_len, LIT(def->default_value_str), - cast(int)max_pos_len, LIT(def->pos_str)); + gb_printf("%.*s :: %.*s\n\n", LIT(def->name), LIT(def->default_value_str)); } } -- cgit v1.2.3 From c560553c21b970d38a302a11e94181de5415d043 Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Thu, 13 Jun 2024 13:01:51 -0400 Subject: Fix compiler silently returning if `parse_packages` fails --- src/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 70def5802..f4cd40fe9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2934,7 +2934,8 @@ int main(int arg_count, char const **arg_ptr) { // TODO(jeroen): Remove the `init_filename` param. // Let's put that on `build_context.build_paths[0]` instead. if (parse_packages(parser, init_filename) != ParseFile_None) { - return 1; + GB_ASSERT_MSG(any_errors(), "parse_packages failed but no error was reported."); + // We depend on the next conditional block to return 1, after printing errors. } if (any_errors()) { -- cgit v1.2.3 From 9f696a646f5b9ee5f5cc2a89be5ec3de765d727f Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Fri, 21 Jun 2024 16:02:55 +0200 Subject: Add `-build-mode:test`. --- src/main.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 368b9aa6d..1896dd0b7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1082,6 +1082,9 @@ gb_internal bool parse_build_flags(Array args) { build_context.build_mode = BuildMode_Assembly; } else if (str == "llvm" || str == "llvm-ir") { build_context.build_mode = BuildMode_LLVM_IR; + } else if (str == "test") { + build_context.build_mode = BuildMode_Executable; + build_context.command_kind = Command_test; } else { gb_printf_err("Unknown build mode '%.*s'\n", LIT(str)); gb_printf_err("Valid build modes:\n"); @@ -1091,6 +1094,7 @@ gb_internal bool parse_build_flags(Array args) { gb_printf_err("\texe\n"); gb_printf_err("\tasm, assembly, assembler\n"); gb_printf_err("\tllvm, llvm-ir\n"); + gb_printf_err("\ttest\n"); bad_flags = true; break; } -- cgit v1.2.3 From 17efb87eef5c24bdc95da8b2406e4bde13941251 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 28 Jun 2024 11:44:05 +0100 Subject: Add `-custom-attribute` --- src/build_settings.cpp | 4 ++++ src/checker.cpp | 5 +++-- src/main.cpp | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) (limited to 'src/main.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 1988e9cac..4b348256b 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -862,6 +862,8 @@ struct BuildContext { bool keep_object_files; bool disallow_do; + StringSet custom_attributes; + bool strict_style; bool ignore_warnings; @@ -1882,6 +1884,8 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta bc->thread_count = gb_max(bc->affinity.thread_count, 1); } + string_set_init(&bc->custom_attributes); + bc->ODIN_VENDOR = str_lit("odin"); bc->ODIN_VERSION = ODIN_VERSION; bc->ODIN_ROOT = odin_root_dir(); diff --git a/src/checker.cpp b/src/checker.cpp index 8ccdcb9f7..734659510 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3900,10 +3900,11 @@ gb_internal void check_decl_attributes(CheckerContext *c, Array const &at } if (!proc(c, elem, name, value, ac)) { - if (!build_context.ignore_unknown_attributes) { + if (!build_context.ignore_unknown_attributes && + !string_set_exists(&build_context.custom_attributes, name)) { ERROR_BLOCK(); error(elem, "Unknown attribute element name '%.*s'", LIT(name)); - error_line("\tDid you forget to use build flag '-ignore-unknown-attributes'?\n"); + error_line("\tDid you forget to use the build flag '-ignore-unknown-attributes' or '-custom-attribute:%.*s'?\n", LIT(name)); } } } diff --git a/src/main.cpp b/src/main.cpp index 1896dd0b7..b24796559 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -301,6 +301,7 @@ enum BuildFlagKind { BuildFlag_VetStyle, BuildFlag_VetSemicolon, + BuildFlag_CustomAttribute, BuildFlag_IgnoreUnknownAttributes, BuildFlag_ExtraLinkerFlags, BuildFlag_ExtraAssemblerFlags, @@ -499,6 +500,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_VetStyle, str_lit("vet-style"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_VetSemicolon, str_lit("vet-semicolon"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_CustomAttribute, str_lit("custom-attribute"), BuildFlagParam_String, Command__does_check, true); 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); @@ -1151,6 +1153,29 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_VetStyle: build_context.vet_flags |= VetFlag_Style; break; case BuildFlag_VetSemicolon: build_context.vet_flags |= VetFlag_Semicolon; break; + case BuildFlag_CustomAttribute: + { + GB_ASSERT(value.kind == ExactValue_String); + String val = value.value_string; + String_Iterator it = {val, 0}; + for (;;) { + String attr = string_split_iterator(&it, ','); + if (attr.len == 0) { + break; + } + + attr = string_trim_whitespace(attr); + if (!string_is_valid_identifier(attr)) { + gb_printf_err("-custom-attribute '%.*s' must be a valid identifier\n", LIT(attr)); + bad_flags = true; + continue; + } + + string_set_add(&build_context.custom_attributes, attr); + } + } + break; + case BuildFlag_IgnoreUnknownAttributes: build_context.ignore_unknown_attributes = true; break; @@ -2221,6 +2246,15 @@ gb_internal void print_show_help(String const arg0, String const &command) { } if (check) { + print_usage_line(1, "-custom-attribute:"); + print_usage_line(2, "Add a custom attribute which will be ignored if it is unknown."); + print_usage_line(2, "This can be used with metaprogramming tools."); + print_usage_line(2, "Examples:"); + print_usage_line(3, "-custom-attribute:my_tag"); + print_usage_line(3, "-custom-attribute:my_tag,the_other_thing"); + print_usage_line(3, "-custom-attribute:my_tag -custom-attribute:the_other_thing"); + print_usage_line(0, ""); + print_usage_line(1, "-ignore-unknown-attributes"); print_usage_line(2, "Ignores unknown attributes."); print_usage_line(2, "This can be used with metaprogramming tools."); -- cgit v1.2.3 From fa5be93da2971e6485162ba8361678928065b8c3 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Fri, 28 Jun 2024 19:33:34 +0200 Subject: re-raise signals from the `odin run` binary --- src/main.cpp | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index b24796559..8bf78f89d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -61,6 +61,7 @@ gb_global Timings global_timings = {0}; #include "llvm-c/Types.h" #else #include +#include #endif #include "parser.hpp" @@ -94,16 +95,13 @@ gb_global Timings global_timings = {0}; #include "bug_report.cpp" // NOTE(bill): 'name' is used in debugging and profiling modes -gb_internal i32 system_exec_command_line_app(char const *name, char const *fmt, ...) { +gb_internal i32 system_exec_command_line_app_internal(bool exit_on_err, char const *name, char const *fmt, va_list va) { 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; - va_list va; i32 exit_code = 0; - va_start(va, fmt); cmd_len = gb_snprintf_va(cmd_line, cmd_cap-1, fmt, va); - va_end(va); #if defined(GB_SYSTEM_WINDOWS) STARTUPINFOW start_info = {gb_size_of(STARTUPINFOW)}; @@ -143,18 +141,36 @@ gb_internal i32 system_exec_command_line_app(char const *name, char const *fmt, gb_printf_err("%s\n\n", cmd_line); } exit_code = system(cmd_line); + if (exit_on_err && WIFSIGNALED(exit_code)) { + raise(WTERMSIG(exit_code)); + } if (WIFEXITED(exit_code)) { exit_code = WEXITSTATUS(exit_code); } #endif - if (exit_code) { + if (exit_on_err && exit_code) { exit(exit_code); } return exit_code; } +gb_internal i32 system_exec_command_line_app(char const *name, char const *fmt, ...) { + va_list va; + va_start(va, fmt); + i32 exit_code = system_exec_command_line_app_internal(/* exit_on_err= */ false, name, fmt, va); + va_end(va); + return exit_code; +} + +gb_internal void system_must_exec_command_line_app(char const *name, char const *fmt, ...) { + va_list va; + va_start(va, fmt); + system_exec_command_line_app_internal(/* exit_on_err= */ true, name, fmt, va); + va_end(va); +} + #if defined(GB_SYSTEM_WINDOWS) #define popen _popen #define pclose _pclose @@ -3252,7 +3268,7 @@ int main(int arg_count, char const **arg_ptr) { String exe_name = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Output]); defer (gb_free(heap_allocator(), exe_name.text)); - return system_exec_command_line_app("odin run", "\"%.*s\" %.*s", LIT(exe_name), LIT(run_args_string)); + system_must_exec_command_line_app("odin run", "\"%.*s\" %.*s", LIT(exe_name), LIT(run_args_string)); } return 0; } -- cgit v1.2.3 From 6496432b8056eeecd9ba396148f7c458a5cc02ac Mon Sep 17 00:00:00 2001 From: Feoramund <161657516+Feoramund@users.noreply.github.com> Date: Fri, 28 Jun 2024 22:49:24 -0400 Subject: Add `-vet-identical-cast` --- src/build_settings.cpp | 5 ++++- src/check_expr.cpp | 23 +++++++++++++++++++++-- src/main.cpp | 7 +++++++ 3 files changed, 32 insertions(+), 3 deletions(-) (limited to 'src/main.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 4b348256b..f44179da0 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -742,10 +742,11 @@ enum VetFlags : u64 { VetFlag_UnusedVariables = 1u<<5, VetFlag_UnusedImports = 1u<<6, VetFlag_Deprecated = 1u<<7, + VetFlag_IdenticalCast = 1u<<8, VetFlag_Unused = VetFlag_UnusedVariables|VetFlag_UnusedImports, - VetFlag_All = VetFlag_Unused|VetFlag_Shadowing|VetFlag_UsingStmt|VetFlag_Deprecated, + VetFlag_All = VetFlag_Unused|VetFlag_Shadowing|VetFlag_UsingStmt|VetFlag_Deprecated|VetFlag_IdenticalCast, VetFlag_Using = VetFlag_UsingStmt|VetFlag_UsingParam, }; @@ -769,6 +770,8 @@ u64 get_vet_flag_from_name(String const &name) { return VetFlag_Semicolon; } else if (name == "deprecated") { return VetFlag_Deprecated; + } else if (name == "identical-cast") { + return VetFlag_IdenticalCast; } return VetFlag_NONE; } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 891378b99..7d2f10c95 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3310,7 +3310,7 @@ gb_internal bool check_cast_internal(CheckerContext *c, Operand *x, Type *type) } -gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type) { +gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type, bool forbid_identical = false) { if (!is_operand_value(*x)) { error(x->expr, "Only values can be casted"); x->mode = Addressing_Invalid; @@ -3382,6 +3382,25 @@ gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type) { add_package_dependency(c, "runtime", "gnu_f2h_ieee", REQUIRE); } } + if (forbid_identical && check_vet_flags(c) & VetFlag_IdenticalCast) { + Type *src_exact = x->type; + Type *dst_exact = type; + + if (src_exact != nullptr && + dst_exact != nullptr && + // If we check polymorphic procedures, we risk erring on + // identical casts that cannot be foreseen or otherwise + // forbidden, so just skip them. + (c->curr_proc_sig == nullptr || !is_type_polymorphic(c->curr_proc_sig)) && + src_exact == dst_exact) + { + gbString oper_str = expr_to_string(x->expr); + gbString to_type = type_to_string(dst_exact); + error(x->expr, "Unneeded cast of `%s` to identical type `%s`", oper_str, to_type); + gb_string_free(oper_str); + gb_string_free(to_type); + } + } } x->type = type; @@ -10718,7 +10737,7 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast check_transmute(c, node, o, type); break; case Token_cast: - check_cast(c, o, type); + check_cast(c, o, type, true); break; default: error(node, "Invalid AST: Invalid casting expression"); diff --git a/src/main.cpp b/src/main.cpp index b24796559..aa701b61b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -300,6 +300,7 @@ enum BuildFlagKind { BuildFlag_VetUsingParam, BuildFlag_VetStyle, BuildFlag_VetSemicolon, + BuildFlag_VetIdenticalCast, BuildFlag_CustomAttribute, BuildFlag_IgnoreUnknownAttributes, @@ -499,6 +500,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_VetUsingParam, str_lit("vet-using-param"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_VetStyle, str_lit("vet-style"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_VetSemicolon, str_lit("vet-semicolon"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_VetIdenticalCast, str_lit("vet-identical-cast"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_CustomAttribute, str_lit("custom-attribute"), BuildFlagParam_String, Command__does_check, true); add_flag(&build_flags, BuildFlag_IgnoreUnknownAttributes, str_lit("ignore-unknown-attributes"), BuildFlagParam_None, Command__does_check); @@ -1152,6 +1154,7 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_VetUsingParam: build_context.vet_flags |= VetFlag_UsingParam; break; case BuildFlag_VetStyle: build_context.vet_flags |= VetFlag_Style; break; case BuildFlag_VetSemicolon: build_context.vet_flags |= VetFlag_Semicolon; break; + case BuildFlag_VetIdenticalCast: build_context.vet_flags |= VetFlag_IdenticalCast; break; case BuildFlag_CustomAttribute: { @@ -2243,6 +2246,10 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(1, "-vet-semicolon"); print_usage_line(2, "Errs on unneeded semicolons."); print_usage_line(0, ""); + + print_usage_line(1, "-vet-identical-cast"); + print_usage_line(2, "Errs on casting a value to its own type."); + print_usage_line(0, ""); } if (check) { -- cgit v1.2.3 From 704530497b166dfa6fcee8f2c95a9e492a78a024 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 29 Jun 2024 11:44:45 +0100 Subject: Rename `-vet-identical-cast` to `-vet-cast`; with minor code clean up --- src/build_settings.cpp | 8 ++++---- src/check_expr.cpp | 16 ++++++++-------- src/main.cpp | 10 +++++----- 3 files changed, 17 insertions(+), 17 deletions(-) (limited to 'src/main.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index f44179da0..f9c426487 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -742,11 +742,11 @@ enum VetFlags : u64 { VetFlag_UnusedVariables = 1u<<5, VetFlag_UnusedImports = 1u<<6, VetFlag_Deprecated = 1u<<7, - VetFlag_IdenticalCast = 1u<<8, + VetFlag_Cast = 1u<<8, VetFlag_Unused = VetFlag_UnusedVariables|VetFlag_UnusedImports, - VetFlag_All = VetFlag_Unused|VetFlag_Shadowing|VetFlag_UsingStmt|VetFlag_Deprecated|VetFlag_IdenticalCast, + VetFlag_All = VetFlag_Unused|VetFlag_Shadowing|VetFlag_UsingStmt|VetFlag_Deprecated|VetFlag_Cast, VetFlag_Using = VetFlag_UsingStmt|VetFlag_UsingParam, }; @@ -770,8 +770,8 @@ u64 get_vet_flag_from_name(String const &name) { return VetFlag_Semicolon; } else if (name == "deprecated") { return VetFlag_Deprecated; - } else if (name == "identical-cast") { - return VetFlag_IdenticalCast; + } else if (name == "cast") { + return VetFlag_Cast; } return VetFlag_NONE; } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 7d2f10c95..2fa491417 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3382,18 +3382,18 @@ gb_internal void check_cast(CheckerContext *c, Operand *x, Type *type, bool forb add_package_dependency(c, "runtime", "gnu_f2h_ieee", REQUIRE); } } - if (forbid_identical && check_vet_flags(c) & VetFlag_IdenticalCast) { + // If we check polymorphic procedures, we risk erring on + // identical casts that cannot be foreseen or otherwise + // forbidden, so just skip them. + if (forbid_identical && check_vet_flags(c) & VetFlag_Cast && + (c->curr_proc_sig == nullptr || !is_type_polymorphic(c->curr_proc_sig))) { Type *src_exact = x->type; Type *dst_exact = type; if (src_exact != nullptr && - dst_exact != nullptr && - // If we check polymorphic procedures, we risk erring on - // identical casts that cannot be foreseen or otherwise - // forbidden, so just skip them. - (c->curr_proc_sig == nullptr || !is_type_polymorphic(c->curr_proc_sig)) && - src_exact == dst_exact) - { + dst_exact != nullptr && + are_types_identical(src_exact, dst_exact) + ) { gbString oper_str = expr_to_string(x->expr); gbString to_type = type_to_string(dst_exact); error(x->expr, "Unneeded cast of `%s` to identical type `%s`", oper_str, to_type); diff --git a/src/main.cpp b/src/main.cpp index aa701b61b..62aeccaf5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -300,7 +300,7 @@ enum BuildFlagKind { BuildFlag_VetUsingParam, BuildFlag_VetStyle, BuildFlag_VetSemicolon, - BuildFlag_VetIdenticalCast, + BuildFlag_VetCast, BuildFlag_CustomAttribute, BuildFlag_IgnoreUnknownAttributes, @@ -500,7 +500,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_VetUsingParam, str_lit("vet-using-param"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_VetStyle, str_lit("vet-style"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_VetSemicolon, str_lit("vet-semicolon"), BuildFlagParam_None, Command__does_check); - add_flag(&build_flags, BuildFlag_VetIdenticalCast, str_lit("vet-identical-cast"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_VetCast, str_lit("vet-cast"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_CustomAttribute, str_lit("custom-attribute"), BuildFlagParam_String, Command__does_check, true); add_flag(&build_flags, BuildFlag_IgnoreUnknownAttributes, str_lit("ignore-unknown-attributes"), BuildFlagParam_None, Command__does_check); @@ -1154,7 +1154,7 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_VetUsingParam: build_context.vet_flags |= VetFlag_UsingParam; break; case BuildFlag_VetStyle: build_context.vet_flags |= VetFlag_Style; break; case BuildFlag_VetSemicolon: build_context.vet_flags |= VetFlag_Semicolon; break; - case BuildFlag_VetIdenticalCast: build_context.vet_flags |= VetFlag_IdenticalCast; break; + case BuildFlag_VetCast: build_context.vet_flags |= VetFlag_Cast; break; case BuildFlag_CustomAttribute: { @@ -2247,8 +2247,8 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(2, "Errs on unneeded semicolons."); print_usage_line(0, ""); - print_usage_line(1, "-vet-identical-cast"); - print_usage_line(2, "Errs on casting a value to its own type."); + print_usage_line(1, "-vet-cast"); + print_usage_line(2, "Errs on casting a value to its own type or using `transmute` rather than `cast`."); print_usage_line(0, ""); } -- cgit v1.2.3 From d6b8544f508183871b636f8742ba813863d036f3 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 29 Jun 2024 12:04:31 +0100 Subject: Add internal flag for testing stuff --- src/build_settings.cpp | 1 + src/check_builtin.cpp | 12 +++++++----- src/main.cpp | 5 +++++ 3 files changed, 13 insertions(+), 5 deletions(-) (limited to 'src/main.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index f9c426487..47a29a461 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -878,6 +878,7 @@ struct BuildContext { bool ignore_lazy; bool ignore_llvm_build; + bool ignore_panic; bool ignore_microsoft_magic; bool linker_map_file; diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 47abd42cf..c1422e80e 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1726,11 +1726,13 @@ gb_internal bool check_builtin_procedure_directive(CheckerContext *c, Operand *o gb_string_free(str); return false; } - error(call, "Compile time panic: %.*s", LIT(operand->value.value_string)); - if (c->proc_name != "") { - gbString str = type_to_string(c->curr_proc_sig); - error_line("\tCalled within '%.*s' :: %s\n", LIT(c->proc_name), str); - gb_string_free(str); + if (!build_context.ignore_panic) { + error(call, "Compile time panic: %.*s", LIT(operand->value.value_string)); + if (c->proc_name != "") { + gbString str = type_to_string(c->curr_proc_sig); + error_line("\tCalled within '%.*s' :: %s\n", LIT(c->proc_name), str); + gb_string_free(str); + } } operand->type = t_invalid; operand->mode = Addressing_NoValue; diff --git a/src/main.cpp b/src/main.cpp index 62aeccaf5..c1ec77ec4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -345,6 +345,7 @@ enum BuildFlagKind { // internal use only BuildFlag_InternalIgnoreLazy, BuildFlag_InternalIgnoreLLVMBuild, + BuildFlag_InternalIgnorePanic, BuildFlag_Tilde, @@ -543,6 +544,7 @@ gb_internal bool parse_build_flags(Array args) { 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); + add_flag(&build_flags, BuildFlag_InternalIgnorePanic, str_lit("internal-ignore-panic"), BuildFlagParam_None, Command_all); #if ALLOW_TILDE add_flag(&build_flags, BuildFlag_Tilde, str_lit("tilde"), BuildFlagParam_None, Command__does_build); @@ -1352,6 +1354,9 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_InternalIgnoreLLVMBuild: build_context.ignore_llvm_build = true; break; + case BuildFlag_InternalIgnorePanic: + build_context.ignore_panic = true; + break; case BuildFlag_Tilde: build_context.tilde_backend = true; break; -- cgit v1.2.3 From 835e8bf87a700c695b30d1efaa224e2207cb61f4 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 29 Jun 2024 19:15:33 +0100 Subject: Update `-strict-style` --- src/main.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index c1ec77ec4..611890a5c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2352,6 +2352,8 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(2, "Errs on unneeded tokens, such as unneeded semicolons."); print_usage_line(2, "Errs on missing trailing commas followed by a newline."); print_usage_line(2, "Errs on deprecated syntax."); + print_usage_line(2, "Errs when 'case' labels are not in the same column as the associated 'switch' token."); + print_usage_line(2, "Errs when the attached-brace style in not adhered to (also known as 1TBS)."); print_usage_line(0, ""); print_usage_line(1, "-ignore-warnings"); -- cgit v1.2.3 From 888bf28076eea73b89b3a299523e4371cdf2b6b2 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 29 Jun 2024 19:26:11 +0100 Subject: `-strict-style` implies `-disallow-do` --- src/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 611890a5c..610f214ff 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1276,6 +1276,7 @@ gb_internal bool parse_build_flags(Array args) { break; case BuildFlag_StrictStyle: build_context.strict_style = true; + build_context.disallow_do = true; break; case BuildFlag_Short: build_context.cmd_doc_flags |= CmdDocFlag_Short; @@ -2353,7 +2354,8 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(2, "Errs on missing trailing commas followed by a newline."); print_usage_line(2, "Errs on deprecated syntax."); print_usage_line(2, "Errs when 'case' labels are not in the same column as the associated 'switch' token."); - print_usage_line(2, "Errs when the attached-brace style in not adhered to (also known as 1TBS)."); + print_usage_line(2, "Errs when 'case' labels are not in the same column as the associated 'switch' token."); + print_usage_line(2, "Disallows the 'do' keyword in the project (same as '-disallow-do')."); print_usage_line(0, ""); print_usage_line(1, "-ignore-warnings"); -- cgit v1.2.3 From f64d1df90b969c0d13c8b77c9acd153b7243f3a6 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 29 Jun 2024 19:27:26 +0100 Subject: Add note regarding `-strict-style` --- src/main.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 610f214ff..9b05fab2f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2350,6 +2350,8 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(0, ""); print_usage_line(1, "-strict-style"); + print_usage_line(2, "This enforces parts of same style as the Odin compiler, prefer '-vet-style -vet-semicolon' if you do not want to match it exactly."); + print_usage_line(2, ""); print_usage_line(2, "Errs on unneeded tokens, such as unneeded semicolons."); print_usage_line(2, "Errs on missing trailing commas followed by a newline."); print_usage_line(2, "Errs on deprecated syntax."); -- cgit v1.2.3 From 90244a0849afe9f17e011dc8c3bae571c9f5bb26 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 29 Jun 2024 19:41:45 +0100 Subject: Fix accidental deletion in the `-strict-style` help comment --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 9b05fab2f..ea82651f5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2355,7 +2355,7 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(2, "Errs on unneeded tokens, such as unneeded semicolons."); print_usage_line(2, "Errs on missing trailing commas followed by a newline."); print_usage_line(2, "Errs on deprecated syntax."); - print_usage_line(2, "Errs when 'case' labels are not in the same column as the associated 'switch' token."); + print_usage_line(2, "Errs when the attached-brace style in not adhered to (also known as 1TBS)."); print_usage_line(2, "Errs when 'case' labels are not in the same column as the associated 'switch' token."); print_usage_line(2, "Disallows the 'do' keyword in the project (same as '-disallow-do')."); print_usage_line(0, ""); -- cgit v1.2.3 From b1a1da6618ce8ea5ffc8b7fca520895f01d36929 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 29 Jun 2024 19:54:31 +0100 Subject: Add `-vet-tabs` --- src/build_settings.cpp | 3 +++ src/main.cpp | 7 +++++++ src/parser.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) (limited to 'src/main.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index d79343a8b..c3b4f2506 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -282,6 +282,7 @@ enum VetFlags : u64 { VetFlag_UnusedImports = 1u<<6, VetFlag_Deprecated = 1u<<7, VetFlag_Cast = 1u<<8, + VetFlag_Tabs = 1u<<9, VetFlag_Unused = VetFlag_UnusedVariables|VetFlag_UnusedImports, @@ -311,6 +312,8 @@ u64 get_vet_flag_from_name(String const &name) { return VetFlag_Deprecated; } else if (name == "cast") { return VetFlag_Cast; + } else if (name == "tabs") { + return VetFlag_Tabs; } return VetFlag_NONE; } diff --git a/src/main.cpp b/src/main.cpp index ea82651f5..53e631bb0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -301,6 +301,7 @@ enum BuildFlagKind { BuildFlag_VetStyle, BuildFlag_VetSemicolon, BuildFlag_VetCast, + BuildFlag_VetTabs, BuildFlag_CustomAttribute, BuildFlag_IgnoreUnknownAttributes, @@ -502,6 +503,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_VetStyle, str_lit("vet-style"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_VetSemicolon, str_lit("vet-semicolon"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_VetCast, str_lit("vet-cast"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_VetTabs, str_lit("vet-tabs"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_CustomAttribute, str_lit("custom-attribute"), BuildFlagParam_String, Command__does_check, true); add_flag(&build_flags, BuildFlag_IgnoreUnknownAttributes, str_lit("ignore-unknown-attributes"), BuildFlagParam_None, Command__does_check); @@ -1157,6 +1159,7 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_VetStyle: build_context.vet_flags |= VetFlag_Style; break; case BuildFlag_VetSemicolon: build_context.vet_flags |= VetFlag_Semicolon; break; case BuildFlag_VetCast: build_context.vet_flags |= VetFlag_Cast; break; + case BuildFlag_VetTabs: build_context.vet_flags |= VetFlag_Tabs; break; case BuildFlag_CustomAttribute: { @@ -2256,6 +2259,10 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(1, "-vet-cast"); print_usage_line(2, "Errs on casting a value to its own type or using `transmute` rather than `cast`."); print_usage_line(0, ""); + + print_usage_line(1, "-vet-tabs"); + print_usage_line(2, "Errs when the use of tabs has not been used for indentation."); + print_usage_line(0, ""); } if (check) { diff --git a/src/parser.cpp b/src/parser.cpp index 9b27ae156..51dc03085 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -5286,12 +5286,53 @@ gb_internal Ast *parse_stmt(AstFile *f) { return ast_bad_stmt(f, token, f->curr_token); } + + +gb_internal u64 check_vet_flags(AstFile *file) { + if (file && file->vet_flags_set) { + return file->vet_flags; + } + return build_context.vet_flags; +} + + +gb_internal void parse_enforce_tabs(AstFile *f) { + Token prev = f->prev_token; + Token curr = f->curr_token; + if (prev.pos.line < curr.pos.line) { + u8 *start = f->tokenizer.start+prev.pos.offset; + u8 *end = f->tokenizer.start+curr.pos.offset; + u8 *it = end; + while (it > start) { + if (*it == '\n') { + it++; + break; + } + it--; + } + + isize len = end-it; + for (isize i = 0; i < len; i++) { + if (it[i] == ' ') { + syntax_error(curr, "With '-vet-tabs', tabs must be used for indentation"); + break; + } + } + } +} + gb_internal Array parse_stmt_list(AstFile *f) { auto list = array_make(ast_allocator(f)); while (f->curr_token.kind != Token_case && f->curr_token.kind != Token_CloseBrace && f->curr_token.kind != Token_EOF) { + + // Checks to see if tabs have been used for indentation + if (check_vet_flags(f) & VetFlag_Tabs) { + parse_enforce_tabs(f); + } + Ast *stmt = parse_stmt(f); if (stmt && stmt->kind != Ast_EmptyStmt) { array_add(&list, stmt); -- cgit v1.2.3 From af3401631ad44487b7fba47330bfffea9ccf797b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 29 Jun 2024 22:48:43 +0100 Subject: Remove the `-disallow-do` aspect from `-strict-style` --- src/main.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 53e631bb0..dca2b7fc8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1279,7 +1279,6 @@ gb_internal bool parse_build_flags(Array args) { break; case BuildFlag_StrictStyle: build_context.strict_style = true; - build_context.disallow_do = true; break; case BuildFlag_Short: build_context.cmd_doc_flags |= CmdDocFlag_Short; @@ -2364,7 +2363,6 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(2, "Errs on deprecated syntax."); print_usage_line(2, "Errs when the attached-brace style in not adhered to (also known as 1TBS)."); print_usage_line(2, "Errs when 'case' labels are not in the same column as the associated 'switch' token."); - print_usage_line(2, "Disallows the 'do' keyword in the project (same as '-disallow-do')."); print_usage_line(0, ""); print_usage_line(1, "-ignore-warnings"); -- cgit v1.2.3 From f6892d22365b97e53e17c3bac3fbc91d04512668 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Wed, 3 Jul 2024 19:30:25 +0200 Subject: Fix help text. --- src/main.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index dca2b7fc8..acbef86c7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2148,7 +2148,6 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(3, "-build-mode:shared Builds as a dynamically linked library."); print_usage_line(3, "-build-mode:lib Builds as a statically linked library."); print_usage_line(3, "-build-mode:static Builds as a statically linked library."); - print_usage_line(3, "-build-mode:lib Builds as an static library."); print_usage_line(3, "-build-mode:obj Builds as an object file."); print_usage_line(3, "-build-mode:object Builds as an object file."); print_usage_line(3, "-build-mode:assembly Builds as an assembly file."); -- cgit v1.2.3 From 86c58167ed2cef39c64268f30b748f003a5a2969 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 8 Jul 2024 10:40:04 +0100 Subject: Add `-print-linker-flags` --- src/build_settings.cpp | 2 ++ src/main.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 2 deletions(-) (limited to 'src/main.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 9c93a5b69..6f4b51df8 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -440,6 +440,8 @@ struct BuildContext { bool min_link_libs; + bool print_linker_flags; + RelocMode reloc_mode; bool disable_red_zone; diff --git a/src/main.cpp b/src/main.cpp index c4fccedbc..f80da8c68 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -103,6 +103,31 @@ gb_internal i32 system_exec_command_line_app_internal(bool exit_on_err, char con cmd_len = gb_snprintf_va(cmd_line, cmd_cap-1, fmt, va); + if (build_context.print_linker_flags) { + // NOTE(bill): remove the first argument (the executable) from the executable list + // and then print it for the "linker flags" + while (*cmd_line && gb_char_is_space(*cmd_line)) { + cmd_line++; + } + if (*cmd_line == '\"') for (cmd_line++; *cmd_line; cmd_line++) { + if (*cmd_line == '\\') { + cmd_line++; + if (*cmd_line == '\"') { + cmd_line++; + } + } else if (*cmd_line == '\"') { + cmd_line++; + break; + } + } + while (*cmd_line && gb_char_is_space(*cmd_line)) { + cmd_line++; + } + + fprintf(stdout, "%s\n", cmd_line); + return exit_code; + } + #if defined(GB_SYSTEM_WINDOWS) STARTUPINFOW start_info = {gb_size_of(STARTUPINFOW)}; PROCESS_INFORMATION pi = {0}; @@ -359,6 +384,8 @@ enum BuildFlagKind { BuildFlag_MinLinkLibs, + BuildFlag_PrintLinkerFlags, + // internal use only BuildFlag_InternalIgnoreLazy, BuildFlag_InternalIgnoreLLVMBuild, @@ -560,6 +587,8 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_MinLinkLibs, str_lit("min-link-libs"), BuildFlagParam_None, Command__does_build); + add_flag(&build_flags, BuildFlag_PrintLinkerFlags, str_lit("print-linker-flags"), BuildFlagParam_None, Command_build); + 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); add_flag(&build_flags, BuildFlag_InternalIgnorePanic, str_lit("internal-ignore-panic"), BuildFlagParam_None, Command_all); @@ -828,8 +857,7 @@ gb_internal bool parse_build_flags(Array args) { gb_printf_err("\tjson\n"); bad_flags = true; } - - break; + break; } case BuildFlag_ExportDependenciesFile: { GB_ASSERT(value.kind == ExactValue_String); @@ -1367,6 +1395,10 @@ gb_internal bool parse_build_flags(Array args) { build_context.min_link_libs = true; break; + case BuildFlag_PrintLinkerFlags: + build_context.print_linker_flags = true; + break; + case BuildFlag_InternalIgnoreLazy: build_context.ignore_lazy = true; break; @@ -1535,6 +1567,16 @@ gb_internal bool parse_build_flags(Array args) { gb_printf_err("`-export-timings:` requires `-show-timings` or `-show-more-timings` to be present\n"); bad_flags = true; } + + + if (build_context.export_dependencies_format != DependenciesExportUnspecified && build_context.print_linker_flags) { + gb_printf_err("-export-dependencies cannot be used with -print-linker-flags\n"); + bad_flags = true; + } else if (build_context.show_timings && build_context.print_linker_flags) { + gb_printf_err("-show-timings/-show-more-timings cannot be used with -print-linker-flags\n"); + bad_flags = true; + } + return !bad_flags; } @@ -2361,6 +2403,12 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(0, ""); } + if (build) { + print_usage_line(1, "-print-linker-flags"); + print_usage_line(2, "Prints the all of the flags/arguments that will be passed to the linker."); + print_usage_line(0, ""); + } + if (check) { print_usage_line(1, "-disallow-do"); print_usage_line(2, "Disallows the 'do' keyword in the project."); -- cgit v1.2.3 From 8491e2491cd6fe4ea1b5205614f43f1a525cb77f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 8 Jul 2024 14:48:59 +0100 Subject: Experiment with different uses of `-use-separate-modules` --- src/build_settings.cpp | 1 + src/llvm_backend.cpp | 6 +++++- src/llvm_backend_general.cpp | 21 ++++++++++----------- src/main.cpp | 8 +++++++- 4 files changed, 23 insertions(+), 13 deletions(-) (limited to 'src/main.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 6f4b51df8..f5a91e6ab 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -426,6 +426,7 @@ struct BuildContext { bool linker_map_file; bool use_separate_modules; + bool module_per_file; bool no_threaded_checker; bool show_debug_messages; diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 375abb0dd..8c82d7117 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -3437,7 +3437,11 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { TIME_SECTION("LLVM Add Foreign Library Paths"); lb_add_foreign_library_paths(gen); - TIME_SECTION("LLVM Object Generation"); + gbString label_object_generation = gb_string_make(heap_allocator(), "LLVM Object Generation"); + if (gen->modules.count > 1) { + label_object_generation = gb_string_append_fmt(label_object_generation, " (%d modules)", gen->modules.count); + } + TIME_SECTION_WITH_LEN(label_object_generation, gb_string_length(label_object_generation)); if (build_context.ignore_llvm_build) { gb_printf_err("LLVM object generation has been ignored!\n"); diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index db89910dd..f65bc9ac7 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -120,23 +120,22 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) { if (USE_SEPARATE_MODULES) { for (auto const &entry : gen->info->packages) { AstPackage *pkg = entry.value; - #if 1 auto m = gb_alloc_item(permanent_allocator(), lbModule); m->pkg = pkg; m->gen = gen; map_set(&gen->modules, cast(void *)pkg, m); lb_init_module(m, c); - #else - // NOTE(bill): Probably per file is not a good idea, so leave this for later - for (AstFile *file : pkg->files) { - auto m = gb_alloc_item(permanent_allocator(), lbModule); - m->file = file; - m->pkg = pkg; - m->gen = gen; - map_set(&gen->modules, cast(void *)file, m); - lb_init_module(m, c); + if (build_context.module_per_file) { + // NOTE(bill): Probably per file is not a good idea, so leave this for later + for (AstFile *file : pkg->files) { + auto m = gb_alloc_item(permanent_allocator(), lbModule); + m->file = file; + m->pkg = pkg; + m->gen = gen; + map_set(&gen->modules, cast(void *)file, m); + lb_init_module(m, c); + } } - #endif } } diff --git a/src/main.cpp b/src/main.cpp index f80da8c68..8ea0ae62c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -390,6 +390,7 @@ enum BuildFlagKind { BuildFlag_InternalIgnoreLazy, BuildFlag_InternalIgnoreLLVMBuild, BuildFlag_InternalIgnorePanic, + BuildFlag_InternalModulePerFile, BuildFlag_Tilde, @@ -591,7 +592,8 @@ gb_internal bool parse_build_flags(Array args) { 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); - add_flag(&build_flags, BuildFlag_InternalIgnorePanic, str_lit("internal-ignore-panic"), BuildFlagParam_None, Command_all); + add_flag(&build_flags, BuildFlag_InternalIgnorePanic, str_lit("internal-ignore-panic"), BuildFlagParam_None, Command_all); + add_flag(&build_flags, BuildFlag_InternalModulePerFile, str_lit("internal-module-per-file"), BuildFlagParam_None, Command_all); #if ALLOW_TILDE add_flag(&build_flags, BuildFlag_Tilde, str_lit("tilde"), BuildFlagParam_None, Command__does_build); @@ -1408,6 +1410,10 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_InternalIgnorePanic: build_context.ignore_panic = true; break; + case BuildFlag_InternalModulePerFile: + build_context.module_per_file = true; + break; + case BuildFlag_Tilde: build_context.tilde_backend = true; break; -- cgit v1.2.3 From 2a219fa8305f2d246d5b3ae5b2b1e25c75bb4332 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 8 Jul 2024 15:13:40 +0100 Subject: Correct `-use-separate-module` behaviour --- src/entity.cpp | 3 +++ src/llvm_backend.cpp | 2 +- src/llvm_backend_general.cpp | 3 ++- src/main.cpp | 7 ++++++- src/timings.cpp | 7 ++++--- 5 files changed, 16 insertions(+), 6 deletions(-) (limited to 'src/main.cpp') diff --git a/src/entity.cpp b/src/entity.cpp index 8f55c1faf..9dee9cbe7 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -338,6 +338,9 @@ gb_internal Entity *alloc_entity(EntityKind kind, Scope *scope, Token token, Typ entity->token = token; entity->type = type; entity->id = 1 + global_entity_id.fetch_add(1); + if (token.pos.file_id) { + entity->file = thread_safe_get_ast_file_from_id(token.pos.file_id); + } return entity; } diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 8c82d7117..9818c5435 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -3439,7 +3439,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { gbString label_object_generation = gb_string_make(heap_allocator(), "LLVM Object Generation"); if (gen->modules.count > 1) { - label_object_generation = gb_string_append_fmt(label_object_generation, " (%d modules)", gen->modules.count); + label_object_generation = gb_string_append_fmt(label_object_generation, " (%td modules)", gen->modules.count); } TIME_SECTION_WITH_LEN(label_object_generation, gb_string_length(label_object_generation)); diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index f65bc9ac7..77f78a24c 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -118,6 +118,7 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) { map_init(&gen->anonymous_proc_lits, 1024); if (USE_SEPARATE_MODULES) { + bool module_per_file = build_context.module_per_file && build_context.optimization_level <= 0; for (auto const &entry : gen->info->packages) { AstPackage *pkg = entry.value; auto m = gb_alloc_item(permanent_allocator(), lbModule); @@ -125,7 +126,7 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) { m->gen = gen; map_set(&gen->modules, cast(void *)pkg, m); lb_init_module(m, c); - if (build_context.module_per_file) { + if (module_per_file) { // NOTE(bill): Probably per file is not a good idea, so leave this for later for (AstFile *file : pkg->files) { auto m = gb_alloc_item(permanent_allocator(), lbModule); diff --git a/src/main.cpp b/src/main.cpp index 8ea0ae62c..89ce93b18 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3304,11 +3304,16 @@ int main(int arg_count, char const **arg_ptr) { } else #endif { - MAIN_TIME_SECTION("LLVM API Code Gen"); lbGenerator *gen = gb_alloc_item(permanent_allocator(), lbGenerator); if (!lb_init_generator(gen, checker)) { return 1; } + + gbString label_code_gen = gb_string_make(heap_allocator(), "LLVM API Code Gen"); + if (gen->modules.count > 1) { + label_code_gen = gb_string_append_fmt(label_code_gen, " ( %4td modules )", gen->modules.count); + } + MAIN_TIME_SECTION_WITH_LEN(label_code_gen, gb_string_length(label_code_gen)); if (lb_generate_code(gen)) { switch (build_context.build_mode) { case BuildMode_Executable: diff --git a/src/timings.cpp b/src/timings.cpp index 712e804cb..3f8402b36 100644 --- a/src/timings.cpp +++ b/src/timings.cpp @@ -146,9 +146,10 @@ gb_internal f64 time_stamp_as_us(TimeStamp const &ts, u64 freq) { return 1000000.0*time_stamp_as_s(ts, freq); } -#define MAIN_TIME_SECTION(str) do { debugf("[Section] %s\n", str); timings_start_section(&global_timings, str_lit(str)); } while (0) -#define TIME_SECTION(str) do { debugf("[Section] %s\n", str); if (build_context.show_more_timings) timings_start_section(&global_timings, str_lit(str)); } while (0) -#define TIME_SECTION_WITH_LEN(str, len) do { debugf("[Section] %s\n", str); if (build_context.show_more_timings) timings_start_section(&global_timings, make_string((u8 *)str, len)); } while (0) +#define MAIN_TIME_SECTION(str) do { debugf("[Section] %s\n", str); timings_start_section(&global_timings, str_lit(str)); } while (0) +#define MAIN_TIME_SECTION_WITH_LEN(str, len) do { debugf("[Section] %s\n", str); timings_start_section(&global_timings, make_string((u8 *)str, len)); } while (0) +#define TIME_SECTION(str) do { debugf("[Section] %s\n", str); if (build_context.show_more_timings) timings_start_section(&global_timings, str_lit(str)); } while (0) +#define TIME_SECTION_WITH_LEN(str, len) do { debugf("[Section] %s\n", str); if (build_context.show_more_timings) timings_start_section(&global_timings, make_string((u8 *)str, len)); } while (0) enum TimingUnit { -- cgit v1.2.3 From 564d5af8b2094e629793b504168fa40432bd4f1c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 8 Jul 2024 16:12:22 +0100 Subject: Default to `-o:none` for all builds --- src/build_settings.cpp | 2 +- src/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/main.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index f5a91e6ab..c8c83422f 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1633,7 +1633,7 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta } } - if (bc->ODIN_DEBUG && !bc->custom_optimization_level) { + if (!bc->custom_optimization_level) { // NOTE(bill): when building with `-debug` but not specifying an optimization level // default to `-o:none` to improve the debug symbol generation by default bc->optimization_level = -1; // -o:none diff --git a/src/main.cpp b/src/main.cpp index 89ce93b18..606b2b592 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2112,7 +2112,7 @@ gb_internal void print_show_help(String const arg0, String const &command) { if (LB_USE_NEW_PASS_SYSTEM) { print_usage_line(3, "-o:aggressive"); } - print_usage_line(2, "The default is -o:minimal."); + print_usage_line(2, "The default is -o:none."); print_usage_line(0, ""); } -- cgit v1.2.3 From 48aef5016499291996f0710449a26f1f92078d51 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 8 Jul 2024 17:46:10 +0100 Subject: Add #load cache files to `-export-dependencies:json` --- src/check_builtin.cpp | 3 ++ src/main.cpp | 92 ++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 72 insertions(+), 23 deletions(-) (limited to 'src/main.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 5a8d9b782..eec01b497 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1296,6 +1296,9 @@ gb_internal LoadDirectiveResult check_load_directive(CheckerContext *c, Operand gb_internal int file_cache_sort_cmp(void const *x, void const *y) { LoadFileCache const *a = *(LoadFileCache const **)(x); LoadFileCache const *b = *(LoadFileCache const **)(y); + if (a == b) { + return 0; + } return string_compare(a->path, b->path); } diff --git a/src/main.cpp b/src/main.cpp index 606b2b592..bbb326af3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1918,7 +1918,16 @@ gb_internal void show_timings(Checker *c, Timings *t) { } } -gb_internal void export_dependencies(Parser *p) { +gb_internal GB_COMPARE_PROC(file_path_cmp) { + AstFile *x = *(AstFile **)a; + AstFile *y = *(AstFile **)b; + if (x == y) { + return 0; + } + return string_compare(x->fullpath, y->fullpath); +} + +gb_internal void export_dependencies(Checker *c) { GB_ASSERT(build_context.export_dependencies_format != DependenciesExportUnspecified); if (build_context.export_dependencies_file.len <= 0) { @@ -1927,6 +1936,8 @@ gb_internal void export_dependencies(Parser *p) { return; } + Parser *p = c->parser; + gbFile f = {}; char * fileName = (char *)build_context.export_dependencies_file.text; gbFileError err = gb_file_open_mode(&f, gbFileMode_Write, fileName); @@ -1937,6 +1948,26 @@ gb_internal void export_dependencies(Parser *p) { } defer (gb_file_close(&f)); + + auto files = array_make(heap_allocator()); + for (AstPackage *pkg : p->packages) { + for (AstFile *f : pkg->files) { + array_add(&files, f); + } + } + array_sort(files, file_path_cmp); + + + auto load_files = array_make(heap_allocator()); + for (auto const &entry : c->info.load_file_cache) { + auto *cache = entry.value; + if (!cache || !cache->exists) { + continue; + } + array_add(&load_files, cache); + } + array_sort(files, file_cache_sort_cmp); + if (build_context.export_dependencies_format == DependenciesExportMake) { String exe_name = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Output]); defer (gb_free(heap_allocator(), exe_name.text)); @@ -1945,26 +1976,25 @@ gb_internal void export_dependencies(Parser *p) { isize current_line_length = exe_name.len + 1; - for(AstPackage *pkg : p->packages) { - for(AstFile *file : pkg->files) { - /* Arbitrary line break value. Maybe make this better? */ - if (current_line_length >= 80-2) { - gb_file_write(&f, " \\\n ", 4); - current_line_length = 1; - } + for_array(i, files) { + AstFile *file = files[i]; + /* Arbitrary line break value. Maybe make this better? */ + if (current_line_length >= 80-2) { + gb_file_write(&f, " \\\n ", 4); + current_line_length = 1; + } - gb_file_write(&f, " ", 1); - current_line_length++; + gb_file_write(&f, " ", 1); + current_line_length++; - for (isize k = 0; k < file->fullpath.len; k++) { - char part = file->fullpath.text[k]; - if (part == ' ') { - gb_file_write(&f, "\\", 1); - current_line_length++; - } - gb_file_write(&f, &part, 1); + for (isize k = 0; k < file->fullpath.len; k++) { + char part = file->fullpath.text[k]; + if (part == ' ') { + gb_file_write(&f, "\\", 1); current_line_length++; } + gb_file_write(&f, &part, 1); + current_line_length++; } } @@ -1974,14 +2004,30 @@ gb_internal void export_dependencies(Parser *p) { gb_fprintf(&f, "\t\"source_files\": [\n"); - for(AstPackage *pkg : p->packages) { - for(AstFile *file : pkg->files) { - gb_fprintf(&f, "\t\t\"%.*s\",\n", LIT(file->fullpath)); + for_array(i, files) { + AstFile *file = files[i]; + gb_fprintf(&f, "\t\t\"%.*s\"", LIT(file->fullpath)); + if (i+1 == files.count) { + gb_fprintf(&f, ","); } + gb_fprintf(&f, "\n"); } gb_fprintf(&f, "\t],\n"); + gb_fprintf(&f, "\t\"load_files\": [\n"); + + for_array(i, load_files) { + LoadFileCache *cache = load_files[i]; + gb_fprintf(&f, "\t\t\"%.*s\"", LIT(cache->path)); + if (i+1 == load_files.count) { + gb_fprintf(&f, ","); + } + gb_fprintf(&f, "\n"); + } + + gb_fprintf(&f, "\t]\n"); + gb_fprintf(&f, "}\n"); } } @@ -3295,7 +3341,7 @@ int main(int arg_count, char const **arg_ptr) { } if (build_context.export_dependencies_format != DependenciesExportUnspecified) { - export_dependencies(parser); + export_dependencies(checker); } return result; } @@ -3326,7 +3372,7 @@ int main(int arg_count, char const **arg_ptr) { } if (build_context.export_dependencies_format != DependenciesExportUnspecified) { - export_dependencies(parser); + export_dependencies(checker); } return result; } @@ -3342,7 +3388,7 @@ int main(int arg_count, char const **arg_ptr) { } if (build_context.export_dependencies_format != DependenciesExportUnspecified) { - export_dependencies(parser); + export_dependencies(checker); } if (run_output) { -- cgit v1.2.3 From 87ac68fcf2b5fcaa02118929b820e61bbd8c10c4 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 8 Jul 2024 23:39:14 +0100 Subject: Add `-internal-cached` --- src/build_settings.cpp | 10 +- src/cached.cpp | 213 +++++++++++++++++++++++++++++++++++++++++++ src/llvm_backend.cpp | 4 +- src/llvm_backend_general.cpp | 22 ++--- src/main.cpp | 26 +++++- src/string.cpp | 7 ++ 6 files changed, 265 insertions(+), 17 deletions(-) create mode 100644 src/cached.cpp (limited to 'src/main.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index c8c83422f..be896f6fa 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -326,7 +326,12 @@ enum SanitizerFlags : u32 { SanitizerFlag_Thread = 1u<<2, }; - +struct BuildCacheData { + u64 crc; + String cache_dir; + String manifest_path; + bool copy_already_done; +}; // This stores the information for the specify architecture of this build struct BuildContext { @@ -427,6 +432,9 @@ struct BuildContext { bool use_separate_modules; bool module_per_file; + bool cached; + BuildCacheData build_cache_data; + bool no_threaded_checker; bool show_debug_messages; diff --git a/src/cached.cpp b/src/cached.cpp new file mode 100644 index 000000000..89158ccbb --- /dev/null +++ b/src/cached.cpp @@ -0,0 +1,213 @@ +gb_internal GB_COMPARE_PROC(cached_file_cmp) { + String const &x = *(String *)a; + String const &y = *(String *)b; + return string_compare(x, y); +} + + +u64 crc64_with_seed(void const *data, isize len, u64 seed) { + isize remaining; + u64 result = ~seed; + u8 const *c = cast(u8 const *)data; + for (remaining = len; remaining--; c++) { + result = (result >> 8) ^ (GB__CRC64_TABLE[(result ^ *c) & 0xff]); + } + return ~result; +} + +bool check_if_exists_file_otherwise_create(String const &str) { + char const *str_c = alloc_cstring(permanent_allocator(), str); + if (!gb_file_exists(str_c)) { + gbFile f = {}; + gb_file_create(&f, str_c); + gb_file_close(&f); + return true; + } + return false; +} + + +bool check_if_exists_directory_otherwise_create(String const &str) { +#if defined(GB_SYSTEM_WINDOWS) + String16 wstr = string_to_string16(permanent_allocator(), str); + wchar_t *wstr_c = alloc_wstring(permanent_allocator(), wstr); + return CreateDirectoryW(wstr_c, nullptr); +#else + char const *str_c = alloc_cstring(permanent_allocator(), str); + if (!gb_file_exists(str_c)) { + return false; + } + return false; +#endif +} +bool try_copy_executable_cache_internal(bool to_cache) { + String exe_name = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Output]); + defer (gb_free(heap_allocator(), exe_name.text)); + + gbString cache_name = gb_string_make(heap_allocator(), ""); + defer (gb_string_free(cache_name)); + + String cache_dir = build_context.build_cache_data.cache_dir; + + cache_name = gb_string_append_length(cache_name, cache_dir.text, cache_dir.len); + cache_name = gb_string_appendc(cache_name, "/"); + + cache_name = gb_string_appendc(cache_name, "cached-exe"); + if (selected_target_metrics) { + cache_name = gb_string_appendc(cache_name, "-"); + cache_name = gb_string_append_length(cache_name, selected_target_metrics->name.text, selected_target_metrics->name.len); + } + cache_name = gb_string_appendc(cache_name, ".bin"); + + if (to_cache) { + return gb_file_copy( + alloc_cstring(temporary_allocator(), exe_name), + cache_name, + false + ); + } else { + return gb_file_copy( + cache_name, + alloc_cstring(temporary_allocator(), exe_name), + false + ); + } +} + + + +bool try_copy_executable_to_cache(void) { + if (try_copy_executable_cache_internal(true)) { + build_context.build_cache_data.copy_already_done = true; + return true; + } + return false; +} + +bool try_copy_executable_from_cache(void) { + if (try_copy_executable_cache_internal(false)) { + build_context.build_cache_data.copy_already_done = true; + return true; + } + return false; +} + + + + +// returns false if different, true if it is the same +bool try_cached_build(Checker *c) { + Parser *p = c->parser; + + auto files = array_make(heap_allocator()); + for (AstPackage *pkg : p->packages) { + for (AstFile *f : pkg->files) { + array_add(&files, f->fullpath); + } + } + + for (auto const &entry : c->info.load_file_cache) { + auto *cache = entry.value; + if (!cache || !cache->exists) { + continue; + } + array_add(&files, cache->path); + } + + array_sort(files, cached_file_cmp); + + u64 crc = 0; + for (String const &path : files) { + crc = crc64_with_seed(path.text, path.len, crc); + } + + String base_cache_dir = build_context.build_paths[BuildPath_Output].basename; + base_cache_dir = concatenate_strings(permanent_allocator(), base_cache_dir, str_lit("/.odin-cache")); + (void)check_if_exists_directory_otherwise_create(base_cache_dir); + + gbString crc_str = gb_string_make_reserve(permanent_allocator(), 16); + crc_str = gb_string_append_fmt(crc_str, "%016llx", crc); + String cache_dir = concatenate3_strings(permanent_allocator(), base_cache_dir, str_lit("/"), make_string_c(crc_str)); + String manifest_path = concatenate3_strings(permanent_allocator(), cache_dir, str_lit("/"), str_lit("odin.manifest")); + + build_context.build_cache_data.cache_dir = cache_dir; + build_context.build_cache_data.manifest_path = manifest_path; + + if (check_if_exists_directory_otherwise_create(cache_dir)) { + goto do_write_file; + } + + if (check_if_exists_file_otherwise_create(manifest_path)) { + goto do_write_file; + } else { + // exists already + LoadedFile loaded_file = {}; + + LoadedFileError file_err = load_file_32( + alloc_cstring(temporary_allocator(), manifest_path), + &loaded_file, + false + ); + if (file_err) { + return false; + } + + String data = {cast(u8 *)loaded_file.data, loaded_file.size}; + String_Iterator it = {data, 0}; + + isize file_count = 0; + + for (; it.pos < data.len; file_count++) { + String line = string_split_iterator(&it, '\n'); + if (line.len == 0) { + break; + } + isize sep = string_index_byte(line, ' '); + if (sep < 0) { + goto do_write_file; + } + + String timestamp_str = substring(line, 0, sep); + String path_str = substring(line, sep+1, line.len); + + timestamp_str = string_trim_whitespace(timestamp_str); + path_str = string_trim_whitespace(path_str); + + if (files[file_count] != path_str) { + goto do_write_file; + } + + u64 timestamp = exact_value_to_u64(exact_value_integer_from_string(timestamp_str)); + gbFileTime last_write_time = gb_file_last_write_time(alloc_cstring(temporary_allocator(), path_str)); + if (last_write_time != timestamp) { + goto do_write_file; + } + } + + if (file_count != files.count) { + goto do_write_file; + } + + goto try_copy_executable; + } + +do_write_file:; + { + char const *manifest_path_c = alloc_cstring(temporary_allocator(), manifest_path); + gb_file_remove(manifest_path_c); + + gbFile f = {}; + defer (gb_file_close(&f)); + gb_file_open_mode(&f, gbFileMode_Write, manifest_path_c); + + for (String const &path : files) { + gbFileTime ft = gb_file_last_write_time(alloc_cstring(temporary_allocator(), path)); + gb_fprintf(&f, "%llu %.*s\n", cast(unsigned long long)ft, LIT(path)); + } + return false; + } + +try_copy_executable:; + return try_copy_executable_from_cache(); +} + diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 44b6e3839..b0df17778 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1397,8 +1397,8 @@ gb_internal void lb_create_global_procedures_and_types(lbGenerator *gen, Checker for (auto const &entry : gen->modules) { lbModule *m = entry.value; - gb_sort_array(m->global_types_to_create.data, m->global_types_to_create.count, llvm_global_entity_cmp); - gb_sort_array(m->global_procedures_to_create.data, m->global_procedures_to_create.count, llvm_global_entity_cmp); + array_sort(m->global_types_to_create, llvm_global_entity_cmp); + array_sort(m->global_procedures_to_create, llvm_global_entity_cmp); } if (do_threading) { diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 77f78a24c..bbeff562c 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -126,16 +126,17 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) { m->gen = gen; map_set(&gen->modules, cast(void *)pkg, m); lb_init_module(m, c); - if (module_per_file) { - // NOTE(bill): Probably per file is not a good idea, so leave this for later - for (AstFile *file : pkg->files) { - auto m = gb_alloc_item(permanent_allocator(), lbModule); - m->file = file; - m->pkg = pkg; - m->gen = gen; - map_set(&gen->modules, cast(void *)file, m); - lb_init_module(m, c); - } + if (!module_per_file) { + continue; + } + // NOTE(bill): Probably per file is not a good idea, so leave this for later + for (AstFile *file : pkg->files) { + auto m = gb_alloc_item(permanent_allocator(), lbModule); + m->file = file; + m->pkg = pkg; + m->gen = gen; + map_set(&gen->modules, cast(void *)file, m); + lb_init_module(m, c); } } } @@ -144,7 +145,6 @@ gb_internal bool lb_init_generator(lbGenerator *gen, Checker *c) { map_set(&gen->modules, cast(void *)1, &gen->default_module); lb_init_module(&gen->default_module, c); - for (auto const &entry : gen->modules) { lbModule *m = entry.value; LLVMContextRef ctx = LLVMGetModuleContext(m->mod); diff --git a/src/main.cpp b/src/main.cpp index bbb326af3..006a7ddbc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -71,6 +71,8 @@ gb_global Timings global_timings = {0}; #include "checker.cpp" #include "docs.cpp" +#include "cached.cpp" + #include "linker.cpp" #if defined(GB_SYSTEM_WINDOWS) && defined(ODIN_TILDE_BACKEND) @@ -391,6 +393,7 @@ enum BuildFlagKind { BuildFlag_InternalIgnoreLLVMBuild, BuildFlag_InternalIgnorePanic, BuildFlag_InternalModulePerFile, + BuildFlag_InternalCached, BuildFlag_Tilde, @@ -594,6 +597,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_InternalIgnoreLLVMBuild, str_lit("internal-ignore-llvm-build"),BuildFlagParam_None, Command_all); add_flag(&build_flags, BuildFlag_InternalIgnorePanic, str_lit("internal-ignore-panic"), BuildFlagParam_None, Command_all); add_flag(&build_flags, BuildFlag_InternalModulePerFile, str_lit("internal-module-per-file"), BuildFlagParam_None, Command_all); + add_flag(&build_flags, BuildFlag_InternalCached, str_lit("internal-cached"), BuildFlagParam_None, Command_all); #if ALLOW_TILDE add_flag(&build_flags, BuildFlag_Tilde, str_lit("tilde"), BuildFlagParam_None, Command__does_build); @@ -1413,6 +1417,10 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_InternalModulePerFile: build_context.module_per_file = true; break; + case BuildFlag_InternalCached: + build_context.cached = true; + build_context.use_separate_modules = true; + break; case BuildFlag_Tilde: build_context.tilde_backend = true; @@ -1921,9 +1929,6 @@ gb_internal void show_timings(Checker *c, Timings *t) { gb_internal GB_COMPARE_PROC(file_path_cmp) { AstFile *x = *(AstFile **)a; AstFile *y = *(AstFile **)b; - if (x == y) { - return 0; - } return string_compare(x->fullpath, y->fullpath); } @@ -3322,6 +3327,13 @@ int main(int arg_count, char const **arg_ptr) { return 0; } + if (build_context.cached) { + MAIN_TIME_SECTION("check cached build"); + if (try_cached_build(checker)) { + goto end_of_code_gen; + } + } + #if ALLOW_TILDE if (build_context.tilde_backend) { LinkerData linker_data = {}; @@ -3383,6 +3395,8 @@ int main(int arg_count, char const **arg_ptr) { remove_temp_files(gen); } +end_of_code_gen:; + if (build_context.show_timings) { show_timings(checker, &global_timings); } @@ -3391,6 +3405,12 @@ int main(int arg_count, char const **arg_ptr) { export_dependencies(checker); } + + if (!build_context.build_cache_data.copy_already_done && + build_context.cached) { + try_copy_executable_to_cache(); + } + if (run_output) { String exe_name = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Output]); defer (gb_free(heap_allocator(), exe_name.text)); diff --git a/src/string.cpp b/src/string.cpp index ab08e3d4a..a39d93ad9 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -88,6 +88,13 @@ gb_internal char *alloc_cstring(gbAllocator a, String s) { return c_str; } +gb_internal wchar_t *alloc_wstring(gbAllocator a, String16 s) { + wchar_t *c_str = gb_alloc_array(a, wchar_t, s.len+1); + gb_memmove(c_str, s.text, s.len*2); + c_str[s.len] = '\0'; + return c_str; +} + gb_internal gb_inline bool str_eq_ignore_case(String const &a, String const &b) { if (a.len == b.len) { -- cgit v1.2.3 From ccdad8b8dd3af934ef12e833b79c239c8a04895e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 9 Jul 2024 13:31:54 +0100 Subject: Add `odin clear-cache` --- src/cached.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 2 ++ 2 files changed, 83 insertions(+) (limited to 'src/main.cpp') diff --git a/src/cached.cpp b/src/cached.cpp index 62c7641e5..83950c82b 100644 --- a/src/cached.cpp +++ b/src/cached.cpp @@ -4,6 +4,87 @@ gb_internal GB_COMPARE_PROC(cached_file_cmp) { return string_compare(x, y); } +bool recursively_delete_directory(wchar_t *wpath_c) { +#if defined(GB_SYSTEM_WINDOWS) + auto const is_dots_w = [](wchar_t const *str) -> bool { + if (!str) { + return false; + } + return wcscmp(str, L".") == 0 || wcscmp(str, L"..") == 0; + }; + + TEMPORARY_ALLOCATOR_GUARD(); + + wchar_t dir_path[MAX_PATH] = {}; + wchar_t filename[MAX_PATH] = {}; + wcscpy(dir_path, wpath_c); + wcscat(dir_path, L"\\*"); + + wcscpy(filename, wpath_c); + wcscat(filename, L"\\"); + + + WIN32_FIND_DATAW find_file_data = {}; + HANDLE hfind = FindFirstFileW(dir_path, &find_file_data); + if (hfind == INVALID_HANDLE_VALUE) { + return false; + } + defer (FindClose(hfind)); + + wcscpy(dir_path, filename); + + for (;;) { + if (FindNextFileW(hfind, &find_file_data)) { + if (is_dots_w(find_file_data.cFileName)) { + continue; + } + wcscat(filename, find_file_data.cFileName); + + if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + if (!recursively_delete_directory(filename)) { + return false; + } + RemoveDirectoryW(filename); + wcscpy(filename, dir_path); + } else { + if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { + _wchmod(filename, _S_IWRITE); + } + if (!DeleteFileW(filename)) { + return false; + } + wcscpy(filename, dir_path); + } + } else { + if (GetLastError() == ERROR_NO_MORE_FILES) { + break; + } + return false; + } + } + + + return RemoveDirectoryW(wpath_c); +#else + return false; +#endif +} + +bool recursively_delete_directory(String const &path) { +#if defined(GB_SYSTEM_WINDOWS) + String16 wpath = string_to_string16(permanent_allocator(), path); + wchar_t *wpath_c = alloc_wstring(permanent_allocator(), wpath); + return recursively_delete_directory(wpath_c); +#else + return false; +#endif +} + +int try_clear_cache(void) { + bool ok = recursively_delete_directory(str_lit(".odin-cache")); + return ok ? 0 : 1; +} + u64 crc64_with_seed(void const *data, isize len, u64 seed) { isize remaining; diff --git a/src/main.cpp b/src/main.cpp index 006a7ddbc..49c34014b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3057,6 +3057,8 @@ int main(int arg_count, char const **arg_ptr) { } else if (command == "root") { gb_printf("%.*s", LIT(odin_root_dir())); return 0; + } else if (command == "clear-cache") { + return try_clear_cache(); } else { String argv1 = {}; if (args.count > 1) { -- cgit v1.2.3 From 886ee66e7fcabbd09c20fd55d98051e3854dfd76 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 9 Jul 2024 14:16:56 +0100 Subject: Cache files, env, and args --- src/build_settings.cpp | 7 +- src/cached.cpp | 170 +++++++++++++++++++++++++++++++++++++++++-------- src/main.cpp | 13 +++- src/parser.cpp | 10 +++ src/parser.hpp | 4 ++ 5 files changed, 175 insertions(+), 29 deletions(-) (limited to 'src/main.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index be896f6fa..28ca0f088 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -329,7 +329,12 @@ enum SanitizerFlags : u32 { struct BuildCacheData { u64 crc; String cache_dir; - String manifest_path; + + // manifests + String files_path; + String args_path; + String env_path; + bool copy_already_done; }; diff --git a/src/cached.cpp b/src/cached.cpp index ab6d99848..da72e9989 100644 --- a/src/cached.cpp +++ b/src/cached.cpp @@ -1,4 +1,4 @@ -gb_internal GB_COMPARE_PROC(cached_file_cmp) { +gb_internal GB_COMPARE_PROC(string_cmp) { String const &x = *(String *)a; String const &y = *(String *)b; return string_compare(x, y); @@ -182,7 +182,9 @@ bool try_copy_executable_from_cache(void) { // returns false if different, true if it is the same -bool try_cached_build(Checker *c) { +bool try_cached_build(Checker *c, Array const &args) { + TEMPORARY_ALLOCATOR_GUARD(); + Parser *p = c->parser; auto files = array_make(heap_allocator()); @@ -200,7 +202,7 @@ bool try_cached_build(Checker *c) { array_add(&files, cache->path); } - array_sort(files, cached_file_cmp); + array_sort(files, string_cmp); u64 crc = 0; for (String const &path : files) { @@ -213,28 +215,58 @@ bool try_cached_build(Checker *c) { gbString crc_str = gb_string_make_reserve(permanent_allocator(), 16); crc_str = gb_string_append_fmt(crc_str, "%016llx", crc); - String cache_dir = concatenate3_strings(permanent_allocator(), base_cache_dir, str_lit("/"), make_string_c(crc_str)); - String manifest_path = concatenate3_strings(permanent_allocator(), cache_dir, str_lit("/"), str_lit("odin.manifest")); + String cache_dir = concatenate3_strings(permanent_allocator(), base_cache_dir, str_lit("/"), make_string_c(crc_str)); + String files_path = concatenate3_strings(permanent_allocator(), cache_dir, str_lit("/"), str_lit("files.manifest")); + String args_path = concatenate3_strings(permanent_allocator(), cache_dir, str_lit("/"), str_lit("args.manifest")); + String env_path = concatenate3_strings(permanent_allocator(), cache_dir, str_lit("/"), str_lit("env.manifest")); build_context.build_cache_data.cache_dir = cache_dir; - build_context.build_cache_data.manifest_path = manifest_path; + build_context.build_cache_data.files_path = files_path; + build_context.build_cache_data.args_path = args_path; + build_context.build_cache_data.env_path = env_path; + + auto envs = array_make(heap_allocator()); + defer (array_free(&envs)); + { + #if defined(GB_SYSTEM_WINDOWS) + wchar_t *strings = GetEnvironmentStringsW(); + defer (FreeEnvironmentStringsW(strings)); + + wchar_t *curr_string = strings; + while (curr_string && *curr_string) { + String16 wstr = make_string16_c(curr_string); + curr_string += wstr.len+1; + String str = string16_to_string(temporary_allocator(), wstr); + array_add(&envs, str); + } + #endif + } + array_sort(envs, string_cmp); if (check_if_exists_directory_otherwise_create(cache_dir)) { - goto do_write_file; + goto write_cache; } - if (check_if_exists_file_otherwise_create(manifest_path)) { - goto do_write_file; - } else { + if (check_if_exists_file_otherwise_create(files_path)) { + goto write_cache; + } + if (check_if_exists_file_otherwise_create(args_path)) { + goto write_cache; + } + if (check_if_exists_file_otherwise_create(env_path)) { + goto write_cache; + } + + { // exists already LoadedFile loaded_file = {}; LoadedFileError file_err = load_file_32( - alloc_cstring(temporary_allocator(), manifest_path), + alloc_cstring(temporary_allocator(), files_path), &loaded_file, false ); - if (file_err) { + if (file_err > LoadedFile_Empty) { return false; } @@ -250,7 +282,7 @@ bool try_cached_build(Checker *c) { } isize sep = string_index_byte(line, ' '); if (sep < 0) { - goto do_write_file; + goto write_cache; } String timestamp_str = substring(line, 0, sep); @@ -260,43 +292,131 @@ bool try_cached_build(Checker *c) { path_str = string_trim_whitespace(path_str); if (file_count >= files.count) { - goto do_write_file; + goto write_cache; } if (files[file_count] != path_str) { - goto do_write_file; + goto write_cache; } u64 timestamp = exact_value_to_u64(exact_value_integer_from_string(timestamp_str)); gbFileTime last_write_time = gb_file_last_write_time(alloc_cstring(temporary_allocator(), path_str)); if (last_write_time != timestamp) { - goto do_write_file; + goto write_cache; } } if (file_count != files.count) { - goto do_write_file; + goto write_cache; } + } + { + LoadedFile loaded_file = {}; - goto try_copy_executable; + LoadedFileError file_err = load_file_32( + alloc_cstring(temporary_allocator(), args_path), + &loaded_file, + false + ); + if (file_err > LoadedFile_Empty) { + return false; + } + + String data = {cast(u8 *)loaded_file.data, loaded_file.size}; + String_Iterator it = {data, 0}; + + isize args_count = 0; + + for (; it.pos < data.len; args_count++) { + String line = string_split_iterator(&it, '\n'); + line = string_trim_whitespace(line); + if (line.len == 0) { + break; + } + if (args_count >= args.count) { + goto write_cache; + } + + if (line != args[args_count]) { + goto write_cache; + } + } } + { + LoadedFile loaded_file = {}; -do_write_file:; + LoadedFileError file_err = load_file_32( + alloc_cstring(temporary_allocator(), env_path), + &loaded_file, + false + ); + if (file_err > LoadedFile_Empty) { + return false; + } + + String data = {cast(u8 *)loaded_file.data, loaded_file.size}; + String_Iterator it = {data, 0}; + + isize env_count = 0; + + for (; it.pos < data.len; env_count++) { + String line = string_split_iterator(&it, '\n'); + line = string_trim_whitespace(line); + if (line.len == 0) { + break; + } + if (env_count >= envs.count) { + goto write_cache; + } + + if (line != envs[env_count]) { + goto write_cache; + } + } + } + + return try_copy_executable_from_cache(); + +write_cache:; { - char const *manifest_path_c = alloc_cstring(temporary_allocator(), manifest_path); - gb_file_remove(manifest_path_c); + char const *path_c = alloc_cstring(temporary_allocator(), files_path); + gb_file_remove(path_c); gbFile f = {}; defer (gb_file_close(&f)); - gb_file_open_mode(&f, gbFileMode_Write, manifest_path_c); + gb_file_open_mode(&f, gbFileMode_Write, path_c); for (String const &path : files) { gbFileTime ft = gb_file_last_write_time(alloc_cstring(temporary_allocator(), path)); gb_fprintf(&f, "%llu %.*s\n", cast(unsigned long long)ft, LIT(path)); } - return false; } + { + char const *path_c = alloc_cstring(temporary_allocator(), args_path); + gb_file_remove(path_c); -try_copy_executable:; - return try_copy_executable_from_cache(); + gbFile f = {}; + defer (gb_file_close(&f)); + gb_file_open_mode(&f, gbFileMode_Write, path_c); + + for (String const &arg : args) { + String targ = string_trim_whitespace(arg); + gb_fprintf(&f, "%.*s\n", LIT(targ)); + } + } + { + char const *path_c = alloc_cstring(temporary_allocator(), env_path); + gb_file_remove(path_c); + + gbFile f = {}; + defer (gb_file_close(&f)); + gb_file_open_mode(&f, gbFileMode_Write, path_c); + + for (String const &env : envs) { + gb_fprintf(&f, "%.*s\n", LIT(env)); + } + } + + + return false; } diff --git a/src/main.cpp b/src/main.cpp index 49c34014b..f2312f248 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3271,12 +3271,19 @@ int main(int arg_count, char const **arg_ptr) { print_all_errors(); } - MAIN_TIME_SECTION("type check"); checker->parser = parser; init_checker(checker); - defer (destroy_checker(checker)); + defer (destroy_checker(checker)); // this is here because of a `goto` + + if (build_context.cached && parser->total_seen_load_directive_count.load() == 0) { + MAIN_TIME_SECTION("check cached build (pre-semantic check)"); + if (try_cached_build(checker, args)) { + goto end_of_code_gen; + } + } + MAIN_TIME_SECTION("type check"); check_parsed_files(checker); check_defines(&build_context, checker); if (any_errors()) { @@ -3331,7 +3338,7 @@ int main(int arg_count, char const **arg_ptr) { if (build_context.cached) { MAIN_TIME_SECTION("check cached build"); - if (try_cached_build(checker)) { + if (try_cached_build(checker, args)) { goto end_of_code_gen; } } diff --git a/src/parser.cpp b/src/parser.cpp index 548e46cbe..eb012e980 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -787,6 +787,9 @@ gb_internal Ast *ast_basic_directive(AstFile *f, Token token, Token name) { Ast *result = alloc_ast_node(f, Ast_BasicDirective); result->BasicDirective.token = token; result->BasicDirective.name = name; + if (string_starts_with(name.string, str_lit("load"))) { + f->seen_load_directive_count++; + } return result; } @@ -6576,6 +6579,13 @@ gb_internal ParseFileError parse_packages(Parser *p, String init_filename) { } } } + + for (AstPackage *pkg : p->packages) { + for (AstFile *file : pkg->files) { + p->total_seen_load_directive_count += file->seen_load_directive_count; + } + } + return ParseFile_None; } diff --git a/src/parser.hpp b/src/parser.hpp index 521fd7a37..86b3393af 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -140,6 +140,8 @@ struct AstFile { // This is effectively a queue but does not require any multi-threading capabilities Array delayed_decls_queues[AstDelayQueue_COUNT]; + std::atomic seen_load_directive_count; + #define PARSER_MAX_FIX_COUNT 6 isize fix_count; TokenPos fix_prev_pos; @@ -210,6 +212,8 @@ struct Parser { std::atomic total_token_count; std::atomic total_line_count; + std::atomic total_seen_load_directive_count; + // TODO(bill): What should this mutex be per? // * Parser // * Package -- cgit v1.2.3 From 14dc3598b4ef4b32e4fd1bcbf3f6f3ce3e40a9cf Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 9 Jul 2024 14:33:01 +0100 Subject: Add `gb_internal` to procedures --- src/cached.cpp | 23 +++++++++++------------ src/main.cpp | 2 +- 2 files changed, 12 insertions(+), 13 deletions(-) (limited to 'src/main.cpp') diff --git a/src/cached.cpp b/src/cached.cpp index 59c68c6ee..0cf9dcf5f 100644 --- a/src/cached.cpp +++ b/src/cached.cpp @@ -4,7 +4,7 @@ gb_internal GB_COMPARE_PROC(string_cmp) { return string_compare(x, y); } -bool recursively_delete_directory(wchar_t *wpath_c) { +gb_internal bool recursively_delete_directory(wchar_t *wpath_c) { #if defined(GB_SYSTEM_WINDOWS) auto const is_dots_w = [](wchar_t const *str) -> bool { if (!str) { @@ -70,7 +70,7 @@ bool recursively_delete_directory(wchar_t *wpath_c) { #endif } -bool recursively_delete_directory(String const &path) { +gb_internal bool recursively_delete_directory(String const &path) { #if defined(GB_SYSTEM_WINDOWS) String16 wpath = string_to_string16(permanent_allocator(), path); wchar_t *wpath_c = alloc_wstring(permanent_allocator(), wpath); @@ -80,13 +80,12 @@ bool recursively_delete_directory(String const &path) { #endif } -int try_clear_cache(void) { - bool ok = recursively_delete_directory(str_lit(".odin-cache")); - return ok ? 0 : 1; +gb_internal bool try_clear_cache(void) { + return recursively_delete_directory(str_lit(".odin-cache")); } -u64 crc64_with_seed(void const *data, isize len, u64 seed) { +gb_internal u64 crc64_with_seed(void const *data, isize len, u64 seed) { isize remaining; u64 result = ~seed; u8 const *c = cast(u8 const *)data; @@ -96,7 +95,7 @@ u64 crc64_with_seed(void const *data, isize len, u64 seed) { return ~result; } -bool check_if_exists_file_otherwise_create(String const &str) { +gb_internal bool check_if_exists_file_otherwise_create(String const &str) { char const *str_c = alloc_cstring(permanent_allocator(), str); if (!gb_file_exists(str_c)) { gbFile f = {}; @@ -108,7 +107,7 @@ bool check_if_exists_file_otherwise_create(String const &str) { } -bool check_if_exists_directory_otherwise_create(String const &str) { +gb_internal bool check_if_exists_directory_otherwise_create(String const &str) { #if defined(GB_SYSTEM_WINDOWS) String16 wstr = string_to_string16(permanent_allocator(), str); wchar_t *wstr_c = alloc_wstring(permanent_allocator(), wstr); @@ -121,7 +120,7 @@ bool check_if_exists_directory_otherwise_create(String const &str) { return false; #endif } -bool try_copy_executable_cache_internal(bool to_cache) { +gb_internal bool try_copy_executable_cache_internal(bool to_cache) { String exe_name = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_Output]); defer (gb_free(heap_allocator(), exe_name.text)); @@ -162,7 +161,7 @@ bool try_copy_executable_cache_internal(bool to_cache) { -bool try_copy_executable_to_cache(void) { +gb_internal bool try_copy_executable_to_cache(void) { debugf("Cache: try_copy_executable_to_cache\n"); if (try_copy_executable_cache_internal(true)) { @@ -172,7 +171,7 @@ bool try_copy_executable_to_cache(void) { return false; } -bool try_copy_executable_from_cache(void) { +gb_internal bool try_copy_executable_from_cache(void) { debugf("Cache: try_copy_executable_from_cache\n"); if (try_copy_executable_cache_internal(false)) { @@ -186,7 +185,7 @@ bool try_copy_executable_from_cache(void) { // returns false if different, true if it is the same -bool try_cached_build(Checker *c, Array const &args) { +gb_internal bool try_cached_build(Checker *c, Array const &args) { TEMPORARY_ALLOCATOR_GUARD(); Parser *p = c->parser; diff --git a/src/main.cpp b/src/main.cpp index f2312f248..7763ccd23 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3058,7 +3058,7 @@ int main(int arg_count, char const **arg_ptr) { gb_printf("%.*s", LIT(odin_root_dir())); return 0; } else if (command == "clear-cache") { - return try_clear_cache(); + return try_clear_cache() ? 0 : 1; } else { String argv1 = {}; if (args.count > 1) { -- cgit v1.2.3 From 8dc4eca4d2940500de30dfb8fd2ec25f7c31eba7 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Tue, 9 Jul 2024 20:03:50 +0200 Subject: Allow using precompiled .res file. --- src/build_settings.cpp | 9 +++++---- src/linker.cpp | 45 +++++++++++++++++++++++++-------------------- src/main.cpp | 6 ++++-- 3 files changed, 34 insertions(+), 26 deletions(-) (limited to 'src/main.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 28ca0f088..4d3e20a7a 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1805,10 +1805,11 @@ gb_internal bool init_build_paths(String init_filename) { #if defined(GB_SYSTEM_WINDOWS) if (bc->metrics.os == TargetOs_windows) { if (bc->resource_filepath.len > 0) { - bc->build_paths[BuildPath_RC] = path_from_string(ha, bc->resource_filepath); - bc->build_paths[BuildPath_RES] = path_from_string(ha, bc->resource_filepath); - bc->build_paths[BuildPath_RC].ext = copy_string(ha, STR_LIT("rc")); - bc->build_paths[BuildPath_RES].ext = copy_string(ha, STR_LIT("res")); + bc->build_paths[BuildPath_RES] = path_from_string(ha, bc->resource_filepath); + if (!string_ends_with(bc->resource_filepath, str_lit(".res"))) { + bc->build_paths[BuildPath_RC] = path_from_string(ha, bc->resource_filepath); + bc->build_paths[BuildPath_RC].ext = copy_string(ha, STR_LIT("rc")); + } } if (bc->pdb_filepath.len > 0) { diff --git a/src/linker.cpp b/src/linker.cpp index 890a74e5a..ac3e32851 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -305,30 +305,35 @@ gb_internal i32 linker_stage(LinkerData *gen) { defer (gb_free(heap_allocator(), windows_sdk_bin_path.text)); if (!build_context.use_lld) { // msvc - String res_path = {}; + String temp_res_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_RES]); + String temp_rc_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_RC]); + defer (gb_free(heap_allocator(), temp_res_path.text)); + defer (gb_free(heap_allocator(), temp_rc_path.text)); + + String res_path = concatenate3_strings(heap_allocator(), str_lit("\""), temp_res_path, str_lit("\"")); + String rc_path = concatenate3_strings(heap_allocator(), str_lit("\""), temp_rc_path, str_lit("\"")); defer (gb_free(heap_allocator(), res_path.text)); + defer (gb_free(heap_allocator(), rc_path.text)); - // TODO(Jeroen): Add ability to reuse .res file instead of recompiling, if `-resource:file.res` is given. if (build_context.has_resource) { - String temp_res_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_RES]); - res_path = concatenate3_strings(heap_allocator(), str_lit("\""), temp_res_path, str_lit("\"")); - gb_free(heap_allocator(), temp_res_path.text); - - String temp_rc_path = path_to_string(heap_allocator(), build_context.build_paths[BuildPath_RC]); - String rc_path = concatenate3_strings(heap_allocator(), str_lit("\""), temp_rc_path, str_lit("\"")); - gb_free(heap_allocator(), temp_rc_path.text); - defer (gb_free(heap_allocator(), rc_path.text)); - - result = system_exec_command_line_app("msvc-link", - "\"%.*src.exe\" /nologo /fo %.*s %.*s", - LIT(windows_sdk_bin_path), - LIT(res_path), - LIT(rc_path) - ); - - if (result) { - return result; + if (temp_rc_path == "") { + debugf("Using precompiled resource %.*s\n", LIT(res_path)); + } else { + debugf("Compiling resource %.*s\n", LIT(res_path)); + + result = system_exec_command_line_app("msvc-link", + "\"%.*src.exe\" /nologo /fo %.*s %.*s", + LIT(windows_sdk_bin_path), + LIT(res_path), + LIT(rc_path) + ); + + if (result) { + return result; + } } + } else { + res_path = {}; } String linker_name = str_lit("link.exe"); diff --git a/src/main.cpp b/src/main.cpp index 7763ccd23..e6a0aecf0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1452,8 +1452,9 @@ gb_internal bool parse_build_flags(Array args) { String path = value.value_string; path = string_trim_whitespace(path); if (is_build_flag_path_valid(path)) { - if(!string_ends_with(path, str_lit(".rc"))) { - gb_printf_err("Invalid -resource path %.*s, missing .rc\n", LIT(path)); + bool is_resource = string_ends_with(path, str_lit(".rc")) || string_ends_with(path, str_lit(".res")); + if(!is_resource) { + gb_printf_err("Invalid -resource path %.*s, missing .rc or .res file\n", LIT(path)); bad_flags = true; break; } else if (!gb_file_exists((const char *)path.text)) { @@ -2552,6 +2553,7 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(2, "[Windows only]"); print_usage_line(2, "Defines the resource file for the executable."); print_usage_line(2, "Example: -resource:path/to/file.rc"); + print_usage_line(2, "or: -resource:path/to/file.res for a precompiled one."); print_usage_line(0, ""); print_usage_line(1, "-pdb-name:"); -- cgit v1.2.3 From 6feace23511eaf5f9fa981e8fbfd3087331a0cc4 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 14 Jul 2024 16:05:07 +0100 Subject: Add pseudo flag `-fast-build` --- src/main.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index e6a0aecf0..96225d14d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -399,6 +399,8 @@ enum BuildFlagKind { BuildFlag_Sanitize, + BuildFlag_FastBuild, + #if defined(GB_SYSTEM_WINDOWS) BuildFlag_IgnoreVsSearch, BuildFlag_ResourceFile, @@ -605,6 +607,9 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Sanitize, str_lit("sanitize"), BuildFlagParam_String, Command__does_build, true); + add_flag(&build_flags, BuildFlag_FastBuild, str_lit("fast-build"), BuildFlagParam_String, Command__does_build); + + #if defined(GB_SYSTEM_WINDOWS) add_flag(&build_flags, BuildFlag_IgnoreVsSearch, str_lit("ignore-vs-search"), BuildFlagParam_None, Command__does_build); add_flag(&build_flags, BuildFlag_ResourceFile, str_lit("resource"), BuildFlagParam_String, Command__does_build); @@ -1441,6 +1446,13 @@ gb_internal bool parse_build_flags(Array args) { } break; + + case BuildFlag_FastBuild: + build_context.custom_optimization_level = true; + build_context.optimization_level = -1; + build_context.use_separate_modules = true; + break; + #if defined(GB_SYSTEM_WINDOWS) case BuildFlag_IgnoreVsSearch: { GB_ASSERT(value.kind == ExactValue_Invalid); -- cgit v1.2.3 From e7d37607ef9ce54a80d83230150874b71d628d6d Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 14 Jul 2024 16:05:47 +0100 Subject: Fix parameter to none --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 96225d14d..388184be9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -607,7 +607,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Sanitize, str_lit("sanitize"), BuildFlagParam_String, Command__does_build, true); - add_flag(&build_flags, BuildFlag_FastBuild, str_lit("fast-build"), BuildFlagParam_String, Command__does_build); + add_flag(&build_flags, BuildFlag_FastBuild, str_lit("fast-build"), BuildFlagParam_None, Command__does_build); #if defined(GB_SYSTEM_WINDOWS) -- cgit v1.2.3 From 3311ea1c7667364af9cd3f233d1a774e50879e3c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 15 Jul 2024 00:38:10 +0100 Subject: Keep MSVC happy with secure versions of C calls --- src/cached.cpp | 16 ++++++++-------- src/checker.cpp | 4 ++++ src/common.cpp | 2 ++ src/main.cpp | 10 ---------- 4 files changed, 14 insertions(+), 18 deletions(-) (limited to 'src/main.cpp') diff --git a/src/cached.cpp b/src/cached.cpp index 7f213ba21..4ad65ee9e 100644 --- a/src/cached.cpp +++ b/src/cached.cpp @@ -17,11 +17,11 @@ gb_internal bool recursively_delete_directory(wchar_t *wpath_c) { wchar_t dir_path[MAX_PATH] = {}; wchar_t filename[MAX_PATH] = {}; - wcscpy(dir_path, wpath_c); - wcscat(dir_path, L"\\*"); + wcscpy_s(dir_path, wpath_c); + wcscat_s(dir_path, L"\\*"); - wcscpy(filename, wpath_c); - wcscat(filename, L"\\"); + wcscpy_s(filename, wpath_c); + wcscat_s(filename, L"\\"); WIN32_FIND_DATAW find_file_data = {}; @@ -31,21 +31,21 @@ gb_internal bool recursively_delete_directory(wchar_t *wpath_c) { } defer (FindClose(hfind)); - wcscpy(dir_path, filename); + wcscpy_s(dir_path, filename); for (;;) { if (FindNextFileW(hfind, &find_file_data)) { if (is_dots_w(find_file_data.cFileName)) { continue; } - wcscat(filename, find_file_data.cFileName); + wcscat_s(filename, find_file_data.cFileName); if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (!recursively_delete_directory(filename)) { return false; } RemoveDirectoryW(filename); - wcscpy(filename, dir_path); + wcscpy_s(filename, dir_path); } else { if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { _wchmod(filename, _S_IWRITE); @@ -53,7 +53,7 @@ gb_internal bool recursively_delete_directory(wchar_t *wpath_c) { if (!DeleteFileW(filename)) { return false; } - wcscpy(filename, dir_path); + wcscpy_s(filename, dir_path); } } else { if (GetLastError() == ERROR_NO_MORE_FILES) { diff --git a/src/checker.cpp b/src/checker.cpp index 0a671cc2d..0e65af211 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1117,7 +1117,11 @@ gb_internal void init_universal(void) { int minimum_os_version = 0; if (build_context.minimum_os_version_string != "") { int major, minor, revision = 0; + #if defined(GB_SYSTEM_WINDOWS) + sscanf_s(cast(const char *)(build_context.minimum_os_version_string.text), "%d.%d.%d", &major, &minor, &revision); + #else sscanf(cast(const char *)(build_context.minimum_os_version_string.text), "%d.%d.%d", &major, &minor, &revision); + #endif minimum_os_version = (major*10000)+(minor*100)+revision; } add_global_constant("ODIN_MINIMUM_OS_VERSION", t_untyped_integer, exact_value_i64(minimum_os_version)); diff --git a/src/common.cpp b/src/common.cpp index 69426e2a6..0ef39bd10 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -14,6 +14,8 @@ #undef NOMINMAX #endif +#include + #define GB_WINDOWS_H_INCLUDED #define GB_IMPLEMENTATION #include "gb/gb.h" diff --git a/src/main.cpp b/src/main.cpp index 388184be9..ef9cad873 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -399,8 +399,6 @@ enum BuildFlagKind { BuildFlag_Sanitize, - BuildFlag_FastBuild, - #if defined(GB_SYSTEM_WINDOWS) BuildFlag_IgnoreVsSearch, BuildFlag_ResourceFile, @@ -607,8 +605,6 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Sanitize, str_lit("sanitize"), BuildFlagParam_String, Command__does_build, true); - add_flag(&build_flags, BuildFlag_FastBuild, str_lit("fast-build"), BuildFlagParam_None, Command__does_build); - #if defined(GB_SYSTEM_WINDOWS) add_flag(&build_flags, BuildFlag_IgnoreVsSearch, str_lit("ignore-vs-search"), BuildFlagParam_None, Command__does_build); @@ -1447,12 +1443,6 @@ gb_internal bool parse_build_flags(Array args) { break; - case BuildFlag_FastBuild: - build_context.custom_optimization_level = true; - build_context.optimization_level = -1; - build_context.use_separate_modules = true; - break; - #if defined(GB_SYSTEM_WINDOWS) case BuildFlag_IgnoreVsSearch: { GB_ASSERT(value.kind == ExactValue_Invalid); -- cgit v1.2.3 From c64702ae5ad57240743fc425bb5029fb9c1cc02e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 15 Jul 2024 00:43:46 +0100 Subject: Make `-use-separate-modules` the default behaviour for `-o:none` and `-o:minimal` --- src/build_settings.cpp | 7 +++++++ src/main.cpp | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 32640d732..47f7bf5ba 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1658,6 +1658,13 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta bc->optimization_level = gb_clamp(bc->optimization_level, -1, 3); + if (bc->optimization_level <= 0) { + if (!is_arch_wasm()) { + bc->use_separate_modules = true; + } + } + + // TODO: Static map calls are bugged on `amd64sysv` abi. if (bc->metrics.os != TargetOs_windows && bc->metrics.arch == TargetArch_amd64) { // ENFORCE DYNAMIC MAP CALLS diff --git a/src/main.cpp b/src/main.cpp index ef9cad873..da8322476 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2312,9 +2312,9 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(0, ""); print_usage_line(1, "-use-separate-modules"); - print_usage_line(1, "[EXPERIMENTAL]"); print_usage_line(2, "The backend generates multiple build units which are then linked together."); print_usage_line(2, "Normally, a single build unit is generated for a standard project."); + print_usage_line(2, "This is the default behaviour for '-o:none' and '-o:minimal' builds"); print_usage_line(0, ""); } -- cgit v1.2.3 From 664a71454bd2c58ab6f06f8de6d7d34c3eb397d7 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 15 Jul 2024 02:53:01 +0100 Subject: `-use-separate-modules` default on Windows only --- src/build_settings.cpp | 2 +- src/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/main.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 4bb76acc1..e0e7810e6 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1658,7 +1658,7 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta bc->optimization_level = gb_clamp(bc->optimization_level, -1, 3); -#if !defined(GB_SYSTEM_OSX) +#if defined(GB_SYSTEM_WINDOWS) if (bc->optimization_level <= 0) { if (!is_arch_wasm()) { bc->use_separate_modules = true; diff --git a/src/main.cpp b/src/main.cpp index da8322476..0c3ef1399 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2314,7 +2314,7 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(1, "-use-separate-modules"); print_usage_line(2, "The backend generates multiple build units which are then linked together."); print_usage_line(2, "Normally, a single build unit is generated for a standard project."); - print_usage_line(2, "This is the default behaviour for '-o:none' and '-o:minimal' builds"); + print_usage_line(2, "This is the default behaviour on Windows for '-o:none' and '-o:minimal' builds."); print_usage_line(0, ""); } -- cgit v1.2.3 From 1e37eaf54daf885636ea3ad9606a2b54e01721f9 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 15 Jul 2024 14:49:20 +0100 Subject: Begin work for `bit_set[...; [N]T]` (not working) --- src/build_settings.cpp | 2 + src/check_expr.cpp | 6 ++- src/check_type.cpp | 21 ++------ src/llvm_backend_const.cpp | 2 + src/llvm_backend_expr.cpp | 120 ++++++++++++++++++++++++++++++++++--------- src/llvm_backend_general.cpp | 2 + src/llvm_backend_proc.cpp | 5 ++ src/main.cpp | 5 ++ src/types.cpp | 21 ++++++++ 9 files changed, 141 insertions(+), 43 deletions(-) (limited to 'src/main.cpp') diff --git a/src/build_settings.cpp b/src/build_settings.cpp index e0e7810e6..49bb83b22 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -440,6 +440,8 @@ struct BuildContext { bool cached; BuildCacheData build_cache_data; + bool internal_no_inline; + bool no_threaded_checker; bool show_debug_messages; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 3fcfe29f5..01ff9da5b 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -9947,10 +9947,14 @@ gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast * } Type *et = base_type(t->BitSet.elem); isize field_count = 0; - if (et->kind == Type_Enum) { + if (et != nullptr && et->kind == Type_Enum) { field_count = et->Enum.fields.count; } + if (is_type_array(bit_set_to_int(t))) { + is_constant = false; + } + if (cl->elems[0]->kind == Ast_FieldValue) { error(cl->elems[0], "'field = value' in a bit_set a literal is not allowed"); is_constant = false; diff --git a/src/check_type.cpp b/src/check_type.cpp index fea937e4e..e3609970a 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -939,22 +939,6 @@ gb_internal void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *nam enum_type->Enum.max_value_index = max_value_index; } -gb_internal bool is_valid_bit_field_backing_type(Type *type) { - if (type == nullptr) { - return false; - } - type = base_type(type); - if (is_type_untyped(type)) { - return false; - } - if (is_type_integer(type)) { - return true; - } - if (type->kind == Type_Array) { - return is_type_integer(type->Array.elem); - } - return false; -} gb_internal void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type, Type *named_type, Ast *node) { ast_node(bf, BitFieldType, node); @@ -1268,11 +1252,14 @@ gb_internal void check_bit_set_type(CheckerContext *c, Type *type, Type *named_t Type *t = default_type(lhs.type); if (bs->underlying != nullptr) { Type *u = check_type(c, bs->underlying); + // if (!is_valid_bit_field_backing_type(u)) { if (!is_type_integer(u)) { gbString ts = type_to_string(u); error(bs->underlying, "Expected an underlying integer for the bit set, got %s", ts); gb_string_free(ts); - return; + if (!is_valid_bit_field_backing_type(u)) { + return; + } } type->BitSet.underlying = u; } diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index 5d9caeba1..12bcc4e1f 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -434,6 +434,8 @@ gb_internal LLVMValueRef lb_big_int_to_llvm(lbModule *m, Type *original_type, Bi } } + GB_ASSERT(!is_type_array(original_type)); + LLVMValueRef value = LLVMConstIntOfArbitraryPrecision(lb_type(m, original_type), cast(unsigned)((sz+7)/8), cast(u64 *)rop); if (big_int_is_neg(a)) { value = LLVMConstNeg(value); diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index bcacc0537..dfb7e162e 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -296,12 +296,6 @@ gb_internal bool lb_try_direct_vector_arith(lbProcedure *p, TokenKind op, lbValu GB_ASSERT(vector_type0 == vector_type1); LLVMTypeRef vector_type = vector_type0; - LLVMValueRef lhs_vp = LLVMBuildPointerCast(p->builder, lhs_ptr.value, LLVMPointerType(vector_type, 0), ""); - LLVMValueRef rhs_vp = LLVMBuildPointerCast(p->builder, rhs_ptr.value, LLVMPointerType(vector_type, 0), ""); - LLVMValueRef x = LLVMBuildLoad2(p->builder, vector_type, lhs_vp, ""); - LLVMValueRef y = LLVMBuildLoad2(p->builder, vector_type, rhs_vp, ""); - LLVMValueRef z = nullptr; - Type *integral_type = base_type(elem_type); if (is_type_simd_vector(integral_type)) { integral_type = core_array_type(integral_type); @@ -311,8 +305,18 @@ gb_internal bool lb_try_direct_vector_arith(lbProcedure *p, TokenKind op, lbValu case Token_Add: op = Token_Or; break; case Token_Sub: op = Token_AndNot; break; } + Type *u = bit_set_to_int(type); + if (is_type_array(u)) { + return false; + } } + LLVMValueRef lhs_vp = LLVMBuildPointerCast(p->builder, lhs_ptr.value, LLVMPointerType(vector_type, 0), ""); + LLVMValueRef rhs_vp = LLVMBuildPointerCast(p->builder, rhs_ptr.value, LLVMPointerType(vector_type, 0), ""); + LLVMValueRef x = LLVMBuildLoad2(p->builder, vector_type, lhs_vp, ""); + LLVMValueRef y = LLVMBuildLoad2(p->builder, vector_type, rhs_vp, ""); + LLVMValueRef z = nullptr; + if (is_type_float(integral_type)) { switch (op) { case Token_Add: @@ -1286,6 +1290,14 @@ handle_op:; case Token_Add: op = Token_Or; break; case Token_Sub: op = Token_AndNot; break; } + Type *u = bit_set_to_int(type); + if (is_type_array(u)) { + lhs.type = u; + rhs.type = u; + res = lb_emit_arith(p, op, lhs, rhs, u); + res.type = type; + return res; + } } Type *integral_type = type; @@ -1441,6 +1453,7 @@ gb_internal lbValue lb_build_binary_in(lbProcedure *p, lbValue left, lbValue rig GB_ASSERT(are_types_identical(left.type, key_type)); Type *it = bit_set_to_int(rt); + left = lb_emit_conv(p, left, it); if (is_type_different_to_arch_endianness(it)) { left = lb_emit_byte_swap(p, left, integer_endian_type_to_platform_type(it)); @@ -2054,6 +2067,26 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { } } + // bit_set <-> backing type + if (is_type_bit_set(src)) { + Type *backing = bit_set_to_int(src); + if (are_types_identical(backing, dst)) { + lbValue res = {}; + res.type = t; + res.value = value.value; + return res; + } + } + if (is_type_bit_set(dst)) { + Type *backing = bit_set_to_int(dst); + if (are_types_identical(src, backing)) { + lbValue res = {}; + res.type = t; + res.value = value.value; + return res; + } + } + // Pointer <-> uintptr if (is_type_pointer(src) && is_type_uintptr(dst)) { @@ -2951,13 +2984,32 @@ gb_internal lbValue lb_emit_comp_against_nil(lbProcedure *p, TokenKind op_kind, case Type_Pointer: case Type_MultiPointer: case Type_Proc: - case Type_BitSet: if (op_kind == Token_CmpEq) { res.value = LLVMBuildIsNull(p->builder, x.value, ""); } else if (op_kind == Token_NotEq) { res.value = LLVMBuildIsNotNull(p->builder, x.value, ""); } return res; + case Type_BitSet: + { + Type *u = bit_set_to_int(bt); + if (is_type_array(u)) { + auto args = array_make(permanent_allocator(), 2); + lbValue lhs = lb_address_from_load_or_generate_local(p, x); + args[0] = lb_emit_conv(p, lhs, t_rawptr); + args[1] = lb_const_int(p->module, t_int, type_size_of(t)); + lbValue val = lb_emit_runtime_call(p, "memory_compare_zero", args); + lbValue res = lb_emit_comp(p, op_kind, val, lb_const_int(p->module, t_int, 0)); + return res; + } else { + if (op_kind == Token_CmpEq) { + res.value = LLVMBuildIsNull(p->builder, x.value, ""); + } else if (op_kind == Token_NotEq) { + res.value = LLVMBuildIsNotNull(p->builder, x.value, ""); + } + } + return res; + } case Type_Slice: { @@ -4878,29 +4930,47 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) { case Type_BitSet: { i64 sz = type_size_of(type); if (cl->elems.count > 0 && sz > 0) { - lb_addr_store(p, v, lb_const_value(p->module, type, exact_value_compound(expr))); - lbValue lower = lb_const_value(p->module, t_int, exact_value_i64(bt->BitSet.lower)); - for (Ast *elem : cl->elems) { - GB_ASSERT(elem->kind != Ast_FieldValue); - if (lb_is_elem_const(elem, et)) { - continue; + Type *backing = bit_set_to_int(type); + if (is_type_array(backing)) { + GB_PANIC("TODO: bit_set [N]T"); + Type *base_it = core_array_type(backing); + i64 bits_per_elem = 8*type_size_of(base_it); + gb_unused(bits_per_elem); + lbValue one = lb_const_value(p->module, t_i64, exact_value_i64(1)); + for (Ast *elem : cl->elems) { + GB_ASSERT(elem->kind != Ast_FieldValue); + lbValue expr = lb_build_expr(p, elem); + GB_ASSERT(expr.type->kind != Type_Tuple); + + lbValue e = lb_emit_conv(p, expr, t_i64); + e = lb_emit_arith(p, Token_Sub, e, lower, t_i64); + // lbValue idx = lb_emit_arith(p, Token_Div, e, bits_per_elem, t_i64); + // lbValue val = lb_emit_arith(p, Token_Div, e, bits_per_elem, t_i64); } - - lbValue expr = lb_build_expr(p, elem); - GB_ASSERT(expr.type->kind != Type_Tuple); - + } else { Type *it = bit_set_to_int(bt); lbValue one = lb_const_value(p->module, it, exact_value_i64(1)); - lbValue e = lb_emit_conv(p, expr, it); - e = lb_emit_arith(p, Token_Sub, e, lower, it); - e = lb_emit_arith(p, Token_Shl, one, e, it); - - lbValue old_value = lb_emit_transmute(p, lb_addr_load(p, v), it); - lbValue new_value = lb_emit_arith(p, Token_Or, old_value, e, it); - new_value = lb_emit_transmute(p, new_value, type); - lb_addr_store(p, v, new_value); + for (Ast *elem : cl->elems) { + GB_ASSERT(elem->kind != Ast_FieldValue); + + if (lb_is_elem_const(elem, et)) { + continue; + } + + lbValue expr = lb_build_expr(p, elem); + GB_ASSERT(expr.type->kind != Type_Tuple); + + lbValue e = lb_emit_conv(p, expr, it); + e = lb_emit_arith(p, Token_Sub, e, lower, it); + e = lb_emit_arith(p, Token_Shl, one, e, it); + + lbValue old_value = lb_emit_transmute(p, lb_addr_load(p, v), it); + lbValue new_value = lb_emit_arith(p, Token_Or, old_value, e, it); + new_value = lb_emit_transmute(p, new_value, type); + lb_addr_store(p, v, new_value); + } } } break; diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index bb04fc746..a91c1d1fe 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -1023,6 +1023,8 @@ gb_internal void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) { LLVMTypeRef rawptr_type = lb_type(p->module, t_rawptr); LLVMTypeRef rawptr_ptr_type = LLVMPointerType(rawptr_type, 0); LLVMBuildStore(p->builder, LLVMConstNull(rawptr_type), LLVMBuildBitCast(p->builder, ptr.value, rawptr_ptr_type, "")); + } else if (is_type_bit_set(a)) { + lb_mem_zero_ptr(p, ptr.value, a, 1); } else if (lb_sizeof(src_t) <= lb_max_zero_init_size()) { LLVMBuildStore(p->builder, LLVMConstNull(src_t), ptr.value); } else { diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index eefe1c422..4ee4fb769 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -159,6 +159,11 @@ gb_internal lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool i case ProcInlining_no_inline: lb_add_attribute_to_proc(m, p->value, "noinline"); break; + default: + if (build_context.internal_no_inline) { + lb_add_attribute_to_proc(m, p->value, "noinline"); + break; + } } switch (entity->Procedure.optimization_mode) { diff --git a/src/main.cpp b/src/main.cpp index 0c3ef1399..e7f4ccc0a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -394,6 +394,7 @@ enum BuildFlagKind { BuildFlag_InternalIgnorePanic, BuildFlag_InternalModulePerFile, BuildFlag_InternalCached, + BuildFlag_InternalNoInline, BuildFlag_Tilde, @@ -598,6 +599,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_InternalIgnorePanic, str_lit("internal-ignore-panic"), BuildFlagParam_None, Command_all); add_flag(&build_flags, BuildFlag_InternalModulePerFile, str_lit("internal-module-per-file"), BuildFlagParam_None, Command_all); add_flag(&build_flags, BuildFlag_InternalCached, str_lit("internal-cached"), BuildFlagParam_None, Command_all); + add_flag(&build_flags, BuildFlag_InternalNoInline, str_lit("internal-no-inline"), BuildFlagParam_None, Command_all); #if ALLOW_TILDE add_flag(&build_flags, BuildFlag_Tilde, str_lit("tilde"), BuildFlagParam_None, Command__does_build); @@ -1422,6 +1424,9 @@ gb_internal bool parse_build_flags(Array args) { build_context.cached = true; build_context.use_separate_modules = true; break; + case BuildFlag_InternalNoInline: + build_context.internal_no_inline = true; + break; case BuildFlag_Tilde: build_context.tilde_backend = true; diff --git a/src/types.cpp b/src/types.cpp index fdc174d81..3f86d4c50 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -2011,6 +2011,24 @@ gb_internal bool is_type_valid_bit_set_elem(Type *t) { return false; } + +gb_internal bool is_valid_bit_field_backing_type(Type *type) { + if (type == nullptr) { + return false; + } + type = base_type(type); + if (is_type_untyped(type)) { + return false; + } + if (is_type_integer(type)) { + return true; + } + if (type->kind == Type_Array) { + return is_type_integer(type->Array.elem); + } + return false; +} + gb_internal Type *bit_set_to_int(Type *t) { GB_ASSERT(is_type_bit_set(t)); Type *bt = base_type(t); @@ -2018,6 +2036,9 @@ gb_internal Type *bit_set_to_int(Type *t) { if (underlying != nullptr && is_type_integer(underlying)) { return underlying; } + if (underlying != nullptr && is_valid_bit_field_backing_type(underlying)) { + return underlying; + } i64 sz = type_size_of(t); switch (sz) { -- cgit v1.2.3 From bd562116b834ed44440665f2fe4b080c665e9b85 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 15 Jul 2024 15:08:26 +0100 Subject: Minor change to an internal flag --- src/main.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index e7f4ccc0a..00734c050 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1419,6 +1419,7 @@ gb_internal bool parse_build_flags(Array args) { break; case BuildFlag_InternalModulePerFile: build_context.module_per_file = true; + build_context.use_separate_modules = true; break; case BuildFlag_InternalCached: build_context.cached = true; -- cgit v1.2.3