From bb58926b7a09b5b06b681d53e6d3e86e098f08e9 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Wed, 20 Mar 2024 00:38:02 +0100 Subject: [PATCH 01/26] 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(-) 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 From b91e7f5c51d26b5a8e985e8fe22758442b8f5ae0 Mon Sep 17 00:00:00 2001 From: Laytan Date: Thu, 21 Mar 2024 22:21:59 +0100 Subject: [PATCH 02/26] llvm-18: linux (amd64) --- src/build_settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index ebdc64285..9b8531e12 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -949,7 +949,7 @@ gb_global TargetMetrics target_linux_i386 = { gb_global TargetMetrics target_linux_amd64 = { TargetOs_linux, TargetArch_amd64, - 8, 8, 8, 16, + 8, 8, 16, 16, str_lit("x86_64-pc-linux-gnu"), str_lit("e-m:w-i64:64-f80:128-n8:16:32:64-S128"), }; From 043dd98e91f40ef8a3980667d83dd69db8f7b8de Mon Sep 17 00:00:00 2001 From: Laytan Date: Thu, 21 Mar 2024 22:22:23 +0100 Subject: [PATCH 03/26] fix demo out of bounds error --- examples/demo/demo.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/demo/demo.odin b/examples/demo/demo.odin index a62c11310..39345e39c 100644 --- a/examples/demo/demo.odin +++ b/examples/demo/demo.odin @@ -48,7 +48,7 @@ the_basics :: proc() { // os.args holds the path to the current executable and any arguments passed to it. if len(os.args) == 1 { fmt.printf("Hellope from %v.\n", os.args[0]) - } else { + } else if len(os.args) > 2 { fmt.printf("%v, %v! from %v.\n", os.args[1], os.args[2], os.args[0]) } From e3e04ffa22f11cb9b7fcb55ec91daad34137d61d Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Tue, 16 Apr 2024 17:52:44 +0200 Subject: [PATCH 04/26] llvm-18: enable sroa and static map calls --- src/build_settings.cpp | 2 ++ src/llvm_backend.cpp | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 9b8531e12..c01309b35 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -2027,10 +2027,12 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta bc->optimization_level = gb_clamp(bc->optimization_level, -1, 3); + #if LLVM_VERSION_MAJOR != 18 if (bc->metrics.os != TargetOs_windows) { // ENFORCE DYNAMIC MAP CALLS bc->dynamic_map_calls = true; } + #endif bc->ODIN_VALGRIND_SUPPORT = false; if (build_context.metrics.os != TargetOs_windows) { diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index be800a53f..03c17a8bb 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1640,6 +1640,7 @@ inferattrs, function( lower-expect, simplifycfg, + sroa, early-cse<> ), ipsccp, @@ -1661,6 +1662,7 @@ cgscc( inline, function-attrs, function( + sroa, early-cse, speculative-execution, jump-threading, @@ -1688,6 +1690,7 @@ cgscc( loop-deletion, loop-unroll-full ), + sroa, vector-combine, mldst-motion, gvn<>, @@ -1737,6 +1740,7 @@ function( instcombine, loop-unroll, transform-warning, + sroa, infer-alignment, instcombine, loop-mssa( @@ -1896,6 +1900,7 @@ inferattrs, function( lower-expect, simplifycfg, + sroa, early-cse<> ), ipsccp, @@ -1917,6 +1922,7 @@ cgscc( inline, function-attrs, function( + sroa, early-cse, speculative-execution, jump-threading, @@ -1945,6 +1951,7 @@ cgscc( loop-deletion, loop-unroll-full ), + sroa, vector-combine, mldst-motion, gvn<>, @@ -1994,6 +2001,7 @@ function( instcombine, loop-unroll, transform-warning, + sroa, infer-alignment, instcombine, loop-mssa( @@ -2157,6 +2165,7 @@ inferattrs, function( lower-expect, simplifycfg, + sroa, early-cse<>, callsite-splitting ), @@ -2178,6 +2187,7 @@ cgscc( function-attrs, argpromotion, function( + sroa, early-cse, speculative-execution, jump-threading, @@ -2206,6 +2216,7 @@ cgscc( loop-deletion, loop-unroll-full ), + sroa, vector-combine, mldst-motion, gvn<>, @@ -2254,6 +2265,7 @@ function( instcombine, loop-unroll, transform-warning, + sroa, infer-alignment, instcombine, loop-mssa(licm), From f64e8ffd6465422528d1643c0b2e58f4722c646f Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Mon, 22 Apr 2024 20:50:44 +0200 Subject: [PATCH 05/26] llvm-18: fix linking the compiler with clang-18 --- build_odin.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_odin.sh b/build_odin.sh index 328ac81bd..26f6393b3 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -65,7 +65,7 @@ Darwin) fi CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" - LDFLAGS="$LDFLAGS -liconv -ldl -framework System -lLLVM -Wl,-rpath $($LLVM_CONFIG --libdir)" + LDFLAGS="$LDFLAGS -isysroot $(xcrun --show-sdk-path -sdk macosx) -liconv -ldl -framework System -lLLVM -Wl,-rpath $($LLVM_CONFIG --libdir)" ;; FreeBSD) CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" From c219ca5b1b896a832bede9f2546252fa2444fbf9 Mon Sep 17 00:00:00 2001 From: Laytan Date: Tue, 23 Apr 2024 00:13:24 +0200 Subject: [PATCH 06/26] llvm-18: fix undocumented breaking change on i128 alignment --- src/build_settings.cpp | 51 +++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index c01309b35..0ac06b7ec 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1,3 +1,5 @@ +#include + #if defined(GB_SYSTEM_FREEBSD) || defined(GB_SYSTEM_OPENBSD) #include #include @@ -613,7 +615,6 @@ struct TargetMetrics { isize max_align; isize max_simd_align; String target_triplet; - String target_data_layout; TargetABIKind abi; }; @@ -923,7 +924,12 @@ gb_internal isize MAX_ERROR_COLLECTOR_COUNT(void) { return build_context.max_error_count; } - +// NOTE: AMD64 targets had their alignment on 128 bit ints bumped from 8 to 16 (undocumented of course). +#if LLVM_VERSION_MAJOR >= 18 + #define AMD64_MAX_ALIGNMENT (16) +#else + #define AMD64_MAX_ALIGNMENT (8) +#endif gb_global TargetMetrics target_windows_i386 = { TargetOs_windows, @@ -934,9 +940,8 @@ gb_global TargetMetrics target_windows_i386 = { gb_global TargetMetrics target_windows_amd64 = { TargetOs_windows, TargetArch_amd64, - 8, 8, 8, 16, + 8, 8, AMD64_MAX_ALIGNMENT, 16, str_lit("x86_64-pc-windows-msvc"), - str_lit("e-m:w-i64:64-f80:128-n8:16:32:64-S128"), }; gb_global TargetMetrics target_linux_i386 = { @@ -949,16 +954,14 @@ gb_global TargetMetrics target_linux_i386 = { gb_global TargetMetrics target_linux_amd64 = { TargetOs_linux, TargetArch_amd64, - 8, 8, 16, 16, + 8, 8, AMD64_MAX_ALIGNMENT, 16, str_lit("x86_64-pc-linux-gnu"), - str_lit("e-m:w-i64:64-f80:128-n8:16:32:64-S128"), }; gb_global TargetMetrics target_linux_arm64 = { TargetOs_linux, TargetArch_arm64, - 8, 8, 8, 16, + 8, 8, 16, 16, str_lit("aarch64-linux-elf"), - str_lit("e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"), }; gb_global TargetMetrics target_linux_arm32 = { @@ -966,15 +969,13 @@ gb_global TargetMetrics target_linux_arm32 = { TargetArch_arm32, 4, 4, 4, 8, str_lit("arm-linux-gnu"), - str_lit("e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"), }; gb_global TargetMetrics target_darwin_amd64 = { TargetOs_darwin, TargetArch_amd64, - 8, 8, 8, 16, + 8, 8, AMD64_MAX_ALIGNMENT, 16, str_lit("x86_64-apple-macosx"), // NOTE: Changes during initialization based on build flags. - str_lit("e-m:o-i64:64-f80:128-n8:16:32:64-S128"), }; gb_global TargetMetrics target_darwin_arm64 = { @@ -982,7 +983,6 @@ gb_global TargetMetrics target_darwin_arm64 = { TargetArch_arm64, 8, 8, 16, 16, str_lit("arm64-apple-macosx"), // NOTE: Changes during initialization based on build flags. - str_lit("e-m:o-i64:64-i128:128-n32:64-S128"), }; gb_global TargetMetrics target_freebsd_i386 = { @@ -995,9 +995,8 @@ gb_global TargetMetrics target_freebsd_i386 = { gb_global TargetMetrics target_freebsd_amd64 = { TargetOs_freebsd, TargetArch_amd64, - 8, 8, 8, 16, + 8, 8, AMD64_MAX_ALIGNMENT, 16, str_lit("x86_64-unknown-freebsd-elf"), - str_lit("e-m:w-i64:64-f80:128-n8:16:32:64-S128"), }; gb_global TargetMetrics target_freebsd_arm64 = { @@ -1011,22 +1010,21 @@ gb_global TargetMetrics target_freebsd_arm64 = { gb_global TargetMetrics target_openbsd_amd64 = { TargetOs_openbsd, TargetArch_amd64, - 8, 8, 8, 16, + 8, 8, AMD64_MAX_ALIGNMENT, 16, str_lit("x86_64-unknown-openbsd-elf"), - str_lit("e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"), }; gb_global TargetMetrics target_haiku_amd64 = { TargetOs_haiku, TargetArch_amd64, - 8, 8, 8, 16, + 8, 8, AMD64_MAX_ALIGNMENT, 16, str_lit("x86_64-unknown-haiku"), }; gb_global TargetMetrics target_essence_amd64 = { TargetOs_essence, TargetArch_amd64, - 8, 8, 8, 16, + 8, 8, AMD64_MAX_ALIGNMENT, 16, str_lit("x86_64-pc-none-elf"), }; @@ -1036,7 +1034,6 @@ gb_global TargetMetrics target_freestanding_wasm32 = { TargetArch_wasm32, 4, 4, 8, 16, str_lit("wasm32-freestanding-js"), - str_lit("e-m:e-p:32:32-i64:64-n32:64-S128"), }; gb_global TargetMetrics target_js_wasm32 = { @@ -1044,7 +1041,6 @@ gb_global TargetMetrics target_js_wasm32 = { TargetArch_wasm32, 4, 4, 8, 16, str_lit("wasm32-js-js"), - str_lit("e-m:e-p:32:32-i64:64-n32:64-S128"), }; gb_global TargetMetrics target_wasi_wasm32 = { @@ -1052,7 +1048,6 @@ gb_global TargetMetrics target_wasi_wasm32 = { TargetArch_wasm32, 4, 4, 8, 16, str_lit("wasm32-wasi-js"), - str_lit("e-m:e-p:32:32-i64:64-n32:64-S128"), }; @@ -1061,7 +1056,6 @@ gb_global TargetMetrics target_freestanding_wasm64p32 = { TargetArch_wasm64p32, 4, 8, 8, 16, str_lit("wasm32-freestanding-js"), - str_lit("e-m:e-p:32:32-i64:64-n32:64-S128"), }; gb_global TargetMetrics target_js_wasm64p32 = { @@ -1069,7 +1063,6 @@ gb_global TargetMetrics target_js_wasm64p32 = { TargetArch_wasm64p32, 4, 8, 8, 16, str_lit("wasm32-js-js"), - str_lit("e-m:e-p:32:32-i64:64-n32:64-S128"), }; gb_global TargetMetrics target_wasi_wasm64p32 = { @@ -1077,7 +1070,6 @@ gb_global TargetMetrics target_wasi_wasm64p32 = { TargetArch_wasm32, 4, 8, 8, 16, str_lit("wasm32-wasi-js"), - str_lit("e-m:e-p:32:32-i64:64-n32:64-S128"), }; @@ -1085,27 +1077,24 @@ gb_global TargetMetrics target_wasi_wasm64p32 = { gb_global TargetMetrics target_freestanding_amd64_sysv = { TargetOs_freestanding, TargetArch_amd64, - 8, 8, 8, 16, + 8, 8, AMD64_MAX_ALIGNMENT, 16, str_lit("x86_64-pc-none-gnu"), - str_lit("e-m:w-i64:64-f80:128-n8:16:32:64-S128"), TargetABI_SysV, }; gb_global TargetMetrics target_freestanding_amd64_win64 = { TargetOs_freestanding, TargetArch_amd64, - 8, 8, 8, 16, + 8, 8, AMD64_MAX_ALIGNMENT, 16, str_lit("x86_64-pc-none-msvc"), - str_lit("e-m:w-i64:64-f80:128-n8:16:32:64-S128"), TargetABI_Win64, }; gb_global TargetMetrics target_freestanding_arm64 = { TargetOs_freestanding, TargetArch_arm64, - 8, 8, 8, 16, + 8, 8, 16, 16, str_lit("aarch64-none-elf"), - str_lit("e-m:o-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"), }; struct NamedTargetMetrics { @@ -2027,7 +2016,7 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta bc->optimization_level = gb_clamp(bc->optimization_level, -1, 3); - #if LLVM_VERSION_MAJOR != 18 + #if LLVM_VERSION_MAJOR < 18 if (bc->metrics.os != TargetOs_windows) { // ENFORCE DYNAMIC MAP CALLS bc->dynamic_map_calls = true; From f9a7d2bf04f9fa88cdf8d3cdc6c4e14089f1d459 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Tue, 23 Apr 2024 00:40:31 +0200 Subject: [PATCH 07/26] llvm-18: enable static map calls on non amd64sysv targets --- src/build_settings.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 0ac06b7ec..a2534b01f 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -2016,12 +2016,11 @@ gb_internal void init_build_context(TargetMetrics *cross_target, Subtarget subta bc->optimization_level = gb_clamp(bc->optimization_level, -1, 3); - #if LLVM_VERSION_MAJOR < 18 - if (bc->metrics.os != TargetOs_windows) { + // TODO: Static map calls are bugged on `amd64sysv` abi. + if (bc->metrics.os != TargetOs_windows && bc->metrics.arch == TargetArch_amd64) { // ENFORCE DYNAMIC MAP CALLS bc->dynamic_map_calls = true; } - #endif bc->ODIN_VALGRIND_SUPPORT = false; if (build_context.metrics.os != TargetOs_windows) { From a3821615dc94c9d7b0ff9cc8f5a6c53f8a816a58 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Tue, 23 Apr 2024 00:44:37 +0200 Subject: [PATCH 08/26] llvm-18: fix windows build error because of include --- src/build_settings.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index a2534b01f..b9682adc8 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1,5 +1,3 @@ -#include - #if defined(GB_SYSTEM_FREEBSD) || defined(GB_SYSTEM_OPENBSD) #include #include @@ -925,10 +923,16 @@ gb_internal isize MAX_ERROR_COLLECTOR_COUNT(void) { } // NOTE: AMD64 targets had their alignment on 128 bit ints bumped from 8 to 16 (undocumented of course). -#if LLVM_VERSION_MAJOR >= 18 - #define AMD64_MAX_ALIGNMENT (16) +#if defined(GB_SYSTEM_WINDOWS) + #define AMD64_MAX_ALIGNMENT (8) // TODO: up to 16 when Windows is updated to LLVM 18. #else - #define AMD64_MAX_ALIGNMENT (8) + #include + + #if LLVM_VERSION_MAJOR >= 18 + #define AMD64_MAX_ALIGNMENT (16) + #else + #define AMD64_MAX_ALIGNMENT (8) + #endif #endif gb_global TargetMetrics target_windows_i386 = { From ecddf3b7f10b02028bf41674c9414b9307f8dae9 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Tue, 23 Apr 2024 20:09:59 +0200 Subject: [PATCH 09/26] llvm-18: cleanup --- build_odin.sh | 2 +- src/build_settings.cpp | 14 +++++++------- src/llvm_backend.hpp | 13 ++++--------- 3 files changed, 12 insertions(+), 17 deletions(-) diff --git a/build_odin.sh b/build_odin.sh index 26f6393b3..76c4e1198 100755 --- a/build_odin.sh +++ b/build_odin.sh @@ -65,7 +65,7 @@ Darwin) fi CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" - LDFLAGS="$LDFLAGS -isysroot $(xcrun --show-sdk-path -sdk macosx) -liconv -ldl -framework System -lLLVM -Wl,-rpath $($LLVM_CONFIG --libdir)" + LDFLAGS="$LDFLAGS -liconv -ldl -framework System -lLLVM" ;; FreeBSD) CXXFLAGS="$CXXFLAGS $($LLVM_CONFIG --cxxflags --ldflags)" diff --git a/src/build_settings.cpp b/src/build_settings.cpp index b9682adc8..675940036 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -922,17 +922,17 @@ gb_internal isize MAX_ERROR_COLLECTOR_COUNT(void) { return build_context.max_error_count; } -// NOTE: AMD64 targets had their alignment on 128 bit ints bumped from 8 to 16 (undocumented of course). #if defined(GB_SYSTEM_WINDOWS) - #define AMD64_MAX_ALIGNMENT (8) // TODO: up to 16 when Windows is updated to LLVM 18. + #include #else #include +#endif - #if LLVM_VERSION_MAJOR >= 18 - #define AMD64_MAX_ALIGNMENT (16) - #else - #define AMD64_MAX_ALIGNMENT (8) - #endif +// NOTE: AMD64 targets had their alignment on 128 bit ints bumped from 8 to 16 (undocumented of course). +#if LLVM_VERSION_MAJOR >= 18 + #define AMD64_MAX_ALIGNMENT 16 +#else + #define AMD64_MAX_ALIGNMENT 8 #endif gb_global TargetMetrics target_windows_i386 = { diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 975aa17c5..9f7bc8843 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -1,13 +1,9 @@ #if defined(GB_SYSTEM_WINDOWS) -#include "llvm-c/Core.h" -#include "llvm-c/ExecutionEngine.h" -#include "llvm-c/Target.h" -#include "llvm-c/Analysis.h" -#include "llvm-c/Object.h" -#include "llvm-c/BitWriter.h" -#include "llvm-c/DebugInfo.h" -#include "llvm-c/Transforms/PassBuilder.h" +#include #else +#include +#endif + #include #include #include @@ -26,7 +22,6 @@ #include #include #endif -#endif #if LLVM_VERSION_MAJOR < 11 #error "LLVM Version 11 is the minimum required" From d93cc18dacf7800972cab91053fc1ed3c68dd34b Mon Sep 17 00:00:00 2001 From: Laytan Date: Thu, 25 Apr 2024 00:19:48 +0200 Subject: [PATCH 10/26] fix packed gep loads with wrong alignment --- src/check_type.cpp | 2 ++ src/types.cpp | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/check_type.cpp b/src/check_type.cpp index c119ce6b5..9653a980b 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -135,6 +135,8 @@ gb_internal void check_struct_fields(CheckerContext *ctx, Ast *node, SliceStruct.is_polymorphic = true; type = nullptr; + } else if(struct_type->Struct.is_packed) { + type->flags |= TypeFlag_Packed; } } if (type == nullptr) { diff --git a/src/types.cpp b/src/types.cpp index 3ec05059f..55d083a9a 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -321,6 +321,7 @@ enum TypeFlag : u32 { TypeFlag_Polymorphic = 1<<1, TypeFlag_PolySpecialized = 1<<2, TypeFlag_InProcessOfCheckingPolymorphic = 1<<3, + TypeFlag_Packed = 1<<4, }; struct Type { @@ -3671,6 +3672,9 @@ gb_internal i64 type_align_of(Type *t) { if (t == nullptr) { return 1; } + if (t->flags & TypeFlag_Packed) { + return 1; + } if (t->kind != Type_Named && t->cached_align > 0) { return t->cached_align.load(); } From 58c0abb98d50fa9f2cd1e0ab2ce255430f5d9253 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Thu, 2 May 2024 11:27:40 +0200 Subject: [PATCH 11/26] revert wrong approach in fixing the load alignment --- src/check_type.cpp | 2 -- src/checker.cpp | 2 +- src/types.cpp | 5 ----- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/check_type.cpp b/src/check_type.cpp index 9653a980b..c119ce6b5 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -135,8 +135,6 @@ gb_internal void check_struct_fields(CheckerContext *ctx, Ast *node, SliceStruct.is_polymorphic = true; type = nullptr; - } else if(struct_type->Struct.is_packed) { - type->flags |= TypeFlag_Packed; } } if (type == nullptr) { diff --git a/src/checker.cpp b/src/checker.cpp index 70ca4fc47..047017290 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -4315,7 +4315,7 @@ gb_internal bool correct_single_type_alias(CheckerContext *c, Entity *e) { gb_internal bool correct_type_alias_in_scope_backwards(CheckerContext *c, Scope *s) { bool correction = false; - for (u32 n = s->elements.count, i = n-1; i < n; i--) { + for (u32 n = s->elements.capacity, i = n-1; i < n; i--) { auto const &entry = s->elements.entries[i]; Entity *e = entry.value; if (entry.hash && e != nullptr) { diff --git a/src/types.cpp b/src/types.cpp index 55d083a9a..0c6729b87 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -321,7 +321,6 @@ enum TypeFlag : u32 { TypeFlag_Polymorphic = 1<<1, TypeFlag_PolySpecialized = 1<<2, TypeFlag_InProcessOfCheckingPolymorphic = 1<<3, - TypeFlag_Packed = 1<<4, }; struct Type { @@ -949,7 +948,6 @@ gb_internal void set_base_type(Type *t, Type *base) { } } - gb_internal Type *alloc_type(TypeKind kind) { // gbAllocator a = heap_allocator(); gbAllocator a = permanent_allocator(); @@ -3672,9 +3670,6 @@ gb_internal i64 type_align_of(Type *t) { if (t == nullptr) { return 1; } - if (t->flags & TypeFlag_Packed) { - return 1; - } if (t->kind != Type_Named && t->cached_align > 0) { return t->cached_align.load(); } From 77efdcd89911f1c9b831cfcf5e5aba49ec8d53d5 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Thu, 2 May 2024 19:23:17 +0200 Subject: [PATCH 12/26] fix packed gep loads with wrong alignment --- src/checker.cpp | 2 +- src/llvm_backend.hpp | 1 + src/types.cpp | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/checker.cpp b/src/checker.cpp index 047017290..70ca4fc47 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -4315,7 +4315,7 @@ gb_internal bool correct_single_type_alias(CheckerContext *c, Entity *e) { gb_internal bool correct_type_alias_in_scope_backwards(CheckerContext *c, Scope *s) { bool correction = false; - for (u32 n = s->elements.capacity, i = n-1; i < n; i--) { + for (u32 n = s->elements.count, i = n-1; i < n; i--) { auto const &entry = s->elements.entries[i]; Entity *e = entry.value; if (entry.hash && e != nullptr) { diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 9f7bc8843..0fed376aa 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -66,6 +66,7 @@ struct lbProcedure; struct lbValue { LLVMValueRef value; Type *type; + bool is_packed; }; diff --git a/src/types.cpp b/src/types.cpp index 0c6729b87..3ec05059f 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -948,6 +948,7 @@ gb_internal void set_base_type(Type *t, Type *base) { } } + gb_internal Type *alloc_type(TypeKind kind) { // gbAllocator a = heap_allocator(); gbAllocator a = permanent_allocator(); From 87b099b5aadda9d82b6c013da4849daec1192407 Mon Sep 17 00:00:00 2001 From: Laytan Date: Mon, 6 May 2024 23:19:06 +0200 Subject: [PATCH 13/26] fix merge conflict --- src/build_settings.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 675940036..c6ef33af2 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1008,7 +1008,6 @@ gb_global TargetMetrics target_freebsd_arm64 = { TargetArch_arm64, 8, 8, 16, 16, str_lit("aarch64-unknown-freebsd-elf"), - str_lit("e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"), }; gb_global TargetMetrics target_openbsd_amd64 = { From b0b60fe7ed00cedf6e928bb86016d54856f4a759 Mon Sep 17 00:00:00 2001 From: Laytan Date: Tue, 7 May 2024 14:29:57 +0200 Subject: [PATCH 14/26] fix segfault in release builds of the compiler with clang++-18 --- src/exact_value.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/exact_value.cpp b/src/exact_value.cpp index 83af82f55..1a42a82a9 100644 --- a/src/exact_value.cpp +++ b/src/exact_value.cpp @@ -121,12 +121,14 @@ gb_internal ExactValue exact_value_string(String string) { gb_internal ExactValue exact_value_i64(i64 i) { ExactValue result = {ExactValue_Integer}; + result.value_integer = {0}; big_int_from_i64(&result.value_integer, i); return result; } gb_internal ExactValue exact_value_u64(u64 i) { ExactValue result = {ExactValue_Integer}; + result.value_integer = {0}; big_int_from_u64(&result.value_integer, i); return result; } @@ -177,6 +179,7 @@ gb_internal ExactValue exact_value_typeid(Type *type) { gb_internal ExactValue exact_value_integer_from_string(String const &string) { ExactValue result = {ExactValue_Integer}; + result.value_integer = {0}; bool success; big_int_from_string(&result.value_integer, string, &success); if (!success) { @@ -585,6 +588,7 @@ gb_internal ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i3 return v; case ExactValue_Integer: { ExactValue i = {ExactValue_Integer}; + i.value_integer = {0}; big_int_neg(&i.value_integer, &v.value_integer); return i; } @@ -616,6 +620,7 @@ gb_internal ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i3 case ExactValue_Integer: { GB_ASSERT(precision != 0); ExactValue i = {ExactValue_Integer}; + i.value_integer = {0}; big_int_not(&i.value_integer, &v.value_integer, precision, !is_unsigned); return i; } From 9d1db48549b57635d96a1ecd698b03f3e36a4451 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Tue, 7 May 2024 17:25:17 +0200 Subject: [PATCH 15/26] remove is_packed bodge --- src/llvm_backend.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 0fed376aa..9f7bc8843 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -66,7 +66,6 @@ struct lbProcedure; struct lbValue { LLVMValueRef value; Type *type; - bool is_packed; }; From 97e9c50d116024901ce029c495495fd723cedf7f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 9 May 2024 10:44:06 +0100 Subject: [PATCH 16/26] Fix #3556 --- src/llvm_backend_expr.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index ee1a384ae..030926079 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -4383,7 +4383,11 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) { mask = LLVMConstSub(mask, LLVMConstInt(lit, 1, false)); LLVMValueRef elem = values[i].value; - elem = LLVMBuildZExt(p->builder, elem, lit, ""); + if (lb_sizeof(lit) < lb_sizeof(LLVMTypeOf(elem))) { + elem = LLVMBuildTrunc(p->builder, elem, lit, ""); + } else { + elem = LLVMBuildZExt(p->builder, elem, lit, ""); + } elem = LLVMBuildAnd(p->builder, elem, mask, ""); elem = LLVMBuildShl(p->builder, elem, LLVMConstInt(lit, f.bit_offset, false), ""); From d85c8f0b2c5989f7d14b02c9023060990d241111 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 9 May 2024 10:58:57 +0100 Subject: [PATCH 17/26] Fix #3555 --- src/check_decl.cpp | 11 +++++++++++ src/check_type.cpp | 1 + src/entity.cpp | 1 + src/types.cpp | 4 ++++ 4 files changed, 17 insertions(+) diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 5b9486873..441c8000d 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1619,6 +1619,17 @@ gb_internal bool check_proc_body(CheckerContext *ctx_, Token token, DeclInfo *de if (e->kind != Entity_Variable) { continue; } + if (is_type_polymorphic(e->type)) { + gbString s = type_to_string(e->type); + char const *msg = "Unspecialized polymorphic types are not allowed in procedure parameters, got %s"; + if (e->Variable.type_expr) { + error(e->Variable.type_expr, msg, s); + } else { + error(e->token, msg, s); + } + gb_string_free(s); + } + if (!(e->flags & EntityFlag_Using)) { continue; } diff --git a/src/check_type.cpp b/src/check_type.cpp index c119ce6b5..3d11b5012 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2076,6 +2076,7 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para param = alloc_entity_param(scope, name->Ident.token, type, is_using, true); param->Variable.param_value = param_value; param->Variable.field_group_index = field_group_index; + param->Variable.type_expr = type_expr; } } if (p->flags&FieldFlag_no_alias) { diff --git a/src/entity.cpp b/src/entity.cpp index d76d5f441..60ca208ec 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -210,6 +210,7 @@ struct Entity { CommentGroup *comment; } Constant; struct { + Ast *type_expr; // only used for some variables within procedure bodies Ast *init_expr; // only used for some variables within procedure bodies i32 field_index; i32 field_group_index; diff --git a/src/types.cpp b/src/types.cpp index 3ec05059f..30e009086 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -3267,6 +3267,10 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name } } + if (is_type_polymorphic(type)) { + // NOTE(bill): A polymorphic struct has no fields, this only hits in the case of an error + return sel; + } wait_signal_until_available(&type->Struct.fields_wait_signal); isize field_count = type->Struct.fields.count; if (field_count != 0) for_array(i, type->Struct.fields) { From b0f0e4d02a88b27e04d9d7241959107ce08ff592 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 9 May 2024 15:47:09 +0100 Subject: [PATCH 18/26] Add intrinsics `type_bit_set_elem_type` & `type_bit_set_underlying_type` --- base/intrinsics/intrinsics.odin | 19 +++++++----- src/check_builtin.cpp | 52 +++++++++++++++++++++++++++++++++ src/checker_builtin_procs.hpp | 6 ++++ 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/base/intrinsics/intrinsics.odin b/base/intrinsics/intrinsics.odin index d887f8dcc..0c4e5d6c3 100644 --- a/base/intrinsics/intrinsics.odin +++ b/base/intrinsics/intrinsics.odin @@ -169,15 +169,18 @@ type_has_nil :: proc($T: typeid) -> bool --- type_is_specialization_of :: proc($T, $S: typeid) -> bool --- -type_is_variant_of :: proc($U, $V: typeid) -> bool where type_is_union(U) --- -type_union_tag_type :: proc($T: typeid) -> typeid where type_is_union(T) --- -type_union_tag_offset :: proc($T: typeid) -> uintptr where type_is_union(T) --- -type_union_base_tag_value :: proc($T: typeid) -> int where type_is_union(U) --- -type_union_variant_count :: proc($T: typeid) -> int where type_is_union(T) --- -type_variant_type_of :: proc($T: typeid, $index: int) -> typeid where type_is_union(T) --- -type_variant_index_of :: proc($U, $V: typeid) -> int where type_is_union(U) --- +type_is_variant_of :: proc($U, $V: typeid) -> bool where type_is_union(U) --- +type_union_tag_type :: proc($T: typeid) -> typeid where type_is_union(T) --- +type_union_tag_offset :: proc($T: typeid) -> uintptr where type_is_union(T) --- +type_union_base_tag_value :: proc($T: typeid) -> int where type_is_union(U) --- +type_union_variant_count :: proc($T: typeid) -> int where type_is_union(T) --- +type_variant_type_of :: proc($T: typeid, $index: int) -> typeid where type_is_union(T) --- +type_variant_index_of :: proc($U, $V: typeid) -> int where type_is_union(U) --- -type_has_field :: proc($T: typeid, $name: string) -> bool --- +type_bit_set_elem_type :: proc($T: typeid) -> typeid where type_is_bit_set(T) --- +type_bit_set_underlying_type :: proc($T: typeid) -> typeid where type_is_bit_set(T) --- + +type_has_field :: proc($T: typeid, $name: string) -> bool --- type_field_type :: proc($T: typeid, $name: string) -> typeid --- type_proc_parameter_count :: proc($T: typeid) -> int where type_is_proc(T) --- diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 3d31ec75d..c7d27cf38 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -5433,6 +5433,58 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As operand->value = exact_value_i64(u->Union.kind == UnionType_no_nil ? 0 : 1); } break; + case BuiltinProc_type_bit_set_elem_type: + { + + if (operand->mode != Addressing_Type) { + error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name)); + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + Type *bs = operand->type; + + if (!is_type_bit_set(bs)) { + error(operand->expr, "Expected a bit_set type for '%.*s'", LIT(builtin_name)); + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + bs = base_type(bs); + GB_ASSERT(bs->kind == Type_BitSet); + + operand->mode = Addressing_Type; + operand->type = bs->BitSet.elem; + } break; + + case BuiltinProc_type_bit_set_underlying_type: + { + + if (operand->mode != Addressing_Type) { + error(operand->expr, "Expected a type for '%.*s'", LIT(builtin_name)); + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + Type *bs = operand->type; + + if (!is_type_bit_set(bs)) { + error(operand->expr, "Expected a bit_set type for '%.*s'", LIT(builtin_name)); + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + return false; + } + + bs = base_type(bs); + GB_ASSERT(bs->kind == Type_BitSet); + + operand->mode = Addressing_Type; + operand->type = bit_set_to_int(bs); + } break; + case BuiltinProc_type_union_variant_count: { if (operand->mode != Addressing_Type) { diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 8419c6568..04a8bb848 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -269,6 +269,9 @@ BuiltinProc__type_simple_boolean_end, BuiltinProc_type_variant_type_of, BuiltinProc_type_variant_index_of, + BuiltinProc_type_bit_set_elem_type, + BuiltinProc_type_bit_set_underlying_type, + BuiltinProc_type_struct_field_count, BuiltinProc_type_proc_parameter_count, @@ -577,6 +580,9 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("type_variant_type_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_variant_index_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_bit_set_elem_type"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_bit_set_underlying_type"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_struct_field_count"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_proc_parameter_count"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, From f54977336b27c32eab52b77d94e7b1610f4350cf Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 9 May 2024 15:56:00 +0100 Subject: [PATCH 19/26] With `-vet-style`, give suggestion of separating where clauses with a comma rather than '&&' This improves the error messages --- src/check_expr.cpp | 14 ++++++++++++++ src/check_type.cpp | 2 +- src/parser.cpp | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 013638e63..98aebfe4e 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6193,6 +6193,20 @@ gb_internal bool evaluate_where_clauses(CheckerContext *ctx, Ast *call_expr, Sco } return false; } + + if (ast_file_vet_style(ctx->file)) { + Ast *c = unparen_expr(clause); + if (c->kind == Ast_BinaryExpr && c->BinaryExpr.op.kind == Token_CmpAnd) { + ERROR_BLOCK(); + error(c, "Prefer to separate 'where' clauses with a comma rather than '&&'"); + gbString x = expr_to_string(c->BinaryExpr.left); + gbString y = expr_to_string(c->BinaryExpr.right); + error_line("\tSuggestion: '%s, %s'", x, y); + gb_string_free(y); + gb_string_free(x); + } + } + } } diff --git a/src/check_type.cpp b/src/check_type.cpp index 3d11b5012..11e332757 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -1166,7 +1166,7 @@ gb_internal void check_bit_field_type(CheckerContext *ctx, Type *bit_field_type, } } if (all_ones && all_booleans) { - if (build_context.vet_flags & VetFlag_Style) { + if (ast_file_vet_style(ctx->file)) { char const *msg = "This 'bit_field' is better expressed as a 'bit_set' since all of the fields are booleans, of 1-bit in size, and the backing type is an integer (-vet-style)"; error(node, msg); } else { diff --git a/src/parser.cpp b/src/parser.cpp index 04505cbd7..6e859fe32 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1,7 +1,7 @@ #include "parser_pos.cpp" gb_internal u64 ast_file_vet_flags(AstFile *f) { - if (f->vet_flags_set) { + if (f != nullptr && f->vet_flags_set) { return f->vet_flags; } return build_context.vet_flags; From 7bcf3b1a0d1b72ab25e4942b06bbec3ac1d7539a Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Thu, 9 May 2024 17:15:45 +0200 Subject: [PATCH 20/26] Add slice.enum_slice_to_bitset & slice.bitset_to_enum_slice --- core/slice/slice.odin | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/core/slice/slice.odin b/core/slice/slice.odin index dd8d9868a..170e4cbf3 100644 --- a/core/slice/slice.odin +++ b/core/slice/slice.odin @@ -701,3 +701,27 @@ enumerated_array :: proc(ptr: ^$T) -> []intrinsics.type_elem_type(T) where intrinsics.type_is_enumerated_array(T) { return ([^]intrinsics.type_elem_type(T))(ptr)[:len(T)] } + +// Turn a `[]E` into `bit_set[E]` +// e.g.: +// bs := slice.enum_slice_to_bitset(my_flag_slice, rl.ConfigFlags) +@(require_results) +enum_slice_to_bitset :: proc(enums: []$E, $T: typeid/bit_set[E]) -> (bits: T) where intrinsics.type_is_enum(E) && intrinsics.type_bit_set_elem_type(T) == E { + for v in enums { + bits |= {v} + } + return +} + +// Turn a `bit_set[E]` into a `[]E` +// e.g.: +// sl := slice.bitset_to_enum_slice(flag_buf[:], bs) +@(require_results) +bitset_to_enum_slice :: proc(buf: []$E, bs: $T) -> (slice: []E) where intrinsics.type_is_enum(E) && intrinsics.type_bit_set_elem_type(T) == E { + count := 0 + for v in bs { + buf[count] = v + count += 1 + } + return buf[:count] +} \ No newline at end of file From a61d8daec1eb8f5f22a6190d1b51e784faed8bdf Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Thu, 9 May 2024 17:44:05 +0200 Subject: [PATCH 21/26] Add make version of bitset to slice. --- core/slice/slice.odin | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/core/slice/slice.odin b/core/slice/slice.odin index 170e4cbf3..6cb844b40 100644 --- a/core/slice/slice.odin +++ b/core/slice/slice.odin @@ -717,11 +717,27 @@ enum_slice_to_bitset :: proc(enums: []$E, $T: typeid/bit_set[E]) -> (bits: T) wh // e.g.: // sl := slice.bitset_to_enum_slice(flag_buf[:], bs) @(require_results) -bitset_to_enum_slice :: proc(buf: []$E, bs: $T) -> (slice: []E) where intrinsics.type_is_enum(E) && intrinsics.type_bit_set_elem_type(T) == E { +bitset_to_enum_slice_with_buffer :: proc(buf: []$E, bs: $T) -> (slice: []E) where intrinsics.type_is_enum(E) && intrinsics.type_bit_set_elem_type(T) == E { count := 0 for v in bs { buf[count] = v count += 1 } return buf[:count] -} \ No newline at end of file +} + +// Turn a `bit_set[E]` into a `[]E`, allocates +// e.g.: +// sl := slice.bitset_to_enum_slice(bs) +@(require_results) +bitset_to_enum_slice_with_make :: proc(buf: []$E, bs: $T) -> (slice: []E) where intrinsics.type_is_enum(E) && intrinsics.type_bit_set_elem_type(T) == E { + + count := 0 + for v in bs { + buf[count] = v + count += 1 + } + return buf[:count] +} + +bitset_to_enum_slice :: proc{bitset_to_enum_slice_with_make, bitset_to_enum_slice_with_buffer} \ No newline at end of file From 858c78b8448dc76025fa5e3dc0f9e0bb6b63834e Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Thu, 9 May 2024 17:47:19 +0200 Subject: [PATCH 22/26] Pass new -vet-style check. --- core/slice/slice.odin | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/core/slice/slice.odin b/core/slice/slice.odin index 6cb844b40..606feb22e 100644 --- a/core/slice/slice.odin +++ b/core/slice/slice.odin @@ -706,7 +706,7 @@ enumerated_array :: proc(ptr: ^$T) -> []intrinsics.type_elem_type(T) // e.g.: // bs := slice.enum_slice_to_bitset(my_flag_slice, rl.ConfigFlags) @(require_results) -enum_slice_to_bitset :: proc(enums: []$E, $T: typeid/bit_set[E]) -> (bits: T) where intrinsics.type_is_enum(E) && intrinsics.type_bit_set_elem_type(T) == E { +enum_slice_to_bitset :: proc(enums: []$E, $T: typeid/bit_set[E]) -> (bits: T) where intrinsics.type_is_enum(E), intrinsics.type_bit_set_elem_type(T) == E { for v in enums { bits |= {v} } @@ -717,7 +717,7 @@ enum_slice_to_bitset :: proc(enums: []$E, $T: typeid/bit_set[E]) -> (bits: T) wh // e.g.: // sl := slice.bitset_to_enum_slice(flag_buf[:], bs) @(require_results) -bitset_to_enum_slice_with_buffer :: proc(buf: []$E, bs: $T) -> (slice: []E) where intrinsics.type_is_enum(E) && intrinsics.type_bit_set_elem_type(T) == E { +bitset_to_enum_slice_with_buffer :: proc(buf: []$E, bs: $T) -> (slice: []E) where intrinsics.type_is_enum(E), intrinsics.type_bit_set_elem_type(T) == E { count := 0 for v in bs { buf[count] = v @@ -730,14 +730,19 @@ bitset_to_enum_slice_with_buffer :: proc(buf: []$E, bs: $T) -> (slice: []E) wher // e.g.: // sl := slice.bitset_to_enum_slice(bs) @(require_results) -bitset_to_enum_slice_with_make :: proc(buf: []$E, bs: $T) -> (slice: []E) where intrinsics.type_is_enum(E) && intrinsics.type_bit_set_elem_type(T) == E { - +bitset_to_enum_slice_with_make :: proc(bs: $T, $E: typeid) -> (slice: []E) where intrinsics.type_is_enum(E), intrinsics.type_bit_set_elem_type(T) == E { count := 0 - for v in bs { - buf[count] = v + for _ in bs { count += 1 } - return buf[:count] + slice = make([]E, count) + + i := 0 + for v in bs { + slice[i] = v + i += 1 + } + return } bitset_to_enum_slice :: proc{bitset_to_enum_slice_with_make, bitset_to_enum_slice_with_buffer} \ No newline at end of file From e5af98eabecc820a43f675fc7e57630fddb718a0 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Thu, 9 May 2024 17:55:50 +0200 Subject: [PATCH 23/26] Simplify bitset_to_enum_slice --- core/slice/slice.odin | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/core/slice/slice.odin b/core/slice/slice.odin index 606feb22e..fff901cff 100644 --- a/core/slice/slice.odin +++ b/core/slice/slice.odin @@ -731,18 +731,9 @@ bitset_to_enum_slice_with_buffer :: proc(buf: []$E, bs: $T) -> (slice: []E) wher // sl := slice.bitset_to_enum_slice(bs) @(require_results) bitset_to_enum_slice_with_make :: proc(bs: $T, $E: typeid) -> (slice: []E) where intrinsics.type_is_enum(E), intrinsics.type_bit_set_elem_type(T) == E { - count := 0 - for _ in bs { - count += 1 - } - slice = make([]E, count) - - i := 0 - for v in bs { - slice[i] = v - i += 1 - } - return + ones := intrinsics.count_ones(transmute(E)bs) + buf := make([]E, int(ones)) + return bitset_to_enum_slice(buf, bs) } bitset_to_enum_slice :: proc{bitset_to_enum_slice_with_make, bitset_to_enum_slice_with_buffer} \ No newline at end of file From 8f706a14f84d65b9c543976c3c33bbe60129ae9d Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Thu, 9 May 2024 17:58:48 +0200 Subject: [PATCH 24/26] Add allocator param. --- core/slice/slice.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/slice/slice.odin b/core/slice/slice.odin index fff901cff..03791e7dd 100644 --- a/core/slice/slice.odin +++ b/core/slice/slice.odin @@ -730,9 +730,9 @@ bitset_to_enum_slice_with_buffer :: proc(buf: []$E, bs: $T) -> (slice: []E) wher // e.g.: // sl := slice.bitset_to_enum_slice(bs) @(require_results) -bitset_to_enum_slice_with_make :: proc(bs: $T, $E: typeid) -> (slice: []E) where intrinsics.type_is_enum(E), intrinsics.type_bit_set_elem_type(T) == E { +bitset_to_enum_slice_with_make :: proc(bs: $T, $E: typeid, allocator := context.allocator) -> (slice: []E) where intrinsics.type_is_enum(E), intrinsics.type_bit_set_elem_type(T) == E { ones := intrinsics.count_ones(transmute(E)bs) - buf := make([]E, int(ones)) + buf := make([]E, int(ones), allocator) return bitset_to_enum_slice(buf, bs) } From 98827c867dd88b1a72d74f0a6d703f7a25d81d91 Mon Sep 17 00:00:00 2001 From: Laytan Date: Thu, 9 May 2024 19:21:39 +0200 Subject: [PATCH 25/26] fix duplicate suggestions and add missing newline --- src/check_expr.cpp | 2 +- src/error.cpp | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 98aebfe4e..f0c33d9d8 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6201,7 +6201,7 @@ gb_internal bool evaluate_where_clauses(CheckerContext *ctx, Ast *call_expr, Sco error(c, "Prefer to separate 'where' clauses with a comma rather than '&&'"); gbString x = expr_to_string(c->BinaryExpr.left); gbString y = expr_to_string(c->BinaryExpr.right); - error_line("\tSuggestion: '%s, %s'", x, y); + error_line("\tSuggestion: '%s, %s'\n", x, y); gb_string_free(y); gb_string_free(x); } diff --git a/src/error.cpp b/src/error.cpp index 1877a672b..688d1b34a 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -719,9 +719,13 @@ gb_internal void print_all_errors(void) { } } - if (it.str.len-it.pos > 0) { - array_add_elems(&prev_ev->msg, it.str.text+it.pos, it.str.len-it.pos); + // Merge additional text (suggestions for example) into the previous error. + String current = {prev_ev->msg.data, prev_ev->msg.count}; + String addition = {it.str.text+it.pos, it.str.len-it.pos}; + if (addition.len > 0 && !string_contains_string(current, addition)) { + array_add_elems(&prev_ev->msg, addition.text, addition.len); } + array_free(&ev.msg); array_ordered_remove(&global_error_collector.error_values, i); } else { From d7fdccb08ca811a13715eb21c6c6def6e736558b Mon Sep 17 00:00:00 2001 From: Laytan Date: Thu, 9 May 2024 19:39:48 +0200 Subject: [PATCH 26/26] fix a couple of -vet-style failures after f54977336b27c32eab52b77d94e7b1610f4350cf --- core/math/big/helpers.odin | 2 +- core/math/big/internal.odin | 4 ++-- core/math/big/radix.odin | 4 ++-- core/sys/linux/helpers.odin | 30 +++++++++++++++--------------- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/core/math/big/helpers.odin b/core/math/big/helpers.odin index 35be4f1fd..1969fac49 100644 --- a/core/math/big/helpers.odin +++ b/core/math/big/helpers.odin @@ -356,7 +356,7 @@ int_count_lsb :: proc(a: ^Int, allocator := context.allocator) -> (count: int, e } platform_count_lsb :: #force_inline proc(a: $T) -> (count: int) - where intrinsics.type_is_integer(T) && intrinsics.type_is_unsigned(T) { + where intrinsics.type_is_integer(T), intrinsics.type_is_unsigned(T) { return int(intrinsics.count_trailing_zeros(a)) if a > 0 else 0 } diff --git a/core/math/big/internal.odin b/core/math/big/internal.odin index 07e1e6c03..fa747e46a 100644 --- a/core/math/big/internal.odin +++ b/core/math/big/internal.odin @@ -546,7 +546,7 @@ internal_int_shl1 :: proc(dest, src: ^Int, allocator := context.allocator) -> (e Like `internal_int_mul_digit` but with an integer as the small input. */ internal_int_mul_integer :: proc(dest, a: ^Int, b: $T, allocator := context.allocator) -> (err: Error) -where intrinsics.type_is_integer(T) && T != DIGIT { +where intrinsics.type_is_integer(T), T != DIGIT { context.allocator = allocator t := &Int{} @@ -2806,7 +2806,7 @@ internal_int_count_lsb :: proc(a: ^Int) -> (count: int, err: Error) { } internal_platform_count_lsb :: #force_inline proc(a: $T) -> (count: int) - where intrinsics.type_is_integer(T) && intrinsics.type_is_unsigned(T) { + where intrinsics.type_is_integer(T), intrinsics.type_is_unsigned(T) { return int(intrinsics.count_trailing_zeros(a)) if a > 0 else 0 } diff --git a/core/math/big/radix.odin b/core/math/big/radix.odin index 8d8ea734e..f4eed879f 100644 --- a/core/math/big/radix.odin +++ b/core/math/big/radix.odin @@ -469,7 +469,7 @@ internal_int_pack_count :: proc(a: ^Int, $T: typeid, nails := 0) -> (size_needed Assumes `a` not to be `nil` and to have been initialized. */ internal_int_pack :: proc(a: ^Int, buf: []$T, nails := 0, order := Order.LSB_First) -> (written: int, err: Error) - where intrinsics.type_is_integer(T) && intrinsics.type_is_unsigned(T) && size_of(T) <= 16 { + where intrinsics.type_is_integer(T), intrinsics.type_is_unsigned(T), size_of(T) <= 16 { assert(nails >= 0 && nails < (size_of(T) * 8)) @@ -505,7 +505,7 @@ internal_int_pack :: proc(a: ^Int, buf: []$T, nails := 0, order := Order.LSB_Fir internal_int_unpack :: proc(a: ^Int, buf: []$T, nails := 0, order := Order.LSB_First, allocator := context.allocator) -> (err: Error) - where intrinsics.type_is_integer(T) && intrinsics.type_is_unsigned(T) && size_of(T) <= 16 { + where intrinsics.type_is_integer(T), intrinsics.type_is_unsigned(T), size_of(T) <= 16 { assert(nails >= 0 && nails < (size_of(T) * 8)) context.allocator = allocator diff --git a/core/sys/linux/helpers.odin b/core/sys/linux/helpers.odin index 69c648bf1..75fdd586e 100644 --- a/core/sys/linux/helpers.odin +++ b/core/sys/linux/helpers.odin @@ -26,7 +26,7 @@ where @(private) syscall2 :: #force_inline proc "contextless" (nr: uintptr,p1: $T1, p2: $T2) -> int where - size_of(p1) <= size_of(uintptr) && + size_of(p1) <= size_of(uintptr), size_of(p2) <= size_of(uintptr) { return cast(int) intrinsics.syscall(nr, @@ -36,8 +36,8 @@ where @(private) syscall3 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3) -> int where - size_of(p1) <= size_of(uintptr) && - size_of(p2) <= size_of(uintptr) && + size_of(p1) <= size_of(uintptr), + size_of(p2) <= size_of(uintptr), size_of(p3) <= size_of(uintptr) { return cast(int) intrinsics.syscall(nr, @@ -49,9 +49,9 @@ where @(private) syscall4 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3, p4: $T4) -> int where - size_of(p1) <= size_of(uintptr) && - size_of(p2) <= size_of(uintptr) && - size_of(p3) <= size_of(uintptr) && + size_of(p1) <= size_of(uintptr), + size_of(p2) <= size_of(uintptr), + size_of(p3) <= size_of(uintptr), size_of(p4) <= size_of(uintptr) { return cast(int) intrinsics.syscall(nr, @@ -64,10 +64,10 @@ where @(private) syscall5 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3, p4: $T4, p5: $T5) -> int where - size_of(p1) <= size_of(uintptr) && - size_of(p2) <= size_of(uintptr) && - size_of(p3) <= size_of(uintptr) && - size_of(p4) <= size_of(uintptr) && + size_of(p1) <= size_of(uintptr), + size_of(p2) <= size_of(uintptr), + size_of(p3) <= size_of(uintptr), + size_of(p4) <= size_of(uintptr), size_of(p5) <= size_of(uintptr) { return cast(int) intrinsics.syscall(nr, @@ -81,11 +81,11 @@ where @(private) syscall6 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3, p4: $T4, p5: $T5, p6: $T6) -> int where - size_of(p1) <= size_of(uintptr) && - size_of(p2) <= size_of(uintptr) && - size_of(p3) <= size_of(uintptr) && - size_of(p4) <= size_of(uintptr) && - size_of(p5) <= size_of(uintptr) && + size_of(p1) <= size_of(uintptr), + size_of(p2) <= size_of(uintptr), + size_of(p3) <= size_of(uintptr), + size_of(p4) <= size_of(uintptr), + size_of(p5) <= size_of(uintptr), size_of(p6) <= size_of(uintptr) { return cast(int) intrinsics.syscall(nr,